Skip to content

feat(daemon): one automatic-restore budget per execution host - #27492

Merged
OrcaWin merged 2 commits into
mainfrom
np/d1c-shared-budget
Oct 11, 2026
Merged

OrcaWin merged 2 commits into
mainfrom
np/d1c-shared-budget

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​351 $\color{#cf222e}{\Huge{\mathbf{−}}}$​27 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​324
Prod 6 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​336 $\color{#cf222e}{\Huge{\mathbf{−}}}$​112 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​224

ELI5

A desktop Orca and an orca serve on the same machine each run their own terminal host. Until now each one had its own automatic-restore budget, so two of them could restore 16 agents at once, where the owner decided on 8 per machine. Now they share one budget, using the same small per-machine file that #27488 introduced for the terminal cap.

What Changed

  • Before: each daemon applied the restore limits to itself only: 3 at a time, 1 per second with a burst of 3, and 8 live automatic restores.
  • After: each daemon also publishes its automatic work in its ledger file: restores in flight, live automatic restores, and when it admitted them in the last 10 seconds. Before deciding, it adds what every other daemon on the host published:
    • Live cap and concurrency: its own counts plus everyone else's.
    • Rate: it replays every daemon's recent admits through one bucket. The bucket is never fuller than the daemon's own exact bucket, so sharing can only slow it down, never speed it up.
    • Waiting: a restore waiting because another daemon holds the slots checks again every 500 ms, since one daemon cannot wake another's waiters.
  • The policy itself (decideSpawnAdmission) is unchanged. It receives a merged view for that one decision, and accounting stays on each daemon's own state.
  • An entry written by a daemon from feat(daemon): cap terminals per execution host #27488, which publishes terminals only, reads as zero automatic work.
  • The gate's host-share bookkeeping moves to terminal-spawn-host-share.ts, and the deferral error to its own file, to keep the gate small.

Why

Decision Q1 says the budget is per execution host: a desktop and orcad on one machine share it. The ledger already gives each daemon one file it alone writes, with stale-holder recovery (a dead pid is deleted, an unrefreshed entry is ignored). Reusing it needs no lock, and no lock recovery after a crash.

Alternatives considered:

  • One shared counter file under a lock. Exact, but every fork would then wait on a cross-process lock. Recovering a crashed holder is the hard part, and feat(daemon): cap terminals per execution host #27488 already avoids it.
  • A coordinator daemon per machine. That is a new long-lived process with its own lifecycle.

Accepted imprecision: two daemons deciding in the same millisecond can each take the last automatic slot, because the automatic budget is read and then published, not reserved first. This is bounded by one restore per extra daemon. It is a budget, not a safety ceiling; the ceilings remain #27488's terminal cap, which does reserve first, and the growth breaker. The merged rate bucket starts full 10 seconds back, so a sustained stream across daemons can get at most one extra burst; each daemon's own bucket still holds.

Linked Issue

Part of the headless-serve robustness work for #10493 (D1 step 4, decision Q1 "per execution host"). #27488 is merged; this PR is now based on main.

Visual Proof

N/A. This is host-side admission only; no UI changes.

Testing

  • Pure merge: unchanged state when no other daemon has work; another daemon's live restores hit the shared live cap of 8; a shared concurrency of 3; one rate budget across daemons; admits older than 10 s are forgotten; never more permissive than the daemon's own bucket.

  • Ledger: sums the automatic work other daemons publish, drops old admits, and reads a terminals-only entry from feat(daemon): cap terminals per execution host #27488 as zero.

  • Two real TerminalHost + gate pairs sharing one ledger dir (desktop and serve): 5 + 3 live restores defer the ninth with live_cap, and one exit frees it; desktop and serve spend one burst; a waiter on serve gets through once the desktop releases its slots.

  • pnpm tc, pnpm lint, oxlint and pnpm run check:code-quality:changed pass. The gate, ledger, guard and spawn-intent suites pass.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

Review

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

SSH: each SSH host's daemons share that host's ledger; a client never reads it. The crash pause stays per daemon (its marker sits in its runtime dir). Pressure is already a machine-wide fact. Desktop stays in observe mode, but it still publishes its automatic work. So when the desktop already runs 8 or more resumed agents, an enforcing orca serve on the same machine keeps its own declared restores asleep (live_cap). This is intended: the budget protects the machine, and restores the desktop already runs use it. Those panes keep their resume handle, a click resumes them, and an old client's restores are still only paced. A test pins this. Windows and macOS/Linux use the same file logic.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@OrcaWin
OrcaWin changed the base branch from np/d1c-terminal-cap to main October 11, 2026 14:12
@OrcaWin
OrcaWin requested a review from brennanb2025 as a code owner October 11, 2026 14:12
@OrcaWin
OrcaWin force-pushed the np/d1c-shared-budget branch from 8ab05d5 to 5a78f3e Compare October 11, 2026 14:12
@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fbaf2bcb-7abe-43d3-8321-f69b88de32b7

📥 Commits

Reviewing files that changed from the base of the PR and between 0c98466 and 11a1d7f.


You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e0bb3405-feab-4d99-bc4c-9182ad87c2b4



📥 Commits

Reviewing files that changed from the base of the PR and between ce028b1 and 0c98466.




📒 Files selected for processing (9)
  • src/main/daemon/host-terminal-ledger-entry.ts
  • src/main/daemon/host-terminal-ledger.test.ts
  • src/main/daemon/host-terminal-ledger.ts
  • src/main/daemon/terminal-spawn-deferred-error.ts
  • src/main/daemon/terminal-spawn-gate-shared-budget.test.ts
  • src/main/daemon/terminal-spawn-gate.ts
  • src/main/daemon/terminal-spawn-host-share.ts
  • src/shared/host-automatic-work-budget.test.ts
  • src/shared/host-automatic-work-budget.ts



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





📝 Walkthrough
📝 Walkthrough
📝 Walkthrough

Walkthrough

The host terminal ledger now stores and aggregates terminal counts, automatic-work counts, and recent admission timestamps. Spawn gates use data from other daemons when evaluating automatic-work admission and host terminal capacity. The changes add ledger, budget, and multi-daemon gate tests.





Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 0c984

The change makes automatic-restore limits shared across daemons on one host. No actionable merge-blocking risk is evident from the supplied context.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 9 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Title check Passed The title clearly and concisely describes the primary change: sharing the automatic-restore budget across daemons on one execution host.
Description check Passed The description is complete and aligned with the template. It explains the user impact, implementation, rationale, alternatives, linked issue, testing, platform considerations, and checklist status. I…



✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR





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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@OrcaWin
OrcaWin force-pushed the np/d1c-shared-budget branch from 0c98466 to 11a1d7f Compare October 11, 2026 14:29
@OrcaWin
OrcaWin merged commit 6e9dc09 into main Oct 11, 2026
44 checks passed
@OrcaWin
OrcaWin deleted the np/d1c-shared-budget branch October 11, 2026 14:45
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