Skip to content

feat(launch): cap hangar concurrency and queue launches beyond it - #52

Merged
musingfox merged 7 commits into
mainfrom
feat/hangar-concurrency-cap
Oct 11, 2026
Merged

musingfox merged 7 commits into
mainfrom
feat/hangar-concurrency-cap

Conversation

@musingfox

@musingfox musingfox commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Summary

The hangar now runs at most a fixed number of agents at once. A dispatch beyond that waits in an in-memory queue and starts by itself when a slot frees.

  • Cap: performance cores − 2 (minimum 1), read from /usr/sbin/sysctl -n hw.perflevel0.physicalcpu. If the count can't be read, the cap is 4. CC_MOBILE_HANGAR_CAP overrides it, and a malformed value stops startup. Startup prints one line, hangar cap N (source).
  • Occupancy: the number of entries in the hangar's agent.list, plus launches admitted but not finished. A launch's reservation counts toward every reading issued before it finished, and toward none issued after.
  • POST /api/launch:
    • With a free slot and nobody waiting, it answers 201 as today.
    • Otherwise it answers 202 {queued: true, position} and starts FIFO on a 10 s poll, or as soon as a launch finishes or a hangar teardown runs.
    • A card already waiting or starting gets 409 already_queued.
    • An unknown occupancy (hangar offline, or agent.list silent for 2 s) gets 503 hangar_offline.
    • All existing checks run first with today's codes, and nothing is written before admission.
  • Dequeue: re-reads the card and profile, then does today's writes. A failure before the prompt is a server log line only, with no audit format change.
  • GET /api/cards: each card gains queued, and a waiting or starting card is not dispatchable. The reply gains hangar: {cap, occupied, queued} | null. Card identity (cardKey) is normalized for both bindings and the queue.
  • CLAUDE.md: the Launch API and Cards API sections are updated, pinned by docs-launch-claims.test.ts.

Each commit typechecks and passes bun test on its own (2661 pass at the tip).

Breaking

A caller that treats only 201 as success reads a queued card as a failure. The iPhone QuickAdd script gets this handling under its own card (quickadd-launch-queued-reply).

Live verification (human-run, after merge + pm2 restart cc-mobile-prod)

  • pm2 logs cc-mobile-prod shows hangar cap 4 (6 performance cores).
  • CC_MOBILE_HANGAR_SESSION=fleet CC_MOBILE_HANGAR_CAP=2 bun run dev:server, then curl -s http://127.0.0.1:3001/api/cards | jq .hangar.cap gives 2.
  • Five test cards: four answer 201, the fifth 202 position: 1, and the hangar never exceeds 4 agents.
  • /exit one claude with its pane left open: the fifth card starts within 10 s. Then close a pane: the slot frees too.
  • bun run test:herdr covers server/integration/launch-worktree.e2e.test.ts, which was edited for tsc and not yet run.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Launches now respect Hangar capacity: when all slots are occupied, valid launches wait in a queue and start as capacity becomes available.
    • Launch requests report whether a launch started, its queue position, or whether the Hangar is unavailable or the card is already queued.
    • The Cards API now reports each card’s queue status and Hangar capacity, occupancy, and queue totals. Cards already queued or bound cannot be dispatched.
    • Hangar capacity can be configured, with a default based on available performance cores and a fallback value of 4.
    • Updated documentation describes launch queue behavior and the information returned by the APIs.

musingfox and others added 7 commits October 11, 2026 13:51
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A launch that finds the hangar full answers 202 with its place in line
and starts when a slot frees; an offline hangar is refused with 503, a
card already waiting with 409. GET /api/cards reports the cap, the
occupancy and the queue, and marks queued cards as not dispatchable.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5d4c38c0-fb2c-4db8-b30a-298003562e6a

📥 Commits

Reviewing files that changed from the base of the PR and between 24fc314 and b4c43a5.


📒 Files selected for processing (24)
  • CLAUDE.md
  • server/__tests__/cards-api.test.ts
  • server/__tests__/config.test.ts
  • server/__tests__/docs-launch-claims.test.ts
  • server/__tests__/hangar-assembled.test.ts
  • server/__tests__/hangar-cap.test.ts
  • server/__tests__/launch-api-routing.test.ts
  • server/__tests__/launch-api.test.ts
  • server/__tests__/launch-queue.test.ts
  • server/app.ts
  • server/cards.ts
  • server/config.ts
  • server/hangar-cap.ts
  • server/herdr/backend.test.ts
  • server/herdr/backend.ts
  • server/herdr/client.test.ts
  • server/herdr/client.ts
  • server/herdr/sessions.ts
  • server/herdr/sided-backend.test.ts
  • server/herdr/sided-backend.ts
  • server/index.ts
  • server/integration/launch-worktree.e2e.test.ts
  • server/launch-queue.ts
  • server/launch.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.



📝 Walkthrough

Walkthrough

The server now resolves a hangar launch capacity, tracks occupancy, and queues launches when capacity is full. Launch responses include queue outcomes, and the Cards API reports queued cards and hangar status.

Changes

Hangar launch flow

Layer / File(s) Summary
Capacity and occupancy
server/hangar-cap.ts, server/config.ts, server/index.ts, server/herdr/*, server/sided-backend.ts, server/__tests__/config.test.ts, server/__tests__/hangar-cap.test.ts, server/__tests__/hangar-assembled.test.ts, server/herdr/* tests
The server resolves capacity from CC_MOBILE_HANGAR_CAP, performance-core counts, or the fallback value of 4. The backend reads hangar agent counts with a timeout.
Queue and launch execution
server/launch-queue.ts, server/launch.ts, server/app.ts, server/__tests__/launch-queue.test.ts, server/__tests__/launch-api.test.ts, server/__tests__/launch-api-routing.test.ts, server/__tests__/hangar-assembled.test.ts, server/integration/launch-worktree.e2e.test.ts
The queue checks occupancy, rejects duplicate keys, and dispatches waiting launches in order. The launch endpoint returns immediate results or queued, duplicate, and offline responses.
Cards API queue status
server/cards.ts, server/__tests__/cards-api.test.ts, server/__tests__/hangar-assembled.test.ts, CLAUDE.md, server/__tests__/docs-launch-claims.test.ts
The Cards API reports queue membership and hangar status. Queued cards are not dispatchable. Documentation describes the queue and response behavior.

Priority: ➖ Normal

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

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant LaunchAPI
  participant LaunchQueue
  participant HangarBackend
  Client->>LaunchAPI: Submit validated launch
  LaunchAPI->>LaunchQueue: Submit card key and start callback
  LaunchQueue->>HangarBackend: Read agent count
  HangarBackend-->>LaunchQueue: Return count or unavailable
  LaunchQueue-->>LaunchAPI: Return started result or queue position
  LaunchAPI-->>Client: Return launch response
Loading

Merge Risk | 🔵 Low · up to b4c43

Merge Risk: 🔵 Low · up to b4c43

Hangar launches now queue when the cap is reached. If the hangar lists a new agent late, one extra launch could briefly exceed the cap. This is a narrow, self-correcting edge case, and the PR notes that live verification is still pending.

Security Architecture Review

Security architecture risk: 🔵 Low · up to b4c43

Existing access checks are preserved, launch inputs are checked again before execution, and unknown occupancy prevents admission. Remaining uncertainty concerns authorization changes during long waits and deployment-wide coordination of capacity.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — A caller admitted through the existing access controls can schedule work affecting the configured vault's launch bindings, validated project worktrees, and shared hangar agent capacity. The changed execution path still explicitly creates sessions on the hangar side.

Trust Boundaries and Controls

  • observed — The root request gate remains ahead of the APIs, with identity enforcement conditional on trusted-user configuration. Launch submission additionally requires the configured bearer token before validation or queuing. This preserves the inspected admission boundary relative to the base.
  • observed — Queued execution inherits admission-time authorization rather than authenticating again. It does repeat card containment, file-type, profile, cwd, and allowed-root checks. Production wiring reads launch configuration at startup and uses that configuration to construct the application.

Resilience and Maintainability Implications

  • observed — Binding failure tears down the created session and removes a newly created worktree. Prompt failure retains the session and binding, as it did at the PR base. Queue membership ends when starting finishes, while subsequent capacity decisions still count retained agents reported by the daemon; Cards dispatchability also checks persisted bindings.

Hardening Proposals

  • proposed — Define whether accepted launches survive authorization revocation during a wait. If revocation must cancel accepted work, add an explicit cancellation or authorization-generation mechanism and test it alongside restart and partial-failure behavior.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 44 functions across 23 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely summarizes the main change: limiting Hangar launch concurrency and queueing launches that exceed the cap.
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.

Full details: Docstring Coverage

Explanation

Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 44 functions across 23 files. (1 skipped: 1 unsupported.)


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR


🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@musingfox
musingfox merged commit d9f0690 into main Oct 11, 2026
4 checks passed
@musingfox
musingfox deleted the feat/hangar-concurrency-cap branch October 11, 2026 09:23
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