Skip to content

feat(agent): dynamic, anomaly-derived diagnostic hypotheses + adaptive fork count#93

Merged
atomicdragonranch merged 1 commit into
masterfrom
feat/91-dynamic-hypotheses
Jul 9, 2026
Merged

feat(agent): dynamic, anomaly-derived diagnostic hypotheses + adaptive fork count#93
atomicdragonranch merged 1 commit into
masterfrom
feat/91-dynamic-hypotheses

Conversation

@atomicdragonranch

Copy link
Copy Markdown
Owner

Closes #91.

Problem

Fork hypotheses (#67) were a hard-coded generic list, and the coordinator took the first N regardless of what the anomaly actually was, the cert-video limitation. The forks should be derived from this anomaly, and the fork count should adapt to how ambiguous it is.

Fix

  • config.agent_hypothesis_mode (static | map | llm, default map), validated at startup via a Literal. Only matters when agent_diagnostic_forks > 1.
  • ANOMALY_HYPOTHESES: per-anomaly_type candidate causes (latency_spike, throughput_drop, backpressure, checkpoint_failure, memory_pressure, error_burst); unknown/unmapped types fall back to the generic angles.
  • _plan_hypotheses picks the pool per mode and bounds it by the cap; the resulting length is the fork count, so a clear-cut anomaly runs one agent even when the cap is higher (adaptive). llm mode calls the model once pre-fan-out and falls back to the map on any failure, so a diagnosis never hinges on the optional pre-step.
  • _run_diagnostics fans out over the planned hypotheses (single-agent when 0/1, seeded with the one hypothesis if present).

agent_diagnostic_forks default 1 still preserves single-agent behavior. Also refreshes the fork runbook (mode config, adaptive count, type-specific log example).

Tests

cap<=1 -> single; map type-specific + unknown fallback; static generic; cap bounding; llm parse + failure-fallback-to-map; fork seeding with type hypotheses; adaptive count below cap; config default/override/invalid-rejected.

Full suite 255 passed; ruff + mypy clean.

Related: builds on #67; complements #77 (cross-cycle change awareness).

https://claude.ai/code/session_01R5VygSzbGTggW7mHd3PVwE

…e fork count

Closes #91.

Fork hypotheses were a hard-coded generic list, and the coordinator took the
first N regardless of what the anomaly was. Now they are derived from the
anomaly and the fork count adapts to how many causes it warrants.

- config.agent_hypothesis_mode (static | map | llm, default map), validated at
  startup via a Literal. Only takes effect when agent_diagnostic_forks > 1.
- ANOMALY_HYPOTHESES: per-anomaly_type candidate causes (latency_spike,
  throughput_drop, backpressure, checkpoint_failure, memory_pressure,
  error_burst); unknown/unmapped types fall back to the generic angles.
- _plan_hypotheses picks the pool per mode and bounds it by the cap; the
  resulting length is the fork count, so a clear-cut anomaly runs one agent even
  when the cap is higher (adaptive). llm mode calls the model once pre-fan-out
  and falls back to the map on any failure, so a diagnosis never hinges on it.
- _run_diagnostics fans out over the planned hypotheses (single-agent when 0/1,
  seeded with the one hypothesis if present).

agent_diagnostic_forks default 1 still preserves single-agent behavior. Also
refreshes the fork runbook (mode config, adaptive count, type-specific log
example).

Tests: cap<=1 -> single, map type-specific + unknown fallback, static generic,
cap bounding, llm parse + failure fallback, fork seeding with type hypotheses,
adaptive count below cap, and config default/override/invalid-rejected. Full
suite 255 passed; ruff + mypy clean.
@atomicdragonranch atomicdragonranch merged commit 5d671cf into master Jul 9, 2026
3 checks passed
@atomicdragonranch atomicdragonranch deleted the feat/91-dynamic-hypotheses branch July 9, 2026 19:30
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.

feat(agent): dynamic, anomaly-derived diagnostic hypotheses (not a hard-coded list)

1 participant