feat(agent): fork-style parallel diagnostic exploration#90
Merged
Conversation
Closes #67. One diagnostic agent is a single line of reasoning, prone to tunnel vision on an ambiguous anomaly with several plausible causes. The coordinator can now fan out N diagnostic sub-agents concurrently from the shared detection baseline, each seeded with a distinct hypothesis, then merge the survivors. - config.agent_diagnostic_forks (default 1) gates fan-out; >1 forks (capped at the number of defined hypotheses). Default preserves single-agent behavior. - _run_diagnostics: single-agent path unchanged; fork path spawns via asyncio.gather (truly concurrent, not a loop), each fork retried independently (#51). Partial failure tolerated: survivors aggregated; abort only if every fork fails. - _merge_fork_diagnoses: namespaces each fork's ids (f{i}:) so merged sources, claims, and conflicts never collide; attribution preserved (the merged report re-validates). Forks that concluded a different anomaly_type than the primary (highest-confidence) fork produce a cross-fork ConflictRecord: unresolved, escalated via the existing #82 path, never a silent winner. anomaly_type is the deterministic disagreement signal; semantic claim-level reconciliation would need an LLM (noted out of scope). - _spawn_diagnostic_agent takes an optional hypothesis seed injected into the prompt. Tests: single-agent path when forks=1, concurrent spawn with distinct hypotheses (asyncio.Barrier proves concurrency, not sequential), partial-failure aggregation, all-fail abort, merge namespacing + attribution, cross-fork conflict creation, and the fork path end-to-end through run_cycle. Full suite 244 passed; ruff + mypy clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #67.
Problem
One diagnostic agent is a single line of reasoning, prone to tunnel vision on an ambiguous anomaly with several plausible causes.
Fix
The coordinator can now fan out N diagnostic sub-agents concurrently from the shared detection baseline, each seeded with a distinct hypothesis, then merge the survivors.
config.agent_diagnostic_forks(default1) gates fan-out;>1forks (capped at the number of defined hypotheses). Default preserves single-agent behavior._run_diagnostics: single-agent path unchanged; fork path spawns viaasyncio.gather(truly concurrent, not a loop), each fork retried independently (Structured error handling for subagent failures #51). Partial failure tolerated: survivors aggregated; abort only if every fork fails._merge_fork_diagnoses: namespaces each fork's ids (f{i}:) so merged sources, claims, and conflicts never collide; attribution preserved (the merged report re-validates, building on feat(agent): preserve claim-source attribution through report synthesis #88). Forks that concluded a differentanomaly_typethan the primary (highest-confidence) fork produce a cross-forkConflictRecord: unresolved, escalated via the existing feat(agent): enforce unresolved-conflict escalation to the coordinator #82 path, never a silent winner.anomaly_typeis the deterministic disagreement signal; semantic claim-level reconciliation would need an LLM (out of scope, noted)._spawn_diagnostic_agenttakes an optional hypothesis seed injected into the prompt.Tests
Single-agent path when
forks=1; concurrent spawn with distinct hypotheses (asyncio.Barrierproves concurrency, would deadlock/timeout if sequential); partial-failure aggregation; all-fail abort; merge namespacing + attribution; cross-fork conflict creation; and the fork path end-to-end throughrun_cycle(1 detect + 3 concurrent forks + 1 report).Full suite 244 passed; ruff + mypy clean.
Companion docs runbook is #78 (separate).
https://claude.ai/code/session_01R5VygSzbGTggW7mHd3PVwE