claude-dev-env 4.3.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/.agents/agents/pr-description-writer.md +2 -2
  2. package/.agents/agents/test_agent_frontmatter.py +2 -2
  3. package/.agents/agents/test_pr_description_writer_style.py +1 -3
  4. package/.agents/skills/e-code-review/SKILL.md +12 -12
  5. package/.agents/skills/e-code-review/preflight-proposal.contract.test.mjs +20 -0
  6. package/.agents/skills/e-code-review/reference/fix.md +15 -17
  7. package/.agents/skills/e-code-review/reference/loop.md +35 -39
  8. package/.agents/skills/e-code-review/reference/mode-contract.test.mjs +2 -1
  9. package/.agents/skills/e-code-review/reference/preflight-proposal.md +44 -9
  10. package/.agents/skills/e-code-review/reference/runner-selection.md +13 -14
  11. package/.agents/skills/issue-tracker/SKILL.md +5 -4
  12. package/.agents/skills/pull-request/SKILL.md +11 -13
  13. package/.agents/skills/pull-request/reference/publication-tasks.md +3 -3
  14. package/.agents/skills/pull-request/scripts/github_pr_command_constants/config/constants.py +9 -1
  15. package/.agents/skills/pull-request/scripts/pull_request.py +35 -44
  16. package/.agents/skills/pull-request/scripts/test_github_pr_command_constants.py +9 -0
  17. package/.agents/skills/pull-request/scripts/test_pull_request.py +35 -3
  18. package/.agents/skills/session-continuity/README.md +189 -0
  19. package/.agents/skills/session-continuity/SKILL.md +114 -0
  20. package/.agents/skills/session-continuity/continuity.mjs +375 -0
  21. package/.agents/skills/session-continuity/continuity.test.mjs +303 -0
  22. package/.agents/skills/skill-builder/SKILL.md +3 -196
  23. package/.agents/skills/syncing-submodules/scripts/test_sync_parent_pointer.py +0 -7
  24. package/.agents/skills/windows-scheduled-task/SKILL.md +153 -0
  25. package/_shared/pr-loop/scripts/pr_loop_shared_constants/terminology_sweep_constants.py +6 -0
  26. package/_shared/pr-loop/scripts/terminology_sweep.py +64 -19
  27. package/_shared/pr-loop/scripts/tests/test_terminology_sweep.py +59 -0
  28. package/bin/cde.mjs +36 -8
  29. package/bin/cde.test.mjs +48 -0
  30. package/bin/ever-shipped-skills.mjs +2 -20
  31. package/bin/ever-shipped-skills.test.mjs +8 -0
  32. package/bin/expand_home_directory_tokens.mjs +4 -5
  33. package/bin/expand_home_directory_tokens.test.mjs +128 -0
  34. package/bin/git_hooks_installer.mjs +22 -3
  35. package/bin/git_hooks_installer.test.mjs +159 -5
  36. package/bin/install-session-continuity.mjs +78 -0
  37. package/bin/install-session-continuity.test.mjs +42 -0
  38. package/bin/install.agents-home.test.mjs +15 -13
  39. package/bin/install.codex-rules.test.mjs +5 -2
  40. package/bin/install.cursor-rules.test.mjs +5 -2
  41. package/bin/install.mjs +506 -63
  42. package/bin/install.policy-lint.test.mjs +130 -0
  43. package/bin/install.profiles.test.mjs +10 -0
  44. package/bin/install.prune.test.mjs +286 -37
  45. package/bin/install.pstack-plugin.test.mjs +114 -0
  46. package/bin/install.test.mjs +537 -120
  47. package/bin/install.transaction.test.mjs +3 -3
  48. package/bin/refresh-pstack-plugin-skills.test.mjs +211 -0
  49. package/docs/CODE_RULES.md +1 -1
  50. package/hooks/advisory/pr_done_reminder.py +342 -0
  51. package/hooks/advisory/test_pr_done_reminder.py +249 -0
  52. package/hooks/blocking/bash_post_call_dispatcher.py +53 -6
  53. package/hooks/blocking/code_rules_banned_identifiers.py +3 -0
  54. package/hooks/blocking/code_rules_paired_test.py +22 -15
  55. package/hooks/blocking/precommit_code_rules_gate.py +5 -8
  56. package/hooks/blocking/test_bash_dispatcher_interpreter_starts.py +7 -52
  57. package/hooks/blocking/test_bash_post_call_dispatcher.py +65 -4
  58. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +0 -69
  59. package/hooks/blocking/test_code_rules_banned_identifiers.py +64 -0
  60. package/hooks/blocking/test_code_rules_enforcer_paired_test.py +36 -29
  61. package/hooks/blocking/test_code_rules_js_resume_task_enumeration.py +4 -4
  62. package/hooks/blocking/test_code_rules_js_returns_object_schemaless.py +5 -5
  63. package/hooks/blocking/test_pre_tool_use_dispatcher.py +43 -342
  64. package/hooks/blocking/test_pre_tool_use_dispatcher_native.py +20 -51
  65. package/hooks/blocking/test_shared_stdin_adoption.py +1 -47
  66. package/hooks/git-hooks/git_hooks_constants/staged_policy_lint.py +12 -0
  67. package/hooks/git-hooks/git_hooks_constants/verification_notice_constants.py +116 -0
  68. package/hooks/git-hooks/post_commit.py +33 -0
  69. package/hooks/git-hooks/pre_commit.py +18 -49
  70. package/hooks/git-hooks/pre_push.py +45 -541
  71. package/hooks/git-hooks/test_installed_policy_lint.py +208 -0
  72. package/hooks/git-hooks/test_native_hook_support.py +129 -0
  73. package/hooks/git-hooks/test_native_policy_commit.py +120 -0
  74. package/hooks/git-hooks/test_post_commit.py +43 -0
  75. package/hooks/git-hooks/test_pre_commit.py +38 -148
  76. package/hooks/git-hooks/test_pre_push.py +48 -1631
  77. package/hooks/git-hooks/test_verification_notice.py +60 -0
  78. package/hooks/git-hooks/test_verification_start.py +173 -0
  79. package/hooks/git-hooks/verification_notice.py +192 -0
  80. package/hooks/git-hooks/verification_notice_context.py +253 -0
  81. package/hooks/git-hooks/verification_notice_state.py +237 -0
  82. package/hooks/git-hooks/verification_start.py +100 -0
  83. package/hooks/hooks.json +1 -120
  84. package/hooks/hooks_constants/banned_identifiers_constants.py +4 -0
  85. package/hooks/hooks_constants/bash_post_call_dispatcher_constants.py +14 -1
  86. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +1 -15
  87. package/hooks/hooks_constants/post_tool_use_dispatcher_constants.py +0 -4
  88. package/hooks/hooks_constants/pr_done_reminder_constants.py +98 -0
  89. package/hooks/hooks_constants/pre_tool_use_dispatcher_constants.py +10 -93
  90. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -4
  91. package/hooks/hooks_constants/test_bash_post_call_dispatcher_constants.py +19 -2
  92. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +3 -66
  93. package/hooks/hooks_constants/test_pr_done_reminder_constants.py +40 -0
  94. package/hooks/hooks_constants/test_pre_tool_use_dispatcher_constants.py +46 -201
  95. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +3 -25
  96. package/hooks/validation/test_post_tool_use_dispatcher.py +35 -298
  97. package/hooks/validators/run_all_validators.py +5 -1
  98. package/hooks/validators/security_checks.py +57 -2
  99. package/hooks/validators/test_hook_timing_harness.py +2 -5
  100. package/hooks/validators/test_run_all_validators_mutation_tool_parity.py +3 -11
  101. package/hooks/validators/test_run_all_validators_policy_lint.py +36 -0
  102. package/hooks/validators/test_security_checks.py +57 -0
  103. package/package.json +2 -2
  104. package/rules/confirm-implementation-forks.md +2 -0
  105. package/rules/durable-post-artifacts.md +2 -1
  106. package/rules/git-workflow.md +18 -6
  107. package/rules/pstack-host-mapping.md +48 -0
  108. package/rules/vault-context.md +3 -5
  109. package/rules/verify-runtime-state.md +7 -0
  110. package/scripts/audit-hooks-cli.mjs +5 -0
  111. package/scripts/audit-hooks.mjs +72 -16
  112. package/scripts/automatic_advisory/__init__.py +1 -0
  113. package/scripts/automatic_advisory/checkout.py +51 -0
  114. package/scripts/automatic_advisory/cli.py +334 -0
  115. package/scripts/automatic_advisory/config/__init__.py +1 -0
  116. package/scripts/automatic_advisory/config/constants.py +93 -0
  117. package/scripts/automatic_advisory/config/timing.py +4 -0
  118. package/scripts/automatic_advisory/configuration.py +197 -0
  119. package/scripts/automatic_advisory/execution.py +350 -0
  120. package/scripts/automatic_advisory/git.py +69 -0
  121. package/scripts/automatic_advisory/model.py +107 -0
  122. package/scripts/automatic_advisory/process_host.py +32 -0
  123. package/scripts/automatic_advisory/publisher.py +84 -0
  124. package/scripts/automatic_advisory/runner.py +399 -0
  125. package/scripts/automatic_advisory/state.py +116 -0
  126. package/scripts/automatic_advisory/window_flags.py +41 -0
  127. package/scripts/automatic_advisory/windows_job.py +122 -0
  128. package/scripts/check.ps1 +0 -1
  129. package/{.agents/skills/run-claude-dev-env/driver.mjs → scripts/ci/installer-lifecycle.mjs} +3 -28
  130. package/scripts/ci/installer-lifecycle.test.mjs +26 -0
  131. package/scripts/ci/windows-installer-lifecycle.ps1 +1 -11
  132. package/scripts/codex_compat_materializer.py +99 -13
  133. package/scripts/dev_env_scripts_constants/shared_tree_constants.py +4 -5
  134. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/durable_post_lint.py +35 -43
  135. package/{.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/durable_post_lint_constants.py → scripts/durable_post_lint_config/config/constants.py} +10 -10
  136. package/{.agents/skills/_shared/pr-loop/scripts/test_durable_post_lint_constants.py → scripts/durable_post_lint_config/config/test_constants.py} +14 -1
  137. package/scripts/local_report_cli.py +184 -0
  138. package/scripts/local_report_core.py +247 -0
  139. package/scripts/local_report_publisher.py +12 -0
  140. package/scripts/local_report_validation.py +357 -0
  141. package/scripts/local_verification/__init__.py +23 -0
  142. package/scripts/local_verification/check_runner.py +364 -0
  143. package/scripts/local_verification/check_support.py +99 -0
  144. package/scripts/local_verification/cli.py +158 -0
  145. package/scripts/local_verification/command_runner.py +84 -0
  146. package/scripts/local_verification/config/__init__.py +1 -0
  147. package/scripts/local_verification/config/constants.py +89 -0
  148. package/scripts/local_verification/config/timing.py +1 -0
  149. package/scripts/local_verification/git_state.py +146 -0
  150. package/scripts/local_verification/manifest.py +224 -0
  151. package/scripts/local_verification/model.py +174 -0
  152. package/scripts/local_verification/runner.py +234 -0
  153. package/scripts/policy_lint/adapter_detectors.py +13 -6
  154. package/scripts/policy_lint/adapter_pairing.py +58 -3
  155. package/scripts/policy_lint/adapters.py +7 -4
  156. package/scripts/policy_lint/config/approved_test_pairs.py +323 -0
  157. package/scripts/policy_lint/config/constants.py +5 -0
  158. package/scripts/policy_lint/engine.py +48 -4
  159. package/scripts/policy_lint/model.py +1 -0
  160. package/scripts/policy_lint/registry.py +1 -1
  161. package/scripts/policy_lint/selection.py +2 -1
  162. package/scripts/policy_lint/selection_git.py +2 -0
  163. package/scripts/pr_verification/__init__.py +1 -0
  164. package/scripts/pr_verification/branch_refs.py +114 -0
  165. package/scripts/pr_verification/config/__init__.py +1 -0
  166. package/scripts/pr_verification/config/constants.py +84 -0
  167. package/scripts/pr_verification/config/timing.py +5 -0
  168. package/scripts/pr_verification/github.py +137 -0
  169. package/scripts/pr_verification/github_api.py +376 -0
  170. package/scripts/pr_verification/github_labels.py +88 -0
  171. package/scripts/pr_verification/github_parsing.py +182 -0
  172. package/scripts/pr_verification/github_transport.py +91 -0
  173. package/scripts/pr_verification/lock.py +122 -0
  174. package/scripts/pr_verification/model.py +43 -0
  175. package/scripts/pr_verification/requirements.txt +1 -0
  176. package/scripts/refresh_pstack_plugin_skills.mjs +200 -0
  177. package/scripts/shared_tree_paths.py +32 -3
  178. package/{.agents/skills/_shared/pr-loop/scripts → scripts}/test_durable_post_lint.py +97 -0
  179. package/scripts/test_shared_tree_paths.py +33 -0
  180. package/scripts/tests/test-audit-hooks-cli.mjs +150 -0
  181. package/scripts/tests/test-audit-hooks.mjs +94 -2
  182. package/scripts/tests/test_automatic_advisory.py +376 -0
  183. package/scripts/tests/test_automatic_advisory_job_cleanup.py +71 -0
  184. package/scripts/tests/test_automatic_advisory_polling.py +216 -0
  185. package/scripts/tests/test_automatic_advisory_recovery.py +320 -0
  186. package/scripts/tests/test_automatic_advisory_repairs.py +400 -0
  187. package/scripts/tests/test_automatic_advisory_settings.py +48 -0
  188. package/scripts/tests/test_automatic_advisory_window_flags.py +163 -0
  189. package/scripts/tests/test_closed_pr_label.py +157 -0
  190. package/scripts/tests/test_codex_compat_materializer.py +189 -6
  191. package/scripts/tests/test_github_labels.py +101 -0
  192. package/scripts/tests/test_github_transport.py +125 -0
  193. package/scripts/tests/test_local_report_publisher.py +396 -0
  194. package/scripts/tests/test_local_report_publisher_cli.py +85 -0
  195. package/scripts/tests/test_local_verification.py +348 -0
  196. package/scripts/tests/test_local_verification_cli.py +98 -0
  197. package/scripts/tests/test_policy_lint_rules_archive.py +120 -0
  198. package/scripts/tests/test_policy_lint_rules_engine.py +25 -4
  199. package/scripts/tests/test_policy_lint_rules_installed_loader.py +29 -0
  200. package/scripts/tests/test_policy_lint_rules_pairing.py +163 -0
  201. package/scripts/tests/test_policy_lint_rules_registry.py +227 -13
  202. package/scripts/tests/test_policy_lint_selection.py +25 -2
  203. package/scripts/tests/test_policy_lint_selection_native_index.py +30 -0
  204. package/scripts/tests/test_pr_verification_github.py +392 -0
  205. package/scripts/tests/test_pr_verification_lock.py +168 -0
  206. package/scripts/tests/test_rules.py +3 -7
  207. package/scripts/tests/test_verification_notice.py +347 -0
  208. package/.agents/skills/_shared/pr-loop/.claude/CLAUDE.md +0 -1
  209. package/.agents/skills/_shared/pr-loop/audit-contract.md +0 -5
  210. package/.agents/skills/_shared/pr-loop/audit-reply-template.md +0 -5
  211. package/.agents/skills/_shared/pr-loop/code-rules-gate.md +0 -5
  212. package/.agents/skills/_shared/pr-loop/fix-protocol.md +0 -5
  213. package/.agents/skills/_shared/pr-loop/gh-payloads.md +0 -5
  214. package/.agents/skills/_shared/pr-loop/portable-driver.md +0 -149
  215. package/.agents/skills/_shared/pr-loop/post-audit-thread-contract.md +0 -5
  216. package/.agents/skills/_shared/pr-loop/precatch-rubric.md +0 -5
  217. package/.agents/skills/_shared/pr-loop/preflight-proposal.contract.test.mjs +0 -119
  218. package/.agents/skills/_shared/pr-loop/preflight-proposal.md +0 -5
  219. package/.agents/skills/_shared/pr-loop/prompts/.claude/CLAUDE.md +0 -1
  220. package/.agents/skills/_shared/pr-loop/prompts/AGENTS.md +0 -1
  221. package/.agents/skills/_shared/pr-loop/prompts/pr-consistency-audit.xml +0 -324
  222. package/.agents/skills/_shared/pr-loop/scripts/.claude/CLAUDE.md +0 -1
  223. package/.agents/skills/_shared/pr-loop/scripts/AGENTS.md +0 -1
  224. package/.agents/skills/_shared/pr-loop/scripts/RUNTIME_SCRIPTS.md +0 -29
  225. package/.agents/skills/_shared/pr-loop/scripts/_cli_utils.py +0 -22
  226. package/.agents/skills/_shared/pr-loop/scripts/_path_resolver.py +0 -186
  227. package/.agents/skills/_shared/pr-loop/scripts/_xml_utils.py +0 -20
  228. package/.agents/skills/_shared/pr-loop/scripts/audit_category_schema.py +0 -355
  229. package/.agents/skills/_shared/pr-loop/scripts/build_audit_prompt.py +0 -289
  230. package/.agents/skills/_shared/pr-loop/scripts/build_converge_task_list.py +0 -310
  231. package/.agents/skills/_shared/pr-loop/scripts/build_fix_prompt.py +0 -292
  232. package/.agents/skills/_shared/pr-loop/scripts/init_loop_state.py +0 -134
  233. package/.agents/skills/_shared/pr-loop/scripts/portable_converge_driver.py +0 -1646
  234. package/.agents/skills/_shared/pr-loop/scripts/preflight_worktree.py +0 -392
  235. package/.agents/skills/_shared/pr-loop/scripts/select_converge_pacer.py +0 -215
  236. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/.claude/CLAUDE.md +0 -1
  237. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/AGENTS.md +0 -1
  238. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/__init__.py +0 -0
  239. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/audit_category_schema_constants.py +0 -37
  240. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/converge_task_list_constants.py +0 -56
  241. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/handoff_constants.py +0 -45
  242. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/pacer_constants.py +0 -47
  243. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/path_resolver_constants.py +0 -157
  244. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/portable_driver_constants.py +0 -177
  245. package/.agents/skills/_shared/pr-loop/scripts/skills_pr_loop_constants/preflight_constants.py +0 -70
  246. package/.agents/skills/_shared/pr-loop/scripts/teardown_worktrees.py +0 -172
  247. package/.agents/skills/_shared/pr-loop/scripts/test__path_resolver.py +0 -106
  248. package/.agents/skills/_shared/pr-loop/scripts/test_audit_category_schema.py +0 -94
  249. package/.agents/skills/_shared/pr-loop/scripts/test_build_audit_prompt.py +0 -499
  250. package/.agents/skills/_shared/pr-loop/scripts/test_build_converge_task_list.py +0 -140
  251. package/.agents/skills/_shared/pr-loop/scripts/test_build_fix_prompt.py +0 -262
  252. package/.agents/skills/_shared/pr-loop/scripts/test_init_loop_state.py +0 -71
  253. package/.agents/skills/_shared/pr-loop/scripts/test_portable_converge_driver.py +0 -1119
  254. package/.agents/skills/_shared/pr-loop/scripts/test_preflight_worktree.py +0 -287
  255. package/.agents/skills/_shared/pr-loop/scripts/test_select_converge_pacer.py +0 -207
  256. package/.agents/skills/_shared/pr-loop/scripts/test_teardown_worktrees.py +0 -59
  257. package/.agents/skills/_shared/pr-loop/scripts/test_write_handoff.py +0 -201
  258. package/.agents/skills/_shared/pr-loop/scripts/write_audit_outcomes.py +0 -182
  259. package/.agents/skills/_shared/pr-loop/scripts/write_fix_outcomes.py +0 -206
  260. package/.agents/skills/_shared/pr-loop/scripts/write_handoff.py +0 -309
  261. package/.agents/skills/_shared/pr-loop/state-schema.md +0 -5
  262. package/.agents/skills/_shared/pr-loop/worker-spawn.md +0 -5
  263. package/.agents/skills/autoconverge/.claude/CLAUDE.md +0 -1
  264. package/.agents/skills/autoconverge/AGENTS.md +0 -1
  265. package/.agents/skills/autoconverge/SKILL.md +0 -431
  266. package/.agents/skills/autoconverge/reference/.claude/CLAUDE.md +0 -1
  267. package/.agents/skills/autoconverge/reference/AGENTS.md +0 -1
  268. package/.agents/skills/autoconverge/reference/closing-report.md +0 -93
  269. package/.agents/skills/autoconverge/reference/convergence-gates.md +0 -31
  270. package/.agents/skills/autoconverge/reference/convergence.md +0 -219
  271. package/.agents/skills/autoconverge/reference/copilot-findings.md +0 -51
  272. package/.agents/skills/autoconverge/reference/gotchas.md +0 -66
  273. package/.agents/skills/autoconverge/reference/headless-safety.md +0 -44
  274. package/.agents/skills/autoconverge/reference/multi-pr.md +0 -128
  275. package/.agents/skills/autoconverge/reference/self-closing-loop.md +0 -84
  276. package/.agents/skills/autoconverge/reference/stop-conditions.md +0 -127
  277. package/.agents/skills/autoconverge/test_portable_pacer_gate.py +0 -54
  278. package/.agents/skills/autoconverge/workflow/.claude/CLAUDE.md +0 -1
  279. package/.agents/skills/autoconverge/workflow/AGENTS.md +0 -1
  280. package/.agents/skills/autoconverge/workflow/aggregate_runs.py +0 -371
  281. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/.claude/CLAUDE.md +0 -1
  282. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/AGENTS.md +0 -1
  283. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/__init__.py +0 -0
  284. package/.agents/skills/autoconverge/workflow/autoconverge_report_constants/render_report_constants.py +0 -250
  285. package/.agents/skills/autoconverge/workflow/converge.clean-audit.test.mjs +0 -665
  286. package/.agents/skills/autoconverge/workflow/converge.codex-gate.test.mjs +0 -472
  287. package/.agents/skills/autoconverge/workflow/converge.contract.test.mjs +0 -64
  288. package/.agents/skills/autoconverge/workflow/converge.copilot-gate.test.mjs +0 -1009
  289. package/.agents/skills/autoconverge/workflow/converge.fix-progress.test.mjs +0 -107
  290. package/.agents/skills/autoconverge/workflow/converge.fix-recovery.test.mjs +0 -33
  291. package/.agents/skills/autoconverge/workflow/converge.merge-conflict.test.mjs +0 -15
  292. package/.agents/skills/autoconverge/workflow/converge.mjs +0 -3132
  293. package/.agents/skills/autoconverge/workflow/converge.p2-advance.test.mjs +0 -202
  294. package/.agents/skills/autoconverge/workflow/converge.path-aware.test.mjs +0 -47
  295. package/.agents/skills/autoconverge/workflow/converge.precatch.test.mjs +0 -152
  296. package/.agents/skills/autoconverge/workflow/converge.run-input.test.mjs +0 -116
  297. package/.agents/skills/autoconverge/workflow/converge_multi.mjs +0 -169
  298. package/.agents/skills/autoconverge/workflow/converge_multi.run-input.test.mjs +0 -173
  299. package/.agents/skills/autoconverge/workflow/convergence_summary.py +0 -110
  300. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +0 -2
  301. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +0 -2
  302. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +0 -2
  303. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +0 -2
  304. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +0 -2
  305. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +0 -2
  306. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ab1c2d3e4f5a6b7c8.jsonl +0 -2
  307. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +0 -2
  308. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +0 -2
  309. package/.agents/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +0 -266
  310. package/.agents/skills/autoconverge/workflow/render_report.py +0 -1024
  311. package/.agents/skills/autoconverge/workflow/test_aggregate_runs.py +0 -134
  312. package/.agents/skills/autoconverge/workflow/test_convergence_summary.py +0 -149
  313. package/.agents/skills/autoconverge/workflow/test_render_report.py +0 -812
  314. package/.agents/skills/hitl/SKILL.md +0 -45
  315. package/.agents/skills/pr-cleanup/SKILL.md +0 -140
  316. package/.agents/skills/pr-cleanup/reference/process-inventory.md +0 -17
  317. package/.agents/skills/pr-cleanup/reference/task-seeds.md +0 -22
  318. package/.agents/skills/pr-name-by-capability/SKILL.md +0 -73
  319. package/.agents/skills/pr-name-by-capability/reference/fetch-commands.md +0 -29
  320. package/.agents/skills/pr-name-by-capability/reference/offense-examples.md +0 -32
  321. package/.agents/skills/pr-name-by-capability/reference/report-template.md +0 -29
  322. package/.agents/skills/pr-name-by-capability/reference/rule-checklist.md +0 -38
  323. package/.agents/skills/pr-name-by-capability/reference/task-seeds.md +0 -10
  324. package/.agents/skills/pr-plain-language-cleanup/SKILL.md +0 -93
  325. package/.agents/skills/pr-refinement/SKILL.md +0 -31
  326. package/.agents/skills/pr-shared-extraction/SKILL.md +0 -177
  327. package/.agents/skills/pr-shared-extraction/reference/examples.md +0 -46
  328. package/.agents/skills/pr-shared-extraction/reference/offense-taxonomy.md +0 -100
  329. package/.agents/skills/pr-small-cl/SKILL.md +0 -52
  330. package/.agents/skills/pr-title-description/SKILL.md +0 -96
  331. package/.agents/skills/prototype/SKILL.md +0 -85
  332. package/.agents/skills/prototype/reference/honest-limitations.md +0 -23
  333. package/.agents/skills/prototype/reference/promotion-tasks.md +0 -23
  334. package/.agents/skills/prototype/scripts/build_sandbox_settings.py +0 -249
  335. package/.agents/skills/prototype/scripts/conftest.py +0 -15
  336. package/.agents/skills/prototype/scripts/launch_sandbox.py +0 -205
  337. package/.agents/skills/prototype/scripts/probe_sandbox_safety.py +0 -311
  338. package/.agents/skills/prototype/scripts/prototype_scripts_constants/__init__.py +0 -1
  339. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/__init__.py +0 -0
  340. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/build_sandbox_settings_constants.py +0 -41
  341. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/launch_sandbox_constants.py +0 -23
  342. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/probe_sandbox_safety_constants.py +0 -45
  343. package/.agents/skills/prototype/scripts/prototype_scripts_constants/config/prototype_common_constants.py +0 -10
  344. package/.agents/skills/prototype/scripts/test_build_sandbox_settings.py +0 -275
  345. package/.agents/skills/prototype/scripts/test_launch_sandbox.py +0 -303
  346. package/.agents/skills/prototype/scripts/test_probe_sandbox_safety.py +0 -312
  347. package/.agents/skills/prototype/workflows/promotion.md +0 -25
  348. package/.agents/skills/prototype/workflows/sandbox.md +0 -35
  349. package/.agents/skills/rebase/.claude/CLAUDE.md +0 -1
  350. package/.agents/skills/rebase/AGENTS.md +0 -1
  351. package/.agents/skills/rebase/SKILL.md +0 -178
  352. package/.agents/skills/review-router/SKILL.md +0 -51
  353. package/.agents/skills/review-router/reference/route-policy.json +0 -7
  354. package/.agents/skills/review-router/reference/task-seeds.md +0 -1
  355. package/.agents/skills/review-router/scripts/conftest.py +0 -4
  356. package/.agents/skills/review-router/scripts/review_router.py +0 -50
  357. package/.agents/skills/review-router/scripts/review_router_cli.py +0 -211
  358. package/.agents/skills/review-router/scripts/review_router_constants/__init__.py +0 -1
  359. package/.agents/skills/review-router/scripts/review_router_constants/config/__init__.py +0 -0
  360. package/.agents/skills/review-router/scripts/review_router_constants/config/constants.py +0 -13
  361. package/.agents/skills/review-router/scripts/test_review_router.py +0 -23
  362. package/.agents/skills/review-router/scripts/test_review_router_cli.py +0 -47
  363. package/.agents/skills/review-tier/SKILL.md +0 -56
  364. package/.agents/skills/review-tier/reference/task-seeds.md +0 -1
  365. package/.agents/skills/review-tier/reference/tier-policy.json +0 -9
  366. package/.agents/skills/review-tier/scripts/conftest.py +0 -4
  367. package/.agents/skills/review-tier/scripts/review_tier.py +0 -359
  368. package/.agents/skills/review-tier/scripts/review_tier_constants/__init__.py +0 -1
  369. package/.agents/skills/review-tier/scripts/review_tier_constants/config/__init__.py +0 -0
  370. package/.agents/skills/review-tier/scripts/review_tier_constants/config/constants.py +0 -29
  371. package/.agents/skills/review-tier/scripts/test_generation.py +0 -159
  372. package/.agents/skills/review-tier/scripts/test_review_tier.py +0 -33
  373. package/.agents/skills/run-claude-dev-env/SKILL.md +0 -84
  374. package/.agents/skills/session-log/.claude/CLAUDE.md +0 -1
  375. package/.agents/skills/session-log/AGENTS.md +0 -1
  376. package/.agents/skills/session-log/SKILL.md +0 -170
  377. package/.agents/skills/session-log/templates/frontmatter.md +0 -40
  378. package/.agents/skills/session-tidy/.claude/CLAUDE.md +0 -1
  379. package/.agents/skills/session-tidy/AGENTS.md +0 -1
  380. package/.agents/skills/session-tidy/SKILL.md +0 -191
  381. package/.agents/skills/skill-builder/references/.claude/CLAUDE.md +0 -1
  382. package/.agents/skills/skill-builder/references/AGENTS.md +0 -1
  383. package/.agents/skills/skill-builder/references/delegation-map.md +0 -130
  384. package/.agents/skills/skill-builder/references/description-field.md +0 -111
  385. package/.agents/skills/skill-builder/references/deterministic-elements.md +0 -218
  386. package/.agents/skills/skill-builder/references/progressive-disclosure.md +0 -122
  387. package/.agents/skills/skill-builder/references/self-audit-checklist.md +0 -126
  388. package/.agents/skills/skill-builder/references/skill-modularity.md +0 -111
  389. package/.agents/skills/skill-builder/references/skill-types.md +0 -232
  390. package/.agents/skills/skill-builder/references/thariq-x-post-skills.json +0 -33
  391. package/.agents/skills/skill-builder/templates/.claude/CLAUDE.md +0 -1
  392. package/.agents/skills/skill-builder/templates/AGENTS.md +0 -1
  393. package/.agents/skills/skill-builder/templates/gap-analysis.md +0 -87
  394. package/.agents/skills/skill-builder/workflows/.claude/CLAUDE.md +0 -1
  395. package/.agents/skills/skill-builder/workflows/AGENTS.md +0 -1
  396. package/.agents/skills/skill-builder/workflows/improve-skill.md +0 -136
  397. package/.agents/skills/skill-builder/workflows/new-skill.md +0 -179
  398. package/.agents/skills/skill-builder/workflows/polish-skill.md +0 -139
  399. package/.agents/skills/source-command-sr-loop/SKILL.md +0 -82
  400. package/.agents/skills/update/.claude/CLAUDE.md +0 -1
  401. package/.agents/skills/update/AGENTS.md +0 -1
  402. package/.agents/skills/update/SKILL.md +0 -190
  403. package/_shared/pr-loop/AGENTS.md +0 -1
  404. package/_shared/pr-loop/audit-contract.md +0 -183
  405. package/_shared/pr-loop/audit-reply-template.md +0 -151
  406. package/_shared/pr-loop/code-rules-gate.md +0 -65
  407. package/_shared/pr-loop/fix-protocol.md +0 -60
  408. package/_shared/pr-loop/gh-payloads.md +0 -75
  409. package/_shared/pr-loop/post-audit-thread-contract.md +0 -51
  410. package/_shared/pr-loop/precatch-rubric.md +0 -66
  411. package/_shared/pr-loop/preflight-proposal.md +0 -56
  412. package/_shared/pr-loop/scripts/post_audit_thread.py +0 -1242
  413. package/_shared/pr-loop/scripts/pr_loop_shared_constants/post_audit_thread_constants.py +0 -199
  414. package/_shared/pr-loop/scripts/tests/test_post_audit_thread.py +0 -1115
  415. package/_shared/pr-loop/scripts/tests/test_post_audit_thread_constants.py +0 -129
  416. package/_shared/pr-loop/state-schema.md +0 -45
  417. package/_shared/pr-loop/worker-spawn.md +0 -189
  418. package/hooks/blocking/ask_user_question_shape_blocker.py +0 -83
  419. package/hooks/blocking/bot_mention_comment_blocker.py +0 -76
  420. package/hooks/blocking/claude_md_orphan_file_blocker.py +0 -129
  421. package/hooks/blocking/cursor_cli_python_misfire_blocker.py +0 -108
  422. package/hooks/blocking/destructive_command_blocker.py +0 -2073
  423. package/hooks/blocking/fable_spawn_gate.py +0 -187
  424. package/hooks/blocking/luna_fast_mode_gate.py +0 -160
  425. package/hooks/blocking/nas_ssh_binary_enforcer.py +0 -163
  426. package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +0 -260
  427. package/hooks/blocking/package_inventory_stale_blocker.py +0 -107
  428. package/hooks/blocking/pii_prevention_blocker.py +0 -365
  429. package/hooks/blocking/piped_pytest_blocker.py +0 -1223
  430. package/hooks/blocking/question_to_user_enforcer.py +0 -130
  431. package/hooks/blocking/send_user_file_open_locally_blocker.py +0 -71
  432. package/hooks/blocking/sensitive_file_protector.py +0 -167
  433. package/hooks/blocking/session_edit_stage_gate.py +0 -684
  434. package/hooks/blocking/session_handoff_blocker.py +0 -182
  435. package/hooks/blocking/shell_substitution_blocker.py +0 -350
  436. package/hooks/blocking/test_ask_user_question_shape.py +0 -69
  437. package/hooks/blocking/test_bot_mention_comment_blocker.py +0 -131
  438. package/hooks/blocking/test_claude_md_orphan_file_blocker.py +0 -1277
  439. package/hooks/blocking/test_cursor_cli_python_misfire_blocker.py +0 -208
  440. package/hooks/blocking/test_destructive_command_blocker.py +0 -2024
  441. package/hooks/blocking/test_destructive_command_blocker_deny_mode.py +0 -105
  442. package/hooks/blocking/test_destructive_command_blocker_no_verify.py +0 -122
  443. package/hooks/blocking/test_destructive_command_blocker_patterns.py +0 -133
  444. package/hooks/blocking/test_fable_spawn_gate.py +0 -381
  445. package/hooks/blocking/test_inventory_deadlock_resolution.py +0 -154
  446. package/hooks/blocking/test_luna_fast_mode_gate.py +0 -211
  447. package/hooks/blocking/test_nas_ssh_binary_enforcer.py +0 -225
  448. package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +0 -231
  449. package/hooks/blocking/test_package_inventory_stale_blocker.py +0 -382
  450. package/hooks/blocking/test_pii_prevention_blocker.py +0 -1222
  451. package/hooks/blocking/test_pii_prevention_windows_git_path.py +0 -41
  452. package/hooks/blocking/test_pii_write_surface_ephemeral.py +0 -221
  453. package/hooks/blocking/test_piped_pytest_blocker.py +0 -587
  454. package/hooks/blocking/test_precommit_code_rules_gate_native_owner.py +0 -233
  455. package/hooks/blocking/test_question_to_user_enforcer.py +0 -169
  456. package/hooks/blocking/test_send_user_file_open_locally_blocker.py +0 -118
  457. package/hooks/blocking/test_sensitive_file_protector.py +0 -365
  458. package/hooks/blocking/test_session_edit_stage_gate.py +0 -537
  459. package/hooks/blocking/test_session_edit_stage_gate_staging.py +0 -64
  460. package/hooks/blocking/test_session_edit_stage_gate_support.py +0 -204
  461. package/hooks/blocking/test_session_edit_stage_gate_tracker.py +0 -116
  462. package/hooks/blocking/test_session_handoff_blocker.py +0 -318
  463. package/hooks/blocking/test_shell_substitution_blocker.py +0 -298
  464. package/hooks/blocking/test_unscoped_search_blocker.py +0 -102
  465. package/hooks/blocking/test_write_existing_file_blocker.py +0 -122
  466. package/hooks/blocking/tests/test_pii_prevention_blocker.py +0 -259
  467. package/hooks/blocking/unscoped_search_blocker.py +0 -391
  468. package/hooks/blocking/write_existing_file_blocker.py +0 -124
  469. package/hooks/hooks_constants/bot_mention_comment_blocker_constants.py +0 -19
  470. package/hooks/hooks_constants/cursor_cli_python_misfire_blocker_constants.py +0 -79
  471. package/hooks/hooks_constants/fable_spawn_gate_constants.py +0 -61
  472. package/hooks/hooks_constants/luna_fast_mode_gate_constants.py +0 -45
  473. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +0 -20
  474. package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +0 -57
  475. package/hooks/hooks_constants/send_user_file_open_locally_blocker_constants.py +0 -17
  476. package/hooks/hooks_constants/sensitive_file_protector_constants.py +0 -40
  477. package/hooks/hooks_constants/session_handoff_blocker_constants.py +0 -10
  478. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +0 -80
  479. /package/.agents/skills/{_shared/pr-loop → session-continuity}/AGENTS.md +0 -0
  480. /package/{_shared/pr-loop → .agents/skills/session-continuity}/CLAUDE.md +0 -0
@@ -1,233 +0,0 @@
1
- """Production-path tests for native staged-gate ownership.
2
-
3
- The tests run the Agent Bash dispatcher and a native Git pre-commit hook against
4
- the same isolated repository. The agent path passes the commit through. The
5
- native path runs the staged gate and controls the commit.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- from collections.abc import Iterator
11
- from contextlib import contextmanager
12
- import json
13
- import shutil
14
- import stat
15
- import subprocess
16
- import sys
17
- from pathlib import Path
18
-
19
- import pytest
20
-
21
- HOOKS_ROOT = Path(__file__).resolve().parent.parent
22
- BLOCKING_ROOT = HOOKS_ROOT / "blocking"
23
- GIT_HOOKS_ROOT = HOOKS_ROOT / "git-hooks"
24
- PRE_COMMIT_SOURCE_PATH = GIT_HOOKS_ROOT / "pre_commit.py"
25
- GATE_UTILS_SOURCE_PATH = GIT_HOOKS_ROOT / "gate_utils.py"
26
- GIT_HOOKS_CONSTANTS_SOURCE_PATH = GIT_HOOKS_ROOT / "git_hooks_constants"
27
- DISPATCHER_SOURCE_PATH = BLOCKING_ROOT / "bash_pre_tool_use_dispatcher.py"
28
- GIT_COMMAND_TIMEOUT_SECONDS = 60
29
- CLEAN_MODULE_SOURCE = "def add_one(number: int) -> int:\n return number + 1\n"
30
-
31
-
32
- def run_git(
33
- repository_root: Path,
34
- *git_arguments: str,
35
- check: bool = True,
36
- ) -> subprocess.CompletedProcess[str]:
37
- """Run one isolated Git command and return its captured process record."""
38
- return subprocess.run(
39
- ["git", *git_arguments],
40
- cwd=str(repository_root),
41
- check=check,
42
- capture_output=True,
43
- text=True,
44
- timeout=GIT_COMMAND_TIMEOUT_SECONDS,
45
- )
46
-
47
-
48
- def initialize_repository(repository_root: Path) -> None:
49
- """Create a repository with one committed base file and no active hook."""
50
- run_git(repository_root, "init")
51
- run_git(repository_root, "config", "user.name", "Hook Test")
52
- run_git(repository_root, "config", "user.email", "hook-test@example.invalid")
53
- run_git(repository_root, "config", "core.hooksPath", "absent_fixture_hooks")
54
- (repository_root / "README.md").write_text("base\n", encoding="utf-8")
55
- run_git(repository_root, "add", "README.md")
56
- run_git(repository_root, "commit", "-m", "base")
57
-
58
-
59
- def write_gate_script(gate_path: Path, marker_path: Path, exit_code: int) -> None:
60
- """Write a staged-gate fixture that records arguments and exits."""
61
- gate_path.write_text(
62
- "import pathlib\n"
63
- "import sys\n"
64
- f"pathlib.Path({str(marker_path)!r}).write_text("
65
- "'\\n'.join(sys.argv[1:]), encoding='utf-8')\n"
66
- f"sys.exit({exit_code})\n",
67
- encoding="utf-8",
68
- )
69
-
70
-
71
- def install_native_pre_commit(hooks_path: Path) -> None:
72
- """Install the native pre-commit module and its self-contained imports."""
73
- hooks_path.mkdir()
74
- shutil.copyfile(PRE_COMMIT_SOURCE_PATH, hooks_path / "pre_commit.py")
75
- shutil.copyfile(GATE_UTILS_SOURCE_PATH, hooks_path / "gate_utils.py")
76
- shutil.copytree(
77
- GIT_HOOKS_CONSTANTS_SOURCE_PATH,
78
- hooks_path / "git_hooks_constants",
79
- )
80
- pre_commit_path = hooks_path / "pre-commit"
81
- pre_commit_path.write_text(
82
- "#!/usr/bin/env python3\n"
83
- "import sys\n"
84
- "from pathlib import Path\n"
85
- "shim_directory = Path(__file__).resolve().parent\n"
86
- "sys.path.insert(0, str(shim_directory))\n"
87
- "import pre_commit\n"
88
- "sys.exit(pre_commit.main())\n",
89
- encoding="utf-8",
90
- )
91
- pre_commit_path.chmod(pre_commit_path.stat().st_mode | stat.S_IXUSR)
92
-
93
-
94
- def configured_hooks_path(repository_root: Path) -> str | None:
95
- """Return the repository-local hooks path when one is configured."""
96
- completed_config = run_git(
97
- repository_root,
98
- "config",
99
- "--local",
100
- "--get",
101
- "core.hooksPath",
102
- check=False,
103
- )
104
- if completed_config.returncode != 0:
105
- return None
106
- return completed_config.stdout.strip()
107
-
108
-
109
- def restore_hooks_path(repository_root: Path, prior_hooks_path: str | None) -> None:
110
- """Restore the repository-local hooks path captured before a benchmark."""
111
- if prior_hooks_path is None:
112
- run_git(
113
- repository_root,
114
- "config",
115
- "--local",
116
- "--unset-all",
117
- "core.hooksPath",
118
- check=False,
119
- )
120
- return
121
- run_git(repository_root, "config", "--local", "core.hooksPath", prior_hooks_path)
122
-
123
-
124
- @contextmanager
125
- def temporary_hooks_path(repository_root: Path, benchmark_hooks_path: Path) -> Iterator[None]:
126
- """Apply a benchmark hooks path and restore the prior local setting."""
127
- prior_hooks_path = configured_hooks_path(repository_root)
128
- run_git(repository_root, "config", "--local", "core.hooksPath", str(benchmark_hooks_path))
129
- try:
130
- yield
131
- finally:
132
- restore_hooks_path(repository_root, prior_hooks_path)
133
-
134
-
135
- def stage_module(repository_root: Path) -> None:
136
- """Write and stage one Python module for the commit fixture."""
137
- (repository_root / "widget.py").write_text(CLEAN_MODULE_SOURCE, encoding="utf-8")
138
- run_git(repository_root, "add", "widget.py")
139
-
140
-
141
- def build_bash_payload(repository_root: Path) -> str:
142
- """Build the Bash dispatcher payload for a commit in the fixture repository."""
143
- commit_command = f'git -C "{repository_root}" commit -m add'
144
- return json.dumps({"tool_name": "Bash", "tool_input": {"command": commit_command}})
145
-
146
-
147
- def run_agent_dispatcher(repository_root: Path) -> subprocess.CompletedProcess[str]:
148
- """Run the production Bash dispatcher against the fixture commit command."""
149
- return subprocess.run(
150
- [sys.executable, str(DISPATCHER_SOURCE_PATH)],
151
- cwd=str(repository_root),
152
- input=build_bash_payload(repository_root),
153
- capture_output=True,
154
- text=True,
155
- timeout=GIT_COMMAND_TIMEOUT_SECONDS,
156
- )
157
-
158
-
159
- def run_native_commit(repository_root: Path) -> subprocess.CompletedProcess[str]:
160
- """Run the real Git commit that invokes the configured native hook."""
161
- return run_git(
162
- repository_root,
163
- "commit",
164
- "-m",
165
- "add widget",
166
- check=False,
167
- )
168
-
169
-
170
- def test_agent_dispatcher_passes_commit_through_without_running_gate(
171
- tmp_path: Path,
172
- monkeypatch: pytest.MonkeyPatch,
173
- ) -> None:
174
- """The Agent Bash path continues the commit without running the staged gate."""
175
- initialize_repository(tmp_path)
176
- stage_module(tmp_path)
177
- gate_marker_path = tmp_path / "agent_gate_invocation.txt"
178
- gate_path = tmp_path / "agent_gate.py"
179
- write_gate_script(gate_path, gate_marker_path, exit_code=1)
180
- monkeypatch.setenv("CODE_RULES_GATE_PATH", str(gate_path))
181
-
182
- completed_dispatcher = run_agent_dispatcher(tmp_path)
183
-
184
- assert completed_dispatcher.returncode == 0, completed_dispatcher.stderr
185
- assert completed_dispatcher.stdout.strip() == ""
186
- assert not gate_marker_path.exists()
187
-
188
-
189
- @pytest.mark.parametrize("gate_exit_code, expected_commit_exit_code", [(1, 1), (0, 0)])
190
- def test_installed_native_pre_commit_controls_staged_gate_decision(
191
- tmp_path: Path,
192
- monkeypatch: pytest.MonkeyPatch,
193
- gate_exit_code: int,
194
- expected_commit_exit_code: int,
195
- ) -> None:
196
- """The native Git hook runs the staged gate and returns its commit decision."""
197
- initialize_repository(tmp_path)
198
- native_hooks_path = tmp_path / "native_hooks"
199
- install_native_pre_commit(native_hooks_path)
200
- stage_module(tmp_path)
201
- gate_marker_path = tmp_path / "native_gate_invocation.txt"
202
- gate_path = tmp_path / "native_gate.py"
203
- write_gate_script(gate_path, gate_marker_path, gate_exit_code)
204
- monkeypatch.setenv("CODE_RULES_GATE_PATH", str(gate_path))
205
-
206
- with temporary_hooks_path(tmp_path, native_hooks_path):
207
- completed_commit = run_native_commit(tmp_path)
208
-
209
- assert completed_commit.returncode == expected_commit_exit_code
210
- assert gate_marker_path.read_text(encoding="utf-8") == "--immediate"
211
-
212
-
213
- def test_temporary_hooks_path_restores_shared_worktree_config_on_timeout(
214
- tmp_path: Path,
215
- ) -> None:
216
- initialize_repository(tmp_path)
217
- supported_hooks_path = tmp_path / "supported_hooks"
218
- supported_hooks_path.mkdir()
219
- run_git(tmp_path, "config", "--local", "core.hooksPath", str(supported_hooks_path))
220
- unrelated_worktree = tmp_path.parent / "unrelated_worktree"
221
- run_git(tmp_path, "worktree", "add", "--detach", str(unrelated_worktree))
222
- benchmark_hooks_path = tmp_path / "benchmark_hooks"
223
- benchmark_hooks_path.mkdir()
224
-
225
- try:
226
- with pytest.raises(subprocess.TimeoutExpired):
227
- with temporary_hooks_path(tmp_path, benchmark_hooks_path):
228
- raise subprocess.TimeoutExpired("benchmark", 1)
229
-
230
- assert configured_hooks_path(tmp_path) == str(supported_hooks_path)
231
- assert configured_hooks_path(unrelated_worktree) == str(supported_hooks_path)
232
- finally:
233
- run_git(tmp_path, "worktree", "remove", "--force", str(unrelated_worktree))
@@ -1,169 +0,0 @@
1
- """Tests for question_to_user_enforcer hook response shape and detection logic."""
2
-
3
- import json
4
- import os
5
- import subprocess
6
- import sys
7
-
8
- HOOK_SCRIPT_PATH = os.path.join(
9
- os.path.dirname(__file__), "question_to_user_enforcer.py"
10
- )
11
- _HOOKS_DIR = os.path.dirname(HOOK_SCRIPT_PATH)
12
- _HOOKS_ROOT = os.path.join(_HOOKS_DIR, "..")
13
- if _HOOKS_DIR not in sys.path:
14
- sys.path.insert(0, _HOOKS_DIR)
15
- if _HOOKS_ROOT not in sys.path:
16
- sys.path.insert(0, _HOOKS_ROOT)
17
- import question_to_user_enforcer
18
- from hooks_constants.messages import USER_FACING_ASKUSERQUESTION_NOTICE
19
- from hooks_constants.text_stripping import strip_code_and_quotes
20
-
21
- CLEAN_DECLARATIVE_MESSAGE = "I applied the rename across both files. The tests pass."
22
- TRAILING_QUESTION_MESSAGE = (
23
- "I applied the rename across both files. Should this also propagate to the docs?"
24
- )
25
- WANT_ME_TO_MESSAGE = "I finished the refactor.\n\nWant me to open the PR now?"
26
- SHOULD_I_STATEMENT_MESSAGE = (
27
- "The diff is ready.\n\nShould I proceed with committing it."
28
- )
29
- FENCED_CODE_QUESTION_MESSAGE = (
30
- "Here is the diagnostic snippet:\n\n"
31
- "```python\n"
32
- "print('does this work?')\n"
33
- "```\n\n"
34
- "The snippet confirms the behavior."
35
- )
36
- RHETORICAL_MIDDLE_MESSAGE = (
37
- "Consider the failure mode.\n\n"
38
- "What happens if the queue is empty? The handler short-circuits cleanly.\n\n"
39
- "That covers the edge case."
40
- )
41
- QUESTION_WITH_TRAILING_DOUBLE_QUOTE_MESSAGE = (
42
- 'I renamed the flag.\n\nDid you mean "enable_fast_path?"'
43
- )
44
- QUESTION_WITH_TRAILING_SINGLE_QUOTE_MESSAGE = (
45
- "I renamed the flag.\n\nDid you mean 'enable_fast_path?'"
46
- )
47
- QUESTION_WITH_TRAILING_PAREN_MESSAGE = (
48
- "I finished the refactor.\n\nShould I also bump the version (minor or patch?)"
49
- )
50
- QUESTION_WITH_TRAILING_BRACKET_MESSAGE = (
51
- "I finished the refactor.\n\nShould I also bump the version [minor or patch?]"
52
- )
53
- QUESTION_WITH_TRAILING_SPACE_MESSAGE = (
54
- "I finished the refactor.\n\nShould I also bump the version? "
55
- )
56
-
57
-
58
- def run_hook_with_payload(payload: dict) -> subprocess.CompletedProcess:
59
- hook_input_payload = json.dumps(payload)
60
- return subprocess.run(
61
- [sys.executable, HOOK_SCRIPT_PATH],
62
- input=hook_input_payload,
63
- capture_output=True,
64
- text=True,
65
- check=False,
66
- )
67
-
68
-
69
- def run_hook_with_message(assistant_message: str) -> subprocess.CompletedProcess:
70
- return run_hook_with_payload({"last_assistant_message": assistant_message})
71
-
72
-
73
- def test_blocker_uses_shared_strip_code_and_quotes() -> None:
74
- assert question_to_user_enforcer.strip_code_and_quotes is strip_code_and_quotes
75
-
76
-
77
- def test_clean_declarative_message_passes_through():
78
- completed_process = run_hook_with_message(CLEAN_DECLARATIVE_MESSAGE)
79
- assert completed_process.returncode == 0
80
- assert completed_process.stdout == ""
81
-
82
-
83
- def test_final_paragraph_ending_with_question_mark_emits_block():
84
- completed_process = run_hook_with_message(TRAILING_QUESTION_MESSAGE)
85
- assert completed_process.returncode == 0
86
- parsed_response = json.loads(completed_process.stdout)
87
- assert parsed_response["decision"] == "block"
88
-
89
-
90
- def test_want_me_to_preamble_in_final_paragraph_emits_block():
91
- completed_process = run_hook_with_message(WANT_ME_TO_MESSAGE)
92
- assert completed_process.returncode == 0
93
- parsed_response = json.loads(completed_process.stdout)
94
- assert parsed_response["decision"] == "block"
95
-
96
-
97
- def test_should_i_preamble_without_question_mark_emits_block():
98
- completed_process = run_hook_with_message(SHOULD_I_STATEMENT_MESSAGE)
99
- assert completed_process.returncode == 0
100
- parsed_response = json.loads(completed_process.stdout)
101
- assert parsed_response["decision"] == "block"
102
-
103
-
104
- def test_question_mark_inside_fenced_code_block_passes_through():
105
- completed_process = run_hook_with_message(FENCED_CODE_QUESTION_MESSAGE)
106
- assert completed_process.returncode == 0
107
- assert completed_process.stdout == ""
108
-
109
-
110
- def test_stop_hook_active_flag_passes_through():
111
- completed_process = run_hook_with_payload(
112
- {
113
- "last_assistant_message": TRAILING_QUESTION_MESSAGE,
114
- "stop_hook_active": True,
115
- }
116
- )
117
- assert completed_process.returncode == 0
118
- assert completed_process.stdout == ""
119
-
120
-
121
- def test_rhetorical_middle_paragraph_with_declarative_final_passes_through():
122
- completed_process = run_hook_with_message(RHETORICAL_MIDDLE_MESSAGE)
123
- assert completed_process.returncode == 0
124
- assert completed_process.stdout == ""
125
-
126
-
127
- def test_block_response_json_shape():
128
- completed_process = run_hook_with_message(TRAILING_QUESTION_MESSAGE)
129
- assert completed_process.returncode == 0
130
- parsed_response = json.loads(completed_process.stdout)
131
- assert parsed_response["decision"] == "block"
132
- assert "AskUserQuestion" in parsed_response["reason"]
133
- assert parsed_response["systemMessage"] == USER_FACING_ASKUSERQUESTION_NOTICE
134
- assert parsed_response["suppressOutput"] is True
135
-
136
-
137
- def test_question_followed_by_double_quote_emits_block():
138
- completed_process = run_hook_with_message(QUESTION_WITH_TRAILING_DOUBLE_QUOTE_MESSAGE)
139
- assert completed_process.returncode == 0
140
- parsed_response = json.loads(completed_process.stdout)
141
- assert parsed_response["decision"] == "block"
142
-
143
-
144
- def test_question_followed_by_single_quote_emits_block():
145
- completed_process = run_hook_with_message(QUESTION_WITH_TRAILING_SINGLE_QUOTE_MESSAGE)
146
- assert completed_process.returncode == 0
147
- parsed_response = json.loads(completed_process.stdout)
148
- assert parsed_response["decision"] == "block"
149
-
150
-
151
- def test_question_followed_by_closing_paren_emits_block():
152
- completed_process = run_hook_with_message(QUESTION_WITH_TRAILING_PAREN_MESSAGE)
153
- assert completed_process.returncode == 0
154
- parsed_response = json.loads(completed_process.stdout)
155
- assert parsed_response["decision"] == "block"
156
-
157
-
158
- def test_question_followed_by_closing_bracket_emits_block():
159
- completed_process = run_hook_with_message(QUESTION_WITH_TRAILING_BRACKET_MESSAGE)
160
- assert completed_process.returncode == 0
161
- parsed_response = json.loads(completed_process.stdout)
162
- assert parsed_response["decision"] == "block"
163
-
164
-
165
- def test_question_followed_by_trailing_space_emits_block():
166
- completed_process = run_hook_with_message(QUESTION_WITH_TRAILING_SPACE_MESSAGE)
167
- assert completed_process.returncode == 0
168
- parsed_response = json.loads(completed_process.stdout)
169
- assert parsed_response["decision"] == "block"
@@ -1,118 +0,0 @@
1
- """Unit tests for the send-user-file-open-locally PreToolUse hook."""
2
-
3
- import importlib.util
4
- import io
5
- import json
6
- import pathlib
7
- import sys
8
- from unittest import mock
9
-
10
- _HOOK_DIR = pathlib.Path(__file__).parent
11
- if str(_HOOK_DIR) not in sys.path:
12
- sys.path.insert(0, str(_HOOK_DIR))
13
-
14
- hook_spec = importlib.util.spec_from_file_location(
15
- "send_user_file_open_locally_blocker",
16
- _HOOK_DIR / "send_user_file_open_locally_blocker.py",
17
- )
18
- assert hook_spec is not None
19
- assert hook_spec.loader is not None
20
- hook_module = importlib.util.module_from_spec(hook_spec)
21
- hook_spec.loader.exec_module(hook_module)
22
-
23
- _should_block = hook_module._should_block
24
-
25
- from hooks_constants.send_user_file_open_locally_blocker_constants import (
26
- CORRECTIVE_MESSAGE,
27
- PROACTIVE_STATUS,
28
- TOOL_NAME,
29
- )
30
-
31
-
32
- def test_blocks_normal_status() -> None:
33
- assert _should_block("normal") is True
34
-
35
-
36
- def test_blocks_empty_status() -> None:
37
- assert _should_block("") is True
38
-
39
-
40
- def test_blocks_unknown_status() -> None:
41
- assert _should_block("whatever") is True
42
-
43
-
44
- def test_allows_proactive_status() -> None:
45
- assert _should_block(PROACTIVE_STATUS) is False
46
-
47
-
48
- def test_corrective_message_points_to_native_windows_app() -> None:
49
- assert "native Windows app" in CORRECTIVE_MESSAGE
50
- assert "Invoke-Item -LiteralPath" in CORRECTIVE_MESSAGE
51
- assert "Show-Asset.ps1" not in CORRECTIVE_MESSAGE
52
- assert "Cursor.exe" in CORRECTIVE_MESSAGE
53
- assert "EPIPE" in CORRECTIVE_MESSAGE
54
-
55
-
56
- def test_corrective_message_names_proactive_escape_hatch() -> None:
57
- assert PROACTIVE_STATUS in CORRECTIVE_MESSAGE
58
-
59
-
60
- def _run_main_with_io(input_text: str) -> str:
61
- with mock.patch("sys.stdin", io.StringIO(input_text)):
62
- with mock.patch("sys.stdout", new_callable=io.StringIO) as mock_stdout:
63
- try:
64
- hook_module.main()
65
- except SystemExit:
66
- pass
67
- return mock_stdout.getvalue()
68
-
69
-
70
- def test_main_blocks_normal_attach() -> None:
71
- hook_input = {
72
- "tool_name": TOOL_NAME,
73
- "tool_input": {"files": ["report.html"], "status": "normal"},
74
- }
75
- output_text = _run_main_with_io(json.dumps(hook_input))
76
- output = json.loads(output_text)
77
- assert output["hookSpecificOutput"]["permissionDecision"] == "deny"
78
- assert "native Windows app" in output["hookSpecificOutput"]["permissionDecisionReason"]
79
-
80
-
81
- def test_main_allows_proactive_attach() -> None:
82
- hook_input = {
83
- "tool_name": TOOL_NAME,
84
- "tool_input": {"files": ["report.html"], "status": "proactive"},
85
- }
86
- assert _run_main_with_io(json.dumps(hook_input)) == ""
87
-
88
-
89
- def test_main_blocks_when_status_missing() -> None:
90
- hook_input = {
91
- "tool_name": TOOL_NAME,
92
- "tool_input": {"files": ["report.html"]},
93
- }
94
- output_text = _run_main_with_io(json.dumps(hook_input))
95
- output = json.loads(output_text)
96
- assert output["hookSpecificOutput"]["permissionDecision"] == "deny"
97
-
98
-
99
- def test_main_blocks_when_tool_input_is_null() -> None:
100
- hook_input = {
101
- "tool_name": TOOL_NAME,
102
- "tool_input": None,
103
- }
104
- output_text = _run_main_with_io(json.dumps(hook_input))
105
- output = json.loads(output_text)
106
- assert output["hookSpecificOutput"]["permissionDecision"] == "deny"
107
-
108
-
109
- def test_main_passes_wrong_tool_name() -> None:
110
- hook_input = {
111
- "tool_name": "Write",
112
- "tool_input": {"files": ["report.html"], "status": "normal"},
113
- }
114
- assert _run_main_with_io(json.dumps(hook_input)) == ""
115
-
116
-
117
- def test_main_passes_malformed_json() -> None:
118
- assert _run_main_with_io("not valid json {{{") == ""