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,287 +0,0 @@
1
- """Tests for preflight_worktree against real git working trees."""
2
-
3
- from __future__ import annotations
4
-
5
- import importlib.util
6
- import subprocess
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_preflight() -> ModuleType:
19
- module_path = _SCRIPTS_DIR / "preflight_worktree.py"
20
- spec = importlib.util.spec_from_file_location("preflight_worktree", module_path)
21
- assert spec is not None
22
- assert spec.loader is not None
23
- module = importlib.util.module_from_spec(spec)
24
- sys.modules["preflight_worktree"] = module
25
- spec.loader.exec_module(module)
26
- return module
27
-
28
-
29
- preflight = _load_preflight()
30
-
31
- GIT_TIMEOUT = 30
32
- CLAUDE_REMOTE = "https://github.com/jl-cmd/claude-dev-env.git"
33
- GIT_CEILING_DIRECTORIES = "GIT_CEILING_DIRECTORIES"
34
-
35
-
36
- @pytest.fixture(autouse=True)
37
- def _isolate_git_from_ancestor_repos(
38
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
39
- ) -> None:
40
- monkeypatch.setenv(GIT_CEILING_DIRECTORIES, str(tmp_path))
41
-
42
-
43
- def _git(repo_dir: Path, *args: str) -> None:
44
- subprocess.run(
45
- ["git", "-C", str(repo_dir), *args],
46
- check=True,
47
- capture_output=True,
48
- text=True,
49
- timeout=GIT_TIMEOUT,
50
- )
51
-
52
-
53
- def _init_repo(repo_dir: Path, origin_url: str | None) -> Path:
54
- repo_dir.mkdir(parents=True, exist_ok=True)
55
- subprocess.run(
56
- ["git", "init", "-q", str(repo_dir)],
57
- check=True,
58
- capture_output=True,
59
- text=True,
60
- timeout=GIT_TIMEOUT,
61
- )
62
- if origin_url is not None:
63
- _git(repo_dir, "remote", "add", "origin", origin_url)
64
- return repo_dir
65
-
66
-
67
- @pytest.mark.parametrize(
68
- ("remote_url", "expected_owner", "expected_repo"),
69
- [
70
- (
71
- "https://github.com/jl-cmd/claude-dev-env.git",
72
- "jl-cmd",
73
- "claude-dev-env",
74
- ),
75
- (
76
- "https://github.com/jl-cmd/claude-dev-env",
77
- "jl-cmd",
78
- "claude-dev-env",
79
- ),
80
- ("git@github.com:Example/llm-settings.git", "example", "llm-settings"),
81
- (
82
- "ssh://git@github.com/jl-cmd/Claude-Dev-Env",
83
- "jl-cmd",
84
- "claude-dev-env",
85
- ),
86
- ("https://github.com/jl-cmd/repo/", "jl-cmd", "repo"),
87
- ],
88
- )
89
- def test_parse_repo_identity_accepts_every_github_remote_form(
90
- remote_url: str, expected_owner: str, expected_repo: str
91
- ) -> None:
92
- identity = preflight.parse_repo_identity(remote_url)
93
- assert identity is not None
94
- assert identity.owner == expected_owner
95
- assert identity.repo == expected_repo
96
-
97
-
98
- @pytest.mark.parametrize(
99
- "remote_url",
100
- ["https://gitlab.com/foo/bar.git", "", "not-a-url"],
101
- )
102
- def test_parse_repo_identity_rejects_non_github_remotes(remote_url: str) -> None:
103
- assert preflight.parse_repo_identity(remote_url) is None
104
-
105
-
106
- def test_is_inside_work_tree_true_in_git_repo(tmp_path: Path) -> None:
107
- repo_dir = _init_repo(tmp_path / "session", None)
108
- assert preflight.is_inside_work_tree(repo_dir) is True
109
-
110
-
111
- def test_is_inside_work_tree_false_in_plain_directory(tmp_path: Path) -> None:
112
- plain_dir = tmp_path / "home"
113
- plain_dir.mkdir()
114
- assert preflight.is_inside_work_tree(plain_dir) is False
115
-
116
-
117
- def test_worktree_machinery_is_healthy_true_in_git_repo(tmp_path: Path) -> None:
118
- repo_dir = _init_repo(tmp_path / "session", None)
119
- assert preflight.worktree_machinery_is_healthy(repo_dir) is True
120
-
121
-
122
- def test_worktree_machinery_is_healthy_false_in_plain_directory(
123
- tmp_path: Path,
124
- ) -> None:
125
- plain_dir = tmp_path / "home"
126
- plain_dir.mkdir()
127
- assert preflight.worktree_machinery_is_healthy(plain_dir) is False
128
-
129
-
130
- def test_classify_same_repo_when_origin_matches_pr(tmp_path: Path) -> None:
131
- repo_dir = _init_repo(tmp_path / "session", CLAUDE_REMOTE)
132
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
133
- verdict = preflight.classify_environment(repo_dir, pr_identity)
134
- assert verdict.outcome == preflight.OUTCOME_SAME_REPO
135
- assert verdict.cwd_identity == pr_identity
136
- assert verdict.has_healthy_worktree_machinery is True
137
-
138
-
139
- def test_classify_different_repo_when_origin_is_another_github_repo(
140
- tmp_path: Path,
141
- ) -> None:
142
- repo_dir = _init_repo(
143
- tmp_path / "session", "https://github.com/example/llm-settings.git"
144
- )
145
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
146
- verdict = preflight.classify_environment(repo_dir, pr_identity)
147
- assert verdict.outcome == preflight.OUTCOME_DIFFERENT_REPO
148
- assert verdict.cwd_identity == preflight.RepoIdentity("example", "llm-settings")
149
-
150
-
151
- def test_classify_different_repo_when_origin_is_non_github(tmp_path: Path) -> None:
152
- repo_dir = _init_repo(tmp_path / "session", "https://gitlab.com/foo/bar.git")
153
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
154
- verdict = preflight.classify_environment(repo_dir, pr_identity)
155
- assert verdict.outcome == preflight.OUTCOME_DIFFERENT_REPO
156
- assert verdict.cwd_identity is None
157
-
158
-
159
- def test_classify_re_rooted_when_origin_is_absent(tmp_path: Path) -> None:
160
- repo_dir = _init_repo(tmp_path / "session", None)
161
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
162
- verdict = preflight.classify_environment(repo_dir, pr_identity)
163
- assert verdict.outcome == preflight.OUTCOME_RE_ROOTED
164
-
165
-
166
- def test_classify_re_rooted_when_directory_is_not_a_work_tree(
167
- tmp_path: Path,
168
- ) -> None:
169
- plain_dir = tmp_path / "home"
170
- plain_dir.mkdir()
171
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
172
- verdict = preflight.classify_environment(plain_dir, pr_identity)
173
- assert verdict.outcome == preflight.OUTCOME_RE_ROOTED
174
- assert verdict.has_healthy_worktree_machinery is False
175
-
176
-
177
- @pytest.mark.parametrize(
178
- ("outcome", "is_healthy", "mode", "expected_exit"),
179
- [
180
- ("same_repo", True, "strict", 0),
181
- ("same_repo", True, "classify", 0),
182
- ("same_repo", False, "strict", 1),
183
- ("same_repo", False, "classify", 1),
184
- ("different_repo", True, "strict", 1),
185
- ("different_repo", True, "classify", 0),
186
- ("re_rooted", False, "strict", 1),
187
- ("re_rooted", False, "classify", 1),
188
- ],
189
- )
190
- def test_decide_exit_code_matrix(
191
- outcome: str, is_healthy: bool, mode: str, expected_exit: int
192
- ) -> None:
193
- verdict = preflight.PreflightVerdict(
194
- outcome=outcome,
195
- cwd_identity=None,
196
- has_healthy_worktree_machinery=is_healthy,
197
- )
198
- assert preflight.decide_exit_code(verdict, mode) == expected_exit
199
-
200
-
201
- def test_build_report_lines_marks_outcome_and_routes_cross_repo() -> None:
202
- verdict = preflight.PreflightVerdict(
203
- outcome=preflight.OUTCOME_DIFFERENT_REPO,
204
- cwd_identity=preflight.RepoIdentity("example", "llm-settings"),
205
- has_healthy_worktree_machinery=True,
206
- )
207
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
208
- classify_lines = preflight.build_report_lines(
209
- verdict, "classify", Path("/tmp/x"), pr_identity
210
- )
211
- assert classify_lines[0] == "PREFLIGHT_OUTCOME=different_repo"
212
- assert any("ROUTE" in line for line in classify_lines)
213
- strict_lines = preflight.build_report_lines(
214
- verdict, "strict", Path("/tmp/x"), pr_identity
215
- )
216
- assert any("ABORT" in line for line in strict_lines)
217
-
218
-
219
- def test_build_report_lines_aborts_on_broken_worktree_machinery() -> None:
220
- verdict = preflight.PreflightVerdict(
221
- outcome=preflight.OUTCOME_SAME_REPO,
222
- cwd_identity=preflight.RepoIdentity("jl-cmd", "claude-dev-env"),
223
- has_healthy_worktree_machinery=False,
224
- )
225
- pr_identity = preflight.RepoIdentity("jl-cmd", "claude-dev-env")
226
- lines = preflight.build_report_lines(verdict, "strict", Path("/tmp/x"), pr_identity)
227
- assert lines[0] == "PREFLIGHT_OUTCOME=same_repo"
228
- assert any("git worktree prune" in line for line in lines)
229
-
230
-
231
- def test_main_strict_passes_in_matching_repo(
232
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
233
- ) -> None:
234
- repo_dir = _init_repo(tmp_path / "session", CLAUDE_REMOTE)
235
- monkeypatch.chdir(repo_dir)
236
- exit_code = preflight.main(
237
- ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "strict"]
238
- )
239
- captured = capsys.readouterr()
240
- assert exit_code == preflight.EXIT_PREFLIGHT_OK
241
- assert "PREFLIGHT_OUTCOME=same_repo" in captured.out
242
-
243
-
244
- def test_main_strict_aborts_when_session_rooted_in_other_repo(
245
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
246
- ) -> None:
247
- repo_dir = _init_repo(
248
- tmp_path / "session", "https://github.com/example/llm-settings.git"
249
- )
250
- monkeypatch.chdir(repo_dir)
251
- exit_code = preflight.main(
252
- ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "strict"]
253
- )
254
- captured = capsys.readouterr()
255
- assert exit_code == preflight.EXIT_PREFLIGHT_ABORT
256
- assert "PREFLIGHT_OUTCOME=different_repo" in captured.out
257
- assert "ABORT" in captured.out
258
-
259
-
260
- def test_main_classify_routes_cross_repo_without_abort(
261
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
262
- ) -> None:
263
- repo_dir = _init_repo(
264
- tmp_path / "session", "https://github.com/example/llm-settings.git"
265
- )
266
- monkeypatch.chdir(repo_dir)
267
- exit_code = preflight.main(
268
- ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "classify"]
269
- )
270
- captured = capsys.readouterr()
271
- assert exit_code == preflight.EXIT_PREFLIGHT_OK
272
- assert "PREFLIGHT_OUTCOME=different_repo" in captured.out
273
- assert "ROUTE" in captured.out
274
-
275
-
276
- def test_main_classify_aborts_when_re_rooted(
277
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
278
- ) -> None:
279
- plain_dir = tmp_path / "home"
280
- plain_dir.mkdir()
281
- monkeypatch.chdir(plain_dir)
282
- exit_code = preflight.main(
283
- ["--owner", "jl-cmd", "--repo", "claude-dev-env", "--mode", "classify"]
284
- )
285
- captured = capsys.readouterr()
286
- assert exit_code == preflight.EXIT_PREFLIGHT_ABORT
287
- assert "PREFLIGHT_OUTCOME=re_rooted" in captured.out
@@ -1,207 +0,0 @@
1
- """Tests for select_converge_pacer — host tool surface → pacer mapping."""
2
-
3
- from __future__ import annotations
4
-
5
- import json
6
- import subprocess
7
- import sys
8
- from pathlib import Path
9
-
10
- import pytest
11
-
12
- _SCRIPTS_DIR = Path(__file__).resolve().parent
13
- if str(_SCRIPTS_DIR) not in sys.path:
14
- sys.path.insert(0, str(_SCRIPTS_DIR))
15
-
16
- import select_converge_pacer as pacer_module # noqa: E402
17
- from skills_pr_loop_constants.pacer_constants import ( # noqa: E402
18
- CLI_HAS_SCHEDULE_WAKEUP_FLAG,
19
- CLI_HAS_WORKFLOW_FLAG,
20
- CLI_SKILL_FLAG,
21
- ENTRY_SKILL_AUTOCONVERGE,
22
- ENTRY_SKILL_PR_CONVERGE,
23
- EXIT_SUCCESS,
24
- EXIT_USAGE_ERROR,
25
- PACER_PORTABLE,
26
- PACER_SCHEDULE_WAKEUP,
27
- PACER_WORKFLOW,
28
- RESULT_KEY_ENTRY_SKILL,
29
- RESULT_KEY_HAS_SCHEDULE_WAKEUP,
30
- RESULT_KEY_HAS_WORKFLOW,
31
- RESULT_KEY_PACER,
32
- )
33
-
34
- SCRIPT_PATH = _SCRIPTS_DIR / "select_converge_pacer.py"
35
-
36
-
37
- def test_autoconverge_with_workflow_selects_workflow() -> None:
38
- selection = pacer_module.select_converge_pacer(
39
- entry_skill=ENTRY_SKILL_AUTOCONVERGE,
40
- has_workflow=True,
41
- has_schedule_wakeup=False,
42
- )
43
- assert selection.pacer == PACER_WORKFLOW
44
- assert selection.entry_skill == ENTRY_SKILL_AUTOCONVERGE
45
-
46
-
47
- def test_autoconverge_without_workflow_selects_portable() -> None:
48
- selection = pacer_module.select_converge_pacer(
49
- entry_skill=ENTRY_SKILL_AUTOCONVERGE,
50
- has_workflow=False,
51
- has_schedule_wakeup=True,
52
- )
53
- assert selection.pacer == PACER_PORTABLE
54
-
55
-
56
- def test_pr_converge_with_schedule_wakeup_selects_schedule_wakeup() -> None:
57
- selection = pacer_module.select_converge_pacer(
58
- entry_skill=ENTRY_SKILL_PR_CONVERGE,
59
- has_workflow=False,
60
- has_schedule_wakeup=True,
61
- )
62
- assert selection.pacer == PACER_SCHEDULE_WAKEUP
63
- assert selection.entry_skill == ENTRY_SKILL_PR_CONVERGE
64
-
65
-
66
- def test_pr_converge_without_schedule_wakeup_selects_portable() -> None:
67
- selection = pacer_module.select_converge_pacer(
68
- entry_skill=ENTRY_SKILL_PR_CONVERGE,
69
- has_workflow=True,
70
- has_schedule_wakeup=False,
71
- )
72
- assert selection.pacer == PACER_PORTABLE
73
-
74
-
75
- def test_third_party_surface_selects_portable_for_both_entries() -> None:
76
- for each_skill in (ENTRY_SKILL_AUTOCONVERGE, ENTRY_SKILL_PR_CONVERGE):
77
- selection = pacer_module.select_converge_pacer(
78
- entry_skill=each_skill,
79
- has_workflow=False,
80
- has_schedule_wakeup=False,
81
- )
82
- assert selection.pacer == PACER_PORTABLE, each_skill
83
-
84
-
85
- def test_unknown_entry_skill_raises() -> None:
86
- with pytest.raises(ValueError, match="entry skill must be one of"):
87
- pacer_module.select_converge_pacer(
88
- entry_skill="bugteam",
89
- has_workflow=False,
90
- has_schedule_wakeup=False,
91
- )
92
-
93
-
94
- def test_parse_bool_flag_accepts_common_tokens() -> None:
95
- assert pacer_module.parse_bool_flag("1") is True
96
- assert pacer_module.parse_bool_flag("true") is True
97
- assert pacer_module.parse_bool_flag("YES") is True
98
- assert pacer_module.parse_bool_flag("0") is False
99
- assert pacer_module.parse_bool_flag("false") is False
100
- assert pacer_module.parse_bool_flag("OFF") is False
101
-
102
-
103
- def test_parse_bool_flag_rejects_unknown_token() -> None:
104
- with pytest.raises(ValueError, match="boolean token"):
105
- pacer_module.parse_bool_flag("maybe")
106
-
107
-
108
- def test_selection_as_json_dict_uses_stable_keys() -> None:
109
- selection = pacer_module.select_converge_pacer(
110
- entry_skill=ENTRY_SKILL_PR_CONVERGE,
111
- has_workflow=False,
112
- has_schedule_wakeup=False,
113
- )
114
- payload = pacer_module.selection_as_json_dict(selection)
115
- assert payload[RESULT_KEY_PACER] == PACER_PORTABLE
116
- assert payload[RESULT_KEY_ENTRY_SKILL] == ENTRY_SKILL_PR_CONVERGE
117
- assert payload[RESULT_KEY_HAS_WORKFLOW] is False
118
- assert payload[RESULT_KEY_HAS_SCHEDULE_WAKEUP] is False
119
-
120
-
121
- def test_cli_prints_json_and_exits_zero() -> None:
122
- completed = subprocess.run(
123
- [
124
- sys.executable,
125
- str(SCRIPT_PATH),
126
- "--skill",
127
- ENTRY_SKILL_AUTOCONVERGE,
128
- "--has-workflow",
129
- "0",
130
- "--has-schedule-wakeup",
131
- "0",
132
- ],
133
- check=False,
134
- capture_output=True,
135
- text=True,
136
- )
137
- assert completed.returncode == EXIT_SUCCESS, completed.stderr
138
- payload = json.loads(completed.stdout)
139
- assert payload[RESULT_KEY_PACER] == PACER_PORTABLE
140
- assert payload[RESULT_KEY_ENTRY_SKILL] == ENTRY_SKILL_AUTOCONVERGE
141
-
142
-
143
- def test_cli_rejects_bad_bool_with_usage_exit() -> None:
144
- completed = subprocess.run(
145
- [
146
- sys.executable,
147
- str(SCRIPT_PATH),
148
- "--skill",
149
- ENTRY_SKILL_PR_CONVERGE,
150
- "--has-workflow",
151
- "nope",
152
- "--has-schedule-wakeup",
153
- "0",
154
- ],
155
- check=False,
156
- capture_output=True,
157
- text=True,
158
- )
159
- assert completed.returncode == EXIT_USAGE_ERROR
160
- assert "boolean token" in completed.stderr
161
-
162
-
163
- def test_main_returns_usage_error_on_value_error(
164
- monkeypatch: pytest.MonkeyPatch,
165
- ) -> None:
166
- def raise_value_error(**_kwargs: object) -> object:
167
- raise ValueError("entry skill must be one of")
168
-
169
- monkeypatch.setattr(
170
- pacer_module, "select_converge_pacer", raise_value_error
171
- )
172
- exit_code = pacer_module.main(
173
- [
174
- "--skill",
175
- ENTRY_SKILL_PR_CONVERGE,
176
- "--has-workflow",
177
- "0",
178
- "--has-schedule-wakeup",
179
- "0",
180
- ]
181
- )
182
- assert exit_code == EXIT_USAGE_ERROR
183
-
184
-
185
- def test_build_argument_parser_requires_skill_and_host_flags() -> None:
186
- parser = pacer_module.build_argument_parser()
187
- all_option_strings = {
188
- each_option
189
- for each_action in parser._actions
190
- for each_option in each_action.option_strings
191
- }
192
- assert CLI_SKILL_FLAG in all_option_strings
193
- assert CLI_HAS_WORKFLOW_FLAG in all_option_strings
194
- assert CLI_HAS_SCHEDULE_WAKEUP_FLAG in all_option_strings
195
- parsed_namespace = parser.parse_args(
196
- [
197
- CLI_SKILL_FLAG,
198
- ENTRY_SKILL_AUTOCONVERGE,
199
- CLI_HAS_WORKFLOW_FLAG,
200
- "1",
201
- CLI_HAS_SCHEDULE_WAKEUP_FLAG,
202
- "0",
203
- ]
204
- )
205
- assert parsed_namespace.skill == ENTRY_SKILL_AUTOCONVERGE
206
- assert parsed_namespace.has_workflow == "1"
207
- assert parsed_namespace.has_schedule_wakeup == "0"
@@ -1,59 +0,0 @@
1
- """Tests for teardown_worktrees.teardown_run consuming the typed workspace."""
2
-
3
- from __future__ import annotations
4
-
5
- import importlib.util
6
- import sys
7
- from pathlib import Path
8
- from types import ModuleType
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
-
15
- def _load_teardown_module() -> ModuleType:
16
- module_path = _SCRIPTS_DIR / "teardown_worktrees.py"
17
- spec = importlib.util.spec_from_file_location("teardown_worktrees", module_path)
18
- assert spec is not None
19
- assert spec.loader is not None
20
- module = importlib.util.module_from_spec(spec)
21
- spec.loader.exec_module(module)
22
- return module
23
-
24
-
25
- teardown_worktrees = _load_teardown_module()
26
-
27
-
28
- def test_teardown_run_returns_zero_when_no_worktrees_exist(tmp_path: Path) -> None:
29
- """With absent worktrees, teardown_run removes nothing and reports zero,
30
- reading each worktree path from the typed PerPrWorkspace.worktree attribute
31
- rather than a dict lookup."""
32
- run_temp_dir = tmp_path / "run"
33
- run_temp_dir.mkdir()
34
- all_pr_entries: list[dict[str, object]] = [
35
- {"number": 7, "owner": "owner", "repo": "repo"},
36
- ]
37
- removed_count = teardown_worktrees.teardown_run(
38
- run_temp_dir=run_temp_dir,
39
- all_pr_entries=all_pr_entries,
40
- )
41
- assert removed_count == 0
42
- assert not run_temp_dir.exists()
43
-
44
-
45
- def test_teardown_run_skips_entries_without_integer_number(tmp_path: Path) -> None:
46
- """A PR entry whose number is not an integer is skipped before any workspace
47
- resolution, so teardown_run reports zero removals and still clears the run
48
- temp directory."""
49
- run_temp_dir = tmp_path / "run"
50
- run_temp_dir.mkdir()
51
- all_pr_entries: list[dict[str, object]] = [
52
- {"number": "not-an-int", "owner": "owner", "repo": "repo"},
53
- ]
54
- removed_count = teardown_worktrees.teardown_run(
55
- run_temp_dir=run_temp_dir,
56
- all_pr_entries=all_pr_entries,
57
- )
58
- assert removed_count == 0
59
- assert not run_temp_dir.exists()