Custom body support for advancement/rejection notification emails, evaluation
config toggle fix, user actions improvements, round finalization with reorder
support, project detail page enhancements, award pool duplicate prevention.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add notifiedAt field to AwardEligibility. notifyEligibleProjects now
skips already-notified entries and stamps notifiedAt after sending,
so re-clicking "Notify Pool" only emails newly added projects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- getNavFlags/getMyEvaluations: return empty when project has no round
states instead of dropping the filter (prevented phantom eval rounds)
- getUpcomingDeadlines: detect isInAwardTrack from ProjectRoundState
join instead of pre-filtered deadline rounds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Projects in SEPARATE_POOL awards now only see their award rounds (not main
pool rounds) across all applicant queries: openRounds, deadlines, document
completeness, nav flags, and evaluations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The email was implying projects had won the award. Updated banner, subject,
and body copy to clarify they are being considered, not awarded.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add drag-and-drop round reordering on award detail Rounds tab (dnd-kit)
- Replace "Open Voting" with "Assign to First Round" for SEPARATE_POOL awards
- Add reorderAwardRounds mutation (two-phase transaction for unique constraint)
- Add assignToFirstRound mutation (re-runnable, moves/creates ProjectRoundState)
- Extend applicant timeline to show award-specific rounds for SEPARATE_POOL projects
- Hide irrelevant main competition rounds when project is in award track
- Prefix award round labels with award name in timeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add admin settings: learning_hub_external, learning_hub_external_url, support_email
- Jury/Mentor nav respects external Learning Hub URL (opens in new tab)
- RoleNav supports external nav items with ExternalLink icon
- Applicant header shows Help button with configurable support email
- Settings update mutation now upserts (creates on first use)
- Shared inferSettingCategory for consistent category assignment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Award "Notify Pool" dialog now uses EmailPreviewDialog with live preview
- Button shows eligible project count: "Notify Pool (38)"
- Finalization tab email section has "Preview" buttons for both
advancement and rejection messages
- EmailPreviewDialog supports previewOnly mode (close button, no send)
- Backend: previewAwardSelectionEmail, previewFinalizationAdvancementEmail,
previewFinalizationRejectionEmail queries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- processRoundClose now applies reordersJson drag-reorder overrides
when building the evaluation pass set (was ignoring admin reorders)
- Finalization tab groups proposed outcomes by category (Startup/Concept)
with per-group pass/reject/total counts
- Added category filter dropdown alongside the existing outcome filter
- Removed legacy "Advance Top N" button and dialog from ranking page
(replaced by the finalization workflow)
- Fix project edit status defaultValue showing empty placeholder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The migration adding gracePeriodEndsAt, finalizedAt, finalizedBy to Round
and proposedOutcome to ProjectRoundState was never committed, causing
production to fail with "column does not exist" errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- processRoundClose EVALUATION uses ranking scores + advanceMode config
(threshold vs count) to auto-set proposedOutcome instead of defaulting all to PASSED
- Advancement emails generate invite tokens for passwordless users with
"Create Your Account" CTA; rejection emails have no link
- Finalization UI shows account stats (invite vs dashboard link counts)
- Fixed getFinalizationSummary ranking query (was using non-existent rankingsJson)
- New award pool notification system: getAwardSelectionNotificationTemplate email,
notifyEligibleProjects mutation with invite token generation,
"Notify Pool" button on award detail page with custom message dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Submission, Intake, and Mentoring rounds don't use score-based
advancement (Fixed Count / Score Threshold). The section is now
only shown for Evaluation and Filtering rounds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The outer Tooltip on the status badge was overlaying the DropdownMenu
content, hiding "Reopen Round". Now the tooltip is forced closed
whenever the dropdown is open.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Always display yes/no count format (e.g. "0/2 Yes") instead of
generic "2 jurors" when no advance votes exist
- Color coding: 2/2 Yes = green, 1/2 Yes = amber, 0/2 Yes = red
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The display was sorted by compositeScore (which factors in pass rate and
z-score normalization) but the cutoff line and displayed values use
avgGlobalScore. This caused projects with high averages but low pass
rates (e.g. 1/2 Yes) to appear below the cutoff even when their average
exceeded the threshold.
Now sorts by avgGlobalScore (the visible metric) with compositeScore as
tiebreaker. Also adds a green left border to advancing projects for
clearer threshold highlighting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sort deduped ranking entries by compositeScore descending during
localOrder init — ensures correct display order for both formula
and old AI snapshots
- Fix threshold cutoff: scan forward to find first non-qualifying
project instead of backward scan that left non-qualifying projects
above the line
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add scoreWeight and passRateWeight (0-10) to evaluation config for
configurable composite score formula. When ranking criteria text is
empty, triggerAutoRank uses pure formula ranking (no LLM calls).
When criteria text is present, AI-assisted ranking runs as before.
- Add FORMULA to RankingMode enum with migration
- Extract fetchCategoryProjects helper, add formulaRank service
- Update computeCompositeScore to accept configurable weights
- Add score/pass-rate weight sliders to ranking dashboard UI
- Mode-aware button labels (Calculator/formula vs Sparkles/AI)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create snapshot with status RUNNING before AI call starts
- Update to COMPLETED/FAILED when done
- Dashboard derives rankingInProgress from server snapshot status
- All admins see the spinner, not just the one who triggered it
- Poll snapshots every 3s so progress updates appear quickly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sort all ranked projects by compositeScore descending so highest-rated
projects always appear first (instead of relying on AI's inconsistent rank order)
- Deduplicate AI ranking response (AI sometimes returns same project multiple times)
- Deduplicate ranking entries and reorder IDs on dashboard load as defensive measure
- Show advancement cutoff line only once (precompute last advancing index)
- Override badge only shown when admin has actually drag-reordered (not on fresh rankings)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a round is reopened (ROUND_CLOSED → ROUND_ACTIVE), the old
windowCloseAt was still in the past, causing jury submissions to fail
with "Voting window has closed" even though the round status was active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Apply saved reordersJson when initializing the dashboard so any admin
sees the latest drag-reorder state, not just the original AI order.
The latest reorder event per category is used as the initial localOrder.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AI ranking now includes ALL projects (never filters/excludes any)
- Updated system prompt: filter criteria inform priority, not exclusion
- Dynamic maxTokens scaling for large project pools (80 tokens/project)
- Fallback: projects AI omits are appended sorted by composite score
- Override badge uses snapshotOrder state (synced with localOrder in same
useEffect) instead of rankingMap.originalIndex to prevent stale-render
mismatch where all items incorrectly showed as overridden
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Header shows "Score >= X advance" instead of "Top N" in threshold mode
- Cutoff line placed after last project meeting threshold, not at fixed count
- Projects advancing determined by avg score vs threshold, not position
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backfilled 166 evaluations' binaryDecision from criterionScoresJson on production DB
- Fixed roundEvaluationScores and ai-ranking to look in EvaluationForm.criteriaJson
instead of round.configJson for the boolean "Move to the Next Stage?" criterion
- Added advanceMode (count/threshold) toggle to round config Advancement Targets
- Added "Assign to Jurors" button on Unassigned Projects section and Projects tab bulk bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add criteriaWeights to EvaluationConfig for per-criterion weight assignment (0-10)
- Rewrite ai-ranking service: fetch eval form criteria, compute per-criterion averages,
z-score normalize juror scores to correct grading bias, send weighted criteria to AI
- Update AI prompts with criteria_definitions and per-project criteria_scores
- compositeScore uses weighted criteria when configured, falls back to globalScore
- Add collapsible ranking config section to dashboard (criteria text + weight sliders)
- Move rankingCriteria textarea from eval config tab to ranking dashboard
- Store criteriaWeights in ranking snapshot parsedRulesJson for audit
- Enhance projectScores CSV export with per-criterion averages, category, country
- Add Export CSV button to ranking dashboard header
- Add threshold-based advancement mode (decimal score threshold, e.g. 6.5)
alongside existing top-N mode in advance dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add adminEditEvaluation mutation and getJurorEvaluations query
- Create shared EvaluationEditSheet component with inline feedback editing
- Add Evaluations tab to member detail page (grouped by round)
- Make jury group member names clickable (link to member detail)
- Replace inline EvaluationDetailSheet on project page with shared component
- Fix project status transition validation (skip when status unchanged)
- Fix frontend to not send status when unchanged on project edit
- Ranking dashboard improvements and boolean decision converter fixes
- Backfill script updates for binary decisions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add nationality/institution fields to User model with migration
- Applicant onboarding wizard (name, photo, nationality, country, institution, bio, project logo, preferences)
- Project logo upload from applicant context with team membership verification
- APPLICANT redirects in set-password, onboarding, and auth layout
- Mask evaluation round names as "Evaluation Round 1/2/..." for applicants
- Extend inviteTeamMember with nationality/country/institution/sendInvite fields
- Admin getApplicants query with search/filter/pagination
- Admin bulkInviteApplicants mutation with token generation and emails
- Applicants tab on Members page with bulk select and floating invite bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new tRPC procedure `round.getSubmissionRoundForProgram` that
fetches the most recent SUBMISSION round for a given program, then
displays any `requiredDocuments` from its configJson as labeled info
cards above the general file upload section on the project edit page.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ProjectStatesTable local search now covers country, institution, competitionCategory, geographicZone
- project-pool.ts DB search extended to institution, country, geographicZone, team member names
- AwardShortlist eligibility table gains a search input filtering by title, team, country, institution, category
- IndividualAssignmentsTable project filter extended to include country and institution
- Add "Generate AI Tags" dropdown item per row in ProjectStatesTable using tag.tagProject mutation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- IndividualAssignmentsTable: add View Project (new tab) as first dropdown item
- AwardShortlist: make project title a clickable link opening in new tab
- ProjectStatesTable: change View Project from same-tab Link to new-tab anchor
- Round page: Awards tab now only shown when roundAwards.length > 0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add optional roundId field to project.create mutation input schema
- After project creation, update project.roundId FK and create a
ProjectRoundState record (state: PENDING) when roundId is supplied
- Pass selectedRoundId from the new-project form to createProject.mutate()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds competitionCategory, oceanIssue, institution, geographicZone,
wantsMentorship, and foundedAt to the tRPC update mutation input schema
and the admin project edit form UI (with CountrySelect + Switch).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Chart: fixed bars not rendering by using explicit h-[160px] + min-h-0 on
the bar container so percentage-based heights resolve correctly.
Script: one-off backfill copies the custom "Move to the Next Stage?" boolean
criterion value into binaryDecision for evaluations where it's null.
Run: npx tsx scripts/backfill-binary-decision.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds getProjectStates query to build a projectInfoMap lookup. Each row now
shows the project title, team name, and country. Also renames "Pass" label
to "Yes" to match the binary yes/no vote semantics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The backend reads rankingCriteria from configJson but there was no UI field
to set it. Adds a Textarea and autoRankEnabled switch to the AI Features card
in the evaluation round config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add pendingReorderCount ref + onMutate/onSettled to saveReorderMutation (DASH-07)
- Add advanceMutation (trpc.round.advanceProjects) with getProjectStates invalidation
- Add batchRejectMutation (trpc.roundEngine.batchTransition) using .length per MEMORY.md
- Add handleAdvance: advances top N per category, optionally batch-rejects the rest
- Add Advance Top N button in header (disabled when saveReorderMutation.isPending)
- Add Dialog with per-category N inputs, batch-reject checkbox, and count preview
- Import Dialog, Input, Label, Trophy from shadcn/lucide