Repository navigation
fix(childThreads): skip ancestor loads for children with no requests (#256) - #257
Conversation
…to deliver (#256) Startup reconciles every subagent thread. Each child loaded its ancestors' full projections and the parent's runs and messages, so a large parent with many children ran the server out of memory at boot, in a crash loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
What: Independent Sol review passes at exact head Round 1 retry. Read the PR body in full, inspected
Proof executed only in an independent
The production OOM disappearance was not independently live-verified. This review verifies the skipped ancestor-read mechanism and the scoped behavior above. No writes were made in Reviewer: gpt-6.1-sol, Codex harness, medium effort. |
|
Independent review of The early return matches the loop. A new request still reconciles. The new check reads before the parent lock, while the loop re-reads under the lock. A request that appears only after that first read is not dropped: it is its own Scope: parent is Proof, in
|
…to deliver (#256) (#257) Startup reconciles every subagent thread. Each child loaded its ancestors' full projections and the parent's runs and messages, so a large parent with many children ran the server out of memory at boot, in a crash loop. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
What changed: A child thread with no requests to deliver no longer loads its ancestors during request reconciliation.
Why: Startup reconciles every subagent thread. Each one loaded its whole ancestor chain, including the parent's full projection, runs and messages. On rocky, a large planner thread with many children made the server run out of memory at boot: 25+ V8 OOM aborts since 2026-10-13 20:09Z, on both the new and the previous build.
So what: After Sol and Grok review, the planner merges this, builds, and redeploys rocky to stop the crash loop.
Partly fixes #256 (the hot event-decode loop on the shared connection). It does not close it.
Change
reconcileChildRequestsreturns right after reading the child's ownruntimeRequestswhen none of them is a deliverable kind (dynamic_tool_callandauth_refreshwere already skipped inside the loop). The loop body does nothing for such a child, so behavior is unchanged; only the ancestor and parent reads are skipped.runtime-request.updated, which reconciles that child again, so an early return can't lose a request.Proof
requestWake.noRequests.test.tsfails on916b0febwithloaded ancestor shell parentand passes with the fix.src/childThreads/tests pass: 30 passed, 1 skipped, including the existing startup reconcile test that uses real requests.Chromeria-2026-10-13-*.ips, 25 of them, allnode::OOMErrorHandler. The server's own trace is dominated bychildThreads.readRetirementState,childThreads.reconcileRequestsandOrchestrationEventStore.rowToV2StoredEvent. Rolling back toa6fc446didn't help: the server reached 3.6 GB in 2 minutes.Elon record
requestWake.ts,retirement.tsand the Orchestrator startup path, ran the failing-then-passing test and the childThreads suite, and queried the runtime request counts read-only.🤖 Generated with Claude Code