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
@@ -1,345 +1,17 @@
1
- """Tests for hook_log_stop_wrapper -- debounced, fire-and-forget Stop hook."""
1
+ """Tests for the disabled hook_log_stop_wrapper Stop hook."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import os
6
- import subprocess
7
5
  import sys
8
- import time
9
6
  from pathlib import Path
10
7
 
11
- import pytest
12
-
13
8
  _HOOKS_ROOT = Path(__file__).resolve().parent.parent
14
9
  if str(_HOOKS_ROOT) not in sys.path:
15
10
  sys.path.insert(0, str(_HOOKS_ROOT))
16
11
 
17
12
  from diagnostic import hook_log_stop_wrapper
18
- from hooks_constants.hook_log_extractor_constants import (
19
- BWS_ACCESS_TOKEN_ENV_VAR,
20
- BWS_EXECUTABLE_NAME,
21
- FLAG_INCREMENTAL,
22
- STOP_WRAPPER_DEBOUNCE_SECONDS,
23
- )
24
-
25
-
26
- def _redirect_timestamp_path(
27
- monkeypatch: pytest.MonkeyPatch, tmp_path: Path
28
- ) -> Path:
29
- timestamp_file = tmp_path / "stop_wrapper_last_run.txt"
30
- monkeypatch.setattr(
31
- hook_log_stop_wrapper,
32
- "_last_run_timestamp_path",
33
- lambda: timestamp_file,
34
- )
35
- return timestamp_file
36
-
37
-
38
- def test_main_returns_zero_when_extractor_spawn_raises(
39
- monkeypatch: pytest.MonkeyPatch,
40
- tmp_path: Path,
41
- ) -> None:
42
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
43
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
44
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
45
-
46
- def _raise(*_args: object, **_kwargs: object) -> None:
47
- raise RuntimeError("boom")
48
13
 
49
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _raise)
50
14
 
15
+ def test_main_returns_zero_without_side_effects() -> None:
16
+ """Disabled main exits success and does no work."""
51
17
  assert hook_log_stop_wrapper.main() == 0
52
- assert not timestamp_file.exists()
53
-
54
-
55
- def test_main_writes_timestamp_before_spawn_to_narrow_toctou_window(
56
- monkeypatch: pytest.MonkeyPatch,
57
- tmp_path: Path,
58
- ) -> None:
59
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
60
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
61
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
62
-
63
- timestamp_file_existed_at_spawn_time: list[bool] = []
64
-
65
- def _capture_timestamp_state(*_args: object, **_kwargs: object) -> object:
66
- timestamp_file_existed_at_spawn_time.append(timestamp_file.exists())
67
- return object()
68
-
69
- monkeypatch.setattr(
70
- hook_log_stop_wrapper.subprocess, "Popen", _capture_timestamp_state
71
- )
72
-
73
- hook_log_stop_wrapper.main()
74
-
75
- assert timestamp_file_existed_at_spawn_time == [True]
76
-
77
-
78
- def test_main_removes_timestamp_when_spawn_fails_to_allow_retry(
79
- monkeypatch: pytest.MonkeyPatch,
80
- tmp_path: Path,
81
- ) -> None:
82
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
83
- timestamp_file.parent.mkdir(parents=True, exist_ok=True)
84
- stale_timestamp = time.time() - STOP_WRAPPER_DEBOUNCE_SECONDS - 1
85
- timestamp_file.write_text(str(stale_timestamp))
86
-
87
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
88
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
89
-
90
- def _raise(*_args: object, **_kwargs: object) -> None:
91
- raise RuntimeError("boom")
92
-
93
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _raise)
94
-
95
- assert hook_log_stop_wrapper.main() == 0
96
- assert not timestamp_file.exists()
97
-
98
-
99
- def test_main_uses_bws_when_token_and_binary_present(
100
- monkeypatch: pytest.MonkeyPatch,
101
- tmp_path: Path,
102
- ) -> None:
103
- _redirect_timestamp_path(monkeypatch, tmp_path)
104
- monkeypatch.setenv(BWS_ACCESS_TOKEN_ENV_VAR, "secret-value")
105
- monkeypatch.setattr(
106
- hook_log_stop_wrapper.shutil,
107
- "which",
108
- lambda _name: "/usr/local/bin/bws",
109
- )
110
-
111
- captured_commands: list[list[str]] = []
112
-
113
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
114
- captured_commands.append(list(command_list))
115
- return object()
116
-
117
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
118
-
119
- exit_code = hook_log_stop_wrapper.main()
120
-
121
- assert exit_code == 0
122
- assert len(captured_commands) == 1
123
- assert captured_commands[0][0] == BWS_EXECUTABLE_NAME
124
- assert FLAG_INCREMENTAL in captured_commands[0]
125
-
126
-
127
- def test_main_skips_bws_when_token_missing(
128
- monkeypatch: pytest.MonkeyPatch,
129
- tmp_path: Path,
130
- ) -> None:
131
- _redirect_timestamp_path(monkeypatch, tmp_path)
132
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
133
- monkeypatch.setattr(
134
- hook_log_stop_wrapper.shutil,
135
- "which",
136
- lambda _name: "/usr/local/bin/bws",
137
- )
138
-
139
- captured_commands: list[list[str]] = []
140
-
141
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
142
- captured_commands.append(list(command_list))
143
- return object()
144
-
145
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
146
-
147
- exit_code = hook_log_stop_wrapper.main()
148
-
149
- assert exit_code == 0
150
- assert len(captured_commands) == 1
151
- assert BWS_EXECUTABLE_NAME not in captured_commands[0]
152
-
153
-
154
- def test_main_skips_bws_when_binary_missing(
155
- monkeypatch: pytest.MonkeyPatch,
156
- tmp_path: Path,
157
- ) -> None:
158
- _redirect_timestamp_path(monkeypatch, tmp_path)
159
- monkeypatch.setenv(BWS_ACCESS_TOKEN_ENV_VAR, "secret-value")
160
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
161
-
162
- captured_commands: list[list[str]] = []
163
-
164
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
165
- captured_commands.append(list(command_list))
166
- return object()
167
-
168
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
169
-
170
- exit_code = hook_log_stop_wrapper.main()
171
-
172
- assert exit_code == 0
173
- assert len(captured_commands) == 1
174
- assert BWS_EXECUTABLE_NAME not in captured_commands[0]
175
-
176
-
177
- def test_main_skips_spawn_when_recent_timestamp_within_debounce_window(
178
- monkeypatch: pytest.MonkeyPatch,
179
- tmp_path: Path,
180
- ) -> None:
181
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
182
- timestamp_file.parent.mkdir(parents=True, exist_ok=True)
183
- timestamp_file.write_text(str(time.time()))
184
-
185
- captured_commands: list[list[str]] = []
186
-
187
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
188
- captured_commands.append(list(command_list))
189
- return object()
190
-
191
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
192
-
193
- exit_code = hook_log_stop_wrapper.main()
194
-
195
- assert exit_code == 0
196
- assert len(captured_commands) == 0
197
-
198
-
199
- def test_main_spawns_when_timestamp_older_than_debounce_window(
200
- monkeypatch: pytest.MonkeyPatch,
201
- tmp_path: Path,
202
- ) -> None:
203
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
204
- timestamp_file.parent.mkdir(parents=True, exist_ok=True)
205
- stale_timestamp = time.time() - STOP_WRAPPER_DEBOUNCE_SECONDS - 1
206
- timestamp_file.write_text(str(stale_timestamp))
207
-
208
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
209
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
210
-
211
- captured_commands: list[list[str]] = []
212
-
213
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
214
- captured_commands.append(list(command_list))
215
- return object()
216
-
217
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
218
-
219
- exit_code = hook_log_stop_wrapper.main()
220
-
221
- assert exit_code == 0
222
- assert len(captured_commands) == 1
223
-
224
-
225
- def test_main_writes_current_timestamp_to_file(
226
- monkeypatch: pytest.MonkeyPatch,
227
- tmp_path: Path,
228
- ) -> None:
229
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
230
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
231
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
232
- monkeypatch.setattr(
233
- hook_log_stop_wrapper.subprocess,
234
- "Popen",
235
- lambda *_args, **_kwargs: object(),
236
- )
237
-
238
- timestamp_before_call = time.time()
239
- hook_log_stop_wrapper.main()
240
- timestamp_after_call = time.time()
241
-
242
- assert timestamp_file.exists()
243
- written_timestamp = float(timestamp_file.read_text().strip())
244
- assert timestamp_before_call <= written_timestamp <= timestamp_after_call
245
-
246
-
247
- def test_main_passes_devnull_streams_to_detached_spawn(
248
- monkeypatch: pytest.MonkeyPatch,
249
- tmp_path: Path,
250
- ) -> None:
251
- _redirect_timestamp_path(monkeypatch, tmp_path)
252
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
253
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
254
-
255
- captured_kwargs: dict[str, object] = {}
256
-
257
- def _fake_popen(command_list: list[str], **kwargs: object) -> object:
258
- captured_kwargs.update(kwargs)
259
- return object()
260
-
261
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
262
-
263
- hook_log_stop_wrapper.main()
264
-
265
- assert captured_kwargs.get("stdin") is hook_log_stop_wrapper.subprocess.DEVNULL
266
- assert captured_kwargs.get("stdout") is hook_log_stop_wrapper.subprocess.DEVNULL
267
- assert captured_kwargs.get("stderr") is hook_log_stop_wrapper.subprocess.DEVNULL
268
-
269
-
270
- def test_main_recovers_when_timestamp_file_is_corrupted(
271
- monkeypatch: pytest.MonkeyPatch,
272
- tmp_path: Path,
273
- ) -> None:
274
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
275
- timestamp_file.parent.mkdir(parents=True, exist_ok=True)
276
- timestamp_file.write_text("not-a-float")
277
-
278
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
279
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
280
-
281
- captured_commands: list[list[str]] = []
282
-
283
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
284
- captured_commands.append(list(command_list))
285
- return object()
286
-
287
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
288
-
289
- exit_code = hook_log_stop_wrapper.main()
290
-
291
- assert exit_code == 0
292
- assert len(captured_commands) == 1
293
-
294
-
295
- def test_main_treats_future_timestamp_as_not_debounced(
296
- monkeypatch: pytest.MonkeyPatch,
297
- tmp_path: Path,
298
- ) -> None:
299
- timestamp_file = _redirect_timestamp_path(monkeypatch, tmp_path)
300
- timestamp_file.parent.mkdir(parents=True, exist_ok=True)
301
- far_future_timestamp = time.time() + 3600
302
- timestamp_file.write_text(str(far_future_timestamp))
303
-
304
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
305
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
306
-
307
- captured_commands: list[list[str]] = []
308
-
309
- def _fake_popen(command_list: list[str], **_kwargs: object) -> object:
310
- captured_commands.append(list(command_list))
311
- return object()
312
-
313
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
314
-
315
- exit_code = hook_log_stop_wrapper.main()
316
-
317
- assert exit_code == 0
318
- assert len(captured_commands) == 1
319
-
320
-
321
- def test_main_passes_hidden_startupinfo_on_windows(
322
- monkeypatch: pytest.MonkeyPatch,
323
- tmp_path: Path,
324
- ) -> None:
325
- _redirect_timestamp_path(monkeypatch, tmp_path)
326
- monkeypatch.delenv(BWS_ACCESS_TOKEN_ENV_VAR, raising=False)
327
- monkeypatch.setattr(hook_log_stop_wrapper.shutil, "which", lambda _name: None)
328
-
329
- captured_kwargs: dict[str, object] = {}
330
-
331
- def _fake_popen(command_list: list[str], **kwargs: object) -> object:
332
- captured_kwargs.update(kwargs)
333
- return object()
334
-
335
- monkeypatch.setattr(hook_log_stop_wrapper.subprocess, "Popen", _fake_popen)
336
-
337
- hook_log_stop_wrapper.main()
338
-
339
- if os.name == "nt":
340
- startup_info = captured_kwargs.get("startupinfo")
341
- assert startup_info is not None
342
- assert startup_info.dwFlags & subprocess.STARTF_USESHOWWINDOW
343
- assert startup_info.wShowWindow == subprocess.SW_HIDE
344
- else:
345
- assert captured_kwargs.get("start_new_session") is True
@@ -0,0 +1,31 @@
1
+ # hooks/git-hooks
2
+
3
+ Native git hooks that run outside the Claude Code lifecycle — invoked directly by git at commit and push time. The installer copies these scripts into the user's shared git-hooks directory (`core.hooksPath`).
4
+
5
+ ## Key files
6
+
7
+ | File | Git hook | What it does |
8
+ |---|---|---|
9
+ | `pre_commit.py` | `pre-commit` | Runs the CODE_RULES gate (`precommit_code_rules_gate.py`) over staged changes; exits 1 when any staged file has a blocking violation |
10
+ | `pre_push.py` | `pre-push` | Blocks a push that would land a non-`main` local branch onto remote `main` (or `master`), then runs the CODE_RULES gate. An existing branch's gate base is the merge base with the remote default branch; the gate process still diffs that base against checkout HEAD, so the surface matches the pushed tip only when HEAD is that tip. |
11
+ | `pre_push_base_reference.py` | — | Resolves a usable gate base for `pre_push.py`: reads the pushed remote name from git's arguments, then turns a symbolic default-branch head into a reference that git can resolve |
12
+ | `post_commit.py` | `post-commit` | Runs after a commit lands; performs any post-commit bookkeeping |
13
+ | `gate_utils.py` | — | Shared helpers: resolves the gate script path, checks that the path is a safe regular file |
14
+ | `test_config.py` | — | Test configuration helpers |
15
+ | `test_gate_utils.py` | — | Tests for `gate_utils.py` |
16
+ | `test_pre_commit.py` | — | Tests for `pre_commit.py` |
17
+ | `test_pre_push.py` | — | Tests for `pre_push.py` |
18
+ | `test_pre_push_base_reference.py` | — | Tests for the gate base resolution in `pre_push.py` |
19
+ | `conftest.py` | — | Puts this directory on `sys.path` and clears cached `config` modules, so each test module imports the hooks at the top of the file |
20
+
21
+ ## Subdirectory
22
+
23
+ | Directory | Role |
24
+ |---|---|
25
+ | `git_hooks_constants/` | Shared constants imported by the git-hook scripts |
26
+
27
+ ## Conventions
28
+
29
+ - The installer strips the `_` and `.py` suffix when copying into the live git-hooks path (e.g. `pre_commit.py` becomes `pre-commit`).
30
+ - Constants (exit codes, argument names, error messages) live in `git_hooks_constants/` and are imported at the top of each script.
31
+ - Run tests with `python -m pytest git-hooks/test_<name>.py`.
@@ -1,31 +1 @@
1
- # hooks/git-hooks
2
-
3
- Native git hooks that run outside the Claude Code lifecycle — invoked directly by git at commit and push time. The installer copies these scripts into the user's shared git-hooks directory (`core.hooksPath`).
4
-
5
- ## Key files
6
-
7
- | File | Git hook | What it does |
8
- |---|---|---|
9
- | `pre_commit.py` | `pre-commit` | Runs the CODE_RULES gate (`precommit_code_rules_gate.py`) over staged changes; exits 1 when any staged file has a blocking violation |
10
- | `pre_push.py` | `pre-push` | Blocks a push that would land a non-`main` local branch onto remote `main` (or `master`), then runs the CODE_RULES gate. An existing branch's gate base is the merge base with the remote default branch; the gate process still diffs that base against checkout HEAD, so the surface matches the pushed tip only when HEAD is that tip. |
11
- | `pre_push_base_reference.py` | — | Resolves a usable gate base for `pre_push.py`: reads the pushed remote name from git's arguments, then turns a symbolic default-branch head into a reference that git can resolve |
12
- | `post_commit.py` | `post-commit` | Runs after a commit lands; performs any post-commit bookkeeping |
13
- | `gate_utils.py` | — | Shared helpers: resolves the gate script path, checks that the path is a safe regular file |
14
- | `test_config.py` | — | Test configuration helpers |
15
- | `test_gate_utils.py` | — | Tests for `gate_utils.py` |
16
- | `test_pre_commit.py` | — | Tests for `pre_commit.py` |
17
- | `test_pre_push.py` | — | Tests for `pre_push.py` |
18
- | `test_pre_push_base_reference.py` | — | Tests for the gate base resolution in `pre_push.py` |
19
- | `conftest.py` | — | Puts this directory on `sys.path` and clears cached `config` modules, so each test module imports the hooks at the top of the file |
20
-
21
- ## Subdirectory
22
-
23
- | Directory | Role |
24
- |---|---|
25
- | `git_hooks_constants/` | Shared constants imported by the git-hook scripts |
26
-
27
- ## Conventions
28
-
29
- - The installer strips the `_` and `.py` suffix when copying into the live git-hooks path (e.g. `pre_commit.py` becomes `pre-commit`).
30
- - Constants (exit codes, argument names, error messages) live in `git_hooks_constants/` and are imported at the top of each script.
31
- - Run tests with `python -m pytest git-hooks/test_<name>.py`.
1
+ @AGENTS.md
@@ -0,0 +1,21 @@
1
+ # hooks/git-hooks/git_hooks_constants
2
+
3
+ Shared constants imported by the git-hook scripts in `git-hooks/`. Centralizes exit codes, argument names, and error messages so every tunable lives in one place.
4
+
5
+ ## Files
6
+
7
+ | File | Contents |
8
+ |---|---|
9
+ | `__init__.py` | Exports all constants; marks this as a package so `from git_hooks_constants import ...` resolves |
10
+
11
+ ## Key constants (defined in `__init__.py`)
12
+
13
+ - `GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE` — exit code when the gate script cannot be found or launched
14
+ - `GATE_SCRIPT_NOT_FOUND_MESSAGE` — error message when the gate script path does not exist
15
+ - `INVOKE_GATE_FAILURE_MESSAGE` — error message when the gate subprocess fails to start
16
+ - `STAGED_SCOPE_ARGUMENT` — CLI argument passed to the gate script to scope it to staged changes
17
+
18
+ ## Conventions
19
+
20
+ - Import with `from git_hooks_constants import <CONSTANT>` from within the `git-hooks/` directory.
21
+ - Add new constants here rather than inline in the hook scripts.
@@ -1,21 +1 @@
1
- # hooks/git-hooks/git_hooks_constants
2
-
3
- Shared constants imported by the git-hook scripts in `git-hooks/`. Centralizes exit codes, argument names, and error messages so every tunable lives in one place.
4
-
5
- ## Files
6
-
7
- | File | Contents |
8
- |---|---|
9
- | `__init__.py` | Exports all constants; marks this as a package so `from git_hooks_constants import ...` resolves |
10
-
11
- ## Key constants (defined in `__init__.py`)
12
-
13
- - `GATE_INFRASTRUCTURE_FAILURE_EXIT_CODE` — exit code when the gate script cannot be found or launched
14
- - `GATE_SCRIPT_NOT_FOUND_MESSAGE` — error message when the gate script path does not exist
15
- - `INVOKE_GATE_FAILURE_MESSAGE` — error message when the gate subprocess fails to start
16
- - `STAGED_SCOPE_ARGUMENT` — CLI argument passed to the gate script to scope it to staged changes
17
-
18
- ## Conventions
19
-
20
- - Import with `from git_hooks_constants import <CONSTANT>` from within the `git-hooks/` directory.
21
- - Add new constants here rather than inline in the hook scripts.
1
+ @AGENTS.md
@@ -49,12 +49,9 @@ NO_PARSEABLE_STDIN_LINES_MESSAGE: str = (
49
49
  NO_PARSEABLE_STDIN_LINES_SENTINEL: str = "__no_parseable_stdin_lines__"
50
50
  UNRESOLVABLE_MERGE_BASE_SENTINEL: str = "__unresolvable_merge_base__"
51
51
  UNRESOLVABLE_MERGE_BASE_MESSAGE: str = (
52
- "claude-dev-env pre-push: git found no merge base between the pushed object "
53
- "and the default branch, so the gate scope is unknown and "
54
- "enforcement is skipped. That happens when the pushed branch and the "
55
- "default branch hold unrelated histories, or when a default-branch ref "
56
- "resolved and merge-base still could not name a shared commit "
57
- "(for example a shallow clone missing the connecting history)."
52
+ "claude-dev-env pre-push: CODE_RULES validation is pending because the pushed "
53
+ "object and default branch have no shared merge base. Restore shared history "
54
+ "or provide a reachable default branch, then run the push again."
58
55
  )
59
56
  LOCAL_BRANCH_REFERENCE_PREFIX: str = "refs/heads/"
60
57
  ORIGIN_HEAD_SYMBOLIC_REFERENCE: str = "refs/remotes/origin/HEAD"
@@ -63,6 +60,7 @@ ALL_DEFAULT_BRANCH_FALLBACK_REFERENCES: tuple[str, ...] = (
63
60
  "refs/remotes/origin/main",
64
61
  "refs/remotes/origin/master",
65
62
  )
63
+ REMOTE_BRANCH_REFERENCE_TEMPLATE: str = "refs/remotes/{remote}/{branch}"
66
64
  ALL_GIT_SYMBOLIC_REFERENCE_COMMAND_PREFIX: tuple[str, ...] = (
67
65
  "git",
68
66
  "symbolic-ref",
@@ -76,12 +74,6 @@ ALL_GIT_VERIFY_REFERENCE_COMMAND_PREFIX: tuple[str, ...] = (
76
74
  )
77
75
  ALL_GIT_MERGE_BASE_COMMAND_PREFIX: tuple[str, ...] = ("git", "merge-base")
78
76
  GIT_REFERENCE_QUERY_TIMEOUT_SECONDS: int = 15
79
- CODE_REVIEW_PUSH_GATE_PATH_OVERRIDE_ENV_VAR: str = "CODE_REVIEW_PUSH_GATE_PATH"
80
- CODE_REVIEW_PUSH_GATE_MODULE_NAME: str = "code_review_push_gate"
81
- CODE_REVIEW_PUSH_GATE_SCRIPT_FILENAME: str = "code_review_push_gate.py"
82
- CODE_REVIEW_DENY_REASON_FUNCTION_NAME: str = "deny_reason_for_directory"
83
- BLOCKING_DIRECTORY_NAME: str = "blocking"
84
- CODE_REVIEW_STAMP_BLOCK_EXIT_CODE: int = 1
85
77
  ALL_PROTECTED_BRANCH_PUSH_NAMES: tuple[str, ...] = ("main", "master")
86
78
  PROTECTED_BRANCH_PUSH_BLOCK_EXIT_CODE: int = 1
87
79
  PROTECTED_BRANCH_PUSH_BLOCK_MESSAGE: str = (