claude-dev-env 4.2.0 → 7.0.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 (350) hide show
  1. package/.agents/agents/pr-description-writer.md +2 -2
  2. package/.agents/agents/test_agent_frontmatter.py +2 -2
  3. package/.agents/agents/test_pr_description_writer_style.py +1 -3
  4. package/.agents/skills/e-code-review/SKILL.md +12 -12
  5. package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
  6. package/.agents/skills/e-code-review/reference/fix.md +15 -17
  7. package/.agents/skills/e-code-review/reference/loop.md +35 -39
  8. package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
  9. package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
  10. package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
  11. package/.agents/skills/issue-tracker/SKILL.md +7 -0
  12. package/.agents/skills/pull-request/SKILL.md +216 -0
  13. package/.agents/skills/pull-request/reference/publication-tasks.md +18 -0
  14. package/.agents/skills/pull-request/scripts/github_pr_command_constants/__init__.py +1 -0
  15. package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/__init__.py +1 -0
  16. package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +69 -0
  17. package/.agents/skills/pull-request/scripts/pull_request.py +265 -0
  18. package/.agents/skills/pull-request/scripts/recover_legacy_author.py +251 -0
  19. package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +58 -0
  20. package/.agents/skills/pull-request/scripts/test_pull_request.py +396 -0
  21. package/.agents/skills/pull-request/scripts/test_recover_legacy_author.py +221 -0
  22. package/.agents/skills/skill-builder/SKILL.md +3 -196
  23. package/.agents/skills/test-runner/SKILL.md +69 -0
  24. package/.agents/skills/test-runner/scripts/preflight_checks.py +365 -0
  25. package/.agents/skills/test-runner/scripts/run_tests.py +316 -0
  26. package/.agents/skills/test-runner/scripts/test_preflight_checks.py +185 -0
  27. package/.agents/skills/test-runner/scripts/test_run_tests.py +281 -0
  28. package/.agents/skills/test-runner/scripts/test_runner_constants/__init__.py +1 -0
  29. package/.agents/skills/test-runner/scripts/test_runner_constants/config/__init__.py +1 -0
  30. package/.agents/skills/test-runner/scripts/test_runner_constants/config/constants.py +96 -0
  31. package/.agents/skills-archived/pr-loop-cloud-transport/reference/identity-and-hooks.md +1 -1
  32. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
  33. package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
  34. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
  35. package/bin/ever-shipped-skills.mjs +2 -0
  36. package/bin/ever-shipped-skills.test.mjs +8 -0
  37. package/bin/install.agents-home.test.mjs +15 -13
  38. package/bin/install.mjs +37 -1
  39. package/bin/install.policy-lint.test.mjs +78 -0
  40. package/bin/install.prune.test.mjs +149 -20
  41. package/bin/install.pstack-plugin.test.mjs +114 -0
  42. package/bin/install.test.mjs +61 -7
  43. package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
  44. package/hooks/advisory/pr_done_reminder.py +342 -0
  45. package/hooks/advisory/test_pr_done_reminder.py +249 -0
  46. package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
  47. package/hooks/blocking/code_rules_paired_test.py +22 -15
  48. package/hooks/blocking/pii_prevention_blocker.py +32 -51
  49. package/hooks/blocking/test_bash_post_call_dispatcher.py +55 -17
  50. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +1 -4
  51. package/hooks/blocking/test_code_rules_command_dispatch.py +2 -2
  52. package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
  53. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
  54. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
  55. package/hooks/blocking/test_pii_prevention_blocker.py +37 -89
  56. package/hooks/blocking/test_pre_tool_use_dispatcher.py +68 -133
  57. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
  58. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +18 -18
  59. package/hooks/gh_post_body_texts.py +195 -0
  60. package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
  61. package/hooks/git-hooks/pre_commit.py +52 -11
  62. package/hooks/git-hooks/test_installed_policy_lint.py +159 -0
  63. package/hooks/git-hooks/test_native_policy_commit.py +87 -0
  64. package/hooks/git-hooks/test_pre_commit.py +246 -0
  65. package/hooks/hooks.json +1 -16
  66. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -2
  67. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -8
  68. package/hooks/hooks_constants/gh_post_body_texts_constants.py +12 -0
  69. package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
  70. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -43
  71. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +17 -7
  72. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +0 -7
  73. package/hooks/hooks_constants/test_failure_recorder_constants.py +3 -3
  74. package/hooks/hooks_constants/test_gh_post_body_texts_constants.py +19 -0
  75. package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
  76. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +20 -32
  77. package/hooks/observability/test_failure_recorder.py +1 -1
  78. package/hooks/pyproject.toml +1 -1
  79. package/hooks/test_gh_post_body_texts.py +79 -0
  80. package/package.json +2 -2
  81. package/rules/durable-post-artifacts.md +32 -20
  82. package/rules/gh-cli-conventions.md +23 -13
  83. package/rules/git-workflow.md +21 -8
  84. package/scripts/check.ps1 +0 -1
  85. package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
  86. package/scripts/ci/installer-lifecycle.test.mjs +26 -0
  87. package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
  88. package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
  89. package/scripts/durable_post_lint.py +206 -0
  90. package/scripts/durable_post_lint_config/config/constants.py +96 -0
  91. package/scripts/durable_post_lint_config/config/test_constants.py +25 -0
  92. package/scripts/policy_lint/adapter_configuration.py +53 -12
  93. package/scripts/policy_lint/adapter_detectors.py +13 -6
  94. package/scripts/policy_lint/adapters.py +7 -4
  95. package/scripts/policy_lint/config/constants.py +5 -0
  96. package/scripts/policy_lint/engine.py +48 -4
  97. package/scripts/policy_lint/model.py +1 -0
  98. package/scripts/policy_lint/registry.py +1 -1
  99. package/scripts/policy_lint/selection.py +2 -1
  100. package/scripts/policy_lint/selection_git.py +2 -0
  101. package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
  102. package/scripts/repository_checks/config/constants.py +0 -5
  103. package/scripts/shared_tree_paths.py +32 -3
  104. package/scripts/test_durable_post_lint.py +332 -0
  105. package/scripts/test_shared_tree_paths.py +33 -0
  106. package/scripts/tests/test_adapter_configuration.py +54 -0
  107. package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
  108. package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
  109. package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
  110. package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
  111. package/scripts/tests/test_policy_lint_selection.py +25 -2
  112. package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
  113. package/scripts/tests/test_rules.py +3 -7
  114. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
  115. package/.agents/skills/_shared/pr-loop/AGENTS.md +0 -1
  116. package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
  117. package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
  118. package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
  119. package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
  120. package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
  121. package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
  122. package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
  123. package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
  124. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
  125. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
  126. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
  127. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
  128. package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
  129. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
  130. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
  131. package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
  132. package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
  133. package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
  134. package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
  135. package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
  136. package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
  137. package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
  138. package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
  139. package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
  140. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
  141. package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
  142. package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
  143. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
  144. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
  145. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
  146. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
  147. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
  148. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
  149. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
  150. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
  151. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
  152. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
  153. package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
  154. package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
  155. package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
  156. package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
  157. package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
  158. package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
  159. package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
  160. package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
  161. package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
  162. package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
  163. package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
  164. package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
  165. package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
  166. package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
  167. package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
  168. package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
  169. package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
  170. package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
  171. package/.agents/skills/autoconverge/AGENTS.md +0 -1
  172. package/.agents/skills/autoconverge/SKILL.md +0 -431
  173. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
  174. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
  175. package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
  176. package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
  177. package/.agents/skills/autoconverge/reference/convergence.md +0 -219
  178. package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
  179. package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
  180. package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
  181. package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
  182. package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
  183. package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
  184. package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
  185. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
  186. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
  187. package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
  188. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
  189. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
  190. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
  191. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
  192. package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
  193. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
  194. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
  195. package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
  196. package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
  197. package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
  198. package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
  199. package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
  200. package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
  201. package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
  202. package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
  203. package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
  204. package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
  205. package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
  206. package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
  207. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
  208. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
  209. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
  210. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
  211. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
  212. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
  213. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
  214. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
  215. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
  216. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
  217. package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
  218. package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
  219. package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
  220. package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
  221. package/.agents/skills/hitl/SKILL.md +0 -45
  222. package/.agents/skills/pr-cleanup/SKILL.md +0 -140
  223. package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
  224. package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
  225. package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
  226. package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
  227. package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
  228. package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
  229. package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
  230. package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
  231. package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
  232. package/.agents/skills/pr-refinement/SKILL.md +0 -31
  233. package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
  234. package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
  235. package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
  236. package/.agents/skills/pr-small-cl/SKILL.md +0 -52
  237. package/.agents/skills/pr-title-description/SKILL.md +0 -96
  238. package/.agents/skills/prototype/SKILL.md +0 -85
  239. package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
  240. package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
  241. package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
  242. package/.agents/skills/prototype/scripts/conftest.py +0 -15
  243. package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
  244. package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
  245. package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
  246. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  247. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
  248. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
  249. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
  250. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
  251. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
  252. package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
  253. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
  254. package/.agents/skills/prototype/workflows/promotion.md +0 -25
  255. package/.agents/skills/prototype/workflows/sandbox.md +0 -35
  256. package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
  257. package/.agents/skills/rebase/AGENTS.md +0 -1
  258. package/.agents/skills/rebase/SKILL.md +0 -178
  259. package/.agents/skills/review-router/SKILL.md +0 -51
  260. package/.agents/skills/review-router/reference/route-policy.json +0 -7
  261. package/.agents/skills/review-router/reference/task-seeds.md +0 -1
  262. package/.agents/skills/review-router/scripts/conftest.py +0 -4
  263. package/.agents/skills/review-router/scripts/review_router.py +0 -50
  264. package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
  265. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
  266. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  267. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
  268. package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
  269. package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
  270. package/.agents/skills/review-tier/SKILL.md +0 -56
  271. package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
  272. package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
  273. package/.agents/skills/review-tier/scripts/conftest.py +0 -4
  274. package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
  275. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
  276. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  277. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
  278. package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
  279. package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
  280. package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
  281. package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
  282. package/.agents/skills/session-log/AGENTS.md +0 -1
  283. package/.agents/skills/session-log/SKILL.md +0 -170
  284. package/.agents/skills/session-log/templates/frontmatter.md +0 -40
  285. package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
  286. package/.agents/skills/session-tidy/AGENTS.md +0 -1
  287. package/.agents/skills/session-tidy/SKILL.md +0 -191
  288. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
  289. package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
  290. package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
  291. package/.agents/skills/skill-builder/references/description-field.md +0 -111
  292. package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
  293. package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
  294. package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
  295. package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
  296. package/.agents/skills/skill-builder/references/skill-types.md +0 -232
  297. package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
  298. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
  299. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
  300. package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
  301. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
  302. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
  303. package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
  304. package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
  305. package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
  306. package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
  307. package/.agents/skills/update/.claude/CLAUDE.md +0 -1
  308. package/.agents/skills/update/AGENTS.md +0 -1
  309. package/.agents/skills/update/SKILL.md +0 -190
  310. package/_shared/pr-loop/AGENTS.md +0 -1
  311. package/_shared/pr-loop/CLAUDE.md +0 -1
  312. package/_shared/pr-loop/audit-contract.md +0 -183
  313. package/_shared/pr-loop/audit-reply-template.md +0 -151
  314. package/_shared/pr-loop/code-rules-gate.md +0 -65
  315. package/_shared/pr-loop/fix-protocol.md +0 -60
  316. package/_shared/pr-loop/gh-payloads.md +0 -75
  317. package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
  318. package/_shared/pr-loop/precatch-rubric.md +0 -66
  319. package/_shared/pr-loop/preflight-proposal.md +0 -56
  320. package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
  321. package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
  322. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
  323. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
  324. package/_shared/pr-loop/state-schema.md +0 -45
  325. package/_shared/pr-loop/worker-spawn.md +0 -189
  326. package/hooks/_gh_pr_author_swap_utils.py +0 -1225
  327. package/hooks/blocking/conventional_pr_title_gate.py +0 -443
  328. package/hooks/blocking/gh_body_arg_blocker.py +0 -176
  329. package/hooks/blocking/gh_pr_author_enforcer.py +0 -487
  330. package/hooks/blocking/gh_pr_author_restore.py +0 -105
  331. package/hooks/blocking/pr_description_writer_gate.py +0 -256
  332. package/hooks/blocking/test_conventional_pr_title_gate.py +0 -640
  333. package/hooks/blocking/test_gh_body_arg_blocker.py +0 -441
  334. package/hooks/blocking/test_gh_pr_author_enforcer.py +0 -1166
  335. package/hooks/blocking/test_gh_pr_author_restore.py +0 -513
  336. package/hooks/blocking/test_gh_pr_author_swap_utils.py +0 -910
  337. package/hooks/blocking/test_pr_description_writer_gate.py +0 -234
  338. package/hooks/blocking/test_preflight_check.py +0 -343
  339. package/hooks/blocking/test_test_preflight_check.py +0 -80
  340. package/hooks/blocking/test_volatile_path_in_post_blocker.py +0 -322
  341. package/hooks/blocking/volatile_path_in_post_blocker.py +0 -461
  342. package/hooks/hooks_constants/conventional_pr_title_gate_constants.py +0 -58
  343. package/hooks/hooks_constants/gh_pr_author_swap_constants.py +0 -76
  344. package/hooks/hooks_constants/pr_description_writer_gate_constants.py +0 -73
  345. package/hooks/hooks_constants/volatile_path_in_post_blocker_constants.py +0 -55
  346. package/hooks/observability/pr_description_writer_spawn_tracker.py +0 -113
  347. package/hooks/observability/test_pr_description_writer_spawn_tracker.py +0 -150
  348. package/hooks/session/gh_pr_author_session_cleanup.py +0 -175
  349. package/hooks/session/test_gh_pr_author_session_cleanup.py +0 -576
  350. package/hooks/test__gh_pr_author_swap_utils.py +0 -333
@@ -1,201 +0,0 @@
1
- """Tests for write_handoff: the durable per-run handoff writer."""
2
-
3
- from __future__ import annotations
4
-
5
- import importlib.util
6
- import json
7
- import sys
8
- from pathlib import Path
9
- from types import ModuleType
10
-
11
- import pytest
12
-
13
- _SCRIPTS_DIR = Path(__file__).resolve().parent
14
- if str(_SCRIPTS_DIR) not in sys.path:
15
- sys.path.insert(0, str(_SCRIPTS_DIR))
16
-
17
-
18
- def _load_write_handoff_module() -> ModuleType:
19
- module_path = _SCRIPTS_DIR / "write_handoff.py"
20
- spec = importlib.util.spec_from_file_location("write_handoff", module_path)
21
- assert spec is not None
22
- assert spec.loader is not None
23
- module = importlib.util.module_from_spec(spec)
24
- spec.loader.exec_module(module)
25
- return module
26
-
27
-
28
- write_handoff = _load_write_handoff_module()
29
-
30
-
31
- _FROZEN_TIMESTAMP = "2026-07-03T12:00:00+00:00"
32
-
33
-
34
- def _point_base_dir_at(monkeypatch: pytest.MonkeyPatch, base: Path) -> None:
35
- monkeypatch.setattr(write_handoff, "_handoff_base_dir", lambda: base)
36
- monkeypatch.setattr(write_handoff, "_now_iso", lambda: _FROZEN_TIMESTAMP)
37
-
38
-
39
- def test_resolve_handoff_dir_joins_run_name_under_base(
40
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
41
- ) -> None:
42
- """resolve_handoff_dir places the run's directory under the durable base."""
43
- _point_base_dir_at(monkeypatch, tmp_path)
44
- resolved = write_handoff.resolve_handoff_dir("bugteam-pr-4")
45
- assert resolved == tmp_path / "bugteam-pr-4"
46
-
47
-
48
- def test_handoff_base_dir_lives_under_home_runtime_pr_loop(
49
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
50
- ) -> None:
51
- """The durable base sits under the user home, not the OS temp directory."""
52
- monkeypatch.setenv("USERPROFILE", str(tmp_path))
53
- monkeypatch.setenv("HOME", str(tmp_path))
54
- base = write_handoff._handoff_base_dir()
55
- assert base == tmp_path / ".claude" / "runtime" / "pr-loop"
56
-
57
-
58
- def test_write_handoff_records_resume_command_and_phase(
59
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
60
- ) -> None:
61
- """write_handoff writes handoff.json and HANDOFF.md carrying the resume
62
- command, phase, run id, completed steps, and a timestamp."""
63
- _point_base_dir_at(monkeypatch, tmp_path)
64
- handoff_dir = write_handoff.write_handoff(
65
- pr_number=4,
66
- head_ref="feat/pr-loop-durable-handoff",
67
- phase="tick",
68
- resume_command="claude --resume /pr-converge",
69
- run_id="wf_abc123",
70
- all_completed_steps=["preflight", "audit"],
71
- note="Copilot wait-gate still open.",
72
- )
73
- assert handoff_dir == tmp_path / "bugteam-pr-4"
74
-
75
- payload = json.loads((handoff_dir / "handoff.json").read_text(encoding="utf-8"))
76
- assert payload["resume_command"] == "claude --resume /pr-converge"
77
- assert payload["phase"] == "tick"
78
- assert payload["run_id"] == "wf_abc123"
79
- assert payload["completed_steps"] == ["preflight", "audit"]
80
- assert payload["timestamp"] == _FROZEN_TIMESTAMP
81
-
82
- markdown = (handoff_dir / "HANDOFF.md").read_text(encoding="utf-8")
83
- assert "claude --resume /pr-converge" in markdown
84
- assert "preflight" in markdown
85
- assert "Copilot wait-gate still open." in markdown
86
-
87
-
88
- def test_write_handoff_copies_state_file_when_given(
89
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
90
- ) -> None:
91
- """A supplied --state-file is copied to state-copy.json and the copy path is
92
- recorded in handoff.json."""
93
- _point_base_dir_at(monkeypatch, tmp_path)
94
- source_state = tmp_path / "loop-state.json"
95
- source_state.write_text('{"loop_count": 3}', encoding="utf-8")
96
-
97
- handoff_dir = write_handoff.write_handoff(
98
- pr_number=4,
99
- head_ref="feat/branch",
100
- phase="teardown",
101
- resume_command="claude --resume /autoconverge",
102
- state_file=source_state,
103
- )
104
-
105
- state_copy = handoff_dir / "state-copy.json"
106
- assert json.loads(state_copy.read_text(encoding="utf-8")) == {"loop_count": 3}
107
- payload = json.loads((handoff_dir / "handoff.json").read_text(encoding="utf-8"))
108
- assert payload["state_file"] == state_copy.as_posix()
109
-
110
-
111
- def test_write_handoff_omits_state_copy_when_absent(
112
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
113
- ) -> None:
114
- """With no --state-file, no state-copy.json is written and state_file is null."""
115
- _point_base_dir_at(monkeypatch, tmp_path)
116
- handoff_dir = write_handoff.write_handoff(
117
- pr_number=4,
118
- head_ref="feat/branch",
119
- phase="tick",
120
- resume_command="claude --resume /pr-converge",
121
- )
122
- assert not (handoff_dir / "state-copy.json").exists()
123
- payload = json.loads((handoff_dir / "handoff.json").read_text(encoding="utf-8"))
124
- assert payload["state_file"] is None
125
-
126
-
127
- def test_parse_arguments_reads_completed_steps_value() -> None:
128
- """The CLI captures the raw comma-separated --completed-steps value."""
129
- arguments = write_handoff.parse_arguments(
130
- [
131
- "--pr-number",
132
- "4",
133
- "--head-ref",
134
- "feat/branch",
135
- "--phase",
136
- "tick",
137
- "--resume-command",
138
- "claude --resume /pr-converge",
139
- "--completed-steps",
140
- "preflight,audit,fix",
141
- ]
142
- )
143
- assert arguments.completed_steps == "preflight,audit,fix"
144
-
145
-
146
- def test_main_writes_handoff_and_prints_dir(
147
- tmp_path: Path,
148
- monkeypatch: pytest.MonkeyPatch,
149
- capsys: pytest.CaptureFixture[str],
150
- ) -> None:
151
- """main writes the handoff files and prints the durable directory path."""
152
- _point_base_dir_at(monkeypatch, tmp_path)
153
- exit_code = write_handoff.main(
154
- [
155
- "--pr-number",
156
- "4",
157
- "--head-ref",
158
- "feat/branch",
159
- "--phase",
160
- "tick",
161
- "--resume-command",
162
- "claude --resume /pr-converge",
163
- "--completed-steps",
164
- "preflight,audit",
165
- ]
166
- )
167
- assert exit_code == 0
168
- printed = capsys.readouterr().out.strip()
169
- assert "\\" not in printed
170
- assert printed.endswith("bugteam-pr-4")
171
- payload = json.loads(
172
- (tmp_path / "bugteam-pr-4" / "handoff.json").read_text(encoding="utf-8")
173
- )
174
- assert payload["completed_steps"] == ["preflight", "audit"]
175
-
176
-
177
- def test_main_returns_one_on_non_utf8_state_file(
178
- tmp_path: Path,
179
- monkeypatch: pytest.MonkeyPatch,
180
- capsys: pytest.CaptureFixture[str],
181
- ) -> None:
182
- """main exits 1 rather than crashing when --state-file holds non-UTF-8 bytes."""
183
- _point_base_dir_at(monkeypatch, tmp_path)
184
- bad_state = tmp_path / "loop-state.json"
185
- bad_state.write_bytes(b"\xff\xfe not valid utf-8")
186
- exit_code = write_handoff.main(
187
- [
188
- "--pr-number",
189
- "4",
190
- "--head-ref",
191
- "feat/branch",
192
- "--phase",
193
- "teardown",
194
- "--resume-command",
195
- "claude --resume /autoconverge",
196
- "--state-file",
197
- str(bad_state),
198
- ]
199
- )
200
- assert exit_code == 1
201
- assert "write_handoff failed" in capsys.readouterr().err
@@ -1,182 +0,0 @@
1
- """Validate Shape A/B contract and write <bugteam_audit> XML at the canonical path.
2
-
3
- Usage:
4
- python scripts/write_audit_outcomes.py --pr-number 422 --loop 3 --review-url <URL> --findings-json <PATH> --worktree-path <PATH>
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import argparse
10
- import json
11
- import sys
12
- from pathlib import Path
13
- from xml.etree.ElementTree import Element, SubElement
14
-
15
- _self_dir = Path(__file__).resolve().parent
16
- if str(_self_dir) not in sys.path:
17
- sys.path.insert(0, str(_self_dir))
18
-
19
- from _cli_utils import require_file
20
- from _path_resolver import outcome_xml_path
21
- from _xml_utils import emit_pretty_xml
22
- from skills_pr_loop_constants.path_resolver_constants import ALL_FINDING_BODY_ELEMENT_KEYS
23
-
24
-
25
- def build_audit_xml(
26
- *,
27
- pr_number: int,
28
- loop: int,
29
- review_url: str,
30
- findings_json_path: Path,
31
- ) -> Element:
32
- """Build the <bugteam_audit> XML element from findings data.
33
-
34
- Args:
35
- pr_number: Pull request number.
36
- loop: Loop iteration number.
37
- review_url: URL of the GitHub review.
38
- findings_json_path: Path to the findings JSON file.
39
-
40
- Returns:
41
- Root <bugteam_audit> element.
42
-
43
- Raises:
44
- SystemExit: When findings-json is not a JSON array of objects.
45
- """
46
- findings_data = json.loads(findings_json_path.read_text(encoding="utf-8"))
47
- if not isinstance(findings_data, list):
48
- print("findings-json must contain a JSON array", file=sys.stderr)
49
- raise SystemExit(1)
50
- for each_index, each_finding in enumerate(findings_data):
51
- if not isinstance(each_finding, dict):
52
- print(
53
- f"findings-json[{each_index}]: each entry must be a JSON object",
54
- file=sys.stderr,
55
- )
56
- raise SystemExit(1)
57
- root = Element("bugteam_audit", {
58
- "pr": str(pr_number),
59
- "loop": str(loop),
60
- "review_url": review_url,
61
- })
62
-
63
- findings_elem = SubElement(root, "findings")
64
- _populate_findings(findings_elem, findings_data)
65
- return root
66
-
67
-
68
- def _populate_findings(parent: Element, findings_data: list[dict[str, object]]) -> None:
69
- """Populate <finding> elements from a validated list of finding dicts.
70
-
71
- Scalar finding fields become XML attributes on `<finding>`; the
72
- body fields named in `ALL_FINDING_BODY_ELEMENT_KEYS` (defined in
73
- `packages/claude-dev-env/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py`
74
- and currently `("title", "excerpt", "description")`) become child elements.
75
- Nested dicts or lists in scalar slots are flattened to string form
76
- so attribute serialization stays well-defined.
77
-
78
- Args:
79
- parent: Parent XML element (typically `<findings>`).
80
- findings_data: Validated list of finding dicts (caller must have
81
- confirmed each entry is a dict via the build_audit_xml gate).
82
- """
83
- all_finding_body_element_keys = ALL_FINDING_BODY_ELEMENT_KEYS
84
- for each_finding in findings_data:
85
- finding_elem = SubElement(parent, "finding")
86
- for each_key, each_field_detail in each_finding.items():
87
- field_text = (
88
- str(each_field_detail) if each_field_detail is not None else ""
89
- )
90
- if each_key in all_finding_body_element_keys:
91
- child = SubElement(finding_elem, each_key)
92
- child.text = field_text
93
- else:
94
- finding_elem.set(each_key, field_text)
95
-
96
-
97
- def write_audit_xml(
98
- *,
99
- pr_number: int,
100
- loop: int,
101
- review_url: str,
102
- findings_json_path: Path,
103
- worktree_path: Path,
104
- ) -> Path:
105
- """Write the <bugteam_audit> XML to the canonical outcome path.
106
-
107
- Args:
108
- pr_number: Pull request number.
109
- loop: Loop iteration number.
110
- review_url: URL of the GitHub review.
111
- findings_json_path: Path to the findings JSON file.
112
- worktree_path: Path to the git worktree.
113
-
114
- Returns:
115
- Path to the written XML file.
116
- """
117
- root = build_audit_xml(
118
- pr_number=pr_number,
119
- loop=loop,
120
- review_url=review_url,
121
- findings_json_path=findings_json_path,
122
- )
123
- xml_string = emit_pretty_xml(root)
124
-
125
- output_path = outcome_xml_path(worktree_path, pr_number, loop)
126
- output_path.write_text(xml_string, encoding="utf-8")
127
- return output_path
128
-
129
-
130
- def parse_arguments(all_argv: list[str]) -> argparse.Namespace:
131
- """Parse command-line arguments.
132
-
133
- Args:
134
- all_argv: Command-line argument list.
135
-
136
- Returns:
137
- Parsed namespace with pr_number, loop, review_url, findings_json, and worktree_path.
138
- """
139
- parser = argparse.ArgumentParser(description=__doc__)
140
- parser.add_argument("--pr-number", type=int, required=True)
141
- parser.add_argument("--loop", type=int, required=True)
142
- parser.add_argument("--review-url", required=True)
143
- parser.add_argument("--findings-json", type=Path, required=True)
144
- parser.add_argument("--worktree-path", type=Path, required=True)
145
- return parser.parse_args(all_argv)
146
-
147
-
148
- def main(all_arguments: list[str]) -> int:
149
- """Entry point: write <bugteam_audit> XML at the canonical path.
150
-
151
- Args:
152
- all_arguments: Command-line arguments.
153
-
154
- Returns:
155
- 0 on success, 1 on validation or write failure.
156
- """
157
- arguments = parse_arguments(all_arguments)
158
- findings_path = getattr(arguments, "findings_json")
159
-
160
- early_exit = require_file(findings_path, "findings-json")
161
- if early_exit is not None:
162
- return early_exit
163
-
164
- try:
165
- output_path = write_audit_xml(
166
- pr_number=getattr(arguments, "pr_number"),
167
- loop=arguments.loop,
168
- review_url=getattr(arguments, "review_url"),
169
- findings_json_path=findings_path,
170
- worktree_path=getattr(arguments, "worktree_path"),
171
- )
172
- except SystemExit:
173
- return 1
174
- except (json.JSONDecodeError, OSError) as exc:
175
- print(f"write_audit_xml failed: {exc}", file=sys.stderr)
176
- return 1
177
- print(output_path)
178
- return 0
179
-
180
-
181
- if __name__ == "__main__":
182
- raise SystemExit(main(sys.argv[1:]))
@@ -1,206 +0,0 @@
1
- """Validate status enum values and write <bugteam_fix> XML at the canonical path.
2
-
3
- Status enum (canonical source: `ALL_VALID_FIX_STATUSES` in
4
- `packages/claude-dev-env/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py`):
5
- fixed | could_not_address | hook_blocked | unverified_fixed.
6
-
7
- Each outcome's scalar fields become XML attributes on `<outcome>`; the
8
- body fields named in `ALL_FIX_OUTCOME_BODY_ELEMENT_KEYS` (currently
9
- `("reason", "hook_output")`) become child elements.
10
-
11
- Usage:
12
- python scripts/write_fix_outcomes.py --pr-number 422 --loop 3 --commit-sha abc1234 --outcomes-json <PATH> --worktree-path <PATH>
13
- """
14
-
15
- from __future__ import annotations
16
-
17
- import argparse
18
- import json
19
- import sys
20
- from pathlib import Path
21
- from xml.etree.ElementTree import Element, SubElement
22
-
23
- _self_dir = Path(__file__).resolve().parent
24
- if str(_self_dir) not in sys.path:
25
- sys.path.insert(0, str(_self_dir))
26
-
27
- from _cli_utils import require_file
28
- from _path_resolver import fix_outcome_xml_path
29
- from _xml_utils import emit_pretty_xml
30
- from skills_pr_loop_constants.path_resolver_constants import (
31
- ALL_FIX_OUTCOME_BODY_ELEMENT_KEYS,
32
- ALL_VALID_FIX_STATUSES,
33
- )
34
-
35
-
36
- def validate_fix_statuses(all_outcomes: list[dict[str, object]]) -> list[str]:
37
- """Validate that every outcome entry has a recognized status.
38
-
39
- Args:
40
- all_outcomes: List of outcome dicts, each expected to have a 'status' key.
41
-
42
- Returns:
43
- List of validation error messages (empty when valid).
44
- """
45
- valid_statuses = ALL_VALID_FIX_STATUSES
46
- errors: list[str] = []
47
- for each_index, each_outcome in enumerate(all_outcomes):
48
- status = each_outcome.get("status")
49
- if not isinstance(status, str):
50
- errors.append(f"outcome[{each_index}]: status missing or not a string")
51
- continue
52
- if status not in valid_statuses:
53
- errors.append(
54
- f"outcome[{each_index}]: invalid status '{status}' "
55
- f"(expected one of {sorted(valid_statuses)})"
56
- )
57
- return errors
58
-
59
-
60
- def build_fix_xml(
61
- *,
62
- pr_number: int,
63
- loop: int,
64
- commit_sha: str,
65
- outcomes_json_path: Path,
66
- ) -> Element:
67
- """Build the <bugteam_fix> XML element from outcomes data.
68
-
69
- Args:
70
- pr_number: Pull request number.
71
- loop: Loop iteration number.
72
- commit_sha: Commit SHA of the fix commit.
73
- outcomes_json_path: Path to the outcomes JSON file.
74
-
75
- Returns:
76
- Root <bugteam_fix> element.
77
-
78
- Raises:
79
- SystemExit: When outcomes-json is not a JSON array of objects, or
80
- when status validation fails.
81
- """
82
- outcomes_data = json.loads(outcomes_json_path.read_text(encoding="utf-8"))
83
- if not isinstance(outcomes_data, list):
84
- print("outcomes-json must contain a JSON array", file=sys.stderr)
85
- raise SystemExit(1)
86
- for each_index, each_entry in enumerate(outcomes_data):
87
- if not isinstance(each_entry, dict):
88
- print(
89
- f"outcomes-json[{each_index}]: each entry must be a JSON object",
90
- file=sys.stderr,
91
- )
92
- raise SystemExit(1)
93
- errors = validate_fix_statuses(outcomes_data)
94
- if errors:
95
- for each_error in errors:
96
- print(each_error, file=sys.stderr)
97
- raise SystemExit(1)
98
-
99
- root = Element("bugteam_fix", {
100
- "pr": str(pr_number),
101
- "loop": str(loop),
102
- "commit_sha": commit_sha,
103
- })
104
-
105
- all_fix_outcome_body_element_keys = ALL_FIX_OUTCOME_BODY_ELEMENT_KEYS
106
- outcomes_elem = SubElement(root, "outcomes")
107
- for each_outcome in outcomes_data:
108
- outcome_elem = SubElement(outcomes_elem, "outcome")
109
- for each_key, each_field_detail in each_outcome.items():
110
- field_text = (
111
- str(each_field_detail) if each_field_detail is not None else ""
112
- )
113
- if each_key in all_fix_outcome_body_element_keys:
114
- child = SubElement(outcome_elem, each_key)
115
- child.text = field_text
116
- else:
117
- outcome_elem.set(each_key, field_text)
118
- return root
119
-
120
-
121
- def write_fix_xml(
122
- *,
123
- pr_number: int,
124
- loop: int,
125
- commit_sha: str,
126
- outcomes_json_path: Path,
127
- worktree_path: Path,
128
- ) -> Path:
129
- """Write the <bugteam_fix> XML to the canonical outcome path.
130
-
131
- Args:
132
- pr_number: Pull request number.
133
- loop: Loop iteration number.
134
- commit_sha: Commit SHA of the fix commit.
135
- outcomes_json_path: Path to the outcomes JSON file.
136
- worktree_path: Path to the git worktree.
137
-
138
- Returns:
139
- Path to the written XML file.
140
- """
141
- root = build_fix_xml(
142
- pr_number=pr_number,
143
- loop=loop,
144
- commit_sha=commit_sha,
145
- outcomes_json_path=outcomes_json_path,
146
- )
147
- xml_string = emit_pretty_xml(root)
148
-
149
- output_path = fix_outcome_xml_path(worktree_path, pr_number, loop)
150
- output_path.write_text(xml_string, encoding="utf-8")
151
- return output_path
152
-
153
-
154
- def parse_arguments(all_argv: list[str]) -> argparse.Namespace:
155
- """Parse command-line arguments.
156
-
157
- Args:
158
- all_argv: Command-line argument list.
159
-
160
- Returns:
161
- Parsed namespace with pr_number, loop, commit_sha, outcomes_json, and worktree_path.
162
- """
163
- parser = argparse.ArgumentParser(description=__doc__)
164
- parser.add_argument("--pr-number", type=int, required=True)
165
- parser.add_argument("--loop", type=int, required=True)
166
- parser.add_argument("--commit-sha", required=True)
167
- parser.add_argument("--outcomes-json", type=Path, required=True)
168
- parser.add_argument("--worktree-path", type=Path, required=True)
169
- return parser.parse_args(all_argv)
170
-
171
-
172
- def main(all_arguments: list[str]) -> int:
173
- """Entry point: write <bugteam_fix> XML at the canonical path.
174
-
175
- Args:
176
- all_arguments: Command-line arguments.
177
-
178
- Returns:
179
- 0 on success, 1 on validation or write failure.
180
- """
181
- arguments = parse_arguments(all_arguments)
182
- outcomes_path = getattr(arguments, "outcomes_json")
183
-
184
- early_exit = require_file(outcomes_path, "outcomes-json")
185
- if early_exit is not None:
186
- return early_exit
187
-
188
- try:
189
- output_path = write_fix_xml(
190
- pr_number=getattr(arguments, "pr_number"),
191
- loop=arguments.loop,
192
- commit_sha=getattr(arguments, "commit_sha"),
193
- outcomes_json_path=outcomes_path,
194
- worktree_path=getattr(arguments, "worktree_path"),
195
- )
196
- except SystemExit:
197
- return 1
198
- except (json.JSONDecodeError, OSError) as exc:
199
- print(f"write_fix_xml failed: {exc}", file=sys.stderr)
200
- return 1
201
- print(output_path)
202
- return 0
203
-
204
-
205
- if __name__ == "__main__":
206
- raise SystemExit(main(sys.argv[1:]))