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,499 +0,0 @@
1
- """Tests pinning build_audit_prompt's emitted A-Q category taxonomy."""
2
-
3
- from __future__ import annotations
4
-
5
- import importlib.util
6
- import re
7
- import sys
8
- from pathlib import Path
9
- from types import ModuleType
10
- from xml.etree.ElementTree import Element
11
-
12
- import pytest
13
-
14
- _SCRIPTS_DIR = Path(__file__).resolve().parent
15
- _skills_home_directory = _SCRIPTS_DIR.parents[3]
16
- _PACKAGE_ROOT_FOR_RUBRICS = (
17
- _skills_home_directory.parent
18
- if _skills_home_directory.name == ".agents"
19
- else _skills_home_directory
20
- )
21
- if str(_SCRIPTS_DIR) not in sys.path:
22
- sys.path.insert(0, str(_SCRIPTS_DIR))
23
-
24
- from skills_pr_loop_constants.path_resolver_constants import (
25
- ALL_AUDIT_CATEGORY_ENTRIES,
26
- AUDIT_COMMENT_POSTING_AGENT_TEXT,
27
- AUDIT_COMMENT_POSTING_HEADLESS_TEXT,
28
- AUDIT_OUTPUT_FORMAT_AGENT_TEXT,
29
- AUDIT_OUTPUT_FORMAT_HEADLESS_TEMPLATE,
30
- AUDIT_PROMPT_FLAVOR_AGENT,
31
- AUDIT_PROMPT_FLAVOR_HEADLESS,
32
- OUTCOME_XML_TEMPLATE,
33
- )
34
-
35
- _CATEGORY_RUBRICS_DIR = _PACKAGE_ROOT_FOR_RUBRICS / "audit-rubrics" / "category_rubrics"
36
- _HEADING_PATTERN = re.compile(r"^# Category ([A-Q]) — (.+)$")
37
-
38
-
39
- def _load_build_audit_prompt() -> ModuleType:
40
- module_path = _SCRIPTS_DIR / "build_audit_prompt.py"
41
- spec = importlib.util.spec_from_file_location("build_audit_prompt", module_path)
42
- assert spec is not None
43
- assert spec.loader is not None
44
- module = importlib.util.module_from_spec(spec)
45
- sys.modules["build_audit_prompt"] = module
46
- spec.loader.exec_module(module)
47
- return module
48
-
49
-
50
- build_audit_prompt = _load_build_audit_prompt()
51
-
52
-
53
- def _rubric_label_by_letter() -> dict[str, str]:
54
- assert _CATEGORY_RUBRICS_DIR.is_dir(), f"Missing rubric directory: {_CATEGORY_RUBRICS_DIR}"
55
- all_labels: dict[str, str] = {}
56
- for each_rubric_file in sorted(_CATEGORY_RUBRICS_DIR.glob("category-*.md")):
57
- all_rubric_lines = each_rubric_file.read_text(encoding="utf-8").splitlines()
58
- assert all_rubric_lines, f"Empty rubric file: {each_rubric_file}"
59
- each_match = _HEADING_PATTERN.match(all_rubric_lines[0])
60
- assert each_match is not None, f"Heading pattern not matched in {each_rubric_file}"
61
- all_labels[each_match.group(1)] = each_match.group(2)
62
- return all_labels
63
-
64
-
65
- def _build_audit_root() -> Element:
66
- return build_audit_prompt.build_audit_prompt_xml(
67
- owner="jl-cmd",
68
- repo="claude-dev-env",
69
- pr_number=422,
70
- loop=1,
71
- head_ref="feat/branch",
72
- base_ref="main",
73
- worktree_path=Path("/tmp/bugteam-pr-422/worktree"),
74
- run_temp_dir=Path("/tmp/bugteam-pr-422"),
75
- )
76
-
77
-
78
- def test_context_and_scope_render_paths_with_forward_slashes() -> None:
79
- root = build_audit_prompt.build_audit_prompt_xml(
80
- owner="jl-cmd",
81
- repo="claude-dev-env",
82
- pr_number=376,
83
- loop=1,
84
- head_ref="feat/branch",
85
- base_ref="main",
86
- worktree_path=Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree"),
87
- run_temp_dir=Path("C:/Users/example/AppData/Local/Temp/bugteam-pr-376"),
88
- )
89
- context = root.find("context")
90
- assert context is not None
91
- worktree_text = context.findtext("worktree_path")
92
- run_temp_text = context.findtext("run_temp_dir")
93
- assert worktree_text == "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree"
94
- assert run_temp_text == "C:/Users/example/AppData/Local/Temp/bugteam-pr-376"
95
- scope = root.find("scope")
96
- assert scope is not None
97
- assert scope.text is not None
98
- assert "\\" not in scope.text
99
- assert "C:/Users/example/AppData/Local/Temp/bugteam-pr-376/worktree" in scope.text
100
-
101
-
102
- def test_bug_categories_carry_ids_a_through_q_in_order() -> None:
103
- root = _build_audit_root()
104
- bug_categories = root.find("bug_categories")
105
- assert bug_categories is not None
106
- all_emitted_ids = [each_category.get("id") for each_category in bug_categories]
107
- all_expected_ids = list("ABCDEFGHIJKLMNOPQ")
108
- assert all_emitted_ids == all_expected_ids
109
-
110
-
111
- def test_emitted_category_labels_match_constant_entries() -> None:
112
- root = _build_audit_root()
113
- bug_categories = root.find("bug_categories")
114
- assert bug_categories is not None
115
- label_by_id = {
116
- each_category.get("id"): each_category.text for each_category in bug_categories
117
- }
118
- for each_category_id, each_category_label in ALL_AUDIT_CATEGORY_ENTRIES:
119
- assert label_by_id[each_category_id] == each_category_label
120
-
121
-
122
- def test_category_labels_match_rubric_file_headings() -> None:
123
- assert dict(ALL_AUDIT_CATEGORY_ENTRIES) == _rubric_label_by_letter()
124
-
125
-
126
- def test_rubric_reference_element_names_category_rubrics_directory() -> None:
127
- root = _build_audit_root()
128
- rubric_reference = root.find("rubric_reference")
129
- assert rubric_reference is not None
130
- assert rubric_reference.text is not None
131
- assert "audit-rubrics/category_rubrics" in rubric_reference.text
132
-
133
-
134
- def test_prompt_skeleton_sub_bucket_counts_match_rubric_rows() -> None:
135
- """Each prompt skeleton's numeric sub-bucket count equals its rubric's row count.
136
-
137
- For every (letter, label) the prompts dir holds a category-<letter>- file.
138
- The skeleton above the first standalone --- line states "decomposed into N
139
- sub-buckets"; that N must equal the rubric's count of | <letter>N | rows,
140
- and a numeric walk-instruction range (For each sub-bucket X1-Xn) must end
141
- at that same row count. Skeletons with a [N] placeholder are skipped.
142
- """
143
- prompts_directory = _CATEGORY_RUBRICS_DIR.parent / "prompts"
144
- count_pattern = re.compile(r"decomposed into (\d+) sub-buckets")
145
- for each_letter, _each_label in ALL_AUDIT_CATEGORY_ENTRIES:
146
- all_prompt_matches = sorted(prompts_directory.glob(f"category-{each_letter.lower()}-*.md"))
147
- assert all_prompt_matches, f"Missing prompt file for category {each_letter}"
148
- all_skeleton_lines: list[str] = []
149
- for each_line in all_prompt_matches[0].read_text(encoding="utf-8").splitlines():
150
- if each_line == "---":
151
- break
152
- all_skeleton_lines.append(each_line)
153
- skeleton_text = "\n".join(all_skeleton_lines)
154
- each_count_match = count_pattern.search(skeleton_text)
155
- if each_count_match is None:
156
- assert "decomposed into [N] sub-buckets" in skeleton_text, (
157
- f"Category {each_letter}: skeleton neither states a numeric "
158
- "sub-bucket count nor carries the [N] placeholder"
159
- )
160
- continue
161
- all_rubric_matches = sorted(_CATEGORY_RUBRICS_DIR.glob(f"category-{each_letter.lower()}-*.md"))
162
- assert all_rubric_matches, f"Missing rubric file for category {each_letter}"
163
- rubric_row_pattern = re.compile(r"^\| " + each_letter + r"\d+ \|", re.MULTILINE)
164
- sub_bucket_row_count = len(rubric_row_pattern.findall(all_rubric_matches[0].read_text(encoding="utf-8")))
165
- assert int(each_count_match.group(1)) == sub_bucket_row_count, (
166
- f"Category {each_letter}: skeleton says {each_count_match.group(1)} sub-buckets "
167
- f"but rubric has {sub_bucket_row_count} rows"
168
- )
169
- walk_range_pattern = re.compile(
170
- rf"For each sub-bucket {each_letter}1[-–]{each_letter}(\d+)"
171
- )
172
- each_walk_match = walk_range_pattern.search(skeleton_text)
173
- if each_walk_match is not None:
174
- assert int(each_walk_match.group(1)) == sub_bucket_row_count, (
175
- f"Category {each_letter}: walk instruction ends at "
176
- f"{each_letter}{each_walk_match.group(1)} but rubric has "
177
- f"{sub_bucket_row_count} rows"
178
- )
179
-
180
-
181
- def test_bug_categories_include_category_q() -> None:
182
- root = _build_audit_root()
183
- bug_categories = root.find("bug_categories")
184
- assert bug_categories is not None
185
- label_by_id = {
186
- each_category.get("id"): each_category.text for each_category in bug_categories
187
- }
188
- assert label_by_id["Q"] == (
189
- "Cross-surface claim consistency "
190
- "(terminology, PR-description claims, message-vs-guard)"
191
- )
192
-
193
-
194
- def test_pr_description_carries_body_text_when_supplied() -> None:
195
- root = build_audit_prompt.build_audit_prompt_xml(
196
- owner="jl-cmd",
197
- repo="claude-dev-env",
198
- pr_number=422,
199
- loop=1,
200
- head_ref="feat/branch",
201
- base_ref="main",
202
- worktree_path=Path("/tmp/bugteam-pr-422/worktree"),
203
- run_temp_dir=Path("/tmp/bugteam-pr-422"),
204
- pr_body_text="## Summary\nCloses the gate.",
205
- )
206
- pr_description = root.find("pr_description")
207
- assert pr_description is not None
208
- assert pr_description.text == "## Summary\nCloses the gate."
209
-
210
-
211
- def test_pr_description_empty_when_body_absent() -> None:
212
- root = _build_audit_root()
213
- pr_description = root.find("pr_description")
214
- assert pr_description is not None
215
- assert pr_description.text is None
216
-
217
-
218
- def test_read_pr_body_text_returns_file_contents(tmp_path: Path) -> None:
219
- body_file = tmp_path / "pr-body.md"
220
- body_file.write_text("body from disk", encoding="utf-8")
221
- assert build_audit_prompt.read_pr_body_text(body_file) == "body from disk"
222
-
223
-
224
- def test_read_pr_body_text_returns_none_when_path_absent() -> None:
225
- assert build_audit_prompt.read_pr_body_text(None) is None
226
-
227
-
228
- def test_read_pr_body_text_returns_none_when_file_missing(tmp_path: Path) -> None:
229
- missing_file = tmp_path / "does-not-exist.md"
230
- assert build_audit_prompt.read_pr_body_text(missing_file) is None
231
-
232
-
233
- def test_emit_audit_prompt_embeds_pr_body_text_in_pr_description() -> None:
234
- xml_text = build_audit_prompt.emit_audit_prompt(
235
- owner="jl-cmd",
236
- repo="claude-dev-env",
237
- pr_number=422,
238
- loop=1,
239
- head_ref="feat/branch",
240
- base_ref="main",
241
- worktree_path=Path("/tmp/bugteam-pr-422/worktree"),
242
- run_temp_dir=Path("/tmp/bugteam-pr-422"),
243
- pr_body_text="body via emit",
244
- )
245
- assert "body via emit" in xml_text
246
-
247
-
248
- def test_parse_arguments_defaults_pr_body_file_to_none() -> None:
249
- arguments = build_audit_prompt.parse_arguments([
250
- "--owner", "jl-cmd",
251
- "--repo", "claude-dev-env",
252
- "--pr-number", "422",
253
- "--loop", "1",
254
- "--head-ref", "feat/branch",
255
- "--base-ref", "main",
256
- "--worktree-path", "/tmp/wt",
257
- "--run-temp-dir", "/tmp/rt",
258
- ])
259
- assert arguments.pr_body_file is None
260
-
261
-
262
- def test_parse_arguments_reads_pr_body_file_path() -> None:
263
- arguments = build_audit_prompt.parse_arguments([
264
- "--owner", "jl-cmd",
265
- "--repo", "claude-dev-env",
266
- "--pr-number", "422",
267
- "--loop", "1",
268
- "--head-ref", "feat/branch",
269
- "--base-ref", "main",
270
- "--worktree-path", "/tmp/wt",
271
- "--run-temp-dir", "/tmp/rt",
272
- "--pr-body-file", "/tmp/body.md",
273
- ])
274
- assert arguments.pr_body_file == Path("/tmp/body.md")
275
-
276
-
277
- def test_parse_arguments_defaults_flavor_to_agent() -> None:
278
- arguments = build_audit_prompt.parse_arguments([
279
- "--owner", "jl-cmd",
280
- "--repo", "claude-dev-env",
281
- "--pr-number", "422",
282
- "--loop", "1",
283
- "--head-ref", "feat/branch",
284
- "--base-ref", "main",
285
- "--worktree-path", "/tmp/wt",
286
- "--run-temp-dir", "/tmp/rt",
287
- ])
288
- assert arguments.flavor == AUDIT_PROMPT_FLAVOR_AGENT
289
-
290
-
291
- def test_parse_arguments_reads_headless_flavor() -> None:
292
- arguments = build_audit_prompt.parse_arguments([
293
- "--owner", "jl-cmd",
294
- "--repo", "claude-dev-env",
295
- "--pr-number", "422",
296
- "--loop", "1",
297
- "--head-ref", "feat/branch",
298
- "--base-ref", "main",
299
- "--worktree-path", "/tmp/wt",
300
- "--run-temp-dir", "/tmp/rt",
301
- "--flavor", AUDIT_PROMPT_FLAVOR_HEADLESS,
302
- ])
303
- assert arguments.flavor == AUDIT_PROMPT_FLAVOR_HEADLESS
304
-
305
-
306
- def test_agent_flavor_comment_posting_names_mcp_tool() -> None:
307
- root = build_audit_prompt.build_audit_prompt_xml(
308
- owner="jl-cmd",
309
- repo="claude-dev-env",
310
- pr_number=422,
311
- loop=1,
312
- head_ref="feat/branch",
313
- base_ref="main",
314
- worktree_path=Path("/tmp/bugteam-pr-422/worktree"),
315
- run_temp_dir=Path("/tmp/bugteam-pr-422"),
316
- flavor=AUDIT_PROMPT_FLAVOR_AGENT,
317
- )
318
- comment_posting = root.find("comment_posting")
319
- assert comment_posting is not None
320
- assert comment_posting.text == AUDIT_COMMENT_POSTING_AGENT_TEXT
321
- output_format = root.find("output_format")
322
- assert output_format is not None
323
- assert output_format.text == AUDIT_OUTPUT_FORMAT_AGENT_TEXT
324
-
325
-
326
- def test_headless_flavor_writes_outcome_path_and_forbids_mcp() -> None:
327
- worktree_path = Path("/tmp/bugteam-pr-422/worktree")
328
- pr_number = 422
329
- loop = 3
330
- root = build_audit_prompt.build_audit_prompt_xml(
331
- owner="jl-cmd",
332
- repo="claude-dev-env",
333
- pr_number=pr_number,
334
- loop=loop,
335
- head_ref="feat/branch",
336
- base_ref="main",
337
- worktree_path=worktree_path,
338
- run_temp_dir=Path("/tmp/bugteam-pr-422"),
339
- flavor=AUDIT_PROMPT_FLAVOR_HEADLESS,
340
- )
341
- comment_posting = root.find("comment_posting")
342
- assert comment_posting is not None
343
- assert comment_posting.text == AUDIT_COMMENT_POSTING_HEADLESS_TEXT
344
- assert "MCP" not in (comment_posting.text or "")
345
- assert "TaskCreate" not in (comment_posting.text or "")
346
- assert "gh" in (comment_posting.text or "")
347
- assert "post_audit_thread.py" in (comment_posting.text or "")
348
-
349
- expected_outcome_path = (
350
- worktree_path / OUTCOME_XML_TEMPLATE.format(number=pr_number, loop=loop)
351
- ).as_posix()
352
- output_format = root.find("output_format")
353
- assert output_format is not None
354
- assert output_format.text == AUDIT_OUTPUT_FORMAT_HEADLESS_TEMPLATE.format(
355
- outcome_path=expected_outcome_path,
356
- )
357
- assert expected_outcome_path in (output_format.text or "")
358
- assert "TaskCreate" in (output_format.text or "")
359
- assert "MCP" in (output_format.text or "")
360
-
361
-
362
- def test_main_headless_flavor_emits_outcome_path_on_stdout(
363
- capsys: pytest.CaptureFixture[str],
364
- ) -> None:
365
- worktree_path = "/tmp/bugteam-pr-99/worktree"
366
- exit_code = build_audit_prompt.main([
367
- "--owner", "jl-cmd",
368
- "--repo", "claude-dev-env",
369
- "--pr-number", "99",
370
- "--loop", "2",
371
- "--head-ref", "feat/branch",
372
- "--base-ref", "main",
373
- "--worktree-path", worktree_path,
374
- "--run-temp-dir", "/tmp/bugteam-pr-99",
375
- "--flavor", AUDIT_PROMPT_FLAVOR_HEADLESS,
376
- ])
377
- assert exit_code == 0
378
- captured = capsys.readouterr()
379
- expected_outcome = (
380
- Path(worktree_path)
381
- / OUTCOME_XML_TEMPLATE.format(number=99, loop=2)
382
- ).as_posix()
383
- assert expected_outcome in captured.out
384
- assert "post_audit_thread.py" in captured.out
385
- assert "Do not post reviews" in captured.out
386
- assert "add_comment_to_pending_review" not in captured.out
387
-
388
-
389
- def test_code_quality_agent_requires_scoped_intake_and_evidence_gaps() -> None:
390
- agent_text = _CODE_QUALITY_AGENT_PATH.read_text(encoding="utf-8")
391
-
392
- required_phrases = (
393
- "read each existing `AGENTS.md` and `CLAUDE.md`",
394
- "scoped `AGENTS.md` files as the canonical",
395
- "`docs/CODE_RULES.md` is a compact projection",
396
- "`hooks/blocking/code_rules_enforcer.py` is hand-maintained write-time coverage",
397
- "full diff",
398
- "resolved base or merge-base",
399
- "complete changed-file list",
400
- "PR description",
401
- "evidence gap",
402
- "Never infer omitted content",
403
- )
404
- for each_phrase in required_phrases:
405
- assert each_phrase in agent_text
406
-
407
- assert "## Review intake and policy sources" in agent_text
408
- assert "Open questions" in agent_text
409
-
410
-
411
- _PACKAGE_ROOT = _PACKAGE_ROOT_FOR_RUBRICS
412
- _CODE_QUALITY_AGENT_PATH = _PACKAGE_ROOT / ".agents" / "agents" / "code-quality-agent.md"
413
- _AUDIT_CONTRACT_PATH = _PACKAGE_ROOT / "_shared" / "pr-loop" / "audit-contract.md"
414
- _PRECATCH_RUBRIC_PATH = _PACKAGE_ROOT / "_shared" / "pr-loop" / "precatch-rubric.md"
415
- _CATEGORY_Q_LABEL = (
416
- "Cross-surface claim consistency "
417
- "(terminology, PR-description claims, message-vs-guard)"
418
- )
419
- _CATEGORY_Q_RUBRIC_REFERENCE = (
420
- "`<managed-root>/audit-rubrics/category_rubrics/"
421
- "category-q-cross-surface-claims.md`"
422
- " (source fallback: "
423
- "`packages/claude-dev-env/audit-rubrics/category_rubrics/"
424
- "category-q-cross-surface-claims.md`)"
425
- )
426
- _A_THROUGH_Q_PATTERN = re.compile(r"A[\u2013-]Q")
427
- _SEVENTEEN_CATEGORIES_PATTERN = re.compile(r"seventeen categor", re.IGNORECASE)
428
- _STALE_SIXTEEN_PATTERN = re.compile(r"sixteen categor", re.IGNORECASE)
429
- _STALE_A_THROUGH_P_PATTERN = re.compile(r"A[\u2013-]P")
430
-
431
-
432
- def test_code_quality_agent_default_scope_is_a_through_q() -> None:
433
- agent_text = _CODE_QUALITY_AGENT_PATH.read_text(encoding="utf-8")
434
- assert _A_THROUGH_Q_PATTERN.search(agent_text) is not None
435
- assert _SEVENTEEN_CATEGORIES_PATTERN.search(agent_text) is not None
436
- assert _STALE_SIXTEEN_PATTERN.search(agent_text) is None
437
- assert "A through Q" in agent_text
438
- assert "A through P" not in agent_text
439
- assert _STALE_A_THROUGH_P_PATTERN.search(agent_text) is None
440
- assert "## Bug Categories A–Q" in agent_text
441
- assert _CATEGORY_Q_LABEL in agent_text
442
- assert _CATEGORY_Q_RUBRIC_REFERENCE in agent_text
443
- assert "| Q |" in agent_text
444
-
445
-
446
- def test_code_quality_agent_contract_is_caller_neutral() -> None:
447
- agent_text = _CODE_QUALITY_AGENT_PATH.read_text(encoding="utf-8")
448
- stale_terms = (
449
- "PR #394",
450
- "PR #397",
451
- "May 2026",
452
- "r3210166636",
453
- "/bugteam",
454
- "/pr-converge",
455
- "/autoconverge",
456
- "opus",
457
- "sonnet",
458
- "model:",
459
- )
460
- for stale_term in stale_terms:
461
- assert stale_term not in agent_text
462
- assert "The caller provides the diff, audit scope, ID prefix, and output format." in agent_text
463
- assert "Do not assume a model, caller name, or persistence path." in agent_text
464
-
465
-
466
- def test_audit_contract_category_schema_includes_q() -> None:
467
- contract_text = _AUDIT_CONTRACT_PATH.read_text(encoding="utf-8")
468
- assert '"category": "A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q"' in (
469
- contract_text
470
- )
471
- assert _A_THROUGH_Q_PATTERN.search(contract_text) is not None
472
- assert _STALE_A_THROUGH_P_PATTERN.search(contract_text) is None
473
-
474
-
475
- def test_precatch_rubric_adversarial_lane_uses_a_through_q() -> None:
476
- rubric_text = _PRECATCH_RUBRIC_PATH.read_text(encoding="utf-8")
477
- assert _A_THROUGH_Q_PATTERN.search(rubric_text) is not None
478
- assert _STALE_A_THROUGH_P_PATTERN.search(rubric_text) is None
479
-
480
-
481
- def test_audit_prompt_constraints_require_collection_before_severity_filter() -> None:
482
- root = _build_audit_root()
483
- constraints = root.find("constraints")
484
- assert constraints is not None
485
- all_constraint_texts = [
486
- each_constraint.text or "" for each_constraint in constraints
487
- ]
488
- joined = "\n".join(all_constraint_texts)
489
- assert "Report every real finding" in joined
490
- assert "Do not drop findings by severity during collection" in joined
491
- assert "separate consumer stage" in joined
492
- assert "P0" in joined and "P1" in joined and "P2" in joined
493
-
494
-
495
- def test_audit_contract_documents_collection_before_severity_filtering() -> None:
496
- contract_text = _AUDIT_CONTRACT_PATH.read_text(encoding="utf-8")
497
- assert "## Collection before severity filtering" in contract_text
498
- assert "separate consumer stage" in contract_text
499
- assert "Do not drop a real finding because its severity is low" in contract_text
@@ -1,140 +0,0 @@
1
- """Tests for build_converge_task_list — runnable gates and final CLEAN task."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import subprocess
7
- import sys
8
- from pathlib import Path
9
-
10
- _SCRIPTS_DIR = Path(__file__).resolve().parent
11
- if str(_SCRIPTS_DIR) not in sys.path:
12
- sys.path.insert(0, str(_SCRIPTS_DIR))
13
-
14
- import build_converge_task_list as task_list_module # noqa: E402
15
- from skills_pr_loop_constants.converge_task_list_constants import ( # noqa: E402
16
- EXIT_SUCCESS,
17
- RESULT_KEY_DONE_WHEN,
18
- RESULT_KEY_FINAL_TASK_ID,
19
- RESULT_KEY_RUNNABLE_REVIEW_IDS,
20
- RESULT_KEY_SKIPPED_REVIEW_IDS,
21
- RESULT_KEY_TASKS,
22
- SKIP_REASON_BUGBOT_DOWN,
23
- SKIP_REASON_CODEX_NOT_REQUIRED,
24
- SKIP_REASON_COPILOT_DOWN,
25
- TASK_FIELD_ID,
26
- TASK_FIELD_IS_RUNNABLE,
27
- TASK_FIELD_KIND,
28
- TASK_ID_ALL_CLEAN_SAME_HEAD,
29
- TASK_ID_BUGBOT,
30
- TASK_ID_BUGTEAM,
31
- TASK_ID_CODE_REVIEW,
32
- TASK_ID_CODEX,
33
- TASK_ID_COPILOT,
34
- TASK_KIND_FINAL,
35
- TASK_KIND_REVIEW,
36
- )
37
-
38
- SCRIPT_PATH = _SCRIPTS_DIR / "build_converge_task_list.py"
39
-
40
-
41
- def test_default_flags_code_review_and_bugteam_runnable_final_last() -> None:
42
- payload = task_list_module.build_converge_task_list(
43
- is_bugbot_down=False,
44
- is_copilot_down=False,
45
- is_codex_down=False,
46
- is_codex_required=False,
47
- )
48
- all_tasks = payload[RESULT_KEY_TASKS]
49
- assert isinstance(all_tasks, list)
50
- assert all_tasks[0][TASK_FIELD_ID] == TASK_ID_CODE_REVIEW
51
- assert all_tasks[1][TASK_FIELD_ID] == TASK_ID_BUGTEAM
52
- assert all_tasks[-1][TASK_FIELD_ID] == TASK_ID_ALL_CLEAN_SAME_HEAD
53
- assert all_tasks[-1][TASK_FIELD_KIND] == TASK_KIND_FINAL
54
- assert payload[RESULT_KEY_FINAL_TASK_ID] == TASK_ID_ALL_CLEAN_SAME_HEAD
55
- assert TASK_ID_CODE_REVIEW in payload[RESULT_KEY_RUNNABLE_REVIEW_IDS]
56
- assert TASK_ID_BUGTEAM in payload[RESULT_KEY_RUNNABLE_REVIEW_IDS]
57
- assert TASK_ID_BUGBOT in payload[RESULT_KEY_RUNNABLE_REVIEW_IDS]
58
- assert TASK_ID_COPILOT in payload[RESULT_KEY_RUNNABLE_REVIEW_IDS]
59
- assert TASK_ID_CODEX in payload[RESULT_KEY_SKIPPED_REVIEW_IDS]
60
-
61
-
62
- def test_down_flags_skip_external_reviews() -> None:
63
- payload = task_list_module.build_converge_task_list(
64
- is_bugbot_down=True,
65
- is_copilot_down=True,
66
- is_codex_down=True,
67
- is_codex_required=True,
68
- )
69
- all_tasks = payload[RESULT_KEY_TASKS]
70
- assert isinstance(all_tasks, list)
71
- all_tasks_by_id = {
72
- each_task[TASK_FIELD_ID]: each_task for each_task in all_tasks
73
- }
74
- assert all_tasks_by_id[TASK_ID_BUGBOT][TASK_FIELD_IS_RUNNABLE] is False
75
- assert all_tasks_by_id[TASK_ID_COPILOT][TASK_FIELD_IS_RUNNABLE] is False
76
- assert all_tasks_by_id[TASK_ID_CODEX][TASK_FIELD_IS_RUNNABLE] is False
77
- assert payload[RESULT_KEY_RUNNABLE_REVIEW_IDS] == [
78
- TASK_ID_CODE_REVIEW,
79
- TASK_ID_BUGTEAM,
80
- ]
81
- assert SKIP_REASON_BUGBOT_DOWN in str(all_tasks_by_id[TASK_ID_BUGBOT])
82
- assert SKIP_REASON_COPILOT_DOWN in str(all_tasks_by_id[TASK_ID_COPILOT])
83
-
84
-
85
- def test_codex_required_is_runnable() -> None:
86
- payload = task_list_module.build_converge_task_list(
87
- is_bugbot_down=True,
88
- is_copilot_down=True,
89
- is_codex_down=False,
90
- is_codex_required=True,
91
- )
92
- assert TASK_ID_CODEX in payload[RESULT_KEY_RUNNABLE_REVIEW_IDS]
93
- assert SKIP_REASON_CODEX_NOT_REQUIRED not in str(payload)
94
-
95
-
96
- def test_final_task_always_last_and_runnable() -> None:
97
- payload = task_list_module.build_converge_task_list(
98
- is_bugbot_down=True,
99
- is_copilot_down=False,
100
- is_codex_down=False,
101
- is_codex_required=True,
102
- )
103
- all_tasks = payload[RESULT_KEY_TASKS]
104
- assert isinstance(all_tasks, list)
105
- final_task = all_tasks[-1]
106
- assert final_task[TASK_FIELD_ID] == TASK_ID_ALL_CLEAN_SAME_HEAD
107
- assert final_task[TASK_FIELD_IS_RUNNABLE] is True
108
- assert final_task[TASK_FIELD_KIND] == TASK_KIND_FINAL
109
- assert payload[RESULT_KEY_DONE_WHEN]
110
-
111
-
112
- def test_cli_prints_json() -> None:
113
- completed = subprocess.run(
114
- [
115
- sys.executable,
116
- str(SCRIPT_PATH),
117
- "--bugbot-down",
118
- "1",
119
- "--copilot-down",
120
- "0",
121
- "--codex-required",
122
- "0",
123
- ],
124
- check=False,
125
- capture_output=True,
126
- text=True,
127
- )
128
- assert completed.returncode == EXIT_SUCCESS, completed.stderr
129
- payload = json.loads(completed.stdout)
130
- assert payload[RESULT_KEY_FINAL_TASK_ID] == TASK_ID_ALL_CLEAN_SAME_HEAD
131
- assert TASK_ID_BUGBOT in payload[RESULT_KEY_SKIPPED_REVIEW_IDS]
132
- assert any(
133
- each_task[TASK_FIELD_KIND] == TASK_KIND_REVIEW
134
- for each_task in payload[RESULT_KEY_TASKS]
135
- )
136
-
137
-
138
- def test_main_returns_usage_on_bad_bool() -> None:
139
- exit_code = task_list_module.main(["--bugbot-down", "maybe"])
140
- assert exit_code == task_list_module.EXIT_USAGE_ERROR