Skip to content

feat(comms): delegation ledger — task ids, busy retries, durable receipts, read-back tools - #566

Merged
milind-soni merged 1 commit into
mainfrom
feat/delegation-ledger
Aug 29, 2026
Merged

feat(comms): delegation ledger — task ids, busy retries, durable receipts, read-back tools#566
milind-soni merged 1 commit into
mainfrom
feat/delegation-ledger

Conversation

@milind-soni

Copy link
Copy Markdown
Owner

What changed

The async handoff path (delegate_bot) grows the missing half: the delegating bot can now learn what happened.

  • Task ids: queueDelegation returns an id; the tool reply hands it to the bot as a claim ticket.
  • Busy ≠ canceled: a busy target keeps the handoff queued with bounded retries (3). When any of the target's turns settles, waiting source threads re-drain. This also surfaced and fixes a real race: a drainDelegations call landing while a drain was already running was silently dropped by the drainingThreads lock — exactly where the waiting-on retry lands — now remembered via queuedRedrains and honored when the running drain finishes.
  • Durable receipts: every terminal outcome (done/failed/denied/busy_gave_up/dropped/error + the peer's bounded reply, 4k chars) persists to delegation-receipts.json, pruned by count (100) and age (48h), loaded at boot, written before any mirror short-circuits so a receipt exists even when the channel/target is gone.
  • Read-back tools: check_delegation (status now) and wait_delegation (bounded long-poll, ≤240s — one parked HTTP request instead of a model inference per peek) over GET /api/internal/delegations/:id, with sender+thread ownership enforced (403 on cross-thread reads). Flat schemas and guiding errors per CONTRIBUTING's MCP rules.

Why

The third borrow from the vercel-labs/fx architecture review (after #564 and #563): fx's subagent ledger lets a parent delegate, keep working, and pull bounded results later. Our delegate_bot was fire-and-forget by contract — the requester never learned the outcome — and ask_bot's 4-minute synchronous wait was the only alternative. Per the maintainer's direction this replaces the parallel efforts in #516/#423 with one implementation built on main's existing delegations.ts queue (whose design — durable pending file, drain-on-settle, approval-at-drain — is kept intact).

How it was verified

  • server/delegations.test.ts — 27 pass, run 3× for determinism. New: busy→waiting-chip→retention→retry-drain dispatch with the task id riding to the target; bounded give-up with a busy_gave_up receipt; receipts surviving _loadPending() reload and pruning at 100; dropped receipts on discard. The pre-existing busy test updated from "canceled" to the new waiting semantics.
  • server/drivers/agents-proxy.test.ts + server/comms.test.ts — 42 pass. New: task-id suffix in the delegate reply; flat-schema guard for both new tools; guided error without a wire call; wait_ms/ownership params on the read-back wire.
  • Mutation check: disabling the requeue branch fails 3 tests.
  • tsc -p tsconfig.server.json clean. Lint: server/index.ts exact parity (107→107); delegations.ts +7 and proxy +2 findings, all no-runtime-typeof-family hits in the same style as the surrounding loaders/wire-parsers (lint is not a CI gate; flagged for transparency — the new receipts loader narrows every field into locals with a single SAFETY-commented view).

Checklist

  • pnpm typecheck and the touched test files pass locally
  • Server behavior changes come with tests
  • No dist-server/ edits
  • No macOS-only code; no shell: true
  • No secrets in logs, responses, events, or argv (receipts carry bot-visible reply text only)

🤖 Generated with Claude Code

…ceipts, and read-back tools

Bots could hand work to a peer but never learn what happened: delegate_bot
was fire-and-forget by contract, a busy target CANCELED the handoff outright,
and ask_bot's synchronous wait was the only way to get an answer back.
Modeled on fx's durable subagent message ledger, adapted to the existing
queue in delegations.ts:

- queueDelegation returns a task id; the delegating bot receives it in the
  tool reply as its claim ticket.
- A busy target no longer cancels the handoff. The item stays queued with a
  bounded retry count (3); any of the target's turns settling re-drains the
  waiting source threads. Fixed en route: a drain request arriving while a
  drain was already running was silently dropped by the drainingThreads
  lock — precisely where the waiting-on retry lands — so requests are now
  remembered and honored when the running drain finishes.
- Every terminal outcome writes a durable receipt (done/failed/denied/
  busy_gave_up/dropped/error + the peer's bounded reply), persisted to
  delegation-receipts.json, pruned by count (100) and age (48h), loaded at
  boot, and written before any mirror short-circuits.
- New MCP tools: check_delegation (status now) and wait_delegation (bounded
  long-poll up to 240s — ONE parked HTTP request instead of a model
  inference per status peek), over GET /api/internal/delegations/:id with
  sender/thread ownership enforced. Flat schemas, guiding errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openmausbot-docs Ready Ready Preview Aug 29, 2026 2:27pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 10 seconds.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 69c41f9d-27da-47fe-90e3-bf87bf5a79ad

📥 Commits

Reviewing files that changed from the base of the PR and between aad38e8 and e73b250.

📒 Files selected for processing (5)
  • server/delegations.test.ts
  • server/delegations.ts
  • server/drivers/agents-proxy.test.ts
  • server/drivers/agents-proxy.ts
  • server/index.ts

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.

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