Skip to content

Commit 91eb4fe

Browse files
Jammy2211claude
authored andcommitted
feat(bug): add the Bug Agent conductor (the organism's immune system)
Add agents/conductors/bug/ — a new PyAutoBrain conductor framed as the organism's immune system: recognise a bug / regression / failing test / PyAutoHeart finding, tell it from benign self, classify it (severity/scope/type/confidence), decide where the fix belongs (source-first; never degrade a user-facing workspace script, the autoimmune failure mode), and emit a BugDecision the start_dev -> ship_* workflow consumes. It reasons; it never edits source. - _bug.py reuses the Feature Agent core (parse_prompt / estimate_difficulty / memory_context / in-flight down-ranking) and adds classify / reproduction / fix_locus / health_mode; stdlib-only, offline, never writes. - bug.sh entrypoint; health mode reads the live vitals verdict AND scans filed PyAutoHeart issues (gh), routing real defects to bug/health_fixes/. - Consults the vitals faculty, never Heart directly; conductor-only with a documented seam for a future read-only diagnosis faculty. - Promote /bug from a work-type entry to a real conductor across bin/pyauto-brain, skills/bug/bug.md, skills/COMMANDS.md, README.md, AGENTS.md. Refs #18 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 84210ee commit 91eb4fe

9 files changed

Lines changed: 869 additions & 22 deletions

File tree

AGENTS.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ humans invoke identically, so behaviour isn't re-derived from prose each time.
119119
context and (for risky work) the vitals faculty, and emits a `FeatureDecision`
120120
that the existing `start_dev → ship_library/ship_workspace` workflow consumes.
121121
It reasons; it never edits source. (Organism-facing name: *Growth Agent*.)
122+
- **`agents/conductors/bug/`** — the organism's **immune system**: recognises a
123+
pathogen (bug, regression, failing test or PyAutoHeart finding), tells it from
124+
benign self, classifies it (severity/scope/type/confidence), consults PyAutoMemory
125+
as immune memory, and mounts a *targeted* response — deciding **where the fix
126+
belongs** (source-first; never degrading a user-facing workspace script, the
127+
autoimmune failure mode) and emitting a `BugDecision` the `start_dev → ship_*`
128+
workflow consumes. Health mode reads two inputs: the live vitals verdict **and**
129+
the filed PyAutoHeart issues. Reuses the Feature Agent's core; consults the vitals
130+
faculty, never Heart directly. It reasons; it never edits source. (Organism-facing
131+
name: *Immune Agent*.)
122132
- **`agents/conductors/build/`** — the executive function for execution work.
123133
Consults the vitals faculty, reasons over the verdict, and on a healthy result
124134
delegates to the appropriate PyAutoBuild capability. The canonical example of
@@ -155,8 +165,9 @@ humans invoke identically, so behaviour isn't re-derived from prose each time.
155165
> consulting the vitals faculty *more strictly*, then requesting execution from the
156166
> Build Agent / PyAutoBuild. Until then: one agent now, clean seam for two later.
157167
158-
More specialist agents are expected over time (Bug / Refactor / Documentation /
159-
Research agents, cost/risk faculties, …). When adding one, **place it by tier**:
168+
More specialist agents are expected over time (Refactor / Documentation / Research
169+
agents, a `diagnosis` faculty split from the Bug Agent, cost/risk faculties, …).
170+
When adding one, **place it by tier**:
160171
a side-effecting decider you drive → `agents/conductors/<name>/`; a read-only
161172
opinion the conductors consult → `agents/faculties/<name>/`. Follow the Build
162173
Agent's shape (a concise `AGENTS.md` opening with its `Tier:` line, a
@@ -194,16 +205,17 @@ to the right agent; normal usage never says "PyAutoBrain".
194205
| Command | Routes to | Tier |
195206
|---------|-----------|------|
196207
| `/feature` | Feature Agent → `start_dev` | real conductor |
208+
| `/bug` | Bug Agent → `start_dev` (health mode → vitals + Heart issues) | real conductor |
197209
| `/build` | Build Agent → vitals → Heart → PyAutoBuild | real conductor |
198210
| `/health` | Health Agent loop → vitals → Heart | real conductor |
199-
| `/bug` `/refactor` `/docs` `/research` | `start_dev` pre-tagged with the work-type | work-type entry* |
211+
| `/refactor` `/docs` `/research` | `start_dev` pre-tagged with the work-type | work-type entry* |
200212
| `/route <text>` | infers the work-type and dispatches to one of the above | NL router |
201213
| `/brain <agent>` | raw `bin/pyauto-brain` passthrough | debug door |
202214

203-
\* No dedicated Bug/Refactor/Docs/Research conductor exists yet — those verbs
204-
route through the Brain dev-flow with their PyAutoMind work-type fixed (still
205-
through the Brain, nothing bypassed), until each earns promotion to its own
206-
conductor. Every command routes **through** the Brain; none replaces it.
215+
\* No dedicated Refactor/Docs/Research conductor exists yet — those verbs route
216+
through the Brain dev-flow with their PyAutoMind work-type fixed (still through the
217+
Brain, nothing bypassed), until each earns promotion to its own conductor (as `/bug`
218+
now has). Every command routes **through** the Brain; none replaces it.
207219

208220
The command bodies live in `skills/<verb>/<verb>.md` (thin; installed as flat
209221
commands by `bin/install.sh`); the shared architecture prose is in

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ faculties multiply behind them.
5050

5151
- **`agents/conductors/feature/`** — the growth function: reasons over PyAutoMind
5252
`feature/*` intent and plans how the organism grows.
53+
- **`agents/conductors/bug/`** — the immune system: recognises a bug / regression /
54+
failing test / PyAutoHeart finding, classifies it, decides where the fix belongs
55+
(source-first, never degrading a user-facing script), and plans the repair.
5356
- **`agents/conductors/build/`** — the executive function for execution work.
5457
Consults the vitals faculty, reasons over the verdict, and on a healthy result
5558
delegates to PyAutoBuild. Has `build` / `deploy` / `release` modes.
@@ -108,11 +111,11 @@ natural language) and it routes to the right agent — normal usage never says
108111

109112
> **Users speak in short commands; PyAutoBrain performs the routing.**
110113
111-
- **Real conductors:** `/feature` → Feature Agent, `/build`Build Agent,
112-
`/health` → Health Agent (each → vitals/Heart/Build as needed).
113-
- **Work-type entries:** `/bug` `/refactor` `/docs` `/research` route through the
114-
Brain dev-flow (`start_dev`) with their PyAutoMind work-type fixed — honest
115-
interim doors until each earns its own conductor.
114+
- **Real conductors:** `/feature` → Feature Agent, `/bug`Bug Agent, `/build`
115+
Build Agent, `/health` → Health Agent (each → vitals/Heart/Build as needed).
116+
- **Work-type entries:** `/refactor` `/docs` `/research` route through the Brain
117+
dev-flow (`start_dev`) with their PyAutoMind work-type fixed — honest interim
118+
doors until each earns its own conductor.
116119
- **Router + debug:** `/route <text>` infers the work-type and dispatches;
117120
`/brain <agent>` is the raw passthrough. Every command routes **through** the
118121
Brain; none replaces it.

agents/conductors/bug/AGENTS.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Bug agent
2+
3+
> **Tier: conductor** — a front-door agent you *drive*. The organism's
4+
> **immune system**: it recognises a pathogen (a bug, regression, failing test or
5+
> PyAutoHeart finding), tells it from benign self, types the threat, recalls whether
6+
> it has met it before, and mounts a *targeted* response — neutralising the defect at
7+
> its source without harming healthy tissue. It *consults* the read-only vitals
8+
> faculty (`--check-health`), never queries Heart directly, and never wields the
9+
> scalpel itself. (Organism-facing name: *Immune Agent*.)
10+
11+
The **immune response** of PyAutoBrain. Where the Feature Agent grows the organism and
12+
the Health conductor keeps it in homeostasis, the Bug Agent answers a *specific threat*:
13+
it detects and classifies a defect, tells a real pathogen from benign self (an expected
14+
failure, a flaky test, a mis-filed feature), consults immune **memory** (PyAutoMemory)
15+
for prior/recurring/flaky cases, and produces a precise repair plan the `start_dev →
16+
ship_*` workflow executes. It reasons; it does not edit source.
17+
18+
```
19+
report / failing test / issue / PyAutoHeart finding
20+
→ Bug Agent → start_dev → start_library / ship_library
21+
→ start_workspace / ship_workspace
22+
consults ↘ ↙ consults
23+
vitals faculty PyAutoMemory (recurring failures, prior fixes, flaky tests)
24+
```
25+
26+
## Fundamental principle — a precise response, no autoimmunity
27+
28+
A healthy immune response neutralises the pathogen at its source and spares healthy
29+
tissue. The most delicate tissue here is the **user-facing workspace scripts — they are
30+
documentation.** A fix that injects test env-vars, hard-codes a path, mutates
31+
`os.environ`, or drops a silent guard into a tutorial script is an **autoimmune
32+
reaction** — it damages what it exists to protect. So before proposing any patch the Bug
33+
Agent asks *where the fix belongs*, and strongly prefers a **general fix in library
34+
source**. It edits a workspace script only when the defect truly lives there, never in a
35+
way that reduces clarity; sanctioned knobs go through `config/build/env_vars.yaml` /
36+
`no_run.yaml`, not inline edits. This surfaces as the `Fix locus:` field of every
37+
decision. See [`BUG_TAXONOMY.md`](./BUG_TAXONOMY.md) for the full fix-locus rules.
38+
39+
## It reasons; it does not build
40+
41+
The Bug Agent never edits source, opens PRs, or runs builds — that is the existing
42+
`start_dev` / `ship_*` workflow (and PyAutoBuild at release). It never *runs* tests or
43+
health checks either: reproduction means **identifying** the repro command or the Heart
44+
check, and validation is delegated to the vitals faculty. It emits a `BugDecision`; the
45+
workflow acts on it.
46+
47+
## Four modes
48+
49+
| Mode | Trigger | What it does |
50+
|------|---------|--------------|
51+
| **specific** | a `bug/…md` path (or a report) is given | Classify (severity/scope/type/confidence), locate the owner, decide the fix locus + strategy, and produce a `start_dev`-ready plan. |
52+
| **selection** | nothing given | Scan `bug/**`, rank **severity-first** (a bug list is a triage queue), down-rank in-flight work (`active.md`/`planned.md`), and recommend the next bug — with the reason. |
53+
| **difficulty-constrained** | `--difficulty` / `--model` / `--budget` / `--ambitious` / `--impact` | Estimate difficulty per bug and select to match (easy/weak/limited-token → small; ambitious → large; impact → highest severity). |
54+
| **health** | `health` subcommand | Read **two** health inputs — the live **vitals verdict** and the **filed PyAutoHeart GitHub issues** — and route real defects to `bug/health_fixes/`. |
55+
56+
## Classification
57+
58+
Every decision types the threat (heuristic first pass — the reasoning layer refines it):
59+
60+
- **severity:** `critical | high | medium | low`
61+
- **scope:** `single-file | single-repo | multi-repo | ecosystem`
62+
- **type:** `test-failure | runtime-error | wrong-result | docs-error | workflow-error | config-error | release-error | flaky | unknown`
63+
- **confidence:** `high | medium | low`
64+
65+
If a `bug/` prompt is really a feature, refactor, docs or research task, the agent says
66+
so (`rehome_suggestion`) instead of planning a fix.
67+
68+
## Health mode — two inputs, one router
69+
70+
The bug can come from PyAutoHeart. `bug.sh health` gathers both signals and hands them
71+
to `_bug.py`, which classifies each finding **real-bug / flaky / config / expected** and
72+
decides whether the fix belongs in the affected repo, PyAutoHeart, PyAutoBuild or
73+
PyAutoBrain:
74+
75+
1. the **live vitals verdict** — via the vitals faculty (never Heart directly);
76+
2. the **filed PyAutoHeart issues**`gh issue list --repo PyAutoLabs/PyAutoHeart`
77+
(`$PYAUTO_HEART_REPO` overridable), the durable findings Heart authored.
78+
79+
Real defects become `PyAutoMind/bug/health_fixes/<name>.md` prompts (its README already
80+
cites Heart issue #27); flaky/expected findings are left to the Health conductor.
81+
82+
> **Boundary with the Health conductor.** The Health conductor drives the assess →
83+
> triage → dispatch loop toward GREEN — its cut is *validation + recommend, no edit-in
84+
> fixes*. The Bug Agent is that deferred edit-in-fix arm: Health hands it a red that is a
85+
> genuine *code* failure, and the Bug Agent turns it into a repair plan. No duplicated
86+
> triage, no re-implemented Heart checks.
87+
88+
## BugDecision (the structured return)
89+
90+
```
91+
Bug · Mode · Classification (severity / scope / type / confidence) · Likely owner
92+
Reproduction (known / unknown / PyAutoHeart check) · Relevant context (PyAutoMemory)
93+
Fix locus (library-source-first · workspace-config · workspace-script[justified] · infra)
94+
Fix strategy (direct · investigate-first · split-into-phases · defer/re-home)
95+
Recommended workflow (library | workspace | combined | infrastructure)
96+
Health validation (vitals checks required before shipping) · Risks · Next action
97+
```
98+
99+
`--json` returns the same shape (JSON-consistent with the Feature Agent's
100+
`FeatureDecision`, plus `classification` and `fix_locus`), so a future Python
101+
`BugAgent().decide(...)` can return it verbatim.
102+
103+
## Run
104+
105+
```bash
106+
bin/pyauto-brain bug # selection mode (severity-first)
107+
bin/pyauto-brain bug bug/autoarray/rect_adapt.md # specific mode
108+
bin/pyauto-brain bug select --difficulty easy # easy bug for limited tokens
109+
bin/pyauto-brain bug select --impact # highest-severity bug
110+
bin/pyauto-brain bug health # vitals verdict + Heart issue scan
111+
bin/pyauto-brain bug --json bug/autofit/x.md # machine-readable BugDecision
112+
bin/pyauto-brain bug --check-health bug/autolens/x.md # also annotate with the vitals verdict
113+
```
114+
115+
Exit codes mirror the Feature Agent: `0` produced a decision · `4` no prompts /
116+
could-not-resolve mind · `5` bad usage. The analysis core (`_bug.py`) is stdlib-only,
117+
does no network/Git, and never writes — `bug.sh` feeds it the verdict + Heart issues.
118+
119+
## Faculties (a seam, not yet built)
120+
121+
The Bug Agent ships as a **conductor only**, consulting the existing `vitals` faculty.
122+
Its pure, side-effect-free reasoning — classify + locate + fix-locus — is the shape of a
123+
future read-only **`diagnosis` faculty** (reusable by the Feature Agent's re-homing and
124+
the Health conductor). Keeping the conductor set small, that split is deferred with a
125+
clean seam, exactly as Release stayed a mode of Build. See
126+
[`BUG_TAXONOMY.md`](./BUG_TAXONOMY.md).
127+
128+
## What this agent must never do
129+
130+
- Edit source, open PRs, or run builds — that is `start_dev` / `ship_*` / PyAutoBuild.
131+
- Run tests or health checks, or re-implement a PyAutoHeart check — consult the vitals
132+
faculty (`--check-health`) and let Heart measure.
133+
- Query PyAutoHeart directly — only the vitals faculty talks to the Heart organ.
134+
- **Degrade a user-facing workspace script** to mask a symptom (the autoimmune failure
135+
mode) — prefer a general library-source fix.
136+
- Just pick the first bug in selection mode — rank severity-first and explain the choice.
137+
138+
See [`BUG_TAXONOMY.md`](./BUG_TAXONOMY.md) for the classification taxonomy, the fix-locus
139+
rules, the two health inputs, and the reuse of the Feature difficulty heuristic.

0 commit comments

Comments
 (0)