claude-dev-env 1.36.2 → 1.37.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/_shared/pr-loop/scripts/config/preflight_constants.py +29 -8
- package/_shared/pr-loop/scripts/preflight.py +242 -20
- package/_shared/pr-loop/scripts/tests/test_preflight.py +362 -25
- package/_shared/pr-loop/scripts/tests/test_preflight_constants.py +9 -14
- package/hooks/blocking/code_rules_enforcer.py +269 -23
- package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +157 -1
- package/hooks/config/test_unused_module_import_constants.py +48 -0
- package/hooks/config/unused_module_import_constants.py +41 -0
- package/package.json +1 -1
- package/skills/bg-agent/SKILL.md +69 -0
- package/skills/bugteam/CONSTRAINTS.md +10 -19
- package/skills/bugteam/PROMPTS.md +3 -3
- package/skills/bugteam/SKILL.md +103 -202
- package/skills/bugteam/SKILL_EVALS.md +75 -114
- package/skills/bugteam/reference/README.md +2 -4
- package/skills/bugteam/reference/design-rationale.md +3 -8
- package/skills/bugteam/reference/team-setup.md +11 -19
- package/skills/bugteam/reference/teardown-publish-permissions.md +2 -14
- package/skills/bugteam/scripts/config/__init__.py +0 -0
- package/skills/bugteam/scripts/config/reflow_skill_md_constants.py +12 -0
- package/skills/bugteam/scripts/reflow_skill_md.py +51 -47
- package/skills/bugteam/sources.md +1 -25
- package/skills/bugteam/test_skill_additions.py +4 -13
- package/skills/fresh-branch/SKILL.md +71 -0
- package/skills/gotcha/SKILL.md +73 -0
- package/skills/monitor-open-prs/SKILL.md +4 -37
- package/skills/monitor-open-prs/test_skill_contract.py +0 -5
- package/skills/pr-converge/SKILL.md +60 -1298
- package/skills/pr-converge/reference/convergence-gates.md +118 -0
- package/skills/pr-converge/reference/examples.md +76 -0
- package/skills/pr-converge/reference/fix-protocol.md +54 -0
- package/skills/pr-converge/reference/ground-rules.md +13 -0
- package/skills/pr-converge/reference/multi-pr-orchestration.md +204 -0
- package/skills/pr-converge/reference/per-tick.md +201 -0
- package/skills/pr-converge/reference/state-schema.md +19 -0
- package/skills/pr-converge/reference/stop-conditions.md +26 -0
- package/skills/pr-converge/scripts/README.md +36 -9
- package/skills/pr-converge/scripts/check_pr_mergeability.py +1 -2
- package/skills/pr-converge/scripts/config/pr_converge_constants.py +58 -5
- package/skills/pr-converge/scripts/config/reflow_skill_md_constants.py +13 -0
- package/skills/pr-converge/scripts/config/test_pr_converge_constants.py +0 -24
- package/skills/pr-converge/scripts/cursor-agents-continue.ahk +22 -2
- package/skills/pr-converge/scripts/fetch_bugbot_inline_comments.py +19 -59
- package/skills/pr-converge/scripts/fetch_bugbot_reviews.py +15 -61
- package/skills/pr-converge/scripts/fetch_claude_inline_comments.py +70 -0
- package/skills/pr-converge/scripts/fetch_claude_reviews.py +61 -0
- package/skills/pr-converge/scripts/fetch_copilot_inline_comments.py +19 -61
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +14 -74
- package/skills/pr-converge/scripts/reflow_skill_md.py +71 -50
- package/skills/pr-converge/scripts/reviewer_fetch_core.py +153 -0
- package/skills/pr-converge/scripts/reviewer_specs.py +98 -0
- package/skills/pr-converge/scripts/test_cursor_agents_continue.py +65 -0
- package/skills/pr-converge/scripts/test_fetch_bugbot_inline_comments.py +107 -6
- package/skills/pr-converge/scripts/test_fetch_bugbot_reviews.py +85 -6
- package/skills/pr-converge/scripts/test_fetch_claude_inline_comments.py +485 -0
- package/skills/pr-converge/scripts/test_fetch_claude_reviews.py +368 -0
- package/skills/pr-converge/scripts/test_fetch_copilot_inline_comments.py +74 -6
- package/skills/pr-converge/scripts/test_fetch_copilot_reviews.py +94 -8
- package/skills/pr-converge/scripts/test_reflow_skill_md.py +162 -0
- package/skills/pr-converge/scripts/test_reviewer_fetch_core.py +448 -0
- package/skills/pr-converge/scripts/test_reviewer_specs.py +107 -0
- package/skills/pr-converge/workflows/schedule-wakeup-loop.md +24 -22
- package/skills/bugteam/reference/workflow-path-a-orchestrated-teams.md +0 -113
- package/skills/bugteam/reference/workflow-path-b-task-harness.md +0 -48
- package/skills/bugteam/test_team_lifecycle.py +0 -103
- package/skills/monitor-open-prs/test_team_lifecycle.py +0 -46
- package/skills/pr-converge/scripts/open_followup_copilot_pr.py +0 -136
- package/skills/pr-converge/scripts/test_open_followup_copilot_pr.py +0 -236
- package/skills/pr-converge/test_team_lifecycle.py +0 -56
- package/skills/pr-converge/workflows/ahk-auto-continue-loop.md +0 -108
|
@@ -1,35 +1,26 @@
|
|
|
1
1
|
# Bugteam — invariants and design rationale
|
|
2
2
|
|
|
3
|
-
## Path A vs Path B
|
|
4
|
-
|
|
5
|
-
**Path A** (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`): the constraints below apply as written — `TeamCreate`, isolated teammate sessions, lead-only `TeamDelete`. **Path B** (Task harness): read [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) for harness-only steps; **agent types** (`code-quality-agent`, `clean-coder`), **models**, **one commit per fix**, **gate-before-AUDIT**, **10-loop cap**, and **outcome XML** remain identical to `SKILL.md`. Path B intentionally uses **`Task`** from the lead instead of teammate isolation — see that file **Clean-room note**.
|
|
6
|
-
|
|
7
3
|
## Constraints
|
|
8
4
|
|
|
9
|
-
- **
|
|
10
|
-
- **Path B — Cursor `Task` registry.** When the host `Task` tool rejects `subagent_type="clean-coder"`, Path B FIX MUST use `subagent_type: "generalPurpose"` plus the mandatory **Read** of `clean-coder.md` in the FIX prompt per [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) (FIX spawn, Cursor host split). This is the documented shim, not an ad-hoc `generalPurpose` bypass of the clean-coder contract.
|
|
11
|
-
- **Path A — orchestrator-only `TeamCreate`.** Only the lead session (this session, when `/bugteam` is invoked) calls `TeamCreate`. Teammates never call `TeamCreate` — if a teammate's spawn prompt instructs it to, that is a skill defect. When additional parallel work is needed (e.g., parallel auditors from loop 4 onward, supplementary audit of adjacent files), the lead spawns additional teammates into the EXISTING team by passing the current `team_name` to every `Agent(...)` call. Multiple teammate "sets" live inside one team under one orchestrator. The runtime enforces this: `TeamCreate` called while the session already leads a team returns the error `Already leading team "<name>". A leader can only manage one team at a time. Use TeamDelete to end the current team before creating a new one.` — direct quote from the runtime's response when this invariant is violated. The Step 2 lifecycle resolution in [Team lifecycle](SKILL.md#team-lifecycle-path-a-only) parses this exact error in `auto` mode to attach to the existing team rather than fail. **Path B:** no `TeamCreate`; parallel work uses parallel **`Task`** calls per [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md).
|
|
12
|
-
- **One team per invocation, multi-PR supported.** All PRs in a single /bugteam invocation share one team created by the orchestrator. Per-PR identity lives in the teammate name prefix (`bugfind-pr<N>-loop<L>` / `bugfix-pr<N>-loop<L>`) and the `<team_temp_dir>/pr-<N>/` subfolder containing that PR's git worktree, diff patches, and outcome XML files.
|
|
5
|
+
- **One run per invocation, multi-PR supported.** All PRs in a single /bugteam invocation share one `run_temp_dir`. Per-PR identity lives in the subagent name prefix (`bugfind-pr<N>-loop<L>` / `bugfix-pr<N>-loop<L>`) and the `<run_temp_dir>/pr-<N>/` subfolder containing that PR's git worktree, diff patches, and outcome XML files.
|
|
13
6
|
- **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.
|
|
14
|
-
- **Fresh
|
|
7
|
+
- **Fresh subagent per loop.** Both bugfind and bugfix are spawned new each loop. Reusing a subagent across loops accumulates context inside that subagent's window — defeats clean-room.
|
|
15
8
|
- **One up-front confirmation = whole cycle.** The `/bugteam` invocation authorizes the entire cycle; every subsequent decision runs on that single authorization.
|
|
16
9
|
- **10-loop hard cap.** Counted as **AUDIT** completions (increment in Step 3). Standards-fix passes before an audit do not advance `loop_count`. Worst case includes extra clean-coder spawns for the code-rules gate.
|
|
17
10
|
- **Code rules gate before every AUDIT.** Run `_shared/pr-loop/scripts/code_rules_gate.py` (resolved via `${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/code_rules_gate.py`) until exit **0** before spawning **bugfind**. Same `validate_content` logic as `hooks/blocking/code_rules_enforcer.py`.
|
|
18
|
-
- **Clean-room audits, every loop.** Each bugfind
|
|
19
|
-
- **Targeted fixes.** Each fix
|
|
20
|
-
- **Opus 4.7 at xhigh effort for both
|
|
21
|
-
- **Fix
|
|
11
|
+
- **Clean-room audits, every loop.** Each bugfind subagent's spawn prompt contains only the PR scope, audit rubric, and the current loop number. Prior loop history stays in the lead.
|
|
12
|
+
- **Targeted fixes.** Each fix subagent sees ONLY the most recent audit's findings. Prior loops are invisible to the fix subagent.
|
|
13
|
+
- **Opus 4.7 at xhigh effort for both subagents.** Both `Agent(...)` spawns pass `model="opus"`, which resolves to Opus 4.7 on the Anthropic API. Opus 4.7's default effort level in Claude Code is `xhigh` (https://code.claude.com/docs/en/model-config — *"On Opus 4.7, the default effort is `xhigh` for all plans and providers."*), so no `effort` override is needed at spawn time. Effort is set per-subagent in YAML frontmatter, not via the `Agent` tool's parameters; `code-quality-agent` and `clean-coder` rely on the model default. The trade vs Sonnet is higher per-loop cost in exchange for deeper audit recall and stronger fix correctness on bug-hunting work, which the per-PR loop economics tolerate (10-loop hard cap bounds total spend).
|
|
14
|
+
- **Fix subagent receives the latest audit as its input contract.** Passing the audit's findings to the fix subagent is the input contract — each loop's fix run operates on the current audit's output and only that.
|
|
22
15
|
- **One commit per fix action.** Loops produce one commit per loop, not one per bug.
|
|
23
16
|
- **Linear branch, fixed PR base.** Every loop appends one forward-only commit; existing commits and the PR base stay intact throughout the cycle.
|
|
24
|
-
- **Lead-only cleanup
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
27
|
-
- **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.
|
|
28
|
-
- **Audit/fix comment posting.** **Path A:** 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. **Path B:** the **lead** performs the same POSTs after Task handoffs (`SKILL.md` Step 2.5 + [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § Step 2.5).
|
|
17
|
+
- **Lead-only cleanup.** Cleanup runs in the lead (this session) only. Step 4 removes the full `<run_temp_dir>` so no loop patches leak between runs.
|
|
18
|
+
- **Cleanup all `.bugteam-*` files on exit.** The per-run `<run_temp_dir>` is removed entirely by Step 4, which covers `<run_temp_dir>/pr-<N>/loop-<L>.patch` and `<run_temp_dir>/pr-<N>/loop-<L>-{b,c}.outcomes.xml`. The per-loop outcomes XML at `<worktree_path>/.bugteam-pr<N>-loop<L>.outcomes.xml` is removed with the worktree. Step 4.5 deletes `.bugteam-final.diff`, `.bugteam-original-body.md`, and `.bugteam-final-body.md`. Working directory ends clean.
|
|
19
|
+
- **Audit/fix comment posting.** The bugfind subagent posts ONE per-loop review (parent body + child finding comments in a single batched POST, with review-fallback to a top-level issue comment). The bugfix subagent posts the fix replies after committing. All comment, review, and reply POSTs belong to the subagents; the lead's single PR-write action is the final description rewrite at Step 4.5.
|
|
29
20
|
- **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.
|
|
30
21
|
- **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.
|
|
31
22
|
- **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.
|
|
32
|
-
- **Outcome XML, not JSON.** Both
|
|
23
|
+
- **Outcome XML, not JSON.** Both subagents write structured outcome data (findings or fix outcomes) to `.bugteam-pr<N>-loop<L>.outcomes.xml`. The lead reads these files between actions. XML chosen for parser robustness against multi-line, special-character, and quoted reason fields.
|
|
33
24
|
|
|
34
25
|
## Why this design
|
|
35
26
|
|
|
@@ -18,7 +18,7 @@ Keep the spawn prompt self-contained: reference only the PR scope, audit rubric,
|
|
|
18
18
|
cd into `<worktree_path>` before any git, gh, or file operation.
|
|
19
19
|
|
|
20
20
|
<scope>
|
|
21
|
-
<diff_path>Absolute path to the per-PR patch file: <
|
|
21
|
+
<diff_path>Absolute path to the per-PR patch file: <run_temp_dir>/pr-<N>/loop-<L>.patch (same path as gh pr diff redirect in AUDIT)</diff_path>
|
|
22
22
|
<scope_rule>Audit only lines added or modified in the diff. Pre-existing code on untouched lines is out of scope.</scope_rule>
|
|
23
23
|
</scope>
|
|
24
24
|
|
|
@@ -76,8 +76,8 @@ cd into `<worktree_path>` before any git, gh, or file operation.
|
|
|
76
76
|
</comment_posting>
|
|
77
77
|
|
|
78
78
|
<output_format>
|
|
79
|
-
|
|
80
|
-
the PR's worktree directory (<worktree_path>). Return only that path on stdout. The schema:
|
|
79
|
+
For the primary (-a) auditor: write the outcome XML below to .bugteam-pr<N>-loop<L>.outcomes.xml inside
|
|
80
|
+
the PR's worktree directory (<worktree_path>). For sibling auditors (-b/-c): write to <run_temp_dir>/pr-<N>/loop-<L>-{b,c}.outcomes.xml (absolute path passed in prompt). Return only that path on stdout. The schema:
|
|
81
81
|
</output_format>
|
|
82
82
|
```
|
|
83
83
|
|
package/skills/bugteam/SKILL.md
CHANGED
|
@@ -3,13 +3,9 @@ name: bugteam
|
|
|
3
3
|
description: >-
|
|
4
4
|
Open pull request audit–fix until convergence: CODE_RULES gate, clean-room
|
|
5
5
|
audit (`code-quality-agent`, opus) and fix (`clean-coder`, opus), per-loop
|
|
6
|
-
GitHub reviews, 10-audit cap; grant then revoke `.claude/**`.
|
|
7
|
-
`
|
|
8
|
-
|
|
9
|
-
`reference/workflow-path-b-task-harness.md`). **This `SKILL.md` holds only
|
|
10
|
-
shared steps**; per-path harness lives in `reference/workflow-path-*.md`.
|
|
11
|
-
Triggers: '/bugteam', 'run the bug team', 'auto-fix the PR until clean', 'loop
|
|
12
|
-
audit and fix'.
|
|
6
|
+
GitHub reviews, 10-audit cap; grant then revoke `.claude/**`. Spawns
|
|
7
|
+
background subagents (`Agent(..., run_in_background=true)`). Triggers: '/bugteam', 'run
|
|
8
|
+
the bug team', 'auto-fix the PR until clean', 'loop audit and fix'.
|
|
13
9
|
---
|
|
14
10
|
|
|
15
11
|
# Bugteam
|
|
@@ -18,103 +14,22 @@ description: >-
|
|
|
18
14
|
`code-quality-agent`, fresh context each loop. **Bugfix:** `clean-coder`. Hard
|
|
19
15
|
cap: 10 audit loops. Grant `.claude/**` at start, revoke always at end.
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`
|
|
24
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] and
|
|
25
|
-
[`reference/workflow-path-b-task-harness.md`][path-b]. Verbatim doc quotes and
|
|
26
|
-
URLs: [`sources.md`](sources.md).
|
|
27
|
-
|
|
28
|
-
## Path routing (mandatory first branch)
|
|
29
|
-
|
|
30
|
-
At `/bugteam` entry, evaluate **once** (same rule as pr-converge §Team
|
|
31
|
-
infrastructure detection):
|
|
32
|
-
|
|
33
|
-
- **Path A** — `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` set and equals **`1`**
|
|
34
|
-
after trim → load and follow
|
|
35
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] for every harness
|
|
36
|
-
step (with this `SKILL.md` for shared material).
|
|
37
|
-
- **Path B** — otherwise → load and follow
|
|
38
|
-
[`reference/workflow-path-b-task-harness.md`][path-b] for every harness step
|
|
39
|
-
(with this `SKILL.md` for shared material).
|
|
40
|
-
|
|
41
|
-
Shared material is **everything else in this file** plus
|
|
42
|
-
[`PROMPTS.md`](PROMPTS.md), [`EXAMPLES.md`](EXAMPLES.md),
|
|
43
|
-
[`CONSTRAINTS.md`](CONSTRAINTS.md) — agent types, models, XML, gates, cycle
|
|
44
|
-
state machine, Step 2.5 payload shapes, shared teardown `rmtree`, revoke, final
|
|
45
|
-
report.
|
|
46
|
-
|
|
47
|
-
## Team lifecycle (Path A only)
|
|
48
|
-
|
|
49
|
-
The `TeamCreate` / `TeamDelete` pair has historically been bound to a single
|
|
50
|
-
`/bugteam` invocation. That coupling fails when an orchestrator (`pr-converge`
|
|
51
|
-
multi-PR mode, `monitor-open-prs`) needs to call `/bugteam` repeatedly inside
|
|
52
|
-
one parent session: only one team can be led at a time, and a missed Step 4
|
|
53
|
-
leaks the team. To decouple, every Path A invocation reads
|
|
54
|
-
`BUGTEAM_TEAM_LIFECYCLE` (defaults to `auto`) and may also read
|
|
55
|
-
`BUGTEAM_TEAM_NAME`.
|
|
56
|
-
|
|
57
|
-
**`owned`**
|
|
58
|
-
|
|
59
|
-
- **Step 2:** `TeamCreate(<computed_team_name>)`. If the runtime returns
|
|
60
|
-
`Already leading team "<existing>". A leader can only manage one team at a
|
|
61
|
-
time.` → **error**: `Already leading team <existing>; rerun with
|
|
62
|
-
BUGTEAM_TEAM_LIFECYCLE=attach BUGTEAM_TEAM_NAME=<existing>`.
|
|
63
|
-
- **Step 4:** `TeamDelete()` (lead-owned).
|
|
64
|
-
- **Use case:** Pre-decoupling behavior. Use only when you know the session
|
|
65
|
-
leads no other team.
|
|
66
|
-
|
|
67
|
-
**`attach`**
|
|
68
|
-
|
|
69
|
-
- **Step 2:** Require `BUGTEAM_TEAM_NAME`. Treat that team as already-led; do
|
|
70
|
-
**not** call `TeamCreate`.
|
|
71
|
-
- **Step 4:** **Skip** `TeamDelete` — the orchestrator owns teardown.
|
|
72
|
-
- **Use case:** Orchestrators (pr-converge multi-PR, monitor-open-prs) that
|
|
73
|
-
explicitly created a team and will tear it down themselves.
|
|
74
|
-
|
|
75
|
-
### `auto` (**default: `auto`**)
|
|
76
|
-
|
|
77
|
-
- **Step 2:** Try `TeamCreate(<computed_team_name>)`. On `Already leading team
|
|
78
|
-
"<existing>"` → parse `<existing>`, attach (do **not** call `TeamCreate`
|
|
79
|
-
again), set `team_owned=false`. On success → set `team_owned=true`.
|
|
80
|
-
- **Step 4:** If `team_owned=true` → `TeamDelete()`. Else → **skip**
|
|
81
|
-
`TeamDelete`.
|
|
82
|
-
- **Use case:** All callers when in doubt. Solo invocations behave like `owned`;
|
|
83
|
-
nested or repeated invocations attach safely.
|
|
84
|
-
|
|
85
|
-
**`team_owned` flag** — set in Step 2 by all three modes
|
|
86
|
-
(`owned` always `true`; `attach` always `false`; `auto` reflects the
|
|
87
|
-
`TeamCreate` outcome). Read in Step
|
|
88
|
-
4 to decide whether to call `TeamDelete`. The same flag also gates
|
|
89
|
-
`<team_temp_dir>` `rmtree`: when `team_owned=false`, only the per-PR subfolders
|
|
90
|
-
this invocation created (`<team_temp_dir>/pr-<N>/`) are removed; the
|
|
91
|
-
orchestrator's parent directory survives.
|
|
92
|
-
|
|
93
|
-
**Path B note:** Path B does not use `TeamCreate` / `TeamDelete`, so
|
|
94
|
-
`BUGTEAM_TEAM_LIFECYCLE` is read but only its `team_temp_dir` cleanup behavior
|
|
95
|
-
applies. `team_owned` is treated as `true` by default in Path B; orchestrators
|
|
96
|
-
driving Path B that share a temp directory should set
|
|
97
|
-
`BUGTEAM_TEAM_LIFECYCLE=attach` so the per-PR subfolder cleanup rule applies.
|
|
17
|
+
Both audit and fix roles run as background subagents
|
|
18
|
+
(`Agent(..., run_in_background=true)`). Verbatim doc quotes and URLs:
|
|
19
|
+
[`sources.md`](sources.md).
|
|
98
20
|
|
|
99
21
|
## Contents
|
|
100
22
|
|
|
101
23
|
Orchestration lives here; companion files hold prompts, invariants, examples,
|
|
102
24
|
citations, and domain reference notes. Scan this list before a partial read.
|
|
103
25
|
|
|
104
|
-
- [Path routing](#path-routing-mandatory-first-branch) — Path A vs Path B
|
|
105
|
-
- [Team lifecycle](#team-lifecycle-path-a-only) — `owned` / `attach` / `auto`
|
|
106
|
-
modes; orchestrator-owned teams
|
|
107
|
-
- [`reference/workflow-path-a-orchestrated-teams.md`][path-a] — Path A harness
|
|
108
|
-
(orchestrated teams)
|
|
109
|
-
- [`reference/workflow-path-b-task-harness.md`][path-b] — Path B harness (Task
|
|
110
|
-
harness)
|
|
111
26
|
- When this skill applies — refusal cases and trigger conditions
|
|
112
27
|
- Utility scripts — pre-flight (`scripts/`, executed not inlined)
|
|
113
28
|
- Pre-audit gate — `validate_content` before each AUDIT
|
|
114
29
|
- The Process — checklist + Steps 0–6
|
|
115
30
|
- Step 0 — Grant project permissions
|
|
116
31
|
- Step 1 — Resolve PR scope
|
|
117
|
-
- Step 2 —
|
|
32
|
+
- Step 2 — Loop state
|
|
118
33
|
- Step 2.5 — PR comment lifecycle (per-loop review + fix replies)
|
|
119
34
|
- Step 3 — Cycle (AUDIT ↔ FIX, exits)
|
|
120
35
|
- Step 4 — Teardown + clean tree
|
|
@@ -140,12 +55,6 @@ Refusals — first match wins; respond with the quoted line exactly and stop:
|
|
|
140
55
|
- **Missing subagents.** Before Step 0, confirm `code-quality-agent` and
|
|
141
56
|
`clean-coder` exist. Else: `Required subagent type <name> not installed.
|
|
142
57
|
/bugteam needs both code-quality-agent and clean-coder available.`
|
|
143
|
-
- **Lead role must be held by the orchestrator.** Run /bugteam in the session
|
|
144
|
-
that received the user's command. **Path A:** lead calls `TeamCreate` per
|
|
145
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a]; runtime may
|
|
146
|
-
return `Already leading team "<name>". A leader can only manage one team at a
|
|
147
|
-
time.` **Path B:** lead runs the Task harness per
|
|
148
|
-
[`reference/workflow-path-b-task-harness.md`][path-b]; no `TeamCreate`.
|
|
149
58
|
|
|
150
59
|
## Utility scripts
|
|
151
60
|
|
|
@@ -189,9 +98,9 @@ the auto-remediation only applies to the `core.hooksPath` failure mode.
|
|
|
189
98
|
```
|
|
190
99
|
[ ] Step 0: project permissions granted
|
|
191
100
|
[ ] Step 1: PR scope resolved
|
|
192
|
-
[ ] Step 2: loop state set
|
|
101
|
+
[ ] Step 2: loop state set
|
|
193
102
|
[ ] Step 3: cycle complete (converged | cap reached | stuck | error)
|
|
194
|
-
[ ] Step 4:
|
|
103
|
+
[ ] Step 4: working tree clean
|
|
195
104
|
[ ] Step 4.5: PR description rewritten (or skip warning logged)
|
|
196
105
|
[ ] Step 5: project permissions revoked
|
|
197
106
|
[ ] Step 6: final report printed
|
|
@@ -200,9 +109,9 @@ the auto-remediation only applies to the `core.hooksPath` failure mode.
|
|
|
200
109
|
### Step 0: Grant project permissions (once, first)
|
|
201
110
|
|
|
202
111
|
```bash
|
|
203
|
-
python
|
|
204
|
-
"${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/
|
|
205
|
-
|
|
112
|
+
python \
|
|
113
|
+
"${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/"\
|
|
114
|
+
"grant_project_claude_permissions.py"
|
|
206
115
|
```
|
|
207
116
|
|
|
208
117
|
`${CLAUDE_SKILL_DIR}` is host-substituted before the shell runs (unlike normal
|
|
@@ -219,62 +128,59 @@ follows the same downstream rules.
|
|
|
219
128
|
|
|
220
129
|
Keep: owner/repo, branches, PR number, URL — for all loops.
|
|
221
130
|
|
|
131
|
+
**`<run_temp_dir>`:** `Path(tempfile.gettempdir()) / run_name` where
|
|
132
|
+
`run_name = "bugteam-pr-<number>-<YYYYMMDDHHMMSS>"` for a single-PR invocation
|
|
133
|
+
or `"bugteam-<YYYYMMDDHHMMSS>"` for multi-PR. Lead resolves once to an absolute
|
|
134
|
+
path; every shell gets that literal string.
|
|
135
|
+
|
|
222
136
|
#### Per-PR workspace
|
|
223
137
|
|
|
224
138
|
For each PR in all_prs:
|
|
225
139
|
|
|
226
|
-
1. Create `<
|
|
227
|
-
2. Run `git worktree add "<
|
|
140
|
+
1. Create `<run_temp_dir>/pr-<N>/`.
|
|
141
|
+
2. Run `git worktree add "<run_temp_dir>/pr-<N>/worktree" origin/<headRef>`.
|
|
228
142
|
3. Record the absolute worktree path alongside the PR's other fields.
|
|
229
143
|
|
|
230
|
-
|
|
231
|
-
teardown runs `git worktree remove "<
|
|
232
|
-
PR
|
|
233
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] or
|
|
234
|
-
[`reference/workflow-path-b-task-harness.md`][path-b] § Step 4.
|
|
235
|
-
|
|
236
|
-
### Step 2: Path harness + loop state
|
|
237
|
-
|
|
238
|
-
Apply the path you chose in [Path
|
|
239
|
-
routing](#path-routing-mandatory-first-branch): **Path A** —
|
|
240
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] § Step 2
|
|
241
|
-
(`TeamCreate`, team name, `team_temp_dir`, roles, optional Groq FIX,
|
|
242
|
-
`--bugbot-retrigger`). **Path B** —
|
|
243
|
-
[`reference/workflow-path-b-task-harness.md`][path-b] § Step 2 (no `TeamCreate`
|
|
244
|
-
/ `TeamDelete`; same worktrees and variables).
|
|
144
|
+
Background subagents for a PR operate inside that PR's worktree. Step 4
|
|
145
|
+
teardown runs `git worktree remove "<run_temp_dir>/pr-<N>/worktree"` for each
|
|
146
|
+
PR before the shared `rmtree`.
|
|
245
147
|
|
|
246
|
-
|
|
247
|
-
lifecycle](#team-lifecycle-path-a-only): pick the mode (`owned` / `attach` /
|
|
248
|
-
`auto`) from `BUGTEAM_TEAM_LIFECYCLE`, set `team_name` (computed for
|
|
249
|
-
`owned`/`auto` create paths; required `BUGTEAM_TEAM_NAME` for `attach` and
|
|
250
|
-
`auto`'s attach branch), and set `team_owned` (`true` when `TeamCreate`
|
|
251
|
-
succeeded in this invocation; `false` when attaching to an existing team). Step
|
|
252
|
-
4 reads `team_owned` to decide whether to call `TeamDelete`.
|
|
148
|
+
### Step 2: Loop state
|
|
253
149
|
|
|
254
|
-
**Loop state (lead; not a single script):**
|
|
150
|
+
**Loop state (lead; not a single script; per-PR):** The variables
|
|
151
|
+
below are tracked independently for each PR in `all_prs`. Each PR has its
|
|
152
|
+
own cycle, state, and exit reason.
|
|
255
153
|
|
|
256
154
|
```bash
|
|
257
155
|
loop_count=0
|
|
258
156
|
last_action="fresh"
|
|
259
157
|
last_findings='{"total": 0}'
|
|
260
158
|
audit_log=""
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
team_temp_dir="<absolute-path>/<team_name>"
|
|
264
|
-
team_owned="true" # set by Step 2 lifecycle resolution; see Team lifecycle table
|
|
159
|
+
run_temp_dir="<absolute-path>/<run_name>"
|
|
160
|
+
starting_sha="$(git -C "<run_temp_dir>/pr-<N>/worktree" rev-parse HEAD)"
|
|
265
161
|
loop_comment_index=""
|
|
266
162
|
```
|
|
267
163
|
|
|
164
|
+
**Optional Groq-backed FIX (explicit opt-in only):** when the user explicitly
|
|
165
|
+
sets `BUGTEAM_FIX_IMPLEMENTER=groq-coder` before invocation, spawn the FIX
|
|
166
|
+
subagent with `subagent_type="groq-coder"`. Requires `GROQ_API_KEY` in the
|
|
167
|
+
environment (load from `packages/claude-dev-env/.env` when that file exists;
|
|
168
|
+
prompt the user to create it from `.env.example` if still unset). Any other
|
|
169
|
+
`BUGTEAM_FIX_IMPLEMENTER` value (or unset) uses `clean-coder`.
|
|
170
|
+
|
|
171
|
+
**`--bugbot-retrigger` flag:** when present, the FIX subagent posts a `bugbot
|
|
172
|
+
run` issue comment via the Step 2.5 issue-comments fallback endpoint after
|
|
173
|
+
every successful FIX push, to re-trigger Cursor's bugbot on the new commit.
|
|
174
|
+
|
|
268
175
|
**`loop_comment_index`:** reset each AUDIT start; filled during AUDIT; FIX
|
|
269
176
|
consumes for replies; cleared after FIX. Entries: `{loop, finding_id,
|
|
270
177
|
finding_comment_id, finding_comment_url, used_fallback, fix_status}`.
|
|
271
178
|
|
|
272
179
|
### Step 2.5: PR comments (one review per loop)
|
|
273
180
|
|
|
274
|
-
**Who posts:**
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
endpoints below are identical for both paths.
|
|
181
|
+
**Who posts:** the AUDIT subagent posts one `POST .../pulls/<n>/reviews` per
|
|
182
|
+
loop. The FIX subagent posts `.../comments/<id>/replies` after push. The lead's
|
|
183
|
+
only PR write before Step 4.5 is the final description rewrite.
|
|
278
184
|
|
|
279
185
|
Order: audit → buffer → validate anchors vs diff → single review POST.
|
|
280
186
|
Review body states counts; zero findings → still one review, `comments: []`,
|
|
@@ -316,7 +222,7 @@ POST --input -`
|
|
|
316
222
|
<tmp_fallback.md | gh api repos/<owner>/<repo>/issues/<number>/comments -X POST
|
|
317
223
|
--input -`
|
|
318
224
|
|
|
319
|
-
`<head_sha_at_post_time>`: `git rev-parse HEAD` in
|
|
225
|
+
`<head_sha_at_post_time>`: `git rev-parse HEAD` in subagent cwd immediately
|
|
320
226
|
before POST.
|
|
321
227
|
|
|
322
228
|
**Review body template (`<tmp_review_body.md>`):**
|
|
@@ -342,8 +248,7 @@ before POST.
|
|
|
342
248
|
|
|
343
249
|
### Step 3: The cycle
|
|
344
250
|
|
|
345
|
-
Run the AUDIT-FIX cycle for each PR in all_prs
|
|
346
|
-
PRs. The 10-loop cap applies per PR. Exit reasons (converged, cap reached,
|
|
251
|
+
Run the AUDIT-FIX cycle for each PR in all_prs. The 10-loop cap applies per PR. Exit reasons (converged, cap reached,
|
|
347
252
|
stuck, error) are tracked per PR; the final report lists one outcome line per
|
|
348
253
|
PR.
|
|
349
254
|
|
|
@@ -360,9 +265,8 @@ dirty so the AUDIT runs against the latest diff with that signal in mind:
|
|
|
360
265
|
|
|
361
266
|
```bash
|
|
362
267
|
dirty_review_count=0
|
|
363
|
-
gh api "repos/<owner>/<repo>/pulls/<number>/reviews" \
|
|
364
|
-
|
|
365
|
-
sort_by(.submitted_at) | reverse'
|
|
268
|
+
gh api "repos/<owner>/<repo>/pulls/<number>/reviews?per_page=100" --paginate --slurp \
|
|
269
|
+
| jq '[.[][] | select((.body // "") | startswith("## /bugteam loop "))] | sort_by(.submitted_at) | reverse'
|
|
366
270
|
```
|
|
367
271
|
|
|
368
272
|
Iterate from index 0 (most recent) toward older entries:
|
|
@@ -432,85 +336,84 @@ before the next AUDIT.
|
|
|
432
336
|
### AUDIT action
|
|
433
337
|
|
|
434
338
|
```bash
|
|
435
|
-
mkdir -p "<
|
|
436
|
-
gh pr diff <N> -R <owner>/<repo> > "<
|
|
339
|
+
mkdir -p "<run_temp_dir>/pr-<N>"
|
|
340
|
+
gh pr diff <N> -R <owner>/<repo> > "<run_temp_dir>/pr-<N>/loop-<L>.patch"
|
|
437
341
|
```
|
|
438
342
|
|
|
439
|
-
**Spawn
|
|
440
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] § AUDIT. Path B —
|
|
441
|
-
[`reference/workflow-path-b-task-harness.md`][path-b] § AUDIT. Same
|
|
442
|
-
`prompt="<audit XML; see PROMPTS.md>"` and outcome files.
|
|
343
|
+
**Spawn:**
|
|
443
344
|
|
|
444
|
-
|
|
445
|
-
(
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
345
|
+
```
|
|
346
|
+
Agent(
|
|
347
|
+
subagent_type="code-quality-agent",
|
|
348
|
+
name="bugfind-pr<N>-loop<L>",
|
|
349
|
+
model="opus",
|
|
350
|
+
run_in_background=true,
|
|
351
|
+
description="Bugfind audit PR <N> loop <L>",
|
|
352
|
+
prompt="<audit XML; see PROMPTS.md>"
|
|
353
|
+
)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Fresh spawn each loop for clean-room isolation. Lead awaits the
|
|
357
|
+
background-completion notification, then reads
|
|
358
|
+
`.bugteam-pr<N>-loop<L>.outcomes.xml` from the worktree directory, fills
|
|
359
|
+
`loop_comment_index`. [`PROMPTS.md`](PROMPTS.md): XML + outcome schema.
|
|
449
360
|
|
|
450
361
|
`last_action = "audited"`; append audit line to `audit_log`.
|
|
451
362
|
|
|
452
363
|
**Parallel auditors (`loop_count >= 4`):** gate passes immediately before;
|
|
453
|
-
after three full audit/fix rounds without convergence, issue three
|
|
454
|
-
one assistant message (
|
|
455
|
-
|
|
456
|
-
`-a` posts
|
|
457
|
-
the review and merges outcomes from `-b`/`-c` (read
|
|
364
|
+
after three full audit/fix rounds without convergence, issue three `Agent`
|
|
365
|
+
calls in one assistant message (`run_in_background=true`): `-a` posts the
|
|
366
|
+
review and merges outcomes from `-b`/`-c` (read
|
|
458
367
|
`.bugteam-pr<N>-loop<L>.outcomes.xml` plus
|
|
459
|
-
`<
|
|
368
|
+
`<run_temp_dir>/pr-<N>/loop-<L>-b.outcomes.xml` and `...-c...`); merge key
|
|
460
369
|
`(file, line, category_letter)`; re-id `loopN-K`. `-b`/`-c` write sibling XML
|
|
461
|
-
only; prompts must pass literal absolute sibling paths.
|
|
462
|
-
|
|
370
|
+
only; prompts must pass literal absolute sibling paths. Output path
|
|
371
|
+
contract: `-b`/`-c` write to `<run_temp_dir>/pr-<N>/loop-<L>-b.outcomes.xml`
|
|
372
|
+
and `<run_temp_dir>/pr-<N>/loop-<L>-c.outcomes.xml`; `-a` writes to
|
|
373
|
+
`<worktree_path>/.bugteam-pr<N>-loop<L>.outcomes.xml`.
|
|
374
|
+
Lead awaits all three background-completion notifications before merging
|
|
375
|
+
outcomes.
|
|
463
376
|
|
|
464
377
|
### FIX action
|
|
465
378
|
|
|
466
|
-
**Spawn
|
|
467
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] § FIX. Path B —
|
|
468
|
-
[`reference/workflow-path-b-task-harness.md`][path-b] § FIX.
|
|
379
|
+
**Spawn:**
|
|
469
380
|
|
|
470
|
-
|
|
471
|
-
|
|
381
|
+
```
|
|
382
|
+
Agent(
|
|
383
|
+
subagent_type="clean-coder",
|
|
384
|
+
name="bugfix-pr<N>-loop<L>",
|
|
385
|
+
model="opus",
|
|
386
|
+
run_in_background=true,
|
|
387
|
+
description="Bugfix PR <N> loop <L>",
|
|
388
|
+
prompt="<fix XML; see PROMPTS.md>"
|
|
389
|
+
)
|
|
390
|
+
```
|
|
472
391
|
|
|
473
|
-
|
|
474
|
-
|
|
392
|
+
Pass finding comment URLs/ids from `loop_comment_index` in XML. Lead awaits the
|
|
393
|
+
background-completion notification. Replies: `Fixed in <sha>` or `Could not
|
|
394
|
+
address this loop: <reason>`.
|
|
395
|
+
|
|
396
|
+
[`PROMPTS.md`](PROMPTS.md): fix XML + schema. Verify from worktree: `git -C "<run_temp_dir>/pr-<N>/worktree" rev-parse HEAD`
|
|
397
|
+
advanced; `git -C "<run_temp_dir>/pr-<N>/worktree" fetch origin <branch> && git -C "<run_temp_dir>/pr-<N>/worktree" rev-parse origin/<branch>` matches
|
|
475
398
|
`HEAD`. Unchanged HEAD →
|
|
476
|
-
`stuck — bugfix
|
|
399
|
+
`stuck — bugfix subagent could not address findings`.
|
|
477
400
|
|
|
478
401
|
### Step 4: Teardown
|
|
479
402
|
|
|
480
403
|
1. For each PR in `all_prs`: `git worktree remove
|
|
481
|
-
"<
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
2. Path-specific harness —
|
|
485
|
-
[`reference/workflow-path-a-orchestrated-teams.md`][path-a] § Step 4
|
|
486
|
-
(teammate `SendMessage`, `TeamDelete` **only when `team_owned=true`**) or
|
|
487
|
-
[`reference/workflow-path-b-task-harness.md`][path-b] § Step 4 (omit those).
|
|
488
|
-
|
|
489
|
-
3. **Windows-safe `rmtree` — gated by `team_owned` from [Team
|
|
490
|
-
lifecycle](#team-lifecycle-path-a-only).** The Windows-safe handler strips
|
|
491
|
-
the Windows ReadOnly attribute and retries the failing syscall (see
|
|
492
|
-
`~/.claude/rules/windows-filesystem-safe.md`).
|
|
404
|
+
"<run_temp_dir>/pr-<N>/worktree"` (from Step 1) — tolerate already-removed
|
|
405
|
+
worktrees.
|
|
493
406
|
|
|
494
|
-
|
|
407
|
+
2. **Windows-safe `rmtree`** — strips the Windows ReadOnly attribute and retries
|
|
408
|
+
the failing syscall (see `~/.claude/rules/windows-filesystem-safe.md`).
|
|
409
|
+
Remove the full `<run_temp_dir>`:
|
|
495
410
|
|
|
496
|
-
|
|
411
|
+
```bash
|
|
497
412
|
python -c "import os, shutil, stat, sys; \
|
|
498
413
|
h = lambda f, p, *_: (os.chmod(p, stat.S_IWRITE), f(p)); \
|
|
499
|
-
shutil.rmtree(r'<
|
|
414
|
+
shutil.rmtree(r'<run_temp_dir>', **({'onexc': h} if sys.version_info >= (3, 12)
|
|
500
415
|
else {'onerror': h}))"
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
- `team_owned=false` (attach mode) → for each PR in `all_prs`, remove only
|
|
504
|
-
that PR's `<team_temp_dir>/pr-<N>/` subfolder. The orchestrator-owned
|
|
505
|
-
parent `<team_temp_dir>` survives so the next attached invocation can write
|
|
506
|
-
its own per-PR subfolders without colliding.
|
|
507
|
-
|
|
508
|
-
```bash
|
|
509
|
-
python -c "import os, shutil, stat, sys; \
|
|
510
|
-
h = lambda f, p, *_: (os.chmod(p, stat.S_IWRITE), f(p)); \
|
|
511
|
-
shutil.rmtree(r'<team_temp_dir>/pr-<N>', **({'onexc': h} if sys.version_info >=
|
|
512
|
-
(3, 12) else {'onerror': h}))"
|
|
513
|
-
```
|
|
416
|
+
```
|
|
514
417
|
|
|
515
418
|
### Step 4.5: PR description
|
|
516
419
|
|
|
@@ -532,9 +435,9 @@ On failure: log in final report; continue to Step 5.
|
|
|
532
435
|
### Step 5: Revoke permissions (always)
|
|
533
436
|
|
|
534
437
|
```bash
|
|
535
|
-
python
|
|
536
|
-
"${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/
|
|
537
|
-
|
|
438
|
+
python \
|
|
439
|
+
"${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/"\
|
|
440
|
+
"revoke_project_claude_permissions.py"
|
|
538
441
|
```
|
|
539
442
|
|
|
540
443
|
Removes Step 0 grant — run even if Step 4 partially failed (log separately).
|
|
@@ -572,7 +475,5 @@ See [`reference/README.md`](reference/README.md).
|
|
|
572
475
|
|
|
573
476
|
See [`sources.md`](sources.md).
|
|
574
477
|
|
|
575
|
-
[path-a]: reference/workflow-path-a-orchestrated-teams.md
|
|
576
|
-
[path-b]: reference/workflow-path-b-task-harness.md
|
|
577
478
|
[path-code-rules]: ../../_shared/pr-loop/code-rules-gate.md
|
|
578
479
|
[path-scripts-readme]: ../../_shared/pr-loop/scripts/README.md
|