Skip to content

fix(subagent): reap orchestration-dispatched sub-agent handles#6333

Merged
bug-ops merged 1 commit into
mainfrom
fix/6288-subagent-collect-dispatch
Jul 16, 2026
Merged

fix(subagent): reap orchestration-dispatched sub-agent handles#6333
bug-ops merged 1 commit into
mainfrom
fix/6288-subagent-collect-dispatch

Conversation

@bug-ops

@bug-ops bug-ops commented Jul 16, 2026

Copy link
Copy Markdown
Owner

Summary

SubAgentManager::collect() was only ever invoked from the interactive /agent
polling path (poll_subagents()), never from the orchestration dispatch loop
(run_scheduler_loop). Every plan-executed sub-agent leaked its handle and never
wrote a final TranscriptMeta sidecar.

A naive ordering fix (call collect() right after the verifier reads the trace)
is not sufficient: status_tx flips to Completed before the corresponding
TaskEvent is even enqueued, and SchedulerAction::Verify is never emitted for
Failed outcomes or when verify_completeness is disabled, so a Verify-only reap
would still leak most terminal tasks.

Instead, grounding trace reads are decoupled from handle residency:

  • SubAgentManager::transcript_path_for() resolves the transcript path from
    config alone, independent of whether the handle is still tracked.
  • build_tool_trace_for_task and resolve_whole_plan_trace_paths (whole-plan
    grounding, a related residency hazard found during implementation) both now
    use it, so reaping can no longer silently degrade verifier grounding to
    fail-open None.
  • Agent::collect_finished_subagents() reaps every Completed/Failed/Canceled
    handle once per scheduler tick.

specs/009-orchestration/spec.md updated to reflect that grounding no longer
depends on handle residency.

Closes #6288

Test plan

  • cargo +nightly fmt --check — clean
  • cargo clippy --profile ci --workspace --all-targets --features "desktop,ide,server,chat,pdf,scheduler,testing" -- -D warnings — clean
  • cargo nextest run --config-file .github/nextest.toml --workspace --features "desktop,ide,server,chat,pdf,scheduler" --lib --bins — 13808 passed, 0 failed
  • RUSTFLAGS="-D warnings" RUSTDOCFLAGS="--deny rustdoc::broken_intra_doc_links" cargo doc --no-deps --workspace --features "desktop,ide,server,chat,pdf,scheduler" — clean
  • cargo test --doc -p zeph-subagent — clean, including new transcript_path_for doctest
  • 6 new/extended regression tests added, covering: the leak fix itself, grounding survives collection (per-task and whole-plan), None-manager no-op, Canceled-state reap
  • gitleaks protect --staged — clean

@github-actions github-actions Bot added bug Something isn't working documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate size/XL Extra large PR (500+ lines) labels Jul 16, 2026
@bug-ops
bug-ops enabled auto-merge (squash) July 16, 2026 18:42
SubAgentManager::collect() was only ever invoked from the interactive
/agent polling path, never from the orchestration dispatch loop
(run_scheduler_loop). Every plan-executed sub-agent leaked its handle
and never wrote a final TranscriptMeta sidecar.

A naive ordering fix is not sufficient: status_tx flips to Completed
before the corresponding TaskEvent is even enqueued, and
SchedulerAction::Verify is never emitted for Failed outcomes or when
verify_completeness is disabled, so a Verify-only reap would still
leak most terminal tasks.

Decouple grounding trace reads from handle residency instead:
SubAgentManager::transcript_path_for() resolves the transcript path
from config alone, with no dependency on the handle still being
tracked. build_tool_trace_for_task and resolve_whole_plan_trace_paths
both now use it, so reaping handles can no longer silently degrade
verifier grounding to fail-open None. Agent::collect_finished_subagents()
reaps every Completed/Failed/Canceled handle once per scheduler tick.

Update specs/009-orchestration/spec.md to reflect that grounding no
longer depends on residency.
@bug-ops
bug-ops force-pushed the fix/6288-subagent-collect-dispatch branch from bb349a5 to c4f0e8f Compare July 16, 2026 18:48
@bug-ops
bug-ops merged commit 0203786 into main Jul 16, 2026
43 checks passed
@bug-ops
bug-ops deleted the fix/6288-subagent-collect-dispatch branch July 16, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working core zeph-core crate documentation Improvements or additions to documentation rust Rust code changes size/XL Extra large PR (500+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zeph-subagent: SubAgentManager::collect() never called on the orchestration dispatch path

1 participant