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
@@ -3,7 +3,13 @@
3
3
  Run **only** when Step 2 BUGTEAM reports `convergence (zero findings)` AND
4
4
  `bugbot_clean_at == current_head` AND no push during bugteam tick. Gates run
5
5
  in order; first failure determines next-tick behavior. Mark PR ready only
6
- when all four pass.
6
+ when all six pass.
7
+
8
+ **Mandatory evidence rule:** Every gate that fetches data MUST produce a
9
+ summary of its findings before proceeding to the next gate. Gate (f) MUST
10
+ reference evidence from each prior gate. Skipping any gate silently is a
11
+ hard blocker — report "gate evidence missing: <gate name>" and omit loop
12
+ pacing. Do not mark ready with unverified gates.
7
13
 
8
14
  ## (a) Copilot findings gate
9
15
 
@@ -12,12 +18,11 @@ plus inline comments anchored to most recent Copilot review on
12
18
  `current_head`:
13
19
 
14
20
  ```
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
21
+ python ~/.claude/skills/pr-converge/scripts/fetch_copilot_reviews.py --owner <O> --repo <R> --pr-number <N>
22
+ → filter by `.commit_id == current_head`, sort by `.submitted_at` descending
18
23
 
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")
24
+ python ~/.claude/skills/pr-converge/scripts/fetch_copilot_inline_comments.py --owner <O> --repo <R> --pr-number <N> --commit <current_head>
25
+ unaddressed inline threads on the latest Copilot review at current_head
21
26
  ```
22
27
 
23
28
  Decide (four branches; match first whose predicate holds):
@@ -25,28 +30,63 @@ Decide (four branches; match first whose predicate holds):
25
30
  - **`classification == "dirty"` with non-empty inline comments matching
26
31
  `pull_request_review_id`:** Fix protocol input (same shape as bugbot
27
32
  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
33
+ `python ~/.claude/skills/pr-converge/scripts/post_fix_reply.py` → Step 3 in same tick (see
29
34
  [Single-PR fix workflow](fix-protocol.md#single-pr-fix-workflow) for
30
35
  full contract).
31
36
  Reset `bugbot_clean_at = null` AND `copilot_clean_at = null`, `phase =
32
37
  BUGBOT`, schedule next wakeup, return. Full back-to-back-clean cycle
33
- plus all four gates must hold again on new HEAD.
38
+ plus all six gates must hold again on new HEAD.
34
39
  - **`classification == "dirty"` with empty inline comments matching
35
40
  `pull_request_review_id`:** Copilot posted findings only in review body
36
41
  (`CHANGES_REQUESTED` or `COMMENTED` with non-empty body, no inline
37
42
  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.
43
+ top-level review reply via `python ~/.claude/skills/pr-converge/scripts/post_fix_reply.py` citing new HEAD SHA → Step 3 in same tick.
39
44
  Reset
40
45
  `bugbot_clean_at = null` AND
41
46
  `copilot_clean_at = null`, `phase = BUGBOT`, Step 3 on new HEAD,
42
47
  schedule next wakeup, return. Convergence requires full
43
48
  back-to-back-clean on new HEAD.
44
49
  - **`classification == "clean"` (state `APPROVED`):** Set
45
- `copilot_clean_at = current_head`. Continue to gate (b).
46
- - **No Copilot review on `current_head` yet:** Skip — gate (c) issues
47
- proactive request. Continue to gate (b).
50
+ `copilot_clean_at = current_head`. Record evidence: "Copilot APPROVED at <SHA>".
51
+ Continue to gate (b).
52
+ - **No Copilot review on `current_head` yet:** Record evidence: "No Copilot review at <SHA>".
53
+ Skip — gate (d) issues proactive request. Continue to gate (b).
54
+
55
+ ## (b) Claude reviewer gate
56
+
57
+ Fetch latest Claude reviewer (`claude[bot]`) review plus inline comments
58
+ anchored to most recent Claude review on `current_head`:
59
+
60
+ ```
61
+ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_reviews")
62
+ → filter `.user.login` for claude (case-insensitive substring "claude")
63
+ AND `.commit_id == current_head`
64
+ → sort by `.submitted_at` descending
65
+
66
+ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_review_comments")
67
+ → filter threads where `is_resolved == false`
68
+ ```
48
69
 
49
- ## (b) Mergeability gate
70
+ Decide (four branches; match first whose predicate holds):
71
+
72
+ - **`classification == "dirty"` with non-empty inline comments matching
73
+ `pull_request_review_id`:** Treat identically to gate (a) dirty+inline
74
+ path — spawn Agent (subagent_type: clean-coder) to fix → push → reply inline on each thread. Reset
75
+ `bugbot_clean_at = null` AND `copilot_clean_at = null`, `phase = BUGBOT`,
76
+ schedule next wakeup, return.
77
+ - **`classification == "dirty"` with empty inline comments matching
78
+ `pull_request_review_id`:** Claude posted findings only in review body
79
+ (`CHANGES_REQUESTED` or `COMMENTED` with non-empty body, no inline
80
+ threads). Treat identically to gate (a) dirty+body path — spawn Agent
81
+ (subagent_type: clean-coder) to implement → push → post top-level review reply via `python ~/.claude/skills/pr-converge/scripts/post_fix_reply.py`. Reset
82
+ `bugbot_clean_at = null` AND `copilot_clean_at = null`, `phase = BUGBOT`,
83
+ schedule next wakeup, return.
84
+ - **`classification == "clean"` (state `APPROVED`):** Record evidence:
85
+ "Claude APPROVED at <SHA>". Continue to gate (c).
86
+ - **No Claude review on `current_head` yet:** Record evidence:
87
+ "Claude absent at <SHA>". Continue to gate (c).
88
+
89
+ ## (c) Mergeability gate
50
90
 
51
91
  Resolve PR's mergeability state:
52
92
 
@@ -58,7 +98,8 @@ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get")
58
98
  Persist `mergeable_state` into `merge_state_status`. Decide:
59
99
 
60
100
  - **`mergeable_state == "clean"` AND `mergeable == true`:**
61
- Continue to gate (c).
101
+ Record evidence: "mergeable_state clean, mergeable=true at <SHA>".
102
+ Continue to gate (d).
62
103
  - **`mergeable_state == "dirty"` (or `mergeable == false`):** Do
63
104
  **not** mark ready. Invoke **`rebase`** skill
64
105
  ([`../../rebase/SKILL.md`](../../rebase/SKILL.md)) Phase 1–4 against PR's
@@ -67,47 +108,99 @@ Persist `mergeable_state` into `merge_state_status`. Decide:
67
108
  `copilot_clean_at = null`, `merge_state_status = null`, `phase = BUGBOT`,
68
109
  Step 3 on new HEAD, schedule next wakeup, return. Loop re-runs from
69
110
  scratch on new HEAD.
70
- - **`mergeable_state` is `"blocked"`, `"behind"`, or `"unknown"` for
71
- non-conflict reasons** (required checks pending, branch behind base
72
- without conflicts GitHub cannot auto-resolve): **hard blocker** per
111
+ - **`mergeable_state` is `"blocked"`, `"behind"`, `"unknown"`, or `"unstable"` for
112
+ non-conflict reasons** (required checks pending/failing for "unstable",
113
+ branch behind base without conflicts for "behind", GitHub indeterminate
114
+ for "unknown"): **hard blocker** per
73
115
  [stop-conditions.md](stop-conditions.md) — do not invent a fix. Report specific
74
116
  `mergeable_state`, omit loop pacing.
75
117
 
76
- ## (c) Post-convergence Copilot review request
118
+ ## (d) Post-convergence Copilot review request
77
119
 
78
- Once gates (a) and (b) both pass (Copilot clean at `current_head` *or* no
79
- Copilot review yet, AND `mergeable_state == "clean"`), request Copilot
80
- review:
120
+ Once gates (a), (b), and (c) all pass (Copilot clean at `current_head` *or* no
121
+ Copilot review yet, AND Claude clean or absent at `current_head`, AND
122
+ `mergeable_state == "clean"`), request Copilot review:
81
123
 
82
124
  ```
83
- request_copilot_review(owner=OWNER, repo=REPO, pullNumber=NUMBER)
125
+ gh api --method POST repos/<O>/<R>/pulls/<N>/requested_reviewers \
126
+ -f 'reviewers[]=copilot-pull-request-reviewer[bot]'
84
127
  ```
85
128
 
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")`.
129
+ Check for an existing pending review first with
130
+ `python ~/.claude/skills/pr-converge/scripts/check_pending_reviews.py --owner <O> --repo <R> --pr-number <N> --user copilot`.
131
+
132
+ After request, set `phase = COPILOT_WAIT`, schedule next wakeup, and return.
133
+ The COPILOT_WAIT phase prevents the agent from re-entering convergence gates
134
+ while Copilot processes. Next tick with `phase == COPILOT_WAIT`:
135
+ re-run the fetch from gate (a) — `python ~/.claude/skills/pr-converge/scripts/fetch_copilot_reviews.py`
136
+ plus MCP `get_review_comments` filtered for Copilot inline threads —
137
+ against `current_head`. Decide:
138
+
139
+ - **Copilot review present at `current_head`:**
140
+ - `state: APPROVED` → set `copilot_clean_at = current_head`. Record
141
+ evidence: "Copilot APPROVED at <SHA>". Re-validate gates (b) and (c)
142
+ on same tick (Claude status and mergeability may have changed while
143
+ waiting). Set `phase = BUGTEAM`.
144
+ Continue to gate (e) when (b) and (c) still pass.
145
+ - `state: CHANGES_REQUESTED` or `COMMENTED` with non-empty body → dirty.
146
+ Treat identically to gate (a) dirty path — spawn Agent (subagent_type: clean-coder) to fix,
147
+ reset `bugbot_clean_at = null` AND `copilot_clean_at = null`,
148
+ `phase = BUGBOT`, schedule next wakeup, return.
149
+ - **No Copilot review at `current_head` yet:** Record evidence: "No Copilot
150
+ review at <SHA> (wait count: <N>)". Increment `copilot_wait_count`
151
+ (init 0 on first COPILOT_WAIT entry; reset to 0 on every push and on every
152
+ successful Copilot review). After three consecutive empty waits
153
+ (`copilot_wait_count >= 3`), escalate as hard blocker — report
154
+ "Copilot did not surface a review on current_head after 3 wakeups"
155
+ and omit loop pacing. Otherwise schedule next wakeup (360s), return.
156
+
157
+ ## (e) Thread-resolution gate
158
+
159
+ Before marking ready, count ALL unresolved review threads on the PR:
160
+
161
+ ```
162
+ pull_request_read(owner=OWNER, repo=REPO, pullNumber=NUMBER, method="get_review_comments")
163
+ → filter threads where `is_resolved == false`
164
+ → count
165
+ ```
166
+
167
+ When you address an unresolved thread, you still need its author and
168
+ anchor commit so you can decide how to fix it — but the gate doesn't
169
+ filter on those fields.
170
+
171
+ Decide:
172
+
173
+ - **Zero unresolved threads:** Record evidence:
174
+ "0 unresolved threads across PR at <SHA>". Continue to gate (f).
175
+ - **One or more unresolved threads:** Do **not** mark ready. For each
176
+ unresolved thread, verify the concern against current HEAD. If still
177
+ applies, apply Fix protocol (test → fix → push → reply → resolve). If
178
+ no longer applies (e.g. code already changed), reply-with-note
179
+ explaining why and resolve. Push if any code changed → reset
180
+ `bugbot_clean_at = null` AND `copilot_clean_at = null`,
181
+ `phase = BUGBOT`, schedule next wakeup, return. If only resolutions
182
+ (no code changes), re-check this gate without resetting.
87
183
 
88
- After request, schedule next wakeup and return — next tick checks response.
184
+ ## (f) Mark ready and report
89
185
 
90
- Next tick with `phase == BUGTEAM` and prior state preserved → re-run gate
91
- (a) first. Decide:
186
+ **Mandatory pre-condition checklist.** Before calling `update_pull_request`,
187
+ verify ALL seven conditions below. Three are preconditions from the main
188
+ loop (bugbot clean, bugteam convergence, no intervening push); four are
189
+ evidence from gates (a)–(e) above. All seven must be confirmed:
92
190
 
93
- - **Copilot review `clean` (state `APPROVED`):** Set `copilot_clean_at =
94
- current_head`. Mark PR ready (`update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`), report convergence
95
- per §(d), terminate per [stop-conditions.md](stop-conditions.md) / Convergence.
96
- - **Copilot review `dirty`:** Treat identically to gate (a) dirty path —
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.
103
- - **No Copilot review at `current_head` yet (still propagating):**
104
- Schedule one more wakeup (270s), re-check next tick. After three consecutive empty waits,
105
- escalate as hard blocker per [stop-conditions.md](stop-conditions.md).
191
+ - [ ] `bugbot_clean_at == current_head` (from per-tick.md Step 2 BUGBOT §c)
192
+ - [ ] bugteam `convergence (zero findings)` at `current_head` (from per-tick.md Step 2 BUGTEAM §d)
193
+ - [ ] `copilot_clean_at == current_head` (from gate (a) or gate (d))
194
+ - [ ] Claude `APPROVED` or absent at `current_head` (from gate (b))
195
+ - [ ] `mergeable_state == "clean"` AND `mergeable == true` (from gate (c))
196
+ - [ ] Zero unresolved review threads anywhere on the PR (from gate (e))
197
+ - [ ] No push since bugteam convergence (from per-tick.md Step 2 BUGTEAM §b)
106
198
 
107
- ## (d) Mark ready and report
199
+ If ANY checkbox cannot be confirmed with evidence, do NOT mark ready.
200
+ Report the specific missing condition and route through the appropriate
201
+ fix path (BUGBOT for dirty reviews, rebase for merge conflicts, etc.).
108
202
 
109
- Only when all four gates pass — bugbot CLEAN ∧ bugteam CLEAN ∧
110
- `mergeable_state == "clean"` ∧ Copilot CLEAN at HEAD — run:
203
+ Only when ALL seven conditions are confirmed:
111
204
 
112
205
  Use the `update_pull_request` MCP tool:
113
206
 
@@ -116,5 +209,6 @@ Use the `update_pull_request` MCP tool:
116
209
  With `state.json`, append convergence row to
117
210
  `<TMPDIR>/pr-converge-<session_id>/converged.log` per `multi-pr-orchestration.md` §Memory; else skip.
118
211
  Report: `PR #<NUMBER> converged: bugbot CLEAN at <SHA>, bugteam CLEAN at
119
- <SHA>, mergeable_state CLEAN, copilot CLEAN at <SHA>; marked ready for
120
- review`. **Omit loop pacing** per **Convergence** of active pacing workflow.
212
+ <SHA>, mergeable_state clean, copilot CLEAN at <SHA>, claude <APPROVED|absent>
213
+ at <SHA>, 0 unresolved threads across PR; marked ready for review`.
214
+ **Omit loop pacing** per **Convergence** of active pacing workflow.
@@ -25,9 +25,33 @@ 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 `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`, reports "PR
29
- converged: bugbot CLEAN at <SHA>, bugteam CLEAN at <SHA>; marked ready for
30
- review", applies **Convergence** from `workflows/schedule-wakeup-loop.md`]
28
+ == current_head` (no push). Claude: [back-to-back clean necessary, not
29
+ sufficient. Runs `convergence-gates.md` gates in order:
30
+ Gate (a): two calls `pull_request_read(method="get_reviews")` +
31
+ `pull_request_read(method="get_review_comments")`
32
+ → filter Copilot → APPROVED at `current_head`
33
+ → record evidence, set `copilot_clean_at = current_head`.
34
+ Gate (b): two calls — `pull_request_read(method="get_reviews")` +
35
+ `pull_request_read(method="get_review_comments")`
36
+ → filter Claude → absent at `current_head`
37
+ → record evidence, continue (trivially clean).
38
+ Gate (c): `pull_request_read(method="get")` → `.mergeable_state == "clean"`
39
+ AND `.mergeable == true` → record evidence.
40
+ Gate (d): set `phase = COPILOT_WAIT`;
41
+ `request_copilot_review(owner=OWNER, repo=REPO, pullNumber=NUMBER)`
42
+ → schedule next wakeup, return.
43
+ Next tick: re-run gate (a) fetch → Copilot `APPROVED` at `current_head`
44
+ → set `copilot_clean_at = current_head`, record evidence: "Copilot
45
+ APPROVED at <SHA>", set `phase = BUGTEAM`, re-validate gates (b) and (c).
46
+ Gate (e): `pull_request_read(method="get_review_comments")` → count
47
+ threads where `is_resolved == false` (no author/commit/outdated
48
+ filter) → zero across PR → record evidence.
49
+ Gate (f): all six gates pass → `update_pull_request(pullNumber=NUMBER,
50
+ owner=OWNER, repo=REPO, draft=false)`.
51
+ Reports "PR #N converged: bugbot CLEAN at <SHA>, bugteam CLEAN at <SHA>,
52
+ mergeable_state clean, copilot CLEAN at <SHA>, claude absent at <SHA>,
53
+ 0 unresolved threads across PR; marked ready for review",
54
+ applies **Convergence** from `workflows/schedule-wakeup-loop.md`]
31
55
  </example>
32
56
 
33
57
  <example> BUGTEAM phase, bugteam pushed fix commit during run. Claude:
@@ -42,7 +66,7 @@ HEAD but inline API returns zero matching for `current_head`. Claude:
42
66
  </example>
43
67
 
44
68
  <example> Back-to-back clean reached, but `mergeStateStatus: DIRTY` (base
45
- advanced, merge conflicts). Claude: [runs §Convergence gates (b); does NOT
69
+ advanced, merge conflicts). Claude: [runs §Convergence gate (c); does NOT
46
70
  mark ready; invokes `rebase` skill per `../../rebase/SKILL.md` Phase 1–4;
47
71
  after force-with-lease push, resets `bugbot_clean_at = null`,
48
72
  `copilot_clean_at = null`, `merge_state_status = null`, `phase = BUGBOT`,
@@ -58,19 +82,27 @@ HEAD, schedules next wakeup]
58
82
  </example>
59
83
 
60
84
  <example> Back-to-back clean, mergeability CLEAN, no Copilot review on
61
- `current_head`. Claude requests Copilot via `add_issue_comment(owner=OWNER, repo=REPO, issueNumber=NUMBER, body="@copilot review")`,
62
- waits one tick. Next tick: Copilot review `state: APPROVED`. Claude: [sets
63
- `copilot_clean_at = current_head`; runs `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`; reports "PR
64
- #N converged: bugbot CLEAN at <SHA>, bugteam CLEAN at <SHA>,
65
- mergeable_state clean, copilot CLEAN; marked ready for review"]
85
+ `current_head`. Claude sets `phase = COPILOT_WAIT`, runs gate (d):
86
+ `request_copilot_review(owner=OWNER, repo=REPO, pullNumber=NUMBER)`,
87
+ schedules next wakeup, returns. Next tick:
88
+ Copilot review `state: APPROVED` at `current_head`. Claude: [re-runs
89
+ gate (a) fetch APPROVED sets `copilot_clean_at = current_head`,
90
+ records evidence: "Copilot APPROVED at <SHA>", sets `phase = BUGTEAM`;
91
+ re-validates gates (b) Claude absent and (c) mergeability clean,
92
+ records evidence for both; gate (e) zero unresolved threads passes
93
+ trivially, record evidence: "0 unresolved threads across PR at <SHA>";
94
+ runs `update_pull_request(pullNumber=NUMBER,
95
+ owner=OWNER, repo=REPO, draft=false)`; reports "PR #N converged: bugbot CLEAN
96
+ at <SHA>, bugteam CLEAN at <SHA>, mergeable_state clean, copilot CLEAN at
97
+ <SHA>, claude absent at <SHA>, 0 unresolved threads across PR; marked ready for review"]
66
98
  </example>
67
99
 
68
100
  <example> Back-to-back clean, mergeability CLEAN, post-convergence Copilot
69
101
  review returned `state: CHANGES_REQUESTED` with inline findings on
70
- `current_head`. Claude: [does NOT mark PR ready — gate (4) failed;
102
+ `current_head`. Claude: [does NOT mark PR ready — gate (d) failed;
71
103
  applies Fix protocol on every confirmed Copilot finding (TDD test → fix →
72
104
  push → reply inline on each thread); resets `bugbot_clean_at = null` and
73
105
  `copilot_clean_at = null`; `phase = BUGBOT`; posts `bugbot run` on new
74
- HEAD; schedules next wakeup. Full back-to-back-clean cycle plus all four
106
+ HEAD; schedules next wakeup. Full back-to-back-clean cycle plus all six
75
107
  gates must hold again on new HEAD.]
76
108
  </example>
@@ -8,12 +8,13 @@ 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
- `add_reply_to_pull_request_comment(owner, repo, pullNumber, commentId, body)`
11
+ `python scripts/post_fix_reply.py --owner <O> --repo <R> --pr-number <N> --in-reply-to <COMMENT_ID> --body <text>`
12
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
- `bugbot_clean_at: null`, `phase: "BUGBOT"`, `status: "awaiting_bugbot"`,
16
- `last_updated` (ISO-8601 UTC) to `state.json` (per §Concurrency).
15
+ `bugbot_clean_at: null`, `bugbot_down: false`, `phase: "BUGBOT"`,
16
+ `status: "awaiting_bugbot"`, `last_updated` (ISO-8601 UTC) to
17
+ `state.json` (per §Concurrency).
17
18
  - Goes idle. Orchestrator spawns follow-up `general-purpose` agent for
18
19
  bugbot trigger and monitoring.
19
20
 
@@ -40,10 +41,10 @@ git push origin <BRANCH>
40
41
  ```
41
42
  **Pre-push gate:** honor hooks; full-stop on bypass. Capture new HEAD
42
43
  only after both gates pass; set `current_head`, `bugbot_clean_at = null`.
43
- - Reply inline on each addressed comment thread using the `add_reply_to_pull_request_comment` MCP tool:
44
+ - Reply inline on each addressed comment thread using `python scripts/post_fix_reply.py`:
44
45
 
45
46
  ```
46
- add_reply_to_pull_request_comment(owner=OWNER, repo=REPO, pullNumber=NUMBER, commentId=COMMENT_ID, body="Fixed in <SHA> — <what changed>")
47
+ python scripts/post_fix_reply.py --owner <O> --repo <R> --pr-number <N> --in-reply-to <COMMENT_ID> --body "Fixed in <SHA> — <what changed>"
47
48
  ```
48
49
  - **After pushing a fix, always run Step 3 (`bugbot run`) in the same
49
50
  tick** regardless of phase. New commit **resets full convergence cycle**:
@@ -3,11 +3,13 @@
3
3
  - **Append commits.** Each tick adds at most one fix commit.
4
4
  - **Bugbot findings on current SHA mean fix-then-push-then-`bugbot run`,
5
5
  not another naked `bugbot run`.**
6
- - **All `*_clean_at` and `merge_state_status` reset on every push.**
6
+ - **All `*_clean_at`, `merge_state_status`, and `bugbot_down` reset on every push.**
7
7
  - **`bugbot run` comment is load-bearing.** Literal phrase exactly —
8
8
  empirically the only re-trigger Cursor Bugbot recognizes.
9
- - **Honor pre-push and pre-commit hooks.** Read output, fix the cause,
10
- retry. Full-stop on bypass.
9
+ - **All production edits go through `clean-coder`.** The lead never edits
10
+ production files directly. Every fix — bugbot, bugteam, Copilot, or
11
+ Claude finding — spawns `Agent(subagent_type="clean-coder")` to
12
+ implement. No exceptions.
11
13
  - **Adapt when reality contradicts on-disk state.** If `state.json`,
12
14
  `git`, or `gh` disagree with live PR, escalate as hard blocker per
13
15
  [stop-conditions.md](stop-conditions.md).
@@ -42,6 +42,7 @@ Create once at session start. Each teammate writes result before going idle.
42
42
  "current_head": "f9a7d49e",
43
43
  "bugbot_clean_at": null,
44
44
  "inline_lag_streak": 0,
45
+ "bugbot_down": false,
45
46
  "tick_count": 5,
46
47
  "last_action": "bugbot_triggered",
47
48
  "status": "in_progress",
@@ -109,14 +110,15 @@ Bugfind subagent completes (findings or clean):
109
110
  4. Replies inline on each addressed finding via
110
111
  `add_reply_to_pull_request_comment(owner, repo, pullNumber, commentId, body)`.
111
112
  5. Writes `state.json` (per §Concurrency): `last_action: "fix_pushed"`,
112
- `current_head: <new SHA>`, `bugbot_clean_at: null`, `phase:
113
+ `current_head: <new SHA>`, `bugbot_clean_at: null`,
114
+ `bugbot_down: false`, `phase:
113
115
  "BUGBOT"`, `status: "awaiting_bugbot"`, `last_updated` ISO-8601 UTC.
114
116
  6. Goes idle.
115
117
 
116
118
  - **PRs with zero findings:** spawn one `general-purpose` subagent per PR via
117
119
  `Agent(subagent_type="general-purpose", run_in_background=true)`. Subagent:
118
120
  1. `bugbot_clean_at == current_head` (back-to-back clean): run
119
- `update_pull_request(pullNumber=PR_NUMBER, owner=OWNER, repo=REPO, draft=false)`, append convergence row to
121
+ `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`, append convergence row to
120
122
  `<TMPDIR>/pr-converge-<session_id>/converged.log` per §Memory, then
121
123
  write `state.json` (per §Concurrency) with `status: "converged"`,
122
124
  `last_action: "converged"` (or `marked_ready`), `phase: "BUGBOT"`,
@@ -125,8 +127,18 @@ Bugfind subagent completes (findings or clean):
125
127
  duplicate work.
126
128
  2. Else: update `state.json` (per §Concurrency) with `last_action:
127
129
  "audit_clean"`, `status: "awaiting_bugbot"`, `phase: "BUGBOT"`, then
128
- trigger bugbot via `add_issue_comment(owner, repo, issueNumber, body="bugbot run")`.
129
- 3. Goes idle.
130
+ trigger bugbot via `add_issue_comment(owner, repo, issue_number, body="bugbot run")`.
131
+ 3. **Bugbot-down detection.** Capture the comment ID from the
132
+ `add_issue_comment` response. Sleep 15 seconds. Fetch comments via
133
+ `issue_read(method="get_comments", owner=owner, repo=repo, issue_number=issue_number)`,
134
+ select the comment whose `id` matches the captured ID, and check its
135
+ reactions. If the comment has zero reactions (reactions
136
+ count is `0` or absent): set `bugbot_down = true`,
137
+ `phase: "BUGTEAM"`, `status: "in_progress"`,
138
+ `last_action: "bugbot_down_detected"`, `last_updated` ISO-8601 UTC
139
+ via `state.json`, spawn a `bugteam` subagent, and return (skip going
140
+ idle). If one or more reactions present, continue to step 4.
141
+ 4. Goes idle.
130
142
 
131
143
  ### Fix result → general-purpose per PR
132
144
 
@@ -135,40 +147,53 @@ When bugfix (clean-coder) subagent completes after push:
135
147
  - Spawn one `general-purpose` subagent per PR via
136
148
  `Agent(subagent_type="general-purpose", run_in_background=true)`. Subagent:
137
149
  1. Reads `state.json` for its PR.
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
- 4. **Poll / classify loop** (repeat from 4a whenever 4c retries):
142
- - **4a.** Fetch inline comments via `pull_request_read(method="get_review_comments")` filtered by review ID and `commit_id == current_head`.
143
- - **4b.** Classify three outcomes (same as `SKILL.md` Step 2 BUGBOT):
150
+ 2. Triggers bugbot via `add_issue_comment(owner, repo, issue_number, body="bugbot run")`.
151
+ 3. **Bugbot-down detection.** Capture the comment ID from the
152
+ `add_issue_comment` response. Sleep 15 seconds. Fetch comments via
153
+ `issue_read(method="get_comments", owner=owner, repo=repo, issue_number=issue_number)`,
154
+ select the comment whose `id` matches the captured ID, and check its
155
+ reactions. If the comment has zero reactions (reactions
156
+ count is `0` or absent): set `bugbot_down = true`,
157
+ `phase: "BUGTEAM"`, `status: "in_progress"`,
158
+ `last_action: "bugbot_down_detected"`, `last_updated` ISO-8601 UTC
159
+ via `state.json`, spawn a `bugteam` subagent, and return (skip
160
+ polling loop). If one or more reactions present, continue to step 4.
161
+ 4. Polls `pull_request_read(method="get_reviews")` every 60s (up to 10 polls)
162
+ until review anchored to `current_head` appears with `commit_id ==
163
+ current_head`. If polling reaches limit without a matching review, write
164
+ `state.json` with `status: "blocked"`, `last_action: "review_timeout"`,
165
+ and go idle.
166
+ 5. **Poll / classify loop** (repeat from 5a whenever 5c retries):
167
+ - **5a.** Fetch inline comments via `pull_request_read(method="get_review_comments")` filtered by review ID and `commit_id == current_head`.
168
+ - **5b.** Classify — three outcomes (same as `SKILL.md` Step 2 BUGBOT):
144
169
  - **`clean`:** review body clean, zero unaddressed inline findings.
145
170
  - **`dirty`:** ≥1 unaddressed inline finding for `current_head`
146
171
  (actionable for Fix protocol / `clean-coder`).
147
172
  - **`inline_lag`:** review body shows findings, inline API returns
148
173
  zero matching for `current_head` (transient desync — `SKILL.md`
149
174
  Step 2 BUGBOT fourth bullet).
150
- - **4c. `inline_lag`:** locked merge: increment `inline_lag_streak`
175
+ - **5c. `inline_lag`:** locked merge: increment `inline_lag_streak`
151
176
  (missing → `0` first); set `last_action: "inline_lag_wait"`,
152
177
  `phase: "BUGBOT"`, `last_updated`; keep `status` consistent (e.g.
153
178
  `awaiting_bugbot`). `inline_lag_streak >= 3` → **hard blocker** per
154
179
  `SKILL.md` §Stop conditions (structurally inconsistent review);
155
180
  report and go idle **without** classifying as `dirty`. Else sleep
156
- 90s and repeat from 4a (re-fetch inline only).
157
- - **4d. `clean`:** exit. Locked merge: `bugbot_clean_at =
181
+ 90s and repeat from 5a (re-fetch inline only).
182
+ - **5d. `clean`:** exit. Locked merge: `bugbot_clean_at =
158
183
  current_head`, reset `inline_lag_streak`, update `last_action`,
159
184
  `status`, `phase: BUGTEAM`.
160
- - **4e. `dirty`:** exit. Locked merge: reset `inline_lag_streak`,
185
+ - **5e. `dirty`:** exit. Locked merge: reset `inline_lag_streak`,
161
186
  record findings count, update `last_action`, `status`, `phase:
162
187
  BUGBOT`.
163
- 5. Reports one-line outcome to orchestrator.
188
+ 6. Reports one-line outcome to orchestrator.
164
189
 
165
190
  - Orchestrator reads updated `state.json`, spawns next agent:
166
191
  - `clean` → `general-purpose` runs BUGTEAM phase (bugteam via `Skill`
167
192
  when available, else inline by reading bugteam `SKILL.md`).
168
- - Exited on `dirty` (4e) with actionable inline threads → spawn same
193
+ - Exited on `dirty` (5e) with actionable inline threads → spawn same
169
194
  fix worker as "audit result with findings". Do **not** spawn
170
- `clean-coder` when monitor only saw `inline_lag` (4c retries) without
171
- reaching 4e — that path retries or escalates via `inline_lag_streak ≥
195
+ `clean-coder` when monitor only saw `inline_lag` (5c retries) without
196
+ reaching 5e — that path retries or escalates via `inline_lag_streak ≥
172
197
  3` hard blocker, not fix pass.
173
198
 
174
199
  ## What orchestrator does per tick
@@ -196,7 +221,7 @@ can remove files mid-run — environmental risk.
196
221
  - **Path:** sibling of `state.json`.
197
222
  - **Format:** one tab-separated row per converged PR: ISO8601 UTC,
198
223
  owner/repo#number, bugbot SHA, bugteam SHA.
199
- - **Append site:** agent running `update_pull_request(pullNumber=PR_NUMBER, owner=OWNER, repo=REPO, draft=false)`. Append **before**
224
+ - **Append site:** agent running `update_pull_request(pullNumber=NUMBER, owner=OWNER, repo=REPO, draft=false)`. Append **before**
200
225
  locked `state.json` publish so log row survives failed merge.
201
226
  - **Never read inside loop.** User / follow-up tooling only.
202
227
 
@@ -0,0 +1,13 @@
1
+ # Post fix replies
2
+
3
+ Post fix reply on each addressed comment thread via add_reply_to_pull_request_comment
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
+ # Publish fix summary
2
+
3
+ Publish fix summary HTML via /doc-gist with commit SHA and per-fix descriptions
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
+ # Push
2
+
3
+ git push origin BRANCH, honor pre-push hooks
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
+ # Read file:lines
2
+
3
+ Read each referenced file:line before implementing
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
+ # Reset state
2
+
3
+ Set bugbot_clean_at=null, capture new current_head
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
+ # Resolve threads
2
+
3
+ Resolve each addressed thread via pull_request_review_write resolve_thread
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
+ # Spawn clean-coder
2
+
3
+ Spawn Agent(subagent_type=clean-coder) to implement fixes
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
+ # Stage and commit
2
+
3
+ git add files, git commit, honor pre-commit hooks
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
+