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,166 +0,0 @@
1
- """Behavioral tests for the code-review enforcement constants and comparator.
2
-
3
- These exercise ``effort_meets_threshold`` against the ordered effort tokens and
4
- assert the push and pull-request thresholds carry the push-based names the gate
5
- family reads, so a rename that reintroduces commit terminology fails loudly.
6
- """
7
-
8
- import importlib.util
9
- import pathlib
10
- import re
11
-
12
- import pytest
13
-
14
- _CONFIG_DIR = pathlib.Path(__file__).parent
15
-
16
- SAMPLE_ROOT_KEY_HEX_LENGTH = 16
17
-
18
- _constants_spec = importlib.util.spec_from_file_location(
19
- "code_review_enforcement_constants",
20
- _CONFIG_DIR / "code_review_enforcement_constants.py",
21
- )
22
- assert _constants_spec is not None
23
- assert _constants_spec.loader is not None
24
- _constants_module = importlib.util.module_from_spec(_constants_spec)
25
- _constants_spec.loader.exec_module(_constants_module)
26
-
27
- effort_meets_threshold = _constants_module.effort_meets_threshold
28
- CODE_REVIEW_ENFORCEMENT_ENV_VAR = _constants_module.CODE_REVIEW_ENFORCEMENT_ENV_VAR
29
- code_review_enforcement_enabled_in_environment = (
30
- _constants_module.code_review_enforcement_enabled_in_environment
31
- )
32
- PUSH_REQUIRED_EFFORT = _constants_module.PUSH_REQUIRED_EFFORT
33
- PR_CREATE_REQUIRED_EFFORT = _constants_module.PR_CREATE_REQUIRED_EFFORT
34
- GATED_PUSH_SUBCOMMANDS = _constants_module.GATED_PUSH_SUBCOMMANDS
35
- ALL_EFFORT_TOKENS_IN_ASCENDING_ORDER = _constants_module.ALL_EFFORT_TOKENS_IN_ASCENDING_ORDER
36
- PUSH_GATE_CORRECTIVE_MESSAGE = _constants_module.PUSH_GATE_CORRECTIVE_MESSAGE
37
- SANCTIONED_STAMP_MINTER_FLAG = _constants_module.SANCTIONED_STAMP_MINTER_FLAG
38
- STAMP_DIRECTORY_GUARD_MESSAGE = _constants_module.STAMP_DIRECTORY_GUARD_MESSAGE
39
- STAMP_DIRECTORY_NAME = _constants_module.STAMP_DIRECTORY_NAME
40
- GH_PR_CREATE_INVOCATION_PATTERN = _constants_module.GH_PR_CREATE_INVOCATION_PATTERN
41
- STAMP_FILE_REFERENCE_BOUNDARY_PREFIX_PATTERN = (
42
- _constants_module.STAMP_FILE_REFERENCE_BOUNDARY_PREFIX_PATTERN
43
- )
44
- STAMP_FILE_ROOT_KEY_JSON_SUFFIX_PATTERN = _constants_module.STAMP_FILE_ROOT_KEY_JSON_SUFFIX_PATTERN
45
-
46
-
47
- def test_gh_pr_create_pattern_matches_create_but_not_edit() -> None:
48
- invocation_pattern = re.compile(GH_PR_CREATE_INVOCATION_PATTERN, re.IGNORECASE)
49
- assert invocation_pattern.search("gh pr create --title T --body-file b.md") is not None
50
- assert invocation_pattern.search("gh pr edit 1 --title T") is None
51
-
52
-
53
- def test_stamp_file_pattern_fragments_match_a_stamp_file_reference() -> None:
54
- stamp_file_pattern = re.compile(
55
- STAMP_FILE_REFERENCE_BOUNDARY_PREFIX_PATTERN
56
- + re.escape(STAMP_DIRECTORY_NAME)
57
- + STAMP_FILE_ROOT_KEY_JSON_SUFFIX_PATTERN % SAMPLE_ROOT_KEY_HEX_LENGTH,
58
- re.IGNORECASE,
59
- )
60
- stamp_file_reference = f"cat {STAMP_DIRECTORY_NAME}/{'a' * SAMPLE_ROOT_KEY_HEX_LENGTH}.json"
61
- assert stamp_file_pattern.search(stamp_file_reference) is not None
62
- assert stamp_file_pattern.search("cat notes.json") is None
63
-
64
-
65
- def test_higher_effort_meets_a_lower_threshold() -> None:
66
- assert effort_meets_threshold("xhigh", "low") is True
67
-
68
-
69
- def test_lower_effort_fails_a_higher_threshold() -> None:
70
- assert effort_meets_threshold("low", "xhigh") is False
71
-
72
-
73
- def test_equal_effort_meets_the_threshold() -> None:
74
- assert effort_meets_threshold("low", "low") is True
75
-
76
-
77
- def test_ultra_is_unranked_and_meets_nothing() -> None:
78
- assert effort_meets_threshold("ultra", "low") is False
79
-
80
-
81
- def test_unknown_required_effort_meets_nothing() -> None:
82
- assert effort_meets_threshold("low", "ultra") is False
83
-
84
-
85
- def test_push_requires_the_lowest_effort_token() -> None:
86
- every_token_meets_push = all(
87
- effort_meets_threshold(each_token, PUSH_REQUIRED_EFFORT)
88
- for each_token in ALL_EFFORT_TOKENS_IN_ASCENDING_ORDER
89
- )
90
- assert every_token_meets_push
91
-
92
-
93
- def test_pr_create_threshold_admits_xhigh_but_rejects_high() -> None:
94
- assert effort_meets_threshold("xhigh", PR_CREATE_REQUIRED_EFFORT) is True
95
- assert effort_meets_threshold("high", PR_CREATE_REQUIRED_EFFORT) is False
96
-
97
-
98
- def test_gated_push_subcommands_gates_push_not_commit() -> None:
99
- assert "push" in GATED_PUSH_SUBCOMMANDS
100
- assert "commit" not in GATED_PUSH_SUBCOMMANDS
101
-
102
-
103
- def test_ultra_absent_from_the_ordered_tokens() -> None:
104
- assert "ultra" not in ALL_EFFORT_TOKENS_IN_ASCENDING_ORDER
105
-
106
-
107
- def test_push_gate_message_names_the_push_action_and_low_effort() -> None:
108
- assert "git push" in PUSH_GATE_CORRECTIVE_MESSAGE
109
- assert "CODE_REVIEW_PUSH_GATE" in PUSH_GATE_CORRECTIVE_MESSAGE
110
- assert "'low'" in PUSH_GATE_CORRECTIVE_MESSAGE
111
-
112
-
113
- def test_guard_message_directs_users_to_the_sanctioned_minter_flag() -> None:
114
- assert SANCTIONED_STAMP_MINTER_FLAG in STAMP_DIRECTORY_GUARD_MESSAGE
115
-
116
-
117
- def test_enforcement_defaults_to_off(monkeypatch: pytest.MonkeyPatch) -> None:
118
- monkeypatch.delenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, raising=False)
119
- assert code_review_enforcement_enabled_in_environment() is False
120
-
121
-
122
- @pytest.mark.parametrize("enabling_value", ["1", "true", "TRUE", " yes ", "on"])
123
- def test_enforcement_turns_on_for_each_enabling_environment_value(
124
- monkeypatch: pytest.MonkeyPatch, enabling_value: str
125
- ) -> None:
126
- monkeypatch.setenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, enabling_value)
127
- assert code_review_enforcement_enabled_in_environment() is True
128
-
129
-
130
- @pytest.mark.parametrize("non_enabling_value", ["0", "false", "off", "", "maybe"])
131
- def test_enforcement_stays_off_for_a_non_enabling_environment_value(
132
- monkeypatch: pytest.MonkeyPatch, non_enabling_value: str
133
- ) -> None:
134
- monkeypatch.setenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, non_enabling_value)
135
- assert code_review_enforcement_enabled_in_environment() is False
136
-
137
-
138
- def _module_flag_after_a_fresh_import(
139
- monkeypatch: pytest.MonkeyPatch, environment_value: str | None
140
- ) -> bool:
141
- if environment_value is None:
142
- monkeypatch.delenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, raising=False)
143
- else:
144
- monkeypatch.setenv(CODE_REVIEW_ENFORCEMENT_ENV_VAR, environment_value)
145
- fresh_spec = importlib.util.spec_from_file_location(
146
- "code_review_enforcement_constants_fresh_import",
147
- _CONFIG_DIR / "code_review_enforcement_constants.py",
148
- )
149
- assert fresh_spec is not None
150
- assert fresh_spec.loader is not None
151
- fresh_module = importlib.util.module_from_spec(fresh_spec)
152
- fresh_spec.loader.exec_module(fresh_module)
153
- flag_value: bool = fresh_module.CODE_REVIEW_ENFORCEMENT_ENABLED
154
- return flag_value
155
-
156
-
157
- def test_module_flag_turns_on_when_the_environment_asks_for_enforcement(
158
- monkeypatch: pytest.MonkeyPatch,
159
- ) -> None:
160
- assert _module_flag_after_a_fresh_import(monkeypatch, "true") is True
161
-
162
-
163
- def test_module_flag_stays_off_when_the_environment_is_unset(
164
- monkeypatch: pytest.MonkeyPatch,
165
- ) -> None:
166
- assert _module_flag_after_a_fresh_import(monkeypatch, None) is False
@@ -1,160 +0,0 @@
1
- """Constants for the verified-commit gate hook family.
2
-
3
- Shared by ``verification_verdict_store.py``, ``verified_commit_gate.py``,
4
- and ``verifier_verdict_minter.py`` so every tunable lives in one place.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- GIT_TIMEOUT_SECONDS = 30
10
- ROOT_KEY_HEX_LENGTH = 16
11
- VERDICT_JSON_INDENT = 2
12
- CLAUDE_HOME_DIRECTORY_NAME = ".claude"
13
- VERDICT_DIRECTORY_NAME = "verification"
14
- VERDICT_DIRECTORY_NAME_SEPARATOR_PATTERN = r"['\"\\/,\s]+"
15
- VERDICT_DIRECTORY_PATH_BOUNDARY_PATTERN = r"(?=['\"]*[\\/,])"
16
- RELATIVE_VERDICT_DIRECTORY_PATTERN = r"(?:^|(?<=[\s;&|(='\"]))verification[\\/]"
17
- VERDICT_PATH_GLUE_PATTERN = r"['\"+\\/\s]*[\\/]['\"+\\/\s]*"
18
- VERDICT_DIRECTORY_CHANGE_TARGET_PATTERN = r"[ \t]+['\"]?verification[\\/]?['\"]?(?=[\s;&|]|$)"
19
- VERDICT_PATH_JOINED_VARIABLE_PATTERN = r"\$\{?(\w+)\}?[\\/]|[\\/]\$\{?(\w+)\}?"
20
- VERDICT_PATH_VARIABLE_ASSIGNMENT_PATTERN = r"(?:^|(?<=[\s;&|(]))%s=(\S+)"
21
- VERDICT_FILE_RELATIVE_REFERENCE_PATTERN = (
22
- rf"(?:^|(?<=[\s;&|(='\"\\/]))verification[\\/][0-9a-f]{{{ROOT_KEY_HEX_LENGTH}}}\.json"
23
- )
24
- PATH_OBFUSCATION_PRIMITIVE_PATTERN = (
25
- r"chr\s*\(|bytes\.fromhex\s*\(|b64decode\s*\(|codecs\.decode\s*\("
26
- r"|(?:bytes|bytearray)\s*\(\s*\[|\[char\[?\]?\]"
27
- )
28
- ALL_VERDICT_PATH_SEGMENT_NAMES = (".claude", "verification")
29
- ALL_VERDICT_PATH_SEGMENT_BODIES = ("claude", "verification")
30
- HEX_TOKEN_PATTERN = r"(?<![0-9a-fx])([0-9a-f]{6,})(?![0-9a-f])"
31
- BASE64_TOKEN_PATTERN = r"[A-Za-z0-9+/]{8,}={0,2}"
32
- CHARACTER_CODE_SEQUENCE_PATTERN = r"\d{1,3}(?:\s*,\s*\d{1,3})+"
33
- CHR_CALL_CHAIN_PATTERN = r"chr\(\s*\d{1,3}\s*\)(?:\s*\+\s*chr\(\s*\d{1,3}\s*\))+"
34
- CHR_CALL_CODE_PATTERN = r"chr\(\s*(\d{1,3})\s*\)"
35
- HEX_DIGITS_PER_BYTE = 2
36
- FILE_WRITE_PRIMITIVE_PATTERN = (
37
- r"\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
38
- r"|Out-File|Set-Content|Add-Content|\btee\b|>"
39
- )
40
- NON_REDIRECT_FILE_WRITE_PRIMITIVE_PATTERN = (
41
- r"\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
42
- r"|Out-File|Set-Content|Add-Content|\btee\b"
43
- )
44
- WRITE_CALL_REGION_PATTERN = (
45
- r"(?:\bopen\s*\(|\.write_text\s*\(|\.write_bytes\s*\("
46
- r"|Out-File|Set-Content|Add-Content|\btee\b)[^;&|\n]*"
47
- )
48
- VERDICT_KEY_ALL_PASS = "all_pass"
49
- VERDICT_KEY_MANIFEST_SHA256 = "manifest_sha256"
50
- VERDICT_KEY_FINDINGS = "findings"
51
- VERDICT_FINDING_CHECK_KEY = "check"
52
- LOGS_DIRECTORY_NAME = "logs"
53
- VERIFIER_VERDICTS_JSONL_FILENAME = "verifier-verdicts.jsonl"
54
- LEDGER_KEY_TIMESTAMP = "timestamp"
55
- LEDGER_KEY_REPO_ROOT = "repo_root"
56
- LEDGER_KEY_BRANCH = "branch"
57
- LEDGER_KEY_MANIFEST_HASH = "manifest_hash"
58
- LEDGER_KEY_ALL_PASS = "all_pass"
59
- LEDGER_KEY_FINDING_COUNT = "finding_count"
60
- LEDGER_KEY_FINDING_CHECK_NAMES = "finding_check_names"
61
- LEDGER_KEY_MINTED_FROM_AGENT_ID = "minted_from_agent_id"
62
- VERDICT_FILE_GLOB = "*.json"
63
- SUBAGENTS_DIRECTORY_NAME = "subagents"
64
- AGENT_TRANSCRIPT_GLOB = "agent-*.jsonl"
65
- AGENT_META_SIDECAR_SUFFIX = ".meta.json"
66
- AGENT_META_TYPE_KEY = "agentType"
67
- TRANSCRIPT_ENTRY_TYPE_KEY = "type"
68
- TRANSCRIPT_ASSISTANT_ENTRY_TYPE = "assistant"
69
- TRANSCRIPT_MESSAGE_KEY = "message"
70
- TRANSCRIPT_CONTENT_KEY = "content"
71
- TRANSCRIPT_CONTENT_TYPE_KEY = "type"
72
- TRANSCRIPT_TEXT_CONTENT_TYPE = "text"
73
- TRANSCRIPT_TEXT_KEY = "text"
74
- VERDICT_FENCE_PATTERN = r"```verdict\s*\n(.*?)```"
75
- MANIFEST_HASH_CLI_FLAG = "--manifest-hash"
76
- MANIFEST_HASH_FOR_BRANCH_CLI_FLAG = "--manifest-hash-for-branch"
77
- WORKTREE_LIST_PATH_PREFIX = "worktree "
78
- WORKTREE_LIST_BRANCH_PREFIX = "branch "
79
- BRANCH_REFERENCE_PREFIX = "refs/heads/"
80
- EMPTY_SURFACE_GUARD_MESSAGE = (
81
- "ERROR: The work tree at {repo_root} has no changed or untracked files "
82
- "versus origin/main (empty change surface). This work tree holds nothing "
83
- "to verify — you are pointed at the wrong work tree. Run `git worktree list` "
84
- "to see all checked-out work trees and target the one on the branch under review."
85
- )
86
- BRANCH_WORKTREE_ABSENT_MESSAGE = (
87
- "ERROR: No work tree has branch '{branch}' checked out. "
88
- "Check it out in a work tree first: "
89
- "`git worktree add <path> <branch>` or `git checkout <branch>`."
90
- )
91
- DOCS_ONLY_EXTENSIONS = frozenset(
92
- {".md", ".txt", ".rst", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".ico"}
93
- )
94
- PYTHON_EXTENSION = ".py"
95
- TEST_FILE_PREFIX = "test_"
96
- TEST_FILE_SUFFIX = "_test.py"
97
- CONFTEST_FILE_NAME = "conftest.py"
98
- MINIMUM_STATUS_FIELD_COUNT = 2
99
- ALL_FALLBACK_BASE_REFERENCES = ("origin/main", "origin/master")
100
- DETACHED_HEAD_LABEL = "HEAD"
101
- BRANCH_REMOTE_CONFIG_KEY_TEMPLATE = "branch.{branch_name}.remote"
102
- ALL_TOOLING_STATE_PREFIXES = (
103
- ".claude/verification/",
104
- ".claude/worktrees/",
105
- ".claude/daemon/",
106
- ".claude/teams/",
107
- ".claude/sessions/",
108
- ".cursor/worktrees/",
109
- ".claude-plugin-data/",
110
- )
111
- GATED_GIT_SUBCOMMANDS = frozenset({"commit", "push"})
112
- ALL_GIT_BINARY_NAMES = frozenset({"git", "git.exe"})
113
- VALUE_TAKING_GIT_OPTIONS = frozenset({"-C", "-c", "--git-dir", "--work-tree", "--namespace"})
114
- REPO_DIRECTORY_OPTION = "-C"
115
- WORK_TREE_OPTION = "--work-tree"
116
- DIRECTORY_CHANGE_VERBS = frozenset({"cd", "pushd", "set-location", "sl"})
117
- DIRECTORY_CHANGE_PATH_OPTIONS = frozenset({"-path", "-literalpath"})
118
- DIRECTORY_CHANGE_OPTION_TERMINATOR = "--"
119
- DIRECTORY_CHANGE_PATTERN_PREFIX = r"(?:^|(?<=[\s;&|(]))(?:"
120
- DIRECTORY_CHANGE_PATTERN_SUFFIX = r")(?=\s|$)"
121
- DIRECTORY_CHANGE_OPTION_PREFIX_PATTERN = r"(?:[ \t]+(?:%s)(?=\s|$))*"
122
- DIRECTORY_CHANGE_TARGET_PATTERN = r"[ \t]+['\"]?\S*"
123
- CLAUDE_HOME_TARGET_BOUNDARY_PATTERN = r"[\\/]?['\"]?(?=[\s;&|]|$)"
124
- VERDICT_DIRECTORY_TARGET_BOUNDARY_PATTERN = r"[\\/]?['\"]?(?=[\s;&|]|$)"
125
- COMMAND_AFTER_DIRECTORY_CHANGE_PATTERN = r"[;&|\n][\s]*\S"
126
- OPTION_WITH_VALUE_STEP = 2
127
- ALL_GATED_TOOL_NAMES = ("Bash", "PowerShell")
128
- HASH_PREVIEW_LENGTH = 16
129
- VERIFICATION_BYPASS_MARKER = "# verify-skip"
130
- MINTING_AGENT_TYPE = "code-verifier"
131
- VERDICT_DIRECTORY_GUARD_MESSAGE = (
132
- "BLOCKED: [VERDICT_DIRECTORY_GUARD] Shell access to the verification "
133
- "verdict directory (~/.claude/verification/) is denied. Only the "
134
- "verifier_verdict_minter.py SubagentStop hook writes verdict files; a "
135
- "shell write here would forge a passing verdict and defeat the "
136
- "verified-commit gate. Spawn the code-verifier agent to earn a verdict "
137
- "instead of writing one."
138
- )
139
- CORRECTIVE_MESSAGE = (
140
- "BLOCKED: [VERIFIED_COMMIT_GATE] This branch surface has no passing "
141
- "verification verdict. Clear commit-committability gates first "
142
- "(CODE_RULES on changed lines and merge conflicts vs base — the "
143
- "code_verifier_spawn_preflight_gate enforces these on the spawn). If a "
144
- "prior commit failed on CODE_RULES or staging, fix those before "
145
- "re-verifying. Then spawn the code-verifier agent (Agent or Task tool, "
146
- "subagent_type 'code-verifier') with the task texts, the diff scope, "
147
- "and recorded baselines; when it finishes with a clean verdict the "
148
- "SubagentStop hook mints the verdict and this command will pass. Any "
149
- "file change after verification invalidates the verdict, so verify "
150
- "last only after commit gates are green. The verdict binds to the exact "
151
- "surface content (every changed and untracked file's bytes), not to a "
152
- "work-tree path, so a commit from a different work tree passes only "
153
- "when its surface is byte-identical; a work tree carrying any extra or "
154
- "later edit has a surface no verdict covers. To land this change, run "
155
- "this command from the work tree that holds the verified surface, or "
156
- "verify this surface here. Exempt automatically: docs/image files, "
157
- "pytest test files, and "
158
- "Python files whose docstring- and comment-stripped AST is unchanged "
159
- "(comment-only edits in non-Python files are not exempt)."
160
- )
@@ -1,21 +0,0 @@
1
- """The additionalContext text the verified-commit gate attaches to a deny.
2
-
3
- The gate injects this next to the blocked tool result so the agent learns,
4
- at the moment of the block, when the '# verify-skip' marker is legitimate
5
- and when a fresh verification is required instead.
6
- """
7
-
8
- VERIFY_SKIP_ADDITIONAL_CONTEXT = (
9
- "The verified-commit gate honors a one-command escape hatch: appending the "
10
- "marker '# verify-skip' as a trailing shell comment (outside every quoted "
11
- "region) to the blocked command bypasses the gate for that command only. "
12
- "It is allowed only when the branch surface is the "
13
- "same code a code-verifier already passed clean and the gate is "
14
- "blocking on a verdict that does not cover it (an unminted verdict, "
15
- "staging churn, or a reverted concurrent write) — confirm the verified "
16
- "suite still passes and the diff holds nothing beyond the clean verdict "
17
- "before using it. Any real code change since that clean verdict, a "
18
- "first verification, or unrepaired findings all require a fresh "
19
- "verification by the code-verifier agent instead. Full rule: "
20
- "~/.claude/rules/verified-commit-gate-skip.md."
21
- )
@@ -1,14 +0,0 @@
1
- """Output-shape constants for the verified-commit gate's deny payload.
2
-
3
- Shared by ``verified_commit_gate.py`` and its ``verified_commit_gate_parts``
4
- package so the PreToolUse event name, the deny decision string, the hook's
5
- own module name for block logging, and the regex-alternation join separator
6
- live in one place.
7
- """
8
-
9
- from __future__ import annotations
10
-
11
- PRE_TOOL_USE_HOOK_EVENT_NAME = "PreToolUse"
12
- DENY_PERMISSION_DECISION = "deny"
13
- GATE_HOOK_MODULE_NAME = "verified_commit_gate.py"
14
- REGEX_ALTERNATION_SEPARATOR = "|"
@@ -1,123 +0,0 @@
1
- """Pytest fixture that reproduces foreign-``config`` shadowing for the gate family.
2
-
3
- The verified-commit gate hooks import shared constants as
4
- ``from config.verified_commit_constants import ...``. This fixture mirrors the
5
- installed layout that breaks that import -- a real ``hooks/blocking`` package
6
- beside a decoy ``hooks/config`` regular package -- and runs a caller-supplied
7
- driver as a subprocess whose ``sys.path`` places the decoy ahead of
8
- ``blocking``, the ordering under which the wrong ``config`` wins resolution.
9
- """
10
-
11
- import shutil
12
- import subprocess
13
- import sys
14
- import textwrap
15
- from collections.abc import Callable
16
- from pathlib import Path
17
-
18
- import pytest
19
-
20
- _BLOCKING_SOURCE_DIRECTORY = Path(__file__).resolve().parent
21
- _HOOKS_CONSTANTS_SOURCE_DIRECTORY = _BLOCKING_SOURCE_DIRECTORY.parent / "hooks_constants"
22
- _SUBPROCESS_TIMEOUT_SECONDS = 60
23
- _MIRRORED_BLOCKING_FILE_NAMES = (
24
- "verified_commit_gate.py",
25
- "verification_verdict_store.py",
26
- "verifier_verdict_minter.py",
27
- "verdict_directory_write_blocker.py",
28
- "verified_commit_config_bootstrap.py",
29
- "code_review_enforcement_config_bootstrap.py",
30
- "code_review_stamp_store.py",
31
- )
32
- _DECOY_CONFIG_INIT_SOURCE = '"""Foreign config package that must never win resolution."""\n'
33
- _DECOY_CONFIG_CONSTANTS_SOURCE = (
34
- '"""Stale stand-in carrying none of the real gate constants."""\n\nIS_DECOY_CONFIG = True\n'
35
- )
36
-
37
-
38
- def _copy_mirrored_packages(mirrored_hooks_directory: Path, mirrored_blocking_directory: Path) -> None:
39
- """Copy the ``config``, gate-parts, and ``hooks_constants`` packages into the mirror."""
40
- shutil.copytree(_BLOCKING_SOURCE_DIRECTORY / "config", mirrored_blocking_directory / "config")
41
- shutil.copytree(
42
- _BLOCKING_SOURCE_DIRECTORY / "verified_commit_gate_parts",
43
- mirrored_blocking_directory / "verified_commit_gate_parts",
44
- ignore=shutil.ignore_patterns("tests", "__pycache__"),
45
- )
46
- shutil.copytree(_HOOKS_CONSTANTS_SOURCE_DIRECTORY, mirrored_hooks_directory / "hooks_constants")
47
-
48
-
49
- def _write_decoy_config_package(mirrored_hooks_directory: Path) -> None:
50
- """Write the decoy ``config`` package that must never win resolution."""
51
- decoy_config_directory = mirrored_hooks_directory / "config"
52
- decoy_config_directory.mkdir()
53
- (decoy_config_directory / "__init__.py").write_text(_DECOY_CONFIG_INIT_SOURCE, encoding="utf-8")
54
- (decoy_config_directory / "verified_commit_constants.py").write_text(
55
- _DECOY_CONFIG_CONSTANTS_SOURCE, encoding="utf-8"
56
- )
57
-
58
-
59
- def _build_shadowed_hook_tree(tmp_path: Path) -> tuple[Path, Path]:
60
- """Mirror the hook tree with a decoy ``config`` package beside ``blocking``.
61
-
62
- Args:
63
- tmp_path: The directory the mirrored tree is built under.
64
-
65
- Returns:
66
- The mirrored ``hooks`` directory and its ``blocking`` subdirectory.
67
- """
68
- mirrored_hooks_directory = tmp_path / "hooks"
69
- mirrored_blocking_directory = mirrored_hooks_directory / "blocking"
70
- mirrored_blocking_directory.mkdir(parents=True)
71
-
72
- for each_file_name in _MIRRORED_BLOCKING_FILE_NAMES:
73
- source_file = _BLOCKING_SOURCE_DIRECTORY / each_file_name
74
- if source_file.exists():
75
- shutil.copy2(source_file, mirrored_blocking_directory / each_file_name)
76
-
77
- _copy_mirrored_packages(mirrored_hooks_directory, mirrored_blocking_directory)
78
- _write_decoy_config_package(mirrored_hooks_directory)
79
- return mirrored_hooks_directory, mirrored_blocking_directory
80
-
81
-
82
- def _probe_command(mirrored_hooks_directory: Path, mirrored_blocking_directory: Path) -> str:
83
- """Build the ``sys.path`` preamble that shadows ``blocking`` with the decoy config."""
84
- return textwrap.dedent(
85
- f"""\
86
- import sys
87
- sys.path.insert(0, {str(mirrored_blocking_directory)!r})
88
- sys.path.insert(0, {str(mirrored_hooks_directory)!r})
89
- """
90
- )
91
-
92
-
93
- @pytest.fixture
94
- def run_under_config_shadow(
95
- tmp_path: Path,
96
- ) -> Callable[[str], subprocess.CompletedProcess[str]]:
97
- """Return a runner that executes a driver under a foreign-``config`` sys.path.
98
-
99
- ``run_under_config_shadow("import verified_commit_gate")`` returns 0 once
100
- the bootstrap seeds the real module, nonzero while the decoy config wins.
101
-
102
- Args:
103
- tmp_path: Pytest's per-test temporary directory, fixture-injected.
104
-
105
- Returns:
106
- A function taking driver source text and returning the finished
107
- subprocess result.
108
- """
109
- mirrored_hooks_directory, mirrored_blocking_directory = _build_shadowed_hook_tree(tmp_path)
110
- sys_path_preamble = _probe_command(mirrored_hooks_directory, mirrored_blocking_directory)
111
-
112
- def run_driver(driver_body: str) -> subprocess.CompletedProcess[str]:
113
- probe_script = tmp_path / "probe.py"
114
- probe_script.write_text(sys_path_preamble + textwrap.dedent(driver_body), encoding="utf-8")
115
- return subprocess.run(
116
- [sys.executable, str(probe_script)],
117
- check=False,
118
- capture_output=True,
119
- text=True,
120
- timeout=_SUBPROCESS_TIMEOUT_SECONDS,
121
- )
122
-
123
- return run_driver