Title#
Harden PhaseRouterService and PhaseHooksService idempotency for BullMQ retry
Problem#
BullMQ stalled-job retries could produce duplicate side effects — duplicate task rows, duplicate GitHub comments, and double Claude invocations — breaking the pipeline for issues with AW-13 (BullMQ migration).
Task / Link#
Closes #458
Changes#
TaskStateService.createTask()wrapped with try/catch to fall back to existing task on unique-constraint racePhaseHooksService.onPhaseBlocked(): idempotency guard usingeventService.countByTypeto skip duplicate blocked commentsPhaseHooksService.onCompoundComplete(): idempotency guard to skip duplicate completion commentsPhaseRouterService.executePhase(): defensive re-entry guard (belt-and-suspenders) if phase status is alreadyactive- BullMQ stall-retry guard: skips
phase_*re-execution when phase isfailedand task isgated - Added
BullMQ retry idempotencytest suites to bothphase-router.service.spec.tsandphase-hooks.service.spec.ts
Notes#
- Concurrent multi-worker calls for the same job remain out of scope (per issue)
getOrCreateWorktree()was confirmed already idempotent- Comment dedup uses task-state event flags rather than GitHub API calls to avoid rate-limit pressure
Testing#
- 826 unit tests passing (
npm run test) - Lint clean (
npm run lint)