Commit Graph

562 Commits

Author SHA1 Message Date
Matt
cfd9dc6afe fix: scope observer reports preview dialog to selected round
Threads the active roundId through ProjectPreviewDialog and its two
callers (filtering tabs, expandable juror table). When a round is in
scope, the preview's stats card now matches the per-juror list and
the page-level round selector. The roundId prop is optional so the
component still works in any future caller that lacks round context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:17:18 +02:00
Matt
9a2c10a6f8 fix: scope admin ranking dashboard side-sheet stats to current round
The admin dashboard fetches its side-sheet detail from project.getFullDetail
(not analytics.getProjectDetail as the audit assumed), and that procedure
had the same cross-round contamination bug. Add an optional roundId to
its input, filter the SUBMITTED-evaluations query when provided, and pass
roundId from the dashboard's useQuery so the Avg Score / Pass Rate /
Evaluators card now matches the per-juror list rendered below it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:15:47 +02:00
Matt
97d1f2a3af fix: compute z-context per-round in edition-mode rankings rollup
Previously the edition-level branch of analytics.getProjectRankings
(programId mode) pooled every juror's evaluations across every round
into a single z-normalization context. A juror's mean and stddev are
not stable across round types — quick intake screening produces a
very different grading profile than a deep evaluation round, and
mixing them yields a meaningless personal calibration.

The rollup now groups points by roundId, computes one balance context
per round, and aggregates per-project as the unweighted mean of the
per-round balanced averages. roundId mode is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:14:30 +02:00
Matt
7147115918 fix: scope analytics.getProjectDetail by optional roundId
The procedure pulled every SUBMITTED evaluation for a project across
every round it ever participated in, then computed Avg Score / Pass
Rate / Evaluators from that pool. Meanwhile the per-juror list rendered
in the admin sheet filters to the current round, producing a card that
disagreed with the visible list. With roundId in the input, callers
opt into round-scoped stats; omitting it preserves the old aggregate
behavior for any caller that hasn't been updated yet.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:12:27 +02:00
Matt
260baf3a41 docs: add implementation plan for juror-balance toggle and scoping fixes
15 TDD-style tasks covering the round-scoping bug fixes for
getProjectDetail and getProjectRankings, the per-round toggle, the
side-panel deeper display, the shared score explainer dialog, and the
decimal display audit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:59:36 +02:00
Matt
64e7be2418 docs: add design spec for juror-balance toggle and round-scoping fixes
Captures the per-round toggle, side-panel deeper display, "How scores
are calculated" explainer dialog, and the cross-round contamination
fixes for getProjectDetail and getProjectRankings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:50:32 +02:00
Matt
901d9ba982 feat: rank projects by balanced score in ranking dashboard
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m0s
Initial ranking order, advancement cutoff line, and per-row "advancing"
highlight now all use the juror-balanced (z-score corrected) average,
falling back to the raw avgGlobalScore when no balanced score exists.
The init effect waits for evalScores so the sort has the data it needs.

Admin drag-reorders still take precedence — saved reorders override the
default sort exactly as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 15:33:56 +02:00
Matt
2e080a5d09 feat: lift round selector to reports page top-level
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m42s
Top-level selector in the URL (?round=...) drives every single-round tab
(Overview, Analytics, Juror Consistency, Diversity) and narrows the Pipeline
tab to the selected program. Cross-Round keeps its own multi-select because
it compares multiple rounds by design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 18:39:18 +02:00
Matt
982d5193c5 feat: surface juror-balanced scores and AI calibration advisory
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m27s
Adds a shared juror-balancing utility (z-score normalization per juror,
rescaled back onto the raw 1-10 scale) and wires it into:

- Admin reports page: Top-10 project table now shows "Raw Avg" and
  "Balanced" columns side by side, and the summary stats row shows a
  balanced-average tile. Sort defaults to balanced so harsh and lenient
  graders no longer skew the ranking.
- Ranking dashboard: each project row shows a green/amber balanced-score
  chip next to the raw average when the two differ by ≥0.05, making it
  obvious when juror calibration moved a project's effective ranking.

Also adds AI Juror Calibration Advisory — a mutation that takes
anonymized per-juror stats, calls OpenAI, and produces a plain-language
explanation of the cohort's grading patterns plus per-juror severity
(normal / notable / outlier) with a one-sentence narrative. The advisory
describes the statistical balance that already runs; it does not
introduce a new weighting layer. Rendered as a panel in the Juror
Consistency tab when a specific round is selected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 16:19:00 +02:00
Matt
07dd7a0692 fix: scope analytics assignments to selected round
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m38s
getProjectRankings and getAllProjects in the analytics router were
loading every assignment for each project regardless of the selected
round, so per-round rankings in the admin reports were counting
evaluations from prior rounds and mixing their scores into averages.
A Round 2 view with 3 reviews per project was showing 5 evaluations
and a skewed average that included Round 1 data.

Filter the nested assignments include by the round (or program) the
request is scoped to, matching the pattern already used by the ranking
service and by getStatusBreakdown.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 16:07:26 +02:00
Matt
f36f68bbf9 fix: don't mark next round as current before advancement is declared
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m48s
The applicant timeline sidebar was treating any previous round with
status ROUND_CLOSED as "advanced past", which caused the Grand Finale
to show "You are here" as soon as the semi-final round closed — before
admins declared which teams actually advanced.

Require explicit PASSED/COMPLETED project state on every prior round
before marking the next one as current. A closed-but-unresolved round
now correctly keeps the applicant anchored to it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 14:39:43 +02:00
Matt
be4449e4ef fix: surface advance-type criterion in ranking yes/no counts
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m7s
The ranking dashboard showed 0/X Yes for every project in rounds using
the 'advance' criterion type because the matcher only looked for
type === 'boolean' with a "move to the next stage" label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:03:26 +02:00
Matt
f37a9b49b5 test: add integration coverage for admin proxy evaluation
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m0s
Seven scenarios covering the new admin procedures:
- non-admin users are rejected on adminStart/adminSubmitOnBehalf
- admin can list a juror's assignments with COI flag surfaced
- admin can complete the full draft→autosave→submit cycle with the
  voting window already closed, confirming bypass works
- COI-declared assignments still block admin submission
- feedback minimum length is enforced on admin submit
- adminAutosave refuses to overwrite a SUBMITTED evaluation
- audit log captures admin id, juror id, and bypassedWindow flag

Also swaps a lucide icon alias (FileEdit → Pencil) in the juror
assignments page to avoid the deprecated alias form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 17:00:03 +02:00
Matt
9cb3b9de13 feat: admin can fill in evaluations on behalf of jurors
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m54s
When a juror cannot connect during an evaluation round, an admin
can now submit evaluations for them.

Router — new admin procedures:
- adminStart / adminAutosave: create and save drafts for any juror.
- adminSubmitOnBehalf: submit bypassing ROUND_ACTIVE and voting-window
  checks. COI block and feedback/criterion validation still enforced.
  Audit log records both admin and juror IDs plus bypassedWindow flag.
- getJurorAssignmentsForRound: list a juror's assignments + eval state.

UI — two new admin pages under /admin/rounds/[roundId]/jurors/[userId]/:
- evaluate: list of pending + completed assignments, COI flagged.
- evaluate/[projectId]: evaluation form reusing the juror's scoring UI,
  with an "acting on behalf" banner and confirmation dialog before
  submit. Back button returns to the assignments list.

Entry point: FilePen icon on each juror row in JuryProgressTable.

Refactor: extracted the scoring form JSX into shared
EvaluationFormFields component so the juror page and the admin proxy
page render identical inputs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:41:14 +02:00
Matt
fd4f6dde16 fix: humanize category label in unassigned queue row
Queue payload exposes the field as `category` (aliased from
`competitionCategory`), not `competitionCategory` itself, so the
previous lookup was always undefined and every project rendered as
"No category". Now shows "Startup" / "Business Concept" correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 16:40:54 +02:00
Matt
f1955b68f9 feat: show vote status on jury dashboard and add logos to award-master
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m47s
- Jury dashboard now shows "Submitted" badge (green) with "Edit
  Rankings" button when juror has already voted, instead of always
  showing "Vote Now" — prevents confusion about whether vote saved
- Award-master page now shows project logos next to project names
- Backend getMyAwardDetailEnhanced now returns logo URLs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 13:09:34 -04:00
Matt
3a6a9a2b45 feat: add inline file viewer and project logos to award voting
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m24s
- Replace custom download-only file list with full FileViewer component
  that supports inline preview (PDF, video, images, Office docs),
  open in new tab, and download
- Add project logos next to project names in award voting cards
- Backend now returns full file metadata (mimeType, size, pageCount,
  language detection) and project logo URLs
- Award jurors can access files for eligible projects (access control
  already added in prior commit)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 12:49:28 -04:00
Matt
0987d49817 feat: show awards on jury dashboard and add project details to award voting
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m27s
- Jury dashboard now shows active award voting banners with project
  count, deadline countdown, and direct link to vote
- Award voting page shows full project details: description, team
  members, tags, and downloadable files in expandable cards
- Award jurors can now download files for eligible projects (added
  awardJuror access check to file.getDownloadUrl)
- Backend query enhanced to include files and team members

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 12:28:53 -04:00
Matt
acd75427b3 feat: add jury group import to special awards and fix juror dropdown
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m43s
The juror dropdown was always empty because the page requested
perPage: 200 but the user.list API caps at 100 (Zod validation).
Fixed to perPage: 100 with role filter for JURY_MEMBER/AWARD_MASTER.

Added "Import from Jury Group" section to the awards juror tab:
select a jury group, see members with checkboxes (already-assigned
shown as disabled), bulk-add selected members via bulkAddJurors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:39:34 -04:00
Matt
eb1e8a7870 fix: case-insensitive email matching in auth and password reset
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m10s
Email lookups used findUnique (case-sensitive on PostgreSQL) but user
input was lowercased, causing login failures for users with mixed-case
emails stored in the DB (e.g. Laurent_Faure@dietsmann.com). Also
normalized 7 affected emails to lowercase on the production DB.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:04:31 -04:00
Matt
ec69706bc7 fix: include direct round files in finalization doc count
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m36s
Files uploaded by admins with roundId but no requirementId were not
counted in the finalization page Docs column.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:37:52 -04:00
Matt
c7488b3e07 fix: save roundId on admin file upload and group assignments by round
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m45s
The admin upload flow accepted roundId but never wrote it to the
ProjectFile record, causing all admin-uploaded files to appear under
"General". Fixed the create call, the listByProject filter, and the
listByProjectForStage grouping to also use the direct roundId field.

Jury assignments on the project detail page are now grouped by round
with per-round completion counts instead of a flat list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 23:20:48 -04:00
Matt
2344f2e4ff fix: drop stale unique index blocking per-category evaluation forms
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m35s
The category migration used DROP CONSTRAINT but the index was created
with CREATE UNIQUE INDEX, so it was never actually removed. This
prevented saving business concept criteria when startup criteria
already existed at the same version number.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:57:36 -04:00
Matt
498baa7e01 feat: add clickable projects and doc counts to finalization page
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m36s
Project names now link to their detail page on all finalization tabs.
Submission/intake rounds show a docs submitted/required column.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:38:05 -04:00
Matt
a51241f7ff feat: add multi-role editor to member detail page
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m42s
Adds an "Additional Roles" checkbox section below the primary Role
dropdown. Admins can now grant a user multiple dashboard views (e.g.,
Observer + Jury Member) without changing their primary role. The roles
array is saved alongside the primary role and used by the role switcher.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 21:08:32 -04:00
Matt
2d6cee394f feat: add bulk invite to jury group page + widen member search role filter
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m48s
Adds bulkInviteMembers procedure to juryGroup router and integrates
BulkInviteForm into the jury group members tab. Also removes the
JURY_MEMBER-only filter from the user search — any user can now be
added to a jury group.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:37:25 -04:00
Matt
5537946b5a feat: add bulk invite form to award juror tab, widen role filter to all users
All checks were successful
Build and Push Docker Image / build (push) Successful in 7m57s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:15:55 -04:00
Matt
29502a2b88 feat: add Decision Mode dropdown to award edit page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:13:51 -04:00
Matt
b901047418 fix: show jury group selector at top of assignments tab when none assigned
Previously showed "Select a jury group below" but the selector was
buried at the bottom (or not rendered at all when no jury was assigned).
Now shows the actual dropdown + "New Jury" button right where the
empty state message was.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:12:25 -04:00
Matt
22a08ef957 feat: add reusable BulkInviteForm component for multi-row name+email invites
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:11:45 -04:00
Matt
158eba416d feat: add auto-retry (3 attempts) for file uploads on flaky connections
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:10:52 -04:00
Matt
97d7f9b625 docs: add implementation plan for award UX fixes and bulk invite
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 19:36:20 -04:00
Matt
3854b6ff0c fix: auto-resolve failed migrations in docker entrypoint
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m25s
On startup, check for any failed migration in _prisma_migrations and
automatically mark it as rolled-back before running migrate deploy.
This prevents a partially-applied migration from permanently blocking
all future deployments. Also reduce max retries from 30 to 6.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:50:20 -04:00
Matt
d9f3b3d2a4 fix: make evaluation form category migration fully idempotent
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m59s
The migration partially applied (column added, then failed on DROP
CONSTRAINT). Make every statement idempotent with IF EXISTS / IF NOT
EXISTS so it can safely re-run after resolve --rolled-back.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:34:47 -04:00
Matt
ef2186e89a fix: make EvaluationForm constraint drop idempotent (IF EXISTS)
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
The migration failed on deploy because the constraint
EvaluationForm_roundId_version_key did not exist in the target DB.
Using DROP CONSTRAINT IF EXISTS makes this safe for databases where
the constraint was already removed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:34:01 -04:00
Matt
2864579e92 fix: type-safe route for award master dashboard links
All checks were successful
Build and Push Docker Image / build (push) Successful in 12m23s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:50:38 -04:00
Matt
8800f2bcc7 feat: add award master voting page with project detail, documents, scores, justification, and chair confirmation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:48:46 -04:00
Matt
0be8c5ecc7 feat: add chair toggle to admin award juror management
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:45:25 -04:00
Matt
fbc8b5165a feat: add award master tRPC procedures — enhanced detail, vote with justification, confirm winner, set chair
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:42:21 -04:00
Matt
9368c1221f feat: add award master dashboard page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:36:47 -04:00
Matt
9fcafec346 feat: add award-master route group layout and nav component
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:36:20 -04:00
Matt
f61cebe6ae feat: wire AWARD_MASTER into auth redirects and role-switch navigation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:35:34 -04:00
Matt
4d68392ada feat: add award winner resolver with tiebreak logic and tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:34:44 -04:00
Matt
de12b232d9 fix: allow AWARD_MASTER role to access project files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:34:38 -04:00
Matt
a002f544a6 schema: add isChair to AwardJuror, justification to AwardVote
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:33:13 -04:00
Matt
3ccf9b0542 feat: per-category evaluation criteria (startup vs business concept)
Add ability to define completely different evaluation criteria for each
competition category. Admins toggle "Separate Criteria per Category" in
round config, then configure criteria independently via tabbed editor.

- Schema: add nullable `category` to EvaluationForm with updated constraints
- Config: add `perCategoryCriteria` boolean to EvaluationConfigSchema
- Helper: new `findActiveForm()` with category-aware resolution + fallback
- Backend: getForm, upsertForm, getStageForm, startStage all category-aware
- AI services: use project category for form lookup in summaries + ranking
- Export/ranking: merge criteria from all active forms for cross-category reports
- Admin UI: toggle switch + tabbed criteria editor with per-category builders
- Jury UI: auto-selects correct form based on project category (invisible to juror)
- Fully backwards compatible: toggle defaults OFF, existing forms unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:03:22 -04:00
Matt
7ead21114e fix: pipeline progress, message variables, jury invite flow, accept-invite UX
- Pipeline: SUBMISSION rounds count IN_PROGRESS + COMPLETED for progress %
- Round engine: remove phantom SubmissionFileRequirement check blocking auto-transition
- Messages: implement {{userName}}, {{projectName}}, {{roundName}}, {{programName}}, {{deadline}} substitution
- Email preview: show greeting, CTA button, and footer matching actual sent email
- Message composer: add green dot indicator for active rounds in round selector
- User create: generate invite token atomically (prevents stuck INVITED state on email failure)
- Jury invites: use jury-specific email template mentioning round context
- Bulk invite: animated progress bar, batch size hint, success/failure counts
- Accept invite: distinguish server errors (retry button) from expired tokens (redirect)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 13:47:42 -04:00
6b40fe7726 refactor: tech debt batch 3 — type safety + assignment router split
All checks were successful
Build and Push Docker Image / build (push) Successful in 13m4s
#5 — Replaced 55x PrismaClient | any with proper Prisma types across 8 files
- Service files: PrismaClient | any → PrismaClient, tx: any → Prisma.TransactionClient
- Fixed 4 real bugs uncovered by typing:
  - mentor-workspace.ts: wrong FK fields (mentorAssignmentId → workspaceId, role → senderRole)
  - ai-shortlist.ts: untyped string passed to CompetitionCategory enum filter
  - result-lock.ts: unknown passed where Prisma.InputJsonValue required

#9 — Split assignment.ts (2,775 lines) into 6 focused files:
  - shared.ts (93 lines) — MOVABLE_EVAL_STATUSES, buildBatchNotifications, getCandidateJurors
  - assignment-crud.ts (473 lines) — 8 core CRUD procedures
  - assignment-suggestions.ts (880 lines) — AI suggestions + job runner
  - assignment-notifications.ts (138 lines) — 2 notification procedures
  - assignment-redistribution.ts (1,162 lines) — 8 reassign/transfer procedures
  - index.ts (15 lines) — barrel export with router merge, zero frontend changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:47:06 +01:00
1c78ecf21d refactor: tech debt batch 2 — drop dead models, stale columns, schema cleanup
Schema:
- Drop 4 dead models: OverrideAction, NotificationPolicy, AssignmentException, AdvancementRule
- Drop 2 dead enums: OverrideReasonCode, AdvancementRuleType
- Drop 3 stale columns: Project.roundId, ConflictOfInterest.roundId, Evaluation.version
- Remove 3 back-relation fields from User, Assignment, Round

Code:
- Fix 6 COI queries in assignment.ts + 1 in juror-reassignment.ts
  (roundId filter → assignment.roundId after column drop)
- Remove orphaned Project.roundId write in project.ts createProject
- Remove advancementRules include from round.ts getById
- Remove AdvancementRule from RoundWithRelations type
- Clean up seed.ts (remove advancement rule seeding)
- Clean up tests/helpers.ts (remove dead model cleanup)
- Add TODO comments on user delete mutations (FK violation risk)

Migration: 20260308000000_drop_dead_models_and_stale_columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 12:35:23 +01:00
1356809cb1 fix: tech debt batch 1 — TS errors, vulnerabilities, dead code
- Fixed 12 TypeScript errors across analytics.ts, observer-project-detail.tsx, bulk-upload/page.tsx, settings/profile/page.tsx
- npm audit: 8 vulnerabilities resolved (1 critical, 4 high, 3 moderate)
- Deleted 3 dead files: live-control.ts (618 lines), feature-flags.ts, file-type-categories.ts
- Removed typescript.ignoreBuildErrors: true — TS errors now block builds

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:51:44 +01:00