claude-dev-env 1.37.0 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +3 -0
- package/_shared/pr-loop/audit-contract.md +4 -3
- package/_shared/pr-loop/fix-protocol.md +2 -0
- package/_shared/pr-loop/gh-payloads.md +38 -37
- package/_shared/pr-loop/scripts/README.md +0 -1
- package/_shared/pr-loop/scripts/preflight.py +2 -1
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +2 -2
- package/_shared/pr-loop/scripts/tests/test_preflight.py +22 -0
- package/_shared/pr-loop/state-schema.md +10 -10
- package/agents/clean-coder.md +4 -0
- package/agents/code-quality-agent.md +23 -85
- package/agents/groq-coder.md +8 -6
- package/hooks/blocking/__init__.py +0 -0
- package/hooks/blocking/hedging_language_blocker.py +2 -2
- package/hooks/blocking/state_description_blocker.py +243 -0
- package/hooks/blocking/tdd_enforcer.py +94 -0
- package/hooks/blocking/test_hedging_language_blocker.py +1 -1
- package/hooks/blocking/test_state_description_blocker.py +618 -0
- package/hooks/blocking/test_tdd_enforcer.py +152 -0
- package/hooks/config/state_description_blocker_constants.py +130 -0
- package/hooks/hooks.json +10 -0
- package/package.json +1 -1
- package/rules/gh-paginate.md +4 -50
- package/rules/no-historical-clutter.md +57 -0
- package/scripts/config/groq_bugteam_config.py +13 -5
- package/skills/bugteam/CONSTRAINTS.md +20 -27
- package/skills/bugteam/EXAMPLES.md +1 -1
- package/skills/bugteam/PROMPTS.md +78 -42
- package/skills/bugteam/SKILL.md +76 -63
- package/skills/bugteam/SKILL_EVALS.md +12 -12
- package/skills/bugteam/reference/audit-and-teammates.md +21 -48
- package/skills/bugteam/reference/audit-contract.md +7 -7
- package/skills/bugteam/reference/github-pr-reviews.md +31 -31
- package/skills/bugteam/reference/team-setup.md +1 -1
- package/skills/bugteam/reference/teardown-publish-permissions.md +4 -4
- package/skills/copilot-review/SKILL.md +7 -14
- package/skills/findbugs/SKILL.md +2 -2
- package/skills/fixbugs/SKILL.md +1 -1
- package/skills/monitor-open-prs/SKILL.md +6 -6
- package/skills/pr-converge/SKILL.md +7 -6
- package/skills/pr-converge/reference/convergence-gates.md +46 -44
- package/skills/pr-converge/reference/examples.md +4 -4
- package/skills/pr-converge/reference/fix-protocol.md +8 -8
- package/skills/pr-converge/reference/multi-pr-orchestration.md +10 -10
- package/skills/pr-converge/reference/per-tick.md +24 -36
- package/skills/pr-converge/reference/stop-conditions.md +7 -7
- package/skills/pr-converge/scripts/README.md +65 -117
- package/skills/pr-review-responder/EXAMPLES.md +2 -2
- package/skills/pr-review-responder/PRINCIPLES.md +2 -8
- package/skills/pr-review-responder/README.md +7 -48
- package/skills/pr-review-responder/SKILL.md +2 -3
- package/skills/pr-review-responder/TESTING.md +8 -65
- package/skills/qbug/SKILL.md +10 -16
- package/_shared/pr-loop/scripts/config/gh_util_constants.py +0 -31
- package/_shared/pr-loop/scripts/gh_util.py +0 -193
- package/_shared/pr-loop/scripts/tests/test_gh_util.py +0 -257
- package/_shared/pr-loop/scripts/tests/test_gh_util_constants.py +0 -61
- package/skills/pr-converge/scripts/check_pr_mergeability.py +0 -78
- package/skills/pr-converge/scripts/config/pr_converge_constants.py +0 -118
- package/skills/pr-converge/scripts/config/test_pr_converge_constants.py +0 -152
- package/skills/pr-converge/scripts/fetch_bugbot_inline_comments.py +0 -70
- package/skills/pr-converge/scripts/fetch_bugbot_reviews.py +0 -57
- package/skills/pr-converge/scripts/fetch_claude_inline_comments.py +0 -70
- package/skills/pr-converge/scripts/fetch_claude_reviews.py +0 -61
- package/skills/pr-converge/scripts/fetch_copilot_inline_comments.py +0 -70
- package/skills/pr-converge/scripts/fetch_copilot_reviews.py +0 -61
- package/skills/pr-converge/scripts/mark_pr_ready.py +0 -54
- package/skills/pr-converge/scripts/post-bugbot-run.helpers.ps1 +0 -49
- package/skills/pr-converge/scripts/post-bugbot-run.ps1 +0 -33
- package/skills/pr-converge/scripts/reply_to_inline_comment.py +0 -84
- package/skills/pr-converge/scripts/request_copilot_review.py +0 -71
- package/skills/pr-converge/scripts/resolve_pr_head.py +0 -58
- package/skills/pr-converge/scripts/review_field_helpers.py +0 -43
- package/skills/pr-converge/scripts/reviewer_fetch_core.py +0 -153
- package/skills/pr-converge/scripts/reviewer_specs.py +0 -98
- package/skills/pr-converge/scripts/test_check_pr_mergeability.py +0 -126
- package/skills/pr-converge/scripts/test_fetch_bugbot_inline_comments.py +0 -443
- package/skills/pr-converge/scripts/test_fetch_bugbot_reviews.py +0 -299
- package/skills/pr-converge/scripts/test_fetch_claude_inline_comments.py +0 -485
- package/skills/pr-converge/scripts/test_fetch_claude_reviews.py +0 -368
- package/skills/pr-converge/scripts/test_fetch_copilot_inline_comments.py +0 -440
- package/skills/pr-converge/scripts/test_fetch_copilot_reviews.py +0 -366
- package/skills/pr-converge/scripts/test_mark_pr_ready.py +0 -69
- package/skills/pr-converge/scripts/test_post_bugbot_run.py +0 -195
- package/skills/pr-converge/scripts/test_reply_to_inline_comment.py +0 -159
- package/skills/pr-converge/scripts/test_request_copilot_review.py +0 -101
- package/skills/pr-converge/scripts/test_resolve_pr_head.py +0 -79
- package/skills/pr-converge/scripts/test_review_field_helpers.py +0 -80
- package/skills/pr-converge/scripts/test_reviewer_fetch_core.py +0 -448
- package/skills/pr-converge/scripts/test_reviewer_specs.py +0 -107
- package/skills/pr-converge/scripts/test_trigger_bugbot.py +0 -139
- package/skills/pr-converge/scripts/test_view_pr_context.py +0 -111
- package/skills/pr-converge/scripts/trigger_bugbot.py +0 -77
- package/skills/pr-converge/scripts/view_pr_context.py +0 -47
- package/skills/pr-review-responder/scripts/respond_to_reviews.py +0 -376
|
@@ -11,32 +11,36 @@ Fetch latest Copilot reviewer (`copilot-pull-request-reviewer[bot]`) review
|
|
|
11
11
|
plus inline comments anchored to most recent Copilot review on
|
|
12
12
|
`current_head`:
|
|
13
13
|
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
```
|
|
15
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_reviews")
|
|
16
|
+
→ filter `.user.login` for copilot (case-insensitive substring "copilot")
|
|
17
|
+
→ sort by `.submitted_at` descending
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_review_comments")
|
|
20
|
+
→ filter threads where `is_outdated == false` AND any comment has `.author` matching Copilot (case-insensitive substring "copilot")
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
Decide (four branches; match first whose predicate holds):
|
|
23
24
|
|
|
24
25
|
- **`classification == "dirty"` with non-empty inline comments matching
|
|
25
26
|
`pull_request_review_id`:** Fix protocol input (same shape as bugbot
|
|
26
|
-
dirty).
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
dirty). Spawn Agent (subagent_type: clean-coder) to implement → push → reply inline on each thread via
|
|
28
|
+
`add_reply_to_pull_request_comment` MCP → Step 3 in same tick (see
|
|
29
|
+
[Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow) for
|
|
30
|
+
full contract).
|
|
31
|
+
Reset `bugbot_clean_at = null` AND `copilot_clean_at = null`, `phase =
|
|
32
|
+
BUGBOT`, schedule next wakeup, return. Full back-to-back-clean cycle
|
|
33
|
+
plus all four gates must hold again on new HEAD.
|
|
31
34
|
- **`classification == "dirty"` with empty inline comments matching
|
|
32
35
|
`pull_request_review_id`:** Copilot posted findings only in review body
|
|
33
36
|
(`CHANGES_REQUESTED` or `COMMENTED` with non-empty body, no inline
|
|
34
|
-
threads). Parse body for actionable findings
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
`bugbot_clean_at = null` AND
|
|
38
|
-
BUGBOT`, Step 3 on new HEAD,
|
|
39
|
-
|
|
37
|
+
threads). Parse body for actionable findings. Spawn Agent (subagent_type: clean-coder) to implement → push → post
|
|
38
|
+
top-level review reply using `pull_request_review_write(method="create", event="COMMENT", body)` citing new HEAD SHA → Step 3 in same tick.
|
|
39
|
+
Reset
|
|
40
|
+
`bugbot_clean_at = null` AND
|
|
41
|
+
`copilot_clean_at = null`, `phase = BUGBOT`, Step 3 on new HEAD,
|
|
42
|
+
schedule next wakeup, return. Convergence requires full
|
|
43
|
+
back-to-back-clean on new HEAD.
|
|
40
44
|
- **`classification == "clean"` (state `APPROVED`):** Set
|
|
41
45
|
`copilot_clean_at = current_head`. Continue to gate (b).
|
|
42
46
|
- **No Copilot review on `current_head` yet:** Skip — gate (c) issues
|
|
@@ -46,16 +50,16 @@ Decide (four branches; match first whose predicate holds):
|
|
|
46
50
|
|
|
47
51
|
Resolve PR's mergeability state:
|
|
48
52
|
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
```
|
|
54
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get")
|
|
55
|
+
→ `.mergeable_state`, `.mergeable`
|
|
52
56
|
```
|
|
53
57
|
|
|
54
|
-
Persist `
|
|
58
|
+
Persist `mergeable_state` into `merge_state_status`. Decide:
|
|
55
59
|
|
|
56
|
-
- **`
|
|
60
|
+
- **`mergeable_state == "clean"` AND `mergeable == true`:**
|
|
57
61
|
Continue to gate (c).
|
|
58
|
-
- **`
|
|
62
|
+
- **`mergeable_state == "dirty"` (or `mergeable == false`):** Do
|
|
59
63
|
**not** mark ready. Invoke **`rebase`** skill
|
|
60
64
|
([`../../rebase/SKILL.md`](../../rebase/SKILL.md)) Phase 1–4 against PR's
|
|
61
65
|
base ref. After rebase + force-with-lease push, new HEAD invalidates
|
|
@@ -63,39 +67,39 @@ Persist `mergeStateStatus` into `merge_state_status`. Decide:
|
|
|
63
67
|
`copilot_clean_at = null`, `merge_state_status = null`, `phase = BUGBOT`,
|
|
64
68
|
Step 3 on new HEAD, schedule next wakeup, return. Loop re-runs from
|
|
65
69
|
scratch on new HEAD.
|
|
66
|
-
- **`
|
|
70
|
+
- **`mergeable_state` is `"blocked"`, `"behind"`, or `"unknown"` for
|
|
67
71
|
non-conflict reasons** (required checks pending, branch behind base
|
|
68
72
|
without conflicts GitHub cannot auto-resolve): **hard blocker** per
|
|
69
73
|
[stop-conditions.md](stop-conditions.md) — do not invent a fix. Report specific
|
|
70
|
-
`
|
|
74
|
+
`mergeable_state`, omit loop pacing.
|
|
71
75
|
|
|
72
76
|
## (c) Post-convergence Copilot review request
|
|
73
77
|
|
|
74
78
|
Once gates (a) and (b) both pass (Copilot clean at `current_head` *or* no
|
|
75
|
-
Copilot review yet, AND `
|
|
79
|
+
Copilot review yet, AND `mergeable_state == "clean"`), request Copilot
|
|
76
80
|
review:
|
|
77
81
|
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
--owner <OWNER> --repo <REPO> --number <NUMBER>
|
|
82
|
+
```
|
|
83
|
+
request_copilot_review(owner=OWNER, repo=REPO, pullNumber=NUMBER)
|
|
81
84
|
```
|
|
82
85
|
|
|
86
|
+
When the `request_copilot_review` MCP tool is unavailable, use `add_issue_comment` as fallback: `add_issue_comment(owner=OWNER, repo=REPO, issueNumber=NUMBER, body="@copilot review")`.
|
|
87
|
+
|
|
83
88
|
After request, schedule next wakeup and return — next tick checks response.
|
|
84
89
|
|
|
85
90
|
Next tick with `phase == BUGTEAM` and prior state preserved → re-run gate
|
|
86
91
|
(a) first. Decide:
|
|
87
92
|
|
|
88
93
|
- **Copilot review `clean` (state `APPROVED`):** Set `copilot_clean_at =
|
|
89
|
-
current_head`. Mark PR ready (`
|
|
94
|
+
current_head`. Mark PR ready (`update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`), report convergence
|
|
90
95
|
per §(d), terminate per [stop-conditions.md](stop-conditions.md) / Convergence.
|
|
91
96
|
- **Copilot review `dirty`:** Treat identically to gate (a) dirty path —
|
|
92
|
-
fix in same PR, restart convergence from BUGBOT.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
back-to-back-clean cycle plus all four gates must hold again on new HEAD.
|
|
97
|
+
spawn Agent (subagent_type: clean-coder) to fix in same PR, restart convergence from BUGBOT. Follow [Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow).
|
|
98
|
+
For body-only findings with empty inline, spawn Agent (subagent_type: clean-coder) to implement, then post top-level review reply
|
|
99
|
+
citing new HEAD SHA. Reset `bugbot_clean_at = null` AND
|
|
100
|
+
`copilot_clean_at = null`, `phase = BUGBOT`, schedule next wakeup,
|
|
101
|
+
return. Full back-to-back-clean cycle plus all four gates must hold
|
|
102
|
+
again on new HEAD.
|
|
99
103
|
- **No Copilot review at `current_head` yet (still propagating):**
|
|
100
104
|
Schedule one more wakeup (270s), re-check next tick. After three consecutive empty waits,
|
|
101
105
|
escalate as hard blocker per [stop-conditions.md](stop-conditions.md).
|
|
@@ -103,16 +107,14 @@ Next tick with `phase == BUGTEAM` and prior state preserved → re-run gate
|
|
|
103
107
|
## (d) Mark ready and report
|
|
104
108
|
|
|
105
109
|
Only when all four gates pass — bugbot CLEAN ∧ bugteam CLEAN ∧
|
|
106
|
-
`
|
|
110
|
+
`mergeable_state == "clean"` ∧ Copilot CLEAN at HEAD — run:
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
```
|
|
112
|
+
Use the `update_pull_request` MCP tool:
|
|
113
|
+
|
|
114
|
+
update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
equivalent. With `state.json`, append convergence row to
|
|
116
|
+
With `state.json`, append convergence row to
|
|
115
117
|
`<TMPDIR>/pr-converge-<session_id>/converged.log` per `multi-pr-orchestration.md` §Memory; else skip.
|
|
116
118
|
Report: `PR #<NUMBER> converged: bugbot CLEAN at <SHA>, bugteam CLEAN at
|
|
117
|
-
<SHA>,
|
|
119
|
+
<SHA>, mergeable_state CLEAN, copilot CLEAN at <SHA>; marked ready for
|
|
118
120
|
review`. **Omit loop pacing** per **Convergence** of active pacing workflow.
|
|
@@ -25,7 +25,7 @@ convergence or stop]
|
|
|
25
25
|
</example>
|
|
26
26
|
|
|
27
27
|
<example> BUGTEAM phase, bugteam reports convergence and `bugbot_clean_at
|
|
28
|
-
== current_head`. Claude: [runs `
|
|
28
|
+
== current_head`. Claude: [runs `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`, reports "PR
|
|
29
29
|
converged: bugbot CLEAN at <SHA>, bugteam CLEAN at <SHA>; marked ready for
|
|
30
30
|
review", applies **Convergence** from `workflows/schedule-wakeup-loop.md`]
|
|
31
31
|
</example>
|
|
@@ -58,11 +58,11 @@ HEAD, schedules next wakeup]
|
|
|
58
58
|
</example>
|
|
59
59
|
|
|
60
60
|
<example> Back-to-back clean, mergeability CLEAN, no Copilot review on
|
|
61
|
-
`current_head`. Claude requests Copilot via `
|
|
61
|
+
`current_head`. Claude requests Copilot via `add_issue_comment(owner=OWNER, repo=REPO, issueNumber=NUMBER, body="@copilot review")`,
|
|
62
62
|
waits one tick. Next tick: Copilot review `state: APPROVED`. Claude: [sets
|
|
63
|
-
`copilot_clean_at = current_head`; runs `
|
|
63
|
+
`copilot_clean_at = current_head`; runs `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`; reports "PR
|
|
64
64
|
#N converged: bugbot CLEAN at <SHA>, bugteam CLEAN at <SHA>,
|
|
65
|
-
|
|
65
|
+
mergeable_state clean, copilot CLEAN; marked ready for review"]
|
|
66
66
|
</example>
|
|
67
67
|
|
|
68
68
|
<example> Back-to-back clean, mergeability CLEAN, post-convergence Copilot
|
|
@@ -8,8 +8,8 @@ per [ground-rules.md](ground-rules.md).
|
|
|
8
8
|
**Multi-PR (`state.json`) teammate obligations** (plus TDD, commit, push):
|
|
9
9
|
|
|
10
10
|
- Replies inline on each addressed finding via
|
|
11
|
-
`
|
|
12
|
-
matching §Audit result → fix worker step 4 — **before** writing
|
|
11
|
+
`add_reply_to_pull_request_comment(owner, repo, pullNumber, commentId, body)`
|
|
12
|
+
(what changed + commit identifier), matching §Audit result → fix worker step 4 — **before** writing
|
|
13
13
|
`state.json` and going idle.
|
|
14
14
|
- Writes `last_action: "fix_pushed"`, `current_head: <new SHA>`,
|
|
15
15
|
`bugbot_clean_at: null`, `phase: "BUGBOT"`, `status: "awaiting_bugbot"`,
|
|
@@ -20,6 +20,8 @@ per [ground-rules.md](ground-rules.md).
|
|
|
20
20
|
Orchestrator does not reply inline, trigger bugbot, or read repo source
|
|
21
21
|
files during fix phase in multi-PR mode.
|
|
22
22
|
|
|
23
|
+
### Single-PR fix workflow
|
|
24
|
+
|
|
23
25
|
**Single-PR (no `state.json`) — same gates, main session executor:**
|
|
24
26
|
|
|
25
27
|
- Read each referenced file:line.
|
|
@@ -38,12 +40,10 @@ git push origin <BRANCH>
|
|
|
38
40
|
```
|
|
39
41
|
**Pre-push gate:** honor hooks; full-stop on bypass. Capture new HEAD
|
|
40
42
|
only after both gates pass; set `current_head`, `bugbot_clean_at = null`.
|
|
41
|
-
- Reply inline on each addressed comment thread using
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
--owner <OWNER> --repo <REPO> --number <NUMBER> \
|
|
46
|
-
--comment-id <COMMENT_ID> --body-file <path/to/reply.md>
|
|
43
|
+
- Reply inline on each addressed comment thread using the `add_reply_to_pull_request_comment` MCP tool:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
add_reply_to_pull_request_comment(owner=OWNER, repo=REPO, pullNumber=NUMBER, commentId=COMMENT_ID, body="Fixed in <SHA> — <what changed>")
|
|
47
47
|
```
|
|
48
48
|
- **After pushing a fix, always run Step 3 (`bugbot run`) in the same
|
|
49
49
|
tick** regardless of phase. New commit **resets full convergence cycle**:
|
|
@@ -25,7 +25,7 @@ Create once at session start. Each teammate writes result before going idle.
|
|
|
25
25
|
|
|
26
26
|
**Directory lifecycle:** Keep `<TMPDIR>/pr-converge-<session_id>/` until every
|
|
27
27
|
`prs[...]` is `converged` or `blocked`, or user stops. Then delete folder.
|
|
28
|
-
`
|
|
28
|
+
`update_pull_request(draft=false)` on GitHub is canonical record. See
|
|
29
29
|
[Memory](#memory) for optional append-only log.
|
|
30
30
|
|
|
31
31
|
**Barebones schema:**
|
|
@@ -107,7 +107,7 @@ Bugfind subagent completes (findings or clean):
|
|
|
107
107
|
2. Applies TDD fixes (test first, then production).
|
|
108
108
|
3. Commits, pushes one fix commit.
|
|
109
109
|
4. Replies inline on each addressed finding via
|
|
110
|
-
`
|
|
110
|
+
`add_reply_to_pull_request_comment(owner, repo, pullNumber, commentId, body)`.
|
|
111
111
|
5. Writes `state.json` (per §Concurrency): `last_action: "fix_pushed"`,
|
|
112
112
|
`current_head: <new SHA>`, `bugbot_clean_at: null`, `phase:
|
|
113
113
|
"BUGBOT"`, `status: "awaiting_bugbot"`, `last_updated` ISO-8601 UTC.
|
|
@@ -116,7 +116,7 @@ Bugfind subagent completes (findings or clean):
|
|
|
116
116
|
- **PRs with zero findings:** spawn one `general-purpose` subagent per PR via
|
|
117
117
|
`Agent(subagent_type="general-purpose", run_in_background=true)`. Subagent:
|
|
118
118
|
1. `bugbot_clean_at == current_head` (back-to-back clean): run
|
|
119
|
-
`
|
|
119
|
+
`update_pull_request(pullNumber=PR_NUMBER, owner=OWNER, repo=REPO, draft=false)`, append convergence row to
|
|
120
120
|
`<TMPDIR>/pr-converge-<session_id>/converged.log` per §Memory, then
|
|
121
121
|
write `state.json` (per §Concurrency) with `status: "converged"`,
|
|
122
122
|
`last_action: "converged"` (or `marked_ready`), `phase: "BUGBOT"`,
|
|
@@ -125,7 +125,7 @@ Bugfind subagent completes (findings or clean):
|
|
|
125
125
|
duplicate work.
|
|
126
126
|
2. Else: update `state.json` (per §Concurrency) with `last_action:
|
|
127
127
|
"audit_clean"`, `status: "awaiting_bugbot"`, `phase: "BUGBOT"`, then
|
|
128
|
-
trigger bugbot via `
|
|
128
|
+
trigger bugbot via `add_issue_comment(owner, repo, issueNumber, body="bugbot run")`.
|
|
129
129
|
3. Goes idle.
|
|
130
130
|
|
|
131
131
|
### Fix result → general-purpose per PR
|
|
@@ -135,11 +135,11 @@ When bugfix (clean-coder) subagent completes after push:
|
|
|
135
135
|
- Spawn one `general-purpose` subagent per PR via
|
|
136
136
|
`Agent(subagent_type="general-purpose", run_in_background=true)`. Subagent:
|
|
137
137
|
1. Reads `state.json` for its PR.
|
|
138
|
-
2. Triggers bugbot via `
|
|
139
|
-
3. Polls `
|
|
140
|
-
anchored to `current_head` appears
|
|
138
|
+
2. Triggers bugbot via `add_issue_comment(owner, repo, issueNumber, body="bugbot run")`.
|
|
139
|
+
3. Polls `pull_request_read(method="get_reviews")` every 60s (up to 10 polls) until review
|
|
140
|
+
anchored to `current_head` appears with `commit_id == current_head`.
|
|
141
141
|
4. **Poll / classify loop** (repeat from 4a whenever 4c retries):
|
|
142
|
-
- **4a.** Fetch inline comments via `
|
|
142
|
+
- **4a.** Fetch inline comments via `pull_request_read(method="get_review_comments")` filtered by review ID and `commit_id == current_head`.
|
|
143
143
|
- **4b.** Classify — three outcomes (same as `SKILL.md` Step 2 BUGBOT):
|
|
144
144
|
- **`clean`:** review body clean, zero unaddressed inline findings.
|
|
145
145
|
- **`dirty`:** ≥1 unaddressed inline finding for `current_head`
|
|
@@ -186,7 +186,7 @@ When bugfix (clean-coder) subagent completes after push:
|
|
|
186
186
|
Run directory `<TMPDIR>/pr-converge-<session_id>/` holds `state.json` and
|
|
187
187
|
optional `converged.log`. Keep from first create until every PR under `prs`
|
|
188
188
|
is `converged` or `blocked`, or **Stop conditions** ends loop. Safe to
|
|
189
|
-
delete folder after — `
|
|
189
|
+
delete folder after — `update_pull_request(draft=false)` on GitHub is
|
|
190
190
|
canonical record. Folder skill, not a plugin package; do **not** rely
|
|
191
191
|
on `${CLAUDE_PLUGIN_DATA}`. OS/disk cleanup of `<TMPDIR>` (reboot, policy)
|
|
192
192
|
can remove files mid-run — environmental risk.
|
|
@@ -196,7 +196,7 @@ can remove files mid-run — environmental risk.
|
|
|
196
196
|
- **Path:** sibling of `state.json`.
|
|
197
197
|
- **Format:** one tab-separated row per converged PR: ISO8601 UTC,
|
|
198
198
|
owner/repo#number, bugbot SHA, bugteam SHA.
|
|
199
|
-
- **Append site:** agent running `
|
|
199
|
+
- **Append site:** agent running `update_pull_request(pullNumber=PR_NUMBER, owner=OWNER, repo=REPO, draft=false)`. Append **before**
|
|
200
200
|
locked `state.json` publish so log row survives failed merge.
|
|
201
201
|
- **Never read inside loop.** User / follow-up tooling only.
|
|
202
202
|
|
|
@@ -37,10 +37,12 @@ state line when **no** `state.json` (single-PR only). With `state.json`, do
|
|
|
37
37
|
**not** increment here — orchestrator's per-tick bump is sole increment.
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
|
|
40
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get") → `.head.sha`
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
If owner/repo/number are not yet known, extract them from the PR URL.
|
|
44
|
+
|
|
45
|
+
Capture `number`, `head.sha` (= `current_head`), owner/repo, branch.
|
|
44
46
|
|
|
45
47
|
## Step 2: Branch on `phase`
|
|
46
48
|
|
|
@@ -48,15 +50,14 @@ Capture `number`, `headRefOid` (= `current_head`), owner/repo, branch.
|
|
|
48
50
|
|
|
49
51
|
a. Fetch Cursor Bugbot reviews newest-first, walk back until first clean:
|
|
50
52
|
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
```
|
|
54
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_reviews")
|
|
55
|
+
→ filter `.user.login` for cursor/bugbot, sort by `.submitted_at` descending
|
|
54
56
|
```
|
|
55
57
|
|
|
56
|
-
Track dirty entries
|
|
57
|
-
this tick.
|
|
58
|
+
Track dirty entries (review body contains `BUGBOT_REVIEW` markers with finding content); Fix protocol reads them back later this tick.
|
|
58
59
|
|
|
59
|
-
Iterate from index 0 (most recent) toward older:
|
|
60
|
+
Iterate from index 0 (most recent) toward older:
|
|
60
61
|
|
|
61
62
|
- Dirty review → append JSON line with `{review_id, commit_id,
|
|
62
63
|
submitted_at, body}`.
|
|
@@ -69,14 +70,12 @@ review for decisions below. When branch routes to **Fix protocol**, address
|
|
|
69
70
|
**every** entry in `$dirty_reviews_path` — not just index 0.
|
|
70
71
|
|
|
71
72
|
b. Fetch unaddressed inline comments from `cursor[bot]` for newest Bugbot
|
|
72
|
-
review on `current_head
|
|
73
|
-
resolves review via reviews list, returns only inline rows whose
|
|
74
|
-
`pull_request_review_id` matches that review (excludes stale threads from
|
|
75
|
-
older reviews on same SHA).
|
|
73
|
+
review on `current_head`:
|
|
76
74
|
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
```
|
|
76
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_review_comments")
|
|
77
|
+
→ filter threads where `is_outdated == false` AND `is_resolved == false`
|
|
78
|
+
AND any comment has `.author` matching cursor/bugbot (case-insensitive substring)
|
|
80
79
|
```
|
|
81
80
|
|
|
82
81
|
c. Decide (four branches; match first whose predicate holds):
|
|
@@ -93,9 +92,11 @@ c. Decide (four branches; match first whose predicate holds):
|
|
|
93
92
|
`state.json`: clean-coder teammate pushes, replies inline, writes
|
|
94
93
|
`state.json`, goes idle; Step 3 on new HEAD runs after via
|
|
95
94
|
orchestrator-spawned follow-up agent (§Fix result → general-purpose).
|
|
96
|
-
No `state.json` (single-PR): implement → push → inline
|
|
97
|
-
→ Step 3 in same tick
|
|
98
|
-
|
|
95
|
+
No `state.json` (single-PR): spawn Agent (subagent_type: clean-coder) to implement → push → reply inline on each thread
|
|
96
|
+
via `add_reply_to_pull_request_comment` MCP → Step 3 in same tick (see
|
|
97
|
+
[Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow) for
|
|
98
|
+
full contract).
|
|
99
|
+
Schedule next wakeup, return.
|
|
99
100
|
- **`commit_id == current_head` AND review body findings AND inline
|
|
100
101
|
API zero matching for `current_head`:** Transient API lag. Increment
|
|
101
102
|
`inline_lag_streak`. `>= 3` → hard blocker; report and terminate with
|
|
@@ -121,8 +122,7 @@ Skill({skill: "bugteam", args:
|
|
|
121
122
|
b. **Re-resolve current HEAD** — bugteam may have pushed commits during
|
|
122
123
|
its run. `current_head` from Step 1 is potentially stale:
|
|
123
124
|
```bash
|
|
124
|
-
|
|
125
|
-
--owner <OWNER> --repo <REPO> --number <NUMBER>)
|
|
125
|
+
pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get") → `.head.sha`
|
|
126
126
|
```
|
|
127
127
|
If `new_head != current_head`, set `current_head = new_head` AND
|
|
128
128
|
`bugbot_clean_at = null`. New commits invalidate bugbot's prior clean.
|
|
@@ -142,26 +142,14 @@ never falsely terminates:
|
|
|
142
142
|
**omit loop pacing** per **Convergence** of active pacing workflow.
|
|
143
143
|
- **Convergence BUT `bugbot_clean_at != current_head` (no push):**
|
|
144
144
|
`phase = BUGBOT`, schedule next wakeup, return.
|
|
145
|
-
- **Findings without committed fixes:**
|
|
146
|
-
|
|
147
|
-
single-PR. `phase = BUGBOT`, schedule next wakeup, return.
|
|
145
|
+
- **Findings without committed fixes:** spawn Agent (subagent_type: clean-coder) to implement fixes and push, then reply inline via `add_reply_to_pull_request_comment` MCP, following [Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow).
|
|
146
|
+
`phase = BUGBOT`, schedule next wakeup, return.
|
|
148
147
|
|
|
149
148
|
## Step 3: Re-trigger bugbot
|
|
150
149
|
|
|
151
|
-
|
|
150
|
+
Use the `add_issue_comment` MCP tool:
|
|
152
151
|
|
|
153
|
-
|
|
154
|
-
python "${CLAUDE_SKILL_DIR}/scripts/trigger_bugbot.py" \
|
|
155
|
-
--owner <OWNER> --repo <REPO> --number <NUMBER>
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
**Bundled PowerShell alternative** (same gh-body-file contract):
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
POST_BUGBOT_RUN="$HOME/.claude/skills/pr-converge/scripts/post-bugbot-run.ps1"
|
|
162
|
-
pwsh -NoProfile -ExecutionPolicy Bypass -File "$POST_BUGBOT_RUN" \
|
|
163
|
-
"https://github.com/<OWNER>/<REPO>/pull/<NUMBER>"
|
|
164
|
-
```
|
|
152
|
+
add_issue_comment(owner="OWNER", repo="REPO", issueNumber=NUMBER, body="bugbot run")
|
|
165
153
|
|
|
166
154
|
`bugbot run` is empirically the only re-trigger Cursor Bugbot recognizes;
|
|
167
155
|
alternative phrasings (`re-review`, `bugbot please`, etc.) silently no-op.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Stop conditions
|
|
2
2
|
|
|
3
3
|
- **Convergence** (back-to-back clean ∧ no outstanding Copilot findings
|
|
4
|
-
on `current_head` ∧ `
|
|
5
|
-
|
|
6
|
-
`current_head`):
|
|
4
|
+
on `current_head` ∧ `mergeable_state == "clean"` with `mergeable ==
|
|
5
|
+
true` ∧ post-convergence Copilot request returned `clean` at
|
|
6
|
+
`current_head`): use `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`. With
|
|
7
7
|
`state.json`, append convergence row to
|
|
8
8
|
`<TMPDIR>/pr-converge-<session_id>/converged.log` per `multi-pr-orchestration.md` §Memory; else
|
|
9
9
|
skip. Report [convergence-gates.md](convergence-gates.md) (d) summary, then **omit loop pacing**
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
`current_head` after three consecutive wakeups. Report specific
|
|
17
17
|
blocker and diagnosis, **omit loop pacing** per
|
|
18
18
|
`../workflows/schedule-wakeup-loop.md`.
|
|
19
|
-
- **Hard blocker (`
|
|
20
|
-
`
|
|
19
|
+
- **Hard blocker (`mergeable_state` non-clean non-dirty):**
|
|
20
|
+
`mergeable_state` is `"blocked"`, `"unknown"`, or `"behind"` (required
|
|
21
21
|
checks pending, branch behind base without textual conflicts, or
|
|
22
22
|
GitHub indeterminate). Investigate before retrying; `rebase` skill
|
|
23
|
-
handles `
|
|
24
|
-
`
|
|
23
|
+
handles `"dirty"` (textual conflicts) only. Report specific
|
|
24
|
+
`mergeable_state`, **omit loop pacing**.
|
|
25
25
|
- **User stops loop:** "stop the converge loop" → **omit loop pacing**
|
|
26
26
|
per `../workflows/schedule-wakeup-loop.md`.
|