Skip to content

fix: serialize dispatch slot admission - #360

Merged
therockstorm merged 2 commits into
mainfrom
fix/v2-capacity-admission
Aug 10, 2026
Merged

therockstorm merged 2 commits into
mainfrom
fix/v2-capacity-admission

Conversation

@therockstorm

Copy link
Copy Markdown
Member

Why

Two concurrent crew start processes could each observe an open slot before either persisted its run. With maximumInProgress: 1, both could launch, exceeding the configured orchestration limit and consuming more agent capacity than operators allowed.

Summary

  • serialize cross-process slot admission under one state-root lock
  • re-read active provisioning/running runs while holding that lock and persist the provisioning reservation before releasing it
  • add a deterministic two-process regression test for distinct task slugs at a maximum of one

Validation

  • npx vitest run e2e/dispatch.e2e.test.ts -t "reserves one shared slot"
  • npx vitest run e2e/dispatch.e2e.test.ts (46 passed)
  • node --run verify (79 passed, 1 skipped)

Notes

  • Validates and resolves both duplicate findings: fnd_sig-feat-cli-command-49a9766219-_11fd05c55d and fnd_sig-feat-cli-command-012418b101-_4055fbdd6c.
  • Review focus: admission lock scope and durable reservation semantics.

Agent session: codex resume 019fecf3-dfb5-7931-ae12-80611ee76626

🤖 cb-ship:created v1 skill@1.0.2

@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 140f0698-80d3-440c-a3a3-7a34f0b9bc42

📥 Commits

Reviewing files that changed from the base of the PR and between a96b32b and fea5b8e.

📒 Files selected for processing (2)
  • v2/src/run/index.test.ts
  • v2/src/run/index.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • ClipboardHealth/cbh-core (manual)
🚧 Files skipped from review as they are similar to previous changes (1)
  • v2/src/run/index.ts

📝 Walkthrough

Walkthrough

Dispatch startup now reserves capacity atomically through the run module. Core dispatch uses the reservation result for provisioning and progress reporting. Tests validate concurrent starts when capacity is limited to one task.

Changes

Dispatch admission

Layer / File(s) Summary
Reservation contract and locked admission
v2/src/run/index.ts
Adds DispatchReservation and RunModule.reserveDispatch. The store counts provisioning and running runs under a lock, rejects full non-forced requests, and creates admitted provisioning runs.
Core dispatch reservation integration
v2/src/core/index.ts
Replaces local active-count checks and beginDispatch with reserveDispatch. Full reservations record skipped tasks. Successful reservations provide the provisioning run and active-count data.
Concurrent dispatch validation
v2/e2e/dispatch.e2e.test.ts, v2/src/run/index.test.ts
Adds synchronized concurrent-start coverage and verifies single-slot admission, run creation, workspace launch, the slots-full result, and reservation behavior with a matching task lock.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TaskA
  participant TaskB
  participant CoreDispatch
  participant RunModule
  participant RunStore
  TaskA->>CoreDispatch: start dispatch
  TaskB->>CoreDispatch: start dispatch
  CoreDispatch->>RunModule: reserveDispatch
  RunModule->>RunStore: reserve dispatch under lock
  RunStore-->>RunModule: reserved provisioning run
  RunModule-->>CoreDispatch: reserved result
  CoreDispatch->>RunModule: reserveDispatch
  RunModule->>RunStore: reserve dispatch under lock
  RunStore-->>RunModule: full result
  RunModule-->>CoreDispatch: slots-full result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: serializing dispatch slot admission.
Description check ✅ Passed The description directly explains the concurrency issue, implementation, regression test, and validation for the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/v2-capacity-admission

Comment @coderabbitai help to get the list of available commands.

ghost

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@v2/src/run/index.ts`:
- Around line 627-648: Update reserveDispatch to use a lock path that cannot
collide with create’s task-derived lock for the valid task ID
dispatch:admission, while keeping the admission critical section protected. Add
a regression test covering dispatch:admission and verifying dispatch does not
wait for the stale-lock timeout.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6a4facc3-c0d7-4547-aa58-febf68770af2

📥 Commits

Reviewing files that changed from the base of the PR and between 74edac9 and a96b32b.

📒 Files selected for processing (3)
  • v2/e2e/dispatch.e2e.test.ts
  • v2/src/core/index.ts
  • v2/src/run/index.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • ClipboardHealth/cbh-core (manual)

Comment thread v2/src/run/index.ts
@therockstorm

Copy link
Copy Markdown
Member Author

Review-body findings

Agree

  • CodeRabbit: The admission lock could collide with the valid dispatch:admission task slug. Fixed in fea5b8e by moving admission locks into a dedicated namespace and adding a regression test.

Already fixed

  • Mendral reported LGTM with no actionable findings; no additional change was requested.
b0f10785e88d1641
fd6ab370b6a3824c

🤖 cb-babysit:addressed v1 skill@1.0.4

@ghost ghost left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

The new commit sensibly isolates the lock into .locks/dispatch-admission.lock to prevent a slug collision with actual run records. The withFileLock helper already creates parent directories recursively (line 902), so the .locks dir is handled. The regression test correctly validates that a task whose canonical ID contains the lock's basename succeeds without triggering stale-lock reclamation. No issues found.

What this PR does

Moves the dispatch admission lock file into a .locks subdirectory to prevent path collisions with run record files (e.g., if a task slug matched the lock name). Adds a unit test that verifies a task with canonicalTaskId: "dispatch:admission" does not collide with the lock file.

Tag @mendral-app with feedback or questions. View session

@therockstorm
therockstorm merged commit f777c24 into main Aug 10, 2026
8 checks passed
@therockstorm
therockstorm deleted the fix/v2-capacity-admission branch August 10, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant