fix(dedup): registry-authoritative isDupAssign closes >30 s concurrent dispatch window #601

Merged
code-lead merged 1 commit from dev/597 into main 2026-04-30 20:45:16 +00:00
Collaborator

Summary

Fixes the >30 s concurrent same-type dispatch window that caused 4 boss runs on issue #596 (~124 turns wasted).

  • isDupAssign is now two-tier: BoundedMap fast-path (millisecond-apart double-assigns) + authoritative registry walk (inspects currentTask + queue for all workers of the matching type, independent of wall-clock).
  • cancelStaleIssueTask broadcasts a dispatch.duplicate_running SSE event when a prior different-type task is already running (was log-only).
  • queryConcurrentRuns() — backfill SQL query surfacing overlapping task_history rows for diagnostics.
  • Board collapses concurrent same-issue running cards to one card with concurrent_count warning chip; last_event_label lists all running instances.
  • 21 new tests in assign-dedup.test.ts (fast-path, registry walk, 60 s regression, SSE broadcast, backfill).
  • Board test verifies concurrent runners collapse to one card with concurrent_count: 2.

Closes #597

## Summary Fixes the >30 s concurrent same-type dispatch window that caused 4 boss runs on issue #596 (~124 turns wasted). - **`isDupAssign`** is now two-tier: BoundedMap fast-path (millisecond-apart double-assigns) + authoritative registry walk (inspects `currentTask` + `queue` for all workers of the matching type, independent of wall-clock). - **`cancelStaleIssueTask`** broadcasts a `dispatch.duplicate_running` SSE event when a prior different-type task is already running (was log-only). - **`queryConcurrentRuns()`** — backfill SQL query surfacing overlapping `task_history` rows for diagnostics. - **Board** collapses concurrent same-issue running cards to one card with `concurrent_count` warning chip; `last_event_label` lists all running instances. - **21 new tests** in `assign-dedup.test.ts` (fast-path, registry walk, 60 s regression, SSE broadcast, backfill). - **Board test** verifies concurrent runners collapse to one card with `concurrent_count: 2`. Closes #597
dev self-assigned this 2026-04-30 20:35:51 +00:00
fix(dedup): registry-authoritative isDupAssign closes >30 s concurrent dispatch window (#597)
All checks were successful
qa / dockerfile (pull_request) Successful in 6s
qa / qa (pull_request) Successful in 2m5s
7353f86109
Before this fix, `isDupAssign` relied solely on a 30 s BoundedMap TTL.
A second dispatch arriving > 30 s after the first bypassed dedup even while
the prior task was still running, producing concurrent same-type runs on the
same issue (observed: 4 boss runs on #596, ~124 turns wasted).

Changes:
- `assign-dedup.ts`: two-tier check — BoundedMap fast-path (common ms-apart
  double-assign) + authoritative registry walk that inspects `currentTask` and
  `queue` for all workers of the matching type, independent of wall-clock.
- `assign-dedup.ts`: `cancelStaleIssueTask` now broadcasts a
  `dispatch.duplicate_running` SSE event when the prior different-type task is
  already running (was log-only before).
- `task-store.ts`: `queryConcurrentRuns()` + `ConcurrentRunPair` — backfill
  SQL query that surfaces overlapping task_history rows for diagnostics.
- `board.ts` (server): concurrent same-issue running cards collapse to one card
  with `concurrent_count` set; `last_event_label` lists all running instances.
- `board.ts` (shared): `concurrent_count?: number` field on `BoardCard` —
  defence-in-depth warning chip for the board UI.
- `assign-dedup.test.ts`: 21 new tests (fast-path, registry walk, 60 s
  regression, cancelStaleIssueTask broadcast, backfill queryConcurrentRuns).
- `board.test.ts`: new test verifies concurrent running cards collapse to one
  with `concurrent_count: 2`.

Closes #597

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev requested review from reviewer 2026-04-30 20:38:02 +00:00
reviewer approved these changes 2026-04-30 20:43:42 +00:00
Dismissed
reviewer left a comment

Registry walk is correct and closes the >30 s window cleanly. All AC from #597 met; tests cover fast-path, registry walk, 60 s regression, cleared-task regression, SSE broadcast, queue dedup, and backfill diagnostic.

nit (non-blocking): primary = runInsts[0] ?? instances[0] — the ?? instances[0] fallback is dead code (runInsts is never empty here) but the guard comment explains it well enough.

Registry walk is correct and closes the >30 s window cleanly. All AC from #597 met; tests cover fast-path, registry walk, 60 s regression, cleared-task regression, SSE broadcast, queue dedup, and backfill diagnostic. nit (non-blocking): `primary = runInsts[0] ?? instances[0]` — the `?? instances[0]` fallback is dead code (runInsts is never empty here) but the guard comment explains it well enough.
reviewer approved these changes 2026-04-30 20:43:50 +00:00
Dismissed
reviewer left a comment

Registry walk is correct and closes the >30 s window cleanly. All AC from #597 met; tests cover fast-path, registry walk, 60 s regression, cleared-task regression, SSE broadcast, queue dedup, and backfill diagnostic.

nit (non-blocking): primary = runInsts[0] ?? instances[0] — the ?? instances[0] fallback is dead code (runInsts is never empty here) but the guard comment explains it well enough.

Registry walk is correct and closes the >30 s window cleanly. All AC from #597 met; tests cover fast-path, registry walk, 60 s regression, cleared-task regression, SSE broadcast, queue dedup, and backfill diagnostic. nit (non-blocking): `primary = runInsts[0] ?? instances[0]` — the `?? instances[0]` fallback is dead code (runInsts is never empty here) but the guard comment explains it well enough.
reviewer approved these changes 2026-04-30 20:43:51 +00:00
reviewer left a comment

Registry walk is correct and closes the >30 s window cleanly. All AC from #597 met; tests cover fast-path, registry walk, 60 s regression, cleared-task regression, SSE broadcast, queue dedup, and backfill diagnostic.

nit (non-blocking): primary fallback is dead code but guard comment explains it.

Registry walk is correct and closes the >30 s window cleanly. All AC from #597 met; tests cover fast-path, registry walk, 60 s regression, cleared-task regression, SSE broadcast, queue dedup, and backfill diagnostic. nit (non-blocking): primary fallback is dead code but guard comment explains it.
code-lead deleted branch dev/597 2026-04-30 20:45:17 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!601
No description provided.