claude-dev-env 1.38.1 → 1.40.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 (282) hide show
  1. package/CLAUDE.md +10 -36
  2. package/_shared/pr-loop/audit-reply-template.md +147 -0
  3. package/_shared/pr-loop/fix-protocol.md +25 -4
  4. package/_shared/pr-loop/gh-payloads.md +37 -50
  5. package/_shared/pr-loop/scripts/code_rules_gate.py +0 -60
  6. package/_shared/pr-loop/scripts/config/post_audit_thread_constants.py +199 -0
  7. package/_shared/pr-loop/scripts/config/reviews_disabled_constants.py +8 -0
  8. package/_shared/pr-loop/scripts/post_audit_thread.py +1242 -0
  9. package/_shared/pr-loop/scripts/preflight.py +129 -2
  10. package/_shared/pr-loop/scripts/reviews_disabled.py +59 -0
  11. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -19
  12. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +1116 -0
  13. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +127 -0
  14. package/_shared/pr-loop/scripts/tests/test_preflight.py +41 -0
  15. package/_shared/pr-loop/scripts/tests/test_reviews_disabled.py +36 -0
  16. package/_shared/pr-loop/state-schema.md +1 -1
  17. package/agents/clean-coder.md +2 -2
  18. package/agents/pr-description-writer.md +150 -52
  19. package/bin/install.mjs +6 -7
  20. package/bin/install.test.mjs +8 -0
  21. package/commands/doc-gist.md +16 -0
  22. package/commands/plan.md +0 -2
  23. package/commands/review-plan.md +1 -1
  24. package/docs/CODE_RULES.md +122 -2
  25. package/docs/PR_DESCRIPTION_GUIDE.md +127 -64
  26. package/hooks/blocking/bot_mention_comment_blocker.py +75 -0
  27. package/hooks/blocking/code_rules_enforcer.py +1143 -129
  28. package/hooks/blocking/convergence_gate_blocker.py +130 -0
  29. package/hooks/blocking/destructive_command_blocker.py +74 -0
  30. package/hooks/blocking/gh_body_arg_blocker.py +30 -0
  31. package/hooks/blocking/md_to_html_blocker.py +119 -0
  32. package/hooks/blocking/pr_description_enforcer.py +57 -22
  33. package/hooks/blocking/test_bot_mention_comment_blocker.py +131 -0
  34. package/hooks/blocking/test_code_rules_enforcer.py +21 -0
  35. package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +70 -0
  36. package/hooks/blocking/test_code_rules_enforcer_any_imports_and_cast.py +92 -0
  37. package/hooks/blocking/test_code_rules_enforcer_banned_import_alias.py +143 -0
  38. package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +152 -0
  39. package/hooks/blocking/test_code_rules_enforcer_bare_except.py +120 -0
  40. package/hooks/blocking/test_code_rules_enforcer_boundary_types.py +175 -0
  41. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
  42. package/hooks/blocking/test_code_rules_enforcer_collection_prefix.py +50 -0
  43. package/hooks/blocking/test_code_rules_enforcer_docstring_format.py +255 -0
  44. package/hooks/blocking/test_code_rules_enforcer_inline_tuple_string_magic.py +130 -0
  45. package/hooks/blocking/test_code_rules_enforcer_stub_implementations.py +141 -0
  46. package/hooks/blocking/test_code_rules_enforcer_test_branching.py +143 -0
  47. package/hooks/blocking/test_code_rules_enforcer_thin_wrapper_files.py +169 -0
  48. package/hooks/blocking/test_code_rules_enforcer_todo_markers.py +99 -0
  49. package/hooks/blocking/test_code_rules_enforcer_typed_dict_pairs.py +141 -0
  50. package/hooks/blocking/test_convergence_gate_blocker.py +63 -0
  51. package/hooks/blocking/test_destructive_command_blocker.py +146 -0
  52. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +102 -0
  53. package/hooks/blocking/test_gh_body_arg_blocker.py +45 -0
  54. package/hooks/blocking/test_md_to_html_blocker.py +317 -0
  55. package/hooks/blocking/test_pr_description_enforcer.py +69 -8
  56. package/hooks/config/any_type_config.py +7 -0
  57. package/hooks/config/banned_identifiers_constants.py +11 -0
  58. package/hooks/config/blocking_check_limits.py +38 -0
  59. package/hooks/config/bot_mention_comment_blocker_constants.py +20 -0
  60. package/hooks/config/code_rules_enforcer_constants.py +53 -0
  61. package/hooks/config/convergence_branch_constants.py +9 -0
  62. package/hooks/config/doc_gist_auto_publish_constants.py +18 -0
  63. package/hooks/config/html_companion_constants.py +20 -0
  64. package/hooks/config/inline_tuple_string_magic_constants.py +22 -0
  65. package/hooks/config/pr_description_enforcer_constants.py +14 -0
  66. package/hooks/config/test_banned_identifiers_constants.py +17 -0
  67. package/hooks/hooks.json +28 -20
  68. package/hooks/pyproject.toml +69 -0
  69. package/hooks/validators/mypy_integration.py +47 -1
  70. package/hooks/validators/run_all_validators.py +3 -3
  71. package/hooks/validators/test_mypy_integration.py +50 -1
  72. package/hooks/workflow/doc_gist_auto_publish.py +144 -0
  73. package/hooks/workflow/md_to_html_companion.py +365 -0
  74. package/hooks/workflow/test_doc_gist_auto_publish.py +117 -0
  75. package/hooks/workflow/test_md_to_html_companion.py +452 -0
  76. package/package.json +1 -1
  77. package/rules/gh-body-file.md +2 -0
  78. package/scripts/Install-SweepEmptyDirs.ps1 +111 -0
  79. package/scripts/check.ps1 +106 -0
  80. package/scripts/config/timing.py +11 -0
  81. package/scripts/sweep_empty_dirs.py +138 -0
  82. package/scripts/sync_to_cursor/rules.py +1 -1
  83. package/scripts/test_sweep_empty_dirs.py +183 -0
  84. package/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +323 -0
  85. package/skills/_shared/pr-loop/scripts/_cli_utils.py +22 -0
  86. package/skills/_shared/pr-loop/scripts/_path_resolver.py +165 -0
  87. package/skills/_shared/pr-loop/scripts/_xml_utils.py +20 -0
  88. package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +182 -0
  89. package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +185 -0
  90. package/skills/_shared/pr-loop/scripts/config/__init__.py +0 -0
  91. package/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py +78 -0
  92. package/skills/_shared/pr-loop/scripts/init_loop_state.py +135 -0
  93. package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +175 -0
  94. package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +182 -0
  95. package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +206 -0
  96. package/skills/bugteam/CONSTRAINTS.md +21 -22
  97. package/skills/bugteam/EXAMPLES.md +3 -3
  98. package/skills/bugteam/PROMPTS.md +227 -67
  99. package/skills/bugteam/SKILL.md +132 -455
  100. package/skills/bugteam/reference/README.md +1 -1
  101. package/skills/bugteam/reference/audit-and-teammates.md +112 -39
  102. package/skills/bugteam/reference/audit-contract.md +4 -22
  103. package/skills/bugteam/reference/copilot-gap-analysis.md +8 -5
  104. package/skills/bugteam/reference/design-rationale.md +2 -2
  105. package/skills/bugteam/reference/github-pr-reviews.md +50 -57
  106. package/skills/bugteam/reference/obstacles/audit-assign-ids.md +13 -0
  107. package/skills/bugteam/reference/obstacles/audit-capture-excerpts.md +13 -0
  108. package/skills/bugteam/reference/obstacles/audit-walk-categories.md +13 -0
  109. package/skills/bugteam/reference/obstacles/audit-write-xml.md +13 -0
  110. package/skills/bugteam/reference/obstacles/fix-append-summary.md +13 -0
  111. package/skills/bugteam/reference/obstacles/fix-apply-fixes.md +13 -0
  112. package/skills/bugteam/reference/obstacles/fix-git-add-commit.md +13 -0
  113. package/skills/bugteam/reference/obstacles/fix-git-push.md +13 -0
  114. package/skills/bugteam/reference/obstacles/fix-post-reply.md +13 -0
  115. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +13 -0
  116. package/skills/bugteam/reference/obstacles/fix-py-compile.md +13 -0
  117. package/skills/bugteam/reference/obstacles/fix-read-files.md +13 -0
  118. package/skills/bugteam/reference/obstacles/fix-resolve-thread.md +13 -0
  119. package/skills/bugteam/reference/obstacles/fix-test-suite.md +13 -0
  120. package/skills/bugteam/reference/obstacles/fix-violation-count.md +13 -0
  121. package/skills/bugteam/reference/obstacles/fix-write-xml.md +13 -0
  122. package/skills/bugteam/reference/team-setup.md +111 -9
  123. package/skills/bugteam/reference/teardown-publish-permissions.md +39 -8
  124. package/skills/bugteam/scripts/README.md +60 -0
  125. package/skills/bugteam/scripts/_claude_permissions_common.py +358 -0
  126. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +976 -0
  127. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +375 -0
  128. package/skills/bugteam/scripts/bugteam_preflight.py +328 -0
  129. package/skills/bugteam/scripts/config/bugteam_code_rules_gate_constants.py +25 -0
  130. package/skills/bugteam/scripts/config/bugteam_fix_hookspath_constants.py +26 -0
  131. package/skills/bugteam/scripts/config/bugteam_preflight_constants.py +35 -0
  132. package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +20 -0
  133. package/skills/bugteam/scripts/config/probe_code_rules_enforcer_check_constants.py +12 -0
  134. package/skills/bugteam/scripts/config/windows_safe_rmtree_constants.py +7 -0
  135. package/skills/bugteam/scripts/grant_project_claude_permissions.py +175 -0
  136. package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +107 -0
  137. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +220 -0
  138. package/skills/bugteam/scripts/test__claude_permissions_common.py +112 -0
  139. package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +400 -0
  140. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +384 -0
  141. package/skills/bugteam/scripts/test_bugteam_preflight.py +309 -0
  142. package/skills/bugteam/scripts/test_claude_permissions_common.py +195 -0
  143. package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +55 -0
  144. package/skills/bugteam/scripts/test_probe_code_rules_enforcer_check.py +76 -0
  145. package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +55 -0
  146. package/skills/bugteam/scripts/test_windows_safe_rmtree.py +108 -0
  147. package/skills/bugteam/scripts/windows_safe_rmtree.py +100 -0
  148. package/skills/bugteam/test_skill_additions.py +1 -11
  149. package/skills/code/SKILL.md +176 -0
  150. package/skills/copilot-review/SKILL.md +16 -0
  151. package/skills/doc-gist/SKILL.md +99 -0
  152. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +453 -0
  153. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +515 -0
  154. package/skills/doc-gist/references/examples/03-code-review-pr.html +638 -0
  155. package/skills/doc-gist/references/examples/04-code-understanding.html +491 -0
  156. package/skills/doc-gist/references/examples/05-design-system.html +629 -0
  157. package/skills/doc-gist/references/examples/06-component-variants.html +605 -0
  158. package/skills/doc-gist/references/examples/07-prototype-animation.html +455 -0
  159. package/skills/doc-gist/references/examples/08-prototype-interaction.html +396 -0
  160. package/skills/doc-gist/references/examples/09-slide-deck.html +592 -0
  161. package/skills/doc-gist/references/examples/10-svg-illustrations.html +492 -0
  162. package/skills/doc-gist/references/examples/11-status-report.html +528 -0
  163. package/skills/doc-gist/references/examples/12-incident-report.html +596 -0
  164. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +395 -0
  165. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +381 -0
  166. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +368 -0
  167. package/skills/doc-gist/references/examples/16-implementation-plan.html +702 -0
  168. package/skills/doc-gist/references/examples/17-pr-writeup.html +595 -0
  169. package/skills/doc-gist/references/examples/18-editor-triage-board.html +573 -0
  170. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +663 -0
  171. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +722 -0
  172. package/skills/doc-gist/references/examples/README.md +5 -0
  173. package/skills/doc-gist/scripts/config/__init__.py +0 -0
  174. package/skills/doc-gist/scripts/config/gist_upload_constants.py +16 -0
  175. package/skills/doc-gist/scripts/gist_upload.py +177 -0
  176. package/skills/doc-gist/scripts/test_gist_upload.py +51 -0
  177. package/skills/findbugs/SKILL.md +96 -2
  178. package/skills/monitor-open-prs/SKILL.md +14 -32
  179. package/skills/monitor-open-prs/test_skill_contract.py +0 -11
  180. package/skills/pr-consistency-audit/SKILL.md +112 -0
  181. package/skills/pr-consistency-audit/reference/detection-rules.md +96 -0
  182. package/skills/pr-consistency-audit/reference/illustrations.md +78 -0
  183. package/skills/pr-converge/SKILL.md +229 -23
  184. package/skills/pr-converge/config/__init__.py +0 -0
  185. package/skills/pr-converge/config/constants.py +63 -0
  186. package/skills/pr-converge/reference/convergence-gates.md +138 -44
  187. package/skills/pr-converge/reference/examples.md +43 -11
  188. package/skills/pr-converge/reference/fix-protocol.md +6 -5
  189. package/skills/pr-converge/reference/ground-rules.md +5 -3
  190. package/skills/pr-converge/reference/multi-pr-orchestration.md +44 -19
  191. package/skills/pr-converge/reference/obstacles/fix-post-replies.md +13 -0
  192. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +13 -0
  193. package/skills/pr-converge/reference/obstacles/fix-push.md +13 -0
  194. package/skills/pr-converge/reference/obstacles/fix-read-filelines.md +13 -0
  195. package/skills/pr-converge/reference/obstacles/fix-reset-state.md +13 -0
  196. package/skills/pr-converge/reference/obstacles/fix-resolve-threads.md +13 -0
  197. package/skills/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +13 -0
  198. package/skills/pr-converge/reference/obstacles/fix-stage-commit.md +13 -0
  199. package/skills/pr-converge/reference/obstacles/fix-trigger-bugbot.md +13 -0
  200. package/skills/pr-converge/reference/obstacles/fix-write-test.md +13 -0
  201. package/skills/pr-converge/reference/per-tick.md +107 -31
  202. package/skills/pr-converge/reference/state-schema.md +22 -1
  203. package/skills/pr-converge/reference/stop-conditions.md +9 -7
  204. package/skills/pr-converge/scripts/README.md +34 -46
  205. package/skills/pr-converge/scripts/check_bugbot_ci.py +279 -0
  206. package/skills/pr-converge/scripts/check_convergence.py +497 -0
  207. package/skills/pr-converge/scripts/check_pending_reviews.py +154 -0
  208. package/skills/pr-converge/scripts/config/pr_converge_constants.py +118 -0
  209. package/skills/pr-converge/scripts/fetch_copilot_reviews.py +134 -0
  210. package/skills/pr-converge/scripts/post_fix_reply.py +168 -0
  211. package/skills/pr-converge/scripts/test_check_bugbot_ci.py +312 -0
  212. package/skills/pr-converge/workflows/schedule-wakeup-loop.md +5 -12
  213. package/skills/qbug/SKILL.md +157 -27
  214. package/skills/session-log/SKILL.md +216 -114
  215. package/skills/session-tidy/SKILL.md +1 -1
  216. package/skills/skill-builder/SKILL.md +138 -56
  217. package/skills/skill-builder/references/delegation-map.md +72 -113
  218. package/skills/skill-builder/references/progressive-disclosure.md +122 -0
  219. package/skills/skill-builder/references/self-audit-checklist.md +92 -0
  220. package/skills/skill-builder/references/skill-types.md +228 -0
  221. package/skills/skill-builder/references/thariq-x-post-skills.json +33 -0
  222. package/skills/skill-builder/templates/gap-analysis.md +15 -8
  223. package/skills/skill-builder/workflows/improve-skill.md +86 -57
  224. package/skills/skill-builder/workflows/new-skill.md +80 -168
  225. package/skills/skill-builder/workflows/polish-skill.md +78 -54
  226. package/skills/structure-prompt/SKILL.md +50 -0
  227. package/skills/structure-prompt/reference/adversarial-tuning.md +62 -0
  228. package/skills/structure-prompt/reference/block-classification.md +27 -0
  229. package/skills/structure-prompt/reference/canonical-case.md +48 -0
  230. package/skills/structure-prompt/reference/citation-depth.md +70 -0
  231. package/skills/structure-prompt/reference/cleanup.md +33 -0
  232. package/skills/structure-prompt/reference/constraints.md +33 -0
  233. package/skills/structure-prompt/reference/directives.md +37 -0
  234. package/skills/structure-prompt/reference/examples.md +72 -0
  235. package/skills/structure-prompt/reference/instantiation.md +51 -0
  236. package/skills/structure-prompt/reference/output-contract.md +72 -0
  237. package/skills/structure-prompt/reference/per-category.md +23 -0
  238. package/skills/structure-prompt/reference/persona.md +38 -0
  239. package/skills/structure-prompt/reference/research.md +33 -0
  240. package/skills/structure-prompt/reference/structure.md +28 -0
  241. package/agents/code-standards-agent.md +0 -93
  242. package/agents/groq-coder.md +0 -113
  243. package/agents/plan-executor.md +0 -226
  244. package/agents/project-docs-analyzer.md +0 -53
  245. package/agents/project-structure-organizer-agent.md +0 -72
  246. package/agents/skill-to-agent-converter.md +0 -370
  247. package/agents/skill-writer-agent.md +0 -470
  248. package/agents/user-docs-writer.md +0 -67
  249. package/agents/workflow-visual-documenter.md +0 -82
  250. package/commands/readability-review.md +0 -20
  251. package/hooks/mypy.ini +0 -2
  252. package/hooks/notification/attention_needed_notify.py +0 -71
  253. package/hooks/notification/claude_notification_handler.py +0 -67
  254. package/hooks/notification/notification_utils.py +0 -267
  255. package/hooks/notification/subagent_complete_notify.py +0 -381
  256. package/hooks/notification/test_attention_needed_notify.py +0 -47
  257. package/hooks/notification/test_claude_notification_handler.py +0 -54
  258. package/hooks/notification/test_notification_utils.py +0 -91
  259. package/hooks/notification/test_subagent_complete_notify.py +0 -79
  260. package/scripts/config/groq_bugteam_config.py +0 -230
  261. package/scripts/config/test_groq_bugteam_config.py +0 -83
  262. package/scripts/config/test_spec_implementer_prompt.py +0 -32
  263. package/scripts/groq_bugteam.README.md +0 -131
  264. package/scripts/groq_bugteam.py +0 -647
  265. package/scripts/groq_bugteam_dotenv.py +0 -40
  266. package/scripts/groq_bugteam_spec.py +0 -226
  267. package/scripts/test_groq_bugteam.py +0 -529
  268. package/scripts/test_groq_bugteam_apply_fix_from_spec.py +0 -426
  269. package/scripts/test_groq_bugteam_dotenv.py +0 -66
  270. package/scripts/test_groq_bugteam_spec.py +0 -338
  271. package/skills/bugteam/SKILL_EVALS.md +0 -309
  272. package/skills/dream/SKILL.md +0 -118
  273. package/skills/ingest/SKILL.md +0 -40
  274. package/skills/npm-creator/SKILL.md +0 -187
  275. package/skills/readability-review/SKILL.md +0 -127
  276. package/skills/resume-review/SKILL.md +0 -261
  277. package/skills/rule-audit/SKILL.md +0 -307
  278. package/skills/rule-creator/SKILL.md +0 -150
  279. package/skills/searching-obsidian-vault/SKILL.md +0 -131
  280. package/skills/skill-writer/REFERENCE.md +0 -284
  281. package/skills/skill-writer/SKILL.md +0 -222
  282. package/skills/tdd-team/SKILL.md +0 -128
@@ -0,0 +1,13 @@
1
+ # Re-trigger bugbot
2
+
3
+ Run Step 3 bugbot re-trigger in same tick after push
4
+
5
+ ## Self-population
6
+
7
+ Hit a wall on this step? Spawn a background agent to record it. Keep working.
8
+
9
+ 1. Spawn — brief it: check for an open PR touching this file, add a commit to it, or create a fresh branch + worktree + draft PR.
10
+ 2. Tell the agent your obstacle and what fixed it. It writes the entry below.
11
+
12
+ ## Obstacles
13
+
@@ -0,0 +1,13 @@
1
+ # Write failing test
2
+
3
+ Write failing test first when finding has behavior to test
4
+
5
+ ## Self-population
6
+
7
+ Hit a wall on this step? Spawn a background agent to record it. Keep working.
8
+
9
+ 1. Spawn `general-purpose` — brief it: check for an open PR touching this file, add a commit to it, or create a fresh branch + worktree + draft PR.
10
+ 2. Tell the agent your obstacle and what fixed it. It writes the entry below.
11
+
12
+ ## Obstacles
13
+
@@ -23,8 +23,7 @@ protocol per [fix-protocol.md](fix-protocol.md). Pacing stays in main session vi
23
23
  Read [`../workflows/schedule-wakeup-loop.md`](../workflows/schedule-wakeup-loop.md)
24
24
  (installed copy under `$HOME/.claude/skills/pr-converge/workflows/`) before
25
25
  Step 4. The pre-flight gate guarantees `ScheduleWakeup` is invokable; the
26
- workflow file specifies delays, prompts, convergence cleanup, and
27
- inline-lag handling.
26
+ workflow file specifies delays, prompts, and convergence cleanup.
28
27
 
29
28
  - **`/pr-converge`** (default): loops until convergence. After each tick
30
29
  (unless converged or stopped), run **Step 4**.
@@ -41,6 +40,8 @@ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get") → `
41
40
  ```
42
41
 
43
42
  If owner/repo/number are not yet known, extract them from the PR URL.
43
+ If `current_head` changed since last tick, reset `bugbot_down` to `false`
44
+ (new HEAD invalidates prior down-detection state).
44
45
 
45
46
  Capture `number`, `head.sha` (= `current_head`), owner/repo, branch.
46
47
 
@@ -69,15 +70,19 @@ Capture `commit_id`, `submitted_at`, body, `classification` of index-0
69
70
  review for decisions below. When branch routes to **Fix protocol**, address
70
71
  **every** entry in `$dirty_reviews_path` — not just index 0.
71
72
 
72
- b. Fetch unaddressed inline comments from `cursor[bot]` for newest Bugbot
73
- review on `current_head`:
73
+ b. Fetch ALL unresolved inline comment threads on the PR:
74
74
 
75
75
  ```
76
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)
77
+ → filter threads where `is_resolved == false`
79
78
  ```
80
79
 
80
+ For each unresolved thread, you still need to know **who** wrote it
81
+ and **what commit** it anchors to so you can decide how to address it
82
+ — but the gate itself doesn't filter on those fields. Verify each
83
+ thread's concern against current HEAD; either fix-and-resolve or
84
+ reply-with-note-and-resolve.
85
+
81
86
  c. Decide (four branches; match first whose predicate holds):
82
87
  - **No bugbot review yet, OR latest review's `commit_id` ≠
83
88
  `current_head`:** Re-trigger bugbot (Step 3), set `bugbot_clean_at =
@@ -93,15 +98,10 @@ c. Decide (four branches; match first whose predicate holds):
93
98
  `state.json`, goes idle; Step 3 on new HEAD runs after via
94
99
  orchestrator-spawned follow-up agent (§Fix result → general-purpose).
95
100
  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
101
+ via `python ~/.claude/skills/pr-converge/scripts/post_fix_reply.py` → Step 3 in same tick (see
97
102
  [Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow) for
98
103
  full contract).
99
104
  Schedule next wakeup, return.
100
- - **`commit_id == current_head` AND review body findings AND inline
101
- API zero matching for `current_head`:** Transient API lag. Increment
102
- `inline_lag_streak`. `>= 3` → hard blocker; report and terminate with
103
- no loop pacing. Else Step 4 uses the BUGBOT inline-lag section of
104
- `../workflows/schedule-wakeup-loop.md` (`delaySeconds: 90`).
105
105
 
106
106
  ### `phase == BUGTEAM`
107
107
 
@@ -119,13 +119,28 @@ Skill({skill: "bugteam", args:
119
119
  bugteam by reading [`../../bugteam/SKILL.md`](../../bugteam/SKILL.md). Same
120
120
  loop and gates; only harness steps differ.
121
121
 
122
- b. **Re-resolve current HEAD**bugteam may have pushed commits during
123
- its run. `current_head` from Step 1 is potentially stale:
124
- ```bash
125
- pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get") → `.head.sha`
122
+ b. **Re-resolve current HEAD (MANDATORY never skip).** Bugteam may have
123
+ pushed commits during its run. `current_head` from Step 1 is stale:
124
+
125
+ ```
126
+ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get") → `.head.sha`
127
+ ```
128
+
129
+ Capture `new_head`. Then check the most recent commit timestamp:
130
+
131
+ ```
132
+ list_commits(owner=OWNER, repo=REPO, sha="<branch>")
133
+ → sort by `.commit.committer.date` descending → index 0 `.commit.committer.date`
126
134
  ```
127
- If `new_head != current_head`, set `current_head = new_head` AND
128
- `bugbot_clean_at = null`. New commits invalidate bugbot's prior clean.
135
+
136
+ If the most recent commit timestamp is **less than 60 seconds ago**, the
137
+ GitHub API may not have propagated it to review endpoints yet. Do not
138
+ proceed with convergence-gates — schedule a 90s wakeup and return.
139
+ Re-resolve HEAD next tick.
140
+
141
+ If `new_head != current_head`, set `current_head = new_head`,
142
+ `bugbot_clean_at = null`, `bugbot_down = false`. New commits invalidate
143
+ bugbot's prior clean and down-detection state.
129
144
 
130
145
  c. Inspect bugteam outcome. Reports `convergence (zero findings)` or list
131
146
  of unfixed findings with file:line.
@@ -137,34 +152,95 @@ never falsely terminates:
137
152
  Re-trigger bugbot same tick (Step 3) so new HEAD enters queue, `phase
138
153
  = BUGBOT`, schedule next wakeup, return.
139
154
  - **Convergence AND `bugbot_clean_at == current_head` (no push):**
140
- Back-to-back clean — necessary, not sufficient. Run **[convergence-gates.md](convergence-gates.md)** to clear Copilot-findings, mergeability, post-convergence
141
- Copilot-request. Only when all four gates pass mark PR ready and
155
+ Back-to-back clean — necessary, not sufficient. Run **[convergence-gates.md](convergence-gates.md)** to clear all six gates: Copilot findings,
156
+ Claude reviewer, mergeability, post-convergence Copilot request,
157
+ thread resolution. Only when all six gates pass mark PR ready and
142
158
  **omit loop pacing** per **Convergence** of active pacing workflow.
143
159
  - **Convergence BUT `bugbot_clean_at != current_head` (no push):**
144
160
  `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).
161
+ - **Findings without committed fixes:** spawn Agent (subagent_type: clean-coder) to implement fixes and push, then reply inline via `python ~/.claude/skills/pr-converge/scripts/post_fix_reply.py`, following [Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow).
146
162
  `phase = BUGBOT`, schedule next wakeup, return.
147
163
 
148
- ## Step 3: Re-trigger bugbot
164
+ ### `phase == COPILOT_WAIT`
149
165
 
150
- Use the `add_issue_comment` MCP tool:
166
+ Post-convergence Copilot re-check. Enters after gate (d) requests Copilot
167
+ review. Do **not** run bugteam here — that only happens after BUGBOT clean
168
+ on this HEAD.
151
169
 
152
- add_issue_comment(owner="OWNER", repo="REPO", issueNumber=NUMBER, body="bugbot run")
170
+ a. Fetch latest Copilot review at `current_head` plus unaddressed inline
171
+ comments:
153
172
 
154
- `bugbot run` is empirically the only re-trigger Cursor Bugbot recognizes;
155
- alternative phrasings (`re-review`, `bugbot please`, etc.) silently no-op.
173
+ ```
174
+ python ~/.claude/skills/pr-converge/scripts/fetch_copilot_reviews.py --owner <O> --repo <R> --pr-number <N>
175
+ → filter by `.commit_id == current_head`, sort by `.submitted_at` descending
176
+
177
+ python ~/.claude/skills/pr-converge/scripts/fetch_copilot_inline_comments.py --owner <O> --repo <R> --pr-number <N> --commit <current_head>
178
+ → unaddressed inline threads on the latest Copilot review at current_head
179
+ ```
156
180
 
157
- **Gotcha (duplicate `bugbot run` while review queued):** Skip Step 3 when
158
- the latest `bugbot run` PR comment has an `:eyes:` or `:+1:` reaction; wait
159
- for review or HEAD change before re-triggering.
181
+ b. Decide (three branches; match first whose predicate holds):
182
+
183
+ - **Copilot review `state: APPROVED` at `current_head`:** Set
184
+ `copilot_clean_at = current_head`. Record "Copilot APPROVED". Set
185
+ `phase = BUGTEAM`. Continue to convergence-gates.md gate (b) in same
186
+ tick — back-to-back convergence requires all gates on same HEAD.
187
+ - **Copilot review dirty (CHANGES_REQUESTED or COMMENTED with findings)
188
+ at `current_head`:** Apply **Fix protocol** — spawn Agent
189
+ (subagent_type: clean-coder) to implement → push → reply inline on each
190
+ thread via `python ~/.claude/skills/pr-converge/scripts/post_fix_reply.py`. For body-only
191
+ findings (no inline threads), post top-level review reply citing new
192
+ HEAD SHA. Reset
193
+ `bugbot_clean_at = null` AND `copilot_clean_at = null`. **Set
194
+ `phase = BUGBOT`** (NOT COPILOT_WAIT) — every fix push requires a full
195
+ back-to-back-clean cycle on the new HEAD. Schedule next wakeup, return.
196
+ - **No Copilot review at `current_head` yet:** Increment
197
+ `copilot_wait_count` (init 0 on COPILOT_WAIT entry; reset to 0 on
198
+ every push and on every successful Copilot review). `>= 3` → hard
199
+ blocker per [stop-conditions.md](stop-conditions.md). Otherwise
200
+ schedule next wakeup (360s), return.
201
+
202
+ **Non-negotiable:** After any Copilot fix push, `phase` MUST route to
203
+ `BUGBOT`. Never cycle COPILOT_WAIT → fix → COPILOT_WAIT. The
204
+ back-to-back-clean guarantee (bugbot ∧ bugteam both clean on same HEAD
205
+ before gates re-open) only holds when every fix commit re-enters through
206
+ BUGBOT.
207
+
208
+ ## Step 3: Re-trigger bugbot
209
+
210
+ - [ ] **Opt-out gate.** When `CLAUDE_REVIEWS_DISABLED` (comma-separated,
211
+ case-insensitive, whitespace-tolerant) contains `bugbot`, set
212
+ `bugbot_down = true`, skip every check below, set `phase = BUGTEAM`,
213
+ and continue BUGTEAM in the same tick. The downstream loop branches on
214
+ `bugbot_down` exactly the way it does when bugbot CI is unavailable.
215
+ - [ ] **Silent-pass pre-check.** Run `python ~/.claude/skills/pr-converge/scripts/check_bugbot_ci.py --check-clean --owner <O> --repo <R> --sha <current_head>`
216
+ - [ ] Exit 0 → bugbot CI completed clean with no review (silent pass); set `bugbot_clean_at = current_head`, `phase = BUGTEAM`, continue BUGTEAM same tick
217
+ - [ ] Exit 1 (not a silent pass) or Exit 2 (gh CLI error — silent pass not confirmable) → continue with the trigger flow below
218
+ - [ ] Run `python ~/.claude/skills/pr-converge/scripts/check_bugbot_ci.py --check-active --owner <O> --repo <R> --sha <current_head>`
219
+ - [ ] Exit 0 → bugbot already queued on this commit; skip posting, wait for completion
220
+ - [ ] Exit 1 → post trigger via `add_issue_comment(owner="OWNER", repo="REPO", issueNumber=NUMBER, body="bugbot run")`
221
+ - [ ] Wait 8s
222
+ - [ ] Run `python ~/.claude/skills/pr-converge/scripts/check_bugbot_ci.py --owner <O> --repo <R> --sha <current_head>`
223
+ - [ ] Exit non-zero → bugbot is down; set `bugbot_down = true`, `phase = BUGTEAM`, continue BUGTEAM same tick
224
+ - [ ] Exit 0 (check run present) → record `bugbot_acknowledged_at = <now ISO 8601>`, proceed to Step 4
225
+
226
+ The silent-pass pre-check fires FIRST so we never re-trigger a bot that
227
+ already finished cleanly. Cursor Bugbot communicates "no findings" by
228
+ completing the CI check with `conclusion: success` (or `neutral`) and
229
+ posting no review. The pre-check treats that outcome as
230
+ `bugbot_clean_at = current_head`, equivalent to an explicit clean
231
+ review. Without it, the trigger flow would re-prompt a bot that has
232
+ already evaluated this commit and refuses to re-run, and the bypass
233
+ branch would falsely mark `bugbot_down = true`.
234
+
235
+ `bugbot run` is empirically the only re-trigger Cursor Bugbot recognizes;
236
+ alternative phrasings silently no-op.
160
237
 
161
238
  ## Step 4: Loop pacing
162
239
 
163
240
  **`ScheduleWakeup` field hints** (prefer [Pacing
164
241
  workflow](#pacing-workflow)):
165
242
 
166
- - `delaySeconds: 270` after bugbot re-trigger. Bugbot finishes in 1–4
167
- min; 270s stays under 5-min prompt-cache TTL with margin. Exception:
243
+ - `delaySeconds: 360` after bugbot re-trigger. Exception:
168
244
  BUGBOT inline-lag branch uses `delaySeconds: 90` (no re-trigger;
169
245
  awaiting GitHub inline API).
170
246
  - `reason`: short sentence on what is awaited, including `phase` and
@@ -6,12 +6,33 @@ counters, status, not conversation transcript. No `state.json` (typical
6
6
  single-PR `/pr-converge`) → track in each assistant turn as
7
7
  plain text so next tick re-reads from context:
8
8
 
9
- - `phase`: `BUGBOT` or `BUGTEAM`. Start `BUGBOT` on first tick.
9
+ - `phase`: `BUGBOT`, `BUGTEAM`, or `COPILOT_WAIT`. Start `BUGBOT` on first tick.
10
10
  - `bugbot_clean_at`: HEAD SHA where bugbot last reported clean, or `null`.
11
11
  Reset to `null` on every push.
12
+ - `copilot_clean_at`: HEAD SHA where Copilot last reported clean, or `null`.
13
+ Reset to `null` on every push.
14
+ - `copilot_wait_count`: integer, init `0`. Consecutive COPILOT_WAIT ticks
15
+ with no Copilot review surfaced at `current_head`. Escalate as hard blocker
16
+ at `>= 3`. Reset to `0` when a Copilot review surfaces at `current_head`
17
+ (APPROVED or dirty) or on any non-COPILOT_WAIT branch.
12
18
  - `inline_lag_streak`: integer, init `0`. Consecutive ticks where review
13
19
  body shows findings against `current_head` but inline API returns zero
14
20
  matching. Reset to `0` on any other branch outcome.
21
+ - `bugbot_down`: boolean, init `false`. Set `true` when bugbot fails to
22
+ acknowledge a trigger comment; forces phase to BUGTEAM. Also set `true`
23
+ when an acknowledged trigger has been outstanding more than 30 minutes
24
+ with no surfaced review at `current_head` (per Step 2 BUGBOT (c)
25
+ 30-minute budget — see `per-tick.md`). Reset to `false` on every push.
26
+ Once set, remains `true` until the next push; if bugbot stays down
27
+ across ticks, the flag persists and BUGTEAM continues.
28
+ - `bugbot_acknowledged_at`: ISO 8601 timestamp string or `null`. Records
29
+ the wall-clock moment Cursor Bugbot acknowledged the most recent
30
+ `bugbot run` trigger comment (i.e. the trigger comment carries an
31
+ `:eyes:`/`:+1:` reaction). Init `null`. Set in Step 3 once the
32
+ reaction-check fires positive. Reset to `null` on every push and on
33
+ every BUGTEAM jump triggered by the 30-minute budget. Step 2 BUGBOT
34
+ (c) reads this field to decide between "schedule next wakeup" and
35
+ "escalate to bugbot-down".
15
36
  - `tick_count`: integer, init `0`. Increment every tick.
16
37
 
17
38
  Tick begins reading prior state line from most recent assistant message
@@ -1,12 +1,14 @@
1
1
  # Stop conditions
2
2
 
3
- - **Convergence** (back-to-back clean ∧ no outstanding Copilot findings
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
3
+ - **Convergence** (back-to-back clean ∧ all six gates pass per
4
+ [convergence-gates.md](convergence-gates.md) gate (f) checklist:
5
+ Copilot clean at `current_head`, Claude clean or absent,
6
+ `mergeable_state == "clean"` with `mergeable == true`,
7
+ post-convergence Copilot review `APPROVED`, zero unresolved bot
8
+ threads): use `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`. With
7
9
  `state.json`, append convergence row to
8
10
  `<TMPDIR>/pr-converge-<session_id>/converged.log` per `multi-pr-orchestration.md` §Memory; else
9
- skip. Report [convergence-gates.md](convergence-gates.md) (d) summary, then **omit loop pacing**
11
+ skip. Report [convergence-gates.md](convergence-gates.md) (f) summary, then **omit loop pacing**
10
12
  per **Convergence** in `../workflows/schedule-wakeup-loop.md`. End all loops
11
13
  once all PRs terminal (converged or blocked).
12
14
  - **Hard blocker:** API auth failure across two ticks, CI regression
@@ -17,8 +19,8 @@
17
19
  blocker and diagnosis, **omit loop pacing** per
18
20
  `../workflows/schedule-wakeup-loop.md`.
19
21
  - **Hard blocker (`mergeable_state` non-clean non-dirty):**
20
- `mergeable_state` is `"blocked"`, `"unknown"`, or `"behind"` (required
21
- checks pending, branch behind base without textual conflicts, or
22
+ `mergeable_state` is `"blocked"`, `"unknown"`, `"behind"`, or `"unstable"` (required
23
+ checks pending/failing, branch behind base without textual conflicts, or
22
24
  GitHub indeterminate). Investigate before retrying; `rebase` skill
23
25
  handles `"dirty"` (textual conflicts) only. Report specific
24
26
  `mergeable_state`, **omit loop pacing**.
@@ -20,11 +20,11 @@ Fetch all reviews and filter for `cursor[bot]`:
20
20
 
21
21
  Classification: clean if review body has no findings count; dirty if body matches "found N potential issue".
22
22
 
23
- ### Bugbot inline comments: `pull_request_read(method="get_review_comments")`
23
+ ### Inline comment threads (used by BUGBOT phase and convergence gate (e))
24
24
 
25
- Fetch all review comments and filter for `cursor[bot]`, matching `pull_request_review_id` to the newest Bugbot review on the target commit:
26
-
27
- pull_request_read(method="get_review_comments", pullNumber=NUMBER, owner=OWNER, repo=REPO)
25
+ Fetch all unresolved inline threads on the PR. The convergence gate is
26
+ author-agnostic and commit-agnostic — see "Inline comment threads"
27
+ below for the canonical fetch.
28
28
 
29
29
  ### PR head SHA: `pull_request_read(method="get")`
30
30
 
@@ -38,7 +38,7 @@ Access `.head.sha` from the response.
38
38
 
39
39
  Post the bugbot re-trigger comment:
40
40
 
41
- add_issue_comment(owner="OWNER", repo="REPO", issueNumber=NUMBER, body="bugbot run")
41
+ add_issue_comment(owner="OWNER", repo="REPO", issue_number=NUMBER, body="bugbot run")
42
42
 
43
43
  `bugbot run` is the only recognized re-trigger phrase; alternative phrasings silently no-op.
44
44
 
@@ -48,17 +48,16 @@ Mark a draft PR as ready for review:
48
48
 
49
49
  update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)
50
50
 
51
- ### Reply to inline comment: `add_reply_to_pull_request_comment`
51
+ ### Reply to inline comment: `python scripts/post_fix_reply.py`
52
52
 
53
53
  Reply to an inline review comment thread:
54
54
 
55
- add_reply_to_pull_request_comment(
56
- commentId=COMMENT_ID,
57
- body=REPLY_BODY,
58
- owner=OWNER,
59
- repo=REPO,
60
- pullNumber=NUMBER
61
- )
55
+ ```
56
+ python scripts/post_fix_reply.py --owner <O> --repo <R> --pr-number <N> \
57
+ --in-reply-to <COMMENT_ID> --body "<reply text>"
58
+ ```
59
+
60
+ Omit `--in-reply-to` to post a general PR comment instead.
62
61
 
63
62
  ### Mergeability: `pull_request_read(method="get")`
64
63
 
@@ -68,52 +67,41 @@ Read mergeability fields from the PR:
68
67
 
69
68
  Fields: `.mergeable`, `.mergeable_state`, `.head.sha`.
70
69
 
71
- ### Copilot reviews: `pull_request_read(method="get_reviews")`
70
+ ### Copilot reviews: `python scripts/fetch_copilot_reviews.py`
72
71
 
73
- Fetch all reviews and filter for `copilot-pull-request-reviewer[bot]`:
72
+ ```
73
+ python scripts/fetch_copilot_reviews.py --owner <O> --repo <R> --pr-number <N>
74
+ ```
74
75
 
75
- pull_request_read(method="get_reviews", pullNumber=NUMBER, owner=OWNER, repo=REPO)
76
+ Returns JSON array of Copilot reviews newest-first. Classification:
77
+ `APPROVED` → clean, `CHANGES_REQUESTED` → dirty, `COMMENTED` with
78
+ non-empty body → dirty.
76
79
 
77
- Classification: `APPROVED` clean, `CHANGES_REQUESTED` → dirty, `COMMENTED` with non-empty body → dirty.
80
+ ### Inline comment threads: `pull_request_read(method="get_review_comments")`
78
81
 
79
- ### Copilot inline comments: `pull_request_read(method="get_review_comments")`
80
-
81
- Fetch all review comments and filter for `copilot-pull-request-reviewer[bot]`, matching `pull_request_review_id` to the newest Copilot review on the target commit:
82
+ Fetch via MCP. The convergence gate filters ONLY on resolution state:
82
83
 
83
84
  pull_request_read(method="get_review_comments", pullNumber=NUMBER, owner=OWNER, repo=REPO)
85
+ → filter threads where `is_resolved == false`
84
86
 
85
- ### Request Copilot review: `add_issue_comment` or `request_copilot_review`
86
-
87
- Two options:
88
-
89
- 1. Comment-based trigger:
90
- ```
91
- add_issue_comment(owner=OWNER, repo=REPO, issueNumber=NUMBER, body="@copilot review")
92
- ```
93
- 2. Dedicated MCP tool (when available):
94
- ```
95
- request_copilot_review(owner=OWNER, repo=REPO, pullNumber=NUMBER)
96
- ```
87
+ The fields `comment.author`, `comment.commit.oid`, and `is_outdated`
88
+ remain useful for **deciding how to address** each unresolved thread
89
+ (re-fix? reply-with-note?), but they do not exclude a thread from the
90
+ count.
97
91
 
98
- The `[bot]` suffix is load-bearing per `../../copilot-review/SKILL.md`.
92
+ ### Request Copilot review: `gh api` REST endpoint
99
93
 
100
- ### Claude reviews: `pull_request_read(method="get_reviews")`
94
+ ```
95
+ gh api --method POST repos/<O>/<R>/pulls/<N>/requested_reviewers \
96
+ -f 'reviewers[]=copilot-pull-request-reviewer[bot]'
97
+ ```
101
98
 
102
- Fetch all reviews and filter for login containing `claude`:
103
-
104
- pull_request_read(method="get_reviews", pullNumber=NUMBER, owner=OWNER, repo=REPO)
105
-
106
- Classification: same state-based rules as Copilot reviews.
107
-
108
- ### Claude inline comments: `pull_request_read(method="get_review_comments")`
109
-
110
- Fetch all review comments and filter for login containing `claude`, matching `pull_request_review_id` to the newest Claude review on the target commit:
111
-
112
- pull_request_read(method="get_review_comments", pullNumber=NUMBER, owner=OWNER, repo=REPO)
99
+ Check for an existing pending review first with
100
+ `python scripts/check_pending_reviews.py --owner <O> --repo <R> --pr-number <N> --user copilot`.
113
101
 
114
102
  ## Shared modules
115
103
 
116
- No shared fetch core modules are needed. Each review or comment fetch is a single MCP tool call with client-side filtering by login.
104
+ Shared Python utilities live under `_shared/pr-loop/scripts/` — `_xml_utils.py` for XML serialization, `_cli_utils.py` for CLI guards, `_path_resolver.py` for canonical path resolution. These serve `/bugteam`, `/qbug`, `/findbugs`, and `/fixbugs` equally.
117
105
 
118
106
  ## Tests
119
107