Skip to content

perf(subagents): bound the parent-completion bookkeeping with a claim ledger - #744

Merged
Juliusolsson05 merged 3 commits into
mainfrom
perf/subagent-completion-ledger
Sep 3, 2026
Merged

Juliusolsson05 merged 3 commits into
mainfrom
perf/subagent-completion-ledger

Conversation

@Juliusolsson05

Copy link
Copy Markdown
Owner

Problem

SubAgentWatcherManager.observeParentEntry (src/main/subagents/index.ts) recorded every tool_result of the parent transcript into a per-session map — Read, Bash, Edit, Grep, all of it — although the only consumer, SubAgentWatcher.parentResult(toolUseId), ever asks about the handful of ids that belong to Agent sidecars. Nothing trimmed it; it was cleared only when the session stopped. A heavy 24-hour session performs tens of thousands of tool calls: ~1.5–7 MB of retained strings per session, 30–140 MB across twenty, growing for the life of each session. Details in #743.

What changed

  • New src/main/subagents/completionLedger.ts: record(toolUseId, status) keeps results in a bounded recent LRU (2,048) — enough to cover a result landing before its sidecar file is discovered by the poll — and lookup(toolUseId) promotes a hit to a never-evicted claimed tier, bounded by the number of sub-agents the session ever had. A finished sub-agent therefore cannot flip back to "running" once its result has been seen, which matters because the watcher recomputes done/error from lookup on every emit. record on a claimed id updates it in place.
  • The manager holds one ledger per session instead of the raw map; record's changed-flag drives the existing watcher refresh nudge; stop/stopAll unchanged.

Linked issues

Fixes #743. Refs #327 (hypothesis 1: a sibling accumulator), #365, #288, #103.

Verification

  • NODE_ENV=test npx vitest run --project unit src/main/subagents/ — 22 tests passed: the existing watcher, Codex tracker and shared suites plus the new ledger contracts (changed-flag semantics; oldest unclaimed results evicted at the cap; a claimed id survives any number of later records; in-place update of a claimed status; unknown id is undefined; non-positive window rejected).
  • npx tsc -p tsconfig.node.json --noEmit — clean.

Known limitations

  • A sub-agent whose result lands more than 2,048 parent tool results before the watcher first looks it up would show as running until the next parent result for it. The watcher polls every few seconds, so this needs thousands of tool results per second to occur.

Plan: docs/superpowers/plans/2026-09-03-subagent-completion-ledger.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Kk16MNVJtWAnCeGxGRuHqa

Juliusolsson05 and others added 3 commits September 3, 2026 13:34
… ledger

The sub-agent manager recorded every tool_result of the parent transcript
into a per-session map that only the sidecar watcher ever consulted, for
the handful of ids belonging to Agent sub-agents, and nothing trimmed it —
tens of thousands of retained entries per long session.

A CompletionLedger keeps a bounded recent window (2,048 results, enough to
cover a result landing before its sidecar is discovered) and promotes an id
to a never-evicted claimed tier on the watcher's first lookup, so a
finished sub-agent cannot flip back to running once its result was seen.

Fixes #743
Refs #327, #365, #288

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kk16MNVJtWAnCeGxGRuHqa
…n end to end

Review of #744 asked for two contracts the unit tests left implicit: a
re-recorded id is treated as most recently used rather than keeping its
old age, and the manager still reports a sub-agent done when the parent's
result arrived before the sidecar was discovered and thousands of
unrelated results followed — the claimed tier is what makes that hold.
Also corrects the header's "poll is seconds" wording: the watcher polls
every 600 ms and the window is bounded in results, not time.

Refs #743

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kk16MNVJtWAnCeGxGRuHqa
@Juliusolsson05

Copy link
Copy Markdown
Owner Author

Review feedback applied in the latest commit:

  • LRU re-insertion now has its own test: re-recording an id moves it to the young end, so the next overflow evicts the older neighbour instead.
  • Manager-level integration test (src/main/subagents/index.test.ts): a real temp project dir, the parent result recorded before the sidecar exists, then 3,000 unrelated results — the sub-agent stays done, which is exactly the claimed-tier guarantee.
  • Wording: the header now says the watcher polls every 600 ms and that the window is bounded in results, not time.

@Juliusolsson05
Juliusolsson05 merged commit 9833ef2 into main Sep 3, 2026
2 checks passed
@Juliusolsson05
Juliusolsson05 deleted the perf/subagent-completion-ledger branch September 3, 2026 20:59
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.

perf(subagents): completion bookkeeping records every tool result of a session forever

1 participant