claude-dev-env 2.12.0 → 2.14.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 (399) hide show
  1. package/AGENTS.md +61 -0
  2. package/CLAUDE.md +1 -57
  3. package/_shared/AGENTS.md +15 -0
  4. package/_shared/CLAUDE.md +1 -15
  5. package/_shared/advisor/AGENTS.md +22 -0
  6. package/_shared/advisor/CLAUDE.md +1 -22
  7. package/_shared/pr-loop/AGENTS.md +27 -0
  8. package/_shared/pr-loop/CLAUDE.md +1 -27
  9. package/_shared/pr-loop/scripts/AGENTS.md +35 -0
  10. package/_shared/pr-loop/scripts/CLAUDE.md +1 -35
  11. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -3
  12. package/_shared/pr-loop/scripts/code_rules_gate_parts/AGENTS.md +42 -0
  13. package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +1 -42
  14. package/_shared/pr-loop/scripts/pr_loop_shared_constants/AGENTS.md +26 -0
  15. package/_shared/pr-loop/scripts/pr_loop_shared_constants/CLAUDE.md +1 -26
  16. package/_shared/pr-loop/scripts/test_code_rules_gate.py +0 -26
  17. package/_shared/pr-loop/scripts/tests/AGENTS.md +44 -0
  18. package/_shared/pr-loop/scripts/tests/CLAUDE.md +1 -44
  19. package/_shared/process-tree/AGENTS.md +41 -0
  20. package/_shared/process-tree/CLAUDE.md +1 -41
  21. package/agents/AGENTS.md +31 -0
  22. package/agents/CLAUDE.md +1 -32
  23. package/agents/clean-coder.md +6 -6
  24. package/agents/pr-description-writer.md +11 -81
  25. package/agents/test_agent_frontmatter.py +4 -4
  26. package/audit-rubrics/AGENTS.md +43 -0
  27. package/audit-rubrics/CLAUDE.md +1 -43
  28. package/audit-rubrics/category_rubrics/AGENTS.md +37 -0
  29. package/audit-rubrics/category_rubrics/CLAUDE.md +1 -37
  30. package/audit-rubrics/prompts/AGENTS.md +37 -0
  31. package/audit-rubrics/prompts/CLAUDE.md +1 -37
  32. package/bin/AGENTS.md +112 -0
  33. package/bin/CLAUDE.md +1 -112
  34. package/bin/ever-shipped-skills.mjs +1 -0
  35. package/bin/install-constants.mjs +6 -7
  36. package/bin/install.mjs +71 -13
  37. package/bin/install.prune.test.mjs +26 -0
  38. package/bin/install.settings-defaults.test.mjs +60 -33
  39. package/bin/install.test.mjs +36 -4
  40. package/commands/AGENTS.md +23 -0
  41. package/commands/CLAUDE.md +1 -23
  42. package/commands/hook-log-extract.md +3 -3
  43. package/commands/sr-loop.md +9 -5
  44. package/docs/AGENTS.md +32 -0
  45. package/docs/CLAUDE.md +1 -33
  46. package/docs/CODE_RULES.md +1 -1
  47. package/docs/imagegen.md +22 -0
  48. package/docs/references/AGENTS.md +17 -0
  49. package/docs/references/CLAUDE.md +1 -18
  50. package/hooks/AGENTS.md +31 -0
  51. package/hooks/CLAUDE.md +1 -31
  52. package/hooks/_gh_pr_author_swap_utils.py +14 -0
  53. package/hooks/advisory/AGENTS.md +16 -0
  54. package/hooks/advisory/CLAUDE.md +1 -16
  55. package/hooks/blocking/AGENTS.md +123 -0
  56. package/hooks/blocking/CLAUDE.md +1 -148
  57. package/hooks/blocking/claude_md_orphan_file_blocker_parts/AGENTS.md +28 -0
  58. package/hooks/blocking/claude_md_orphan_file_blocker_parts/CLAUDE.md +1 -28
  59. package/hooks/blocking/code_rules_banned_identifiers.py +1 -1
  60. package/hooks/blocking/code_rules_dead_module_constant.py +149 -37
  61. package/hooks/blocking/code_rules_probe_chains.py +6 -2
  62. package/hooks/blocking/config/AGENTS.md +10 -0
  63. package/hooks/blocking/config/CLAUDE.md +1 -22
  64. package/hooks/blocking/conventional_pr_title_gate.py +1 -2
  65. package/hooks/blocking/gh_pr_author_restore.py +7 -2
  66. package/hooks/blocking/intent_only_ending_blocker.py +11 -16
  67. package/hooks/blocking/inventory_intent_records/AGENTS.md +26 -0
  68. package/hooks/blocking/inventory_intent_records/CLAUDE.md +1 -26
  69. package/hooks/blocking/package_inventory_stale_blocker_parts/AGENTS.md +26 -0
  70. package/hooks/blocking/package_inventory_stale_blocker_parts/CLAUDE.md +1 -26
  71. package/hooks/blocking/pii_prevention_blocker_parts/AGENTS.md +24 -0
  72. package/hooks/blocking/pii_prevention_blocker_parts/CLAUDE.md +1 -24
  73. package/hooks/blocking/send_user_file_open_locally_blocker.py +1 -1
  74. package/hooks/blocking/stop_dispatcher.py +4 -4
  75. package/hooks/blocking/tdd_enforcer_parts/AGENTS.md +30 -0
  76. package/hooks/blocking/tdd_enforcer_parts/CLAUDE.md +1 -30
  77. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -3
  78. package/hooks/blocking/test_code_rules_enforcer_banned_prefixes.py +1 -1
  79. package/hooks/blocking/test_code_rules_enforcer_dead_module_constant.py +171 -0
  80. package/hooks/blocking/test_code_rules_enforcer_magic_allowlist.py +1 -1
  81. package/hooks/blocking/test_gh_pr_author_restore.py +2 -1
  82. package/hooks/blocking/test_intent_only_ending_blocker.py +4 -0
  83. package/hooks/blocking/test_pre_tool_use_dispatcher.py +6 -7
  84. package/hooks/blocking/test_send_user_file_open_locally_blocker.py +4 -3
  85. package/hooks/blocking/test_shared_stdin_adoption.py +0 -2
  86. package/hooks/diagnostic/AGENTS.md +43 -0
  87. package/hooks/diagnostic/CLAUDE.md +1 -43
  88. package/hooks/diagnostic/hook_log_extractor.py +4 -38
  89. package/hooks/diagnostic/hook_log_stop_wrapper.py +6 -155
  90. package/hooks/diagnostic/migrations/AGENTS.md +16 -0
  91. package/hooks/diagnostic/migrations/CLAUDE.md +1 -16
  92. package/hooks/diagnostic/queries/AGENTS.md +19 -0
  93. package/hooks/diagnostic/queries/CLAUDE.md +1 -19
  94. package/hooks/diagnostic/test_hook_log_extractor.py +10 -23
  95. package/hooks/diagnostic/test_hook_log_stop_wrapper.py +3 -331
  96. package/hooks/git-hooks/AGENTS.md +31 -0
  97. package/hooks/git-hooks/CLAUDE.md +1 -31
  98. package/hooks/git-hooks/git_hooks_constants/AGENTS.md +21 -0
  99. package/hooks/git-hooks/git_hooks_constants/CLAUDE.md +1 -21
  100. package/hooks/git-hooks/git_hooks_constants/__init__.py +4 -12
  101. package/hooks/git-hooks/pre_push.py +49 -118
  102. package/hooks/git-hooks/test_pre_push.py +111 -137
  103. package/hooks/hooks.json +0 -35
  104. package/hooks/hooks_constants/AGENTS.md +104 -0
  105. package/hooks/hooks_constants/CLAUDE.md +1 -113
  106. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +0 -11
  107. package/hooks/hooks_constants/convergence_branch_constants.py +0 -1
  108. package/hooks/hooks_constants/fable_spawn_gate_constants.py +3 -4
  109. package/hooks/hooks_constants/hook_log_extractor_constants.py +1 -2
  110. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +0 -8
  111. package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +1 -6
  112. package/hooks/hooks_constants/stop_dispatcher_constants.py +0 -1
  113. package/hooks/hooks_constants/task_list_loop_starter_constants.py +4 -3
  114. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +1 -26
  115. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +0 -5
  116. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +0 -1
  117. package/hooks/hooks_constants/working_style_prompt_constants.py +29 -20
  118. package/hooks/lifecycle/AGENTS.md +18 -0
  119. package/hooks/lifecycle/CLAUDE.md +1 -20
  120. package/hooks/observability/AGENTS.md +20 -0
  121. package/hooks/observability/CLAUDE.md +1 -20
  122. package/hooks/session/AGENTS.md +33 -0
  123. package/hooks/session/CLAUDE.md +1 -33
  124. package/hooks/session/gh_pr_author_session_cleanup.py +7 -2
  125. package/hooks/session/task_list_loop_starter.py +3 -3
  126. package/hooks/session/test_gh_pr_author_session_cleanup.py +2 -1
  127. package/hooks/session/test_task_list_loop_starter.py +10 -2
  128. package/hooks/session/test_working_style_prompt.py +9 -4
  129. package/hooks/validation/AGENTS.md +20 -0
  130. package/hooks/validation/CLAUDE.md +1 -20
  131. package/hooks/validators/AGENTS.md +51 -0
  132. package/hooks/validators/CLAUDE.md +1 -51
  133. package/hooks/validators/health_check.py +52 -19
  134. package/hooks/validators/python_style_checks.py +1 -1
  135. package/hooks/validators/test_health_check.py +112 -27
  136. package/hooks/workflow/AGENTS.md +16 -0
  137. package/hooks/workflow/CLAUDE.md +1 -16
  138. package/installable-surfaces.manifest.json +1 -0
  139. package/output-styles/AGENTS.md +15 -0
  140. package/output-styles/CLAUDE.md +1 -15
  141. package/package.json +2 -1
  142. package/rules/AGENTS.md +61 -0
  143. package/rules/CLAUDE.md +1 -63
  144. package/rules/code-standards.md +5 -9
  145. package/rules/doc-prose-cuts.md +1 -1
  146. package/rules/gh-cli-conventions.md +0 -1
  147. package/rules/git-workflow.md +1 -3
  148. package/scripts/AGENTS.md +62 -0
  149. package/scripts/CLAUDE.md +1 -63
  150. package/scripts/_code_review_test_support.py +0 -95
  151. package/scripts/codex_compat_materializer.py +4 -0
  152. package/scripts/dev_env_scripts_constants/AGENTS.md +21 -0
  153. package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -21
  154. package/scripts/dev_env_scripts_constants/code_review_constants.py +9 -98
  155. package/scripts/dev_env_scripts_constants/test_code_review_constants.py +1 -44
  156. package/scripts/invoke_code_review.py +8 -451
  157. package/scripts/sync_to_cursor/AGENTS.md +23 -0
  158. package/scripts/sync_to_cursor/CLAUDE.md +1 -23
  159. package/scripts/test_invoke_code_review.py +5 -61
  160. package/scripts/test_invoke_code_review_cli.py +1 -45
  161. package/scripts/test_invoke_code_review_contract.py +1 -118
  162. package/scripts/test_validate_instruction_pairs.py +90 -0
  163. package/scripts/test_verify_installable_package.py +5 -1
  164. package/scripts/tests/AGENTS.md +33 -0
  165. package/scripts/tests/CLAUDE.md +1 -33
  166. package/scripts/tests/test_codex_compat_materializer.py +36 -1
  167. package/scripts/validate_instruction_pairs.py +183 -0
  168. package/settings.json +1 -10
  169. package/skills/AGENTS.md +72 -0
  170. package/skills/CLAUDE.md +1 -64
  171. package/skills/_shared/AGENTS.md +44 -0
  172. package/skills/_shared/CLAUDE.md +1 -44
  173. package/skills/_shared/advisor/AGENTS.md +9 -0
  174. package/skills/_shared/advisor/CLAUDE.md +1 -9
  175. package/skills/_shared/pr-loop/AGENTS.md +50 -0
  176. package/skills/_shared/pr-loop/CLAUDE.md +1 -50
  177. package/skills/_shared/pr-loop/prompts/AGENTS.md +9 -0
  178. package/skills/_shared/pr-loop/prompts/CLAUDE.md +1 -9
  179. package/skills/_shared/pr-loop/scripts/AGENTS.md +35 -0
  180. package/skills/_shared/pr-loop/scripts/CLAUDE.md +1 -35
  181. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +24 -0
  182. package/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/CLAUDE.md +1 -24
  183. package/skills/anthropic-plan/AGENTS.md +34 -0
  184. package/skills/anthropic-plan/CLAUDE.md +1 -34
  185. package/skills/anthropic-plan/scripts/AGENTS.md +11 -0
  186. package/skills/anthropic-plan/scripts/CLAUDE.md +1 -11
  187. package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/AGENTS.md +16 -0
  188. package/skills/anthropic-plan/scripts/anthropic_plan_scripts_constants/CLAUDE.md +1 -16
  189. package/skills/anthropic-plan/templates/AGENTS.md +13 -0
  190. package/skills/anthropic-plan/templates/CLAUDE.md +1 -13
  191. package/skills/anthropic-plan/workflow/AGENTS.md +14 -0
  192. package/skills/anthropic-plan/workflow/CLAUDE.md +1 -14
  193. package/skills/auditing-claude-config/AGENTS.md +21 -0
  194. package/skills/auditing-claude-config/CLAUDE.md +1 -21
  195. package/skills/autoconverge/AGENTS.md +36 -0
  196. package/skills/autoconverge/CLAUDE.md +1 -36
  197. package/skills/autoconverge/reference/AGENTS.md +16 -0
  198. package/skills/autoconverge/reference/CLAUDE.md +1 -16
  199. package/skills/autoconverge/reference/convergence.md +7 -7
  200. package/skills/autoconverge/reference/gotchas.md +3 -10
  201. package/skills/autoconverge/workflow/AGENTS.md +26 -0
  202. package/skills/autoconverge/workflow/CLAUDE.md +1 -26
  203. package/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +16 -0
  204. package/skills/autoconverge/workflow/autoconverge_report_constants/CLAUDE.md +1 -16
  205. package/skills/autoconverge/workflow/converge.contract.test.mjs +53 -1388
  206. package/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +4 -3
  207. package/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +33 -493
  208. package/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +15 -97
  209. package/skills/autoconverge/workflow/converge.mjs +201 -238
  210. package/skills/autoconverge/workflow/converge.precatch.test.mjs +1 -1
  211. package/skills/bugteam/AGENTS.md +30 -0
  212. package/skills/bugteam/CLAUDE.md +1 -30
  213. package/skills/bugteam/CONSTRAINTS.md +1 -1
  214. package/skills/bugteam/SKILL.md +9 -0
  215. package/skills/bugteam/reference/AGENTS.md +20 -0
  216. package/skills/bugteam/reference/CLAUDE.md +1 -20
  217. package/skills/bugteam/reference/audit-and-teammates.md +10 -6
  218. package/skills/bugteam/reference/obstacles/AGENTS.md +24 -0
  219. package/skills/bugteam/reference/obstacles/CLAUDE.md +1 -24
  220. package/skills/bugteam/scripts/AGENTS.md +30 -0
  221. package/skills/bugteam/scripts/CLAUDE.md +1 -30
  222. package/skills/bugteam/scripts/bugteam_scripts_constants/AGENTS.md +18 -0
  223. package/skills/bugteam/scripts/bugteam_scripts_constants/CLAUDE.md +1 -18
  224. package/skills/bugteam/test_skill_additions.py +9 -0
  225. package/skills/closeout/reference/handoff-prompt-template.md +1 -1
  226. package/skills/codex-review/AGENTS.md +46 -0
  227. package/skills/codex-review/CLAUDE.md +1 -46
  228. package/skills/codex-review/reference/AGENTS.md +15 -0
  229. package/skills/codex-review/reference/CLAUDE.md +1 -15
  230. package/skills/codex-review/scripts/codex_review_scripts_constants/AGENTS.md +18 -0
  231. package/skills/codex-review/scripts/codex_review_scripts_constants/CLAUDE.md +1 -18
  232. package/skills/codex-review/test_skill_scaffold.py +3 -3
  233. package/skills/comments/SKILL.md +65 -0
  234. package/skills/copilot-review/AGENTS.md +18 -0
  235. package/skills/copilot-review/CLAUDE.md +1 -18
  236. package/skills/descriptions/SKILL.md +51 -0
  237. package/skills/emergencies/SKILL.md +42 -0
  238. package/skills/everything-search/AGENTS.md +17 -0
  239. package/skills/everything-search/CLAUDE.md +1 -17
  240. package/skills/fresh-branch/AGENTS.md +14 -0
  241. package/skills/fresh-branch/CLAUDE.md +1 -14
  242. package/skills/grok-spawn/AGENTS.md +28 -0
  243. package/skills/grok-spawn/CLAUDE.md +1 -28
  244. package/skills/orchestrator/SKILL.md +2 -4
  245. package/skills/plan-to-pr/SKILL.md +6 -7
  246. package/skills/plan-to-pr/reference/final-validation-tasks.md +1 -1
  247. package/skills/plan-to-pr/reference/process-inventory.md +2 -2
  248. package/skills/plan-to-pr/reference/review-loop.md +2 -2
  249. package/skills/plan-to-pr/reference/run-record.schema.json +1 -1
  250. package/skills/plan-to-pr/reference/task-seeds.md +1 -1
  251. package/skills/plan-to-pr/reference/task-ticket.md +3 -4
  252. package/skills/plan-to-pr/scripts/config/constants.py +1 -2
  253. package/skills/plan-to-pr/scripts/test_validate_protocol.py +1 -1
  254. package/skills/plan-to-pr/test_skill_contract.py +2 -2
  255. package/skills/pr-converge/AGENTS.md +32 -0
  256. package/skills/pr-converge/CLAUDE.md +1 -32
  257. package/skills/pr-converge/SKILL.md +13 -16
  258. package/skills/pr-converge/pr_converge_skill_constants/AGENTS.md +26 -0
  259. package/skills/pr-converge/pr_converge_skill_constants/CLAUDE.md +1 -26
  260. package/skills/pr-converge/reference/AGENTS.md +28 -0
  261. package/skills/pr-converge/reference/CLAUDE.md +1 -28
  262. package/skills/pr-converge/reference/obstacles/AGENTS.md +23 -0
  263. package/skills/pr-converge/reference/obstacles/CLAUDE.md +1 -23
  264. package/skills/pr-converge/reference/progress-checklist.md +6 -5
  265. package/skills/pr-converge/reference/state-schema.md +1 -27
  266. package/skills/pr-converge/scripts/AGENTS.md +46 -0
  267. package/skills/pr-converge/scripts/CLAUDE.md +1 -46
  268. package/skills/pr-converge/scripts/pr_converge_scripts_constants/AGENTS.md +18 -0
  269. package/skills/pr-converge/scripts/pr_converge_scripts_constants/CLAUDE.md +1 -18
  270. package/skills/pr-converge/workflows/AGENTS.md +16 -0
  271. package/skills/pr-converge/workflows/CLAUDE.md +1 -16
  272. package/skills/pr-loop-cloud-transport/SKILL.md +1 -1
  273. package/skills/pr-loop-cloud-transport/reference/identity-and-hooks.md +3 -3
  274. package/skills/pr-loop-lifecycle/SKILL.md +1 -1
  275. package/skills/pr-loop-lifecycle/reference/teardown-publish-permissions.md +1 -1
  276. package/skills/prototype/SKILL.md +4 -4
  277. package/skills/prototype/reference/honest-limitations.md +5 -5
  278. package/skills/prototype/reference/promotion-tasks.md +2 -2
  279. package/skills/prototype/workflows/promotion.md +4 -6
  280. package/skills/rebase/AGENTS.md +32 -0
  281. package/skills/rebase/CLAUDE.md +1 -32
  282. package/skills/recall/AGENTS.md +30 -0
  283. package/skills/recall/CLAUDE.md +1 -30
  284. package/skills/remember/AGENTS.md +31 -0
  285. package/skills/remember/CLAUDE.md +1 -31
  286. package/skills/reviews/SKILL.md +85 -0
  287. package/skills/session-log/AGENTS.md +32 -0
  288. package/skills/session-log/CLAUDE.md +1 -32
  289. package/skills/session-tidy/AGENTS.md +36 -0
  290. package/skills/session-tidy/CLAUDE.md +1 -36
  291. package/skills/skill-builder/AGENTS.md +49 -0
  292. package/skills/skill-builder/CLAUDE.md +1 -49
  293. package/skills/skill-builder/references/AGENTS.md +25 -0
  294. package/skills/skill-builder/references/CLAUDE.md +1 -25
  295. package/skills/skill-builder/references/deterministic-elements.md +1 -1
  296. package/skills/skill-builder/templates/AGENTS.md +14 -0
  297. package/skills/skill-builder/templates/CLAUDE.md +1 -14
  298. package/skills/skill-builder/workflows/AGENTS.md +19 -0
  299. package/skills/skill-builder/workflows/CLAUDE.md +1 -19
  300. package/skills/small-cl/SKILL.md +52 -0
  301. package/skills/task-build/AGENTS.md +29 -0
  302. package/skills/task-build/CLAUDE.md +1 -29
  303. package/skills/update/AGENTS.md +38 -0
  304. package/skills/update/CLAUDE.md +1 -38
  305. package/system-prompts/AGENTS.md +17 -0
  306. package/system-prompts/CLAUDE.md +1 -17
  307. package/system-prompts/software-engineer.xml +3 -3
  308. package/agents/code-verifier.md +0 -74
  309. package/docs/PR_DESCRIPTION_GUIDE.md +0 -157
  310. package/docs/references/code-review-enforcement.md +0 -132
  311. package/hooks/blocking/code_review_enforcement_config_bootstrap.py +0 -53
  312. package/hooks/blocking/code_review_gate_deny.py +0 -74
  313. package/hooks/blocking/code_review_pr_create_gate.py +0 -198
  314. package/hooks/blocking/code_review_push_gate.py +0 -145
  315. package/hooks/blocking/code_review_stamp_directory_write_blocker.py +0 -348
  316. package/hooks/blocking/code_review_stamp_store.py +0 -233
  317. package/hooks/blocking/code_review_stamp_write_blocker_parts/__init__.py +0 -7
  318. package/hooks/blocking/code_review_stamp_write_blocker_parts/conftest.py +0 -15
  319. package/hooks/blocking/code_review_stamp_write_blocker_parts/obfuscated_stamp_path_reference.py +0 -212
  320. package/hooks/blocking/code_review_stamp_write_blocker_parts/split_directory_change_into_stamp.py +0 -138
  321. package/hooks/blocking/code_review_stamp_write_blocker_parts/test_obfuscated_stamp_path_reference.py +0 -49
  322. package/hooks/blocking/code_review_stamp_write_blocker_parts/test_split_directory_change_into_stamp.py +0 -38
  323. package/hooks/blocking/code_verifier_spawn_preflight_gate.py +0 -483
  324. package/hooks/blocking/config/code_review_enforcement_constants.py +0 -143
  325. package/hooks/blocking/config/test_code_review_enforcement_constants.py +0 -166
  326. package/hooks/blocking/config/verified_commit_constants.py +0 -160
  327. package/hooks/blocking/config/verified_commit_context_constants.py +0 -21
  328. package/hooks/blocking/config/verified_commit_gate_output_constants.py +0 -14
  329. package/hooks/blocking/conftest.py +0 -123
  330. package/hooks/blocking/convergence_gate_blocker.py +0 -310
  331. package/hooks/blocking/pr_converge_bugteam_enforcer.py +0 -170
  332. package/hooks/blocking/pr_description_body_audit.py +0 -148
  333. package/hooks/blocking/pr_description_command_parser.py +0 -237
  334. package/hooks/blocking/pr_description_enforcer.py +0 -227
  335. package/hooks/blocking/pr_description_pr_number.py +0 -155
  336. package/hooks/blocking/pr_description_proof_of_work.py +0 -385
  337. package/hooks/blocking/pr_description_readability.py +0 -364
  338. package/hooks/blocking/reviewer_spawn_gate.py +0 -182
  339. package/hooks/blocking/test_code_review_enforcement_config_bootstrap.py +0 -62
  340. package/hooks/blocking/test_code_review_gate_deny.py +0 -54
  341. package/hooks/blocking/test_code_review_pr_create_gate.py +0 -199
  342. package/hooks/blocking/test_code_review_push_gate.py +0 -205
  343. package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +0 -199
  344. package/hooks/blocking/test_code_review_stamp_store.py +0 -205
  345. package/hooks/blocking/test_code_verifier_spawn_preflight_gate.py +0 -710
  346. package/hooks/blocking/test_code_verifier_tools_contract.py +0 -28
  347. package/hooks/blocking/test_convergence_gate_blocker.py +0 -428
  348. package/hooks/blocking/test_pr_converge_bugteam_enforcer.py +0 -311
  349. package/hooks/blocking/test_pr_converge_bugteam_enforcer_state_tolerance.py +0 -184
  350. package/hooks/blocking/test_pr_description_enforcer.py +0 -221
  351. package/hooks/blocking/test_pr_description_enforcer_body_audit.py +0 -247
  352. package/hooks/blocking/test_pr_description_enforcer_body_rules.py +0 -493
  353. package/hooks/blocking/test_pr_description_enforcer_command_parser.py +0 -366
  354. package/hooks/blocking/test_pr_description_enforcer_pr_number.py +0 -159
  355. package/hooks/blocking/test_pr_description_enforcer_proof_gate.py +0 -175
  356. package/hooks/blocking/test_pr_description_enforcer_readability.py +0 -443
  357. package/hooks/blocking/test_pr_description_proof_of_work.py +0 -313
  358. package/hooks/blocking/test_reviewer_spawn_gate.py +0 -230
  359. package/hooks/blocking/test_verdict_directory_write_blocker.py +0 -804
  360. package/hooks/blocking/test_verification_verdict_store.py +0 -974
  361. package/hooks/blocking/test_verified_commit_config_bootstrap.py +0 -67
  362. package/hooks/blocking/test_verified_commit_docs_delta.py +0 -176
  363. package/hooks/blocking/test_verified_commit_gate.py +0 -581
  364. package/hooks/blocking/test_verified_commit_gate_additional_context.py +0 -134
  365. package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +0 -131
  366. package/hooks/blocking/test_verifier_verdict_minter.py +0 -299
  367. package/hooks/blocking/tests/test_verified_commit_gate.py +0 -41
  368. package/hooks/blocking/verdict_directory_write_blocker.py +0 -687
  369. package/hooks/blocking/verification_verdict_store.py +0 -1039
  370. package/hooks/blocking/verified_commit_config_bootstrap.py +0 -63
  371. package/hooks/blocking/verified_commit_gate.py +0 -113
  372. package/hooks/blocking/verified_commit_gate_parts/CLAUDE.md +0 -28
  373. package/hooks/blocking/verified_commit_gate_parts/__init__.py +0 -1
  374. package/hooks/blocking/verified_commit_gate_parts/command_tokenization.py +0 -174
  375. package/hooks/blocking/verified_commit_gate_parts/deny_payload.py +0 -53
  376. package/hooks/blocking/verified_commit_gate_parts/deny_reason.py +0 -80
  377. package/hooks/blocking/verified_commit_gate_parts/directory_resolution.py +0 -170
  378. package/hooks/blocking/verified_commit_gate_parts/gated_invocations.py +0 -217
  379. package/hooks/blocking/verified_commit_gate_parts/tests/conftest.py +0 -10
  380. package/hooks/blocking/verified_commit_gate_parts/tests/test_command_tokenization.py +0 -94
  381. package/hooks/blocking/verified_commit_gate_parts/tests/test_deny_payload.py +0 -17
  382. package/hooks/blocking/verified_commit_gate_parts/tests/test_deny_reason.py +0 -38
  383. package/hooks/blocking/verified_commit_gate_parts/tests/test_directory_resolution.py +0 -71
  384. package/hooks/blocking/verified_commit_gate_parts/tests/test_gated_invocations.py +0 -96
  385. package/hooks/blocking/verified_commit_message_accuracy_blocker.py +0 -167
  386. package/hooks/blocking/verifier_verdict_minter.py +0 -280
  387. package/hooks/hooks_constants/code_verifier_spawn_preflight_gate_constants.py +0 -64
  388. package/hooks/hooks_constants/convergence_gate_blocker_constants.py +0 -53
  389. package/hooks/hooks_constants/pr_converge_bugteam_enforcer_constants.py +0 -55
  390. package/hooks/hooks_constants/pr_converge_bugteam_enforcer_state.py +0 -67
  391. package/hooks/hooks_constants/pr_description_enforcer_constants.py +0 -167
  392. package/hooks/hooks_constants/pr_description_proof_of_work_constants.py +0 -107
  393. package/hooks/hooks_constants/reviewer_spawn_gate_constants.py +0 -41
  394. package/hooks/hooks_constants/test_pr_description_enforcer_constants.py +0 -292
  395. package/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py +0 -198
  396. package/hooks/lifecycle/test_pr_converge_bugteam_skill_tracker.py +0 -283
  397. package/rules/proof-of-work-pr-comments.md +0 -22
  398. package/rules/verified-commit-gate-skip.md +0 -4
  399. package/scripts/Show-Asset.ps1 +0 -106
@@ -17,8 +17,6 @@ SCRIPT_DIRECTORY = Path(__file__).resolve().parent
17
17
  REAL_RUN_GIT_TEXT_COMMAND = pre_push.run_git_text_command
18
18
 
19
19
 
20
- CODE_REVIEW_ENFORCEMENT_ENV_VAR: str = "CLAUDE_CODE_REVIEW_ENFORCEMENT"
21
- ENFORCEMENT_CONSTANTS_MODULE_NAME: str = "config.code_review_enforcement_constants"
22
20
  ALL_ZEROS_OBJECT_NAME: str = "0" * 40
23
21
  NON_ZERO_LOCAL_SHA: str = "a" * 40
24
22
  NON_ZERO_REMOTE_SHA_ONE: str = "1" * 40
@@ -111,7 +109,6 @@ def _write_gate_that_allows_every_push(
111
109
  passing_gate_path = tmp_path / "code_rules_gate.py"
112
110
  passing_gate_path.write_text("import sys\nsys.exit(0)\n", encoding="utf-8")
113
111
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(passing_gate_path))
114
- _isolate_code_review_gate(tmp_path, monkeypatch)
115
112
  monkeypatch.setattr(sys, "stdin", io.StringIO(NEW_BRANCH_PUSH_STDIN))
116
113
 
117
114
 
@@ -159,11 +156,10 @@ def test_run_git_reference_query_returns_replaced_text_on_locale_invalid_bytes(
159
156
  assert resolved_output == expected_replaced_reference
160
157
 
161
158
 
162
- def test_unresolvable_merge_base_message_does_not_claim_dangling_origin_head() -> None:
159
+ def test_unresolvable_merge_base_message_describes_pending_validation() -> None:
163
160
  skip_message = git_hooks_constants.UNRESOLVABLE_MERGE_BASE_MESSAGE
164
- assert "origin/HEAD names a ref" not in skip_message
165
- assert "unrelated histories" in skip_message
166
- assert "merge-base still could not name a shared commit" in skip_message
161
+ assert "CODE_RULES validation is pending" in skip_message
162
+ assert "Restore shared history" in skip_message
167
163
 
168
164
 
169
165
  def test_run_git_text_command_raises_when_git_cannot_launch(
@@ -242,14 +238,14 @@ def resolve_remote_head_reference(monkeypatch: pytest.MonkeyPatch) -> None:
242
238
  return GIT_RESOLVED_EXIT_CODE, RESOLVED_COMMIT_OBJECT_NAME
243
239
 
244
240
  monkeypatch.setattr(pre_push, "run_git_text_command", fake_run_git_text_command)
245
-
246
-
247
- def _isolate_code_review_gate(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
248
- monkeypatch.setenv(
249
- "CODE_REVIEW_PUSH_GATE_PATH", str(tmp_path / "no_code_review_gate.py")
241
+ monkeypatch.setattr(
242
+ sys,
243
+ "argv",
244
+ [HOOK_INVOCATION_NAME, git_hooks_constants.DEFAULT_REMOTE_NAME, PUSHED_REMOTE_URL],
250
245
  )
251
246
 
252
247
 
248
+
253
249
  def test_resolve_base_reference_from_stdin_uses_remote_object_when_non_zero() -> None:
254
250
  stdin_text = (
255
251
  f"refs/heads/feature {NON_ZERO_LOCAL_SHA} refs/heads/feature {NON_ZERO_REMOTE_SHA_ONE}\n"
@@ -295,7 +291,6 @@ def test_main_exits_zero_when_gate_script_missing(
295
291
  "CODE_RULES_GATE_PATH",
296
292
  str(tmp_path / "does_not_exist.py"),
297
293
  )
298
- _isolate_code_review_gate(tmp_path, monkeypatch)
299
294
  monkeypatch.setattr(sys, "stdin", io.StringIO(""))
300
295
 
301
296
  exit_code = pre_push.main()
@@ -317,7 +312,6 @@ def test_main_invokes_gate_with_resolved_base_reference(
317
312
  encoding="utf-8",
318
313
  )
319
314
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(recording_gate_script_path))
320
- _isolate_code_review_gate(tmp_path, monkeypatch)
321
315
  _isolate_from_default_branch_refs(tmp_path, monkeypatch)
322
316
  remote_sha = "9" * 40
323
317
  monkeypatch.setattr(
@@ -345,7 +339,6 @@ def test_main_passes_the_pushed_remote_name_to_base_resolution(
345
339
  # No default-branch ref so the gate base is the stdin remote object, not a
346
340
  # merge-base skip; usable-base resolution then sees the pushed remote name.
347
341
  _isolate_repository_and_write_passing_code_rules_gate(tmp_path, monkeypatch)
348
- _isolate_code_review_gate(tmp_path, monkeypatch)
349
342
  all_recorded_remote_names: list[str] = []
350
343
 
351
344
  def recording_resolve_usable_base_reference(
@@ -566,7 +559,6 @@ def test_invoke_gate_uses_resolved_path(
566
559
  symlink_gate_path.symlink_to(real_gate_path)
567
560
  resolved_path = symlink_gate_path.resolve()
568
561
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(symlink_gate_path))
569
- _isolate_code_review_gate(tmp_path, monkeypatch)
570
562
  _isolate_from_default_branch_refs(tmp_path, monkeypatch)
571
563
  monkeypatch.setattr(sys, "stdin", io.StringIO(
572
564
  f"refs/heads/feature {NON_ZERO_LOCAL_SHA} refs/heads/feature {NON_ZERO_REMOTE_SHA_ONE}\n"
@@ -684,7 +676,6 @@ def test_main_allows_main_onto_main_push(
684
676
  passing_gate_path = tmp_path / "gate.py"
685
677
  passing_gate_path.write_text("import sys\nsys.exit(0)\n", encoding="utf-8")
686
678
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(passing_gate_path))
687
- _isolate_code_review_gate(tmp_path, monkeypatch)
688
679
  monkeypatch.setattr(
689
680
  sys,
690
681
  "stdin",
@@ -698,8 +689,6 @@ def test_main_allows_main_onto_main_push(
698
689
  assert exit_code == 0
699
690
 
700
691
 
701
- CODE_REVIEW_STUB_BLOCK_REASON: str = "CODE_REVIEW_STUB_BLOCK_REASON"
702
-
703
692
 
704
693
  def _write_passing_code_rules_gate(
705
694
  tmp_path: Path, monkeypatch: pytest.MonkeyPatch
@@ -725,83 +714,6 @@ def _isolate_repository_and_write_passing_code_rules_gate(
725
714
  _write_passing_code_rules_gate(tmp_path, monkeypatch)
726
715
 
727
716
 
728
- def _write_code_review_gate_stub(tmp_path: Path, returned_reason_literal: str) -> Path:
729
- stub_gate_path = tmp_path / "code_review_push_gate.py"
730
- stub_gate_path.write_text(
731
- "def deny_reason_for_directory(target_directory):\n"
732
- f" return {returned_reason_literal}\n",
733
- encoding="utf-8",
734
- )
735
- return stub_gate_path
736
-
737
-
738
- def test_main_blocks_when_code_review_gate_returns_reason(
739
- tmp_path: Path,
740
- monkeypatch: pytest.MonkeyPatch,
741
- capsys: pytest.CaptureFixture[str],
742
- ) -> None:
743
- _isolate_repository_and_write_passing_code_rules_gate(tmp_path, monkeypatch)
744
- stub_gate_path = _write_code_review_gate_stub(
745
- tmp_path, repr(CODE_REVIEW_STUB_BLOCK_REASON)
746
- )
747
- monkeypatch.setenv("CODE_REVIEW_PUSH_GATE_PATH", str(stub_gate_path))
748
-
749
- exit_code = pre_push.main()
750
-
751
- assert exit_code == git_hooks_constants.CODE_REVIEW_STAMP_BLOCK_EXIT_CODE
752
- captured = capsys.readouterr()
753
- assert CODE_REVIEW_STUB_BLOCK_REASON in captured.err
754
-
755
-
756
- def test_main_allows_when_code_review_gate_returns_none(
757
- tmp_path: Path,
758
- monkeypatch: pytest.MonkeyPatch,
759
- ) -> None:
760
- _isolate_repository_and_write_passing_code_rules_gate(tmp_path, monkeypatch)
761
- stub_gate_path = _write_code_review_gate_stub(tmp_path, "None")
762
- monkeypatch.setenv("CODE_REVIEW_PUSH_GATE_PATH", str(stub_gate_path))
763
-
764
- exit_code = pre_push.main()
765
-
766
- assert exit_code == 0
767
-
768
-
769
- def test_main_code_review_check_fails_open_when_gate_module_absent(
770
- tmp_path: Path,
771
- monkeypatch: pytest.MonkeyPatch,
772
- ) -> None:
773
- _isolate_repository_and_write_passing_code_rules_gate(tmp_path, monkeypatch)
774
- monkeypatch.setenv(
775
- "CODE_REVIEW_PUSH_GATE_PATH", str(tmp_path / "does_not_exist.py")
776
- )
777
-
778
- exit_code = pre_push.main()
779
-
780
- assert exit_code == 0
781
-
782
-
783
- def test_main_allows_deletion_push_even_when_code_review_gate_would_block(
784
- tmp_path: Path,
785
- monkeypatch: pytest.MonkeyPatch,
786
- ) -> None:
787
- passing_gate_path = tmp_path / "code_rules_gate.py"
788
- passing_gate_path.write_text("import sys\nsys.exit(0)\n", encoding="utf-8")
789
- monkeypatch.setenv("CODE_RULES_GATE_PATH", str(passing_gate_path))
790
- stub_gate_path = _write_code_review_gate_stub(
791
- tmp_path, repr(CODE_REVIEW_STUB_BLOCK_REASON)
792
- )
793
- monkeypatch.setenv("CODE_REVIEW_PUSH_GATE_PATH", str(stub_gate_path))
794
- deletion_stdin = (
795
- f"refs/heads/feature {ALL_ZEROS_OBJECT_NAME} "
796
- f"refs/heads/feature {ALL_ZEROS_OBJECT_NAME}\n"
797
- )
798
- monkeypatch.setattr(sys, "stdin", io.StringIO(deletion_stdin))
799
-
800
- exit_code = pre_push.main()
801
-
802
- assert exit_code == 0
803
-
804
-
805
717
  DEFAULT_BRANCH_NAME: str = "main"
806
718
  FEATURE_BRANCH_NAME: str = "feature/example"
807
719
  UNPROTECTED_DEFAULT_BRANCH_NAME: str = "develop"
@@ -1086,6 +998,46 @@ def test_resolve_default_branch_reference_reads_the_origin_head_symbolic_referen
1086
998
  assert pre_push.resolve_default_branch_reference() == ORIGIN_DEFAULT_BRANCH_REFERENCE
1087
999
 
1088
1000
 
1001
+ def test_resolve_default_branch_reference_reads_the_requested_remote_head(
1002
+ tmp_path: Path,
1003
+ monkeypatch: pytest.MonkeyPatch,
1004
+ ) -> None:
1005
+ repository, default_branch_tip, _topic_branch_tip = _build_default_branch_repository(
1006
+ tmp_path
1007
+ )
1008
+ upstream_reference = "refs/remotes/upstream/main"
1009
+ upstream_head_reference = "refs/remotes/upstream/HEAD"
1010
+ _run_fixture_git(repository, "update-ref", upstream_reference, default_branch_tip)
1011
+ _run_fixture_git(
1012
+ repository, "symbolic-ref", upstream_head_reference, upstream_reference
1013
+ )
1014
+ monkeypatch.chdir(repository)
1015
+
1016
+ assert pre_push.resolve_default_branch_reference("upstream") == upstream_reference
1017
+
1018
+
1019
+ def test_resolve_default_branch_merge_base_uses_requested_remote_trunk_fallback(
1020
+ tmp_path: Path,
1021
+ monkeypatch: pytest.MonkeyPatch,
1022
+ ) -> None:
1023
+ repository, default_branch_tip, topic_branch_tip = _build_default_branch_repository(
1024
+ tmp_path
1025
+ )
1026
+ upstream_trunk_reference = "refs/remotes/upstream/trunk"
1027
+ _run_fixture_git(
1028
+ repository, "update-ref", upstream_trunk_reference, default_branch_tip
1029
+ )
1030
+ monkeypatch.chdir(repository)
1031
+
1032
+ merge_base_object_name = pre_push.resolve_default_branch_merge_base(
1033
+ FEATURE_BRANCH_NAME,
1034
+ topic_branch_tip,
1035
+ "upstream",
1036
+ )
1037
+
1038
+ assert merge_base_object_name == default_branch_tip
1039
+
1040
+
1089
1041
  def test_resolve_default_branch_reference_returns_none_without_remote_tracking_refs(
1090
1042
  tmp_path: Path,
1091
1043
  monkeypatch: pytest.MonkeyPatch,
@@ -1267,7 +1219,6 @@ def test_main_allows_the_push_when_origin_head_names_an_absent_reference(
1267
1219
  encoding="utf-8",
1268
1220
  )
1269
1221
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(recording_gate_script_path))
1270
- _isolate_code_review_gate(tmp_path, monkeypatch)
1271
1222
  monkeypatch.chdir(repository)
1272
1223
  monkeypatch.setattr(
1273
1224
  sys,
@@ -1291,7 +1242,7 @@ def test_main_allows_the_push_when_origin_head_names_an_absent_reference(
1291
1242
  assert recorded_arguments == ["--base", remote_object_name]
1292
1243
 
1293
1244
 
1294
- def test_main_skips_the_gate_when_no_merge_base_resolves(
1245
+ def test_main_keeps_the_gate_pending_when_no_merge_base_resolves(
1295
1246
  tmp_path: Path,
1296
1247
  monkeypatch: pytest.MonkeyPatch,
1297
1248
  capsys: pytest.CaptureFixture[str],
@@ -1307,7 +1258,6 @@ def test_main_skips_the_gate_when_no_merge_base_resolves(
1307
1258
  encoding="utf-8",
1308
1259
  )
1309
1260
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(recording_gate_script_path))
1310
- _isolate_code_review_gate(tmp_path, monkeypatch)
1311
1261
  monkeypatch.chdir(repository)
1312
1262
  monkeypatch.setattr(
1313
1263
  sys,
@@ -1324,13 +1274,73 @@ def test_main_skips_the_gate_when_no_merge_base_resolves(
1324
1274
 
1325
1275
  exit_code = pre_push.main()
1326
1276
 
1327
- assert exit_code == 0
1277
+ assert exit_code == git_hooks_constants.GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE
1328
1278
  assert not recorded_arguments_path.exists(), (
1329
- "the gate ran on a base the hook could not verify"
1279
+ "the gate remains pending until the hook verifies a usable base"
1330
1280
  )
1331
1281
  assert git_hooks_constants.UNRESOLVABLE_MERGE_BASE_MESSAGE in capsys.readouterr().err
1332
1282
 
1333
1283
 
1284
+ def test_main_uses_the_pushed_remote_when_origin_has_unrelated_history(
1285
+ tmp_path: Path,
1286
+ monkeypatch: pytest.MonkeyPatch,
1287
+ ) -> None:
1288
+ repository, default_branch_tip, topic_branch_tip = _build_default_branch_repository(
1289
+ tmp_path
1290
+ )
1291
+ _run_fixture_git(repository, "checkout", "--orphan", "unrelated-origin")
1292
+ _run_fixture_git(repository, "rm", "-rf", ".")
1293
+ unrelated_origin_tip = _commit_file(repository, "unrelated.txt")
1294
+ _run_fixture_git(repository, "checkout", FEATURE_BRANCH_NAME)
1295
+ _run_fixture_git(
1296
+ repository,
1297
+ "update-ref",
1298
+ ORIGIN_DEFAULT_BRANCH_REFERENCE,
1299
+ unrelated_origin_tip,
1300
+ )
1301
+ _set_origin_head(repository, ORIGIN_DEFAULT_BRANCH_REFERENCE)
1302
+ upstream_reference = "refs/remotes/upstream/main"
1303
+ upstream_head_reference = "refs/remotes/upstream/HEAD"
1304
+ _run_fixture_git(repository, "update-ref", upstream_reference, default_branch_tip)
1305
+ _run_fixture_git(
1306
+ repository, "symbolic-ref", upstream_head_reference, upstream_reference
1307
+ )
1308
+ recorded_arguments_path = tmp_path / "upstream_recorded_arguments.txt"
1309
+ recording_gate_script_path = tmp_path / "upstream_recording_gate.py"
1310
+ recording_gate_script_path.write_text(
1311
+ "import pathlib, sys\n"
1312
+ f'pathlib.Path(r"{recorded_arguments_path}").write_text('
1313
+ "'\\n'.join(sys.argv[1:]), encoding='utf-8')\n"
1314
+ "sys.exit(0)\n",
1315
+ encoding="utf-8",
1316
+ )
1317
+ monkeypatch.setenv("CODE_RULES_GATE_PATH", str(recording_gate_script_path))
1318
+ monkeypatch.chdir(repository)
1319
+ monkeypatch.setattr(
1320
+ sys, "argv", [HOOK_INVOCATION_NAME, PUSHED_REMOTE_NAME, PUSHED_REMOTE_URL]
1321
+ )
1322
+ monkeypatch.setattr(
1323
+ sys,
1324
+ "stdin",
1325
+ io.StringIO(
1326
+ _push_stdin_line(
1327
+ FEATURE_BRANCH_NAME,
1328
+ topic_branch_tip,
1329
+ FEATURE_BRANCH_NAME,
1330
+ NON_ZERO_REMOTE_SHA_ONE,
1331
+ )
1332
+ ),
1333
+ )
1334
+
1335
+ exit_code = pre_push.main()
1336
+
1337
+ assert exit_code == 0
1338
+ assert recorded_arguments_path.read_text(encoding="utf-8").splitlines() == [
1339
+ "--base",
1340
+ default_branch_tip,
1341
+ ]
1342
+
1343
+
1334
1344
  def test_main_allows_default_branch_file_the_rebase_replayed_onto(
1335
1345
  tmp_path: Path,
1336
1346
  monkeypatch: pytest.MonkeyPatch,
@@ -1342,7 +1352,6 @@ def test_main_allows_default_branch_file_the_rebase_replayed_onto(
1342
1352
  )
1343
1353
  _set_origin_head(repository, ORIGIN_DEFAULT_BRANCH_REFERENCE)
1344
1354
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1345
- _isolate_code_review_gate(tmp_path, monkeypatch)
1346
1355
  monkeypatch.chdir(repository)
1347
1356
  monkeypatch.setattr(
1348
1357
  sys,
@@ -1370,7 +1379,6 @@ def test_main_blocks_violation_the_branch_itself_adds(
1370
1379
  )
1371
1380
  _set_origin_head(repository, ORIGIN_DEFAULT_BRANCH_REFERENCE)
1372
1381
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1373
- _isolate_code_review_gate(tmp_path, monkeypatch)
1374
1382
  monkeypatch.chdir(repository)
1375
1383
  monkeypatch.setattr(
1376
1384
  sys,
@@ -1407,7 +1415,6 @@ def test_main_uses_remote_object_when_no_default_branch_reference_resolves(
1407
1415
  encoding="utf-8",
1408
1416
  )
1409
1417
  monkeypatch.setenv("CODE_RULES_GATE_PATH", str(recording_gate_script_path))
1410
- _isolate_code_review_gate(tmp_path, monkeypatch)
1411
1418
  monkeypatch.chdir(repository)
1412
1419
  monkeypatch.setattr(
1413
1420
  sys,
@@ -1446,7 +1453,6 @@ def test_main_uses_remote_object_when_the_default_branch_is_pushed(
1446
1453
  )
1447
1454
  _set_origin_head(repository, ORIGIN_DEFAULT_BRANCH_REFERENCE)
1448
1455
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1449
- _isolate_code_review_gate(tmp_path, monkeypatch)
1450
1456
  monkeypatch.chdir(repository)
1451
1457
  monkeypatch.setattr(
1452
1458
  sys,
@@ -1481,7 +1487,6 @@ def test_main_uses_merge_base_when_a_default_named_local_branch_updates_a_topic_
1481
1487
  )
1482
1488
  _set_origin_head(repository, ORIGIN_UNPROTECTED_DEFAULT_BRANCH_REFERENCE)
1483
1489
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1484
- _isolate_code_review_gate(tmp_path, monkeypatch)
1485
1490
  monkeypatch.chdir(repository)
1486
1491
  monkeypatch.setattr(
1487
1492
  sys,
@@ -1517,7 +1522,6 @@ def test_main_uses_remote_object_when_a_renamed_local_branch_updates_the_default
1517
1522
  )
1518
1523
  _set_origin_head(repository, ORIGIN_UNPROTECTED_DEFAULT_BRANCH_REFERENCE)
1519
1524
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1520
- _isolate_code_review_gate(tmp_path, monkeypatch)
1521
1525
  monkeypatch.chdir(repository)
1522
1526
  monkeypatch.setattr(
1523
1527
  sys,
@@ -1547,7 +1551,6 @@ def test_main_reads_default_branch_tracking_reference_when_origin_head_is_unset(
1547
1551
  branch_file_name=BRANCH_FILE_NAME,
1548
1552
  )
1549
1553
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1550
- _isolate_code_review_gate(tmp_path, monkeypatch)
1551
1554
  monkeypatch.chdir(repository)
1552
1555
  monkeypatch.setattr(
1553
1556
  sys,
@@ -1575,7 +1578,6 @@ def test_main_skips_a_deletion_line_to_reach_the_branch_update(
1575
1578
  )
1576
1579
  _set_origin_head(repository, ORIGIN_DEFAULT_BRANCH_REFERENCE)
1577
1580
  _write_diff_scoped_gate(tmp_path, monkeypatch)
1578
- _isolate_code_review_gate(tmp_path, monkeypatch)
1579
1581
  monkeypatch.chdir(repository)
1580
1582
  deletion_line = (
1581
1583
  f"(delete) {ALL_ZEROS_OBJECT_NAME} refs/heads/retired {NON_ZERO_REMOTE_SHA_ONE}\n"
@@ -1594,31 +1596,3 @@ def test_main_skips_a_deletion_line_to_reach_the_branch_update(
1594
1596
  exit_code = pre_push.main()
1595
1597
 
1596
1598
  assert exit_code == 0
1597
-
1598
-
1599
- def test_main_allows_when_code_review_enforcement_flag_is_off(
1600
- tmp_path: Path,
1601
- monkeypatch: pytest.MonkeyPatch,
1602
- ) -> None:
1603
- """Native pre-push honors the real gate with enforcement off.
1604
-
1605
- Points at the production push gate (not a reason stub). The gate resolves
1606
- its flag when its config module first executes, so this test clears the
1607
- environment variable and evicts that one module if a sibling suite cached
1608
- it earlier in the same session. The gate then returns no deny reason and
1609
- the backstop allows the push.
1610
- """
1611
- monkeypatch.delenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, raising=False)
1612
- monkeypatch.delitem(sys.modules, ENFORCEMENT_CONSTANTS_MODULE_NAME, raising=False)
1613
- _isolate_repository_and_write_passing_code_rules_gate(tmp_path, monkeypatch)
1614
- real_gate_path = (
1615
- Path(__file__).resolve().parent.parent
1616
- / "blocking"
1617
- / "code_review_push_gate.py"
1618
- )
1619
- assert real_gate_path.is_file()
1620
- monkeypatch.setenv("CODE_REVIEW_PUSH_GATE_PATH", str(real_gate_path))
1621
-
1622
- exit_code = pre_push.main()
1623
-
1624
- assert exit_code == 0
package/hooks/hooks.json CHANGED
@@ -42,16 +42,6 @@
42
42
  }
43
43
  ]
44
44
  },
45
- {
46
- "matcher": "mcp__plugin_github_github__create_pull_request",
47
- "hooks": [
48
- {
49
- "type": "command",
50
- "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/code_review_pr_create_gate.py",
51
- "timeout": 20
52
- }
53
- ]
54
- },
55
45
  {
56
46
  "matcher": "mcp__plugin_github_github__.*",
57
47
  "hooks": [
@@ -67,24 +57,9 @@
67
57
  }
68
58
  ]
69
59
  },
70
- {
71
- "matcher": "Agent",
72
- "hooks": [
73
- {
74
- "type": "command",
75
- "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/pr_converge_bugteam_enforcer.py",
76
- "timeout": 10
77
- }
78
- ]
79
- },
80
60
  {
81
61
  "matcher": "Agent|Task",
82
62
  "hooks": [
83
- {
84
- "type": "command",
85
- "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/code_verifier_spawn_preflight_gate.py",
86
- "timeout": 30
87
- },
88
63
  {
89
64
  "type": "command",
90
65
  "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/blocking/fable_spawn_gate.py",
@@ -102,16 +77,6 @@
102
77
  }
103
78
  ]
104
79
  },
105
- {
106
- "matcher": "Skill",
107
- "hooks": [
108
- {
109
- "type": "command",
110
- "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/lifecycle/pr_converge_bugteam_skill_tracker.py",
111
- "timeout": 10
112
- }
113
- ]
114
- },
115
80
  {
116
81
  "matcher": "AskUserQuestion",
117
82
  "hooks": [
@@ -0,0 +1,104 @@
1
+ # hooks/hooks_constants
2
+
3
+ Shared constant modules imported by hooks throughout the `hooks/` tree. Each file holds the tunables for one hook or one cross-cutting concern, keeping magic values out of the hook scripts themselves.
4
+
5
+ ## Files
6
+
7
+ | File | What it holds |
8
+ |---|---|
9
+ | `__init__.py` | Package marker (`# pragma: no-tdd-gate`) |
10
+ | `any_type_config.py` | Config for the `Any`-type escape-hatch check |
11
+ | `ask_user_question_shape.py` | Pure AskUserQuestion lean-block shape analyzer: grades question and option-description prose against shared chat-detail markers and sentence/word caps with no hook I/O |
12
+ | `banned_identifiers_constants.py` | The set of banned short identifiers and banned function-name prefixes |
13
+ | `bash_pre_tool_use_dispatcher_constants.py` | Permission outcomes, tool-name sets, and the ordered hosted-hook roster for the Bash PreToolUse dispatcher (also covers PowerShell-shared gates) |
14
+ | `blocking_check_limits.py` | Max issue counts and preview lengths for blocking hooks |
15
+ | `bot_mention_comment_blocker_constants.py` | Patterns for detecting bot @-mentions in PR comments |
16
+ | `claude_md_orphan_file_blocker_constants.py` | Table patterns, file extensions, scan budget, and block-message text for the CLAUDE.md orphan-file blocker |
17
+ | `code_rules_enforcer_constants.py` | File-extension sets, test-path patterns, advisory line thresholds, boolean-name prefixes |
18
+ | `enter_worktree_prefetch_constants.py` | Tool name, origin-remote ref names, and git-command timeouts for the EnterWorktree origin-prefetch hook |
19
+ | `env_var_table_code_drift_constants.py` | Table patterns, env-var-name and code-file recognizers, scan budget, and block-message text for the env-var-table code-drift blocker |
20
+ | `code_rules_path_utils_constants.py` | Path-matching helpers used by the code-rules check modules |
21
+ | `command_dispatch_constants.py` | Command-word regex, command-key access pattern, tokenization pattern, and anchors for the unanchored command-dispatch meta-gate |
22
+ | `conventional_pr_title_gate_constants.py` | Bash tool name, gh executable basenames and pr create/edit subcommand tokens, title/repo flag names, semantic-title-CI workflow markers, the Conventional Commits type list and title pattern, the semantic-pull-request action `types:` input pattern, and block-message text for the conventional-PR-title gate |
23
+ | `dead_argparse_argument_constants.py` | Patterns for detecting unused argparse arguments |
24
+ | `dead_config_field_constants.py` | Patterns for detecting unused `*Config` / `*Selectors` dataclass fields |
25
+ | `dead_dataclass_field_constants.py` | Patterns for detecting unused dataclass fields |
26
+ | `dead_module_constant_constants.py` | Patterns for detecting unexported `UPPER_SNAKE` constants in `*_constants.py` modules |
27
+ | `destructive_command_segment_constants.py` | The list of destructive shell command patterns the blocker matches |
28
+ | `docstring_rule_gate_count_blocker_constants.py` | Target rule basename, spelled-out-number lookup, count-clause and `check_*` validator patterns, and block-message text for the docstring-rule gate-count staleness blocker |
29
+ | `duplicate_function_body_constants.py` | Hashing and comparison config for the duplicate-body check |
30
+ | `duplicate_rmtree_helper_blocker_constants.py` | Sanctioned Windows-safe rmtree helper names, the definition pattern, and the exempt-path set for the duplicate-rmtree-helper blocker |
31
+ | `dynamic_stderr_handler.py` | `DynamicStderrHandler` — a logging handler that resolves `sys.stderr` at emit time (for testability) |
32
+ | `eli11_reply_enforcer_constants.py` | Reply-shape thresholds (bullet cap, lead-line window, per-list-line word cap, overpacked list-line cap), the bullet / numbered-step / table-row / link-target / word patterns, the imperative instruction verbs, and the user-facing notice for the ELI11 reply-shape Stop hook |
33
+ | `fable_spawn_gate_constants.py` | The spawn tool-name set, the fable model alias and the model-id segment split pattern, the `FABLE-SPAWN-AUTHORIZED` authorization token, the advisor-protocol document path, payload field names, the deny message, and the deny `additionalContext` recovery text for the fable-tier spawn gate |
34
+ | `gh_pr_author_swap_constants.py` | Constants for the PR-author swap enforcement hooks |
35
+ | `hardcoded_user_path_constants.py` | Patterns for detecting hardcoded home-directory paths |
36
+ | `harness_scratchpad_constants.py` | Fixed path components (`claude` / `claude-` user-directory name and prefix, `scratchpad` leaf name), the PreToolUse session-id payload key, and the `CLAUDE_CODE_SESSION_ID` environment variable name that the code-rules and TDD gates use to recognize an existing harness session scratchpad directory |
37
+ | `hedging_uncertainty_constants.py` | Sentence-boundary pattern, explicit uncertainty label patterns, hedge-term list separator, and positive corrective block text for OP-07C sentence-scoped hedging |
38
+ | `hook_block_logger.py` | `log_hook_block()` — shared fail-safe logger every blocking hook calls to append a JSON record of each block decision to `~/.claude/logs/hook-blocks.log` |
39
+ | `hook_log_extractor_constants.py` | Neon table name, offset state file path, timeouts, and outcome-type mapping for the hook-log extractor |
40
+ | `hook_prose_detector_consistency_constants.py` | Trigger patterns and corrective messages for the hook-prose consistency checker |
41
+ | `hosted_hook_runner.py` | `run_hook_capturing_output()` — shared runner that runs one dispatcher-hosted hook in-process via runpy and returns its captured stdout and crash flag |
42
+ | `inline_tuple_string_magic_constants.py` | Patterns for detecting magic strings in inline tuple literals |
43
+ | `js_conventions_constants.py` | Banned identifier set, boolean-prefix pattern, and declaration/JSDoc patterns for the JavaScript convention checks |
44
+ | `local_identity.py` | Loader for local machine values: NAS host, ssh user, and ssh port the ssh enforcer guards (`CLAUDE_NAS_*` / `~/.claude/local-identity.json` with placeholder defaults), the PII commit-scan exempt-repo slug set (`CLAUDE_PII_EXEMPT_REPOS` / `pii_exempt_repositories`), and the per-repository allowlisted-values mapping (`pii_allowlisted_values`, keyed by owner/repo slug) read from the git-ignored local file whose path `CLAUDE_LOCAL_IDENTITY_PATH` may point elsewhere; also composes the ssh enforcer's two deny messages that quote the NAS values |
45
+ | `messages.py` | Short user-facing notice strings shown when a Stop hook redirects agent behavior |
46
+ | `multi_edit_reconstruction.py` | `apply_edits()` / `edits_for_tool()` — shared helpers that reconstruct the post-edit content of an Edit or MultiEdit, imported by the blockers that judge post-edit content |
47
+ | `mypy_integration_constants.py` | Path markers (``.git``, ``.py``, ``pyproject.toml``) for mypy project-root resolution |
48
+ | `mypy_validator_cache_constants.py` | Cache paths and tunables for the mypy_validator per-session caches |
49
+ | `nas_ssh_binary_enforcer_constants.py` | Bash tool name, ssh-family basenames, OpenSSH binary path suffixes, and the batch-mode pattern for the NAS ssh binary enforcer; segment helpers come from `shell_command_segments.py` |
50
+ | `open_questions_in_plans_blocker_constants.py` | Patterns for detecting unresolved open questions in plan documents |
51
+ | `orphan_css_class_constants.py` | Scan radius and selector patterns for the orphan-CSS-class check |
52
+ | `package_inventory_stale_blocker_constants.py` | Inventory document names, production code extensions, backtick token pattern, smallest inventory size, exempt names, scan budget, and block-message text for the package-inventory stale-entry blocker |
53
+ | `paired_test_coverage_constants.py` | Test-directory name, stem-test filename affixes, test-file globs, exempt public-function names, scan budget, coverage threshold, and guidance text for the public-function paired-test coverage check |
54
+ | `path_rewriter_constants.py` | Path rewriting patterns for the Everything-search path rewriter |
55
+ | `pii_prevention_constants.py` | Patterns, allowlists, path exemptions, and deny-message text for `pii_prevention_blocker` |
56
+ | `piped_pytest_blocker_constants.py` | Bash tool name, pytest program basenames and the python-interpreter basename pattern, the pipe and segment-reset operator token sets, and the deny message for the piped-pytest blocker; classification that consumes those program and wrapper constants lives in `pytest_invocation.py` |
57
+ | `pytest_invocation.py` | Pure parsed-segment classifier for pytest runs through interpreters, shims, wrappers, and shell string-exec forms; no pipeline deny decision |
58
+ | `plain_language_blocker_constants.py` | The list of heavy words and their everyday replacements |
59
+ | `prose_matcher_precision_constants.py` | Sample floor, keep/narrow precision floors, matcher ids, label decisions, advisory log path, emit caps, and context fingerprint length for OP-07B prose-matcher advisory telemetry |
60
+ | `pre_tool_use_stdin.py` | `read_hook_input_dictionary_from_stdin()` — shared stdin parser for PreToolUse hooks |
61
+ | `precommit_code_rules_gate_constants.py` | Scope argument and exit-code constants for the precommit gate |
62
+ | project_paths_reader.py | Loads ~/.claude/project-paths.json and finds a home-bounded git root for registry checks |
63
+ | `pyproject_config_discovery_constants.py` | Table names (``tool`` key, ``mypy``, ``ruff``) for resolving a validator's config from a pyproject.toml `[tool.<name>]` table |
64
+ | `pytest_testpaths_orphan_blocker_constants.py` | Marker filename, section and key names, test-file pattern, search budget, and block-message text for the pytest unregistered-test-directory blocker |
65
+ | `python_style_checks_constants.py` | Command-line argument count and blank-line count between top-level functions for the style validator |
66
+ | `ruff_integration_constants.py` | ``NO_COLOR`` / ``FORCE_COLOR`` environment variable names for plain ruff diagnostics |
67
+ | `send_user_file_open_locally_blocker_constants.py` | Tool name, proactive status, and the block message for the open-locally attach blocker |
68
+ | `sensitive_file_protector_constants.py` | Sensitive filename patterns, the committed-template suffixes that earn an exemption, the write/edit tool names, and the deny decision and message template for `sensitive_file_protector` |
69
+ | `session_edit_stage_gate_constants.py` | Tracker filename prefix/suffix, JSON payload key, edit tool name set, session-id sanitize pattern, lock filename suffix and lock-acquire timing, git diff command, commit flag escapes, and deny-message template shared by the session edit stage gate trio |
70
+ | `session_env_cleanup_constants.py` | Stale-age threshold and directory names for the session-env cleanup hook |
71
+ | `session_start_injector.py` | Pure SessionStart context injector: normalize `source` (`startup`/`resume`/`clear`/`compact`), honor enable/timeout, return structured injection results for starter hooks |
72
+ | `session_start_injector_constants.py` | Known SessionStart source values, injection status codes, enable env var, default timeout for the shared injector |
73
+ | `test_session_start_injector.py` | Behavioral tests for every known source, disabled, timeout, and unknown-source paths |
74
+ | `orchestrator_auto_starter_constants.py` | Opt-in env var, enable values, timeout, and SessionStart directive text for the orchestrator auto-starter |
75
+ | `issue_tracker_session_starter_constants.py` | Opt-in env var, enable values, timeout, and SessionStart directive text for the repository-gated issue-tracker starter |
76
+ | `session_handoff_blocker_constants.py` | Trigger phrases for the session-handoff blocker |
77
+ | `setup_project_paths_constants.py` | Encoding policy, BOM marker, and registry meta-key used across multiple hooks |
78
+ | `shell_command_pipeline.py` | Quote-aware shell pipeline parsing: operator-paired segments after line-continuation join, comment strip, heredoc body drop, and parenthesis-group join |
79
+ | `shell_command_segments.py` | Shell tokenization helpers shared by the segment-walking blockers: segment splitting on control operators, a segment's effective leading program, and a token's basename |
80
+ | `shell_substitution_blocker_constants.py` | Tool name, payload keys, the four substitution-detection patterns, the deny decision shape, and the corrective message for the shell-substitution blocker |
81
+ | `stale_comment_reference_blocker_constants.py` | Identifier pattern, comment stopwords, and denial text for the stale-comment-reference blocker |
82
+ | `state_description_blocker_constants.py` | The set of historical/comparative phrases the state-description blocker rejects, plus the docstring-extraction and mention-span patterns for its Python docstring scan |
83
+ | `stop_dispatcher_constants.py` | Ordered hosted-hook roster and Stop block payload field names for the Stop-chain dispatcher |
84
+ | `stuttering_check_config.py` | Config for the stuttering (repeated-phrase) check |
85
+ | `stuttering_import_binding_constants.py` | Import-binding patterns for the stuttering check |
86
+ | `subprocess_budget_completeness_constants.py` | Required argument names for the subprocess-budget completeness check |
87
+ | `sys_path_insert_constants.py` | Patterns for detecting unguarded `sys.path.insert` calls |
88
+ | `task_list_loop_starter_constants.py` | The one-line task-list instruction and the full session-start directive text for the task-list loop starter hook |
89
+ | `test_layout_constants.py` | The named constants for the test-layout write-time checks |
90
+ | `text_stripping.py` | `strip_code_and_quotes()` — shared helper that removes fenced code blocks, inline code, and blockquotes from prose, imported by the Stop-hook prose blockers |
91
+ | `unscoped_search_blocker_constants.py` | Tool names, `find` and listing program basenames, Get-ChildItem option sets, unscoped-root patterns, the flag/value token stride, and the deny message for the unscoped-search blocker |
92
+ | `unused_module_import_constants.py` | Patterns for detecting unused module-level imports |
93
+ | `volatile_path_in_post_blocker_constants.py` | Volatile path markers, affected `gh` post subcommands, MCP body param names, and the corrective message for the volatile-path post blocker |
94
+ | `windows_rmtree_blocker_constants.py` | The unsafe `shutil.rmtree` pattern and the safe replacement pattern |
95
+ | `workflow_substitution_slot_blocker_constants.py` | Per-iteration token patterns for the workflow-slot blocker |
96
+ | `working_style_prompt_constants.py` | The fixed multi-paragraph working-style prompt text for the SessionStart working_style_prompt hook |
97
+
98
+ ## Conventions
99
+
100
+ - Most files in this package are pure constants modules — no side effects, no I/O.
101
+ - Hooks import from this package with `from hooks_constants.<module> import <CONSTANT>`.
102
+ - Tests for these modules live beside them as `test_<module>.py`. Run with `python -m pytest hooks_constants/test_<name>.py`.
103
+ - `dynamic_stderr_handler.py`, `pre_tool_use_stdin.py`, `multi_edit_reconstruction.py`, `hosted_hook_runner.py`, and `text_stripping.py` are utility modules (not pure constants) but live here because they hold logic shared across hook surfaces.
104
+ - `local_identity.py` is a loader: it reads the environment or `~/.claude/local-identity.json` (its path overridable via `CLAUDE_LOCAL_IDENTITY_PATH`) to resolve private NAS values (with committed placeholder defaults), the PII commit-scan exempt-repo slug set (`CLAUDE_PII_EXEMPT_REPOS` / `pii_exempt_repositories`), and the per-repository allowlisted-values mapping (`pii_allowlisted_values`).