Skip to content

October 2026 Release 2 - #167

Merged
jmgasper merged 4 commits into
masterfrom
develop
Oct 14, 2026
Merged

jmgasper merged 4 commits into
masterfrom
develop

Conversation

@jmgasper

Copy link
Copy Markdown
Contributor

jmgasper and others added 4 commits October 9, 2026 18:04
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>
What was broken

When a challenge phase was manually closed or reopened from the review app, the phase change email listed every notified member in the To field, so each member could see the other members' email addresses. Autopilot phase change emails were not affected because autopilot already publishes one email event per recipient.

Root cause

Manual phase changes go through PATCH /challenges/:id/phases/:phaseId, which sends mail through helper.sendPhaseChangeNotification. That helper put the whole recipient list into a single external.action.email bus event. The email service then sends that event as one SendGrid message with all recipients in To. PM-5763 changed ChallengePhaseService to call the helper once per recipient, but the helper still merged any multi-recipient list into one shared email.

What was changed

helper.sendPhaseChangeNotification now publishes a separate external.action.email event for each recipient, with a single address in recipients. This applies the privacy guarantee at the point where the email event is built, so callers cannot expose addresses. A failed publish for one recipient is logged and the remaining recipients are still notified. The helper's doc comment was updated to describe this.

Any added/updated tests

Added test/unit/phase-change-notification-helper.test.js. It loads the helper against a stubbed bus client and checks two things: a multi-recipient call publishes one email event per recipient, each with exactly one address, and a failed publish for one recipient does not block the others. Both tests fail against the previous helper and pass with this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PM-5449: Send manual phase change emails per recipient
PM-5573: Switch an active challenge's timeline with its AI review mode
@jmgasper
jmgasper merged commit 53d251a into master Oct 14, 2026
9 checks passed
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