claude-dev-env 4.3.0 → 7.1.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 (480) 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 +5 -4
  12. package/.agents/skills/pull-request/SKILL.md +11 -13
  13. package/.agents/skills/pull-request/reference/publication-tasks.md +3 -3
  14. package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +9 -1
  15. package/.agents/skills/pull-request/scripts/pull_request.py +35 -44
  16. package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +9 -0
  17. package/.agents/skills/pull-request/scripts/test_pull_request.py +35 -3
  18. package/.agents/skills/session-continuity/README.md +189 -0
  19. package/.agents/skills/session-continuity/SKILL.md +114 -0
  20. package/.agents/skills/session-continuity/continuity.mjs +375 -0
  21. package/.agents/skills/session-continuity/continuity.test.mjs +303 -0
  22. package/.agents/skills/skill-builder/SKILL.md +3 -196
  23. package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +0 -7
  24. package/.agents/skills/windows-scheduled-task/SKILL.md +153 -0
  25. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
  26. package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
  27. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
  28. package/bin/cde.mjs +36 -8
  29. package/bin/cde.test.mjs +48 -0
  30. package/bin/ever-shipped-skills.mjs +2 -20
  31. package/bin/ever-shipped-skills.test.mjs +8 -0
  32. package/bin/expand_home_directory_tokens.mjs +4 -5
  33. package/bin/expand_home_directory_tokens.test.mjs +128 -0
  34. package/bin/git_hooks_installer.mjs +22 -3
  35. package/bin/git_hooks_installer.test.mjs +159 -5
  36. package/bin/install-session-continuity.mjs +78 -0
  37. package/bin/install-session-continuity.test.mjs +42 -0
  38. package/bin/install.agents-home.test.mjs +15 -13
  39. package/bin/install.codex-rules.test.mjs +5 -2
  40. package/bin/install.cursor-rules.test.mjs +5 -2
  41. package/bin/install.mjs +506 -63
  42. package/bin/install.policy-lint.test.mjs +130 -0
  43. package/bin/install.profiles.test.mjs +10 -0
  44. package/bin/install.prune.test.mjs +286 -37
  45. package/bin/install.pstack-plugin.test.mjs +114 -0
  46. package/bin/install.test.mjs +537 -120
  47. package/bin/install.transaction.test.mjs +3 -3
  48. package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
  49. package/docs/CODE_RULES.md +1 -1
  50. package/hooks/advisory/pr_done_reminder.py +342 -0
  51. package/hooks/advisory/test_pr_done_reminder.py +249 -0
  52. package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
  53. package/hooks/blocking/code_rules_banned_identifiers.py +3 -0
  54. package/hooks/blocking/code_rules_paired_test.py +22 -15
  55. package/hooks/blocking/precommit_code_rules_gate.py +5 -8
  56. package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +7 -52
  57. package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
  58. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -69
  59. package/hooks/blocking/test_code_rules_banned_identifiers.py +64 -0
  60. package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
  61. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
  62. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
  63. package/hooks/blocking/test_pre_tool_use_dispatcher.py +43 -342
  64. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
  65. package/hooks/blocking/test_shared_stdin_adoption.py +1 -47
  66. package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
  67. package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +116 -0
  68. package/hooks/git-hooks/post_commit.py +33 -0
  69. package/hooks/git-hooks/pre_commit.py +18 -49
  70. package/hooks/git-hooks/pre_push.py +45 -541
  71. package/hooks/git-hooks/test_installed_policy_lint.py +208 -0
  72. package/hooks/git-hooks/test_native_hook_support.py +129 -0
  73. package/hooks/git-hooks/test_native_policy_commit.py +120 -0
  74. package/hooks/git-hooks/test_post_commit.py +43 -0
  75. package/hooks/git-hooks/test_pre_commit.py +38 -148
  76. package/hooks/git-hooks/test_pre_push.py +48 -1631
  77. package/hooks/git-hooks/test_verification_notice.py +60 -0
  78. package/hooks/git-hooks/test_verification_start.py +173 -0
  79. package/hooks/git-hooks/verification_notice.py +192 -0
  80. package/hooks/git-hooks/verification_notice_context.py +253 -0
  81. package/hooks/git-hooks/verification_notice_state.py +237 -0
  82. package/hooks/git-hooks/verification_start.py +100 -0
  83. package/hooks/hooks.json +1 -120
  84. package/hooks/hooks_constants/banned_identifiers_constants.py +4 -0
  85. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
  86. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +1 -15
  87. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -4
  88. package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
  89. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -93
  90. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -4
  91. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
  92. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +3 -66
  93. package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
  94. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +46 -201
  95. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +3 -25
  96. package/hooks/validation/test_post_tool_use_dispatcher.py +35 -298
  97. package/hooks/validators/run_all_validators.py +5 -1
  98. package/hooks/validators/security_checks.py +57 -2
  99. package/hooks/validators/test_hook_timing_harness.py +2 -5
  100. package/hooks/validators/test_run_all_validators_mutation_tool_parity.py +3 -11
  101. package/hooks/validators/test_run_all_validators_policy_lint.py +36 -0
  102. package/hooks/validators/test_security_checks.py +57 -0
  103. package/package.json +2 -2
  104. package/rules/confirm-implementation-forks.md +2 -0
  105. package/rules/durable-post-artifacts.md +2 -1
  106. package/rules/git-workflow.md +18 -6
  107. package/rules/pstack-host-mapping.md +48 -0
  108. package/rules/vault-context.md +3 -5
  109. package/rules/verify-runtime-state.md +7 -0
  110. package/scripts/audit-hooks-cli.mjs +5 -0
  111. package/scripts/audit-hooks.mjs +72 -16
  112. package/scripts/automatic_advisory/__init__.py +1 -0
  113. package/scripts/automatic_advisory/checkout.py +51 -0
  114. package/scripts/automatic_advisory/cli.py +334 -0
  115. package/scripts/automatic_advisory/config/__init__.py +1 -0
  116. package/scripts/automatic_advisory/config/constants.py +93 -0
  117. package/scripts/automatic_advisory/config/timing.py +4 -0
  118. package/scripts/automatic_advisory/configuration.py +197 -0
  119. package/scripts/automatic_advisory/execution.py +350 -0
  120. package/scripts/automatic_advisory/git.py +69 -0
  121. package/scripts/automatic_advisory/model.py +107 -0
  122. package/scripts/automatic_advisory/process_host.py +32 -0
  123. package/scripts/automatic_advisory/publisher.py +84 -0
  124. package/scripts/automatic_advisory/runner.py +399 -0
  125. package/scripts/automatic_advisory/state.py +116 -0
  126. package/scripts/automatic_advisory/window_flags.py +41 -0
  127. package/scripts/automatic_advisory/windows_job.py +122 -0
  128. package/scripts/check.ps1 +0 -1
  129. package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
  130. package/scripts/ci/installer-lifecycle.test.mjs +26 -0
  131. package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
  132. package/scripts/codex_compat_materializer.py +99 -13
  133. package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
  134. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +35 -43
  135. package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +10 -10
  136. package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +14 -1
  137. package/scripts/local_report_cli.py +184 -0
  138. package/scripts/local_report_core.py +247 -0
  139. package/scripts/local_report_publisher.py +12 -0
  140. package/scripts/local_report_validation.py +357 -0
  141. package/scripts/local_verification/__init__.py +23 -0
  142. package/scripts/local_verification/check_runner.py +364 -0
  143. package/scripts/local_verification/check_support.py +99 -0
  144. package/scripts/local_verification/cli.py +158 -0
  145. package/scripts/local_verification/command_runner.py +84 -0
  146. package/scripts/local_verification/config/__init__.py +1 -0
  147. package/scripts/local_verification/config/constants.py +89 -0
  148. package/scripts/local_verification/config/timing.py +1 -0
  149. package/scripts/local_verification/git_state.py +146 -0
  150. package/scripts/local_verification/manifest.py +224 -0
  151. package/scripts/local_verification/model.py +174 -0
  152. package/scripts/local_verification/runner.py +234 -0
  153. package/scripts/policy_lint/adapter_detectors.py +13 -6
  154. package/scripts/policy_lint/adapter_pairing.py +58 -3
  155. package/scripts/policy_lint/adapters.py +7 -4
  156. package/scripts/policy_lint/config/approved_test_pairs.py +323 -0
  157. package/scripts/policy_lint/config/constants.py +5 -0
  158. package/scripts/policy_lint/engine.py +48 -4
  159. package/scripts/policy_lint/model.py +1 -0
  160. package/scripts/policy_lint/registry.py +1 -1
  161. package/scripts/policy_lint/selection.py +2 -1
  162. package/scripts/policy_lint/selection_git.py +2 -0
  163. package/scripts/pr_verification/__init__.py +1 -0
  164. package/scripts/pr_verification/branch_refs.py +114 -0
  165. package/scripts/pr_verification/config/__init__.py +1 -0
  166. package/scripts/pr_verification/config/constants.py +84 -0
  167. package/scripts/pr_verification/config/timing.py +5 -0
  168. package/scripts/pr_verification/github.py +137 -0
  169. package/scripts/pr_verification/github_api.py +376 -0
  170. package/scripts/pr_verification/github_labels.py +88 -0
  171. package/scripts/pr_verification/github_parsing.py +182 -0
  172. package/scripts/pr_verification/github_transport.py +91 -0
  173. package/scripts/pr_verification/lock.py +122 -0
  174. package/scripts/pr_verification/model.py +43 -0
  175. package/scripts/pr_verification/requirements.txt +1 -0
  176. package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
  177. package/scripts/shared_tree_paths.py +32 -3
  178. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +97 -0
  179. package/scripts/test_shared_tree_paths.py +33 -0
  180. package/scripts/tests/test-audit-hooks-cli.mjs +150 -0
  181. package/scripts/tests/test-audit-hooks.mjs +94 -2
  182. package/scripts/tests/test_automatic_advisory.py +376 -0
  183. package/scripts/tests/test_automatic_advisory_job_cleanup.py +71 -0
  184. package/scripts/tests/test_automatic_advisory_polling.py +216 -0
  185. package/scripts/tests/test_automatic_advisory_recovery.py +320 -0
  186. package/scripts/tests/test_automatic_advisory_repairs.py +400 -0
  187. package/scripts/tests/test_automatic_advisory_settings.py +48 -0
  188. package/scripts/tests/test_automatic_advisory_window_flags.py +163 -0
  189. package/scripts/tests/test_closed_pr_label.py +157 -0
  190. package/scripts/tests/test_codex_compat_materializer.py +189 -6
  191. package/scripts/tests/test_github_labels.py +101 -0
  192. package/scripts/tests/test_github_transport.py +125 -0
  193. package/scripts/tests/test_local_report_publisher.py +396 -0
  194. package/scripts/tests/test_local_report_publisher_cli.py +85 -0
  195. package/scripts/tests/test_local_verification.py +348 -0
  196. package/scripts/tests/test_local_verification_cli.py +98 -0
  197. package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
  198. package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
  199. package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
  200. package/scripts/tests/test_policy_lint_rules_pairing.py +163 -0
  201. package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
  202. package/scripts/tests/test_policy_lint_selection.py +25 -2
  203. package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
  204. package/scripts/tests/test_pr_verification_github.py +392 -0
  205. package/scripts/tests/test_pr_verification_lock.py +168 -0
  206. package/scripts/tests/test_rules.py +3 -7
  207. package/scripts/tests/test_verification_notice.py +347 -0
  208. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
  209. package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
  210. package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
  211. package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
  212. package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
  213. package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
  214. package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
  215. package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
  216. package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
  217. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
  218. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
  219. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
  220. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
  221. package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
  222. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
  223. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
  224. package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
  225. package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
  226. package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
  227. package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
  228. package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
  229. package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
  230. package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
  231. package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
  232. package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
  233. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
  234. package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
  235. package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
  236. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
  237. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
  238. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
  239. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
  240. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
  241. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
  242. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
  243. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
  244. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
  245. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
  246. package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
  247. package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
  248. package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
  249. package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
  250. package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
  251. package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
  252. package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
  253. package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
  254. package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
  255. package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
  256. package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
  257. package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
  258. package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
  259. package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
  260. package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
  261. package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
  262. package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
  263. package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
  264. package/.agents/skills/autoconverge/AGENTS.md +0 -1
  265. package/.agents/skills/autoconverge/SKILL.md +0 -431
  266. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
  267. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
  268. package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
  269. package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
  270. package/.agents/skills/autoconverge/reference/convergence.md +0 -219
  271. package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
  272. package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
  273. package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
  274. package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
  275. package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
  276. package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
  277. package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
  278. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
  279. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
  280. package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
  281. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
  282. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
  283. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
  284. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
  285. package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
  286. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
  287. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
  288. package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
  289. package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
  290. package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
  291. package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
  292. package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
  293. package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
  294. package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
  295. package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
  296. package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
  297. package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
  298. package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
  299. package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
  300. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
  301. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
  302. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
  303. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
  304. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
  305. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
  306. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
  307. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
  308. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
  309. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
  310. package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
  311. package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
  312. package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
  313. package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
  314. package/.agents/skills/hitl/SKILL.md +0 -45
  315. package/.agents/skills/pr-cleanup/SKILL.md +0 -140
  316. package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
  317. package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
  318. package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
  319. package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
  320. package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
  321. package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
  322. package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
  323. package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
  324. package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
  325. package/.agents/skills/pr-refinement/SKILL.md +0 -31
  326. package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
  327. package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
  328. package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
  329. package/.agents/skills/pr-small-cl/SKILL.md +0 -52
  330. package/.agents/skills/pr-title-description/SKILL.md +0 -96
  331. package/.agents/skills/prototype/SKILL.md +0 -85
  332. package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
  333. package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
  334. package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
  335. package/.agents/skills/prototype/scripts/conftest.py +0 -15
  336. package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
  337. package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
  338. package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
  339. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  340. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
  341. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
  342. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
  343. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
  344. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
  345. package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
  346. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
  347. package/.agents/skills/prototype/workflows/promotion.md +0 -25
  348. package/.agents/skills/prototype/workflows/sandbox.md +0 -35
  349. package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
  350. package/.agents/skills/rebase/AGENTS.md +0 -1
  351. package/.agents/skills/rebase/SKILL.md +0 -178
  352. package/.agents/skills/review-router/SKILL.md +0 -51
  353. package/.agents/skills/review-router/reference/route-policy.json +0 -7
  354. package/.agents/skills/review-router/reference/task-seeds.md +0 -1
  355. package/.agents/skills/review-router/scripts/conftest.py +0 -4
  356. package/.agents/skills/review-router/scripts/review_router.py +0 -50
  357. package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
  358. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
  359. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  360. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
  361. package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
  362. package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
  363. package/.agents/skills/review-tier/SKILL.md +0 -56
  364. package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
  365. package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
  366. package/.agents/skills/review-tier/scripts/conftest.py +0 -4
  367. package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
  368. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
  369. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  370. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
  371. package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
  372. package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
  373. package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
  374. package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
  375. package/.agents/skills/session-log/AGENTS.md +0 -1
  376. package/.agents/skills/session-log/SKILL.md +0 -170
  377. package/.agents/skills/session-log/templates/frontmatter.md +0 -40
  378. package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
  379. package/.agents/skills/session-tidy/AGENTS.md +0 -1
  380. package/.agents/skills/session-tidy/SKILL.md +0 -191
  381. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
  382. package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
  383. package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
  384. package/.agents/skills/skill-builder/references/description-field.md +0 -111
  385. package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
  386. package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
  387. package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
  388. package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
  389. package/.agents/skills/skill-builder/references/skill-types.md +0 -232
  390. package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
  391. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
  392. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
  393. package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
  394. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
  395. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
  396. package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
  397. package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
  398. package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
  399. package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
  400. package/.agents/skills/update/.claude/CLAUDE.md +0 -1
  401. package/.agents/skills/update/AGENTS.md +0 -1
  402. package/.agents/skills/update/SKILL.md +0 -190
  403. package/_shared/pr-loop/AGENTS.md +0 -1
  404. package/_shared/pr-loop/audit-contract.md +0 -183
  405. package/_shared/pr-loop/audit-reply-template.md +0 -151
  406. package/_shared/pr-loop/code-rules-gate.md +0 -65
  407. package/_shared/pr-loop/fix-protocol.md +0 -60
  408. package/_shared/pr-loop/gh-payloads.md +0 -75
  409. package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
  410. package/_shared/pr-loop/precatch-rubric.md +0 -66
  411. package/_shared/pr-loop/preflight-proposal.md +0 -56
  412. package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
  413. package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
  414. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
  415. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
  416. package/_shared/pr-loop/state-schema.md +0 -45
  417. package/_shared/pr-loop/worker-spawn.md +0 -189
  418. package/hooks/blocking/ask_user_question_shape_blocker.py +0 -83
  419. package/hooks/blocking/bot_mention_comment_blocker.py +0 -76
  420. package/hooks/blocking/claude_md_orphan_file_blocker.py +0 -129
  421. package/hooks/blocking/cursor_cli_python_misfire_blocker.py +0 -108
  422. package/hooks/blocking/destructive_command_blocker.py +0 -2073
  423. package/hooks/blocking/fable_spawn_gate.py +0 -187
  424. package/hooks/blocking/luna_fast_mode_gate.py +0 -160
  425. package/hooks/blocking/nas_ssh_binary_enforcer.py +0 -163
  426. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +0 -260
  427. package/hooks/blocking/package_inventory_stale_blocker.py +0 -107
  428. package/hooks/blocking/pii_prevention_blocker.py +0 -365
  429. package/hooks/blocking/piped_pytest_blocker.py +0 -1223
  430. package/hooks/blocking/question_to_user_enforcer.py +0 -130
  431. package/hooks/blocking/send_user_file_open_locally_blocker.py +0 -71
  432. package/hooks/blocking/sensitive_file_protector.py +0 -167
  433. package/hooks/blocking/session_edit_stage_gate.py +0 -684
  434. package/hooks/blocking/session_handoff_blocker.py +0 -182
  435. package/hooks/blocking/shell_substitution_blocker.py +0 -350
  436. package/hooks/blocking/test_ask_user_question_shape.py +0 -69
  437. package/hooks/blocking/test_bot_mention_comment_blocker.py +0 -131
  438. package/hooks/blocking/test_claude_md_orphan_file_blocker.py +0 -1277
  439. package/hooks/blocking/test_cursor_cli_python_misfire_blocker.py +0 -208
  440. package/hooks/blocking/test_destructive_command_blocker.py +0 -2024
  441. package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +0 -105
  442. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +0 -122
  443. package/hooks/blocking/test_destructive_command_blocker_patterns.py +0 -133
  444. package/hooks/blocking/test_fable_spawn_gate.py +0 -381
  445. package/hooks/blocking/test_inventory_deadlock_resolution.py +0 -154
  446. package/hooks/blocking/test_luna_fast_mode_gate.py +0 -211
  447. package/hooks/blocking/test_nas_ssh_binary_enforcer.py +0 -225
  448. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +0 -231
  449. package/hooks/blocking/test_package_inventory_stale_blocker.py +0 -382
  450. package/hooks/blocking/test_pii_prevention_blocker.py +0 -1222
  451. package/hooks/blocking/test_pii_prevention_windows_git_path.py +0 -41
  452. package/hooks/blocking/test_pii_write_surface_ephemeral.py +0 -221
  453. package/hooks/blocking/test_piped_pytest_blocker.py +0 -587
  454. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -233
  455. package/hooks/blocking/test_question_to_user_enforcer.py +0 -169
  456. package/hooks/blocking/test_send_user_file_open_locally_blocker.py +0 -118
  457. package/hooks/blocking/test_sensitive_file_protector.py +0 -365
  458. package/hooks/blocking/test_session_edit_stage_gate.py +0 -537
  459. package/hooks/blocking/test_session_edit_stage_gate_staging.py +0 -64
  460. package/hooks/blocking/test_session_edit_stage_gate_support.py +0 -204
  461. package/hooks/blocking/test_session_edit_stage_gate_tracker.py +0 -116
  462. package/hooks/blocking/test_session_handoff_blocker.py +0 -318
  463. package/hooks/blocking/test_shell_substitution_blocker.py +0 -298
  464. package/hooks/blocking/test_unscoped_search_blocker.py +0 -102
  465. package/hooks/blocking/test_write_existing_file_blocker.py +0 -122
  466. package/hooks/blocking/tests/test_pii_prevention_blocker.py +0 -259
  467. package/hooks/blocking/unscoped_search_blocker.py +0 -391
  468. package/hooks/blocking/write_existing_file_blocker.py +0 -124
  469. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +0 -19
  470. package/hooks/hooks_constants/cursor_cli_python_misfire_blocker_constants.py +0 -79
  471. package/hooks/hooks_constants/fable_spawn_gate_constants.py +0 -61
  472. package/hooks/hooks_constants/luna_fast_mode_gate_constants.py +0 -45
  473. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +0 -20
  474. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +0 -57
  475. package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +0 -17
  476. package/hooks/hooks_constants/sensitive_file_protector_constants.py +0 -40
  477. package/hooks/hooks_constants/session_handoff_blocker_constants.py +0 -10
  478. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +0 -80
  479. /package/.agents/skills/{_shared/pr-loop → session-continuity}/AGENTS.md +0 -0
  480. /package/{_shared/pr-loop → .agents/skills/session-continuity}/CLAUDE.md +0 -0
@@ -1,8 +1,9 @@
1
1
  """Constants for the PreToolUse dispatcher that hosts Write/Edit/MultiEdit hooks.
2
2
 
3
- Holds the ordered hosted-hook list with per-hook applicable-tool sets, the
4
- special exit codes, the deny decision string, and the hook-event name. The
5
- dispatcher imports each of these by name.
3
+ The roster keeps action-boundary checks, repository checks, and checks without
4
+ a proven local replacement. File-policy rules with a staged replacement run
5
+ through cde lint in native pre-commit. Their detectors stay importable for that
6
+ linter. Bash cleanup protection uses its own roster.
6
7
  """
7
8
 
8
9
  from __future__ import annotations
@@ -25,7 +26,6 @@ __all__ = [
25
26
  "ALL_WRITE_AND_EDIT_TOOL_NAMES",
26
27
  "ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES",
27
28
  "ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES",
28
- "ALL_IMMEDIATE_HARM_SCRIPT_PATHS",
29
29
  "STATE_DESCRIPTION_BLOCKER_MODULE_NAME",
30
30
  "SYSTEM_MESSAGE_JOIN_SEPARATOR",
31
31
  "HostedHookEntry",
@@ -55,15 +55,6 @@ ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES: frozenset[str] = frozenset(
55
55
  ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES | {APPLY_PATCH_TOOL_NAME}
56
56
  )
57
57
 
58
- # apply_patch reaches this narrower roster: the gates whose miss causes immediate
59
- # harm, plus the TDD gate and the edit tracker. It stays off the full lint surface.
60
- ALL_IMMEDIATE_HARM_SCRIPT_PATHS: tuple[str, ...] = (
61
- "blocking/pii_prevention_blocker.py",
62
- "blocking/sensitive_file_protector.py",
63
- "blocking/write_existing_file_blocker.py",
64
- "blocking/code_rules_enforcer.py",
65
- "blocking/tdd_enforcer.py",
66
- )
67
58
 
68
59
 
69
60
  STATE_DESCRIPTION_BLOCKER_MODULE_NAME = "state_description_blocker"
@@ -71,19 +62,18 @@ STATE_DESCRIPTION_BLOCKER_MODULE_NAME = "state_description_blocker"
71
62
 
72
63
  @dataclass(frozen=True)
73
64
  class HostedHookEntry:
74
- """A single hosted hook with its applicable-tools constraint and blocking flag.
65
+ """One hosted hook, the tools it applies to, and whether a crash blocks.
75
66
 
76
67
  Attributes:
77
68
  script_relative_path: Hook path relative to the hooks/ directory.
78
69
  applicable_tool_names: Tool names this hook applies to. The dispatcher
79
70
  skips the hook when the payload's tool is not in this set.
80
- is_blocking: True when a crash surfaces a blocking signal; False when the
71
+ is_blocking: True when a crash is a blocking signal. False when the
81
72
  hook is advisory and a crash stays silent.
82
- native_module_name: The importable module name whose evaluate function
83
- the dispatcher calls in-process for this hook, or None when the hook
84
- runs via runpy under __main__. The named module exposes a function
85
- named `evaluate` taking the payload dict and returning a deny-reason
86
- string or None.
73
+ native_module_name: Importable module whose evaluate function the
74
+ dispatcher calls in-process, or None when the hook runs via runpy
75
+ under __main__. evaluate takes the payload dict and returns a
76
+ deny-reason string or None.
87
77
  """
88
78
 
89
79
  script_relative_path: str
@@ -93,79 +83,6 @@ class HostedHookEntry:
93
83
 
94
84
 
95
85
  ALL_HOSTED_HOOK_ENTRIES: tuple[HostedHookEntry, ...] = (
96
- HostedHookEntry(
97
- script_relative_path="blocking/write_existing_file_blocker.py",
98
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
99
- ),
100
- HostedHookEntry(
101
- script_relative_path="blocking/sensitive_file_protector.py",
102
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
103
- ),
104
- HostedHookEntry(
105
- script_relative_path="blocking/pii_prevention_blocker.py",
106
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
107
- ),
108
- HostedHookEntry(
109
- script_relative_path="validation/hook_format_validator.py",
110
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
111
- ),
112
- HostedHookEntry(
113
- script_relative_path="blocking/code_rules_enforcer.py",
114
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
115
- ),
116
- HostedHookEntry(
117
- script_relative_path="blocking/tdd_enforcer.py",
118
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
119
- ),
120
- HostedHookEntry(
121
- script_relative_path="blocking/windows_rmtree_blocker.py",
122
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
123
- ),
124
- HostedHookEntry(
125
- script_relative_path="blocking/duplicate_rmtree_helper_blocker.py",
126
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
127
- ),
128
- HostedHookEntry(
129
- script_relative_path="blocking/state_description_blocker.py",
130
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
131
- native_module_name=STATE_DESCRIPTION_BLOCKER_MODULE_NAME,
132
- ),
133
- HostedHookEntry(
134
- script_relative_path="blocking/subprocess_budget_completeness.py",
135
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
136
- ),
137
- HostedHookEntry(
138
- script_relative_path="blocking/hook_prose_detector_consistency.py",
139
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
140
- ),
141
- HostedHookEntry(
142
- script_relative_path="blocking/workflow_substitution_slot_blocker.py",
143
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
144
- ),
145
- HostedHookEntry(
146
- script_relative_path="blocking/claude_md_orphan_file_blocker.py",
147
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
148
- ),
149
- HostedHookEntry(
150
- script_relative_path="blocking/package_inventory_stale_blocker.py",
151
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
152
- ),
153
- HostedHookEntry(
154
- script_relative_path="blocking/env_var_table_code_drift_blocker.py",
155
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
156
- ),
157
- HostedHookEntry(
158
- script_relative_path="blocking/pytest_testpaths_orphan_blocker.py",
159
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
160
- ),
161
- HostedHookEntry(
162
- script_relative_path="blocking/open_questions_in_plans_blocker.py",
163
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
164
- ),
165
- HostedHookEntry(
166
- script_relative_path="blocking/docstring_rule_gate_count_blocker.py",
167
- applicable_tool_names=ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
168
- ),
169
86
  HostedHookEntry(
170
87
  script_relative_path="advisory/refactor_guard.py",
171
88
  applicable_tool_names=frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME}),
@@ -17,7 +17,4 @@ BLOCK_DECISION = "block"
17
17
  DECISION_KEY = "decision"
18
18
  REASON_KEY = "reason"
19
19
 
20
- ALL_STOP_HOSTED_HOOK_PATHS: tuple[str, ...] = (
21
- "blocking/question_to_user_enforcer.py",
22
- "blocking/session_handoff_blocker.py",
23
- )
20
+ ALL_STOP_HOSTED_HOOK_PATHS: tuple[str, ...] = ()
@@ -1,16 +1,33 @@
1
1
  """Behavioral tests for the Bash PostToolUse dispatcher's hosted-hook roster."""
2
2
 
3
+ from hooks_constants import bash_post_call_dispatcher_constants as constants
3
4
  from hooks_constants.bash_post_call_dispatcher_constants import (
4
5
  ALL_BASH_POST_TOOL_USE_HOSTED_HOOK_ENTRIES,
5
6
  )
6
7
  from hooks_constants.bash_pre_tool_use_dispatcher_constants import BASH_TOOL_NAME
7
8
 
8
9
 
9
- def test_roster_names_the_test_failure_recorder_hook() -> None:
10
+ def test_roster_runs_the_recorder_then_the_pr_done_reminder() -> None:
10
11
  all_script_paths = [
11
12
  each_entry.script_relative_path for each_entry in ALL_BASH_POST_TOOL_USE_HOSTED_HOOK_ENTRIES
12
13
  ]
13
- assert "observability/test_failure_recorder.py" in all_script_paths
14
+ assert all_script_paths == [
15
+ "observability/test_failure_recorder.py",
16
+ "advisory/pr_done_reminder.py",
17
+ ]
18
+
19
+
20
+ def test_pr_done_reminder_also_serves_the_powershell_tool() -> None:
21
+ reminder_entry = ALL_BASH_POST_TOOL_USE_HOSTED_HOOK_ENTRIES[-1]
22
+ assert reminder_entry.script_relative_path == "advisory/pr_done_reminder.py"
23
+ assert "PowerShell" in reminder_entry.applicable_tool_names
24
+
25
+
26
+ def test_context_forwarding_keys_match_the_hook_output_contract() -> None:
27
+ assert constants.POST_TOOL_USE_HOOK_EVENT_NAME == "PostToolUse"
28
+ assert constants.HOOK_SPECIFIC_OUTPUT_KEY == "hookSpecificOutput"
29
+ assert constants.ADDITIONAL_CONTEXT_KEY == "additionalContext"
30
+ assert constants.ADDITIONAL_CONTEXT_JOIN_SEPARATOR == "\n\n"
14
31
 
15
32
 
16
33
  def test_every_roster_entry_applies_to_bash() -> None:
@@ -1,11 +1,4 @@
1
- """Tests for the Bash and PowerShell dispatcher hosted-hook roster.
2
-
3
- The roster order and per-hook applicable-tool sets fix the firing sequence and
4
- tool coverage the dispatcher must reproduce, so these tests pin both against the
5
- registration order the standalone chain used.
6
- """
7
-
8
- from __future__ import annotations
1
+ """Tests for the Bash and PowerShell dispatcher hosted-hook roster."""
9
2
 
10
3
  from pathlib import Path
11
4
  from runpy import run_path
@@ -13,64 +6,8 @@ from runpy import run_path
13
6
  ALL_CONSTANT_BINDINGS = run_path(
14
7
  str(Path(__file__).with_name("bash_pre_tool_use_dispatcher_constants.py"))
15
8
  )
16
- ALL_BASH_AND_POWERSHELL_TOOL_NAMES = ALL_CONSTANT_BINDINGS["ALL_BASH_AND_POWERSHELL_TOOL_NAMES"]
17
9
  ALL_BASH_HOSTED_HOOK_ENTRIES = ALL_CONSTANT_BINDINGS["ALL_BASH_HOSTED_HOOK_ENTRIES"]
18
- BASH_TOOL_NAME = ALL_CONSTANT_BINDINGS["BASH_TOOL_NAME"]
19
- POWERSHELL_TOOL_NAME = ALL_CONSTANT_BINDINGS["POWERSHELL_TOOL_NAME"]
20
-
21
- _EXPECTED_BASH_ORDER = (
22
- "blocking/destructive_command_blocker.py",
23
- "blocking/shell_substitution_blocker.py",
24
- "blocking/piped_pytest_blocker.py",
25
- "blocking/cursor_cli_python_misfire_blocker.py",
26
- "blocking/unscoped_search_blocker.py",
27
- "blocking/nas_ssh_binary_enforcer.py",
28
- "blocking/pii_prevention_blocker.py",
29
- "blocking/block_main_commit.py",
30
- "blocking/session_edit_stage_gate.py",
31
- "blocking/windows_rmtree_blocker.py",
32
- )
33
-
34
- _POWERSHELL_APPLICABLE = (
35
- "blocking/cursor_cli_python_misfire_blocker.py",
36
- "blocking/unscoped_search_blocker.py",
37
- "blocking/pii_prevention_blocker.py",
38
- )
39
-
40
-
41
- def test_roster_lists_all_bash_hooks_in_registration_order() -> None:
42
- """The roster reproduces the standalone Bash chain order exactly."""
43
- actual_order = tuple(
44
- each_entry.script_relative_path for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES
45
- )
46
- assert actual_order == _EXPECTED_BASH_ORDER
47
-
48
-
49
- def test_every_hook_applies_to_the_bash_tool() -> None:
50
- """Every hosted hook runs on a Bash tool call."""
51
- for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES:
52
- assert BASH_TOOL_NAME in each_entry.applicable_tool_names
53
-
54
-
55
- def test_powershell_applicable_hooks_include_the_shared_gates() -> None:
56
- """PowerShell runs the shared unscoped-search and PII gates."""
57
- powershell_hooks = tuple(
58
- each_entry.script_relative_path
59
- for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES
60
- if POWERSHELL_TOOL_NAME in each_entry.applicable_tool_names
61
- )
62
- assert powershell_hooks == _POWERSHELL_APPLICABLE
63
-
64
-
65
- def test_powershell_hooks_carry_the_shared_tool_set() -> None:
66
- """The PowerShell-applicable hooks name both Bash and PowerShell."""
67
- for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES:
68
- if each_entry.script_relative_path in _POWERSHELL_APPLICABLE:
69
- assert each_entry.applicable_tool_names == ALL_BASH_AND_POWERSHELL_TOOL_NAMES
70
10
 
71
11
 
72
- def test_every_roster_path_points_at_an_existing_hook() -> None:
73
- """Each roster path names a hook script present on disk, catching a typo."""
74
- hooks_root = Path(__file__).resolve().parent.parent
75
- for each_entry in ALL_BASH_HOSTED_HOOK_ENTRIES:
76
- assert (hooks_root / each_entry.script_relative_path).is_file()
12
+ def test_roster_has_no_blocking_hooks() -> None:
13
+ assert ALL_BASH_HOSTED_HOOK_ENTRIES == ()
@@ -0,0 +1,40 @@
1
+ """Pin the PR done reminder's command shape and checklist wording."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from hooks_constants import pr_done_reminder_constants as constants
6
+
7
+
8
+ def test_gh_probe_asks_for_every_field_the_checklist_reads() -> None:
9
+ assert constants.ALL_GH_PR_VIEW_ARGUMENTS[:3] == ("gh", "pr", "view")
10
+ all_requested_fields = constants.ALL_GH_PR_VIEW_ARGUMENTS[-1].split(",")
11
+ for each_field in ("number", "url", "isDraft", "mergeable", "statusCheckRollup", "labels"):
12
+ assert each_field in all_requested_fields
13
+
14
+
15
+ def test_git_global_options_that_take_a_value_are_named() -> None:
16
+ assert constants.ALL_GIT_OPTIONS_WITH_VALUE == frozenset({"-C", "-c"})
17
+
18
+
19
+ def test_powershell_wrappers_and_their_command_flags_are_named() -> None:
20
+ assert "pwsh" in constants.ALL_POWERSHELL_PROGRAM_NAMES
21
+ assert "powershell" in constants.ALL_POWERSHELL_PROGRAM_NAMES
22
+ assert "-command" in constants.ALL_POWERSHELL_COMMAND_FLAGS
23
+ assert "-c" in constants.ALL_POWERSHELL_COMMAND_FLAGS
24
+
25
+
26
+ def test_checklist_lines_join_on_a_single_newline() -> None:
27
+ assert constants.REMINDER_LINE_SEPARATOR == "\n"
28
+
29
+
30
+ def test_every_mergeable_value_has_a_hint() -> None:
31
+ assert set(constants.ALL_REMINDER_HINTS_BY_MERGEABLE) == {
32
+ constants.MERGEABLE_CLEAN_VALUE,
33
+ constants.MERGEABLE_CONFLICTING_VALUE,
34
+ constants.MERGEABLE_UNKNOWN_VALUE,
35
+ }
36
+
37
+
38
+ def test_header_says_it_never_blocks() -> None:
39
+ assert "never a block" in constants.REMINDER_HEADER
40
+ assert "never a block" in constants.NO_PULL_REQUEST_REMINDER
@@ -4,36 +4,24 @@ import importlib
4
4
  import pathlib
5
5
  import sys
6
6
 
7
- try:
8
- _HOOKS_ROOT = pathlib.Path(__file__).resolve().parent.parent
9
- if str(_HOOKS_ROOT) not in sys.path:
10
- sys.path.insert(0, str(_HOOKS_ROOT))
11
-
12
- _BLOCKING_DIR = _HOOKS_ROOT / "blocking"
13
- if str(_BLOCKING_DIR) not in sys.path:
14
- sys.path.insert(0, str(_BLOCKING_DIR))
15
-
16
- from hooks_constants.pre_tool_use_dispatcher_constants import (
17
- ALL_HOSTED_HOOK_ENTRIES,
18
- ALL_IMMEDIATE_HARM_SCRIPT_PATHS,
19
- ALL_WRITE_AND_EDIT_TOOL_NAMES,
20
- ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
21
- ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
22
- APPLY_PATCH_TOOL_NAME,
23
- BLOCKING_CRASH_DENY_REASON,
24
- EDIT_TOOL_NAME,
25
- MULTI_EDIT_TOOL_NAME,
26
- WRITE_TOOL_NAME,
27
- )
28
- from pre_tool_use_dispatcher import (
29
- HostedHookResult,
30
- aggregate_hosted_hook_results,
31
- )
32
- except ImportError as import_error:
33
- raise ImportError(
34
- "test_pre_tool_use_dispatcher_constants: cannot import its sibling modules; "
35
- "ensure the hooks and blocking directories are importable."
36
- ) from import_error
7
+ _HOOKS_ROOT = pathlib.Path(__file__).resolve().parent.parent
8
+ if str(_HOOKS_ROOT) not in sys.path:
9
+ sys.path.insert(0, str(_HOOKS_ROOT))
10
+
11
+ _BLOCKING_DIR = _HOOKS_ROOT / "blocking"
12
+ if str(_BLOCKING_DIR) not in sys.path:
13
+ sys.path.insert(0, str(_BLOCKING_DIR))
14
+
15
+ from hooks_constants.pre_tool_use_dispatcher_constants import (
16
+ ALL_HOSTED_HOOK_ENTRIES,
17
+ ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES,
18
+ ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES,
19
+ APPLY_PATCH_TOOL_NAME,
20
+ BLOCKING_CRASH_DENY_REASON,
21
+ EDIT_TOOL_NAME,
22
+ MULTI_EDIT_TOOL_NAME,
23
+ )
24
+ from pre_tool_use_dispatcher import HostedHookResult, aggregate_hosted_hook_results
37
25
 
38
26
 
39
27
  def _entry_for(script_relative_path: str):
@@ -45,39 +33,44 @@ def _entry_for(script_relative_path: str):
45
33
  return matching_entries[0] if matching_entries else None
46
34
 
47
35
 
48
- def test_roster_includes_duplicate_rmtree_helper_blocker_script_path() -> None:
49
- all_registered_script_paths = [
36
+ def test_roster_keeps_only_nonblocking_edit_advisors() -> None:
37
+ all_script_paths = tuple(
50
38
  each_entry.script_relative_path for each_entry in ALL_HOSTED_HOOK_ENTRIES
51
- ]
52
- assert "blocking/duplicate_rmtree_helper_blocker.py" in all_registered_script_paths, (
53
- "duplicate_rmtree_helper_blocker must be hosted by the dispatcher so a local "
54
- "re-definition of the Windows-safe rmtree helper trio is blocked at Write time"
55
39
  )
40
+ assert all_script_paths == (
41
+ "advisory/refactor_guard.py",
42
+ "advisory/migration_safety_advisor.py",
43
+ )
44
+ assert all(not each_entry.is_blocking for each_entry in ALL_HOSTED_HOOK_ENTRIES)
56
45
 
57
46
 
58
- def test_duplicate_rmtree_helper_blocker_applies_to_write_and_edit() -> None:
59
- entry = _entry_for("blocking/duplicate_rmtree_helper_blocker.py")
60
- assert entry is not None
61
- assert WRITE_TOOL_NAME in entry.applicable_tool_names
62
- assert EDIT_TOOL_NAME in entry.applicable_tool_names
47
+ def test_advisors_apply_to_edit_and_multi_edit() -> None:
48
+ for each_script_path in (
49
+ "advisory/refactor_guard.py",
50
+ "advisory/migration_safety_advisor.py",
51
+ ):
52
+ entry = _entry_for(each_script_path)
53
+ assert entry is not None
54
+ assert entry.applicable_tool_names == frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME})
63
55
 
64
56
 
65
- def test_duplicate_rmtree_helper_blocker_is_blocking() -> None:
66
- entry = _entry_for("blocking/duplicate_rmtree_helper_blocker.py")
67
- assert entry is not None
68
- assert entry.is_blocking is True
57
+ def test_every_hosted_script_path_exists_under_the_hooks_root() -> None:
58
+ for each_entry in ALL_HOSTED_HOOK_ENTRIES:
59
+ hosted_script_path = _HOOKS_ROOT / each_entry.script_relative_path
60
+ assert hosted_script_path.is_file()
69
61
 
70
62
 
71
- def test_duplicate_rmtree_helper_blocker_runs_via_runpy() -> None:
72
- entry = _entry_for("blocking/duplicate_rmtree_helper_blocker.py")
73
- assert entry is not None
74
- assert entry.native_module_name is None
63
+ def test_retired_native_detector_keeps_its_callable_linter_interface() -> None:
64
+ native_module = importlib.import_module("state_description_blocker")
65
+ assert native_module.find_violations("The API uses port 8080.", "guide.md") == []
66
+ assert native_module.find_violations("Previously set via env var.", "guide.md")
67
+ assert all(each_entry.native_module_name is None for each_entry in ALL_HOSTED_HOOK_ENTRIES)
75
68
 
76
69
 
77
- def test_windows_rmtree_blocker_still_registered() -> None:
78
- entry = _entry_for("blocking/windows_rmtree_blocker.py")
79
- assert entry is not None
80
- assert entry.applicable_tool_names == ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES
70
+ def test_four_way_set_covers_every_mutation_tool_name() -> None:
71
+ assert ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES == (
72
+ ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES | {APPLY_PATCH_TOOL_NAME}
73
+ )
81
74
 
82
75
 
83
76
  def test_blocking_hook_crash_deny_reason_surfaces_the_constant() -> None:
@@ -90,151 +83,3 @@ def test_blocking_hook_crash_deny_reason_surfaces_the_constant() -> None:
90
83
  decision = aggregate_hosted_hook_results([crash_result])
91
84
  assert decision.should_deny
92
85
  assert BLOCKING_CRASH_DENY_REASON in decision.all_deny_reasons
93
-
94
-
95
- def test_refactor_guard_is_hosted_as_an_edit_and_multi_edit_advisory_hook() -> None:
96
- entry = _entry_for("advisory/refactor_guard.py")
97
- assert entry is not None, (
98
- "refactor_guard must be hosted by the dispatcher rather than spawning its own process"
99
- )
100
- assert entry.applicable_tool_names == frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME})
101
- assert entry.is_blocking is False
102
-
103
-
104
- def test_migration_safety_advisor_is_hosted_as_an_edit_and_multi_edit_advisory_hook() -> None:
105
- entry = _entry_for("advisory/migration_safety_advisor.py")
106
- assert entry is not None, (
107
- "migration_safety_advisor must be hosted by the dispatcher rather than "
108
- "spawning its own process"
109
- )
110
- assert entry.applicable_tool_names == frozenset({EDIT_TOOL_NAME, MULTI_EDIT_TOOL_NAME})
111
- assert entry.is_blocking is False
112
-
113
-
114
- def test_every_hosted_script_path_exists_under_the_hooks_root() -> None:
115
- for each_entry in ALL_HOSTED_HOOK_ENTRIES:
116
- hosted_script_path = _HOOKS_ROOT / each_entry.script_relative_path
117
- assert hosted_script_path.is_file(), (
118
- f"{each_entry.script_relative_path} is on the roster but missing from the hooks tree"
119
- )
120
-
121
-
122
- def test_every_native_module_exposes_a_callable_evaluate() -> None:
123
- nativized_entries = [
124
- each_entry
125
- for each_entry in ALL_HOSTED_HOOK_ENTRIES
126
- if each_entry.native_module_name is not None
127
- ]
128
- assert nativized_entries, (
129
- "the roster must carry at least one nativized hook for this test to lock the contract"
130
- )
131
- for each_entry in nativized_entries:
132
- native_module = importlib.import_module(each_entry.native_module_name)
133
- evaluate_function = getattr(native_module, "evaluate", None)
134
- assert callable(evaluate_function), (
135
- f"{each_entry.native_module_name} must expose a callable named evaluate, "
136
- "matching the native_module_name docstring contract"
137
- )
138
-
139
-
140
- def test_four_way_set_covers_every_mutation_tool_name() -> None:
141
- assert ALL_WRITE_EDIT_MULTI_EDIT_APPLY_PATCH_TOOL_NAMES == (
142
- ALL_WRITE_EDIT_MULTI_EDIT_TOOL_NAMES | {APPLY_PATCH_TOOL_NAME}
143
- )
144
-
145
-
146
- def test_immediate_harm_hooks_reach_apply_patch() -> None:
147
- """PII, sensitive-path, existing-file, CODE_RULES, and TDD gates all see apply_patch."""
148
- for each_script_path in ALL_IMMEDIATE_HARM_SCRIPT_PATHS:
149
- entry = _entry_for(each_script_path)
150
- assert entry is not None, f"{each_script_path} must stay on the hosted roster"
151
- assert APPLY_PATCH_TOOL_NAME in entry.applicable_tool_names, (
152
- f"{each_script_path} must reach apply_patch for mutation-tool parity"
153
- )
154
-
155
-
156
- _ALL_DEFERRED_LINT_SCRIPT_PATHS = (
157
- "blocking/state_description_blocker.py",
158
- "blocking/workflow_substitution_slot_blocker.py",
159
- "blocking/claude_md_orphan_file_blocker.py",
160
- "blocking/package_inventory_stale_blocker.py",
161
- "blocking/env_var_table_code_drift_blocker.py",
162
- "blocking/pytest_testpaths_orphan_blocker.py",
163
- "blocking/open_questions_in_plans_blocker.py",
164
- "blocking/docstring_rule_gate_count_blocker.py",
165
- "blocking/duplicate_rmtree_helper_blocker.py",
166
- "validation/hook_format_validator.py",
167
- "blocking/hook_prose_detector_consistency.py",
168
- "blocking/subprocess_budget_completeness.py",
169
- "blocking/windows_rmtree_blocker.py",
170
- "advisory/refactor_guard.py",
171
- "advisory/migration_safety_advisor.py",
172
- )
173
-
174
-
175
- def test_lint_and_advisory_hooks_stay_off_the_apply_patch_roster() -> None:
176
- """Every hook reaching MultiEdit but not apply_patch fails the same one rule.
177
-
178
- apply_patch reaches only a gate whose violation is already real and
179
- unrecoverable the moment the call returns: a leaked secret, an exposed
180
- sensitive path, a blind overwrite, or an untested change landing. Every
181
- hook named here instead judges the quality of the authored content for a
182
- consequence the write itself does not cause right now: doc-inventory
183
- drift, prose or naming style, a future-runtime correctness pattern (an
184
- unsafe rmtree that only misbehaves on Windows, a subprocess-timeout
185
- budget the harness reads separately), or an advisory suggestion that
186
- never denies at all. Each is fixable in a later Edit-tool pass, so none
187
- needs apply_patch's narrower, deny-only roster.
188
- """
189
- for each_script_path in _ALL_DEFERRED_LINT_SCRIPT_PATHS:
190
- entry = _entry_for(each_script_path)
191
- assert entry is not None, f"{each_script_path} must stay on the hosted roster"
192
- assert MULTI_EDIT_TOOL_NAME in entry.applicable_tool_names, (
193
- f"{each_script_path} must still reach MultiEdit"
194
- )
195
- assert APPLY_PATCH_TOOL_NAME not in entry.applicable_tool_names, (
196
- f"{each_script_path} judges deferred-fixable quality, not immediate harm, "
197
- "so it must stay off the apply_patch roster"
198
- )
199
-
200
-
201
- def test_edit_and_multi_edit_applicable_sets_are_equal() -> None:
202
- """The Edit roster and the MultiEdit roster name the same hooks.
203
-
204
- Every hook applicable to Edit judges Write's content or an Edit's
205
- old/new string pair with no dependency on which tool delivered it, so
206
- the two sets must match exactly. A hook that legitimately stays
207
- Edit-only is an exception written down here with its reason, not a
208
- silent gap this test lets back in.
209
- """
210
- all_edit_script_paths = {
211
- each_entry.script_relative_path
212
- for each_entry in ALL_HOSTED_HOOK_ENTRIES
213
- if EDIT_TOOL_NAME in each_entry.applicable_tool_names
214
- }
215
- all_multi_edit_script_paths = {
216
- each_entry.script_relative_path
217
- for each_entry in ALL_HOSTED_HOOK_ENTRIES
218
- if MULTI_EDIT_TOOL_NAME in each_entry.applicable_tool_names
219
- }
220
- assert all_edit_script_paths == all_multi_edit_script_paths, (
221
- "Edit-only (not MultiEdit): "
222
- f"{sorted(all_edit_script_paths - all_multi_edit_script_paths)}; "
223
- "MultiEdit-only (not Edit): "
224
- f"{sorted(all_multi_edit_script_paths - all_edit_script_paths)}"
225
- )
226
-
227
-
228
- def test_multi_edit_widened_hooks_reach_multi_edit() -> None:
229
- all_multi_edit_widened_script_paths = (
230
- "blocking/write_existing_file_blocker.py",
231
- "blocking/code_rules_enforcer.py",
232
- "blocking/tdd_enforcer.py",
233
- "blocking/state_description_blocker.py",
234
- )
235
- for each_script_path in all_multi_edit_widened_script_paths:
236
- entry = _entry_for(each_script_path)
237
- assert entry is not None, f"{each_script_path} must stay on the hosted roster"
238
- assert MULTI_EDIT_TOOL_NAME in entry.applicable_tool_names, (
239
- f"{each_script_path} must reach MultiEdit for mutation-tool parity"
240
- )
@@ -1,29 +1,7 @@
1
1
  """Tests for the Stop-hook dispatcher hosted-hook roster."""
2
2
 
3
- from __future__ import annotations
3
+ from hooks_constants.stop_dispatcher_constants import ALL_STOP_HOSTED_HOOK_PATHS
4
4
 
5
- import sys
6
- from pathlib import Path
7
5
 
8
- _HOOKS_DIR = str(Path(__file__).resolve().parent.parent)
9
- if _HOOKS_DIR not in sys.path:
10
- sys.path.insert(0, _HOOKS_DIR)
11
-
12
- from hooks_constants.stop_dispatcher_constants import ALL_STOP_HOSTED_HOOK_PATHS # noqa: E402
13
-
14
- _EXPECTED_STOP_ORDER = (
15
- "blocking/question_to_user_enforcer.py",
16
- "blocking/session_handoff_blocker.py",
17
- )
18
-
19
-
20
- def test_roster_lists_all_stop_hooks_in_registration_order() -> None:
21
- """The roster reproduces the standalone Stop chain order exactly."""
22
- assert ALL_STOP_HOSTED_HOOK_PATHS == _EXPECTED_STOP_ORDER
23
-
24
-
25
- def test_every_roster_path_points_at_an_existing_hook() -> None:
26
- """Each roster path names a hook script present on disk, catching a typo."""
27
- hooks_root = Path(__file__).resolve().parent.parent
28
- for each_relative_path in ALL_STOP_HOSTED_HOOK_PATHS:
29
- assert (hooks_root / each_relative_path).is_file()
6
+ def test_roster_has_no_blocking_hooks() -> None:
7
+ assert ALL_STOP_HOSTED_HOOK_PATHS == ()