Skip to content

PM-5573: Switch an active challenge's timeline with its AI review mode - #165

Merged
jmgasper merged 1 commit into
developfrom
PM-5573
Oct 9, 2026
Merged

jmgasper merged 1 commit into
developfrom
PM-5573

Conversation

@jmgasper

@jmgasper jmgasper commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

JIRA: PM-5573

Part of a three-repo fix:

  • challenge-api: this PR
  • review-api: review-api-v6#364 allows the mode switch after submissions until review starts
  • platform-ui work app: platform-ui#2476 unlocks the mode select and reloads the timeline

What was broken

Switching a launched challenge between AI_ONLY and AI_GATING left Timeline & Schedule unchanged:

  • A challenge moved to AI_GATING kept the AI Review and Approval phases of the AI Only timeline.
  • A challenge moved to AI_ONLY kept AI Screening, Review and Appeals.

Root cause

updateChallenge only synced the timeline template with the AI review mode on NEW/DRAFT saves and on activation. Its template-change path also rebuilt every phase from scratch. That would restart phases an active challenge had already run.

What was changed

  • updateChallenge now also fetches the AI review config when saving an ACTIVE challenge that has AI reviewers or uses the AI Only template.
    • AI_ONLY moves the challenge to the AI Only template.
    • Any other mode moves it off the AI Only template, back to the default type/track template.
    • This is the same rule drafts already follow.
  • An ACTIVE challenge only switches while none of the phases the new template drops have started (new phaseHelper.hasStartedPhasesOutsideTemplate). In practice that means until its review phase starts. Otherwise the current template is kept. For ACTIVE challenges, only this validated switch bypasses the non-admin "Cannot change the timelineTemplateId" check.
  • New challengeHelper.populatePhasesForActiveTimelineTemplateSwitch rebuilds the phases:
    • Phases shared with the new template (Registration, Submission) keep their record id, open state and actual dates, so autopilot's open phases are untouched.
    • The other phases come from the new template. Phases the new template does not contain are deleted by the existing syncChallengePhases.
    • When leaving AI_ONLY, AI reviewers get AI Screening back, using the existing addAIScreeningPhaseForChallenge.
    • Phases that have not started are rescheduled after their predecessors with populatePhasesForChallengeUpdate.

Resulting timelines with dev's templates:

  • AI_ONLY → AI_GATING: Registration, Submission, AI Screening, Review, Appeals, Appeals Response
  • AI_GATING → AI_ONLY: Registration, Submission, AI Review, Approval

Any added/updated tests

  • test/unit/phase-helper.test.js: hasStartedPhasesOutsideTemplate.
  • test/unit/challenge-helper.test.js: AI_ONLY → AI_GATING and AI_GATING → AI_ONLY rebuilds, using dev's template layouts (including the AI Only template's row order). They check that open phases are kept, AI Screening is inserted and later phases are rescheduled.

Validation

  • Unit suite: 80 passing, 82 failing. There is no local Postgres or S3, and the 82 failures are the same set a clean develop produces in this environment (77 passing there). The 3 new tests pass.
  • eslint on the changed TS files is clean (the lint script only covers .ts), and nest build succeeds.

Notes

  • The updateChallenge path that calls the database is not covered by a unit test, because those suites need a live Postgres.

🤖 Generated with Claude Code

What was broken
Switching a launched challenge between AI_ONLY and AI_GATING left Timeline &
Schedule unchanged. A challenge moved to AI_GATING kept the AI Review and
Approval phases of the AI Only timeline. A challenge moved to AI_ONLY kept
AI Screening, Review and Appeals.

Root cause
updateChallenge only synced the timeline template with the AI review mode on
NEW/DRAFT saves and on activation. Its template-change path also rebuilt all
phases from scratch, which would restart phases an active challenge had
already run.

What was changed
- updateChallenge also fetches the AI review config when saving an ACTIVE
  challenge that has AI reviewers or uses the AI Only template. AI_ONLY moves
  the challenge to the AI Only template. Any other mode moves it off the AI
  Only template back to the default type/track template.
- An ACTIVE challenge only switches while none of the phases the new
  template drops have started (new phaseHelper.hasStartedPhasesOutsideTemplate),
  i.e. until its review phase starts. Otherwise the template is kept. For an
  ACTIVE challenge, only this validated switch bypasses the non-admin
  "Cannot change the timelineTemplateId" check.
- New challengeHelper.populatePhasesForActiveTimelineTemplateSwitch rebuilds
  the phases:
  - Phases shared with the new template (Registration, Submission) keep
    their record id, open state and actual dates.
  - The other phases come from the new template.
  - When leaving AI_ONLY, AI reviewers get AI Screening back.
  - Phases that have not started are rescheduled with
    populatePhasesForChallengeUpdate.

Added/updated tests
- phase-helper.test.js: hasStartedPhasesOutsideTemplate.
- challenge-helper.test.js: AI_ONLY -> AI_GATING and AI_GATING -> AI_ONLY
  rebuilds using dev's template layouts. They check that open phases are
  kept, AI Screening is inserted and later phases are rescheduled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant