claude-dev-env 1.25.2 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +6 -0
- package/agents/clean-coder.md +1 -1
- package/docs/CODE_RULES.md +3 -1
- package/hooks/HOOK_SPECS_PROMPT_WORKFLOW.md +54 -0
- package/hooks/blocking/{code-rules-enforcer.py → code_rules_enforcer.py} +150 -5
- package/hooks/blocking/test_code_rules_enforcer_any_type_ignore.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_banned_identifier.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_conftest_anchor.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_dot_test_pattern.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_file_global_constants.py +181 -0
- package/hooks/blocking/test_code_rules_enforcer_fstring_scan.py +4 -4
- package/hooks/blocking/test_code_rules_enforcer_logger_fstring.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
- package/hooks/blocking/test_code_rules_enforcer_magic_string_masking.py +104 -0
- package/hooks/blocking/test_code_rules_enforcer_naming_pattern.py +2 -2
- package/hooks/blocking/test_code_rules_enforcer_type_checking_scope.py +2 -2
- package/hooks/blocking/test_content_search_to_zoekt_redirector_integration.py +1 -1
- package/hooks/blocking/test_destructive_command_blocker.py +1 -1
- package/hooks/blocking/test_gh_body_arg_blocker.py +1 -1
- package/hooks/blocking/test_pr_description_enforcer.py +8 -8
- package/hooks/blocking/test_tdd_enforcer.py +1 -1
- package/hooks/github-action/pre-push-review.yml +27 -0
- package/hooks/hooks.json +28 -28
- package/hooks/lifecycle/{config-change-guard.py → config_change_guard.py} +27 -12
- package/hooks/lifecycle/test_config_change_guard.py +3 -3
- package/hooks/notification/{attention-needed-notify.py → attention_needed_notify.py} +7 -0
- package/hooks/notification/{claude-notification-handler.py → claude_notification_handler.py} +8 -0
- package/hooks/notification/notification_utils.py +56 -0
- package/hooks/notification/subagent_complete_notify.py +381 -0
- package/hooks/notification/test_attention_needed_notify.py +47 -0
- package/hooks/notification/test_claude_notification_handler.py +54 -0
- package/hooks/notification/test_notification_utils.py +45 -0
- package/hooks/notification/test_subagent_complete_notify.py +72 -0
- package/hooks/validators/README.md +5 -1
- package/hooks/validators/abbreviation_checks.py +1 -1
- package/hooks/validators/code_quality_checks.py +1 -1
- package/hooks/validators/config.py +5 -0
- package/hooks/validators/conftest.py +10 -0
- package/hooks/validators/exempt_paths.py +1 -1
- package/hooks/validators/git_checks.py +80 -0
- package/hooks/validators/magic_value_checks.py +2 -2
- package/hooks/validators/pr_reference_checks.py +1 -1
- package/hooks/validators/python_antipattern_checks.py +1 -1
- package/hooks/validators/run_all_validators.py +53 -105
- package/hooks/validators/security_checks.py +1 -1
- package/hooks/validators/test_abbreviation_checks.py +2 -2
- package/hooks/validators/test_code_quality_checks.py +2 -2
- package/hooks/validators/test_file_structure_checks.py +1 -1
- package/hooks/validators/test_git_checks.py +79 -13
- package/hooks/validators/test_health_check.py +1 -1
- package/hooks/validators/test_magic_value_checks.py +2 -2
- package/hooks/validators/test_mypy_integration.py +1 -1
- package/hooks/validators/test_output_formatter.py +3 -1
- package/hooks/validators/test_pr_reference_checks.py +2 -2
- package/hooks/validators/test_python_antipattern_checks.py +2 -2
- package/hooks/validators/test_python_style_checks.py +2 -4
- package/hooks/validators/test_react_checks.py +1 -1
- package/hooks/validators/test_ruff_integration.py +1 -1
- package/hooks/validators/test_run_all_validators.py +75 -43
- package/hooks/validators/test_run_all_validators_integration.py +14 -37
- package/hooks/validators/test_security_checks.py +2 -2
- package/hooks/validators/test_test_safety_checks.py +1 -1
- package/hooks/validators/test_todo_checks.py +2 -2
- package/hooks/validators/test_type_safety_checks.py +2 -2
- package/hooks/validators/test_useless_test_checks.py +2 -2
- package/hooks/validators/test_validator_base.py +1 -1
- package/hooks/validators/test_verify_paths.py +2 -4
- package/hooks/validators/todo_checks.py +1 -1
- package/hooks/validators/type_safety_checks.py +1 -1
- package/hooks/validators/useless_test_checks.py +1 -1
- package/package.json +1 -1
- package/rules/file-global-constants.md +71 -0
- package/rules/gh-body-file.md +1 -1
- package/rules/prompt-workflow-context-controls.md +48 -0
- package/scripts/sync_to_cursor/rules.py +2 -2
- package/scripts/tests/test_sync_to_cursor.py +2 -2
- package/skills/bugteam/CONSTRAINTS.md +37 -0
- package/skills/bugteam/EXAMPLES.md +64 -0
- package/skills/bugteam/PROMPTS.md +175 -0
- package/skills/bugteam/SKILL.md +204 -295
- package/skills/bugteam/SKILL_EVALS.md +346 -0
- package/skills/bugteam/scripts/README.md +37 -0
- package/skills/bugteam/scripts/bugteam_code_rules_gate.py +334 -0
- package/skills/bugteam/scripts/bugteam_preflight.py +135 -0
- package/skills/rule-audit/SKILL.md +4 -4
- /package/hooks/advisory/{migration-safety-advisor.py → migration_safety_advisor.py} +0 -0
- /package/hooks/advisory/{refactor-guard.py → refactor_guard.py} +0 -0
- /package/hooks/blocking/{block-main-commit.py → block_main_commit.py} +0 -0
- /package/hooks/blocking/{content-search-to-zoekt-redirector.py → content_search_to_zoekt_redirector.py} +0 -0
- /package/hooks/blocking/{destructive-command-blocker.py → destructive_command_blocker.py} +0 -0
- /package/hooks/blocking/{gh-body-arg-blocker.py → gh_body_arg_blocker.py} +0 -0
- /package/hooks/blocking/{hedging-language-blocker.py → hedging_language_blocker.py} +0 -0
- /package/hooks/blocking/{pr-description-enforcer.py → pr_description_enforcer.py} +0 -0
- /package/hooks/blocking/{sensitive-file-protector.py → sensitive_file_protector.py} +0 -0
- /package/hooks/blocking/{tdd-enforcer.py → tdd_enforcer.py} +0 -0
- /package/hooks/blocking/{test-preflight-check.py → test_preflight_check.py} +0 -0
- /package/hooks/blocking/{write-existing-file-blocker.py → write_existing_file_blocker.py} +0 -0
- /package/hooks/git-hooks/{post-commit.py → post_commit.py} +0 -0
- /package/hooks/lifecycle/{session-end-cleanup.py → session_end_cleanup.py} +0 -0
- /package/hooks/{rewrite-plugin-paths.py → rewrite_plugin_paths.py} +0 -0
- /package/hooks/session/{plugin-data-dir-cleanup.py → plugin_data_dir_cleanup.py} +0 -0
- /package/hooks/validation/{hook-format-validator.py → hook_format_validator.py} +0 -0
- /package/hooks/workflow/{auto-formatter.py → auto_formatter.py} +0 -0
- /package/hooks/workflow/{investigation-tracker-reset.py → investigation_tracker_reset.py} +0 -0
- /package/scripts/{sync-to-cursor.py → sync_to_cursor.py} +0 -0
package/skills/bugteam/SKILL.md
CHANGED
|
@@ -7,8 +7,8 @@ description: >-
|
|
|
7
7
|
returns zero bugs or a 10-loop safety cap is reached. One up-front
|
|
8
8
|
confirmation authorizes the entire cycle. Each audit teammate is spawned
|
|
9
9
|
fresh per loop to prevent anchoring bias. Wraps the cycle with project
|
|
10
|
-
permission grant/revoke. Requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
|
|
11
|
-
|
|
10
|
+
permission grant/revoke. Requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1.
|
|
11
|
+
Triggers: '/bugteam', 'run the bug team',
|
|
12
12
|
'auto-fix the PR until clean', 'loop audit and fix'.
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -22,9 +22,11 @@ description: >-
|
|
|
22
22
|
|
|
23
23
|
## Contents
|
|
24
24
|
|
|
25
|
-
This file is
|
|
25
|
+
This file is the orchestration core. The list below is for the LLM reading this skill — partial reads (e.g., `head -100`) miss what comes later, so this section ensures the full scope is visible from the top. (Per Anthropic's [Skill authoring best practices — Structure longer reference files with table of contents](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#structure-longer-reference-files-with-table-of-contents).)
|
|
26
26
|
|
|
27
27
|
- When this skill applies — refusal cases (4) and trigger conditions
|
|
28
|
+
- Utility scripts — pre-flight checks (`scripts/`, executed not loaded as context)
|
|
29
|
+
- Pre-audit code rules gate — `validate_content` / hook parity before each AUDIT
|
|
28
30
|
- The Process — Progress checklist + Steps 0–6
|
|
29
31
|
- Step 0 — Grant project permissions
|
|
30
32
|
- Step 1 — Resolve PR scope
|
|
@@ -35,9 +37,9 @@ This file is 400+ lines. The list below is for the LLM reading this skill — pa
|
|
|
35
37
|
- Step 4.5 — Finalize the PR description (via pr-description-writer)
|
|
36
38
|
- Step 5 — Revoke project permissions
|
|
37
39
|
- Step 6 — Print the final report
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
- Why this design
|
|
40
|
+
- [`PROMPTS.md`](PROMPTS.md) — AUDIT spawn-prompt XML, FIX spawn-prompt XML, the 10 audit categories (A–J), and both outcome XML schemas. Load before spawning bugfind or bugfix, or when parsing teammate outcome XML.
|
|
41
|
+
- [`EXAMPLES.md`](EXAMPLES.md) — six end-to-end scenarios (converged, cap reached, stuck, partial-fix, no-PR, dirty-tree). Load when an unfamiliar exit condition appears.
|
|
42
|
+
- [`CONSTRAINTS.md`](CONSTRAINTS.md) — invariants plus "Why this design" rationale. Load when a constraint question arises.
|
|
41
43
|
|
|
42
44
|
## When this skill applies
|
|
43
45
|
|
|
@@ -46,11 +48,24 @@ User wants automated convergence on a clean PR without babysitting each step. Ty
|
|
|
46
48
|
Refusal cases — check in order; first match short-circuits and stops:
|
|
47
49
|
|
|
48
50
|
- **Agent teams not enabled.** Check `claude config get env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` and `~/.claude/settings.json`. If neither sets it to `"1"`, respond: `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 not set. /bugteam requires the agent teams feature. See https://code.claude.com/docs/en/agent-teams#enable-agent-teams.` and stop.
|
|
49
|
-
- **Claude Code version too old.** Run `claude --version`. If older than v2.1.32, respond: `Claude Code v<version> is older than the v2.1.32 minimum for agent teams. Upgrade first.` and stop.
|
|
50
51
|
- **Missing PR or upstream diff.** Respond exactly: `No PR or upstream diff. /bugteam needs a target.` and stop.
|
|
51
52
|
- **Working tree dirty with uncommitted changes the user did not stage.** Respond: `Uncommitted changes detected. Stash, commit, or revert before /bugteam.` and stop. Reason: the fix teammate will commit the working tree, mixing user-uncommitted work into automated fixes.
|
|
52
53
|
- **Required subagents not installed.** Before Step 0, verify `code-quality-agent` and `clean-coder` subagent types exist in the available agents list. If either is missing, respond: `Required subagent type <name> not installed. /bugteam needs both code-quality-agent and clean-coder available.` and stop.
|
|
53
54
|
|
|
55
|
+
## Utility scripts
|
|
56
|
+
|
|
57
|
+
Fragile or repeatable shell sequences belong in `scripts/` (see Anthropic [Skill authoring best practices — Progressive disclosure](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#progressive-disclosure-patterns): utility scripts are **executed**, not loaded into context). Details: [`scripts/README.md`](scripts/README.md).
|
|
58
|
+
|
|
59
|
+
### Pre-flight (recommended before Step 0)
|
|
60
|
+
|
|
61
|
+
From the repository root, run:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python "${CLAUDE_SKILL_DIR}/scripts/bugteam_preflight.py"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
If the exit code is non-zero, stop and fix failing checks before granting permissions. Optional: `BUGTEAM_PREFLIGHT_SKIP=1` skips pre-flight (emergency only). Optional: `--pre-commit` when `.pre-commit-config.yaml` exists.
|
|
68
|
+
|
|
54
69
|
## The Process
|
|
55
70
|
|
|
56
71
|
### Progress checklist (copy at start, tick as you go)
|
|
@@ -92,7 +107,17 @@ Capture: `<owner>/<repo>`, head branch, base branch, PR number, PR URL. This sco
|
|
|
92
107
|
|
|
93
108
|
### Step 2: Create the agent team
|
|
94
109
|
|
|
95
|
-
This session is the **team lead**. Create
|
|
110
|
+
This session is the **team lead**. Create the team by calling the `TeamCreate` tool with these exact arguments:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
TeamCreate(
|
|
114
|
+
team_name="<team_name>",
|
|
115
|
+
description="Bugteam audit/fix loop for PR <number> (<owner>/<repo>)",
|
|
116
|
+
agent_type="team-lead"
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`<team_name>` is the value built below under **Team name** (sanitization + timestamp already applied). `TeamCreate` is the tool that resolves the docs' phrasing: *"tell Claude to create an agent team and describe the task and the team structure you want in natural language. Claude creates the team, spawns teammates, and coordinates work based on your prompt."*
|
|
96
121
|
|
|
97
122
|
Team specification:
|
|
98
123
|
|
|
@@ -202,20 +227,39 @@ If the audit returns zero findings, the teammate still posts ONE review with `ev
|
|
|
202
227
|
|
|
203
228
|
### Step 3: The cycle
|
|
204
229
|
|
|
205
|
-
Repeat until an exit condition fires
|
|
230
|
+
Repeat until an exit condition fires.
|
|
206
231
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
- `last_action == "audited"` and `last_findings.total > 0` → run **FIX**
|
|
232
|
+
**Ordering principle:** Mandatory **CODE_RULES** checks (`validate_content` from `hooks/blocking/code_rules_enforcer.py`) must pass on the PR-scoped file set **before** any **AUDIT** (bugfind) teammate runs. The **clean-coder** teammate clears gate failures; then the **code-quality-agent** teammate audits. This mirrors “CI green, then review,” without relying on GitHub Actions — the script is the gate.
|
|
233
|
+
|
|
234
|
+
1. Decide the next action from `last_action` and `last_findings`:
|
|
211
235
|
- `last_action == "audited"` and `last_findings.total == 0` → exit reason = `converged`
|
|
212
|
-
- `last_action == "fixed"` and `git rev-parse HEAD` did not change since pre-FIX → exit reason = `stuck` (see FIX action
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
236
|
+
- `last_action == "fixed"` and `git rev-parse HEAD` did not change since pre-FIX → exit reason = `stuck` (see FIX action)
|
|
237
|
+
- `last_action in {"fresh", "fixed"}` → go to **pre-audit path** (below), then **AUDIT**
|
|
238
|
+
- `last_action == "audited"` and `last_findings.total > 0` → go to **FIX** (below)
|
|
239
|
+
|
|
240
|
+
2. **Pre-audit path** (only when the next step is **AUDIT**):
|
|
241
|
+
1. From the repository root, run the gate script (align `--base` with the PR base branch from Step 1, e.g. `origin/main` or `origin/develop`):
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
python "${CLAUDE_SKILL_DIR}/scripts/bugteam_code_rules_gate.py" --base origin/<baseRefName>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Use `git merge-base` + `git diff --name-only` inside the script; see [`scripts/README.md`](scripts/README.md). The lead runs this (not a teammate).
|
|
248
|
+
2. If exit code **0** → continue to step 3 (AUDIT spawn) below.
|
|
249
|
+
3. If exit code **non-zero** → spawn a NEW **clean-coder** teammate — **standards-fix pass** — with instructions: read the script’s stderr, edit the repo until a **re-run** of the **same** gate command exits **0**, then one commit, `git push`, shutdown. Repeat standards-fix spawns until the gate exits **0** or **5** failed gate rounds (each round = one teammate session after a non-zero gate). If still non-zero after 5 rounds → exit reason = `error: code rules gate failed pre-audit`.
|
|
250
|
+
4. After gate exit **0**, increment `loop_count`. If `loop_count > 10`, exit reason = `cap reached` (counts **audits**, not standards-only rounds).
|
|
251
|
+
5. Execute **AUDIT action** (spawn bugfind). Print progress: `Loop <N> audit: ...`
|
|
252
|
+
|
|
253
|
+
3. **FIX path** (when `last_action == "audited"` and `last_findings.total > 0`):
|
|
254
|
+
1. Increment `loop_count`. If `loop_count > 10`, exit reason = `cap reached`.
|
|
255
|
+
2. Execute **FIX action** (spawn bugfix clean-coder for audit findings). Print: `Loop <N> fix: commit ...`
|
|
256
|
+
3. Set `last_action = "fixed"`, update `audit_log`, loop to step 1 (next iteration will hit **pre-audit path** before the next AUDIT).
|
|
257
|
+
|
|
258
|
+
4. After **AUDIT**, update `last_action`, `last_findings`, `audit_log`; print the audit progress line if not already printed.
|
|
259
|
+
|
|
260
|
+
5. Loop.
|
|
261
|
+
|
|
262
|
+
**Note:** The first iteration uses **pre-audit path** then **AUDIT**. After a **FIX** for audit findings, the next iteration runs **pre-audit path** again (gate → then AUDIT), so `validate_content` stays green before semantic audit.
|
|
219
263
|
|
|
220
264
|
### AUDIT action (clean-room teammate, fresh per loop)
|
|
221
265
|
|
|
@@ -228,192 +272,105 @@ gh pr diff <number> -R <owner>/<repo> > "<team_temp_dir>/loop-<N>.patch"
|
|
|
228
272
|
|
|
229
273
|
`<team_temp_dir>` is the absolute path captured in Step 2 (already includes the sanitized team_name and timestamp suffix, and `team_name` itself is already prefixed with `bugteam-`). Claude resolves the portable temp root once via `Path(tempfile.gettempdir()) / team_name` (requires `import tempfile`) and passes the literal absolute path to every shell command. `tempfile.gettempdir()` honors `TMPDIR`, `TEMP`, and `TMP` in the platform-correct order and falls back to `C:\Users\<user>\AppData\Local\Temp` on Windows or `/tmp` on Unix, so this works identically on macOS, Linux, Windows cmd.exe, and PowerShell: Claude resolves the literal path once and every shell receives the same absolute value.
|
|
230
274
|
|
|
231
|
-
Spawn a
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
<
|
|
238
|
-
|
|
239
|
-
<
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
- Read-only on source code: the audit does not modify any source file.
|
|
266
|
-
- Cite file:line for every finding.
|
|
267
|
-
- When the diff alone does not provide enough context to confirm a bug,
|
|
268
|
-
list it under "Open questions" rather than assert it.
|
|
269
|
-
</constraints>
|
|
270
|
-
|
|
271
|
-
<comment_posting>
|
|
272
|
-
1. Audit the diff against the 10 categories above. Buffer the findings
|
|
273
|
-
in memory; all posting happens at step 6 once anchors are validated.
|
|
274
|
-
2. Assign each finding a stable finding_id of exactly the form `loopN-K`
|
|
275
|
-
where K is 1-based within this loop.
|
|
276
|
-
3. Validate every finding's (file, line) against the captured diff. Split
|
|
277
|
-
findings into two buckets: anchored (line is in the diff) and
|
|
278
|
-
unanchored (line is not in the diff — goes into the review body's
|
|
279
|
-
"Findings without a diff anchor" section per Step 2.5).
|
|
280
|
-
4. Build the review body per Step 2.5's review-body shape, filling in the
|
|
281
|
-
P0/P1/P2 counts and the unanchored-findings list (if any).
|
|
282
|
-
5. For each anchored finding, write its body to its own temp file:
|
|
283
|
-
|
|
284
|
-
**[severity] one-line title**
|
|
285
|
-
Category: <letter> (<category name>)
|
|
286
|
-
<2-3 sentence description with concrete trace>
|
|
287
|
-
|
|
288
|
-
_From /bugteam audit loop N._
|
|
289
|
-
|
|
290
|
-
6. Post ONE review via Step 2.5's per-loop review CLI shape. Harvest the
|
|
291
|
-
parent review `html_url` from the response JSON and the `comments[]`
|
|
292
|
-
child entries (each with its own `id` and `html_url`). Match child
|
|
293
|
-
entries to anchored findings in index order.
|
|
294
|
-
7. If the review POST itself fails, use Step 2.5's Review POST failure
|
|
295
|
-
fallback (single issue comment with full body and all findings inline).
|
|
296
|
-
8. Write every body (review body, each finding body, any fallback body)
|
|
297
|
-
to its own temp file. Load each file into the JSON payload via jq's
|
|
298
|
-
`--rawfile` or `-Rs`, then pipe the jq output to `gh api ... --input -`
|
|
299
|
-
so every body reaches GitHub as file contents inside the JSON payload.
|
|
300
|
-
</comment_posting>
|
|
301
|
-
|
|
302
|
-
<output_format>
|
|
303
|
-
Write the outcome XML below to .bugteam-loop-N.outcomes.xml in the
|
|
304
|
-
working directory. Return only that path on stdout. The schema:
|
|
305
|
-
</output_format>
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
Outcome XML schema (bugfind writes this):
|
|
309
|
-
|
|
310
|
-
```xml
|
|
311
|
-
<bugteam_audit loop="<N>" review_url="<url>">
|
|
312
|
-
<finding
|
|
313
|
-
finding_id="loop<N>-<index>"
|
|
314
|
-
severity="P0|P1|P2"
|
|
315
|
-
category="<letter>"
|
|
316
|
-
file="<path>"
|
|
317
|
-
line="<int>"
|
|
318
|
-
finding_comment_id="<gh child comment id, or empty if unanchored/review-fallback>"
|
|
319
|
-
finding_comment_url="<url of child comment, OR review_url if unanchored, OR fallback issue comment URL>"
|
|
320
|
-
used_fallback="true|false"
|
|
321
|
-
>
|
|
322
|
-
<title>one-line title</title>
|
|
323
|
-
<description>2-3 sentence description with concrete trace</description>
|
|
324
|
-
</finding>
|
|
325
|
-
<verified_clean>
|
|
326
|
-
<category letter="<letter>" name="<name>" evidence="brief evidence + cleared conclusion"/>
|
|
327
|
-
</verified_clean>
|
|
328
|
-
</bugteam_audit>
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
After the teammate writes the XML and returns, the lead reads `.bugteam-loop-<N>.outcomes.xml`, parses it, and populates `loop_comment_index` from `<finding>` elements. Then **shut down the bugfind teammate**: `Ask the bugfind teammate to shut down`. Per the docs: *"The lead sends a shutdown request. The teammate can approve, exiting gracefully, or reject with an explanation."* If the teammate rejects shutdown, force-shut by failing the team and starting Step 5 cleanup with exit reason = `error: bugfind teammate refused shutdown`.
|
|
275
|
+
Spawn a fresh `bugfind` teammate for this loop by calling the `Agent` tool with these exact arguments:
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
Agent(
|
|
279
|
+
subagent_type="code-quality-agent",
|
|
280
|
+
name="bugfind",
|
|
281
|
+
team_name="<team_name>",
|
|
282
|
+
model="sonnet",
|
|
283
|
+
description="Bugfind audit loop <N>",
|
|
284
|
+
prompt="<audit XML from the block below, with placeholders substituted>"
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Each loop calls `Agent` again with a fresh `Agent` invocation so the teammate starts with its own context window. The docs guarantee this: *"The lead's conversation history does not carry over."* Spawning per loop keeps every audit independent.
|
|
289
|
+
|
|
290
|
+
See [`PROMPTS.md`](PROMPTS.md) for the AUDIT spawn-prompt XML and bugfind outcome schema. Substitute placeholders (repo, branch, base_branch, pr_url, loop, diff_path) and pass the result as the `prompt` argument.
|
|
291
|
+
|
|
292
|
+
After the teammate writes the XML and returns, the lead reads `.bugteam-loop-<N>.outcomes.xml` with the `Read` tool, parses it, and populates `loop_comment_index` from `<finding>` elements.
|
|
293
|
+
|
|
294
|
+
**Expected path: self-termination.** In practice, teammates self-terminate when their task is complete — the `Agent` call returns and the teammate's session ends automatically. When that happens, no `SendMessage` shutdown is needed and the cycle proceeds directly to the next action.
|
|
295
|
+
|
|
296
|
+
**Fallback path: lead-initiated shutdown.** If the teammate has not self-terminated after the `Agent` call returns (observable as the teammate still appearing in the active-teammates list), send a shutdown message:
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
SendMessage(
|
|
300
|
+
to="bugfind",
|
|
301
|
+
message={
|
|
302
|
+
"type": "shutdown_request",
|
|
303
|
+
"reason": "audit loop <N> complete; outcome XML captured"
|
|
304
|
+
}
|
|
305
|
+
)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The teammate replies with `{type: "shutdown_response", approve: true}` and exits. If `approve` comes back `false`, treat this as a fatal error: set exit reason = `error: bugfind teammate refused shutdown` and jump to Step 4 teardown followed by Step 5 revoke.
|
|
332
309
|
|
|
333
310
|
`last_action = "audited"`. `last_findings = parsed`. Append `(loop=N, action="audit", counts={P0,P1,P2}, sha=current_HEAD, review_url=<url>, finding_count=<n>, fallback_count=<n>)` to `audit_log`.
|
|
334
311
|
|
|
335
|
-
**Parallel auditors from loop 4 onward (`loop_count >= 4`).**
|
|
312
|
+
**Parallel auditors from loop 4 onward (`loop_count >= 4`).** The pre-audit code rules gate must still pass immediately before this step (Step 3). After three full audit/fix rounds without convergence, spawn three bugfind teammates concurrently by issuing three `Agent` calls in a single assistant message so they run in parallel:
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
Agent(subagent_type="code-quality-agent", name="bugfind-loop-<N>-a", team_name="<team_name>", model="sonnet", description="Bugfind audit loop <N> variant a", prompt="<audit XML; write outcome to .bugteam-loop-<N>.outcomes.xml; post the per-loop review; read and merge b/c outcomes from <team_temp_dir>/loop-<N>-b.outcomes.xml and <team_temp_dir>/loop-<N>-c.outcomes.xml>")
|
|
316
|
+
Agent(subagent_type="code-quality-agent", name="bugfind-loop-<N>-b", team_name="<team_name>", model="sonnet", description="Bugfind audit loop <N> variant b", prompt="<audit XML; write outcome to <team_temp_dir>/loop-<N>-b.outcomes.xml; skip PR posting>")
|
|
317
|
+
Agent(subagent_type="code-quality-agent", name="bugfind-loop-<N>-c", team_name="<team_name>", model="sonnet", description="Bugfind audit loop <N> variant c", prompt="<audit XML; write outcome to <team_temp_dir>/loop-<N>-c.outcomes.xml; skip PR posting>")
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Teammate `-a` is the post-owner: it reads all three outcome XML files using their explicit absolute paths — its own outcome at `.bugteam-loop-<N>.outcomes.xml` (working directory), and the sibling outcomes at `<team_temp_dir>/loop-<N>-b.outcomes.xml` and `<team_temp_dir>/loop-<N>-c.outcomes.xml` — then merges findings by `(file, line, category_letter)` (same tuple collapses to one finding, keeping the longest description and the highest severity of the group), re-assigns merged-finding IDs as `loopN-K`, and posts the single per-loop review per the standard posting protocol above. The `-a` spawn prompt must include both sibling paths as literal absolute values so `-a` can read them with the `Read` tool by path without any discovery step.
|
|
321
|
+
|
|
322
|
+
Shut down `-b` and `-c` first with two parallel `SendMessage` calls, then shut down `-a` after its post completes:
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
SendMessage(to="bugfind-loop-<N>-b", message={"type": "shutdown_request", "reason": "variant XML captured"})
|
|
326
|
+
SendMessage(to="bugfind-loop-<N>-c", message={"type": "shutdown_request", "reason": "variant XML captured"})
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
then
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
SendMessage(to="bugfind-loop-<N>-a", message={"type": "shutdown_request", "reason": "merged review posted"})
|
|
333
|
+
```
|
|
336
334
|
|
|
337
335
|
### FIX action (fresh teammate, only sees latest audit)
|
|
338
336
|
|
|
339
|
-
Spawn a
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
<
|
|
349
|
-
|
|
350
|
-
<branch>head</branch>
|
|
351
|
-
<base_branch>base</base_branch>
|
|
352
|
-
<pr_url>url</pr_url>
|
|
353
|
-
<loop>N</loop>
|
|
354
|
-
</context>
|
|
355
|
-
|
|
356
|
-
<bugs_to_fix>
|
|
357
|
-
[for each P0/P1/P2 finding from last_findings:]
|
|
358
|
-
<bug
|
|
359
|
-
finding_id="loop<N>-<index>"
|
|
360
|
-
severity="P0|P1|P2"
|
|
361
|
-
file="<path>"
|
|
362
|
-
line="<int>"
|
|
363
|
-
category="<letter>"
|
|
364
|
-
finding_comment_id="<id>"
|
|
365
|
-
finding_comment_url="<url>"
|
|
366
|
-
>
|
|
367
|
-
<description>...</description>
|
|
368
|
-
</bug>
|
|
369
|
-
</bugs_to_fix>
|
|
370
|
-
|
|
371
|
-
<execution>
|
|
372
|
-
1. Read each referenced file before editing.
|
|
373
|
-
2. Apply each fix you can address.
|
|
374
|
-
3. Run `python -m py_compile` (or language-equivalent) on every modified file.
|
|
375
|
-
4. git add by explicit path, then git commit with a message summarizing the bugs fixed.
|
|
376
|
-
- If the commit fails because a git hook (pre-commit, commit-msg, etc.) blocked it,
|
|
377
|
-
capture the hook's stderr, write status=hook_blocked for every finding in this loop
|
|
378
|
-
(the commit was atomic; if it failed, no finding was applied), populate hook_output
|
|
379
|
-
on each outcome, and return WITHOUT retrying. The lead will treat this loop as no-progress.
|
|
380
|
-
5. git push with a plain fast-forward push (the default, no flag overrides).
|
|
381
|
-
6. For each bug, post a fix reply to its finding_comment_id via the
|
|
382
|
-
Step 2.5 reply CLI shape:
|
|
383
|
-
- "Fixed in <commit_sha>" if the bug was addressed by your commit
|
|
384
|
-
- "Could not address this loop: <one-line reason>" if you skipped or failed it
|
|
385
|
-
- "Hook blocked the fix commit: <one-line summary>" if the commit was hook-blocked
|
|
386
|
-
Use the Fix reply CLI shape from Step 2.5 (`jq -Rs | gh api .../comments/<id>/replies --input -`). Write every reply body to a temp file first.
|
|
387
|
-
7. Write `.bugteam-loop-<N>.outcomes.xml` (schema below) and return its path.
|
|
388
|
-
</execution>
|
|
389
|
-
|
|
390
|
-
<outcome_xml_schema>
|
|
391
|
-
<bugteam_fix loop="<N>" commit_sha="<sha or empty if no commit>">
|
|
392
|
-
<outcome
|
|
393
|
-
finding_id="loop<N>-<index>"
|
|
394
|
-
status="fixed|could_not_address|hook_blocked"
|
|
395
|
-
commit_sha="<sha if fixed, empty otherwise>"
|
|
396
|
-
reply_comment_id="<id of the reply posted>"
|
|
397
|
-
reply_comment_url="<url of the reply posted>"
|
|
398
|
-
>
|
|
399
|
-
<reason>only present when status=could_not_address; one-line reason text</reason>
|
|
400
|
-
<hook_output>only present when status=hook_blocked; verbatim stderr from the blocked hook</hook_output>
|
|
401
|
-
</outcome>
|
|
402
|
-
</bugteam_fix>
|
|
403
|
-
</outcome_xml_schema>
|
|
404
|
-
|
|
405
|
-
<constraints>
|
|
406
|
-
- Modify only files referenced in bugs_to_fix.
|
|
407
|
-
- One commit on the existing branch, then push.
|
|
408
|
-
- Keep the branch linear and the PR base fixed; append one new commit per
|
|
409
|
-
loop and fast-forward push only.
|
|
410
|
-
- Let every git hook run on every commit.
|
|
411
|
-
- git add by explicit path — name each file being staged.
|
|
412
|
-
- Preserve existing comments on lines you do not modify.
|
|
413
|
-
- Type hints on every signature you touch.
|
|
414
|
-
</constraints>
|
|
337
|
+
Spawn a fresh `bugfix` teammate for this loop by calling the `Agent` tool with these exact arguments:
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
Agent(
|
|
341
|
+
subagent_type="clean-coder",
|
|
342
|
+
name="bugfix",
|
|
343
|
+
team_name="<team_name>",
|
|
344
|
+
model="sonnet",
|
|
345
|
+
description="Bugfix loop <N>",
|
|
346
|
+
prompt="<fix XML from the block below, with placeholders substituted>"
|
|
347
|
+
)
|
|
415
348
|
```
|
|
416
349
|
|
|
350
|
+
The teammate sees only the most recent audit's findings — each `Agent` call starts with a fresh context window, so prior-loop findings, prior-loop fix history, and prior chat history stay inside the lead.
|
|
351
|
+
|
|
352
|
+
Pass the **finding comment URL and id for each finding** (from `loop_comment_index`) inside the XML prompt so the teammate owns reply posting. After committing fixes, the teammate posts one reply per finding: `Fixed in <commit_sha>` for addressed findings, `Could not address this loop: <one-line reason>` for skipped or failed findings. Same one-identity model as bugfind: teammate posts, lead waits.
|
|
353
|
+
|
|
354
|
+
After all replies are posted, the teammate writes its own outcome XML (see schema below) and returns.
|
|
355
|
+
|
|
356
|
+
**Expected path: self-termination.** In practice, teammates self-terminate when their task is complete — the `Agent` call returns and the teammate's session ends automatically. When that happens, no `SendMessage` shutdown is needed and the cycle proceeds directly to the next action.
|
|
357
|
+
|
|
358
|
+
**Fallback path: lead-initiated shutdown.** If the teammate has not self-terminated after the `Agent` call returns, send a shutdown message:
|
|
359
|
+
|
|
360
|
+
```
|
|
361
|
+
SendMessage(
|
|
362
|
+
to="bugfix",
|
|
363
|
+
message={
|
|
364
|
+
"type": "shutdown_request",
|
|
365
|
+
"reason": "fix loop <N> complete; commit <sha7> pushed"
|
|
366
|
+
}
|
|
367
|
+
)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
If the shutdown response returns `approve: false`, treat it the same as the bugfind refusal case above: exit reason = `error: bugfix teammate refused shutdown`, jump to Step 4 teardown then Step 5 revoke.
|
|
371
|
+
|
|
372
|
+
See [`PROMPTS.md`](PROMPTS.md) for the FIX spawn-prompt XML and bugfix outcome schema. Substitute placeholders (repo, branch, base_branch, pr_url, loop, and the per-finding bug entries built from `last_findings`) and pass the result as the `prompt` argument.
|
|
373
|
+
|
|
417
374
|
Verify the fix actually committed and pushed:
|
|
418
375
|
|
|
419
376
|
- `git rev-parse HEAD` after fix should differ from before
|
|
@@ -425,10 +382,33 @@ If `git rev-parse HEAD` did not change, exit reason = `stuck — bugfix teammate
|
|
|
425
382
|
|
|
426
383
|
### Step 4: Tear down the team and clean working tree
|
|
427
384
|
|
|
428
|
-
When the cycle exits (any reason):
|
|
385
|
+
When the cycle exits (any reason), run these steps in order from THIS session (the lead):
|
|
386
|
+
|
|
387
|
+
1. **Confirm every teammate has shut down.** Any teammate still alive (for example, from an aborted shutdown mid-loop) must receive a shutdown message first. For each remaining teammate name:
|
|
388
|
+
|
|
389
|
+
```
|
|
390
|
+
SendMessage(to="<teammate_name>", message={"type": "shutdown_request", "reason": "bugteam cycle ending"})
|
|
391
|
+
```
|
|
429
392
|
|
|
430
|
-
|
|
431
|
-
|
|
393
|
+
The docs state: *"When the lead runs cleanup, it checks for active teammates and fails if any are still running, so shut them down first."*
|
|
394
|
+
|
|
395
|
+
If any teammate returns `approve: false` during this cleanup shutdown, log the refusing teammate name (e.g., `cleanup warning: <teammate_name> refused shutdown_request`) and force-proceed to step 2 (`TeamDelete`) anyway. `TeamDelete` may fail if active teammates remain; if it does, surface the error in the final report with the refusing teammate name so the user can manually clean up. Do not abort the cleanup sequence — continue through temp-dir deletion, Step 4.5, and Step 5 regardless.
|
|
396
|
+
|
|
397
|
+
2. **Clean up the team** by calling `TeamDelete` with no arguments — it reads `<team_name>` from the current session's team context:
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
TeamDelete()
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
The docs state: *"When you're done, ask the lead to clean up: 'Clean up the team'."* `TeamDelete` is the tool that resolves that sentence.
|
|
404
|
+
|
|
405
|
+
3. **Delete the per-team scoped temp directory** by running this Python one-liner through the `Bash` tool (same literal `<team_temp_dir>` path resolved at Step 2):
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
python -c "import shutil; shutil.rmtree(r'<team_temp_dir>', ignore_errors=True)"
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
`shutil.rmtree(..., ignore_errors=True)` works identically on Windows and Unix, so the lead uses one command regardless of platform.
|
|
432
412
|
|
|
433
413
|
### Step 4.5: Finalize the PR description (mandatory)
|
|
434
414
|
|
|
@@ -436,7 +416,27 @@ After teardown and before permission revoke, the lead rewrites the PR body to re
|
|
|
436
416
|
|
|
437
417
|
The lead delegates the body authoring to the `pr-description-writer` agent so the global mandatory-pr-description-writer hook accepts the subsequent `gh pr edit`. The lead does NOT compose the body inline.
|
|
438
418
|
|
|
439
|
-
`pr-description-writer` is provided by the global git-workflow rule in `claude-code-config
|
|
419
|
+
`pr-description-writer` is provided by the global git-workflow rule in `claude-code-config`. Invoke it with the `Agent` tool:
|
|
420
|
+
|
|
421
|
+
```
|
|
422
|
+
Agent(
|
|
423
|
+
subagent_type="pr-description-writer",
|
|
424
|
+
description="Rewrite PR <number> body from cumulative diff",
|
|
425
|
+
prompt="<brief from step 3 below>"
|
|
426
|
+
)
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
If `pr-description-writer` is not in the available agents list for the current environment, fall back to `general-purpose` with the same brief — the global hook treats agent-authored bodies the same regardless of the specific agent type:
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
Agent(
|
|
433
|
+
subagent_type="general-purpose",
|
|
434
|
+
description="Rewrite PR <number> body from cumulative diff",
|
|
435
|
+
prompt="<brief from step 3 below>"
|
|
436
|
+
)
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
When neither agent is available, log a warning in the final report and skip Step 4.5 so the original PR body stays in place.
|
|
440
440
|
|
|
441
441
|
Steps:
|
|
442
442
|
|
|
@@ -484,99 +484,8 @@ If exit = `cap reached`, name the remaining bug count and recommend `/findbugs`
|
|
|
484
484
|
|
|
485
485
|
## Constraints
|
|
486
486
|
|
|
487
|
-
|
|
488
|
-
- **Grant before any spawn, revoke before any return.** Step 0 grants project `.claude/**` permissions; Step 5 revokes. Both are mandatory. Revoke runs on every exit path including error, cap-reached, and stuck.
|
|
489
|
-
- **Fresh teammate per loop.** Both bugfind and bugfix are spawned new each loop and shut down after their action. Reusing a teammate across loops accumulates context inside that teammate's window — defeats clean-room.
|
|
490
|
-
- **One up-front confirmation = whole cycle.** The `/bugteam` invocation authorizes the entire cycle; every subsequent decision runs on that single authorization.
|
|
491
|
-
- **10-loop hard cap.** Counted as audits performed. Worst case = 10 audits + 10 fixes = 20 teammate spawns + 20 shutdowns.
|
|
492
|
-
- **Clean-room audits, every loop.** Each bugfind teammate's spawn prompt contains only the PR scope, audit rubric, and the current loop number. Prior loop history stays in the lead.
|
|
493
|
-
- **Targeted fixes.** Each fix teammate sees ONLY the most recent audit's findings. Prior loops are invisible to the fix teammate.
|
|
494
|
-
- **Sonnet for both teammates.** Predictable cost, fits-purpose for code work.
|
|
495
|
-
- **Fix teammate receives the latest audit as its input contract.** Passing the audit's findings to the fix teammate is the input contract — each loop's fix run operates on the current audit's output and only that.
|
|
496
|
-
- **One commit per fix action.** Loops produce one commit per loop, not one per bug.
|
|
497
|
-
- **Linear branch, fixed PR base.** Every loop appends one forward-only commit; existing commits and the PR base stay intact throughout the cycle.
|
|
498
|
-
- **Lead-only cleanup.** Per the docs: *"Always use the lead to clean up. Teammates should not run cleanup because their team context may not resolve correctly, potentially leaving resources in an inconsistent state."* This session is the lead, and cleanup runs here only.
|
|
499
|
-
- **Cleanup the per-team scoped temp directory on exit.** The resolved `<team_temp_dir>` (absolute literal captured in Step 2) is deleted entirely so no loop patches leak between runs.
|
|
500
|
-
- **Cleanup all `.bugteam-*` files on exit.** `.bugteam-loop-*.patch`, `.bugteam-loop-*.outcomes.xml`, `.bugteam-final.diff`, `.bugteam-original-body.md`, `.bugteam-final-body.md`. Working directory ends clean.
|
|
501
|
-
- **Teammates own audit/fix comment posting.** Bugfind posts ONE per-loop review (parent body + child finding comments in a single batched POST, with review-fallback to a top-level issue comment). Bugfix posts the fix replies after committing. All comment, review, and reply POSTs belong to the teammates; the lead's single PR-write action is the final description rewrite at Step 4.5.
|
|
502
|
-
- **Lead owns the final PR description rewrite only** (Step 4.5), and only via the `pr-description-writer` agent. The lead does not compose the description inline.
|
|
503
|
-
- **One review per loop, findings as child comments of that review.** Each loop posts a single pull-request review whose body is the loop header and whose `comments[]` are the anchored findings. Each loop's review stands alone — one review created per loop, fully self-contained on the PR conversation.
|
|
504
|
-
- **PR description rewrite on every exit.** Step 4.5 runs on `converged`, `cap reached`, and `stuck`. On `error`, the rewrite is best-effort; if it fails, surface the error in the final report and continue to revoke.
|
|
505
|
-
- **Outcome XML, not JSON.** Both teammates write structured outcome data (findings or fix outcomes) to `.bugteam-loop-<N>.outcomes.xml`. The lead reads these files between actions. XML chosen for parser robustness against multi-line, special-character, and quoted reason fields.
|
|
487
|
+
See [`CONSTRAINTS.md`](CONSTRAINTS.md).
|
|
506
488
|
|
|
507
489
|
## Examples
|
|
508
490
|
|
|
509
|
-
|
|
510
|
-
User: `/bugteam`
|
|
511
|
-
Claude: [resolves PR #42, runs loop]
|
|
512
|
-
|
|
513
|
-
`Loop 1 audit: 1P0 / 2P1 / 0P2`
|
|
514
|
-
`Loop 1 fix: commit a1b2c3d (3 files, +18/-7)`
|
|
515
|
-
`Loop 2 audit: 0P0 / 1P1 / 0P2`
|
|
516
|
-
`Loop 2 fix: commit e4f5g6h (1 file, +5/-2)`
|
|
517
|
-
`Loop 3 audit: 0P0 / 0P1 / 0P2 → converged`
|
|
518
|
-
|
|
519
|
-
`/bugteam exit: converged`
|
|
520
|
-
`Loops: 3`
|
|
521
|
-
`Starting commit: 9d8c7b6`
|
|
522
|
-
`Final commit: e4f5g6h`
|
|
523
|
-
`Net change: 4 files, +23/-9`
|
|
524
|
-
</example>
|
|
525
|
-
|
|
526
|
-
<example>
|
|
527
|
-
User: `/bugteam`
|
|
528
|
-
Claude: [runs 10 loops without convergence]
|
|
529
|
-
|
|
530
|
-
`Loop 10 audit: 0P0 / 1P1 / 2P2`
|
|
531
|
-
|
|
532
|
-
`/bugteam exit: cap reached`
|
|
533
|
-
`Loops: 10`
|
|
534
|
-
`Remaining: 0P0 / 1P1 / 2P2 — run /findbugs for human triage`
|
|
535
|
-
</example>
|
|
536
|
-
|
|
537
|
-
<example>
|
|
538
|
-
User: `/bugteam`
|
|
539
|
-
Claude: [loop 4 fix produces no commit]
|
|
540
|
-
|
|
541
|
-
`Loop 4 fix: clean-coder reported no changes (could not address remaining bugs)`
|
|
542
|
-
`/bugteam exit: stuck`
|
|
543
|
-
`Unresolved findings (3): src/cache.py:88 (P0 race condition); ...`
|
|
544
|
-
</example>
|
|
545
|
-
|
|
546
|
-
<example>
|
|
547
|
-
User: `/bugteam` (mixed-outcome path: some findings fixed, others skipped)
|
|
548
|
-
Claude: [resolves PR #99, runs loop with partial-fix outcomes]
|
|
549
|
-
|
|
550
|
-
`Loop 1 audit: 1P0 / 3P1 / 0P2`
|
|
551
|
-
`Loop 1 fix: commit a1b2c3d (2 files, +8/-3) — 2 fixed, 2 could_not_address`
|
|
552
|
-
`Loop 2 audit: 0P0 / 2P1 / 0P2`
|
|
553
|
-
`Loop 2 fix: 0 fixed, 2 could_not_address (no commit)`
|
|
554
|
-
|
|
555
|
-
`/bugteam exit: stuck`
|
|
556
|
-
`Loops: 2`
|
|
557
|
-
`Unresolved findings (2): src/auth.py:45 (P1: file is generated, cannot edit); src/legacy.py:200 (P1: rewrite scope exceeds the bug)`
|
|
558
|
-
|
|
559
|
-
The bugfix teammate writes one outcome per finding to `.bugteam-loop-2.outcomes.xml`. Findings with `status=could_not_address` carry their `<reason>` text, and the teammate posts a matching reply to each finding comment so the reviewer sees why each bug stayed open.
|
|
560
|
-
</example>
|
|
561
|
-
|
|
562
|
-
<example>
|
|
563
|
-
User: `/bugteam` (no PR or upstream diff)
|
|
564
|
-
Claude: `No PR or upstream diff. /bugteam needs a target.`
|
|
565
|
-
</example>
|
|
566
|
-
|
|
567
|
-
<example>
|
|
568
|
-
User: `/bugteam` (uncommitted changes in working tree)
|
|
569
|
-
Claude: `Uncommitted changes detected. Stash, commit, or revert before /bugteam.`
|
|
570
|
-
</example>
|
|
571
|
-
|
|
572
|
-
## Why this design
|
|
573
|
-
|
|
574
|
-
The three sibling skills compose, but `/bugteam` solves a problem they cannot solve in sequence:
|
|
575
|
-
|
|
576
|
-
- `/findbugs` audits once and stops.
|
|
577
|
-
- `/fixbugs` fixes the findings of one audit and stops.
|
|
578
|
-
- A human-driven `/findbugs` → `/fixbugs` → `/findbugs` → `/fixbugs` cycle works but requires the user to drive it.
|
|
579
|
-
|
|
580
|
-
`/bugteam` automates that cycle. The clean-room property is preserved by spawning a fresh audit agent each loop with no inherited context — every audit is independent of the prior loop's verdict. The 10-loop cap is the safety: pathological cases (audit agent oscillating, fix agent regressing) cannot run away.
|
|
581
|
-
|
|
582
|
-
The single up-front confirmation is the explicit trade — `/bugteam` is more autonomous than `/findbugs`+`/fixbugs` chained manually. The user accepts that autonomy by typing the command. Stop conditions and the loop log give the user full visibility on exit.
|
|
491
|
+
See [`EXAMPLES.md`](EXAMPLES.md).
|