Skip to content

fix(coding-agent): settle late compaction slices and forward daemon subagent lineage - #2021

Merged
sethkarten merged 1 commit into
mainfrom
fix/semantic-edges-settle-race-and-daemon-lineage
Sep 3, 2026
Merged

sethkarten merged 1 commit into
mainfrom
fix/semantic-edges-settle-race-and-daemon-lineage

Conversation

@snimu

@snimu snimu commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

What provenance consumers lose today

Two defects in the ai.prime.acp/semantic-edges-v1 producer (#1885), both found during review of #1984:

  1. Daemon-hosted subagents have no spawn edge. The runtime and daemon hosts pass semanticParentSessionId/semanticSpawnedByRequestId correctly, but the production runtime factory rebuilds session options through the resolveRuntimeSessionOptions() whitelist — which did not include the two fields. Every session created through that factory (all daemon workers and runtime-hosted subagents) registered with no parent session and no spawning request, so no subagent_call edge could ever be derived for them. Only the inline host, which bypasses the factory, produced complete lineage.
  2. A completed summary call can be recorded as forever in-flight. In a split-turn compaction, the two summary slices run under Promise.all. When one slice rejects, the compaction settles as failed and drains the uncommitted-slice list; a sibling slice that resolves after that pushed its request ID into the already-drained list, leaving a request_started with no terminal event. The fold treats such a request like a crash window (zero edges — no wrong edges are derived), but provenance under-claims a wire call that actually completed.

The two mechanisms

  • resolveRuntimeSessionOptions() forwards semanticParentSessionId and semanticSpawnedByRequestId (2 lines). The factory closure is extracted as createDefaultRuntimeFactory()main() remains its consumer — so the new end-to-end pin exercises the real factory. The prior coverage asserted the fields on the options handed to mocked factories, upstream of the drop; that mock blindness is exactly how this shipped broken.
  • _compact() keeps a compactionSettled flag, set where the slice list drains (commit and catch). A summary slice whose wire call resolves after the compaction settled now settles its own request as request_failed instead of pushing into the drained list. No restructuring of the Promise.all flow.

Deliberate behavior notes

  • The late slice settles as failed even though its wire call succeeded: its output was discarded (the compaction failed), and a failed summary slice contributes no edges — consistent with the existing invariant that a failed or cancelled compaction leaves no committed summary request.
  • createDefaultRuntimeFactory extraction is mechanical; behavior of the factory is unchanged except the whitelist addition.

Validation

  • new pins (each verified fail-unfixed against the pre-fix code): main-interactive-routing — whitelist forwards the two fields; suite/agent-session-runtime — a subagent created through the production factory registers parent_session_id/spawned_by_request_id and derives a subagent_call edge; agent-session-semantic-edges — a slice resolving after a sibling's failure settles as request_failed, never left in-flight (the whitelist pins were failed with only the 2 whitelist lines reverted, isolating them from the extraction)
  • sanitized suites: semantic-edges (52), agent-session-semantic-edges (23), suite/agent-session-compaction, suite/agent-session-compaction-continuation, daemon-mode (184), main-interactive-routing (53), suite/agent-session-runtime (26) — 387 tests, 0 failures
  • root npm run check (biome, tsgo, installer render, browser smoke) passes via the pre-commit hook

LOC

Net src: agent-session.ts +9, main.ts +10/−0 effective (58+/48− is the factory extraction moving the closure body; the semantic delta is the 2 whitelist lines + the export wrapper). Tests +145, changelog +1. Classification: mechanism-preserving fixes — no new mechanism beyond the settled flag; the factory extraction is a move, not an addition.

Linear: RES-1261 https://linear.app/primeintellect/issue/RES-1261


Note

Medium Risk
Touches session compaction ledger semantics and subagent session creation on the daemon/runtime factory path; incorrect behavior under-claims provenance or leaves in-flight requests, but changes are narrow guardrails rather than new compaction or spawn flows.

Overview
Restores semantic spawn lineage for daemon- and runtime-hosted subagents by whitelisting semanticParentSessionId and semanticSpawnedByRequestId in resolveRuntimeSessionOptions(), so the production path can again register parent session / spawning request and derive subagent_call edges. The daemon runtime factory closure is extracted as exported createDefaultRuntimeFactory() (behavior unchanged aside from the whitelist); main() now calls that helper.

Fixes a split-turn compaction race where a summary slice that finished after a sibling failure already drained uncommittedSlices could leave a request_started with no terminal event. _compact() tracks compactionSettled and marks such late slices as failed instead of enqueueing them after drain.

Tests pin whitelist forwarding, end-to-end lineage through the real factory, and late slice settlement on the semantic-edges ledger.

Reviewed by Cursor Bugbot for commit d4ea4a0. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix late compaction slice settlement and forward subagent lineage in AgentSession

  • Adds a compaction-settled flag to AgentSession.compact so summary slices resolving after a sibling failure or after settlement are explicitly failed instead of left in-flight.
  • Forwards semanticParentSessionId and semanticSpawnedByRequestId from runtime session options into resolved options in resolveRuntimeSessionOptions, preserving spawn lineage for child sessions.
  • Extracts the production runtime session factory from main into createDefaultRuntimeFactory and replaces the inline closure with a call to it.
  • Adds regression and integration tests covering late-summary terminalization and lineage forwarding through the production factory boundary.
  • Risk: createDefaultRuntimeFactory is newly exported from main.ts; callers relying on the previous inline closure behavior should use the exported function.

Macroscope summarized d4ea4a0.

…ubagent lineage

resolveRuntimeSessionOptions now whitelists semanticParentSessionId and semanticSpawnedByRequestId, so sessions created through the production runtime factory (daemon workers, runtime hosts) register spawn lineage; the factory is extracted as createDefaultRuntimeFactory so the pin exercises the real path instead of a forward-everything test factory. A split-turn summary slice resolving after a sibling already failed the compaction now settles as request_failed instead of pushing into the drained slice list and staying in-flight forever.
@sethkarten
sethkarten self-requested a review September 3, 2026 21:17
@sethkarten
sethkarten merged commit 6950bc8 into main Sep 3, 2026
26 checks passed
@sethkarten
sethkarten deleted the fix/semantic-edges-settle-race-and-daemon-lineage branch September 3, 2026 21:18
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.

2 participants