claude-dev-env 1.38.0 → 1.39.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 (271) 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 +189 -0
  7. package/_shared/pr-loop/scripts/post_audit_thread.py +947 -0
  8. package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +0 -19
  9. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +923 -0
  10. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +127 -0
  11. package/_shared/pr-loop/state-schema.md +1 -1
  12. package/agents/clean-coder.md +2 -2
  13. package/bin/install.mjs +6 -7
  14. package/bin/install.test.mjs +8 -0
  15. package/commands/doc-gist.md +16 -0
  16. package/commands/plan.md +0 -2
  17. package/commands/review-plan.md +1 -1
  18. package/docs/CODE_RULES.md +122 -2
  19. package/hooks/blocking/bot_mention_comment_blocker.py +75 -0
  20. package/hooks/blocking/code_rules_enforcer.py +1236 -161
  21. package/hooks/blocking/convergence_gate_blocker.py +130 -0
  22. package/hooks/blocking/destructive_command_blocker.py +74 -0
  23. package/hooks/blocking/gh_body_arg_blocker.py +30 -0
  24. package/hooks/blocking/md_to_html_blocker.py +119 -0
  25. package/hooks/blocking/test_bot_mention_comment_blocker.py +131 -0
  26. package/hooks/blocking/test_code_rules_enforcer.py +21 -0
  27. package/hooks/blocking/test_code_rules_enforcer_any_exempt_files.py +70 -0
  28. package/hooks/blocking/test_code_rules_enforcer_any_imports_and_cast.py +92 -0
  29. package/hooks/blocking/test_code_rules_enforcer_banned_import_alias.py +143 -0
  30. package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +152 -0
  31. package/hooks/blocking/test_code_rules_enforcer_bare_except.py +120 -0
  32. package/hooks/blocking/test_code_rules_enforcer_boundary_types.py +175 -0
  33. package/hooks/blocking/test_code_rules_enforcer_cap_meta.py +0 -1
  34. package/hooks/blocking/test_code_rules_enforcer_collection_prefix.py +50 -0
  35. package/hooks/blocking/test_code_rules_enforcer_docstring_format.py +255 -0
  36. package/hooks/blocking/test_code_rules_enforcer_inline_tuple_string_magic.py +130 -0
  37. package/hooks/blocking/test_code_rules_enforcer_stub_implementations.py +141 -0
  38. package/hooks/blocking/test_code_rules_enforcer_test_branching.py +143 -0
  39. package/hooks/blocking/test_code_rules_enforcer_thin_wrapper_files.py +169 -0
  40. package/hooks/blocking/test_code_rules_enforcer_todo_markers.py +99 -0
  41. package/hooks/blocking/test_code_rules_enforcer_typed_dict_pairs.py +141 -0
  42. package/hooks/blocking/test_code_rules_enforcer_unused_imports.py +158 -0
  43. package/hooks/blocking/test_convergence_gate_blocker.py +63 -0
  44. package/hooks/blocking/test_destructive_command_blocker.py +146 -0
  45. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +102 -0
  46. package/hooks/blocking/test_gh_body_arg_blocker.py +45 -0
  47. package/hooks/blocking/test_md_to_html_blocker.py +317 -0
  48. package/hooks/config/any_type_config.py +7 -0
  49. package/hooks/config/banned_identifiers_constants.py +11 -0
  50. package/hooks/config/blocking_check_limits.py +38 -0
  51. package/hooks/config/bot_mention_comment_blocker_constants.py +20 -0
  52. package/hooks/config/code_rules_enforcer_constants.py +53 -0
  53. package/hooks/config/convergence_branch_constants.py +9 -0
  54. package/hooks/config/doc_gist_auto_publish_constants.py +18 -0
  55. package/hooks/config/html_companion_constants.py +20 -0
  56. package/hooks/config/inline_tuple_string_magic_constants.py +22 -0
  57. package/hooks/config/test_banned_identifiers_constants.py +17 -0
  58. package/hooks/hooks.json +28 -20
  59. package/hooks/pyproject.toml +69 -0
  60. package/hooks/validators/mypy_integration.py +47 -1
  61. package/hooks/validators/run_all_validators.py +3 -3
  62. package/hooks/validators/test_mypy_integration.py +50 -1
  63. package/hooks/workflow/doc_gist_auto_publish.py +144 -0
  64. package/hooks/workflow/md_to_html_companion.py +365 -0
  65. package/hooks/workflow/test_doc_gist_auto_publish.py +117 -0
  66. package/hooks/workflow/test_md_to_html_companion.py +452 -0
  67. package/package.json +1 -1
  68. package/rules/gh-body-file.md +2 -0
  69. package/scripts/Install-SweepEmptyDirs.ps1 +111 -0
  70. package/scripts/check.ps1 +106 -0
  71. package/scripts/config/timing.py +11 -0
  72. package/scripts/sweep_empty_dirs.py +138 -0
  73. package/scripts/sync_to_cursor/rules.py +1 -1
  74. package/scripts/test_sweep_empty_dirs.py +183 -0
  75. package/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +323 -0
  76. package/skills/_shared/pr-loop/scripts/_cli_utils.py +22 -0
  77. package/skills/_shared/pr-loop/scripts/_path_resolver.py +165 -0
  78. package/skills/_shared/pr-loop/scripts/_xml_utils.py +20 -0
  79. package/skills/_shared/pr-loop/scripts/build_audit_prompt.py +182 -0
  80. package/skills/_shared/pr-loop/scripts/build_fix_prompt.py +185 -0
  81. package/skills/_shared/pr-loop/scripts/config/__init__.py +0 -0
  82. package/skills/_shared/pr-loop/scripts/config/path_resolver_constants.py +78 -0
  83. package/skills/_shared/pr-loop/scripts/init_loop_state.py +135 -0
  84. package/skills/_shared/pr-loop/scripts/teardown_worktrees.py +175 -0
  85. package/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +182 -0
  86. package/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +206 -0
  87. package/skills/bugteam/CONSTRAINTS.md +21 -22
  88. package/skills/bugteam/EXAMPLES.md +3 -3
  89. package/skills/bugteam/PROMPTS.md +227 -67
  90. package/skills/bugteam/SKILL.md +114 -455
  91. package/skills/bugteam/reference/README.md +1 -1
  92. package/skills/bugteam/reference/audit-and-teammates.md +112 -39
  93. package/skills/bugteam/reference/audit-contract.md +4 -22
  94. package/skills/bugteam/reference/copilot-gap-analysis.md +8 -5
  95. package/skills/bugteam/reference/design-rationale.md +2 -2
  96. package/skills/bugteam/reference/github-pr-reviews.md +50 -57
  97. package/skills/bugteam/reference/obstacles/audit-assign-ids.md +13 -0
  98. package/skills/bugteam/reference/obstacles/audit-capture-excerpts.md +13 -0
  99. package/skills/bugteam/reference/obstacles/audit-walk-categories.md +13 -0
  100. package/skills/bugteam/reference/obstacles/audit-write-xml.md +13 -0
  101. package/skills/bugteam/reference/obstacles/fix-append-summary.md +13 -0
  102. package/skills/bugteam/reference/obstacles/fix-apply-fixes.md +13 -0
  103. package/skills/bugteam/reference/obstacles/fix-git-add-commit.md +13 -0
  104. package/skills/bugteam/reference/obstacles/fix-git-push.md +13 -0
  105. package/skills/bugteam/reference/obstacles/fix-post-reply.md +13 -0
  106. package/skills/bugteam/reference/obstacles/fix-publish-summary.md +13 -0
  107. package/skills/bugteam/reference/obstacles/fix-py-compile.md +13 -0
  108. package/skills/bugteam/reference/obstacles/fix-read-files.md +13 -0
  109. package/skills/bugteam/reference/obstacles/fix-resolve-thread.md +13 -0
  110. package/skills/bugteam/reference/obstacles/fix-test-suite.md +13 -0
  111. package/skills/bugteam/reference/obstacles/fix-violation-count.md +13 -0
  112. package/skills/bugteam/reference/obstacles/fix-write-xml.md +13 -0
  113. package/skills/bugteam/reference/team-setup.md +106 -9
  114. package/skills/bugteam/reference/teardown-publish-permissions.md +39 -8
  115. package/skills/bugteam/scripts/README.md +60 -0
  116. package/skills/bugteam/scripts/_claude_permissions_common.py +358 -0
  117. package/skills/bugteam/scripts/bugteam_code_rules_gate.py +976 -0
  118. package/skills/bugteam/scripts/bugteam_fix_hookspath.py +375 -0
  119. package/skills/bugteam/scripts/bugteam_preflight.py +294 -0
  120. package/skills/bugteam/scripts/config/bugteam_code_rules_gate_constants.py +25 -0
  121. package/skills/bugteam/scripts/config/bugteam_fix_hookspath_constants.py +26 -0
  122. package/skills/bugteam/scripts/config/bugteam_preflight_constants.py +35 -0
  123. package/skills/bugteam/scripts/config/claude_permissions_common_constants.py +20 -0
  124. package/skills/bugteam/scripts/config/probe_code_rules_enforcer_check_constants.py +12 -0
  125. package/skills/bugteam/scripts/config/windows_safe_rmtree_constants.py +7 -0
  126. package/skills/bugteam/scripts/grant_project_claude_permissions.py +175 -0
  127. package/skills/bugteam/scripts/probe_code_rules_enforcer_check.py +107 -0
  128. package/skills/bugteam/scripts/revoke_project_claude_permissions.py +220 -0
  129. package/skills/bugteam/scripts/test__claude_permissions_common.py +112 -0
  130. package/skills/bugteam/scripts/test_bugteam_code_rules_gate.py +400 -0
  131. package/skills/bugteam/scripts/test_bugteam_fix_hookspath.py +384 -0
  132. package/skills/bugteam/scripts/test_bugteam_preflight.py +268 -0
  133. package/skills/bugteam/scripts/test_claude_permissions_common.py +195 -0
  134. package/skills/bugteam/scripts/test_grant_project_claude_permissions.py +55 -0
  135. package/skills/bugteam/scripts/test_probe_code_rules_enforcer_check.py +76 -0
  136. package/skills/bugteam/scripts/test_revoke_project_claude_permissions.py +55 -0
  137. package/skills/bugteam/scripts/test_windows_safe_rmtree.py +108 -0
  138. package/skills/bugteam/scripts/windows_safe_rmtree.py +100 -0
  139. package/skills/bugteam/test_skill_additions.py +1 -11
  140. package/skills/code/SKILL.md +176 -0
  141. package/skills/doc-gist/SKILL.md +99 -0
  142. package/skills/doc-gist/references/examples/01-exploration-code-approaches.html +453 -0
  143. package/skills/doc-gist/references/examples/02-exploration-visual-designs.html +515 -0
  144. package/skills/doc-gist/references/examples/03-code-review-pr.html +638 -0
  145. package/skills/doc-gist/references/examples/04-code-understanding.html +491 -0
  146. package/skills/doc-gist/references/examples/05-design-system.html +629 -0
  147. package/skills/doc-gist/references/examples/06-component-variants.html +605 -0
  148. package/skills/doc-gist/references/examples/07-prototype-animation.html +455 -0
  149. package/skills/doc-gist/references/examples/08-prototype-interaction.html +396 -0
  150. package/skills/doc-gist/references/examples/09-slide-deck.html +592 -0
  151. package/skills/doc-gist/references/examples/10-svg-illustrations.html +492 -0
  152. package/skills/doc-gist/references/examples/11-status-report.html +528 -0
  153. package/skills/doc-gist/references/examples/12-incident-report.html +596 -0
  154. package/skills/doc-gist/references/examples/13-flowchart-diagram.html +395 -0
  155. package/skills/doc-gist/references/examples/14-research-feature-explainer.html +381 -0
  156. package/skills/doc-gist/references/examples/15-research-concept-explainer.html +368 -0
  157. package/skills/doc-gist/references/examples/16-implementation-plan.html +702 -0
  158. package/skills/doc-gist/references/examples/17-pr-writeup.html +595 -0
  159. package/skills/doc-gist/references/examples/18-editor-triage-board.html +573 -0
  160. package/skills/doc-gist/references/examples/19-editor-feature-flags.html +663 -0
  161. package/skills/doc-gist/references/examples/20-editor-prompt-tuner.html +722 -0
  162. package/skills/doc-gist/references/examples/README.md +5 -0
  163. package/skills/doc-gist/scripts/config/__init__.py +0 -0
  164. package/skills/doc-gist/scripts/config/gist_upload_constants.py +16 -0
  165. package/skills/doc-gist/scripts/gist_upload.py +177 -0
  166. package/skills/doc-gist/scripts/test_gist_upload.py +51 -0
  167. package/skills/findbugs/SKILL.md +68 -2
  168. package/skills/monitor-open-prs/SKILL.md +13 -32
  169. package/skills/monitor-open-prs/test_skill_contract.py +0 -11
  170. package/skills/pr-consistency-audit/SKILL.md +112 -0
  171. package/skills/pr-consistency-audit/reference/detection-rules.md +96 -0
  172. package/skills/pr-consistency-audit/reference/illustrations.md +78 -0
  173. package/skills/pr-converge/SKILL.md +227 -23
  174. package/skills/pr-converge/config/__init__.py +0 -0
  175. package/skills/pr-converge/config/constants.py +62 -0
  176. package/skills/pr-converge/reference/convergence-gates.md +138 -44
  177. package/skills/pr-converge/reference/examples.md +43 -11
  178. package/skills/pr-converge/reference/fix-protocol.md +6 -5
  179. package/skills/pr-converge/reference/ground-rules.md +5 -3
  180. package/skills/pr-converge/reference/multi-pr-orchestration.md +44 -19
  181. package/skills/pr-converge/reference/obstacles/fix-post-replies.md +13 -0
  182. package/skills/pr-converge/reference/obstacles/fix-publish-summary.md +13 -0
  183. package/skills/pr-converge/reference/obstacles/fix-push.md +13 -0
  184. package/skills/pr-converge/reference/obstacles/fix-read-filelines.md +13 -0
  185. package/skills/pr-converge/reference/obstacles/fix-reset-state.md +13 -0
  186. package/skills/pr-converge/reference/obstacles/fix-resolve-threads.md +13 -0
  187. package/skills/pr-converge/reference/obstacles/fix-spawn-clean-coder.md +13 -0
  188. package/skills/pr-converge/reference/obstacles/fix-stage-commit.md +13 -0
  189. package/skills/pr-converge/reference/obstacles/fix-trigger-bugbot.md +13 -0
  190. package/skills/pr-converge/reference/obstacles/fix-write-test.md +13 -0
  191. package/skills/pr-converge/reference/per-tick.md +90 -31
  192. package/skills/pr-converge/reference/state-schema.md +22 -1
  193. package/skills/pr-converge/reference/stop-conditions.md +9 -7
  194. package/skills/pr-converge/scripts/README.md +34 -46
  195. package/skills/pr-converge/scripts/check_bugbot_ci.py +174 -0
  196. package/skills/pr-converge/scripts/check_convergence.py +497 -0
  197. package/skills/pr-converge/scripts/check_pending_reviews.py +154 -0
  198. package/skills/pr-converge/scripts/config/pr_converge_constants.py +118 -0
  199. package/skills/pr-converge/scripts/fetch_copilot_reviews.py +134 -0
  200. package/skills/pr-converge/scripts/post_fix_reply.py +168 -0
  201. package/skills/pr-converge/workflows/schedule-wakeup-loop.md +5 -12
  202. package/skills/qbug/SKILL.md +132 -27
  203. package/skills/session-log/SKILL.md +216 -114
  204. package/skills/session-tidy/SKILL.md +1 -1
  205. package/skills/skill-builder/SKILL.md +138 -56
  206. package/skills/skill-builder/references/delegation-map.md +72 -113
  207. package/skills/skill-builder/references/progressive-disclosure.md +122 -0
  208. package/skills/skill-builder/references/self-audit-checklist.md +92 -0
  209. package/skills/skill-builder/references/skill-types.md +228 -0
  210. package/skills/skill-builder/references/thariq-x-post-skills.json +33 -0
  211. package/skills/skill-builder/templates/gap-analysis.md +15 -8
  212. package/skills/skill-builder/workflows/improve-skill.md +86 -57
  213. package/skills/skill-builder/workflows/new-skill.md +80 -168
  214. package/skills/skill-builder/workflows/polish-skill.md +78 -54
  215. package/skills/structure-prompt/SKILL.md +50 -0
  216. package/skills/structure-prompt/reference/adversarial-tuning.md +62 -0
  217. package/skills/structure-prompt/reference/block-classification.md +27 -0
  218. package/skills/structure-prompt/reference/canonical-case.md +48 -0
  219. package/skills/structure-prompt/reference/citation-depth.md +70 -0
  220. package/skills/structure-prompt/reference/cleanup.md +33 -0
  221. package/skills/structure-prompt/reference/constraints.md +33 -0
  222. package/skills/structure-prompt/reference/directives.md +37 -0
  223. package/skills/structure-prompt/reference/examples.md +72 -0
  224. package/skills/structure-prompt/reference/instantiation.md +51 -0
  225. package/skills/structure-prompt/reference/output-contract.md +72 -0
  226. package/skills/structure-prompt/reference/per-category.md +23 -0
  227. package/skills/structure-prompt/reference/persona.md +38 -0
  228. package/skills/structure-prompt/reference/research.md +33 -0
  229. package/skills/structure-prompt/reference/structure.md +28 -0
  230. package/agents/code-standards-agent.md +0 -93
  231. package/agents/groq-coder.md +0 -113
  232. package/agents/plan-executor.md +0 -226
  233. package/agents/project-docs-analyzer.md +0 -53
  234. package/agents/project-structure-organizer-agent.md +0 -72
  235. package/agents/skill-to-agent-converter.md +0 -370
  236. package/agents/skill-writer-agent.md +0 -470
  237. package/agents/user-docs-writer.md +0 -67
  238. package/agents/workflow-visual-documenter.md +0 -82
  239. package/commands/readability-review.md +0 -20
  240. package/hooks/mypy.ini +0 -2
  241. package/hooks/notification/attention_needed_notify.py +0 -71
  242. package/hooks/notification/claude_notification_handler.py +0 -67
  243. package/hooks/notification/notification_utils.py +0 -267
  244. package/hooks/notification/subagent_complete_notify.py +0 -381
  245. package/hooks/notification/test_attention_needed_notify.py +0 -47
  246. package/hooks/notification/test_claude_notification_handler.py +0 -54
  247. package/hooks/notification/test_notification_utils.py +0 -91
  248. package/hooks/notification/test_subagent_complete_notify.py +0 -79
  249. package/scripts/config/groq_bugteam_config.py +0 -230
  250. package/scripts/config/test_groq_bugteam_config.py +0 -83
  251. package/scripts/config/test_spec_implementer_prompt.py +0 -32
  252. package/scripts/groq_bugteam.README.md +0 -131
  253. package/scripts/groq_bugteam.py +0 -647
  254. package/scripts/groq_bugteam_dotenv.py +0 -40
  255. package/scripts/groq_bugteam_spec.py +0 -226
  256. package/scripts/test_groq_bugteam.py +0 -529
  257. package/scripts/test_groq_bugteam_apply_fix_from_spec.py +0 -426
  258. package/scripts/test_groq_bugteam_dotenv.py +0 -66
  259. package/scripts/test_groq_bugteam_spec.py +0 -338
  260. package/skills/bugteam/SKILL_EVALS.md +0 -309
  261. package/skills/dream/SKILL.md +0 -118
  262. package/skills/ingest/SKILL.md +0 -40
  263. package/skills/npm-creator/SKILL.md +0 -187
  264. package/skills/readability-review/SKILL.md +0 -127
  265. package/skills/resume-review/SKILL.md +0 -261
  266. package/skills/rule-audit/SKILL.md +0 -307
  267. package/skills/rule-creator/SKILL.md +0 -150
  268. package/skills/searching-obsidian-vault/SKILL.md +0 -131
  269. package/skills/skill-writer/REFERENCE.md +0 -284
  270. package/skills/skill-writer/SKILL.md +0 -222
  271. package/skills/tdd-team/SKILL.md +0 -128
@@ -1,28 +1,27 @@
1
- # Bugteam constraints
2
-
3
- ## Non-Negotiable
4
-
5
- - **Pre-flight is mandatory.** `preflight.py` must exit 0 before Step 0. If it fails for `core.hooksPath`, auto-remediate with `fix_hookspath.py`. All other failures require manual fixes.
6
- - **Looping against a fixed known count.** 10 audit loops hard cap. No exceptions. The cap is a safety value, set high enough to converge on most non-trivial PRs while preventing infinite loops.
7
- - **`loop_count` is the iteration counter.** It increments before each AUDIT in Step 3. A FIX without a preceding AUDIT does not advance `loop_count`. The `loop_count > 10` check runs before each AUDIT. After 10 AUDITs, the cycle exits regardless of remaining FIX rounds. Standards-fix passes before an audit do not advance `loop_count`.
8
- - **One review per loop, findings as child comments of that review.** Each loop posts a single pull-request review whose body is the loop header and whose `comments[]` are the anchored findings. Each loop's review stands alone one review created per loop, fully self-contained on the PR conversation.
9
- - **PR description rewrite on every exit.** Step 4.5 runs on `converged`, `cap reached`, and `stuck`. On `error`, the rewrite is best-effort; if it fails, surface the error in the final report and continue to revoke.
10
- - **Outcome XML, not JSON.** The AUDIT subagent writes findings to `.bugteam-pr<N>-loop<L>.outcomes.xml` and the FIX subagent writes fix outcomes to `.bugteam-pr<N>-loop<L>.fix-outcomes.xml`. The lead reads these files between actions. Separate paths prevent the FIX output from overwriting the AUDIT's findings file. XML chosen for parser robustness against multi-line, special-character, and quoted reason fields.
1
+ # Bugteam — invariants and design rationale
2
+
3
+ ## Constraints
4
+
5
+ - **Full A–K audit every loop, no exceptions.** PR size, "focused audit," "team overhead," "CODE_RULES already passed" not valid reasons. Empty `<findings/>` for any category is a valid result. The audit agent walks all A–K rubrics each loop.
6
+ - **One run per invocation, multi-PR supported.** All PRs in a single /bugteam invocation share one `run_temp_dir`. Per-PR identity lives in the subagent name prefix (`bugfind-pr<N>-loop<L>` / `bugfix-pr<N>-loop<L>`) and the `<run_temp_dir>/pr-<N>/` subfolder containing that PR's git worktree, diff patches, and outcome XML files.
7
+ - **Grant before any spawn, revoke before any return.** Step 0 grants project `.claude/**` permissions; Step 5 revokes. Both are mandatory. Revoke runs on every exit path including error, cap-reached, and stuck.
8
+ - **Fresh subagent per loop.** Both bugfind and bugfix are spawned new each loop. Reusing a subagent across loops accumulates context inside that subagent's windowdefeats clean-room.
9
+ - **One up-front confirmation = whole cycle.** The `/bugteam` invocation authorizes the entire cycle; every subsequent decision runs on that single authorization.
10
+ - **20-loop hard cap.** Counted as **AUDIT** completions (increment in Step 3). Standards-fix passes before an audit do not advance `loop_count`. Worst case includes extra clean-coder spawns for the code-rules gate.
11
+ - **Code rules gate before every AUDIT.** Run `${CLAUDE_SKILL_DIR}/scripts/bugteam_code_rules_gate.py` until exit **0** before spawning **bugfind**. Same `validate_content` logic as `hooks/blocking/code_rules_enforcer.py`.
12
+ - **Clean-room audits, every loop.** Each bugfind subagent's spawn prompt contains only the PR scope, audit rubric, and the current loop number. Prior loop history stays in the lead.
13
+ - **Targeted fixes.** Each fix subagent sees ONLY the most recent audit's findings. Prior loops are invisible to the fix subagent.
14
+ - **Fix subagent receives the latest audit as its input contract.** Each loop's fix run operates on the current audit's output and only that.
15
+ - **Lead owns the final PR description rewrite only** (Step 4.5), via the `pr-description-writer` agent.
11
16
 
12
17
  ## Why this design
13
18
 
14
- ### Why retry with fix why not just reject and move on
15
-
16
- Bugteam's purpose is to make real PRs better before they ship, not to just point out problems. A review that says "fix this bug" without giving the author&#60;subagent&#62; a chance to fix it in the same session would be a weaker intervention — the PR author still has to go back, figure out the fix, apply it, re-push, and re-trigger review. By bundling fix attempts into the same loop, bugteam reduces round-trips from N audits + N manual fix cycles to N audits + N automated fix attempts, with no human context-switching.
17
-
18
- ### Why 10 loops — why not unlimited
19
-
20
- A PR that needs more than 10 audit-fix rounds has deeper problems than bugteam can address. The 10-loop cap is a forcing function: after 10 rounds, escalate to `/findbugs` or human review rather than grinding on diminishing returns.
21
-
22
- ### Why outcome XML — why not JSON
19
+ The three sibling skills compose, but `/bugteam` solves a problem they cannot solve in sequence:
23
20
 
24
- JSON escapes `\n` inside `"reason": "could not address: some\nmulti-line\ntext"`, making the file hard to read and grep. XML preserves the raw text as element content, so `&#60;reason&#62;could not address: some&#10;multi-line&#10;text&#60;/reason&#62;` renders legibly in every markdown-capable viewer. The choice is ergonomic, not technical — both formats carry the same information.
21
+ - `/findbugs` audits once and stops.
22
+ - `/fixbugs` fixes the findings of one audit and stops.
23
+ - A human-driven `/findbugs` → `/fixbugs` → `/findbugs` → `/fixbugs` cycle works but requires the user to drive it.
25
24
 
26
- ### Why sibling auditor paths diverge (worktree vs temp)
25
+ `/bugteam` automates that cycle. The clean-room property is preserved by spawning a fresh audit agent each loop with no inherited context — every audit is independent of the prior loop's verdict. The 20-loop cap is the safety: pathological cases (audit agent oscillating, fix agent regressing) cannot run away.
27
26
 
28
- Only the -a validator writes to the worktree `.bugteam-pr&#60;N&#62;-loop&#60;L&#62;.outcomes.xml` path, which the lead reads. Sibling auditors (-b through -k) write to unique paths under `&#60;run_temp_dir&#62;` to avoid collisions. Without this split, parallel haiku auditors writing to the same path would clobber each other's output, and the lead consuming one path would see only whichever writer finished last.
27
+ The single up-front confirmation is the explicit trade — `/bugteam` is more autonomous than `/findbugs`+`/fixbugs` chained manually. The user accepts that autonomy by typing the command. Stop conditions and the loop log give the user full visibility on exit.
@@ -19,12 +19,12 @@ Claude: [resolves PR #42, runs loop]
19
19
 
20
20
  <example>
21
21
  User: `/bugteam`
22
- Claude: [runs 10 loops without convergence]
22
+ Claude: [runs 20 loops without convergence]
23
23
 
24
- `Loop 10 audit: 0P0 / 1P1 / 2P2`
24
+ `Loop 20 audit: 0P0 / 1P1 / 2P2`
25
25
 
26
26
  `/bugteam exit: cap reached`
27
- `Loops: 10`
27
+ `Loops: 20`
28
28
  `Remaining: 0P0 / 1P1 / 2P2 — run /findbugs for human triage`
29
29
  </example>
30
30
 
@@ -38,11 +38,11 @@ cd into `<worktree_path>` before any git or file operation.
38
38
  verified-clean -- re-audit with a concrete trace.
39
39
 
40
40
  Categories A–K (one-line summary; full rubric and sub-bucket decomposition
41
- for each is in `packages/claude-dev-env/audit-rubrics/category_rubrics/`;
41
+ for each is in `$HOME/.claude/audit-rubrics/category_rubrics/`;
42
42
  ready-to-send Variant C prompts — each with a PR/repo-independent
43
43
  generalized skeleton above a `---` separator and a worked example against
44
44
  an authentic PR below — are in
45
- `packages/claude-dev-env/audit-rubrics/prompts/`):
45
+ `$HOME/.claude/audit-rubrics/prompts/`):
46
46
 
47
47
  A. API contract verification (signatures, return types, async/await correctness)
48
48
  B. Selector / query / engine compatibility
@@ -69,11 +69,24 @@ cd into `<worktree_path>` before any git or file operation.
69
69
  </constraints>
70
70
 
71
71
  <comment_posting>
72
- Sibling auditors (-b through -k): run only steps 12 (audit, assign IDs,
73
- capture excerpt, validate anchors), then write outcome XML per <output_format> and return.
74
- Skip steps 3–5 sibling auditors do not post PR reviews.
72
+ Load all AK rubrics from
73
+ `$HOME/.claude/audit-rubrics/{category_rubrics,prompts}/`. The prompt file
74
+ is a template for output shape, not a straitjacket — reorganize when the
75
+ diff demands it. The diff supplies the findings; the rubric supplies the
76
+ sub-bucket decomposition and decision criteria. Both must be loaded.
75
77
 
76
- Validator (-a) and single-opus auditors: run all steps below.
78
+ Before starting, create one task per checklist item via TaskCreate. Use
79
+ TaskUpdate to mark each in_progress as you begin it and completed when
80
+ done.
81
+
82
+ <self_audit_checklist>
83
+ [ ] Walk all 11 categories (A–K), each with Shape A or Shape B
84
+ [ ] Assign finding IDs (loop<L>-<K>)
85
+ [ ] Capture excerpts, validate anchors, format finding bodies
86
+ [ ] Build findings JSON, invoke post_audit_thread.py, capture html_url
87
+ [ ] Harvest child-comment ids/urls AND thread_node_ids; populate loop_comment_index
88
+ [ ] Write outcome XML
89
+ </self_audit_checklist>
77
90
 
78
91
  1. Audit the diff against the 11 categories above. Buffer the findings
79
92
  in memory; all posting happens at step 4 once anchors are validated.
@@ -83,58 +96,132 @@ cd into `<worktree_path>` before any git or file operation.
83
96
  line. Populate the `<excerpt>` element in the outcome XML with it. Validate
84
97
  every finding's (file, line) against the captured diff. Split findings into two
85
98
  buckets: anchored (line is in the diff) and unanchored (line is not in the diff
86
- goes into the review body's "Findings without a diff anchor" section per
87
- Step 2.5). Format each finding body as:
88
-
89
- **[severity] one-line title**
90
- Category: <letter> (<category name>)
91
- <2-3 sentence description with concrete trace>
92
-
93
- _From /bugteam audit loop <L>._
94
-
95
- 4. Post ONE review via `pull_request_review_write(method="create",
96
- event="COMMENT", body=<review_body>, owner=<O>, repo=<R>,
97
- pullNumber=<N>, comments=[...])`. See Step 2.5 in SKILL.md for the full
98
- parameter shape. Harvest the parent review `html_url` from the response
99
- and the `comments[]` child entries (each with its own `id` and `html_url`).
100
- Match child entries to anchored findings in index order.
101
- 5. If the review POST fails, use `add_issue_comment(owner=<O>, repo=<R>,
102
- issueNumber=<N>, body=<full_text>)` as fallback.
103
- Body text is passed directly as string parameters to the MCP tool calls
104
- no temp files, no jq, no shell pipes.
99
+ surfaced in the calling skill's user-facing output rather than as inline
100
+ anchored comments).
101
+
102
+ Each anchored finding contributes one entry to the JSON payload built
103
+ in step 4. The payload schema is
104
+ `{path, line, side, severity, description, fix_summary}`; the audit
105
+ teammate populates `description` (the failure narrative) and
106
+ `fix_summary` (the `Fix:` / `Validation:` text) from the
107
+ finding's `failure_mode` per the mapping in step 4. The audit
108
+ teammate does NOT author the inline-comment body directly:
109
+ `post_audit_thread.py` renders every body from
110
+ `INLINE_COMMENT_BODY_TEMPLATE` (defined in
111
+ [`_shared/pr-loop/scripts/config/post_audit_thread_constants.py`](../../_shared/pr-loop/scripts/config/post_audit_thread_constants.py))
112
+ the template prepends `**[<severity>] <Skill> audit finding**`
113
+ and renders the suggested-fix block, so a teammate who hand-formats
114
+ a title or footer wastes the work.
115
+
116
+ 4. **Before posting, read the full review once as if you were the PR
117
+ author.** Ask: would I understand what to fix and why? Do any two
118
+ findings describe the same problem in different words — merge them. Does
119
+ any finding miss its mark — rewrite or drop it. Does the review feel
120
+ coherent as a whole? The review's job is to make the PR author want to
121
+ fix these bugs, not to demonstrate that the rubric ran. Rearrange,
122
+ merge, or rephrase anything that would confuse the author. Then
123
+ proceed with the mechanical script invocation below.
124
+
125
+ Post ONE review per loop via `post_audit_thread.py` per
126
+ [SKILL.md § Audit posting](SKILL.md#audit-posting). Serialize the
127
+ anchored findings to a JSON file shaped as a list of
128
+ `{path, line, side, severity, description, fix_summary}` entries.
129
+ Map each finding's `file` → `path`; split each finding's
130
+ `failure_mode` at the literal `Fix:` heading so the failure
131
+ narrative becomes `description` and the suffix beginning at `Fix:`
132
+ (including the trailing `Validation:` clause) becomes
133
+ `fix_summary`. When the agent omits the `Fix:` heading on a given
134
+ finding, write the full `failure_mode` text to BOTH `description`
135
+ and `fix_summary`. Set `side="RIGHT"` for every entry. Zero
136
+ anchored findings → `--state CLEAN` with the findings file holding
137
+ an empty array (`[]`); one or more → `--state DIRTY` with the full
138
+ list.
139
+
140
+ ```
141
+ python "${CLAUDE_SKILL_DIR}/../../_shared/pr-loop/scripts/post_audit_thread.py" \
142
+ --skill bugteam \
143
+ --owner <O> \
144
+ --repo <R> \
145
+ --pr-number <N> \
146
+ --commit <head_sha> \
147
+ --state <CLEAN|DIRTY> \
148
+ --findings-json <path>
149
+ ```
150
+
151
+ The script POSTs a single review with `event=APPROVE` on CLEAN
152
+ (the request event; GitHub stores it as `state=APPROVED`; empty
153
+ `comments[]`, body documents "no findings") or
154
+ `event=REQUEST_CHANGES` on DIRTY (one inline anchored comment per
155
+ finding; each becomes its own resolvable thread on the PR). It
156
+ handles retries internally (1s / 4s / 16s backoff across four
157
+ attempts). Exit codes:
158
+
159
+ - `0` — review posted; the new review's `html_url` is on stdout.
160
+ Capture this URL as the parent review URL.
161
+ - `1` — user input error (bad arguments, malformed findings JSON,
162
+ missing template).
163
+ - `2` — retry exhaustion. Hard blocker; halt and exit
164
+ `error: post_audit_thread retry exhausted` without retrying and
165
+ without falling back to a flat issue comment. There is no
166
+ fallback path — a hard blocker on the audit-posting path is a
167
+ halt condition.
168
+
169
+ Exit 0 emits the new review's `html_url` on stdout. Extract the
170
+ numeric review id from that URL's `#pullrequestreview-<id>` suffix
171
+ (the trailing URL fragment, the part after `#`). Then harvest child-comment URLs
172
+ **and PR review thread node ids** via
173
+ `pull_request_read(method="get_review_comments", owner=<O>,
174
+ repo=<R>, pullNumber=<N>)` filtered to that review id.
175
+ Match children to findings in the order they appear in the findings
176
+ JSON. Each `loop_comment_index[finding_id]` entry must carry both
177
+ `finding_comment_id` (numeric, used by `add_reply_to_pull_request_comment`)
178
+ and `thread_node_id` (e.g. `PRRT_kwDOxxx`, used by
179
+ `resolve_thread`) so the FIX teammate can reply and resolve.
180
+
181
+ The findings JSON is serialized to a temp file and passed by path; the
182
+ review-body content is read from `audit-reply-template.md` at runtime by
183
+ `post_audit_thread.py`, not passed in by the caller. No body-content
184
+ temp files, no jq, no shell pipes.
105
185
  </comment_posting>
106
186
 
107
187
  <output_format>
108
- For the (-a) validator: write the outcome XML below to .bugteam-pr<N>-loop<L>.outcomes.xml inside
109
- the PR's worktree directory (<worktree_path>). For sibling auditors (-b through -k): write to <run_temp_dir>/pr-<N>/loop-<L>-<letter>.outcomes.xml (absolute path passed in prompt). Sibling auditors do not post PR reviews; set review_url, finding_comment_id, and finding_comment_url to empty strings, and used_fallback to "false". Omit unanchored findings from sibling output — only the validator handles those. Return only that path on stdout. The schema:
188
+ Run `python scripts/write_audit_outcomes.py` to write the outcome XML.
189
+ The script owns the canonical path, filename, and format.
110
190
  </output_format>
111
191
  ```
112
192
 
113
- ## AUDIT outcome XML schema (bugfind writes this)
193
+ ## AUDIT outcome XML schema
194
+
195
+ `write_audit_outcomes.py` reads the findings JSON (list of finding dicts) and
196
+ emits this shape. Scalar finding fields become XML attributes on
197
+ `<finding>`; the body fields `title`, `excerpt`, and `description` become
198
+ child elements. The root carries `pr`, `loop`, and `review_url` as
199
+ attributes.
114
200
 
115
201
  ```xml
116
- <bugteam_audit loop="<L>" review_url="<url>">
117
- <finding
118
- finding_id="loop<L>-<K>"
119
- severity="P0|P1|P2"
120
- category="<letter>"
121
- file="<path>"
122
- line="<int>"
123
- finding_comment_id="<gh child comment id, or empty if unanchored/review-fallback>"
124
- finding_comment_url="<url of child comment, OR review_url if unanchored, OR fallback issue comment URL>"
125
- used_fallback="true|false"
126
- >
127
- <title>one-line title</title>
128
- <excerpt>verbatim source line or snippet from the file at the cited line</excerpt>
129
- <description>2-3 sentence description with concrete trace</description>
130
- </finding>
131
- <verified_clean>
132
- <category letter="<letter>" name="<name>" evidence="brief evidence + cleared conclusion"/>
133
- </verified_clean>
202
+ <bugteam_audit pr="<N>" loop="<L>" review_url="<url>">
203
+ <findings>
204
+ <finding
205
+ finding_id="loop<L>-<K>"
206
+ severity="P0|P1|P2"
207
+ category="<letter>"
208
+ file="<path>"
209
+ line="<int>"
210
+ finding_comment_id="<gh child comment id, or empty if unanchored>"
211
+ finding_comment_url="<url of child comment, OR review_url if unanchored>"
212
+ thread_node_id="<PR review thread node id (PRRT_kwDOxxx), or empty if unanchored>"
213
+ >
214
+ <title>one-line title</title>
215
+ <excerpt>verbatim source line or snippet from the file at the cited line</excerpt>
216
+ <description>2-3 sentence description with concrete trace</description>
217
+ </finding>
218
+ </findings>
134
219
  </bugteam_audit>
135
220
  ```
136
221
 
137
- After the teammate writes the XML and returns, the lead reads `.bugteam-pr<N>-loop<L>.outcomes.xml` from the PR's worktree directory with the `Read` tool, parses it, and populates `loop_comment_index` from `<finding>` elements.
222
+ Verified-clean evidence per A–K category is surfaced in the agent's text-mode
223
+ final report, not in this outcome XML (the writer accepts a flat findings list
224
+ only).
138
225
 
139
226
  ## FIX spawn-prompt XML (bugfix teammate)
140
227
 
@@ -159,14 +246,33 @@ cd into `<worktree_path>` before any git or file operation.
159
246
  file="<path>"
160
247
  line="<int>"
161
248
  category="<letter>"
162
- finding_comment_id="<id>"
249
+ finding_comment_id="<numeric comment id>"
163
250
  finding_comment_url="<url>"
251
+ thread_node_id="<PR review thread node id (PRRT_kwDOxxx)>"
164
252
  >
165
253
  <description>...</description>
166
254
  </bug>
167
255
  </bugs_to_fix>
168
256
 
169
257
  <execution>
258
+ Before starting, create one task per checklist item via TaskCreate. Use
259
+ TaskUpdate to mark each in_progress as you begin it and completed when
260
+ done.
261
+
262
+ <self_audit_checklist>
263
+ [ ] Read each referenced file
264
+ [ ] Apply all addressable fixes
265
+ [ ] py_compile on every modified file
266
+ [ ] Test suite passes
267
+ [ ] Post-fix violation count ≤ previous loop total (skip on L=1)
268
+ [ ] git add + commit
269
+ [ ] git push
270
+ [ ] Per finding: atomically post the unified-template reply, then call resolve_thread (no yield between them)
271
+ [ ] Publish fix summary via /doc-gist, capture URL
272
+ [ ] Append fix summary URL to parent review via add_reply_to_pull_request_comment
273
+ [ ] Write fix outcomes XML
274
+ </self_audit_checklist>
275
+
170
276
  1. Read each referenced file before editing.
171
277
  2. Apply each fix you can address.
172
278
  3. Run `python -m py_compile` (or language-equivalent) on every modified file.
@@ -178,28 +284,82 @@ cd into `<worktree_path>` before any git or file operation.
178
284
  (the commit was atomic; if it failed, no finding was applied), populate hook_output
179
285
  on each outcome, and return WITHOUT retrying. The lead will treat this loop as no-progress.
180
286
  7. git push with a plain fast-forward push (the default, no flag overrides).
181
- 8. For each bug, post a fix reply to its finding_comment_id via
182
- `add_reply_to_pull_request_comment(commentId=<id>, body=<reply_text>,
183
- owner=<O>, repo=<R>, pullNumber=<N>)`:
184
- - "Fixed in <commit_sha>" if the bug was addressed by your commit
185
- - "Could not address this loop: <one-line reason>" if you skipped or failed it
186
- - "Hook blocked the fix commit: <one-line summary>" if the commit was hook-blocked
187
- Body text is passed directly as string parameters -- no temp files, no jq, no shell pipes.
188
- 9. Write `.bugteam-pr<N>-loop<L>.fix-outcomes.xml` inside `<worktree_path>` (schema below) and return its path.
287
+ 8. For each finding, atomically (a) post the fix reply and
288
+ (b) call `resolve_thread`. The two calls form one logical action
289
+ per thread — do not yield to the lead between them, and do not
290
+ batch all replies before any resolves.
291
+
292
+ (a) Reply via
293
+ `add_reply_to_pull_request_comment(commentId=<finding_comment_id>,
294
+ body=<reply_body>, owner=<O>, repo=<R>, pullNumber=<N>)`. The
295
+ reply body uses the unified template at
296
+ [`../../_shared/pr-loop/audit-reply-template.md`](../../_shared/pr-loop/audit-reply-template.md).
297
+ Skeleton (identical across all paths):
298
+
299
+ ```
300
+ **Claude finished @<reviewer>'s task** —— <status_line>
301
+
302
+ ---
303
+ ### <action_heading> ✅
304
+
305
+ <1–2 paragraph plain-language explanation>
306
+
307
+ **`<file>:<line>`:**
308
+ - <bullet describing change or rationale>
309
+ - <bullet describing change or rationale>
310
+
311
+ <closing paragraph>
312
+ ```
313
+
314
+ Per-path `<status_line>` / `<action_heading>`:
315
+ - `status=fixed`: `Fixed in <short_sha>` (first 7 chars) /
316
+ finding-specific action verb (e.g.,
317
+ `Replaced Any with concrete type`).
318
+ - `status=could_not_address`: `Could not address this loop` /
319
+ one-line reason text.
320
+ - `status=hook_blocked`: `Hook blocked the fix commit` /
321
+ one-line hook summary.
322
+
323
+ Body text is passed directly as string parameters — no temp files,
324
+ no jq, no shell pipes.
325
+
326
+ (b) Immediately call
327
+ `pull_request_review_write(method="resolve_thread",
328
+ threadId=<thread_node_id>, owner=<O>, repo=<R>, pullNumber=<N>)`
329
+ for the same thread (this is the PR review thread node ID —
330
+ `PRRT_kwDOxxx` — distinct from the numeric comment ID; the AUDIT
331
+ teammate captures it at audit time when calling
332
+ `get_review_comments` and stores it on each
333
+ `loop_comment_index` entry alongside `finding_comment_id`, see
334
+ [reference/obstacles/fix-resolve-thread.md](reference/obstacles/fix-resolve-thread.md)).
335
+
336
+ 9. Publish the fix summary gist via `/doc-gist`. Pass the fix report
337
+ (what was fixed, what was skipped, what was left unaddressed) as the
338
+ gist body. Capture the returned gist URL.
339
+
340
+ 10. Append the fix summary gist URL (from step 9) to the parent review
341
+ via `add_reply_to_pull_request_comment(commentId=<id>, body=...,
342
+ owner=<O>, repo=<R>, pullNumber=<N>)`. The body carries the
343
+ gist URL plus a one-line summary of fixes applied this loop.
344
+
345
+ 11. Write `.bugteam-pr<N>-loop<L>.fix-outcomes.xml` inside
346
+ `<worktree_path>` (schema below) and return its path.
189
347
  </execution>
190
348
 
191
349
  <outcome_xml_schema>
192
- <bugteam_fix loop="<L>" commit_sha="<sha or empty if no commit>">
193
- <outcome
194
- finding_id="loop<L>-<K>"
195
- status="fixed|could_not_address|hook_blocked"
196
- commit_sha="<sha if fixed, empty otherwise>"
197
- reply_comment_id="<id of the reply posted>"
198
- reply_comment_url="<url of the reply posted>"
199
- >
200
- <reason>only present when status=could_not_address; one-line reason text</reason>
201
- <hook_output>only present when status=hook_blocked; verbatim stderr from the blocked hook</hook_output>
202
- </outcome>
350
+ <bugteam_fix pr="<N>" loop="<L>" commit_sha="<sha or empty if no commit>">
351
+ <outcomes>
352
+ <outcome
353
+ finding_id="loop<L>-<K>"
354
+ status="fixed|could_not_address|hook_blocked|unverified_fixed"
355
+ commit_sha="<sha if fixed, empty otherwise>"
356
+ reply_comment_id="<id of the reply posted>"
357
+ reply_comment_url="<url of the reply posted>"
358
+ >
359
+ <reason>only present when status=could_not_address; one-line reason text</reason>
360
+ <hook_output>only present when status=hook_blocked; verbatim stderr from the blocked hook</hook_output>
361
+ </outcome>
362
+ </outcomes>
203
363
  </bugteam_fix>
204
364
  </outcome_xml_schema>
205
365