claude-dev-env 2.4.0 → 2.7.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 (309) hide show
  1. package/CLAUDE.md +26 -59
  2. package/_shared/pr-loop/scripts/_claude_permissions_common.py +84 -0
  3. package/_shared/pr-loop/scripts/code_rules_gate.py +6 -3
  4. package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +12 -2
  5. package/_shared/pr-loop/scripts/code_rules_gate_parts/baseline_import_isolation.py +309 -0
  6. package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_regression.py +540 -0
  7. package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +206 -70
  8. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/__init__.py +1 -0
  9. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/_repo_test_helpers.py +76 -0
  10. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_baseline_import_isolation.py +248 -0
  11. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_regression.py +309 -0
  12. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_running.py +91 -58
  13. package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +306 -306
  14. package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +44 -0
  15. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +202 -0
  16. package/_shared/pr-loop/scripts/pr_loop_shared_constants/copilot_quota_constants.py +24 -24
  17. package/_shared/pr-loop/scripts/pr_loop_shared_constants/stale_worktree_rule_sweep_constants.py +107 -107
  18. package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +290 -48
  19. package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +42 -2
  20. package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +36 -0
  21. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +100 -1
  22. package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -497
  23. package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +311 -2
  24. package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep.py +301 -301
  25. package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep_constants.py +85 -85
  26. package/_shared/pr-loop/worker-spawn.md +1 -1
  27. package/agents/CLAUDE.md +3 -2
  28. package/agents/caveman.md +0 -1
  29. package/agents/clasp-deployment-orchestrator.md +0 -1
  30. package/agents/clean-coder.md +0 -1
  31. package/agents/code-advisor.md +0 -1
  32. package/agents/code-quality-agent.md +1 -2
  33. package/agents/code-verifier.md +36 -8
  34. package/agents/deep-research.md +0 -1
  35. package/agents/docs-agent.md +0 -1
  36. package/agents/git-commit-crafter.md +0 -1
  37. package/agents/issue-tracker.md +42 -0
  38. package/agents/plan-packet-validator.md +0 -1
  39. package/agents/pr-description-writer.md +0 -1
  40. package/agents/test_agent_frontmatter.py +67 -18
  41. package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +143 -141
  42. package/bin/CLAUDE.md +68 -5
  43. package/bin/codex-compat.mjs +104 -0
  44. package/bin/codex-compat.test.mjs +51 -0
  45. package/bin/ever-shipped-skills.mjs +1 -0
  46. package/bin/install-constants.mjs +88 -0
  47. package/bin/install.mjs +1138 -114
  48. package/bin/install.prune.test.mjs +869 -19
  49. package/bin/install.test.mjs +906 -2
  50. package/codex-capability-map.json +13 -0
  51. package/commands/implement.md +1 -1
  52. package/commands/right-size.md +1 -1
  53. package/docs/CLAUDE.md +1 -0
  54. package/docs/CODE_RULES.md +2 -0
  55. package/docs/codex-compatibility.md +25 -0
  56. package/docs/host-pool-health-monitor.md +102 -0
  57. package/docs/nas-ssh-invocation.md +96 -12
  58. package/docs/references/CLAUDE.md +4 -2
  59. package/docs/references/advisor-tool.md +13 -0
  60. package/docs/references/code-review-enforcement.md +35 -0
  61. package/docs/references/team-advisor-skill.md +14 -0
  62. package/hooks/blocking/CLAUDE.md +4 -0
  63. package/hooks/blocking/code_review_pr_create_gate.py +7 -3
  64. package/hooks/blocking/code_review_push_gate.py +9 -4
  65. package/hooks/blocking/code_review_stamp_directory_write_blocker.py +8 -0
  66. package/hooks/blocking/config/__init__.py +5 -5
  67. package/hooks/blocking/config/code_review_enforcement_constants.py +40 -7
  68. package/hooks/blocking/config/test_code_review_enforcement_constants.py +58 -0
  69. package/hooks/blocking/config/verified_commit_constants.py +160 -159
  70. package/hooks/blocking/eli11_reply_enforcer.py +479 -0
  71. package/hooks/blocking/gh_body_arg_blocker.py +1 -1
  72. package/hooks/blocking/nas_ssh_binary_enforcer.py +8 -46
  73. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +256 -0
  74. package/hooks/blocking/pre_tool_use_dispatcher.py +24 -24
  75. package/hooks/blocking/shell_substitution_blocker.py +129 -0
  76. package/hooks/blocking/state_description_blocker.py +1 -1
  77. package/hooks/blocking/stop_dispatcher.py +1 -1
  78. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +2 -3
  79. package/hooks/blocking/test_code_review_pr_create_gate.py +14 -0
  80. package/hooks/blocking/test_code_review_push_gate.py +16 -0
  81. package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +19 -0
  82. package/hooks/blocking/test_eli11_reply_enforcer.py +457 -0
  83. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +231 -0
  84. package/hooks/blocking/test_pre_tool_use_dispatcher.py +10 -1
  85. package/hooks/blocking/test_shell_substitution_blocker.py +124 -0
  86. package/hooks/blocking/test_stop_dispatcher.py +23 -0
  87. package/hooks/blocking/test_unscoped_search_blocker.py +102 -0
  88. package/hooks/blocking/test_verdict_directory_write_blocker.py +804 -808
  89. package/hooks/blocking/test_verification_verdict_store.py +54 -0
  90. package/hooks/blocking/test_verified_commit_gate.py +581 -581
  91. package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +131 -131
  92. package/hooks/blocking/unscoped_search_blocker.py +391 -0
  93. package/hooks/blocking/verdict_directory_write_blocker.py +687 -687
  94. package/hooks/blocking/verification_verdict_store.py +1039 -1036
  95. package/hooks/blocking/verified_commit_message_accuracy_blocker.py +167 -167
  96. package/hooks/blocking/verifier_verdict_minter.py +280 -280
  97. package/hooks/git-hooks/CLAUDE.md +3 -0
  98. package/hooks/git-hooks/conftest.py +30 -0
  99. package/hooks/git-hooks/gate_utils.py +2 -2
  100. package/hooks/git-hooks/git_hooks_constants/__init__.py +41 -2
  101. package/hooks/git-hooks/pre_push.py +75 -4
  102. package/hooks/git-hooks/pre_push_base_reference.py +166 -0
  103. package/hooks/git-hooks/test_config.py +0 -15
  104. package/hooks/git-hooks/test_gate_utils.py +3 -15
  105. package/hooks/git-hooks/test_pre_commit.py +1 -15
  106. package/hooks/git-hooks/test_pre_push.py +257 -23
  107. package/hooks/git-hooks/test_pre_push_base_reference.py +339 -0
  108. package/hooks/hooks.json +10 -12
  109. package/hooks/hooks_constants/CLAUDE.md +7 -2
  110. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +4 -4
  111. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +101 -0
  112. package/hooks/hooks_constants/enter_worktree_prefetch_constants.py +18 -18
  113. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +2 -8
  114. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +48 -0
  115. package/hooks/hooks_constants/ruff_integration_constants.py +16 -0
  116. package/hooks/hooks_constants/shell_command_segments.py +82 -0
  117. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +67 -0
  118. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -0
  119. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +5 -6
  120. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +1 -0
  121. package/hooks/hooks_constants/unscoped_search_blocker_constants.py +153 -0
  122. package/hooks/lifecycle/enter_worktree_origin_prefetch.py +163 -146
  123. package/hooks/lifecycle/test_enter_worktree_origin_prefetch.py +185 -178
  124. package/hooks/pyproject.toml +1 -0
  125. package/hooks/validators/CLAUDE.md +1 -0
  126. package/hooks/validators/config/__init__.py +0 -0
  127. package/hooks/validators/config/directory_exemption_constants.py +183 -0
  128. package/hooks/validators/config/test_directory_exemption_constants.py +21 -0
  129. package/hooks/validators/conftest.py +4 -0
  130. package/hooks/validators/ruff_integration.py +49 -5
  131. package/hooks/validators/run_all_validators.py +206 -9
  132. package/hooks/validators/test_directory_exemption_constants.py +185 -0
  133. package/hooks/validators/test_python_antipattern_checks.py +110 -5
  134. package/hooks/validators/test_ruff_integration.py +92 -1
  135. package/hooks/validators/test_run_all_validators.py +115 -68
  136. package/hooks/validators/test_run_all_validators_pretooluse.py +159 -1
  137. package/package.json +13 -3
  138. package/rules/CLAUDE.md +17 -22
  139. package/rules/agent-spawn-protocol.md +6 -6
  140. package/rules/anti-corollary-tests.md +1 -1
  141. package/rules/bdd.md +1 -1
  142. package/rules/cleanup-temp-files.md +10 -4
  143. package/rules/code-standards.md +7 -0
  144. package/rules/conservative-action.md +1 -5
  145. package/rules/context7.md +0 -4
  146. package/rules/destructive-commands.md +47 -0
  147. package/rules/doc-inventory-integrity.md +48 -0
  148. package/rules/doc-prose-cuts.md +58 -0
  149. package/rules/docstring-prose-matches-implementation.md +53 -44
  150. package/rules/durable-post-artifacts.md +0 -4
  151. package/rules/eli11-replies.md +31 -0
  152. package/rules/explore-thoroughly.md +4 -4
  153. package/rules/falsify-before-green.md +68 -0
  154. package/rules/file-global-constants.md +1 -1
  155. package/rules/filesystem-search.md +51 -0
  156. package/rules/gh-cli-conventions.md +27 -0
  157. package/rules/git-workflow.md +26 -0
  158. package/rules/hedging-claims.md +9 -0
  159. package/rules/long-horizon-autonomy.md +0 -4
  160. package/rules/measurement-denominators.md +48 -0
  161. package/rules/nas-ssh-invocation.md +23 -5
  162. package/rules/parallel-tools.md +2 -2
  163. package/rules/plain-illustrative-docstrings.md +3 -7
  164. package/rules/plain-language.md +2 -0
  165. package/rules/proof-of-work-pr-comments.md +0 -4
  166. package/rules/re-stage-before-commit.md +2 -0
  167. package/rules/research-mode.md +10 -0
  168. package/rules/shell-invocation.md +21 -0
  169. package/rules/testing.md +4 -0
  170. package/rules/verified-commit-gate-skip.md +3 -27
  171. package/rules/verify-before-asking.md +5 -0
  172. package/rules/windows-filesystem-safe.md +1 -1
  173. package/rules/workers-done-before-complete.md +4 -0
  174. package/scripts/CLAUDE.md +1 -0
  175. package/scripts/Capture-PoolHealth.ps1 +410 -0
  176. package/scripts/Migrate-ShellPolicy.ps1 +1 -1
  177. package/scripts/_code_review_test_support.py +404 -0
  178. package/scripts/claude_chain_runner.py +141 -1
  179. package/scripts/codex_capability_bridge.py +171 -0
  180. package/scripts/codex_compat_materializer.py +1087 -0
  181. package/scripts/codex_compat_watcher.py +502 -0
  182. package/scripts/conftest.py +16 -1
  183. package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
  184. package/scripts/dev_env_scripts_constants/claude_chain_constants.py +9 -0
  185. package/scripts/dev_env_scripts_constants/code_review_constants.py +37 -0
  186. package/scripts/invoke_code_review.py +11 -4
  187. package/scripts/resolve_worker_spawn.py +626 -626
  188. package/scripts/spawn_grok_batch.py +672 -672
  189. package/scripts/sync_to_cursor/rules.py +0 -10
  190. package/scripts/test_claude_chain_runner.py +131 -0
  191. package/scripts/test_invoke_code_review.py +85 -908
  192. package/scripts/test_invoke_code_review_chain.py +70 -0
  193. package/scripts/test_invoke_code_review_cli.py +192 -0
  194. package/scripts/test_invoke_code_review_contract.py +256 -0
  195. package/scripts/test_invoke_code_review_git.py +123 -0
  196. package/scripts/test_invoke_code_review_mode.py +99 -0
  197. package/scripts/test_resolve_worker_spawn.py +1014 -1014
  198. package/scripts/tests/test_code_review_constants.py +80 -0
  199. package/scripts/tests/test_codex_capability_bridge.py +91 -0
  200. package/scripts/tests/test_codex_compat_materializer.py +632 -0
  201. package/scripts/tests/test_codex_compat_watcher.py +599 -0
  202. package/scripts/tests/test_sync_to_cursor.py +0 -1
  203. package/skills/CLAUDE.md +2 -0
  204. package/skills/auditing-claude-config/SKILL.md +114 -114
  205. package/skills/autoconverge/SKILL.md +427 -427
  206. package/skills/autoconverge/reference/convergence.md +24 -3
  207. package/skills/autoconverge/workflow/CLAUDE.md +1 -0
  208. package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +3 -3
  209. package/skills/autoconverge/workflow/converge.contract.test.mjs +1263 -1263
  210. package/skills/autoconverge/workflow/converge.mjs +168 -1
  211. package/skills/autoconverge/workflow/converge.p2-advance.test.mjs +202 -0
  212. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +2 -2
  213. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +2 -2
  214. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +2 -2
  215. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +2 -2
  216. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +2 -2
  217. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +2 -2
  218. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +2 -2
  219. package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +2 -2
  220. package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +265 -265
  221. package/skills/bugteam/reference/copilot-gap-analysis.md +1 -1
  222. package/skills/closeout/SKILL.md +33 -50
  223. package/skills/codex-review/scripts/codex_review_scripts_constants/run_constants.py +8 -0
  224. package/skills/codex-review/scripts/run_codex_review.py +233 -1
  225. package/skills/codex-review/scripts/test_run_codex_review.py +189 -0
  226. package/skills/condensing-instructions/SKILL.md +72 -0
  227. package/skills/copilot-review/SKILL.md +119 -119
  228. package/skills/e-code-review/SKILL.md +52 -0
  229. package/skills/e-code-review/reference/fix.md +54 -0
  230. package/skills/e-code-review/reference/loop.md +43 -0
  231. package/skills/e-code-review/reference/low.md +57 -0
  232. package/skills/e-code-review/reference/medium.md +153 -0
  233. package/skills/e-code-review/reference/xhigh.md +182 -0
  234. package/skills/e-simplify/SKILL.md +97 -0
  235. package/skills/fresh-branch/CLAUDE.md +1 -1
  236. package/skills/fresh-branch/SKILL.md +5 -6
  237. package/skills/fresh-branch/scripts/create_fresh_branch.py +42 -24
  238. package/skills/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +1 -3
  239. package/skills/fresh-branch/scripts/test_create_fresh_branch.py +30 -126
  240. package/skills/issue-tracker/SKILL.md +92 -0
  241. package/skills/issue-tracker/reference/epic-and-sub-issue-model.md +55 -0
  242. package/skills/issue-tracker/reference/handoff-schema.md +64 -0
  243. package/skills/issue-tracker/reference/operation-matrix.md +41 -0
  244. package/skills/orchestrator/SKILL.md +177 -22
  245. package/skills/orchestrator/scripts/status_gate.py +625 -0
  246. package/skills/orchestrator/scripts/status_gate_constants/__init__.py +1 -0
  247. package/skills/orchestrator/scripts/status_gate_constants/config/__init__.py +1 -0
  248. package/skills/orchestrator/scripts/status_gate_constants/config/constants.py +47 -0
  249. package/skills/orchestrator/scripts/test_status_gate.py +439 -0
  250. package/skills/orchestrator-refresh/SKILL.md +129 -35
  251. package/skills/plan-to-pr/SKILL.md +155 -0
  252. package/skills/plan-to-pr/reference/final-validation-tasks.md +15 -0
  253. package/skills/plan-to-pr/reference/model-routing.md +36 -0
  254. package/skills/plan-to-pr/reference/packet-contract.md +43 -0
  255. package/skills/plan-to-pr/reference/packet-schema.json +57 -0
  256. package/skills/plan-to-pr/reference/process-inventory.md +22 -0
  257. package/skills/plan-to-pr/reference/review-loop.md +33 -0
  258. package/skills/plan-to-pr/reference/run-record.schema.json +27 -0
  259. package/skills/plan-to-pr/reference/self-audit-tasks.md +15 -0
  260. package/skills/plan-to-pr/reference/task-seeds.md +14 -0
  261. package/skills/plan-to-pr/reference/task-ticket.md +38 -0
  262. package/skills/plan-to-pr/scripts/config/__init__.py +1 -0
  263. package/skills/plan-to-pr/scripts/config/constants.py +193 -0
  264. package/skills/plan-to-pr/scripts/create_packet.py +173 -0
  265. package/skills/plan-to-pr/scripts/test_create_packet.py +102 -0
  266. package/skills/plan-to-pr/scripts/test_validate_packet.py +256 -0
  267. package/skills/plan-to-pr/scripts/test_validate_protocol.py +135 -0
  268. package/skills/plan-to-pr/scripts/test_validate_run.py +158 -0
  269. package/skills/plan-to-pr/scripts/validate_packet.py +655 -0
  270. package/skills/plan-to-pr/scripts/validate_protocol.py +622 -0
  271. package/skills/plan-to-pr/scripts/validate_run.py +173 -0
  272. package/skills/plan-to-pr/test_skill_contract.py +207 -0
  273. package/skills/plan-to-pr/test_task_ticket_contract.py +151 -0
  274. package/skills/pr-converge/SKILL.md +472 -469
  275. package/skills/pr-converge/reference/examples.md +3 -3
  276. package/skills/pr-converge/reference/fix-protocol.md +1 -1
  277. package/skills/pr-converge/reference/ground-rules.md +7 -4
  278. package/skills/pr-converge/reference/multi-pr-orchestration.md +4 -1
  279. package/skills/pr-converge/reference/per-tick.md +5 -5
  280. package/skills/pr-converge/reference/progress-checklist.md +1 -1
  281. package/skills/pr-converge/scripts/check_convergence_gates.py +279 -279
  282. package/skills/pr-converge/scripts/test_check_convergence_codex.py +507 -507
  283. package/skills/pr-converge/scripts/test_check_convergence_gates.py +84 -84
  284. package/skills/pr-converge/test_step5_host_branch.py +1 -1
  285. package/skills/pr-fix-protocol/SKILL.md +1 -1
  286. package/skills/privacy-hygiene/SKILL.md +68 -68
  287. package/skills/privacy-hygiene/reference/sweep-procedure.md +1 -1
  288. package/skills/prototype/workflows/promotion.md +1 -1
  289. package/skills/release-notes-html/SKILL.md +164 -0
  290. package/skills/session-log/SKILL.md +1 -1
  291. package/skills/task-build/CLAUDE.md +8 -7
  292. package/skills/task-build/SKILL.md +16 -8
  293. package/skills/task-build/reference/tool-routing.md +19 -0
  294. package/rules/claude-md-orphan-file.md +0 -28
  295. package/rules/cleanup-command-forms.md +0 -23
  296. package/rules/code-reviews.md +0 -11
  297. package/rules/env-var-table-code-drift.md +0 -10
  298. package/rules/gh-body-file.md +0 -5
  299. package/rules/gh-paginate.md +0 -3
  300. package/rules/hook-prose-matches-detector.md +0 -15
  301. package/rules/no-historical-clutter.md +0 -26
  302. package/rules/no-inline-destructive-literals.md +0 -9
  303. package/rules/no-justification-noise.md +0 -61
  304. package/rules/package-inventory-stale-entry.md +0 -25
  305. package/rules/right-sized-engineering.md +0 -28
  306. package/rules/self-contained-docs.md +0 -17
  307. package/rules/shell-invocation-policy.md +0 -5
  308. package/rules/tdd.md +0 -7
  309. package/skills/closeout/reference/issue-body-templates.md +0 -108
@@ -1,427 +1,427 @@
1
- ---
2
- name: autoconverge
3
- description: >-
4
- Drives one draft PR to convergence in one autonomous run with a host-selected
5
- pacer. On workflow: three parallel lenses (code-review, bug-audit, self-review)
6
- and one-commit fixes via converge.mjs. On portable: pr-converge continuous ticks
7
- via portable-driver.md. Bugbot, Copilot, and Codex as terminal confirmation
8
- gates before ready. Use when the user says '/autoconverge', 'autoconverge this
9
- PR', 'converge this PR in one run', 'run the converge workflow', or 'drive the
10
- PR to ready autonomously'.
11
- ---
12
-
13
- # Autoconverge
14
-
15
- One launch drives the whole loop to convergence. The `/autoconverge` skill
16
- scans the tool list, selects a **pacer** (Workflow or portable), then resolves
17
- PR scope, enters a worktree, grants project permissions, and drives the shared
18
- converge product to ready (or a named blocker).
19
-
20
- | Pacer | Host surface | How the loop runs |
21
- |---|---|---|
22
- | `workflow` | Tool list includes `Workflow` | `converge.mjs` background pass; state in the workflow journal |
23
- | `portable` | `Workflow` absent | Continuous in-session ticks per [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md); same helpers and `check_convergence.py` ready definition |
24
-
25
- `pr-converge` selects `schedule_wakeup` or `portable` the same way. Both
26
- entry skills share the helper scripts and the convergence gate.
27
-
28
- ## Run scope: one PR or several
29
-
30
- Decide the scope from how many PRs the user named, then follow that path:
31
-
32
- 1. **One PR** → the single-PR run described below: one worktree, one pacer
33
- launch (`converge.mjs` on `pacer=workflow`, portable continuous ticks on
34
- `pacer=portable`), one teardown.
35
- 2. **Several PRs** → the [Multiple PRs](reference/multi-pr.md) run: on
36
- `pacer=workflow`, `workflow/converge_multi.mjs` drives every PR in parallel;
37
- on `pacer=portable`, run the portable driver once per PR (serial or host
38
- fan-out), then one teardown per PR.
39
-
40
- The single-PR sections (Requirements, Pre-flight, Run the workflow or portable
41
- driver, Teardown) each describe one converge run. The multi-PR reference reuses
42
- them once per PR and adds only what fanning out needs: a per-PR worktree and a
43
- per-PR teardown loop.
44
-
45
- ## Requirements
46
-
47
- Scan the tool list for `Workflow` and `ScheduleWakeup`, then select the pacer:
48
-
49
- ```
50
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/select_converge_pacer.py" \
51
- --skill autoconverge \
52
- --has-workflow <0|1> \
53
- --has-schedule-wakeup <0|1>
54
- ```
55
-
56
- - `pacer=workflow` — continue with Pre-flight and **Run the workflow** below.
57
- - `pacer=portable` — continue with Pre-flight (portable worktree rules when
58
- `EnterWorktree` is absent), then the continuous driver in
59
- [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md).
60
- **Do not abort** because the Workflow tool is missing.
61
-
62
- Transport still needs authenticated GitHub access for the PR's owner (`gh` or
63
- `pr-loop-cloud-transport`).
64
-
65
- ## Review-lens boundary
66
-
67
- The code-review lens boundary (workflow agent versus the built-in `/code-review`
68
- command) is defined on the **Code-review lens** bullet in
69
- [`reference/convergence.md`](reference/convergence.md).
70
-
71
- ## Transport check (before any GitHub step)
72
-
73
- Run `command -v gh`; when it succeeds, run `gh auth status`; once the PR
74
- scope is resolved, run `gh api repos/<owner>/<repo> --jq .permissions.push`
75
- and take `true` as the pass. When any check fails, run the
76
- `pr-loop-cloud-transport` skill first and route every `gh` operation in this
77
- skill through its substitution matrix. The workflow script
78
- (`workflow/converge.mjs`) embeds `gh` commands and gh-backed helper scripts in
79
- its agent prompts, so a cloud run also applies the same substitution to those
80
- agent prompts when it authors the launch — the transport skill covers the
81
- orchestrating session's own steps, and the script's agent-prompt text carries
82
- `gh` calls the spawned agents cannot run in a cloud session.
83
-
84
- ## Pre-flight (main session)
85
-
86
- 0. **Build the task list (step 1 of every run).** After Copilot quota / down
87
- flags and Codex required/down are known, run only:
88
-
89
- ```
90
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/build_converge_task_list.py" \
91
- --bugbot-down <0|1> --copilot-down <0|1> \
92
- --codex-down <0|1> --codex-required <0|1>
93
- ```
94
-
95
- Register every `tasks[]` entry on the session task list. **Final task** is
96
- always `all_runnable_reviews_clean_same_head` (`done_when` in the JSON).
97
- The run is complete only when that final task is completed — all runnable
98
- code reviews CLEAN on the same HEAD. Do not invent tasks in prose. On
99
- `pacer=portable`, `open-run` returns the same list; still register it as
100
- step 1 before driving reviews.
101
-
102
- 1. **Enter a worktree.** When `EnterWorktree` is in the tool list, call it with
103
- no arguments before any `gh`, `git`, file read, or edit. `gh`/`git` Bash
104
- calls do not auto-isolate, so isolation is mandatory. If it fails, report
105
- and stop. A bare `EnterWorktree` branches from `origin/main`; step 2
106
- positions the worktree on the PR's head ref. When `EnterWorktree` is
107
- absent, isolate with git worktree machinery per
108
- [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)
109
- § Isolation and worktree, then continue step 2.
110
-
111
- 2. **Resolve PR scope.** When the user passed a PR URL or number, parse owner,
112
- repo, and number from it. Otherwise read the current branch's PR:
113
- `gh pr view --json number,headRefName,url,isDraft,baseRefName`. Capture
114
- `owner`, `repo`, `prNumber`. Confirm the PR is a draft; if it is already
115
- ready, mark it draft first (`gh pr ready <n> --repo <o>/<r> --undo`) so the
116
- loop owns the ready transition.
117
-
118
- **Position the worktree on the PR branch.** The run reviews
119
- `git diff origin/main...HEAD` against this worktree's local `HEAD` and pushes
120
- each fix to the PR branch, so the worktree sits on the PR's head ref at the PR
121
- HEAD before the loop starts. A worktree fresh off `origin/main` has
122
- `HEAD == origin/main`, shows an empty diff, and reports a false convergence
123
- with zero findings. When a local worktree already tracks the PR branch, enter
124
- that one (pass its path to `EnterWorktree` when that tool exists; otherwise
125
- `cd` into it). Otherwise put the checkout on the branch with
126
- `gh pr checkout <number> --repo <owner>/<repo>`
127
- (or `git fetch origin <headRefName>` then `git switch <headRefName>`). Confirm
128
- before launching: `git rev-parse --abbrev-ref HEAD` equals the PR's head ref
129
- and local `HEAD` equals the PR head SHA.
130
-
131
- 3. **Verify the worktree is the PR's repo (strict pre-flight).** Run
132
- `python "$HOME/.claude/skills/_shared/pr-loop/scripts/preflight_worktree.py" --owner <owner> --repo <repo> --mode strict`.
133
- It confirms the working directory is a checkout of the PR's own repo and
134
- that `git worktree` machinery is healthy. A non-zero exit prints a
135
- `PREFLIGHT_OUTCOME` line and an `ABORT` line: report that line and stop.
136
- Autoconverge runs inside the PR's own repo, so a working directory rooted in
137
- a different repo (for example, `claude-dev-env` while the PR lives in
138
- `llm-settings`) or in no git checkout at all cannot continue.
139
-
140
- 4. **Grant project permissions.** Apply the `pr-loop-lifecycle` skill's Open
141
- section (`../pr-loop-lifecycle/SKILL.md`) — the grant command
142
- (`grant_project_claude_permissions.py`) and the auto-mode `AskUserQuestion`
143
- escalation for a blocked grant both live there.
144
-
145
- 5. **Copilot quota pre-check.** Before the pacer starts the loop, apply the
146
- `reviewer-gates` skill's Copilot quota gate (`../reviewer-gates/SKILL.md`)
147
- once. Exit 0 maps to `copilotDisabled: false` / `copilot_down=false`; any
148
- non-zero exit maps to `copilotDisabled: true` / `copilot_down=true`, and the
149
- run skips the Copilot gate with no agent spawned.
150
-
151
- 6. **Branch on pacer.** When `pacer=portable`, follow
152
- [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)
153
- § Continuous tick loop and § Autoconverge entry on portable pacer, then
154
- skip **Run the workflow** (no Workflow tool). When `pacer=workflow`,
155
- continue with **Run the workflow**.
156
-
157
- ## Run the workflow
158
-
159
- (`pacer=workflow` only.) Call the `Workflow` tool against the colocated script:
160
-
161
- ```
162
- Workflow({
163
- scriptPath: "<this skill dir>/workflow/converge.mjs",
164
- args: { owner: "<O>", repo: "<R>", prNumber: <N>, bugbotDisabled: false, copilotDisabled: false, homeDirectory: "<HOME>" }
165
- })
166
- ```
167
-
168
- `scriptPath` is the absolute path to `workflow/converge.mjs` inside this skill's
169
- own directory (on this install,
170
- `<home>/.claude/skills/autoconverge/workflow/converge.mjs`). `homeDirectory` is
171
- the absolute path to the directory that holds `.claude` (resolve it once from
172
- `$HOME`, or `$env:USERPROFILE` on Windows, with forward slashes). The workflow
173
- runs in a sandbox with no access to environment variables, so the run reads the
174
- home directory from this arg to build the path to the codex-review scripts the
175
- Codex gate calls; leave it out and the Codex gate cannot find those scripts. Set
176
- `bugbotDisabled: true` only when the user has opted Cursor Bugbot out for the
177
- run; otherwise the workflow detects an opt-out or an unreachable Bugbot on its
178
- own. Set `copilotDisabled: true` when the step 5 quota pre-check exits non-zero,
179
- and `false` when it exits 0; on `true` the workflow skips the Copilot gate with
180
- no agent spawned. The workflow runs in the background and notifies this session
181
- on completion. Watch live progress with `/workflows`.
182
-
183
- The moment the `Workflow` call returns its run id, write the durable handoff so a
184
- fresh session can resume the same run:
185
-
186
- ```
187
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/write_handoff.py" \
188
- --pr-number <N> --head-ref <branch> --phase workflow \
189
- --resume-command "Workflow({scriptPath, resumeFromRunId: '<runId>'})" \
190
- --run-id <runId>
191
- ```
192
-
193
- Write it again when the result lands, so the handoff carries the final run id and
194
- names the teardown phase the fresh session picks up from.
195
-
196
- The workflow returns
197
- `{ converged, rounds, finalSha, blocker, standardsNote, copilotNote, codexNote, cleanAuditNote, reuseNote, deferredPrs }`,
198
- plus a `userReview` field on a `blocker: "user-review"` return. `cleanAuditNote` is
199
- non-null when the environment refused the CLEAN bugteam review post and the run
200
- recorded the bypass — see
201
- [`reference/stop-conditions.md`](reference/stop-conditions.md) § Clean-audit post
202
- bypassed.
203
- `deferredPrs` is the list of draft environment-hardening PRs the standards-deferral
204
- path opened this run, each as `{ owner, repo, prNumber, copilotDisabled, bugbotDisabled }`.
205
- The two flags carry this run's Copilot and Bugbot availability, so the next generation
206
- skips a reviewer that is down or out of quota without re-probing. This list is the seed the
207
- [self-closing loop](reference/self-closing-loop.md) converges next.
208
-
209
- ## Copilot findings — tier, verify, then route
210
-
211
- The Copilot gate tiers each finding: a **self-healing** finding (style, type
212
- hints, imports, formatting, magic-value extraction, test-only or doc-vs-code
213
- fixes — nothing that changes observable runtime behavior) flows into the fix
214
- round with no user notification. A **code-concern** finding (logic, security,
215
- data handling, error-handling semantics, concurrency — the tier whenever in
216
- doubt) goes to a verification stage before any routing.
217
-
218
- Each code-concern finding gets its own verifier agent, all in parallel, inside
219
- the workflow. A verdict is conclusive only when an actual check ran: the verifier
220
- executes a command against the flagged HEAD — running the code path with crafted
221
- inputs, forcing the claimed error condition, or running a purpose-built test —
222
- and captures its output. The verdict carries
223
- `{ verdict, checkCommand, checkOutput, evidence }`; a conclusive verdict with an
224
- empty `checkCommand` or `checkOutput` downgrades to inconclusive.
225
-
226
- - **confirmed** — the check reproduces the defect. The finding becomes
227
- self-healing: it joins the fix round carrying its repro, and the fix re-runs
228
- that same check, adds a regression test where the suite covers the surface,
229
- lands in one commit, pushes, and replies on the thread with the fix SHA and the
230
- before/after output. No page.
231
- - **refuted** — the check shows the code already behaves correctly in the exact
232
- scenario the finding claims is broken. The workflow replies on the thread with
233
- the command and output, resolves it, and counts it clean. No page.
234
- - **inconclusive** — everything else, and the verifier's default: no runnable
235
- check exists, the check is infeasible here, the results are ambiguous, or the
236
- fix needs a product decision. Any doubt sorts here. Only inconclusive findings
237
- page the user.
238
-
239
- A round whose code concerns all confirm or refute never returns
240
- `blocker: "user-review"`. On one or more inconclusive findings, the workflow
241
- stops with `converged: false`, `blocker: "user-review"`, and a `userReview`
242
- field carrying
243
- `{ reviewUrl, findings: [{ file, line, severity, tier, title, evidence }] }` —
244
- `evidence` is the verifier's one-line note stating what check was attempted and
245
- why it was not decisive.
246
-
247
- The wait for a human belongs to the orchestrating session. On a
248
- `blocker: "user-review"` return, run the
249
- [`copilot-finding-triage`](../copilot-finding-triage/SKILL.md) skill for the ntfy
250
- page only (the per-finding summary and evidence note plus the `reviewUrl`
251
- Copilot review link), then hold for the user's response by pacer. On
252
- `pacer=portable`, override triage's hold step — ntfy plus the portable hold
253
- below; do not follow triage's `ScheduleWakeup` / `send_later` path.
254
-
255
- - **`pacer=workflow`** — triage hold: 45-minute `ScheduleWakeup` (or
256
- `send_later` when that is the host arm).
257
- - **`pacer=portable`** — portable hold only: in-session poll or handoff per
258
- [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md);
259
- never `ScheduleWakeup` or `send_later`.
260
-
261
- When the user answers within the window, follow their direction. When the
262
- window closes with no response, run normal teardown and report the
263
- inconclusive findings un-reviewed.
264
-
265
- ## Budget stop
266
-
267
- Branch the stop and resume path on the selected pacer. Full rule:
268
- [`reference/stop-conditions.md`](reference/stop-conditions.md) § Budget stop.
269
-
270
- - **`pacer=workflow`** — `converge.mjs` paces against the workflow `budget` API
271
- and stops at a round boundary when a full round does not fit. On a
272
- `blocker: "budget"` return, write the durable handoff with the run id and the
273
- `Workflow({scriptPath, resumeFromRunId})` resume command before stopping, so a
274
- fresh session resumes the paced run without the stopped session's transcript.
275
- - **`pacer=portable`** — stop at a tick boundary when the session cannot cover a
276
- full clean tick; write the durable handoff and resume with
277
- `/autoconverge <PR URL>` (see
278
- [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)).
279
- Do not instruct a Workflow resume on the portable path.
280
-
281
- ## Teardown
282
-
283
- ### `pacer=portable`
284
-
285
- Skip Workflow-only report steps that need a workflow run id (journal merge,
286
- HTML closing report, Artifact publish). Run `pr-loop-lifecycle` Close
287
- (description rewrite when converged, working-tree clean, permission revoke)
288
- and print the final report block using tick/`check_convergence` outcomes.
289
- User-review holds use the portable in-session poll (or handoff) from
290
- [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)
291
- — not `ScheduleWakeup`. Resume command: `/autoconverge <PR URL>`.
292
-
293
- ### `pacer=workflow` (on workflow completion)
294
-
295
- Teardown runs as an ordered checkpoint list. After each checkpoint finishes,
296
- re-write the durable handoff with `--phase teardown`, the run id, and the
297
- checkpoints done so far, so a fresh session that resumes reads `handoff.json`
298
- `completed_steps` and skips the checkpoints already done:
299
-
300
- ```
301
- python "$HOME/.claude/skills/_shared/pr-loop/scripts/write_handoff.py" \
302
- --pr-number <N> --head-ref <branch> --phase teardown \
303
- --resume-command "/autoconverge <PR URL>" \
304
- --run-id <runId> \
305
- --completed-steps "<checkpoints done so far>"
306
- ```
307
-
308
- The checkpoints run in this order: `report`, `close`. Write the
309
- handoff after each one finishes.
310
-
311
- On teardown entry, when `~/.claude/runtime/pr-loop/bugteam-pr-<N>/handoff.json`
312
- exists, read its `completed_steps` and skip any checkpoint the list already
313
- names, so a resumed run performs only the checkpoints left.
314
-
315
- On a `blocker: "user-review"` return under `pacer=workflow`, the workflow held
316
- one or more code-concern findings that stayed inconclusive after the
317
- executed-check verification stage. Run the
318
- [`copilot-finding-triage`](../copilot-finding-triage/SKILL.md) gate before
319
- teardown: send the ntfy alert with the per-finding summary and evidence note and
320
- the `userReview.reviewUrl` link, then hold with a 45-minute `ScheduleWakeup` (or
321
- `send_later` when that is the host arm). Act on the user's direction when it
322
- arrives inside the window; when the window closes with no response, fall through
323
- to normal teardown and report the `userReview.findings` un-reviewed. The PR
324
- stays a draft in this path — the workflow marked nothing ready. Under
325
- `pacer=portable`, use the portable teardown hold above (ntfy plus in-session
326
- poll or handoff; never `ScheduleWakeup`).
327
-
328
- Before the checkpoints, when the workflow returned a non-null `copilotNote`
329
- (the Copilot gate was bypassed), query the PR's reviews once more for a
330
- `copilot-pull-request-reviewer[bot]` review on the final HEAD
331
- (`fetch_copilot_reviews.py`, or the GitHub MCP `pull_request_read` method
332
- `get_reviews`). Copilot typically posts within 10–15 minutes of a request, so
333
- a review can land between the bypass and teardown. When one exists and
334
- carries findings, mark the PR draft, route the findings through one fix
335
- round per the `pr-fix-protocol` skill, re-verify, push, and mark the PR
336
- ready again — then run the checkpoints.
337
-
338
- 1. **When `converged` is true — build and publish the closing report.**
339
- Skip this entire step (report, artifact publish, comment, Chrome open) when
340
- the workflow returned a non-null `blocker`. Follow
341
- [`reference/closing-report.md`](reference/closing-report.md) § Building the
342
- report and § Publishing: resolve the seed journal from the run id, merge the
343
- PR's runs with `aggregate_runs.py`, spawn the `convergence-summary` agent
344
- (a `general-purpose` subagent) on the prompt it builds, draw the report with
345
- `render_report.py`, publish the HTML via the `Artifact` tool, post the
346
- one marker-keyed `<!-- autoconverge-report -->` PR comment, and open the
347
- artifact URL in Chrome. After the report is published, write the handoff
348
- with `--completed-steps "report"`.
349
-
350
- 2. **Close the run.** Apply the `pr-loop-lifecycle` skill's Close section
351
- (`../pr-loop-lifecycle/SKILL.md`): when `converged` is true, rewrite the PR
352
- description and clean the working tree — see
353
- [`pr-loop-lifecycle/reference/teardown-publish-permissions.md` § Clean working tree and § Publish the final PR description](../pr-loop-lifecycle/reference/teardown-publish-permissions.md);
354
- the workflow already marked the PR ready. The permission revoke always runs,
355
- including on a blocker exit. Write the handoff with
356
- `--completed-steps "report,close"`.
357
-
358
- 3. **Print the final report:**
359
-
360
- ```
361
- /autoconverge exit: <converged | blocked>
362
- Rounds: <N>
363
- Final commit: <finalSha>
364
- Blocker: <blocker> # only when blocked
365
- Standards: <standardsNote> # only when a round deferred code-standard findings
366
- Copilot: <copilotNote> # only when Copilot was down or out of quota
367
- Codex: <codexNote> # only when the Codex gate was bypassed (codex_down or opt-out)
368
- Clean-audit: <cleanAuditNote> # only when the CLEAN bugteam post was bypassed
369
- Reuse: <reuseNote> # only when the reuse pass identified an improvement
370
- ```
371
-
372
- ## What the workflow does each round
373
-
374
- [`reference/convergence.md`](reference/convergence.md) defines the whole loop:
375
- the merge-conflict pre-flight, the reuse pass and its three landing criteria,
376
- the round shape (static sweep, the three parallel reading lenses, dedup, the
377
- one-commit fix flow, the standards-deferral path), the terminal Bugbot, Copilot,
378
- and Codex gates, the per-role model tiers, the full-diff rule, and the exact
379
- ready definition `check_convergence.py` enforces.
380
- [`reference/stop-conditions.md`](reference/stop-conditions.md) lists every way
381
- the run ends short of ready. Hard-won failure lessons live in
382
- [`reference/gotchas.md`](reference/gotchas.md).
383
-
384
- Every agent prompt the workflow authors carries a headless-safety preamble —
385
- read-only agents get a trimmed form, edit agents the full form with the rm
386
- auto-allow paths — specified in
387
- [`reference/headless-safety.md`](reference/headless-safety.md).
388
-
389
- ## Multiple PRs
390
-
391
- When the user names several PRs, run the multi-PR path in
392
- [`reference/multi-pr.md`](reference/multi-pr.md): one worktree per PR
393
- (`git worktree add` on each head ref, strict pre-flight per worktree, one
394
- permission grant per repository, one Copilot quota check for the whole run),
395
- then launch by pacer — `pacer=workflow`: one `workflow/converge_multi.mjs`
396
- call with one entry per PR; `pacer=portable`: portable driver once per PR
397
- (serial or host fan-out) — then single-PR teardown once per PR and a
398
- one-line-per-PR summary.
399
-
400
- ## Self-closing loop: converge the deferred PRs
401
-
402
- Every autoconverge run — single-PR and multi-PR alike — ends with the
403
- self-closing loop in
404
- [`reference/self-closing-loop.md`](reference/self-closing-loop.md): the
405
- orchestrating session converges the draft environment-hardening PRs the run
406
- deferred (`deferredPrs` on a single-PR run, `allDeferredPrs` on a multi-PR
407
- run), then the PRs those runs defer, generation by generation, until a
408
- generation opens none. An empty seed list ends the loop at once. The reference
409
- also carries the Conventional-Commit title rule each hardening PR must meet.
410
-
411
- ## Folder map
412
-
413
- - `SKILL.md` — this hub.
414
- - [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md) — portable pacer when `Workflow` is absent.
415
- - `workflow/converge.mjs` — the convergence workflow script.
416
- - `workflow/converge_multi.mjs` — the multi-PR fan-out driver: one `converge.mjs` child run per PR in parallel, each pinned to its PR worktree via `repoPath`.
417
- - `workflow/aggregate_runs.py` — merges every autoconverge journal for a PR into one journal and returns its deduped findings, fix summaries, round count, and final SHA.
418
- - `workflow/convergence_summary.py` — builds the convergence-summary agent prompt over a PR's merged findings.
419
- - `workflow/render_report.py` — builds the closing convergence insights HTML report, taking the summary from `--summary-file`.
420
- - `workflow/autoconverge_report_constants/` — named constants for the report builder and the summary prompt.
421
- - `reference/convergence.md` — the whole loop: reuse pass, round shape, terminal gates, model tiers, ready definition.
422
- - `reference/stop-conditions.md` — every way the run ends short of ready, including the budget stop.
423
- - `reference/gotchas.md` — hard-won failure lessons.
424
- - `reference/closing-report.md` — the closing HTML report: data source, build steps, publishing.
425
- - `reference/multi-pr.md` — the several-PRs path: per-PR worktrees, the `converge_multi.mjs` launch, per-PR teardown.
426
- - `reference/self-closing-loop.md` — the deferred-PR generations and the Conventional-Commit title rule.
427
- - `reference/headless-safety.md` — the agent-prompt preamble and the rm auto-allow paths.
1
+ ---
2
+ name: autoconverge
3
+ description: >-
4
+ Drives one draft PR to convergence in one autonomous run with a host-selected
5
+ pacer. On workflow: three parallel lenses (code-review, bug-audit, self-review)
6
+ and one-commit fixes via converge.mjs. On portable: pr-converge continuous ticks
7
+ via portable-driver.md. Bugbot, Copilot, and Codex as terminal confirmation
8
+ gates before ready. Use when the user says '/autoconverge', 'autoconverge this
9
+ PR', 'converge this PR in one run', 'run the converge workflow', or 'drive the
10
+ PR to ready autonomously'.
11
+ ---
12
+
13
+ # Autoconverge
14
+
15
+ One launch drives the whole loop to convergence. The `/autoconverge` skill
16
+ scans the tool list, selects a **pacer** (Workflow or portable), then resolves
17
+ PR scope, enters a worktree, grants project permissions, and drives the shared
18
+ converge product to ready (or a named blocker).
19
+
20
+ | Pacer | Host surface | How the loop runs |
21
+ |---|---|---|
22
+ | `workflow` | Tool list includes `Workflow` | `converge.mjs` background pass; state in the workflow journal |
23
+ | `portable` | `Workflow` absent | Continuous in-session ticks per [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md); same helpers and `check_convergence.py` ready definition |
24
+
25
+ `pr-converge` selects `schedule_wakeup` or `portable` the same way. Both
26
+ entry skills share the helper scripts and the convergence gate.
27
+
28
+ ## Run scope: one PR or several
29
+
30
+ Decide the scope from how many PRs the user named, then follow that path:
31
+
32
+ 1. **One PR** → the single-PR run described below: one worktree, one pacer
33
+ launch (`converge.mjs` on `pacer=workflow`, portable continuous ticks on
34
+ `pacer=portable`), one teardown.
35
+ 2. **Several PRs** → the [Multiple PRs](reference/multi-pr.md) run: on
36
+ `pacer=workflow`, `workflow/converge_multi.mjs` drives every PR in parallel;
37
+ on `pacer=portable`, run the portable driver once per PR (serial or host
38
+ fan-out), then one teardown per PR.
39
+
40
+ The single-PR sections (Requirements, Pre-flight, Run the workflow or portable
41
+ driver, Teardown) each describe one converge run. The multi-PR reference reuses
42
+ them once per PR and adds only what fanning out needs: a per-PR worktree and a
43
+ per-PR teardown loop.
44
+
45
+ ## Requirements
46
+
47
+ Scan the tool list for `Workflow` and `ScheduleWakeup`, then select the pacer:
48
+
49
+ ```
50
+ python "$HOME/.claude/skills/_shared/pr-loop/scripts/select_converge_pacer.py" \
51
+ --skill autoconverge \
52
+ --has-workflow <0|1> \
53
+ --has-schedule-wakeup <0|1>
54
+ ```
55
+
56
+ - `pacer=workflow` — continue with Pre-flight and **Run the workflow** below.
57
+ - `pacer=portable` — continue with Pre-flight (portable worktree rules when
58
+ `EnterWorktree` is absent), then the continuous driver in
59
+ [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md).
60
+ **Do not abort** because the Workflow tool is missing.
61
+
62
+ Transport still needs authenticated GitHub access for the PR's owner (`gh` or
63
+ `pr-loop-cloud-transport`).
64
+
65
+ ## Review-lens boundary
66
+
67
+ The code-review lens boundary (workflow agent versus the built-in `/code-review`
68
+ command) is defined on the **Code-review lens** bullet in
69
+ [`reference/convergence.md`](reference/convergence.md).
70
+
71
+ ## Transport check (before any GitHub step)
72
+
73
+ Run `command -v gh`; when it succeeds, run `gh auth status`; once the PR
74
+ scope is resolved, run `gh api repos/<owner>/<repo> --jq .permissions.push`
75
+ and take `true` as the pass. When any check fails, run the
76
+ `pr-loop-cloud-transport` skill first and route every `gh` operation in this
77
+ skill through its substitution matrix. The workflow script
78
+ (`workflow/converge.mjs`) embeds `gh` commands and gh-backed helper scripts in
79
+ its agent prompts, so a cloud run also applies the same substitution to those
80
+ agent prompts when it authors the launch — the transport skill covers the
81
+ orchestrating session's own steps, and the script's agent-prompt text carries
82
+ `gh` calls the spawned agents cannot run in a cloud session.
83
+
84
+ ## Pre-flight (main session)
85
+
86
+ 0. **Build the task list (step 1 of every run).** After Copilot quota / down
87
+ flags and Codex required/down are known, run only:
88
+
89
+ ```
90
+ python "$HOME/.claude/skills/_shared/pr-loop/scripts/build_converge_task_list.py" \
91
+ --bugbot-down <0|1> --copilot-down <0|1> \
92
+ --codex-down <0|1> --codex-required <0|1>
93
+ ```
94
+
95
+ Register every `tasks[]` entry on the session task list. **Final task** is
96
+ always `all_runnable_reviews_clean_same_head` (`done_when` in the JSON).
97
+ The run is complete only when that final task is completed — all runnable
98
+ code reviews CLEAN on the same HEAD. Do not invent tasks in prose. On
99
+ `pacer=portable`, `open-run` returns the same list; still register it as
100
+ step 1 before driving reviews.
101
+
102
+ 1. **Enter a worktree.** When `EnterWorktree` is in the tool list, call it with
103
+ no arguments before any `gh`, `git`, file read, or edit. `gh`/`git` Bash
104
+ calls do not auto-isolate, so isolation is mandatory. If it fails, report
105
+ and stop. A bare `EnterWorktree` branches from `origin/main`; step 2
106
+ positions the worktree on the PR's head ref. When `EnterWorktree` is
107
+ absent, isolate with git worktree machinery per
108
+ [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)
109
+ § Isolation and worktree, then continue step 2.
110
+
111
+ 2. **Resolve PR scope.** When the user passed a PR URL or number, parse owner,
112
+ repo, and number from it. Otherwise read the current branch's PR:
113
+ `gh pr view --json number,headRefName,url,isDraft,baseRefName`. Capture
114
+ `owner`, `repo`, `prNumber`. Confirm the PR is a draft; if it is already
115
+ ready, mark it draft first (`gh pr ready <n> --repo <o>/<r> --undo`) so the
116
+ loop owns the ready transition.
117
+
118
+ **Position the worktree on the PR branch.** The run reviews
119
+ `git diff origin/main...HEAD` against this worktree's local `HEAD` and pushes
120
+ each fix to the PR branch, so the worktree sits on the PR's head ref at the PR
121
+ HEAD before the loop starts. A worktree fresh off `origin/main` has
122
+ `HEAD == origin/main`, shows an empty diff, and reports a false convergence
123
+ with zero findings. When a local worktree already tracks the PR branch, enter
124
+ that one (pass its path to `EnterWorktree` when that tool exists; otherwise
125
+ `cd` into it). Otherwise put the checkout on the branch with
126
+ `gh pr checkout <number> --repo <owner>/<repo>`
127
+ (or `git fetch origin <headRefName>` then `git switch <headRefName>`). Confirm
128
+ before launching: `git rev-parse --abbrev-ref HEAD` equals the PR's head ref
129
+ and local `HEAD` equals the PR head SHA.
130
+
131
+ 3. **Verify the worktree is the PR's repo (strict pre-flight).** Run
132
+ `python "$HOME/.claude/skills/_shared/pr-loop/scripts/preflight_worktree.py" --owner <owner> --repo <repo> --mode strict`.
133
+ It confirms the working directory is a checkout of the PR's own repo and
134
+ that `git worktree` machinery is healthy. A non-zero exit prints a
135
+ `PREFLIGHT_OUTCOME` line and an `ABORT` line: report that line and stop.
136
+ Autoconverge runs inside the PR's own repo, so a working directory rooted in
137
+ a different repo (for example, `claude-dev-env` while the PR lives in
138
+ `llm-settings`) or in no git checkout at all cannot continue.
139
+
140
+ 4. **Grant project permissions.** Apply the `pr-loop-lifecycle` skill's Open
141
+ section (`../pr-loop-lifecycle/SKILL.md`) — the grant command
142
+ (`grant_project_claude_permissions.py`) and the auto-mode `AskUserQuestion`
143
+ escalation for a blocked grant both live there.
144
+
145
+ 5. **Copilot quota pre-check.** Before the pacer starts the loop, apply the
146
+ `reviewer-gates` skill's Copilot quota gate (`../reviewer-gates/SKILL.md`)
147
+ once. Exit 0 maps to `copilotDisabled: false` / `copilot_down=false`; any
148
+ non-zero exit maps to `copilotDisabled: true` / `copilot_down=true`, and the
149
+ run skips the Copilot gate with no agent spawned.
150
+
151
+ 6. **Branch on pacer.** When `pacer=portable`, follow
152
+ [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)
153
+ § Continuous tick loop and § Autoconverge entry on portable pacer, then
154
+ skip **Run the workflow** (no Workflow tool). When `pacer=workflow`,
155
+ continue with **Run the workflow**.
156
+
157
+ ## Run the workflow
158
+
159
+ (`pacer=workflow` only.) Call the `Workflow` tool against the colocated script:
160
+
161
+ ```
162
+ Workflow({
163
+ scriptPath: "<this skill dir>/workflow/converge.mjs",
164
+ args: { owner: "<O>", repo: "<R>", prNumber: <N>, bugbotDisabled: false, copilotDisabled: false, homeDirectory: "<HOME>" }
165
+ })
166
+ ```
167
+
168
+ `scriptPath` is the absolute path to `workflow/converge.mjs` inside this skill's
169
+ own directory (on this install,
170
+ `<home>/.claude/skills/autoconverge/workflow/converge.mjs`). `homeDirectory` is
171
+ the absolute path to the directory that holds `.claude` (resolve it once from
172
+ `$HOME`, or `$env:USERPROFILE` on Windows, with forward slashes). The workflow
173
+ runs in a sandbox with no access to environment variables, so the run reads the
174
+ home directory from this arg to build the path to the codex-review scripts the
175
+ Codex gate calls; leave it out and the Codex gate cannot find those scripts. Set
176
+ `bugbotDisabled: true` only when the user has opted Cursor Bugbot out for the
177
+ run; otherwise the workflow detects an opt-out or an unreachable Bugbot on its
178
+ own. Set `copilotDisabled: true` when the step 5 quota pre-check exits non-zero,
179
+ and `false` when it exits 0; on `true` the workflow skips the Copilot gate with
180
+ no agent spawned. The workflow runs in the background and notifies this session
181
+ on completion. Watch live progress with `/workflows`.
182
+
183
+ The moment the `Workflow` call returns its run id, write the durable handoff so a
184
+ fresh session can resume the same run:
185
+
186
+ ```
187
+ python "$HOME/.claude/skills/_shared/pr-loop/scripts/write_handoff.py" \
188
+ --pr-number <N> --head-ref <branch> --phase workflow \
189
+ --resume-command "Workflow({scriptPath, resumeFromRunId: '<runId>'})" \
190
+ --run-id <runId>
191
+ ```
192
+
193
+ Write it again when the result lands, so the handoff carries the final run id and
194
+ names the teardown phase the fresh session picks up from.
195
+
196
+ The workflow returns
197
+ `{ converged, rounds, finalSha, blocker, standardsNote, copilotNote, codexNote, cleanAuditNote, reuseNote, deferredPrs }`,
198
+ plus a `userReview` field on a `blocker: "user-review"` return. `cleanAuditNote` is
199
+ non-null when the environment refused the CLEAN bugteam review post and the run
200
+ recorded the bypass — see
201
+ [`reference/stop-conditions.md`](reference/stop-conditions.md) § Clean-audit post
202
+ bypassed.
203
+ `deferredPrs` is the list of draft environment-hardening PRs the standards-deferral
204
+ path opened this run, each as `{ owner, repo, prNumber, copilotDisabled, bugbotDisabled }`.
205
+ The two flags carry this run's Copilot and Bugbot availability, so the next generation
206
+ skips a reviewer that is down or out of quota without re-probing. This list is the seed the
207
+ [self-closing loop](reference/self-closing-loop.md) converges next.
208
+
209
+ ## Copilot findings — tier, verify, then route
210
+
211
+ The Copilot gate tiers each finding: a **self-healing** finding (style, type
212
+ hints, imports, formatting, magic-value extraction, test-only or doc-vs-code
213
+ fixes — nothing that changes observable runtime behavior) flows into the fix
214
+ round with no user notification. A **code-concern** finding (logic, security,
215
+ data handling, error-handling semantics, concurrency — the tier whenever in
216
+ doubt) goes to a verification stage before any routing.
217
+
218
+ Each code-concern finding gets its own verifier agent, all in parallel, inside
219
+ the workflow. A verdict is conclusive only when an actual check ran: the verifier
220
+ executes a command against the flagged HEAD — running the code path with crafted
221
+ inputs, forcing the claimed error condition, or running a purpose-built test —
222
+ and captures its output. The verdict carries
223
+ `{ verdict, checkCommand, checkOutput, evidence }`; a conclusive verdict with an
224
+ empty `checkCommand` or `checkOutput` downgrades to inconclusive.
225
+
226
+ - **confirmed** — the check reproduces the defect. The finding becomes
227
+ self-healing: it joins the fix round carrying its repro, and the fix re-runs
228
+ that same check, adds a regression test where the suite covers the surface,
229
+ lands in one commit, pushes, and replies on the thread with the fix SHA and the
230
+ before/after output. No page.
231
+ - **refuted** — the check shows the code already behaves correctly in the exact
232
+ scenario the finding claims is broken. The workflow replies on the thread with
233
+ the command and output, resolves it, and counts it clean. No page.
234
+ - **inconclusive** — everything else, and the verifier's default: no runnable
235
+ check exists, the check is infeasible here, the results are ambiguous, or the
236
+ fix needs a product decision. Any doubt sorts here. Only inconclusive findings
237
+ page the user.
238
+
239
+ A round whose code concerns all confirm or refute never returns
240
+ `blocker: "user-review"`. On one or more inconclusive findings, the workflow
241
+ stops with `converged: false`, `blocker: "user-review"`, and a `userReview`
242
+ field carrying
243
+ `{ reviewUrl, findings: [{ file, line, severity, tier, title, evidence }] }` —
244
+ `evidence` is the verifier's one-line note stating what check was attempted and
245
+ why it was not decisive.
246
+
247
+ The wait for a human belongs to the orchestrating session. On a
248
+ `blocker: "user-review"` return, run the
249
+ [`copilot-finding-triage`](../copilot-finding-triage/SKILL.md) skill for the ntfy
250
+ page only (the per-finding summary and evidence note plus the `reviewUrl`
251
+ Copilot review link), then hold for the user's response by pacer. On
252
+ `pacer=portable`, override triage's hold step — ntfy plus the portable hold
253
+ below; do not follow triage's `ScheduleWakeup` / `send_later` path.
254
+
255
+ - **`pacer=workflow`** — triage hold: 45-minute `ScheduleWakeup` (or
256
+ `send_later` when that is the host arm).
257
+ - **`pacer=portable`** — portable hold only: in-session poll or handoff per
258
+ [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md);
259
+ never `ScheduleWakeup` or `send_later`.
260
+
261
+ When the user answers within the window, follow their direction. When the
262
+ window closes with no response, run normal teardown and report the
263
+ inconclusive findings un-reviewed.
264
+
265
+ ## Budget stop
266
+
267
+ Branch the stop and resume path on the selected pacer. Full rule:
268
+ [`reference/stop-conditions.md`](reference/stop-conditions.md) § Budget stop.
269
+
270
+ - **`pacer=workflow`** — `converge.mjs` paces against the workflow `budget` API
271
+ and stops at a round boundary when a full round does not fit. On a
272
+ `blocker: "budget"` return, write the durable handoff with the run id and the
273
+ `Workflow({scriptPath, resumeFromRunId})` resume command before stopping, so a
274
+ fresh session resumes the paced run without the stopped session's transcript.
275
+ - **`pacer=portable`** — stop at a tick boundary when the session cannot cover a
276
+ full clean tick; write the durable handoff and resume with
277
+ `/autoconverge <PR URL>` (see
278
+ [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)).
279
+ Do not instruct a Workflow resume on the portable path.
280
+
281
+ ## Teardown
282
+
283
+ ### `pacer=portable`
284
+
285
+ Skip Workflow-only report steps that need a workflow run id (journal merge,
286
+ HTML closing report, Artifact publish). Run `pr-loop-lifecycle` Close
287
+ (description rewrite when converged, working-tree clean, permission revoke)
288
+ and print the final report block using tick/`check_convergence` outcomes.
289
+ User-review holds use the portable in-session poll (or handoff) from
290
+ [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md)
291
+ — not `ScheduleWakeup`. Resume command: `/autoconverge <PR URL>`.
292
+
293
+ ### `pacer=workflow` (on workflow completion)
294
+
295
+ Teardown runs as an ordered checkpoint list. After each checkpoint finishes,
296
+ re-write the durable handoff with `--phase teardown`, the run id, and the
297
+ checkpoints done so far, so a fresh session that resumes reads `handoff.json`
298
+ `completed_steps` and skips the checkpoints already done:
299
+
300
+ ```
301
+ python "$HOME/.claude/skills/_shared/pr-loop/scripts/write_handoff.py" \
302
+ --pr-number <N> --head-ref <branch> --phase teardown \
303
+ --resume-command "/autoconverge <PR URL>" \
304
+ --run-id <runId> \
305
+ --completed-steps "<checkpoints done so far>"
306
+ ```
307
+
308
+ The checkpoints run in this order: `report`, `close`. Write the
309
+ handoff after each one finishes.
310
+
311
+ On teardown entry, when `~/.claude/runtime/pr-loop/bugteam-pr-<N>/handoff.json`
312
+ exists, read its `completed_steps` and skip any checkpoint the list already
313
+ names, so a resumed run performs only the checkpoints left.
314
+
315
+ On a `blocker: "user-review"` return under `pacer=workflow`, the workflow held
316
+ one or more code-concern findings that stayed inconclusive after the
317
+ executed-check verification stage. Run the
318
+ [`copilot-finding-triage`](../copilot-finding-triage/SKILL.md) gate before
319
+ teardown: send the ntfy alert with the per-finding summary and evidence note and
320
+ the `userReview.reviewUrl` link, then hold with a 45-minute `ScheduleWakeup` (or
321
+ `send_later` when that is the host arm). Act on the user's direction when it
322
+ arrives inside the window; when the window closes with no response, fall through
323
+ to normal teardown and report the `userReview.findings` un-reviewed. The PR
324
+ stays a draft in this path — the workflow marked nothing ready. Under
325
+ `pacer=portable`, use the portable teardown hold above (ntfy plus in-session
326
+ poll or handoff; never `ScheduleWakeup`).
327
+
328
+ Before the checkpoints, when the workflow returned a non-null `copilotNote`
329
+ (the Copilot gate was bypassed), query the PR's reviews once more for a
330
+ `copilot-pull-request-reviewer[bot]` review on the final HEAD
331
+ (`fetch_copilot_reviews.py`, or the GitHub MCP `pull_request_read` method
332
+ `get_reviews`). Copilot typically posts within 10–15 minutes of a request, so
333
+ a review can land between the bypass and teardown. When one exists and
334
+ carries findings, mark the PR draft, route the findings through one fix
335
+ round per the `pr-fix-protocol` skill, re-verify, push, and mark the PR
336
+ ready again — then run the checkpoints.
337
+
338
+ 1. **When `converged` is true — build and publish the closing report.**
339
+ Skip this entire step (report, artifact publish, comment, Chrome open) when
340
+ the workflow returned a non-null `blocker`. Follow
341
+ [`reference/closing-report.md`](reference/closing-report.md) § Building the
342
+ report and § Publishing: resolve the seed journal from the run id, merge the
343
+ PR's runs with `aggregate_runs.py`, spawn the `convergence-summary` agent
344
+ (a `general-purpose` subagent) on the prompt it builds, draw the report with
345
+ `render_report.py`, publish the HTML via the `Artifact` tool, post the
346
+ one marker-keyed `<!-- autoconverge-report -->` PR comment, and open the
347
+ artifact URL in Chrome. After the report is published, write the handoff
348
+ with `--completed-steps "report"`.
349
+
350
+ 2. **Close the run.** Apply the `pr-loop-lifecycle` skill's Close section
351
+ (`../pr-loop-lifecycle/SKILL.md`): when `converged` is true, rewrite the PR
352
+ description and clean the working tree — see
353
+ [`pr-loop-lifecycle/reference/teardown-publish-permissions.md` § Clean working tree and § Publish the final PR description](../pr-loop-lifecycle/reference/teardown-publish-permissions.md);
354
+ the workflow already marked the PR ready. The permission revoke always runs,
355
+ including on a blocker exit. Write the handoff with
356
+ `--completed-steps "report,close"`.
357
+
358
+ 3. **Print the final report:**
359
+
360
+ ```
361
+ /autoconverge exit: <converged | blocked>
362
+ Rounds: <N>
363
+ Final commit: <finalSha>
364
+ Blocker: <blocker> # only when blocked
365
+ Standards: <standardsNote> # only when a round deferred code-standard findings
366
+ Copilot: <copilotNote> # only when Copilot was down or out of quota
367
+ Codex: <codexNote> # only when the Codex gate was bypassed (codex_down or opt-out)
368
+ Clean-audit: <cleanAuditNote> # only when the CLEAN bugteam post was bypassed
369
+ Reuse: <reuseNote> # only when the reuse pass identified an improvement
370
+ ```
371
+
372
+ ## What the workflow does each round
373
+
374
+ [`reference/convergence.md`](reference/convergence.md) defines the whole loop:
375
+ the merge-conflict pre-flight, the reuse pass and its three landing criteria,
376
+ the round shape (static sweep, the three parallel reading lenses, dedup, the
377
+ one-commit fix flow, the standards-deferral path), the terminal Bugbot, Copilot,
378
+ and Codex gates, the per-role model tiers, the full-diff rule, and the exact
379
+ ready definition `check_convergence.py` enforces.
380
+ [`reference/stop-conditions.md`](reference/stop-conditions.md) lists every way
381
+ the run ends short of ready. Hard-won failure lessons live in
382
+ [`reference/gotchas.md`](reference/gotchas.md).
383
+
384
+ Every agent prompt the workflow authors carries a headless-safety preamble —
385
+ read-only agents get a trimmed form, edit agents the full form with the rm
386
+ auto-allow paths — specified in
387
+ [`reference/headless-safety.md`](reference/headless-safety.md).
388
+
389
+ ## Multiple PRs
390
+
391
+ When the user names several PRs, run the multi-PR path in
392
+ [`reference/multi-pr.md`](reference/multi-pr.md): one worktree per PR
393
+ (`git worktree add` on each head ref, strict pre-flight per worktree, one
394
+ permission grant per repository, one Copilot quota check for the whole run),
395
+ then launch by pacer — `pacer=workflow`: one `workflow/converge_multi.mjs`
396
+ call with one entry per PR; `pacer=portable`: portable driver once per PR
397
+ (serial or host fan-out) — then single-PR teardown once per PR and a
398
+ one-line-per-PR summary.
399
+
400
+ ## Self-closing loop: converge the deferred PRs
401
+
402
+ Every autoconverge run — single-PR and multi-PR alike — ends with the
403
+ self-closing loop in
404
+ [`reference/self-closing-loop.md`](reference/self-closing-loop.md): the
405
+ orchestrating session converges the draft environment-hardening PRs the run
406
+ deferred (`deferredPrs` on a single-PR run, `allDeferredPrs` on a multi-PR
407
+ run), then the PRs those runs defer, generation by generation, until a
408
+ generation opens none. An empty seed list ends the loop at once. The reference
409
+ also carries the Conventional-Commit title rule each hardening PR must meet.
410
+
411
+ ## Folder map
412
+
413
+ - `SKILL.md` — this hub.
414
+ - [`../_shared/pr-loop/portable-driver.md`](../_shared/pr-loop/portable-driver.md) — portable pacer when `Workflow` is absent.
415
+ - `workflow/converge.mjs` — the convergence workflow script.
416
+ - `workflow/converge_multi.mjs` — the multi-PR fan-out driver: one `converge.mjs` child run per PR in parallel, each pinned to its PR worktree via `repoPath`.
417
+ - `workflow/aggregate_runs.py` — merges every autoconverge journal for a PR into one journal and returns its deduped findings, fix summaries, round count, and final SHA.
418
+ - `workflow/convergence_summary.py` — builds the convergence-summary agent prompt over a PR's merged findings.
419
+ - `workflow/render_report.py` — builds the closing convergence insights HTML report, taking the summary from `--summary-file`.
420
+ - `workflow/autoconverge_report_constants/` — named constants for the report builder and the summary prompt.
421
+ - `reference/convergence.md` — the whole loop: reuse pass, round shape, terminal gates, model tiers, ready definition.
422
+ - `reference/stop-conditions.md` — every way the run ends short of ready, including the budget stop.
423
+ - `reference/gotchas.md` — hard-won failure lessons.
424
+ - `reference/closing-report.md` — the closing HTML report: data source, build steps, publishing.
425
+ - `reference/multi-pr.md` — the several-PRs path: per-PR worktrees, the `converge_multi.mjs` launch, per-PR teardown.
426
+ - `reference/self-closing-loop.md` — the deferred-PR generations and the Conventional-Commit title rule.
427
+ - `reference/headless-safety.md` — the agent-prompt preamble and the rm auto-allow paths.