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.
Files changed (70) hide show
  1. package/_shared/pr-loop/scripts/config/preflight_constants.py +29 -8
  2. package/_shared/pr-loop/scripts/preflight.py +242 -20
  3. package/_shared/pr-loop/scripts/tests/test_preflight.py +362 -25
  4. package/_shared/pr-loop/scripts/tests/test_preflight_constants.py +9 -14
  5. package/hooks/blocking/code_rules_enforcer.py +269 -23
  6. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +157 -1
  7. package/hooks/config/test_unused_module_import_constants.py +48 -0
  8. package/hooks/config/unused_module_import_constants.py +41 -0
  9. package/package.json +1 -1
  10. package/skills/bg-agent/SKILL.md +69 -0
  11. package/skills/bugteam/CONSTRAINTS.md +10 -19
  12. package/skills/bugteam/PROMPTS.md +3 -3
  13. package/skills/bugteam/SKILL.md +103 -202
  14. package/skills/bugteam/SKILL_EVALS.md +75 -114
  15. package/skills/bugteam/reference/README.md +2 -4
  16. package/skills/bugteam/reference/design-rationale.md +3 -8
  17. package/skills/bugteam/reference/team-setup.md +11 -19
  18. package/skills/bugteam/reference/teardown-publish-permissions.md +2 -14
  19. package/skills/bugteam/scripts/config/__init__.py +0 -0
  20. package/skills/bugteam/scripts/config/reflow_skill_md_constants.py +12 -0
  21. package/skills/bugteam/scripts/reflow_skill_md.py +51 -47
  22. package/skills/bugteam/sources.md +1 -25
  23. package/skills/bugteam/test_skill_additions.py +4 -13
  24. package/skills/fresh-branch/SKILL.md +71 -0
  25. package/skills/gotcha/SKILL.md +73 -0
  26. package/skills/monitor-open-prs/SKILL.md +4 -37
  27. package/skills/monitor-open-prs/test_skill_contract.py +0 -5
  28. package/skills/pr-converge/SKILL.md +60 -1298
  29. package/skills/pr-converge/reference/convergence-gates.md +118 -0
  30. package/skills/pr-converge/reference/examples.md +76 -0
  31. package/skills/pr-converge/reference/fix-protocol.md +54 -0
  32. package/skills/pr-converge/reference/ground-rules.md +13 -0
  33. package/skills/pr-converge/reference/multi-pr-orchestration.md +204 -0
  34. package/skills/pr-converge/reference/per-tick.md +201 -0
  35. package/skills/pr-converge/reference/state-schema.md +19 -0
  36. package/skills/pr-converge/reference/stop-conditions.md +26 -0
  37. package/skills/pr-converge/scripts/README.md +36 -9
  38. package/skills/pr-converge/scripts/check_pr_mergeability.py +1 -2
  39. package/skills/pr-converge/scripts/config/pr_converge_constants.py +58 -5
  40. package/skills/pr-converge/scripts/config/reflow_skill_md_constants.py +13 -0
  41. package/skills/pr-converge/scripts/config/test_pr_converge_constants.py +0 -24
  42. package/skills/pr-converge/scripts/cursor-agents-continue.ahk +22 -2
  43. package/skills/pr-converge/scripts/fetch_bugbot_inline_comments.py +19 -59
  44. package/skills/pr-converge/scripts/fetch_bugbot_reviews.py +15 -61
  45. package/skills/pr-converge/scripts/fetch_claude_inline_comments.py +70 -0
  46. package/skills/pr-converge/scripts/fetch_claude_reviews.py +61 -0
  47. package/skills/pr-converge/scripts/fetch_copilot_inline_comments.py +19 -61
  48. package/skills/pr-converge/scripts/fetch_copilot_reviews.py +14 -74
  49. package/skills/pr-converge/scripts/reflow_skill_md.py +71 -50
  50. package/skills/pr-converge/scripts/reviewer_fetch_core.py +153 -0
  51. package/skills/pr-converge/scripts/reviewer_specs.py +98 -0
  52. package/skills/pr-converge/scripts/test_cursor_agents_continue.py +65 -0
  53. package/skills/pr-converge/scripts/test_fetch_bugbot_inline_comments.py +107 -6
  54. package/skills/pr-converge/scripts/test_fetch_bugbot_reviews.py +85 -6
  55. package/skills/pr-converge/scripts/test_fetch_claude_inline_comments.py +485 -0
  56. package/skills/pr-converge/scripts/test_fetch_claude_reviews.py +368 -0
  57. package/skills/pr-converge/scripts/test_fetch_copilot_inline_comments.py +74 -6
  58. package/skills/pr-converge/scripts/test_fetch_copilot_reviews.py +94 -8
  59. package/skills/pr-converge/scripts/test_reflow_skill_md.py +162 -0
  60. package/skills/pr-converge/scripts/test_reviewer_fetch_core.py +448 -0
  61. package/skills/pr-converge/scripts/test_reviewer_specs.py +107 -0
  62. package/skills/pr-converge/workflows/schedule-wakeup-loop.md +24 -22
  63. package/skills/bugteam/reference/workflow-path-a-orchestrated-teams.md +0 -113
  64. package/skills/bugteam/reference/workflow-path-b-task-harness.md +0 -48
  65. package/skills/bugteam/test_team_lifecycle.py +0 -103
  66. package/skills/monitor-open-prs/test_team_lifecycle.py +0 -46
  67. package/skills/pr-converge/scripts/open_followup_copilot_pr.py +0 -136
  68. package/skills/pr-converge/scripts/test_open_followup_copilot_pr.py +0 -236
  69. package/skills/pr-converge/test_team_lifecycle.py +0 -56
  70. 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
- - **Path A agent teams required, not parallel subagents from the lead without `TeamCreate`.** On Path A, the skill MUST use Claude Code's agent teams feature (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`). Spawning `code-quality-agent` and `clean-coder` as parallel **Agents** with `team_name` from the lead is the supported pattern. Spawning ad-hoc `generalPurpose` workers in place of those roles = fail. **Path B** does not use `TeamCreate`; it uses **`Task`** carrying the same Path A spawn contracts per [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) (AUDIT/FIX spawn; when the host rejects `subagent_type="clean-coder"`, apply **Path B Cursor `Task` registry**). Not a substitute for skipping `code-quality-agent` / `clean-coder` work.
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 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.
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 teammate's spawn prompt contains only the PR scope, audit rubric, and the current loop number. Prior loop history stays in the lead.
19
- - **Targeted fixes.** Each fix teammate sees ONLY the most recent audit's findings. Prior loops are invisible to the fix teammate.
20
- - **Opus 4.7 at xhigh effort for both teammates.** 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).
21
- - **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.
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, gated by `team_owned`.** 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. Step 4 calls `TeamDelete` **only when `team_owned == true`** (this invocation called `TeamCreate` itself). When `team_owned == false` (lifecycle `attach`, or `auto` after the runtime's `Already leading team` fallback), the orchestrator that originally created the team owns teardown — see [Team lifecycle](SKILL.md#team-lifecycle-path-a-only).
25
- - **Orchestrators must use `attach` mode, not `owned`.** When `/bugteam` runs inside an orchestrator that is itself managing a long-lived team across PRs (`pr-converge` multi-PR mode, `monitor-open-prs`), the orchestrator passes `BUGTEAM_TEAM_LIFECYCLE=attach` and `BUGTEAM_TEAM_NAME=<existing>`. `owned` mode under such an orchestrator would either error out (the session already leads a team) or, worse, tear down the orchestrator's team mid-sweep on the first invocation's Step 4. `auto` is the safe default for ambiguous callers; `attach` is the explicit-orchestrator contract.
26
- - **Cleanup the per-team scoped temp directory on exit, gated by `team_owned`.** When `team_owned == true`, the resolved `<team_temp_dir>` is removed entirely so no loop patches leak between runs. When `team_owned == false`, only this invocation's per-PR subfolders (`<team_temp_dir>/pr-<N>/`) are removed; the orchestrator-owned parent stays so the next attached invocation can write its own per-PR subfolders without colliding.
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 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.
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: <team_temp_dir>/pr-<N>/loop-<L>.patch (same path as gh pr diff redirect in AUDIT)</diff_path>
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
- Write the outcome XML below to .bugteam-pr<N>-loop<L>.outcomes.xml inside
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
 
@@ -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/**`. **Path A** when
7
- `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (orchestrated teams, `TeamCreate`).
8
- **Path B** otherwise (Task harness workflow in
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
- **Path routing** picks **Path A** (orchestrated teams) vs **Path B** (Task
22
- harness). Harness execution `TeamCreate`, `Agent`/`Task` spawns,
23
- `SendMessage`, `TeamDelete`, who runs Step 2.5 `gh api` — lives only in
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 — Path harness + loop state
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 + path harness applied
101
+ [ ] Step 2: loop state set
193
102
  [ ] Step 3: cycle complete (converged | cap reached | stuck | error)
194
- [ ] Step 4: team torn down + working tree clean
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/grant_project_claude_permis \
205
- sions.py"
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 `<team_temp_dir>/pr-<N>/`.
227
- 2. Run `git worktree add "<team_temp_dir>/pr-<N>/worktree" origin/<headRef>`.
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
- Teammates or Task workers for a PR operate inside that PR's worktree. Step 4
231
- teardown runs `git worktree remove "<team_temp_dir>/pr-<N>/worktree"` for each
232
- PR, then path-specific harness teardown per
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
- Path A also resolves the team lifecycle here per [Team
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
- starting_sha="$(git rev-parse HEAD)"
262
- team_name="bugteam-pr-<number>-<YYYYMMDDHHMMSS>"
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:** Path A vs Path B
275
- [`reference/workflow-path-a-orchestrated-teams.md`][path-a] § Step 2.5 and
276
- [`reference/workflow-path-b-task-harness.md`][path-b] § Step 2.5. Payloads and
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 teammate cwd immediately
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, reusing the same team across
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
- --jq '[.[] | select(.body | startswith("## /bugteam loop "))] |
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 "<team_temp_dir>/pr-<N>"
436
- gh pr diff <N> -R <owner>/<repo> > "<team_temp_dir>/pr-<N>/loop-<L>.patch"
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 and shutdown:** Path A —
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
- Fresh spawn each loop; Path A teammate context excludes lead history
445
- ([`sources.md`](sources.md) § Teammate context isolation). Path B: fresh Task
446
- per loop for the same clean-room intent. [`PROMPTS.md`](PROMPTS.md): XML +
447
- outcome schema. Lead reads `.bugteam-pr<N>-loop<L>.outcomes.xml`, fills
448
- `loop_comment_index`.
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 spawns in
454
- one assistant message (parallel): Path A — three `Agent` calls; Path B —
455
- three `Task` calls full rules in the workflow files § parallel auditors.
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
- `<team_temp_dir>/pr-<N>/loop-<L>-b.outcomes.xml` and `...-c...`); merge key
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. Shutdown order: Path A
462
- workflow § parallel auditors; Path B: await all three Tasks.
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 and shutdown:** Path A —
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
- Pass finding comment URLs/ids from `loop_comment_index` in XML. Replies: `Fixed
471
- in <sha>` or `Could not address this loop: <reason>`.
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
- [`PROMPTS.md`](PROMPTS.md): fix XML + schema. Verify: `git rev-parse HEAD`
474
- advanced; `git fetch origin <branch> && git rev-parse origin/<branch>` matches
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 teammate could not address findings`.
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
- "<team_temp_dir>/pr-<N>/worktree"` (from Step 1) before tearing down the team
482
- harness — tolerate already-removed worktrees.
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
- - `team_owned=true` remove the full `<team_temp_dir>`:
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
- ```bash
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'<team_temp_dir>', **({'onexc': h} if sys.version_info >= (3, 12)
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/revoke_project_claude_permi \
537
- ssions.py"
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