claude-dev-env 1.34.1 → 1.36.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/agents/clean-coder.md +109 -1
- package/agents/docs-agent.md +1 -1
- package/agents/project-docs-analyzer.md +0 -1
- package/agents/skill-to-agent-converter.md +0 -1
- package/bin/install.mjs +28 -8
- package/bin/install.test.mjs +9 -1
- package/commands/initialize.md +0 -1
- package/commands/readability-review.md +4 -4
- package/commands/review-plan.md +2 -4
- package/commands/stubcheck.md +1 -2
- package/docs/CODE_RULES.md +3 -0
- package/docs/agents-md-alignment-plan.md +123 -0
- package/hooks/blocking/code_rules_enforcer.py +686 -60
- package/hooks/blocking/es_exe_path_rewriter.py +10 -4
- package/hooks/blocking/test_code_rules_enforcer.py +273 -39
- package/hooks/blocking/test_code_rules_enforcer_annotations.py +97 -0
- package/hooks/blocking/test_code_rules_enforcer_banned_identifier.py +106 -0
- package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +173 -0
- package/hooks/blocking/test_code_rules_enforcer_collection_prefix.py +328 -0
- package/hooks/blocking/test_code_rules_enforcer_config_path.py +0 -20
- package/hooks/blocking/test_code_rules_enforcer_constant_equality.py +33 -11
- package/hooks/blocking/test_code_rules_enforcer_existence_checks.py +0 -18
- package/hooks/blocking/test_code_rules_enforcer_hardcoded_user_path.py +291 -0
- package/hooks/blocking/test_code_rules_enforcer_inline_literal_collections.py +155 -0
- package/hooks/blocking/test_code_rules_enforcer_loop_variable_naming.py +194 -0
- package/hooks/blocking/test_code_rules_enforcer_naming_pattern.py +49 -13
- package/hooks/blocking/test_code_rules_enforcer_skip_decorators.py +0 -26
- package/hooks/blocking/test_code_rules_enforcer_string_magic.py +234 -0
- package/hooks/blocking/test_code_rules_enforcer_sys_path_insert.py +157 -0
- package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +244 -0
- package/hooks/blocking/test_es_exe_path_rewriter.py +81 -3
- package/hooks/blocking/test_windows_rmtree_blocker.py +120 -8
- package/hooks/blocking/windows_rmtree_blocker.py +23 -6
- package/hooks/config/banned_identifiers_constants.py +24 -0
- package/hooks/config/hardcoded_user_path_constants.py +12 -0
- package/hooks/config/hook_log_extractor_constants.py +1 -1
- package/hooks/config/pre_tool_use_stdin.py +48 -0
- package/hooks/config/setup_project_paths_constants.py +4 -0
- package/hooks/config/stuttering_check_config.py +14 -0
- package/hooks/config/stuttering_import_binding_constants.py +11 -0
- package/hooks/config/sys_path_insert_constants.py +4 -0
- package/hooks/config/test_banned_identifiers_constants.py +48 -0
- package/hooks/config/test_hardcoded_user_path_constants.py +78 -0
- package/hooks/config/test_hook_log_extractor_constants.py +3 -3
- package/hooks/config/test_pre_tool_use_stdin.py +80 -0
- package/hooks/config/unused_module_import_constants.py +7 -0
- package/hooks/config/windows_rmtree_blocker_constants.py +3 -0
- package/hooks/diagnostic/hook_log_stop_wrapper.py +7 -4
- package/hooks/git-hooks/config.py +3 -3
- package/hooks/git-hooks/test_gate_utils.py +10 -10
- package/hooks/mypy.ini +2 -0
- package/package.json +1 -1
- package/rules/gh-paginate.md +125 -0
- package/skills/bugteam/CONSTRAINTS.md +12 -6
- package/skills/bugteam/PROMPTS.md +0 -39
- package/skills/bugteam/SKILL.md +93 -125
- package/skills/bugteam/SKILL_EVALS.md +25 -23
- package/skills/bugteam/reference/README.md +2 -0
- package/skills/bugteam/reference/audit-and-teammates.md +2 -2
- package/skills/bugteam/reference/copilot-gap-analysis.md +12 -0
- package/skills/bugteam/reference/teardown-publish-permissions.md +1 -1
- package/skills/bugteam/reference/workflow-path-a-orchestrated-teams.md +113 -0
- package/skills/bugteam/reference/workflow-path-b-task-harness.md +48 -0
- package/skills/bugteam/test_skill_additions.py +13 -4
- package/skills/bugteam/test_team_lifecycle.py +94 -0
- package/skills/findbugs/SKILL.md +3 -3
- package/skills/fixbugs/SKILL.md +4 -4
- package/skills/monitor-open-prs/SKILL.md +32 -2
- package/skills/monitor-open-prs/test_team_lifecycle.py +46 -0
- package/skills/pr-converge/SKILL.md +576 -95
- package/skills/pr-converge/scripts/README.md +145 -0
- package/skills/pr-converge/scripts/caller-window-pid.ps1 +86 -0
- package/skills/pr-converge/scripts/check_pr_mergeability.py +79 -0
- package/skills/pr-converge/scripts/config/pr_converge_constants.py +65 -0
- package/skills/pr-converge/scripts/config/test_pr_converge_constants.py +176 -0
- package/skills/pr-converge/scripts/cursor-agents-continue-caller.cmd +9 -0
- package/skills/pr-converge/scripts/cursor-agents-continue-stop-others.ps1 +16 -0
- package/skills/pr-converge/scripts/cursor-agents-continue.ahk +172 -0
- package/skills/pr-converge/scripts/cursor-agents-continue.cmd +2 -0
- package/skills/pr-converge/scripts/evict_cached_config_modules.py +20 -0
- package/skills/pr-converge/scripts/fetch_bugbot_inline_comments.py +110 -0
- package/skills/pr-converge/scripts/fetch_bugbot_reviews.py +103 -0
- package/skills/pr-converge/scripts/fetch_copilot_inline_comments.py +112 -0
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +121 -0
- package/skills/pr-converge/scripts/mark_pr_ready.py +54 -0
- package/skills/pr-converge/scripts/open_followup_copilot_pr.py +136 -0
- package/skills/pr-converge/scripts/post-bugbot-run.helpers.ps1 +49 -0
- package/skills/pr-converge/scripts/post-bugbot-run.ps1 +33 -0
- package/skills/pr-converge/scripts/reply_to_inline_comment.py +84 -0
- package/skills/pr-converge/scripts/request_copilot_review.py +71 -0
- package/skills/pr-converge/scripts/resolve_pr_head.py +58 -0
- package/skills/pr-converge/scripts/review_field_helpers.py +43 -0
- package/skills/pr-converge/scripts/test_check_pr_mergeability.py +126 -0
- package/skills/pr-converge/scripts/test_evict_cached_config_modules.py +22 -0
- package/skills/pr-converge/scripts/test_fetch_bugbot_inline_comments.py +342 -0
- package/skills/pr-converge/scripts/test_fetch_bugbot_reviews.py +220 -0
- package/skills/pr-converge/scripts/test_fetch_copilot_inline_comments.py +372 -0
- package/skills/pr-converge/scripts/test_fetch_copilot_reviews.py +280 -0
- package/skills/pr-converge/scripts/test_mark_pr_ready.py +69 -0
- package/skills/pr-converge/scripts/test_open_followup_copilot_pr.py +236 -0
- package/skills/pr-converge/scripts/test_post_bugbot_run.py +195 -0
- package/skills/pr-converge/scripts/test_reply_to_inline_comment.py +159 -0
- package/skills/pr-converge/scripts/test_request_copilot_review.py +101 -0
- package/skills/pr-converge/scripts/test_resolve_pr_head.py +79 -0
- package/skills/pr-converge/scripts/test_review_field_helpers.py +80 -0
- package/skills/pr-converge/scripts/test_trigger_bugbot.py +139 -0
- package/skills/pr-converge/scripts/test_view_pr_context.py +111 -0
- package/skills/pr-converge/scripts/trigger_bugbot.py +77 -0
- package/skills/pr-converge/scripts/view_pr_context.py +47 -0
- package/skills/pr-converge/test_team_lifecycle.py +47 -0
- package/skills/pr-converge/workflows/ahk-auto-continue-loop.md +108 -0
- package/skills/pr-converge/workflows/schedule-wakeup-loop.md +37 -0
- package/skills/qbug/SKILL.md +4 -4
- package/skills/qbug/test_qbug_skill_post_fix_audit.py +2 -2
- package/skills/resume-review/SKILL.md +261 -0
- package/agents/agent-writer.md +0 -157
- package/agents/config-centralizer.md +0 -686
- package/agents/config-extraction-agent.md +0 -225
- package/agents/doc-orchestrator.md +0 -47
- package/agents/docx-agent.md +0 -211
- package/agents/magic-value-eliminator-agent.md +0 -72
- package/agents/mandatory-agent-workflow-agent.md +0 -88
- package/agents/parallel-workflow-coordinator.md +0 -779
- package/agents/pdf-agent.md +0 -302
- package/agents/project-context-loader.md +0 -238
- package/agents/readability-review-agent.md +0 -76
- package/agents/refactoring-specialist.md +0 -69
- package/agents/right-sized-engineer.md +0 -129
- package/agents/session-continuity-manager.md +0 -53
- package/agents/stub-detector-agent.md +0 -140
- package/agents/tdd-test-writer.md +0 -62
- package/agents/test-data-builder.md +0 -68
- package/agents/tooling-builder.md +0 -78
- package/agents/validation-expert.md +0 -71
- package/agents/xlsx-agent.md +0 -169
- package/skills/bugteam/scripts/README.md +0 -58
- package/skills/bugteam/scripts/_claude_permissions_common.py +0 -219
- package/skills/bugteam/scripts/bugteam_code_rules_gate.py +0 -633
- package/skills/bugteam/scripts/bugteam_fix_hookspath.py +0 -260
- package/skills/bugteam/scripts/bugteam_preflight.py +0 -201
- package/skills/bugteam/scripts/config/bugteam_fix_hookspath_constants.py +0 -17
- package/skills/bugteam/scripts/grant_project_claude_permissions.py +0 -109
- package/skills/bugteam/scripts/revoke_project_claude_permissions.py +0 -135
- package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +0 -271
- package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +0 -267
- package/skills/bugteam/scripts/test_bugteam_preflight.py +0 -189
- package/skills/bugteam/scripts/test_claude_permissions_common.py +0 -44
- /package/skills/{bugteam → pr-converge}/scripts/config/__init__.py +0 -0
package/skills/bugteam/SKILL.md
CHANGED
|
@@ -1,34 +1,59 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bugteam
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1. Triggers: '/bugteam',
|
|
12
|
-
'run the bug team', 'auto-fix the PR until clean', 'loop audit and fix'.
|
|
4
|
+
Open pull request audit–fix until convergence: CODE_RULES gate, clean-room
|
|
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**
|
|
7
|
+
when `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (orchestrated teams, `TeamCreate`).
|
|
8
|
+
**Path B** otherwise (Task harness — workflow in `reference/workflow-path-b-task-harness.md`).
|
|
9
|
+
**This `SKILL.md` holds only shared steps**; per-path harness lives in `reference/workflow-path-*.md`.
|
|
10
|
+
Triggers: '/bugteam', 'run the bug team', 'auto-fix the PR until clean', 'loop audit and fix'.
|
|
13
11
|
---
|
|
14
12
|
|
|
15
13
|
# Bugteam
|
|
16
14
|
|
|
17
|
-
**Core principle:**
|
|
15
|
+
**Core principle:** Audit–fix until convergence. **Bugfind:** `code-quality-agent`, fresh context each loop. **Bugfix:** `clean-coder`. Hard cap: 10 audit loops. Grant `.claude/**` at start, revoke always at end.
|
|
18
16
|
|
|
19
|
-
|
|
17
|
+
**Path routing** picks **Path A** (orchestrated teams) vs **Path B** (Task harness). Harness execution — `TeamCreate`, `Agent`/`Task` spawns, `SendMessage`, `TeamDelete`, who runs Step 2.5 `gh api` — lives only in [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) and [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md). Verbatim doc quotes and URLs: [`sources.md`](sources.md).
|
|
18
|
+
|
|
19
|
+
## Path routing (mandatory first branch)
|
|
20
|
+
|
|
21
|
+
At `/bugteam` entry, evaluate **once** (same rule as pr-converge §Team infrastructure detection):
|
|
22
|
+
|
|
23
|
+
- **Path A** — `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` set and equals **`1`** after trim → load and follow [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) for every harness step (with this `SKILL.md` for shared material).
|
|
24
|
+
- **Path B** — otherwise → load and follow [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) for every harness step (with this `SKILL.md` for shared material).
|
|
25
|
+
|
|
26
|
+
Shared material is **everything else in this file** plus [`PROMPTS.md`](PROMPTS.md), [`EXAMPLES.md`](EXAMPLES.md), [`CONSTRAINTS.md`](CONSTRAINTS.md) — agent types, models, XML, gates, cycle state machine, Step 2.5 payload shapes, shared teardown `rmtree`, revoke, final report.
|
|
27
|
+
|
|
28
|
+
## Team lifecycle (Path A only)
|
|
29
|
+
|
|
30
|
+
The `TeamCreate` / `TeamDelete` pair has historically been bound to a single `/bugteam` invocation. That coupling fails when an orchestrator (`pr-converge` multi-PR mode, `monitor-open-prs`) needs to call `/bugteam` repeatedly inside one parent session: only one team can be led at a time, and a missed Step 4 leaks the team. To decouple, every Path A invocation reads `BUGTEAM_TEAM_LIFECYCLE` (defaults to `auto`) and may also read `BUGTEAM_TEAM_NAME`.
|
|
31
|
+
|
|
32
|
+
| Mode | Step 2 behavior | Step 4 behavior | Use case |
|
|
33
|
+
| --- | --- | --- | --- |
|
|
34
|
+
| `owned` | `TeamCreate(<computed_team_name>)`. If the runtime returns `Already leading team "<existing>". A leader can only manage one team at a time.` → **error**: `Already leading team <existing>; rerun with BUGTEAM_TEAM_LIFECYCLE=attach BUGTEAM_TEAM_NAME=<existing>`. | `TeamDelete()` (lead-owned). | Pre-decoupling behavior. Use only when you know the session leads no other team. |
|
|
35
|
+
| `attach` | Require `BUGTEAM_TEAM_NAME`. Treat that team as already-led; do **not** call `TeamCreate`. | **Skip** `TeamDelete` — the orchestrator owns teardown. | Orchestrators (pr-converge multi-PR, monitor-open-prs) that explicitly created a team and will tear it down themselves. |
|
|
36
|
+
| `auto` (**default: `auto`**) | Try `TeamCreate(<computed_team_name>)`. On `Already leading team "<existing>"` → parse `<existing>`, attach (do **not** call `TeamCreate` again), set `team_owned=false`. On success → set `team_owned=true`. | If `team_owned=true` → `TeamDelete()`. Else → **skip** `TeamDelete`. | All callers when in doubt. Solo invocations behave like `owned`; nested or repeated invocations attach safely. |
|
|
37
|
+
|
|
38
|
+
**`team_owned` flag** — set in Step 2 by all three modes (`owned` always `true`; `attach` always `false`; `auto` reflects the `TeamCreate` outcome). Read in Step 4 to decide whether to call `TeamDelete`. The same flag also gates `<team_temp_dir>` `rmtree`: when `team_owned=false`, only the per-PR subfolders this invocation created (`<team_temp_dir>/pr-<N>/`) are removed; the orchestrator's parent directory survives.
|
|
39
|
+
|
|
40
|
+
**Path B note:** Path B does not use `TeamCreate` / `TeamDelete`, so `BUGTEAM_TEAM_LIFECYCLE` is read but only its `team_temp_dir` cleanup behavior applies. `team_owned` is treated as `true` by default in Path B; orchestrators driving Path B that share a temp directory should set `BUGTEAM_TEAM_LIFECYCLE=attach` so the per-PR subfolder cleanup rule applies.
|
|
20
41
|
|
|
21
42
|
## Contents
|
|
22
43
|
|
|
23
44
|
Orchestration lives here; companion files hold prompts, invariants, examples, citations, and domain reference notes. Scan this list before a partial read.
|
|
24
45
|
|
|
25
|
-
-
|
|
46
|
+
- [Path routing](#path-routing-mandatory-first-branch) — Path A vs Path B
|
|
47
|
+
- [Team lifecycle](#team-lifecycle-path-a-only) — `owned` / `attach` / `auto` modes; orchestrator-owned teams
|
|
48
|
+
- [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) — Path A harness (orchestrated teams)
|
|
49
|
+
- [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) — Path B harness (Task harness)
|
|
50
|
+
- When this skill applies — refusal cases and trigger conditions
|
|
26
51
|
- Utility scripts — pre-flight (`scripts/`, executed not inlined)
|
|
27
52
|
- Pre-audit gate — `validate_content` before each AUDIT
|
|
28
53
|
- The Process — checklist + Steps 0–6
|
|
29
54
|
- Step 0 — Grant project permissions
|
|
30
55
|
- Step 1 — Resolve PR scope
|
|
31
|
-
- Step 2 —
|
|
56
|
+
- Step 2 — Path harness + loop state
|
|
32
57
|
- Step 2.5 — PR comment lifecycle (per-loop review + fix replies)
|
|
33
58
|
- Step 3 — Cycle (AUDIT ↔ FIX, exits)
|
|
34
59
|
- Step 4 — Teardown + clean tree
|
|
@@ -47,20 +72,19 @@ Orchestration lives here; companion files hold prompts, invariants, examples, ci
|
|
|
47
72
|
|
|
48
73
|
Refusals — first match wins; respond with the quoted line exactly and stop:
|
|
49
74
|
|
|
50
|
-
- **Agent teams not enabled.** Check `claude config get env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` and `~/.claude/settings.json`. If neither is `"1"`: `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.`
|
|
51
75
|
- **No PR or upstream diff.** `No PR or upstream diff. /bugteam needs a target.`
|
|
52
76
|
- **Dirty tree.** `Uncommitted changes detected. Stash, commit, or revert before /bugteam.`
|
|
53
77
|
- **Missing subagents.** Before Step 0, confirm `code-quality-agent` and `clean-coder` exist. Else: `Required subagent type <name> not installed. /bugteam needs both code-quality-agent and clean-coder available.`
|
|
54
|
-
- **Lead role must be held by the orchestrator.** Run /bugteam in the session that received the user's command.
|
|
78
|
+
- **Lead role must be held by the orchestrator.** Run /bugteam in the session that received the user's command. **Path A:** lead calls `TeamCreate` per [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md); runtime may return `Already leading team "<name>". A leader can only manage one team at a time.` **Path B:** lead runs the Task harness per [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md); no `TeamCreate`.
|
|
55
79
|
|
|
56
80
|
## Utility scripts
|
|
57
81
|
|
|
58
|
-
Shell-heavy steps live under `scripts/` (run, do not paste into context). Utility scripts are **executed**, not loaded as primary context ([`sources.md`](sources.md) § Progressive disclosure and utility scripts).
|
|
82
|
+
Shell-heavy steps live under [`_shared/pr-loop/scripts/`](../../_shared/pr-loop/scripts/) (run, do not paste into context). Utility scripts are **executed**, not loaded as primary context ([`sources.md`](sources.md) § Progressive disclosure and utility scripts).
|
|
59
83
|
|
|
60
84
|
### Pre-flight (before Step 0)
|
|
61
85
|
|
|
62
86
|
```bash
|
|
63
|
-
python "${CLAUDE_SKILL_DIR}/scripts/
|
|
87
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/preflight.py"
|
|
64
88
|
```
|
|
65
89
|
|
|
66
90
|
Non-zero → fix before grant. `BUGTEAM_PREFLIGHT_SKIP=1` emergency only. `--pre-commit` if `.pre-commit-config.yaml` exists.
|
|
@@ -68,10 +92,10 @@ Non-zero → fix before grant. `BUGTEAM_PREFLIGHT_SKIP=1` emergency only. `--pre
|
|
|
68
92
|
**Auto-remediation for `core.hooksPath`:** when preflight fails with stderr containing `core.hooksPath` (the message starts with `bugteam_preflight: core.hooksPath is`, or `Git-side CODE_RULES enforcement is not active`), Claude must auto-invoke the fix script — do not fall through to `AskUserQuestion`, do not punt to the user, do not ask for confirmation:
|
|
69
93
|
|
|
70
94
|
```bash
|
|
71
|
-
python "${CLAUDE_SKILL_DIR}/scripts/
|
|
95
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/fix_hookspath.py"
|
|
72
96
|
```
|
|
73
97
|
|
|
74
|
-
The fix script removes any non-canonical local-scope override on the active repository, sets the global `core.hooksPath` to `~/.claude/hooks/git-hooks` if missing or wrong, and re-runs `
|
|
98
|
+
The fix script removes any non-canonical local-scope override on the active repository, sets the global `core.hooksPath` to `~/.claude/hooks/git-hooks` if missing or wrong, and re-runs `preflight.py`. Its exit code becomes the preflight outcome. Exit 0 → continue to Step 0. Non-zero only when the canonical hooks directory is missing (run `npx claude-dev-env .` first) or `git config --global` writes are blocked. Other preflight failures (pytest, pre-commit) still require manual fixes — the auto-remediation only applies to the `core.hooksPath` failure mode.
|
|
75
99
|
|
|
76
100
|
## The Process
|
|
77
101
|
|
|
@@ -80,10 +104,8 @@ The fix script removes any non-canonical local-scope override on the active repo
|
|
|
80
104
|
```
|
|
81
105
|
[ ] Step 0: project permissions granted
|
|
82
106
|
[ ] Step 1: PR scope resolved
|
|
83
|
-
[ ] Step 2:
|
|
84
|
-
[ ] Step 2.6: INITIAL standards review against cumulative PR diff
|
|
107
|
+
[ ] Step 2: loop state set + path harness applied
|
|
85
108
|
[ ] Step 3: cycle complete (converged | cap reached | stuck | error)
|
|
86
|
-
[ ] Step 3.5: FINAL standards review against cumulative PR diff
|
|
87
109
|
[ ] Step 4: team torn down + working tree clean
|
|
88
110
|
[ ] Step 4.5: PR description rewritten (or skip warning logged)
|
|
89
111
|
[ ] Step 5: project permissions revoked
|
|
@@ -93,7 +115,7 @@ The fix script removes any non-canonical local-scope override on the active repo
|
|
|
93
115
|
### Step 0: Grant project permissions (once, first)
|
|
94
116
|
|
|
95
117
|
```bash
|
|
96
|
-
python "${CLAUDE_SKILL_DIR}/scripts/grant_project_claude_permissions.py"
|
|
118
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/grant_project_claude_permissions.py"
|
|
97
119
|
```
|
|
98
120
|
|
|
99
121
|
`${CLAUDE_SKILL_DIR}` is host-substituted before the shell runs (unlike normal env expansion). Idempotent writes to `~/.claude/settings.json` from repo root. Non-zero → stop. Revoke in Step 5 on every exit path.
|
|
@@ -112,42 +134,25 @@ For each PR in all_prs:
|
|
|
112
134
|
2. Run `git worktree add "<team_temp_dir>/pr-<N>/worktree" origin/<headRef>`.
|
|
113
135
|
3. Record the absolute worktree path alongside the PR's other fields.
|
|
114
136
|
|
|
115
|
-
Teammates
|
|
116
|
-
|
|
117
|
-
### Step 2: Create the agent team
|
|
137
|
+
Teammates or Task workers for a PR operate inside that PR's worktree. Step 4 teardown runs `git worktree remove "<team_temp_dir>/pr-<N>/worktree"` for each PR, then path-specific harness teardown per [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) or [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § Step 4.
|
|
118
138
|
|
|
119
|
-
|
|
139
|
+
### Step 2: Path harness + loop state
|
|
120
140
|
|
|
121
|
-
|
|
122
|
-
TeamCreate(
|
|
123
|
-
team_name="<team_name>",
|
|
124
|
-
description="Bugteam audit/fix loop for PR <number> (<owner>/<repo>)",
|
|
125
|
-
agent_type="team-lead"
|
|
126
|
-
)
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
**Team name:** For a single-PR invocation use `bugteam-pr-<number>-<YYYYMMDDHHMMSS>`. For a multi-PR invocation use `bugteam-<YYYYMMDDHHMMSS>`. The timestamp is captured once at team-creation time. Apply the no-PR fallback (`bugteam-<sanitized-head>-<YYYYMMDDHHMMSS>`) only when no PR resolves at all. `TeamCreate` implements natural-language team creation ([`sources.md`](sources.md) § Team creation in natural language).
|
|
130
|
-
|
|
131
|
-
**Sanitize head branch (no-PR only):** replace characters outside `[A-Za-z0-9._-]` with `-` (e.g. `feat/foo*bar` → `feat-foo-bar`). Apply once; reuse everywhere below.
|
|
132
|
-
|
|
133
|
-
**`<team_temp_dir>`:** `Path(tempfile.gettempdir()) / team_name` (lead resolves once to an absolute path; every shell gets that literal string).
|
|
141
|
+
Apply the path you chose in [Path routing](#path-routing-mandatory-first-branch): **Path A** — [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) § Step 2 (`TeamCreate`, team name, `team_temp_dir`, roles, optional Groq FIX, `--bugbot-retrigger`). **Path B** — [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § Step 2 (no `TeamCreate` / `TeamDelete`; same worktrees and variables).
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
**Optional Groq-backed FIX path (explicit opt-in only):** the default flow above always uses Opus teammates. A separate optional path exists only when the user explicitly sets `BUGTEAM_FIX_IMPLEMENTER=groq-coder` before invocation: spawn the FIX teammate with `subagent_type="groq-coder"`. Before Step 3, `groq_bugteam.py` loads `packages/claude-dev-env/.env` when that file exists (gitignored; start from `packages/claude-dev-env/.env.example`). If `GROQ_API_KEY` is still unset after that load, stop and prompt the user to create `packages/claude-dev-env/.env` from the example path above—do not continue the Groq path without a key. Any other `BUGTEAM_FIX_IMPLEMENTER` value (or unset) keeps `clean-coder` on Opus. The FIX spawn XML in [`PROMPTS.md`](PROMPTS.md) is identical for both implementers.
|
|
138
|
-
|
|
139
|
-
**`--bugbot-retrigger` flag:** when present on the `/bugteam` invocation, after every successful FIX push in Step 3, post an additional `bugbot run` issue comment via the Step 2.5 issue-comments fallback endpoint (`POST .../issues/{issue}/comments`) to re-trigger Cursor's bugbot on the new commit. Omit when the flag is absent.
|
|
143
|
+
Path A also resolves the team lifecycle here per [Team lifecycle](#team-lifecycle-path-a-only): pick the mode (`owned` / `attach` / `auto`) from `BUGTEAM_TEAM_LIFECYCLE`, set `team_name` (computed for `owned`/`auto` create paths; required `BUGTEAM_TEAM_NAME` for `attach` and `auto`'s attach branch), and set `team_owned` (`true` when `TeamCreate` succeeded in this invocation; `false` when attaching to an existing team). Step 4 reads `team_owned` to decide whether to call `TeamDelete`.
|
|
140
144
|
|
|
141
145
|
**Loop state (lead; not a single script):**
|
|
142
146
|
|
|
143
147
|
```bash
|
|
144
148
|
loop_count=0
|
|
145
149
|
last_action="fresh"
|
|
146
|
-
last_findings=""
|
|
150
|
+
last_findings='{"total": 0}'
|
|
147
151
|
audit_log=""
|
|
148
152
|
starting_sha="$(git rev-parse HEAD)"
|
|
149
153
|
team_name="bugteam-pr-<number>-<YYYYMMDDHHMMSS>"
|
|
150
154
|
team_temp_dir="<absolute-path>/<team_name>"
|
|
155
|
+
team_owned="true" # set by Step 2 lifecycle resolution; see Team lifecycle table
|
|
151
156
|
loop_comment_index=""
|
|
152
157
|
```
|
|
153
158
|
|
|
@@ -155,7 +160,7 @@ loop_comment_index=""
|
|
|
155
160
|
|
|
156
161
|
### Step 2.5: PR comments (one review per loop)
|
|
157
162
|
|
|
158
|
-
|
|
163
|
+
**Who posts:** Path A vs Path B — [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) § Step 2.5 and [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § Step 2.5. Payloads and endpoints below are identical for both paths.
|
|
159
164
|
|
|
160
165
|
Order: audit → buffer → validate anchors vs diff → single review POST. Review body states counts; zero findings → still one review, `comments: []`, body `## /bugteam loop <N> audit: 0P0 / 0P1 / 0P2 → clean`.
|
|
161
166
|
|
|
@@ -205,28 +210,27 @@ jq -n \
|
|
|
205
210
|
|
|
206
211
|
**Endpoints:** `POST .../pulls/{pull}/reviews`; `POST .../pulls/{pull}/comments/{id}/replies`; fallback `POST .../issues/{issue}/comments` (`issue` = PR number).
|
|
207
212
|
|
|
208
|
-
### Step 2.6: INITIAL standards review (once, before Loop 1 audit)
|
|
209
|
-
|
|
210
|
-
Run BEFORE the first pre-audit gate fires. Spawn a fresh `code-quality-agent`
|
|
211
|
-
teammate inside the same team and drive it through the K–N addendum (see
|
|
212
|
-
PROMPTS.md `<copilot_derived_addendum_source>`). The teammate audits the
|
|
213
|
-
cumulative PR diff (`gh pr diff <N>`) instead of a single loop's incremental
|
|
214
|
-
patch; clean-room context is preserved by the same agent-team isolation as
|
|
215
|
-
the per-loop bugfind teammate. Findings are posted using the same Step 2.5
|
|
216
|
-
review-shape with body `## /bugteam INITIAL standards review against PR #<N>
|
|
217
|
-
cumulative diff: <P0>P0 / <P1>P1 / <P2>P2`. Findings advance the audit/fix
|
|
218
|
-
cycle exactly as if they had been raised in Loop 1: the lead increments
|
|
219
|
-
`loop_count` to 1, sets `last_action = "audited"` with the merged
|
|
220
|
-
`last_findings`, and Step 3 begins on the FIX branch. When the INITIAL
|
|
221
|
-
review returns zero findings, `loop_count` stays at 0 and Step 3 begins on
|
|
222
|
-
the AUDIT branch as before. Failure on this phase logs the error and
|
|
223
|
-
proceeds to Step 3 unchanged so the legacy A–J cycle still runs.
|
|
224
|
-
|
|
225
213
|
### Step 3: The cycle
|
|
226
214
|
|
|
227
215
|
Run the AUDIT-FIX cycle for each PR in all_prs, reusing the same team across PRs. The 10-loop cap applies per PR. Exit reasons (converged, cap reached, stuck, error) are tracked per PR; the final report lists one outcome line per PR.
|
|
228
216
|
|
|
229
|
-
**Gate:** `validate_content` / `hooks/blocking/code_rules_enforcer.py` on PR-scoped files before every AUDIT (`
|
|
217
|
+
**Gate:** `validate_content` / `hooks/blocking/code_rules_enforcer.py` on PR-scoped files before every AUDIT (`_shared/pr-loop/scripts/code_rules_gate.py`). Lead runs gate; clean-coder clears failures; then bugfind audits.
|
|
218
|
+
|
|
219
|
+
**Pre-cycle: walk prior bugteam reviews end-first** (once per PR, after Step 2 and before iteration begins, when `last_action == "fresh"`). A re-invocation of `/bugteam` on a PR with prior loops detects whether the most recent loop already cleaned this HEAD (short-circuit) and otherwise records that prior loops were dirty so the AUDIT runs against the latest diff with that signal in mind:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
dirty_review_count=0
|
|
223
|
+
gh api "repos/<owner>/<repo>/pulls/<number>/reviews" \
|
|
224
|
+
--jq '[.[] | select(.body | startswith("## /bugteam loop "))] | sort_by(.submitted_at) | reverse'
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Iterate from index 0 (most recent) toward older entries:
|
|
228
|
+
|
|
229
|
+
- A bugteam review body that ends with `→ clean` is **clean**; any other `## /bugteam loop ...` body is **dirty**.
|
|
230
|
+
- For a dirty review, increment `dirty_review_count` by one. The review's specific finding bodies are not carried forward — bugteam's AUDIT regenerates findings against the current HEAD's diff each loop, so prior bodies are stale by definition. The count alone is the carried signal.
|
|
231
|
+
- Stop at the first clean review. Older reviews are presumed addressed at that clean checkpoint and are not re-read.
|
|
232
|
+
- When index 0 is itself clean AND its `commit_id` matches `git rev-parse HEAD`, the PR is already converged on this HEAD — set `last_action="audited"`, `last_findings='{"total": 0}'`, fall through to step 1's `converged` exit, skip Step 3 iteration entirely.
|
|
233
|
+
- When `dirty_review_count > 0`, log the count and proceed into the normal iteration; the next AUDIT regenerates anchored findings against the current HEAD so `loop_comment_index` stays correct. Unlike `pr-converge` — where Cursor Bugbot's prior dirty-review *bodies* are read back by the Fix protocol because each dirty body lists specific findings the loop must still address — bugteam's per-loop bodies are anchored to the diff at *that loop's* HEAD, so re-applying them against a newer diff would be incorrect. The count is sufficient signal that "prior loops did not converge here."
|
|
230
234
|
|
|
231
235
|
1. From `last_action` / `last_findings`:
|
|
232
236
|
- `last_action == "audited"` and `last_findings.total == 0` → exit `converged`
|
|
@@ -237,10 +241,10 @@ Run the AUDIT-FIX cycle for each PR in all_prs, reusing the same team across PRs
|
|
|
237
241
|
2. **Pre-audit** (only when the next step is AUDIT):
|
|
238
242
|
|
|
239
243
|
```bash
|
|
240
|
-
python "${CLAUDE_SKILL_DIR}/scripts/
|
|
244
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/code_rules_gate.py" --base origin/<baseRefName>
|
|
241
245
|
```
|
|
242
246
|
|
|
243
|
-
Lead only; merge-base / diff
|
|
247
|
+
Lead only; merge-base / diff semantics: [`../../_shared/pr-loop/code-rules-gate.md`](../../_shared/pr-loop/code-rules-gate.md); shared script inventory: [`../../_shared/pr-loop/scripts/README.md`](../../_shared/pr-loop/scripts/README.md). Non-zero → spawn **clean-coder** standards-fix (read stderr, edit, re-run **this same** command, one commit, `git push`, shutdown) until exit **0** or **5** failed gate rounds → `error: code rules gate failed pre-audit`. After **0**: `loop_count += 1`; if `loop_count > 10` → `cap reached`. Then **AUDIT** (bugfind); print `Loop <N> audit: ...`.
|
|
244
248
|
|
|
245
249
|
3. **FIX** (`last_action == "audited"` and `last_findings.total > 0`): `loop_count += 1`; if `loop_count > 10` → `cap reached`; **FIX** (bugfix); print `Loop <N> fix: ...`; `last_action = "fixed"`, update `audit_log`; loop to step 1.
|
|
246
250
|
|
|
@@ -257,79 +261,45 @@ mkdir -p "<team_temp_dir>/pr-<N>"
|
|
|
257
261
|
gh pr diff <N> -R <owner>/<repo> > "<team_temp_dir>/pr-<N>/loop-<L>.patch"
|
|
258
262
|
```
|
|
259
263
|
|
|
260
|
-
|
|
261
|
-
Agent(
|
|
262
|
-
subagent_type="code-quality-agent",
|
|
263
|
-
name="bugfind-pr<N>-loop<L>",
|
|
264
|
-
team_name="<team_name>",
|
|
265
|
-
model="opus",
|
|
266
|
-
description="Bugfind audit PR <N> loop <L>",
|
|
267
|
-
prompt="<audit XML; see PROMPTS.md>"
|
|
268
|
-
)
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Fresh `Agent` each loop; teammate context excludes lead history ([`sources.md`](sources.md) § Teammate context isolation). [`PROMPTS.md`](PROMPTS.md): XML + outcome schema. Lead reads `.bugteam-pr<N>-loop<L>.outcomes.xml`, fills `loop_comment_index`.
|
|
272
|
-
|
|
273
|
-
**Shutdown:** If `Agent` returned and the teammate already ended, skip. Otherwise:
|
|
264
|
+
**Spawn and shutdown:** Path A — [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) § AUDIT. Path B — [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § AUDIT. Same `prompt="<audit XML; see PROMPTS.md>"` and outcome files.
|
|
274
265
|
|
|
275
|
-
|
|
276
|
-
SendMessage(
|
|
277
|
-
to="bugfind-pr<N>-loop<L>",
|
|
278
|
-
message={"type": "shutdown_request", "reason": "audit PR <N> loop <L> complete; outcome XML captured"}
|
|
279
|
-
)
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
`approve: false` → `error: bugfind teammate refused shutdown` → Step 4 then 5.
|
|
266
|
+
Fresh spawn each loop; Path A teammate context excludes lead history ([`sources.md`](sources.md) § Teammate context isolation). Path B: fresh Task per loop for the same clean-room intent. [`PROMPTS.md`](PROMPTS.md): XML + outcome schema. Lead reads `.bugteam-pr<N>-loop<L>.outcomes.xml`, fills `loop_comment_index`.
|
|
283
267
|
|
|
284
268
|
`last_action = "audited"`; append audit line to `audit_log`.
|
|
285
269
|
|
|
286
|
-
**Parallel auditors (`loop_count >= 4`):** gate passes immediately before; after three full audit/fix rounds without convergence, issue three `Agent` calls in
|
|
270
|
+
**Parallel auditors (`loop_count >= 4`):** gate passes immediately before; after three full audit/fix rounds without convergence, issue three spawns in one assistant message (parallel): Path A — three `Agent` calls; Path B — three `Task` calls — full rules in the workflow files § parallel auditors. `-a` posts the review and merges outcomes from `-b`/`-c` (read `.bugteam-pr<N>-loop<L>.outcomes.xml` plus `<team_temp_dir>/pr-<N>/loop-<L>-b.outcomes.xml` and `...-c...`); merge key `(file, line, category_letter)`; re-id `loopN-K`. `-b`/`-c` write sibling XML only; prompts must pass literal absolute sibling paths. Shutdown order: Path A workflow § parallel auditors; Path B: await all three Tasks.
|
|
287
271
|
|
|
288
272
|
### FIX action
|
|
289
273
|
|
|
290
|
-
|
|
291
|
-
Agent(
|
|
292
|
-
subagent_type="clean-coder",
|
|
293
|
-
name="bugfix-pr<N>-loop<L>",
|
|
294
|
-
team_name="<team_name>",
|
|
295
|
-
model="opus",
|
|
296
|
-
description="Bugfix PR <N> loop <L>",
|
|
297
|
-
prompt="<fix XML; see PROMPTS.md>"
|
|
298
|
-
)
|
|
299
|
-
```
|
|
274
|
+
**Spawn and shutdown:** Path A — [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) § FIX. Path B — [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § FIX.
|
|
300
275
|
|
|
301
276
|
Pass finding comment URLs/ids from `loop_comment_index` in XML. Replies: `Fixed in <sha>` or `Could not address this loop: <reason>`.
|
|
302
277
|
|
|
303
|
-
**Shutdown:** same as bugfind; else `SendMessage(to="bugfix-pr<N>-loop<L>", message={"type": "shutdown_request", "reason": "fix PR <N> loop <L> complete; commit <sha7> pushed"})`. `approve: false` → `error: bugfix teammate refused shutdown` → Step 4 then 5.
|
|
304
|
-
|
|
305
278
|
[`PROMPTS.md`](PROMPTS.md): fix XML + schema. Verify: `git rev-parse HEAD` advanced; `git fetch origin <branch> && git rev-parse origin/<branch>` matches `HEAD`. Unchanged HEAD → `stuck — bugfix teammate could not address findings`.
|
|
306
279
|
|
|
307
|
-
### Step
|
|
280
|
+
### Step 4: Teardown
|
|
308
281
|
|
|
309
|
-
|
|
310
|
-
BEFORE Step 4 teardown. Spawn one more fresh `code-quality-agent` teammate;
|
|
311
|
-
audit the cumulative PR diff against the K–N addendum a second time. Post
|
|
312
|
-
the review with body `## /bugteam FINAL standards review against PR #<N>
|
|
313
|
-
cumulative diff: <P0>P0 / <P1>P1 / <P2>P2`. When findings remain, the
|
|
314
|
-
exit reason is upgraded to `error: final standards review found <P0>+<P1>+<P2>
|
|
315
|
-
unresolved finding(s)` and the loop log gains an extra `final-review` line.
|
|
316
|
-
A clean FINAL review preserves the existing exit reason. Failure on this
|
|
317
|
-
phase logs the error and continues to Step 4 unchanged so teardown,
|
|
318
|
-
permission revoke, and the final report still run.
|
|
282
|
+
1. For each PR in `all_prs`: `git worktree remove "<team_temp_dir>/pr-<N>/worktree"` (from Step 1) before tearing down the team harness — tolerate already-removed worktrees.
|
|
319
283
|
|
|
320
|
-
|
|
284
|
+
2. Path-specific harness — [`reference/workflow-path-a-orchestrated-teams.md`](reference/workflow-path-a-orchestrated-teams.md) § Step 4 (teammate `SendMessage`, `TeamDelete` **only when `team_owned=true`**) or [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md) § Step 4 (omit those).
|
|
321
285
|
|
|
322
|
-
|
|
286
|
+
3. **Windows-safe `rmtree` — gated by `team_owned` from [Team lifecycle](#team-lifecycle-path-a-only).** The Windows-safe handler strips the Windows ReadOnly attribute and retries the failing syscall (see `~/.claude/rules/windows-filesystem-safe.md`).
|
|
323
287
|
|
|
324
|
-
|
|
288
|
+
- `team_owned=true` → remove the full `<team_temp_dir>`:
|
|
325
289
|
|
|
326
|
-
|
|
290
|
+
```bash
|
|
291
|
+
python -c "import os, shutil, stat, sys; \
|
|
292
|
+
h = lambda f, p, *_: (os.chmod(p, stat.S_IWRITE), f(p)); \
|
|
293
|
+
shutil.rmtree(r'<team_temp_dir>', **({'onexc': h} if sys.version_info >= (3, 12) else {'onerror': h}))"
|
|
294
|
+
```
|
|
327
295
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
296
|
+
- `team_owned=false` (attach mode) → for each PR in `all_prs`, remove only that PR's `<team_temp_dir>/pr-<N>/` subfolder. The orchestrator-owned parent `<team_temp_dir>` survives so the next attached invocation can write its own per-PR subfolders without colliding.
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
python -c "import os, shutil, stat, sys; \
|
|
300
|
+
h = lambda f, p, *_: (os.chmod(p, stat.S_IWRITE), f(p)); \
|
|
301
|
+
shutil.rmtree(r'<team_temp_dir>/pr-<N>', **({'onexc': h} if sys.version_info >= (3, 12) else {'onerror': h}))"
|
|
302
|
+
```
|
|
333
303
|
|
|
334
304
|
### Step 4.5: PR description
|
|
335
305
|
|
|
@@ -346,7 +316,7 @@ On failure: log in final report; continue to Step 5.
|
|
|
346
316
|
### Step 5: Revoke permissions (always)
|
|
347
317
|
|
|
348
318
|
```bash
|
|
349
|
-
python "${CLAUDE_SKILL_DIR}/scripts/revoke_project_claude_permissions.py"
|
|
319
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/revoke_project_claude_permissions.py"
|
|
350
320
|
```
|
|
351
321
|
|
|
352
322
|
Removes Step 0 grant — run even if Step 4 partially failed (log separately).
|
|
@@ -361,10 +331,8 @@ Final commit: <current_HEAD_sha7>
|
|
|
361
331
|
Net change: <total_files> files, +<total_add>/-<total_del>
|
|
362
332
|
|
|
363
333
|
Loop log:
|
|
364
|
-
initial standards review: 1P0 0P1 2P2
|
|
365
334
|
1 audit: 3P0 2P1 0P2
|
|
366
335
|
...
|
|
367
|
-
final standards review: 0P0 0P1 0P2
|
|
368
336
|
```
|
|
369
337
|
|
|
370
338
|
`cap reached` → suggest `/findbugs`. `stuck` → which findings. `error` → detail + loop.
|
|
@@ -14,23 +14,23 @@ Evals are split into two layers. Both layers run against the same trace but carr
|
|
|
14
14
|
|
|
15
15
|
## Ironclad invariants (Layer A, apply to every eval)
|
|
16
16
|
|
|
17
|
-
Each invariant cites the normative section or companion file it derives from.
|
|
17
|
+
Each invariant cites the normative section or companion file it derives from. **Path A vs Path B:** `SKILL.md` **Path routing** splits harnesses. Invariants **I-1, I-3, I-4, I-7, I-9, I-11 (teammate shutdown → `TeamDelete` prefix), I-13** apply to **Path A only**. **Path B** substitutes per [`reference/workflow-path-b-task-harness.md`](reference/workflow-path-b-task-harness.md): no `TeamCreate` / `TeamDelete`; parallel auditors use parallel **`Task`** calls; **I-12 Path B** — the **lead** runs Step 2.5 `gh api` posts. **I-2, I-5, I-6, I-8, I-10** apply to **both** paths (revoke once; fresh spawn per loop; `model="opus"` on audit/fix workers; cap; read outcome XML).
|
|
18
18
|
|
|
19
19
|
| # | Invariant | Citation |
|
|
20
20
|
|---|---|---|
|
|
21
|
-
| I-1 | `Bash` invoking `scripts/grant_project_claude_permissions.py` precedes every `TeamCreate`. | `SKILL.md` § Step 0 |
|
|
22
|
-
| I-2 | `Bash` invoking `scripts/revoke_project_claude_permissions.py` runs exactly once per invocation, after
|
|
23
|
-
| I-3 | Exactly one `TeamCreate` and exactly one `TeamDelete` per invocation. | `SKILL.md` § Step 2; § Step 4 |
|
|
24
|
-
| I-4 | Before `TeamDelete`, no teammate remains active without cleanup
|
|
25
|
-
| I-5 | `Agent` calls are fresh per loop
|
|
26
|
-
| I-6 | Both audit and fix
|
|
27
|
-
| I-7 | `TeamDelete()` is called with no arguments.
|
|
21
|
+
| I-1 | **Path A:** `Bash` invoking `scripts/grant_project_claude_permissions.py` precedes every `TeamCreate`. **Path B:** grant precedes first audit **`Task`**. | `SKILL.md` § Step 0; § Path routing |
|
|
22
|
+
| I-2 | `Bash` invoking `scripts/revoke_project_claude_permissions.py` runs exactly once per invocation on every exit path, **after** teardown that applies to that path (`TeamDelete` only on Path A). | `SKILL.md` § Step 5 |
|
|
23
|
+
| I-3 | **Path A:** Exactly one `TeamCreate` and exactly one `TeamDelete` per invocation. **Path B:** zero `TeamCreate` / `TeamDelete`. | `SKILL.md` § Step 2; § Step 4 |
|
|
24
|
+
| I-4 | **Path A:** Before `TeamDelete`, no teammate remains active without cleanup (self-terminated `Agent` or `SendMessage` shutdown). | `SKILL.md` § AUDIT/FIX shutdown; § Step 4 |
|
|
25
|
+
| I-5 | **Path A:** `Agent` calls are fresh per loop. **Path B:** `Task` calls for audit/fix are fresh per loop (same `name` discipline where the host exposes naming). | `CONSTRAINTS.md` — **Fresh teammate per loop**; deltas **Clean-room note** |
|
|
26
|
+
| I-6 | Both paths: audit and fix worker spawns pass `model="opus"` on `Agent` **or** `Task` as documented in `SKILL.md` § AUDIT/FIX. | `SKILL.md` § Step 2 (**Roles**); `CONSTRAINTS.md` — **Opus 4.7 at xhigh effort for both teammates** |
|
|
27
|
+
| I-7 | **Path A:** `TeamDelete()` is called with no arguments. **Path B:** omit. | `SKILL.md` § Step 4 |
|
|
28
28
|
| I-8 | Loop count ≤ 10 audits. 11th audit never fires. | `SKILL.md` YAML `description` (10-loop cap); § Step 3 (**Pre-audit** / **FIX** increment rules) |
|
|
29
|
-
| I-9 | From loop 4 onward without convergence,
|
|
29
|
+
| I-9 | **Path A:** From loop 4 onward without convergence, three parallel `Agent` calls in one message. **Path B:** three parallel **`Task`** calls. | `SKILL.md` § AUDIT action (**Parallel auditors**); `reference/workflow-path-b-task-harness.md` |
|
|
30
30
|
| I-10 | Lead reads `.bugteam-loop-<N>.outcomes.xml` with the `Read` tool after each audit, before the next action. | `SKILL.md` § AUDIT action |
|
|
31
|
-
| I-11 |
|
|
32
|
-
| I-12 | Lead never posts PR review
|
|
33
|
-
| I-13 | Only the
|
|
31
|
+
| I-11 | **Path A:** `git worktree remove` each PR → teammate shutdowns → `TeamDelete` → `rmtree` `<team_temp_dir>` → Step 4.5 → revoke. **Path B:** `git worktree remove` each PR → (omit shutdown / `TeamDelete`) → `rmtree` → Step 4.5 → revoke. | `SKILL.md` § Step 4; § Step 4.5; § Step 5; `reference/workflow-path-a-orchestrated-teams.md` § Step 4; `reference/workflow-path-b-task-harness.md` § Step 4 |
|
|
32
|
+
| I-12 | **Path A:** Lead never posts PR review / finding / fix replies except Step 4.5 body. **Path B:** Lead performs Step 2.5 posts per deltas; Step 4.5 unchanged. | `CONSTRAINTS.md` — **Audit/fix comment posting** |
|
|
33
|
+
| I-13 | **Path A:** Only the lead invokes `TeamCreate`; every teammate `Agent(..., team_name=...)`. **Path B:** no `TeamCreate`; `Task` spawns omit `team_name`. | `CONSTRAINTS.md` — **Path A — orchestrator-only `TeamCreate`**; `reference/workflow-path-b-task-harness.md` |
|
|
34
34
|
|
|
35
35
|
Any eval failing one or more Layer A invariants fails the run.
|
|
36
36
|
|
|
@@ -46,23 +46,25 @@ The harness does not yet exist; this document defines its contract.
|
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
## Eval 1 —
|
|
49
|
+
## Eval 1 — Path B: agent teams env unset (Task harness, not a refusal)
|
|
50
50
|
|
|
51
51
|
**Scenario.** `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS` is unset in both `claude config` and `~/.claude/settings.json`.
|
|
52
52
|
|
|
53
53
|
**Trigger.** `/bugteam`
|
|
54
54
|
|
|
55
|
-
**Layer A invariants.**
|
|
55
|
+
**Layer A invariants.** Path B subset (I-2, I-5, I-6, I-8, I-10; I-1/I-3/I-4/I-7/I-9/I-11/I-13 N/A or Path-B-shaped).
|
|
56
56
|
|
|
57
|
-
**Layer B predicted trace.**
|
|
57
|
+
**Layer B predicted trace (Path B smoke).**
|
|
58
58
|
1. `Bash("claude config get env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS")` → empty.
|
|
59
|
-
2. `
|
|
60
|
-
3. No
|
|
59
|
+
2. `Bash("python .../grant_project_claude_permissions.py")` runs (Step 0).
|
|
60
|
+
3. **No** `TeamCreate`.
|
|
61
|
+
4. At least one `Task(subagent_type="code-quality-agent", ...)` or host-equivalent for AUDIT; FIX rounds use the host-appropriate FIX `Task` from `workflow-path-b-task-harness.md` § **FIX spawn** (`clean-coder` subtype on Claude Code when accepted; `generalPurpose` + clean-coder **Read** preamble on Cursor when the enum rejects `clean-coder`).
|
|
62
|
+
5. `Bash("python .../revoke_project_claude_permissions.py")` on exit.
|
|
61
63
|
|
|
62
64
|
**Pass criteria.**
|
|
63
|
-
-
|
|
64
|
-
- Zero `TeamCreate`, `
|
|
65
|
-
-
|
|
65
|
+
- **No** refusal string about missing agent teams.
|
|
66
|
+
- Zero `TeamCreate`, zero `TeamDelete`, zero teammate `SendMessage` shutdowns.
|
|
67
|
+
- Non-zero `Task` (or `Agent` without `team_name` only if the host maps Path B that way) carrying **`code-quality-agent`** / **fix worker under the clean-coder contract** (subtype `clean-coder` where accepted, else `generalPurpose` + `clean-coder.md` Read per `workflow-path-b-task-harness.md`).
|
|
66
68
|
|
|
67
69
|
---
|
|
68
70
|
|
|
@@ -95,11 +97,11 @@ The harness does not yet exist; this document defines its contract.
|
|
|
95
97
|
|
|
96
98
|
---
|
|
97
99
|
|
|
98
|
-
## Eval 5 — Happy path: converges in 2 loops
|
|
100
|
+
## Eval 5 — Happy path: converges in 2 loops (Path A fixture)
|
|
99
101
|
|
|
100
|
-
**Scenario.** PR #42 contains three P1 bugs all addressable by the mock fix teammate. Loop 1 audit returns 3 findings; loop 1 fix commits cleanly; loop 2 audit returns zero findings.
|
|
102
|
+
**Scenario.** PR #42 contains three P1 bugs all addressable by the mock fix teammate. Loop 1 audit returns 3 findings; loop 1 fix commits cleanly; loop 2 audit returns zero findings. **`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`** (Path A — `TeamCreate` + teammate `Agent`).
|
|
101
103
|
|
|
102
|
-
**Layer A invariants.** I-1, I-2, I-3, I-4, I-5, I-6, I-7, I-10, I-11, I-12.
|
|
104
|
+
**Layer A invariants.** Path A: I-1, I-2, I-3, I-4, I-5, I-6, I-7, I-10, I-11, I-12, I-13.
|
|
103
105
|
|
|
104
106
|
**Layer B predicted trace.**
|
|
105
107
|
|
|
@@ -4,6 +4,8 @@ Expanded material that used to live inline in `SKILL.md`. Load a file when the o
|
|
|
4
4
|
|
|
5
5
|
| File | Domain |
|
|
6
6
|
|------|--------|
|
|
7
|
+
| [`workflow-path-a-orchestrated-teams.md`](workflow-path-a-orchestrated-teams.md) | **Path A only** — `TeamCreate`, `Agent` + `team_name`, `SendMessage`, `TeamDelete`, who posts Step 2.5 |
|
|
8
|
+
| [`workflow-path-b-task-harness.md`](workflow-path-b-task-harness.md) | **Path B only** — `Task` harness (no `TeamCreate` / `TeamDelete`, lead Step 2.5 `gh api`, Step 4 omissions) |
|
|
7
9
|
| [`design-rationale.md`](design-rationale.md) | Why agent teams (clean-room), table-of-contents habit, when `/bugteam` applies, refusal reasons |
|
|
8
10
|
| [`team-setup.md`](team-setup.md) | Permissions grant (`CLAUDE_SKILL_DIR`), PR scope, `TeamCreate`, team name / sanitization / temp dir / roles / loop state |
|
|
9
11
|
| [`github-pr-reviews.md`](github-pr-reviews.md) | Per-loop reviews, `jq` + `gh api` payloads, anchors, fallbacks, REST endpoints |
|
|
@@ -16,10 +16,10 @@ Repeat until an exit condition fires.
|
|
|
16
16
|
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`):
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
python "${CLAUDE_SKILL_DIR}/scripts/
|
|
19
|
+
python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/code_rules_gate.py" --base origin/<baseRefName>
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
`git merge-base` + `git diff --name-only` live inside the script; see [
|
|
22
|
+
`git merge-base` + `git diff --name-only` live inside the script; see [`../../../_shared/pr-loop/scripts/README.md`](../../../_shared/pr-loop/scripts/README.md) for what lives under this directory, and [`../../../_shared/pr-loop/code-rules-gate.md`](../../../_shared/pr-loop/code-rules-gate.md) for gate-only merge-base / invocation semantics. The lead runs this (not a teammate).
|
|
23
23
|
|
|
24
24
|
2. If exit code **0** → continue to step 2.5 (AUDIT spawn) below.
|
|
25
25
|
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`.
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Copilot gap analysis
|
|
2
2
|
|
|
3
|
+
> **Status: HISTORICAL — patch plan partially superseded.**
|
|
4
|
+
>
|
|
5
|
+
> This file documents the read-only investigation that motivated the K–N rubric addendum and the Step 2.6 / Step 3.5 standards-review phases. **The audit-rubric portion of the patch plan was reverted in [PR #292](https://github.com/jl-cmd/claude-code-config/pull/292):** PROMPTS.md no longer carries the K–N addendum or the `<copilot_derived_addendum_source>` block, and SKILL.md no longer runs the Step 2.6 / Step 3.5 standards-review phases.
|
|
6
|
+
>
|
|
7
|
+
> **What replaced K–N (partial coverage):** several judgment-heavy categories now have deterministic validators in `code_rules_enforcer.py` — `check_collection_prefix` (category K), `check_library_print` (category L), `check_inline_literal_collections`, `check_loop_variable_naming`, `check_parameter_annotations`, `check_return_annotations`. These validators are exercised by `bugteam_code_rules_gate.py` during the bugteam pre-audit / loop, and by the shipped repo `pre-commit` / `pre-push` git hooks that invoke that gate. They are **not** wired into the repo's default `PreToolUse` Write|Edit hook list in `packages/claude-dev-env/hooks/hooks.json`, so they do not block at Write/Edit time by default — enforcement comes from the gate (audit-time) and the git hooks (commit/push-time).
|
|
8
|
+
>
|
|
9
|
+
> **What is NOT a full deterministic replacement (remaining limitations):** the string-literal magic case in this doc is largely about snake_case column / key / table-name literals (`"theme_name"`, `"content_id"`, etc.). `check_string_literal_magic` in `code_rules_enforcer.py` still only flags ALL-CAPS-WITH-UNDERSCORE identifiers and dotted segments, so it does **not** cover those snake_case database-column literals by itself. However, the gap called out in this document is no longer accurately described as “unimplemented”: `check_database_column_string_magic` and `check_wrapper_plumb_through` now exist in `bugteam_code_rules_gate.py` and run in the `/bugteam` gate, including via the shipped repo `pre-commit` / `pre-push` hooks that invoke that gate. The remaining limitation is coverage/wiring scope: these checks are gate-time / git-hook-time validators, not part of the repo's default `PreToolUse` Write|Edit hook path, and any residual misses should be described in terms of validator scope rather than absence.
|
|
10
|
+
>
|
|
11
|
+
> Read this file as **investigation history**: the inventory, rubric/validator coverage diffs, and root-cause statement remain useful context for future bugteam improvements. The "Patch plan" section below describes what was originally proposed, not the current state — references to category K, L, M, N or to Step 2.6 / Step 3.5 in the patch plan are historical and should not be reintroduced.
|
|
12
|
+
|
|
3
13
|
This file is the reference record produced by the read-only investigation of why the `/bugteam` audit/fix loop and `bugteam_code_rules_gate.py` repeatedly miss the classes of code-quality violations that the GitHub Copilot reviewer raises on follow-up review rounds. It is written so future bugteam runs can skim the inventory, the rubric/validator coverage diffs, and the patch plan without re-deriving them.
|
|
4
14
|
|
|
5
15
|
Sources of truth cited below: `~/.claude/docs/CODE_RULES.md`, `~/.claude/CLAUDE.md`, `~/.claude/rules/file-global-constants.md`, `~/.claude/skills/bugteam/SKILL.md`, `~/.claude/skills/bugteam/PROMPTS.md`, `~/.claude/skills/bugteam/CONSTRAINTS.md`, `~/.claude/skills/bugteam/scripts/bugteam_code_rules_gate.py`, `~/.claude/skills/bugteam/scripts/bugteam_preflight.py`, `~/.claude/hooks/blocking/code_rules_enforcer.py`, plus `gh api repos/JonEcho/python-automation/pulls/{70,73}/comments` filtered to author `Copilot`.
|
|
@@ -85,6 +95,8 @@ The bugteam audit rubric (PROMPTS.md §bug_categories A–J) and the determinist
|
|
|
85
95
|
|
|
86
96
|
## Patch plan
|
|
87
97
|
|
|
98
|
+
> **Historical — the rubric/phases portion below was reverted in PR #292.** Sections (a) PROMPTS.md K–N addendum, (b) Step 2.6 INITIAL standards review, and the FINAL standards review (Step 3.5) were reverted and replaced by deterministic validators (see status banner at the top of this file). Sections that landed deterministic validators in `code_rules_enforcer.py` (collection prefix, library print, string-literal magic, inline literal collections, loop-variable naming, parameter/return annotations) remain in force. Treat the rubric/phase sections below as record-of-what-was-tried, not a current to-do list.
|
|
99
|
+
|
|
88
100
|
Each section names exactly one target file, the literal text or regex to add, and a verification step that re-runs the new detection against the PR #70 / PR #73 diffs.
|
|
89
101
|
|
|
90
102
|
### a. `~/.claude/skills/bugteam/PROMPTS.md`
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Utility scripts (progressive disclosure)
|
|
4
4
|
|
|
5
|
-
Fragile or repeatable shell sequences belong in `scripts/`. Anthropic: [Progressive disclosure patterns](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#progressive-disclosure-patterns) — utility scripts are **executed**, not loaded into context as primary reading.
|
|
5
|
+
Fragile or repeatable shell sequences belong in `_shared/pr-loop/scripts/`. Anthropic: [Progressive disclosure patterns](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#progressive-disclosure-patterns) — utility scripts are **executed**, not loaded into context as primary reading. Script inventory and entry points: [`../../../_shared/pr-loop/scripts/README.md`](../../../_shared/pr-loop/scripts/README.md). Gate-only merge-base / diff semantics: [`../../../_shared/pr-loop/code-rules-gate.md`](../../../_shared/pr-loop/code-rules-gate.md).
|
|
6
6
|
|
|
7
7
|
### Pre-flight (recommended before Step 0)
|
|
8
8
|
|