cc-safe-setup 29.7.0 → 30.0.4

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 (1022) hide show
  1. package/.claude-plugin/marketplace.json +72 -19
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CONTRIBUTING.md +7 -2
  4. package/COOKBOOK.md +50 -46
  5. package/LICENSE +21 -0
  6. package/MIGRATION.md +8 -8
  7. package/README.md +419 -512
  8. package/SAFETY_CHECKLIST.md +15 -7
  9. package/SERVICES.md +194 -0
  10. package/SETTINGS_REFERENCE.md +236 -17
  11. package/SKILL.md +5 -5
  12. package/TROUBLESHOOTING.md +35 -14
  13. package/action.yml +12 -4
  14. package/audit/README.md +84 -0
  15. package/audit/audit-checklist.md +152 -0
  16. package/audit/boundary-selftest.sh +85 -0
  17. package/audit/boundary.sh +123 -0
  18. package/audit/count-hooks.py +42 -0
  19. package/audit/find-dead-hooks.sh +82 -0
  20. package/audit/find-unfirable-rules.sh +142 -0
  21. package/audit/fire.sh +97 -0
  22. package/audit/selftest.sh +42 -0
  23. package/audit/unfirable-selftest.sh +81 -0
  24. package/audit-web/index.html +9 -9
  25. package/examples/README.md +54 -17
  26. package/examples/account-billing-log.sh +98 -0
  27. package/examples/account-routing-preflight.sh +123 -0
  28. package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
  29. package/examples/agent-view-quota-decrement.sh +32 -0
  30. package/examples/agent-view-quota-warn.sh +94 -0
  31. package/examples/agents-md-edit-drift-warner.sh +223 -0
  32. package/examples/agents-md-loader.sh +160 -0
  33. package/examples/agents-md-sync-checker.sh +102 -0
  34. package/examples/ai-slop-punctuation-arrest.sh +210 -0
  35. package/examples/allowlist.sh +70 -10
  36. package/examples/always-allow-pattern-suggester.sh +125 -0
  37. package/examples/ansible-vault-guard.sh +2 -1
  38. package/examples/anthropic-base-url-guard.sh +76 -0
  39. package/examples/api-busyloop-guard.sh +123 -0
  40. package/examples/api-endpoint-guard.sh +12 -0
  41. package/examples/api-key-in-url-guard.sh +17 -1
  42. package/examples/api-rate-limit-guard.sh +36 -1
  43. package/examples/api-rate-limit-tracker.sh +12 -0
  44. package/examples/articulated-scope-capture.sh +101 -0
  45. package/examples/askuserquestion-autonomy-gate.sh +102 -0
  46. package/examples/attachment-traversal-guard.sh +118 -0
  47. package/examples/aup-block-pattern-logger.sh +161 -0
  48. package/examples/aup-false-positive-helper.sh +124 -0
  49. package/examples/aup-large-tool-output-warner.sh +282 -0
  50. package/examples/aup-retry-loop-guard.sh +229 -0
  51. package/examples/auth-expiry-reminder.sh +157 -0
  52. package/examples/auth-macos-sleep-detector.sh +185 -0
  53. package/examples/auth-path-detector.sh +171 -0
  54. package/examples/auth-status-checker.sh +157 -0
  55. package/examples/authorized-reconfirmation-detector.sh +195 -0
  56. package/examples/auto-approve-build.sh +39 -0
  57. package/examples/auto-approve-cargo.sh +31 -1
  58. package/examples/auto-approve-docker.sh +35 -0
  59. package/examples/auto-approve-git-read.sh +37 -14
  60. package/examples/auto-approve-go.sh +30 -1
  61. package/examples/auto-approve-gradle.sh +29 -1
  62. package/examples/auto-approve-make.sh +29 -1
  63. package/examples/auto-approve-maven.sh +29 -1
  64. package/examples/auto-approve-python.sh +41 -1
  65. package/examples/auto-approve-readonly-tools.sh +1 -0
  66. package/examples/auto-approve-readonly.sh +110 -33
  67. package/examples/auto-approve-ssh.sh +30 -1
  68. package/examples/auto-approve-test.sh +44 -0
  69. package/examples/auto-checkpoint.sh +1 -1
  70. package/examples/auto-compact-prep.sh +0 -0
  71. package/examples/auto-git-checkpoint.sh +0 -0
  72. package/examples/auto-mode-safe-commands.sh +53 -1
  73. package/examples/auto-mode-safety-enforcer.sh +151 -4
  74. package/examples/auto-push-session-branch.sh +22 -0
  75. package/examples/aws-production-guard.sh +13 -1
  76. package/examples/aws-region-guard.sh +1 -1
  77. package/examples/background-cost-launch-guard.sh +82 -0
  78. package/examples/background-task-guard.sh +12 -0
  79. package/examples/backup-before-refactor.sh +0 -0
  80. package/examples/banned-command-guard.sh +12 -0
  81. package/examples/bash-allowlist-secondary-check.sh +157 -0
  82. package/examples/bash-domain-allowlist.sh +12 -0
  83. package/examples/bash-fanout-bounded-rewriter.sh +191 -0
  84. package/examples/bash-heuristic-approver.sh +112 -10
  85. package/examples/bash-project-fence.sh +194 -0
  86. package/examples/bash-safety-auto-deny.sh +12 -0
  87. package/examples/bash-secret-output-detector.sh +44 -3
  88. package/examples/bash-trace-guard.sh +12 -0
  89. package/examples/bashrc-safety-check.sh +0 -0
  90. package/examples/bg-permission-prompt-warner.sh +182 -0
  91. package/examples/bg-task-cooldown-guard.sh +12 -0
  92. package/examples/binary-read-detector.sh +135 -0
  93. package/examples/binary-upload-guard.sh +12 -0
  94. package/examples/block-database-wipe.sh +35 -10
  95. package/examples/branch-name-check.sh +8 -3
  96. package/examples/branch-naming-convention.sh +0 -0
  97. package/examples/broad-find-guard.sh +12 -0
  98. package/examples/broad-prefix-session-trap-warner.sh +106 -0
  99. package/examples/bulk-file-delete-guard.sh +45 -0
  100. package/examples/bypass-mode-effective-verifier.sh +203 -0
  101. package/examples/cache-creation-drift-detector.sh +120 -0
  102. package/examples/cache-residue-detector.sh +195 -0
  103. package/examples/cache-tier-logger.sh +70 -0
  104. package/examples/cache-ttl-eviction-detector.sh +149 -0
  105. package/examples/cargo-publish-guard.sh +14 -1
  106. package/examples/case-insensitive-path-guard.sh +21 -2
  107. package/examples/case-sensitive-guard.sh +23 -2
  108. package/examples/cch-cache-guard.sh +0 -0
  109. package/examples/cch-sentinel-precommit-guard.sh +47 -0
  110. package/examples/check-abort-controller.sh +1 -1
  111. package/examples/check-accessibility.sh +0 -0
  112. package/examples/check-aria-labels.sh +0 -0
  113. package/examples/check-before-act-enforcer.sh +12 -0
  114. package/examples/check-charset-meta.sh +0 -0
  115. package/examples/check-cookie-flags.sh +0 -0
  116. package/examples/check-cors-config.sh +0 -0
  117. package/examples/check-csp-headers.sh +0 -0
  118. package/examples/check-csrf-protection.sh +0 -0
  119. package/examples/check-debounce.sh +1 -1
  120. package/examples/check-dependency-age.sh +0 -0
  121. package/examples/check-dependency-license.sh +0 -0
  122. package/examples/check-dockerfile-best-practice.sh +0 -0
  123. package/examples/check-error-boundaries.sh +0 -0
  124. package/examples/check-error-class.sh +1 -1
  125. package/examples/check-error-handling.sh +0 -0
  126. package/examples/check-error-logging.sh +1 -1
  127. package/examples/check-error-message.sh +0 -0
  128. package/examples/check-error-stack.sh +0 -0
  129. package/examples/check-favicon.sh +0 -0
  130. package/examples/check-git-hooks-compat.sh +0 -0
  131. package/examples/check-gitattributes.sh +0 -0
  132. package/examples/check-https-redirect.sh +0 -0
  133. package/examples/check-input-validation.sh +0 -0
  134. package/examples/check-lang-attribute.sh +0 -0
  135. package/examples/check-npm-scripts-exist.sh +0 -0
  136. package/examples/check-package-size.sh +0 -0
  137. package/examples/check-port-availability.sh +0 -0
  138. package/examples/check-promise-all.sh +1 -1
  139. package/examples/check-rate-limiting.sh +0 -0
  140. package/examples/check-return-types.sh +0 -0
  141. package/examples/check-semantic-versioning.sh +0 -0
  142. package/examples/check-suspense-fallback.sh +1 -1
  143. package/examples/check-test-exists.sh +0 -0
  144. package/examples/check-test-naming.sh +0 -0
  145. package/examples/check-timeout-cleanup.sh +1 -1
  146. package/examples/check-tls-version.sh +0 -0
  147. package/examples/check-unsubscribe.sh +1 -1
  148. package/examples/check-viewport-meta.sh +0 -0
  149. package/examples/check-worker-terminate.sh +1 -1
  150. package/examples/checkpoint-tamper-guard.sh +12 -0
  151. package/examples/chmod-guard.sh +12 -0
  152. package/examples/chown-guard.sh +24 -0
  153. package/examples/ci-workflow-guard.sh +6 -1
  154. package/examples/claim-verify-detector.sh +109 -0
  155. package/examples/claim-vs-caveat-checker.sh +77 -0
  156. package/examples/classifier-fallback-allow.sh +114 -40
  157. package/examples/claude-cache-gc.sh +1 -0
  158. package/examples/claude-code-version-pin-advisor.sh +183 -0
  159. package/examples/claude-md-reinjector.sh +129 -0
  160. package/examples/claude-md-size-monitor.sh +66 -0
  161. package/examples/claude-update-budget-guard.sh +123 -0
  162. package/examples/claude-update-smart.sh +113 -0
  163. package/examples/claudeignore-enforce-guard.sh +12 -0
  164. package/examples/claudemd-enforcer.sh +0 -0
  165. package/examples/claudemd-tool-prohibition.sh +128 -0
  166. package/examples/clear-command-confirm-guard.sh +32 -15
  167. package/examples/cli-config-pinning-detector.sh +162 -0
  168. package/examples/cliff-countdown-advisor.sh +96 -0
  169. package/examples/clipboard-secret-guard.sh +12 -0
  170. package/examples/closure-word-verify-gate.sh +150 -0
  171. package/examples/cloud-cli-guard.sh +39 -2
  172. package/examples/commit-all-scope-guard.sh +44 -0
  173. package/examples/commit-message-check.sh +1 -1
  174. package/examples/commit-message-quality.sh +6 -1
  175. package/examples/commitment-carry-forward-arrest.sh +361 -0
  176. package/examples/compact-alert-notification.sh +0 -0
  177. package/examples/compact-circuit-breaker.sh +72 -0
  178. package/examples/compact-dispatch-watchdog.sh +149 -0
  179. package/examples/completion-claim-without-verification-detector.sh +207 -0
  180. package/examples/composer-guard.sh +12 -0
  181. package/examples/compound-bash-permission-resolver.sh +156 -0
  182. package/examples/compound-command-allow.sh +1 -1
  183. package/examples/compound-command-deny-enforcer.sh +183 -0
  184. package/examples/compound-inject-guard.sh +12 -0
  185. package/examples/concurrent-edit-lock.sh +12 -0
  186. package/examples/conflict-marker-guard.sh +12 -0
  187. package/examples/consecutive-error-breaker.sh +0 -0
  188. package/examples/console-log-count.sh +1 -0
  189. package/examples/context-compact-advisor.sh +29 -2
  190. package/examples/context-length-budget.sh +69 -0
  191. package/examples/context-threshold-alert.sh +12 -0
  192. package/examples/context-usage-drift-alert.sh +41 -13
  193. package/examples/conversation-history-guard.sh +12 -0
  194. package/examples/core-file-protect-guard.sh +12 -0
  195. package/examples/cors-star-warn.sh +0 -0
  196. package/examples/cost-incident-self-audit.sh +162 -0
  197. package/examples/cowork-claude-md-load-checker.sh +100 -0
  198. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  199. package/examples/cowork-hook-absence-warner.sh +167 -0
  200. package/examples/cowork-model-picker-advisor.sh +115 -0
  201. package/examples/credential-exfil-guard.sh +65 -4
  202. package/examples/credential-file-cat-guard.sh +17 -1
  203. package/examples/cron-create-receipt.sh +112 -0
  204. package/examples/cron-modification-guard.sh +12 -0
  205. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  206. package/examples/cwd-project-boundary-guard.sh +0 -0
  207. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  208. package/examples/daily-cost-guard.sh +164 -0
  209. package/examples/daily-usage-tracker.sh +0 -0
  210. package/examples/dangerous-pip-flag-guard.sh +12 -0
  211. package/examples/db-connect-guard.sh +13 -1
  212. package/examples/denied-action-retry-guard.sh +12 -0
  213. package/examples/deny-bypass-detector.sh +12 -0
  214. package/examples/deny-rule-integrity-verifier.sh +181 -0
  215. package/examples/dependency-install-guard.sh +12 -0
  216. package/examples/deploy-guard.sh +14 -2
  217. package/examples/deploy-path-verify-guard.sh +12 -0
  218. package/examples/deployment-readback-gate.sh +135 -0
  219. package/examples/deployment-readback-gh-adapter.sh +247 -0
  220. package/examples/deployment-verify-guard.sh +25 -2
  221. package/examples/destructive-db-script-write-guard.sh +166 -0
  222. package/examples/destructive-migration-write-guard.sh +163 -0
  223. package/examples/diff-size-guard.sh +12 -0
  224. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  225. package/examples/disk-partition-guard.sh +12 -0
  226. package/examples/dispatch-allowlist-preflight.sh +301 -0
  227. package/examples/dispatch-liveness-watchdog.sh +216 -0
  228. package/examples/dispatch-receipt.sh +174 -0
  229. package/examples/django-migrate-guard.sh +12 -0
  230. package/examples/dns-config-guard.sh +12 -0
  231. package/examples/docker-dangerous-guard.sh +12 -0
  232. package/examples/docker-volume-guard.sh +0 -0
  233. package/examples/dockerfile-latest-guard.sh +1 -0
  234. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  235. package/examples/dotenv-commit-guard.sh +12 -0
  236. package/examples/dotenv-read-guard.sh +12 -0
  237. package/examples/dotfile-protection-guard.sh +12 -0
  238. package/examples/dotnet-build-on-edit.sh +1 -1
  239. package/examples/drizzle-migrate-guard.sh +27 -2
  240. package/examples/echo-probe-spam-detector.sh +176 -0
  241. package/examples/edit-counter-test-gate.sh +12 -0
  242. package/examples/edit-error-counter.sh +1 -1
  243. package/examples/edit-guard.sh +12 -0
  244. package/examples/edit-old-string-validator.sh +12 -0
  245. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  246. package/examples/edit-retry-loop-guard.sh +0 -0
  247. package/examples/edit-verify.sh +0 -0
  248. package/examples/env-inline-secret-guard.sh +14 -2
  249. package/examples/env-naming-convention.sh +0 -0
  250. package/examples/env-prod-guard.sh +0 -0
  251. package/examples/env-required-check.sh +0 -0
  252. package/examples/env-source-guard.sh +12 -0
  253. package/examples/env-var-check.sh +24 -1
  254. package/examples/ephemeral-container-detector.sh +147 -0
  255. package/examples/error-memory-guard.sh +12 -0
  256. package/examples/evidence-claim-gate.sh +187 -0
  257. package/examples/exploration-budget-guard.sh +89 -0
  258. package/examples/expo-eject-guard.sh +13 -0
  259. package/examples/extended-thinking-loop-guard.sh +139 -0
  260. package/examples/extended-thinking-resume-warning.sh +119 -0
  261. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  262. package/examples/fabricated-command-detector.sh +145 -0
  263. package/examples/false-disk-full-guard.sh +63 -0
  264. package/examples/feature-deprecation-detector.sh +109 -0
  265. package/examples/file-change-tracker.sh +1 -1
  266. package/examples/file-change-undo-tracker.sh +0 -0
  267. package/examples/file-edit-backup.sh +63 -14
  268. package/examples/file-reference-check.sh +0 -0
  269. package/examples/file-size-limit.sh +12 -0
  270. package/examples/financial-operation-guard.sh +12 -0
  271. package/examples/firewall-guard.sh +12 -0
  272. package/examples/fish-shell-wrapper.sh +125 -7
  273. package/examples/five-hundred-milestone.sh +1 -0
  274. package/examples/flask-static-route-guard.sh +89 -0
  275. package/examples/forbidden-response-phrase-detector.sh +161 -0
  276. package/examples/gem-push-guard.sh +13 -0
  277. package/examples/gh-cli-destructive-guard.sh +13 -1
  278. package/examples/git-checkout-safety-guard.sh +12 -0
  279. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  280. package/examples/git-config-guard.sh +12 -0
  281. package/examples/git-crypt-worktree-guard.sh +12 -0
  282. package/examples/git-filter-repo-guard.sh +56 -0
  283. package/examples/git-history-rewrite-guard.sh +12 -0
  284. package/examples/git-hook-bypass-guard.sh +0 -0
  285. package/examples/git-maintenance-guard.sh +83 -0
  286. package/examples/git-merge-conflict-prevent.sh +0 -0
  287. package/examples/git-message-length-check.sh +0 -0
  288. package/examples/git-message-length.sh +0 -0
  289. package/examples/git-operations-require-approval.sh +68 -14
  290. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  291. package/examples/git-push-blast-radius-guard.sh +218 -0
  292. package/examples/git-remote-guard.sh +24 -3
  293. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  294. package/examples/git-stash-before-checkout.sh +12 -0
  295. package/examples/git-stash-before-danger.sh +0 -0
  296. package/examples/git-submodule-guard.sh +69 -2
  297. package/examples/git-tag-guard.sh +12 -0
  298. package/examples/github-actions-secret-guard.sh +0 -0
  299. package/examples/gitignore-check.sh +0 -0
  300. package/examples/gitops-drift-guard.sh +12 -0
  301. package/examples/go-mod-tidy-warn.sh +1 -0
  302. package/examples/go-vet-after-edit.sh +12 -0
  303. package/examples/goal-iteration-limit-warner.sh +152 -0
  304. package/examples/grep-nul-false-negative-guard.sh +30 -0
  305. package/examples/growthbook-flag-monitor.sh +257 -0
  306. package/examples/hallucination-url-check.sh +1 -1
  307. package/examples/halt-signal-detector.sh +135 -0
  308. package/examples/handoff-on-clear.sh +65 -0
  309. package/examples/hardcoded-ip-guard.sh +1 -0
  310. package/examples/headless-empty-result-guard.sh +0 -0
  311. package/examples/headless-stop-guard.sh +0 -0
  312. package/examples/helm-install-guard.sh +2 -1
  313. package/examples/home-critical-bash-guard.sh +17 -1
  314. package/examples/hook-debug-wrapper.sh +6 -2
  315. package/examples/hook-permission-fixer.sh +0 -0
  316. package/examples/hook-self-disable-detector.sh +99 -0
  317. package/examples/hook-stdout-sanitizer.sh +6 -2
  318. package/examples/hook-tamper-guard.sh +12 -0
  319. package/examples/idle-session-cost-alert.sh +0 -0
  320. package/examples/image-dimension-guard.sh +109 -0
  321. package/examples/image-file-validator.sh +0 -0
  322. package/examples/iteration-quality-degradation-detector.sh +170 -0
  323. package/examples/java-compile-on-edit.sh +1 -1
  324. package/examples/json-syntax-check.sh +0 -0
  325. package/examples/k8s-production-guard.sh +13 -1
  326. package/examples/kill-process-guard.sh +12 -0
  327. package/examples/kubernetes-guard.sh +13 -1
  328. package/examples/laravel-artisan-guard.sh +13 -0
  329. package/examples/large-file-guard.sh +1 -1
  330. package/examples/log-level-guard.sh +0 -0
  331. package/examples/log-truncation-guard.sh +12 -0
  332. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  333. package/examples/loop-detector.sh +12 -0
  334. package/examples/magic-number-warn.sh +1 -0
  335. package/examples/main-branch-warn.sh +12 -0
  336. package/examples/markdown-link-check.sh +0 -0
  337. package/examples/max-concurrent-agents.sh +12 -0
  338. package/examples/max-edit-size-guard.sh +13 -0
  339. package/examples/max-file-count-guard.sh +0 -0
  340. package/examples/max-file-delete-count.sh +0 -0
  341. package/examples/max-function-length.sh +1 -0
  342. package/examples/max-import-count.sh +0 -0
  343. package/examples/max-subagent-count.sh +0 -0
  344. package/examples/mcp-config-freeze.sh +12 -0
  345. package/examples/mcp-config-poisoning-audit.sh +150 -0
  346. package/examples/mcp-data-boundary.sh +1 -1
  347. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  348. package/examples/mcp-orphan-leak-warner.sh +49 -0
  349. package/examples/mcp-permissions-ask-warner.sh +151 -0
  350. package/examples/mcp-routine-approval-detector.sh +154 -0
  351. package/examples/mcp-server-allowlist.sh +12 -0
  352. package/examples/mcp-server-guard.sh +12 -0
  353. package/examples/mcp-startup-bloat-detector.sh +87 -0
  354. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  355. package/examples/mcp-tool-audit-log.sh +0 -0
  356. package/examples/mcp-tool-guard.sh +101 -1
  357. package/examples/mcp-warmup-wait.sh +0 -0
  358. package/examples/memory-chain-audit.sh +56 -0
  359. package/examples/memory-orphan-detector.sh +188 -0
  360. package/examples/memory-write-guard.sh +99 -17
  361. package/examples/migration-verify-guard.sh +12 -0
  362. package/examples/model-swap-suggester.sh +177 -0
  363. package/examples/model-version-alert.sh +5 -1
  364. package/examples/model-version-lock.sh +63 -0
  365. package/examples/move-delete-sequence-guard.sh +33 -2
  366. package/examples/multi-file-plan-routing-gate.sh +192 -0
  367. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  368. package/examples/multi-window-auth-drift-detector.sh +183 -0
  369. package/examples/multiline-command-approver.sh +161 -23
  370. package/examples/nested-background-agent-guard.sh +109 -0
  371. package/examples/nested-spawn-inflight-guard.sh +178 -0
  372. package/examples/network-exfil-guard.sh +12 -0
  373. package/examples/network-guard.sh +12 -0
  374. package/examples/network-interface-guard.sh +12 -0
  375. package/examples/nextjs-env-guard.sh +1 -1
  376. package/examples/no-absolute-import.sh +0 -0
  377. package/examples/no-alert-confirm-prompt.sh +0 -0
  378. package/examples/no-anonymous-default-export.sh +0 -0
  379. package/examples/no-any-type.sh +0 -0
  380. package/examples/no-any-typescript.sh +1 -0
  381. package/examples/no-ask-human.sh +12 -0
  382. package/examples/no-assignment-in-condition.sh +0 -0
  383. package/examples/no-base64-exfil.sh +12 -0
  384. package/examples/no-callback-hell.sh +0 -0
  385. package/examples/no-circular-dependency.sh +0 -0
  386. package/examples/no-cleartext-storage.sh +0 -0
  387. package/examples/no-commented-code.sh +0 -0
  388. package/examples/no-commit-fixup.sh +0 -0
  389. package/examples/no-console-assert.sh +0 -0
  390. package/examples/no-console-error-swallow.sh +0 -0
  391. package/examples/no-console-in-prod.sh +0 -0
  392. package/examples/no-console-log-commit.sh +12 -0
  393. package/examples/no-console-log.sh +0 -0
  394. package/examples/no-console-time.sh +0 -0
  395. package/examples/no-cors-wildcard.sh +4 -1
  396. package/examples/no-curl-upload.sh +0 -0
  397. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  398. package/examples/no-dangling-await.sh +1 -0
  399. package/examples/no-debug-commit.sh +12 -0
  400. package/examples/no-debug-in-commit.sh +0 -0
  401. package/examples/no-deep-nesting.sh +0 -0
  402. package/examples/no-deep-relative-import.sh +1 -0
  403. package/examples/no-default-credentials.sh +0 -0
  404. package/examples/no-deploy-friday.sh +13 -1
  405. package/examples/no-disabled-test.sh +0 -0
  406. package/examples/no-document-write.sh +0 -0
  407. package/examples/no-empty-function.sh +0 -0
  408. package/examples/no-eval-in-template.sh +0 -0
  409. package/examples/no-eval-template.sh +3 -1
  410. package/examples/no-eval.sh +0 -0
  411. package/examples/no-exec-user-input.sh +0 -0
  412. package/examples/no-fixme-ship.sh +12 -0
  413. package/examples/no-floating-promises.sh +0 -0
  414. package/examples/no-force-flag.sh +22 -5
  415. package/examples/no-force-install.sh +0 -0
  416. package/examples/no-git-amend.sh +12 -0
  417. package/examples/no-git-rebase-public.sh +0 -0
  418. package/examples/no-global-install.sh +12 -0
  419. package/examples/no-global-state.sh +0 -0
  420. package/examples/no-hardcoded-port.sh +1 -0
  421. package/examples/no-hardcoded-url.sh +0 -0
  422. package/examples/no-helmet-missing.sh +0 -0
  423. package/examples/no-http-url.sh +1 -0
  424. package/examples/no-http-without-https.sh +0 -0
  425. package/examples/no-inline-style.sh +0 -0
  426. package/examples/no-inline-styles.sh +1 -0
  427. package/examples/no-innerhtml.sh +0 -0
  428. package/examples/no-install-global.sh +12 -0
  429. package/examples/no-jwt-in-url.sh +0 -0
  430. package/examples/no-large-commit.sh +0 -0
  431. package/examples/no-localhost-expose.sh +0 -0
  432. package/examples/no-magic-number.sh +0 -0
  433. package/examples/no-md5-sha1.sh +0 -0
  434. package/examples/no-mixed-line-endings.sh +8 -1
  435. package/examples/no-mutation-in-reducer.sh +0 -0
  436. package/examples/no-nested-ternary.sh +0 -0
  437. package/examples/no-network-exfil.sh +0 -0
  438. package/examples/no-open-redirect.sh +0 -0
  439. package/examples/no-output-truncation.sh +12 -0
  440. package/examples/no-package-downgrade.sh +0 -0
  441. package/examples/no-package-lock-edit.sh +12 -0
  442. package/examples/no-path-join-user-input.sh +0 -0
  443. package/examples/no-port-bind.sh +0 -0
  444. package/examples/no-process-exit.sh +0 -0
  445. package/examples/no-prototype-pollution.sh +0 -0
  446. package/examples/no-push-without-ci.sh +0 -0
  447. package/examples/no-push-without-tests.sh +12 -0
  448. package/examples/no-raw-password-in-url.sh +0 -0
  449. package/examples/no-root-user-docker.sh +1 -0
  450. package/examples/no-root-write.sh +12 -0
  451. package/examples/no-secrets-in-args.sh +4 -1
  452. package/examples/no-secrets-in-logs.sh +0 -0
  453. package/examples/no-sensitive-log.sh +0 -0
  454. package/examples/no-sleep-in-hooks.sh +0 -0
  455. package/examples/no-star-import-python.sh +1 -0
  456. package/examples/no-string-concat-sql.sh +0 -0
  457. package/examples/no-sudo-guard.sh +12 -0
  458. package/examples/no-sync-fs.sh +0 -0
  459. package/examples/no-todo-in-merge.sh +0 -0
  460. package/examples/no-todo-in-production.sh +1 -0
  461. package/examples/no-todo-without-issue.sh +0 -0
  462. package/examples/no-unused-import.sh +0 -0
  463. package/examples/no-var-keyword.sh +0 -0
  464. package/examples/no-verify-blocker.sh +12 -0
  465. package/examples/no-wget-piped-bash.sh +12 -0
  466. package/examples/no-wildcard-cors.sh +0 -0
  467. package/examples/no-wildcard-delete.sh +0 -0
  468. package/examples/no-wildcard-import.sh +0 -0
  469. package/examples/no-with-statement.sh +0 -0
  470. package/examples/no-write-outside-src.sh +0 -0
  471. package/examples/no-xml-external-entity.sh +0 -0
  472. package/examples/non-english-quality-warner.sh +156 -0
  473. package/examples/notify-waiting.sh +1 -1
  474. package/examples/npm-audit-warn.sh +0 -0
  475. package/examples/npm-global-install-guard.sh +12 -0
  476. package/examples/npm-publish-guard.sh +12 -0
  477. package/examples/npm-script-injection.sh +0 -0
  478. package/examples/npm-supply-chain-guard.sh +0 -0
  479. package/examples/nuxt-config-guard.sh +1 -0
  480. package/examples/oauth-refresh-monitor.sh +210 -0
  481. package/examples/opus-degradation-tracker.sh +187 -0
  482. package/examples/opus48-routine-task-warning.sh +196 -0
  483. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  484. package/examples/output-credential-scan.sh +1 -1
  485. package/examples/output-secret-mask.sh +31 -9
  486. package/examples/output-token-spike-detector.sh +145 -0
  487. package/examples/package-json-guard.sh +12 -0
  488. package/examples/package-lock-frozen.sh +12 -0
  489. package/examples/parallel-batch-size-limiter.sh +121 -0
  490. package/examples/parallel-cascade-detector.sh +116 -0
  491. package/examples/partial-view-claim-arrest.sh +174 -0
  492. package/examples/path-deny-bash-guard.sh +12 -0
  493. package/examples/path-traversal-guard.sh +12 -0
  494. package/examples/per-prompt-token-cap.sh +124 -0
  495. package/examples/permission-audit-log.sh +1 -1
  496. package/examples/permission-denial-enforcer.sh +12 -0
  497. package/examples/permission-entry-validator.sh +0 -0
  498. package/examples/persisted-1m-model-advisor.sh +88 -0
  499. package/examples/php-lint-on-edit.sh +1 -1
  500. package/examples/pii-upload-guard.sh +12 -0
  501. package/examples/pip-publish-guard.sh +13 -0
  502. package/examples/pip-requirements-guard.sh +12 -0
  503. package/examples/pip-venv-required.sh +12 -0
  504. package/examples/plan-mode-edit-guard.sh +12 -0
  505. package/examples/plan-mode-enforcer.sh +12 -0
  506. package/examples/plan-mode-strict-guard.sh +12 -0
  507. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  508. package/examples/plugin-process-cleanup.sh +0 -0
  509. package/examples/polyglot-rm-guard.sh +12 -0
  510. package/examples/post-compact-safety.sh +12 -0
  511. package/examples/post-edit-disk-verify.sh +152 -0
  512. package/examples/powershell-remove-item-guard.sh +85 -0
  513. package/examples/pr-description-check.sh +0 -0
  514. package/examples/pr-duplicate-guard.sh +13 -0
  515. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  516. package/examples/pre-compact-knowledge-save.sh +0 -0
  517. package/examples/pre-compact-transcript-backup.sh +0 -0
  518. package/examples/pre-execution-claim-detector.sh +179 -0
  519. package/examples/prefer-builtin-tools.sh +10 -1
  520. package/examples/prefer-const.sh +0 -0
  521. package/examples/prefer-dedicated-tools.sh +12 -0
  522. package/examples/prefer-optional-chaining.sh +0 -0
  523. package/examples/prisma-migrate-guard.sh +24 -7
  524. package/examples/production-port-kill-guard.sh +12 -0
  525. package/examples/prompt-injection-guard.sh +2 -1
  526. package/examples/prompt-usage-logger.sh +0 -0
  527. package/examples/protect-claudemd.sh +12 -0
  528. package/examples/protect-dotfiles.sh +12 -0
  529. package/examples/proxy-capture-suggester.sh +159 -0
  530. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  531. package/examples/public-repo-push-guard.sh +12 -0
  532. package/examples/push-requires-test-pass-record.sh +0 -0
  533. package/examples/push-requires-test-pass.sh +12 -0
  534. package/examples/quota-anomaly-detector.sh +173 -0
  535. package/examples/quota-reset-audit.sh +58 -0
  536. package/examples/quoted-flag-approver.sh +99 -10
  537. package/examples/rails-migration-guard.sh +12 -0
  538. package/examples/rate-limit-guard.sh +0 -0
  539. package/examples/read-all-files-enforcer.sh +0 -0
  540. package/examples/read-budget-guard.sh +12 -0
  541. package/examples/read-loop-detector.sh +59 -0
  542. package/examples/read-once-guard.sh +96 -0
  543. package/examples/read-only-mode.sh +12 -0
  544. package/examples/readme-exists-check.sh +0 -0
  545. package/examples/record-read-coverage.sh +73 -0
  546. package/examples/redirect-fragment-warner.sh +149 -0
  547. package/examples/redis-flushall-guard.sh +13 -0
  548. package/examples/redundant-read-blocker.sh +132 -0
  549. package/examples/refusal-arrest-gate.sh +248 -0
  550. package/examples/registry-publish-guard.sh +13 -1
  551. package/examples/remote-control-billing-classifier.sh +135 -0
  552. package/examples/replace-all-guard.sh +12 -0
  553. package/examples/repo-visibility-guard.sh +12 -0
  554. package/examples/reroute-after-block-guard.sh +150 -0
  555. package/examples/response-budget-guard.sh +0 -0
  556. package/examples/resume-drift-watcher.sh +57 -0
  557. package/examples/rg-replace-flag-detector.sh +125 -0
  558. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  559. package/examples/ripgrep-permission-fix.sh +0 -0
  560. package/examples/rm-safety-net.sh +151 -8
  561. package/examples/role-tool-guard.sh +12 -0
  562. package/examples/route-handler-emptiness-gate.sh +324 -0
  563. package/examples/ruby-lint-on-edit.sh +1 -1
  564. package/examples/runtime-binary-change-detector.sh +102 -0
  565. package/examples/same-command-repeat-detector.sh +196 -0
  566. package/examples/same-correction-arrest.sh +169 -0
  567. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  568. package/examples/sandbox-relative-path-audit.sh +83 -25
  569. package/examples/sandbox-write-verify.sh +12 -0
  570. package/examples/schema-migration-guard.sh +0 -0
  571. package/examples/scope-expansion-receipt.sh +178 -0
  572. package/examples/scope-guard.sh +88 -9
  573. package/examples/secret-file-read-guard.sh +12 -0
  574. package/examples/secret-file-write-guard.sh +150 -0
  575. package/examples/self-modify-bypass-guard.sh +0 -0
  576. package/examples/sensitive-file-read-guard.sh +23 -3
  577. package/examples/sensitive-log-guard.sh +1 -0
  578. package/examples/server-side-prompt-injection-detector.sh +69 -0
  579. package/examples/session-agent-cost-limiter.sh +12 -0
  580. package/examples/session-backup-on-start.sh +1 -1
  581. package/examples/session-cost-alert.sh +12 -0
  582. package/examples/session-drift-guard.sh +12 -0
  583. package/examples/session-duration-guard.sh +25 -2
  584. package/examples/session-end-logger.sh +0 -0
  585. package/examples/session-health-monitor.sh +0 -0
  586. package/examples/session-index-repair.sh +1 -1
  587. package/examples/session-memory-watchdog.sh +1 -0
  588. package/examples/session-permission-reset-guard.sh +12 -0
  589. package/examples/session-persistence-verifier.sh +93 -0
  590. package/examples/session-plugin-pin-watch.sh +68 -0
  591. package/examples/session-rate-monitor.sh +176 -0
  592. package/examples/session-resume-env-fix.sh +0 -0
  593. package/examples/session-start-quota-status.sh +193 -0
  594. package/examples/session-start-safety-check.sh +55 -3
  595. package/examples/session-state-saver.sh +0 -0
  596. package/examples/session-summary-stop.sh +1 -1
  597. package/examples/session-summary.sh +0 -0
  598. package/examples/session-token-counter.sh +1 -1
  599. package/examples/settings-hooks-key-restorer.sh +99 -0
  600. package/examples/settings-json-health-check.sh +57 -0
  601. package/examples/settings-json-model-guard.sh +0 -0
  602. package/examples/settings-regression-tester.sh +188 -0
  603. package/examples/shell-config-truncation-guard.sh +12 -0
  604. package/examples/shell-wrapper-guard.sh +12 -0
  605. package/examples/skill-cumulative-size-detector.sh +104 -0
  606. package/examples/skill-description-drop-detector.sh +148 -0
  607. package/examples/skill-gate.sh +0 -0
  608. package/examples/skill-truncation-detector.sh +154 -0
  609. package/examples/skills-context-recorder.sh +167 -0
  610. package/examples/skills-load-verifier.sh +96 -0
  611. package/examples/skills-settings-validator.sh +139 -0
  612. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  613. package/examples/spec-file-scope-guard.sh +12 -0
  614. package/examples/spring-profile-guard.sh +1 -0
  615. package/examples/spurious-malformed-notice-detector.sh +247 -0
  616. package/examples/sql-bulk-delete-warn.sh +88 -0
  617. package/examples/sql-injection-detect.sh +0 -0
  618. package/examples/ssh-key-protect.sh +12 -0
  619. package/examples/staged-secret-scan.sh +22 -1
  620. package/examples/stale-temp-settings-detector.sh +86 -0
  621. package/examples/standing-rule-session-surfacer.sh +137 -0
  622. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  623. package/examples/stop-transcript-write-health.sh +64 -0
  624. package/examples/strict-allowlist.sh +57 -15
  625. package/examples/strip-coauthored-by.sh +50 -10
  626. package/examples/subagent-blast-radius-guard.sh +184 -0
  627. package/examples/subagent-boundary-precheck.sh +126 -0
  628. package/examples/subagent-budget-guard.sh +12 -0
  629. package/examples/subagent-claudemd-inject.sh +0 -0
  630. package/examples/subagent-closure-verify-gate.sh +164 -0
  631. package/examples/subagent-destructive-git-guard.sh +120 -0
  632. package/examples/subagent-error-detector.sh +0 -0
  633. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  634. package/examples/subagent-identity-leak-guard.sh +102 -0
  635. package/examples/subagent-identity-reassertion.sh +51 -0
  636. package/examples/subagent-inheritance-tester.sh +179 -0
  637. package/examples/subagent-permission-mode-guard.sh +110 -0
  638. package/examples/subagent-scope-guard.sh +12 -0
  639. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  640. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  641. package/examples/subagent-tool-call-limiter.sh +87 -15
  642. package/examples/subcommand-chain-guard.sh +12 -0
  643. package/examples/subscription-api-billing-warner.sh +160 -0
  644. package/examples/subscription-bypass-detector.sh +152 -0
  645. package/examples/svelte-lint-on-edit.sh +1 -0
  646. package/examples/swift-build-on-edit.sh +1 -1
  647. package/examples/symlink-guard.sh +27 -2
  648. package/examples/symlink-protect.sh +1 -0
  649. package/examples/system-dir-protection-guard.sh +73 -8
  650. package/examples/system-message-workaround.sh +38 -13
  651. package/examples/system-package-guard.sh +12 -0
  652. package/examples/systemd-service-guard.sh +12 -0
  653. package/examples/task-integrity-guard.sh +12 -0
  654. package/examples/temp-file-cleanup.sh +1 -1
  655. package/examples/temporal-suggestion-detector.sh +135 -0
  656. package/examples/terraform-guard.sh +27 -6
  657. package/examples/test-after-edit.sh +1 -1
  658. package/examples/test-before-push.sh +12 -0
  659. package/examples/test-coverage-reminder.sh +24 -1
  660. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  661. package/examples/thinking-stall-detector.sh +61 -0
  662. package/examples/timezone-guard.sh +0 -0
  663. package/examples/tmp-output-size-guard.sh +0 -0
  664. package/examples/todo-check.sh +1 -1
  665. package/examples/token-budget-guard.sh +12 -0
  666. package/examples/token-budget-per-task.sh +12 -0
  667. package/examples/token-usage-tracker.sh +7 -1
  668. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  669. package/examples/tokenizer-ratio-alert.sh +104 -0
  670. package/examples/tool-call-rate-limiter.sh +0 -0
  671. package/examples/tool-result-correlation-checker.sh +167 -0
  672. package/examples/tool-result-size-guard.sh +132 -0
  673. package/examples/tool-retry-budget-guard.sh +12 -0
  674. package/examples/transcript-contamination-detector.sh +138 -0
  675. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  676. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  677. package/examples/unbounded-output-guard.sh +94 -0
  678. package/examples/uncommitted-changes-stop.sh +1 -0
  679. package/examples/uncommitted-discard-guard.sh +23 -5
  680. package/examples/uncommitted-work-guard.sh +12 -0
  681. package/examples/usage-warn.sh +0 -0
  682. package/examples/user-account-guard.sh +12 -0
  683. package/examples/userprompt-submit-receipt.sh +123 -0
  684. package/examples/variable-expansion-guard.sh +12 -0
  685. package/examples/verify-after-publish-reminder.sh +93 -0
  686. package/examples/verify-before-commit.sh +12 -0
  687. package/examples/version-bump-detector.sh +156 -0
  688. package/examples/version-regression-warner.sh +144 -0
  689. package/examples/vue-lint-on-edit.sh +1 -0
  690. package/examples/warn-cron-cost-trap.sh +173 -0
  691. package/examples/webfetch-runaway-guard.sh +89 -0
  692. package/examples/wellness-break-reminder.sh +118 -0
  693. package/examples/windows-destructive-command-guard.sh +177 -0
  694. package/examples/windows-path-guard.sh +12 -0
  695. package/examples/windows-python-stub-detector.sh +63 -0
  696. package/examples/work-hours-guard.sh +12 -0
  697. package/examples/working-directory-fence.sh +12 -0
  698. package/examples/workspace-lease-guard.sh +205 -0
  699. package/examples/worktree-create-log.sh +1 -0
  700. package/examples/worktree-delete-guard.sh +12 -0
  701. package/examples/worktree-edit-boundary-guard.sh +127 -0
  702. package/examples/worktree-escape-write-guard.sh +114 -0
  703. package/examples/worktree-hook-linker.sh +0 -0
  704. package/examples/worktree-hooks-path-fix.sh +111 -0
  705. package/examples/worktree-parent-write-guard.sh +43 -0
  706. package/examples/worktree-project-unify.sh +2 -1
  707. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  708. package/examples/worktree-unmerged-guard.sh +7 -1
  709. package/examples/write-byte-integrity-verifier.sh +190 -0
  710. package/examples/write-empty-content-guard.sh +67 -0
  711. package/examples/write-nul-corruption-detector.sh +61 -0
  712. package/examples/write-overwrite-confirm.sh +160 -14
  713. package/examples/write-secret-guard.sh +27 -5
  714. package/examples/write-shrink-guard.sh +12 -0
  715. package/examples/write-test-ratio.sh +0 -0
  716. package/examples/wsl-host-disk-space-guard.sh +97 -0
  717. package/examples/xml-format-leak-detector.sh +266 -0
  718. package/examples/yaml-syntax-check.sh +12 -0
  719. package/hooks/hooks.json +6 -6
  720. package/index.mjs +1699 -183
  721. package/mission.md +2 -0
  722. package/package.json +4 -4
  723. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  724. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  725. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  726. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  727. package/scripts/agents-md-sync-setup.sh +156 -0
  728. package/scripts/autonomy-blocked-summary.sh +148 -0
  729. package/scripts/build-search-index.py +43 -0
  730. package/scripts/build-sitemap.py +119 -0
  731. package/scripts/cc-doctor.sh +192 -0
  732. package/scripts/check-hook-event-names.py +127 -0
  733. package/scripts/check-misfire-instrument.sh +64 -0
  734. package/scripts/claim-verify-audit.sh +467 -0
  735. package/scripts/cowork-claudemd-helper.sh +136 -0
  736. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  737. package/scripts/measure-heredoc-shapes.sh +67 -0
  738. package/scripts/measure-literal-match-misfire.sh +110 -0
  739. package/scripts/probe-scope-guard-branches.sh +48 -0
  740. package/scripts/probe-skip-line-both-ways.sh +65 -0
  741. package/scripts/receipts-aggregate.py +199 -0
  742. package/scripts/session-forensic-audit.py +360 -0
  743. package/scripts.json +9 -9
  744. package/scripts.json.bak-2026-07-27-find +13 -0
  745. package/skills/safety-setup/SKILL.md +5 -5
  746. package/tests/approve-side-remaining-two.test.sh +129 -0
  747. package/tests/approver-list-granularity.test.sh +145 -0
  748. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  749. package/tests/audit-ci-gate.test.sh +87 -0
  750. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  751. package/tests/audit-fail-open-parse.test.sh +100 -0
  752. package/tests/auto-approve-compound-tail.test.sh +194 -0
  753. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  754. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  755. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  756. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  757. package/tests/blindspots-cross-layer.test.sh +177 -0
  758. package/tests/block-database-wipe.test.sh +64 -0
  759. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  760. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  761. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  762. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  763. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  764. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  765. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  766. package/tests/destructive-guard-every-operand.test.sh +100 -0
  767. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  768. package/tests/destructive-guard-flag-order.test.sh +106 -0
  769. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  770. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  771. package/tests/destructive-guard-separators.test.sh +105 -0
  772. package/tests/destructive-guard-variable-target.test.sh +98 -0
  773. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  774. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  775. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  776. package/tests/example-guards-wrapped-command.test.sh +169 -0
  777. package/tests/file-edit-backup.test.sh +93 -0
  778. package/tests/git-filter-repo-guard.test.sh +60 -0
  779. package/tests/git-global-options-bypass.test.sh +141 -0
  780. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  781. package/tests/git-maintenance-guard.test.sh +83 -0
  782. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  783. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  784. package/tests/git-submodule-guard.test.sh +50 -0
  785. package/tests/grep-pcre-portability.test.sh +155 -0
  786. package/tests/hook-registration-matches-input.test.sh +73 -0
  787. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  788. package/tests/install-does-not-claim-protection.test.sh +110 -0
  789. package/tests/install-example-standalone-tools.test.sh +139 -0
  790. package/tests/line-continuation-bypass.test.sh +114 -0
  791. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  792. package/tests/nested-background-agent-guard.test.sh +58 -0
  793. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  794. package/tests/option-eating-grep-patterns.test.sh +130 -0
  795. package/tests/outdated-core-guards.test.sh +134 -0
  796. package/tests/outdated-report.test.sh +155 -0
  797. package/tests/output-secret-mask-warns.test.sh +73 -0
  798. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  799. package/tests/plugins-word-order.test.sh +126 -0
  800. package/tests/powershell-remove-item-guard.test.sh +85 -0
  801. package/tests/project-dir-naming.test.sh +103 -0
  802. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  803. package/tests/reroute-after-block-guard.test.sh +104 -0
  804. package/tests/secret-guard-documented-promises.test.sh +97 -0
  805. package/tests/session-plugin-pin-watch.test.sh +45 -0
  806. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  807. package/tests/shield-no-silent-adoption.test.py +110 -0
  808. package/tests/shield-no-silent-adoption.test.sh +46 -0
  809. package/tests/stop-transcript-write-health.test.sh +46 -0
  810. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  811. package/tests/test-account-billing-log.sh +100 -0
  812. package/tests/test-account-routing-preflight.sh +77 -0
  813. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  814. package/tests/test-agent-view-quota-warn.sh +184 -0
  815. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  816. package/tests/test-agents-md-loader.sh +204 -0
  817. package/tests/test-agents-md-sync-checker.sh +125 -0
  818. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  819. package/tests/test-allowlist.sh +60 -0
  820. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  821. package/tests/test-anthropic-base-url-guard.sh +88 -0
  822. package/tests/test-articulated-scope-capture.sh +139 -0
  823. package/tests/test-attachment-traversal-guard.sh +168 -0
  824. package/tests/test-aup-block-pattern-logger.sh +315 -0
  825. package/tests/test-aup-false-positive-helper.sh +188 -0
  826. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  827. package/tests/test-aup-retry-loop-guard.sh +341 -0
  828. package/tests/test-auth-expiry-reminder.sh +303 -0
  829. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  830. package/tests/test-auth-path-detector.sh +232 -0
  831. package/tests/test-auth-status-checker.sh +233 -0
  832. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  833. package/tests/test-background-cost-launch-guard.sh +62 -0
  834. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  835. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  836. package/tests/test-bash-project-fence.sh +127 -0
  837. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  838. package/tests/test-binary-read-detector.sh +173 -0
  839. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  840. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  841. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  842. package/tests/test-cache-creation-drift-detector.sh +244 -0
  843. package/tests/test-cache-residue-detector.sh +429 -0
  844. package/tests/test-cache-tier-logger.sh +59 -0
  845. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  846. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  847. package/tests/test-claim-verify-detector.sh +222 -0
  848. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  849. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  850. package/tests/test-claude-md-reinjector.sh +173 -0
  851. package/tests/test-claude-md-size-monitor.sh +107 -0
  852. package/tests/test-claude-update-budget-guard.sh +132 -0
  853. package/tests/test-claude-update-smart.sh +91 -0
  854. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  855. package/tests/test-cli-config-pinning-detector.sh +233 -0
  856. package/tests/test-cliff-countdown-advisor.sh +138 -0
  857. package/tests/test-closure-word-verify-gate.sh +158 -0
  858. package/tests/test-commit-all-scope-guard.sh +73 -0
  859. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  860. package/tests/test-compact-circuit-breaker.sh +134 -0
  861. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  862. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  863. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  864. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  865. package/tests/test-context-length-budget.sh +68 -0
  866. package/tests/test-context-usage-drift-alert.sh +52 -22
  867. package/tests/test-cost-incident-self-audit.sh +94 -0
  868. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  869. package/tests/test-cowork-claudemd-helper.sh +141 -0
  870. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  871. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  872. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  873. package/tests/test-credential-exfil-guard.sh +62 -0
  874. package/tests/test-cron-create-receipt.sh +165 -0
  875. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  876. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  877. package/tests/test-daily-cost-guard.sh +131 -0
  878. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  879. package/tests/test-deployment-readback-gate.sh +92 -0
  880. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  881. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  882. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  883. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  884. package/tests/test-dispatch-receipt.sh +314 -0
  885. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  886. package/tests/test-echo-probe-spam-detector.sh +143 -0
  887. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  888. package/tests/test-ephemeral-container-detector.sh +251 -0
  889. package/tests/test-evidence-claim-gate.sh +291 -0
  890. package/tests/test-exploration-budget-guard.sh +164 -0
  891. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  892. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  893. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  894. package/tests/test-fabricated-command-detector.sh +296 -0
  895. package/tests/test-false-disk-full-guard.sh +36 -0
  896. package/tests/test-feature-deprecation-detector.sh +117 -0
  897. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  898. package/tests/test-git-operations-require-approval.sh +53 -0
  899. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  900. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  901. package/tests/test-growthbook-flag-monitor.sh +428 -0
  902. package/tests/test-halt-signal-detector.sh +120 -0
  903. package/tests/test-hook-self-disable-detector.sh +232 -0
  904. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  905. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  906. package/tests/test-marketplace-plugins.sh +193 -0
  907. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  908. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  909. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  910. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  911. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  912. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  913. package/tests/test-memory-chain-audit.sh +59 -0
  914. package/tests/test-memory-orphan-detector.sh +227 -0
  915. package/tests/test-model-swap-suggester.sh +368 -0
  916. package/tests/test-model-version-lock.sh +83 -0
  917. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  918. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  919. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  920. package/tests/test-no-force-flag.sh +49 -0
  921. package/tests/test-non-english-quality-warner.sh +229 -0
  922. package/tests/test-oauth-refresh-monitor.sh +311 -0
  923. package/tests/test-opus-degradation-tracker.sh +274 -0
  924. package/tests/test-opus48-routine-task-warning.sh +201 -0
  925. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  926. package/tests/test-output-token-spike-detector.sh +315 -0
  927. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  928. package/tests/test-parallel-cascade-detector.sh +191 -0
  929. package/tests/test-partial-view-claim-arrest.sh +272 -0
  930. package/tests/test-per-prompt-token-cap.sh +136 -0
  931. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  932. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  933. package/tests/test-post-edit-disk-verify.sh +294 -0
  934. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  935. package/tests/test-pre-execution-claim-detector.sh +366 -0
  936. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  937. package/tests/test-proxy-capture-suggester.sh +214 -0
  938. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  939. package/tests/test-quota-anomaly-detector.sh +321 -0
  940. package/tests/test-quota-reset-audit.sh +81 -0
  941. package/tests/test-read-loop-detector.sh +137 -0
  942. package/tests/test-read-once-guard.sh +85 -0
  943. package/tests/test-receipts-aggregate.sh +143 -0
  944. package/tests/test-redirect-fragment-warner.sh +130 -0
  945. package/tests/test-redundant-read-blocker.sh +155 -0
  946. package/tests/test-refusal-arrest-gate.sh +303 -0
  947. package/tests/test-remote-control-billing-classifier.sh +125 -0
  948. package/tests/test-resume-drift-watcher.sh +65 -0
  949. package/tests/test-rg-replace-flag-detector.sh +175 -0
  950. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  951. package/tests/test-rm-safety-net.sh +115 -0
  952. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  953. package/tests/test-runtime-binary-change-detector.sh +196 -0
  954. package/tests/test-same-command-repeat-detector.sh +165 -0
  955. package/tests/test-same-correction-arrest.sh +165 -0
  956. package/tests/test-scope-expansion-receipt.sh +207 -0
  957. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  958. package/tests/test-session-persistence-verifier.sh +128 -0
  959. package/tests/test-session-rate-monitor.sh +284 -0
  960. package/tests/test-session-start-quota-status.sh +210 -0
  961. package/tests/test-session-start-safety-check.sh +138 -0
  962. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  963. package/tests/test-settings-json-health-check.sh +70 -0
  964. package/tests/test-settings-regression-tester.sh +197 -0
  965. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  966. package/tests/test-skill-description-drop-detector.sh +236 -0
  967. package/tests/test-skill-truncation-detector.sh +263 -0
  968. package/tests/test-skills-context-recorder.sh +329 -0
  969. package/tests/test-skills-load-verifier.sh +184 -0
  970. package/tests/test-skills-settings-validator.sh +242 -0
  971. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  972. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  973. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  974. package/tests/test-ssh-key-protect.sh +81 -0
  975. package/tests/test-stale-temp-settings-detector.sh +161 -0
  976. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  977. package/tests/test-starter-hooks-manifest.sh +96 -0
  978. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  979. package/tests/test-strict-allowlist.sh +72 -0
  980. package/tests/test-subagent-boundary-precheck.sh +137 -0
  981. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  982. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  983. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  984. package/tests/test-subagent-identity-reassertion.sh +61 -0
  985. package/tests/test-subagent-inheritance-tester.sh +319 -0
  986. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  987. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  988. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  989. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  990. package/tests/test-subscription-api-billing-warner.sh +138 -0
  991. package/tests/test-subscription-bypass-detector.sh +255 -0
  992. package/tests/test-temporal-suggestion-detector.sh +183 -0
  993. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  994. package/tests/test-thinking-stall-detector.sh +151 -0
  995. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  996. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  997. package/tests/test-tool-result-correlation-checker.sh +264 -0
  998. package/tests/test-tool-result-size-guard.sh +121 -0
  999. package/tests/test-transcript-contamination-detector.sh +264 -0
  1000. package/tests/test-trigger-header-parsing.sh +151 -0
  1001. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  1002. package/tests/test-userprompt-submit-receipt.sh +181 -0
  1003. package/tests/test-verify-after-publish-reminder.sh +184 -0
  1004. package/tests/test-version-bump-detector.sh +212 -0
  1005. package/tests/test-version-regression-warner.sh +165 -0
  1006. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1007. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1008. package/tests/test-wellness-break-reminder.sh +138 -0
  1009. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1010. package/tests/test-windows-python-stub-detector.sh +146 -0
  1011. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1012. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1013. package/tests/test-xml-format-leak-detector.sh +299 -0
  1014. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1015. package/tests/workspace-lease-guard.test.sh +144 -0
  1016. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1017. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1018. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1019. package/tests/write-empty-content-guard.test.sh +39 -0
  1020. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1021. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1022. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,195 @@
1
+ #!/bin/bash
2
+ # authorized-reconfirmation-detector.sh — Measure how often
3
+ # AskUserQuestion fires on an action that the operator's prior turn
4
+ # already authorized.
5
+ #
6
+ # Solves: anthropics/claude-code#61929 (Claude Code makes major design
7
+ # decisions silently but asks for confirmation on trivial things),
8
+ # specifically case (3) in the three-way split articulated in
9
+ # https://github.com/anthropics/claude-code/issues/61929#issuecomment-4549798175 :
10
+ #
11
+ # (1) Genuine fork — model has multiple plausible paths; AUQ is correct
12
+ # (2) Articulation-surface mis-bound — model has the answer (marks
13
+ # "(Recommended)") and uses AUQ to describe its choice rather than
14
+ # delegate it
15
+ # (3) Authorized re-confirmation — operator already said "do X" in the
16
+ # prior turn; model opens AUQ asking "Should I do X?" with
17
+ # "(Recommended) yes"
18
+ #
19
+ # This hook does not block. It measures. The output is one structured
20
+ # log line per detected case (3) — turn timestamp, AUQ question text,
21
+ # matched verb stem, user-message excerpt. That log file becomes the
22
+ # empirical foundation for the eventual UserPromptSubmit-side intent
23
+ # classifier (case 3's primary fix). Case (2) cannot be addressed at
24
+ # Stop without already having shown the menu; that one needs PreToolUse
25
+ # visibility into the AUQ preamble (#61983) to convert the menu into an
26
+ # inline articulation.
27
+ #
28
+ # Detection signature (all three required to log):
29
+ # a) An AskUserQuestion tool call exists in the latest assistant turn.
30
+ # b) At least one of its options carries a "(Recommended)" marker
31
+ # (English) or "推奨" (Japanese).
32
+ # c) The most recent user message contains a content word (length >= 4)
33
+ # that also appears in the AUQ question text. Common stopwords are
34
+ # filtered. This is the "operator already named the action" echo.
35
+ #
36
+ # False positives are intentionally tolerated for measurement — the
37
+ # detector emits an advisory log line, never an exit code, never a block.
38
+ # An operator may have authorized an irreversible action and still want
39
+ # AUQ to fire as a safety re-check; that case will show up in the log
40
+ # and informs the classifier's eventual exclusion list.
41
+ #
42
+ # Related:
43
+ # #61337 (mhernz) — /goal-mode authorization is structurally
44
+ # indistinguishable from prior-message authorization;
45
+ # the load-bearing axis that lets one classifier
46
+ # address both with the same signal.
47
+ # #61983 — preamble visibility constraint that blocks the
48
+ # PreToolUse-AUQ menu-to-articulation conversion
49
+ # (case 2 territory).
50
+ #
51
+ # TRIGGER: Stop
52
+ # MATCHER: ""
53
+ #
54
+ # CONFIGURATION (environment variables):
55
+ # CC_AUTH_RECONF_LOG log file path
56
+ # (default: ~/.claude/audit/authorized-reconfirmation.log)
57
+ # CC_AUTH_RECONF_DISABLE set to "1" to disable entirely
58
+ #
59
+ # USAGE (settings.json):
60
+ # {
61
+ # "hooks": {
62
+ # "Stop": [{
63
+ # "matcher": "",
64
+ # "hooks": [{
65
+ # "type": "command",
66
+ # "command": "~/.claude/hooks/authorized-reconfirmation-detector.sh"
67
+ # }]
68
+ # }]
69
+ # }
70
+ # }
71
+
72
+ set -uo pipefail
73
+
74
+ [ "${CC_AUTH_RECONF_DISABLE:-0}" = "1" ] && exit 0
75
+
76
+ INPUT=$(cat 2>/dev/null || true)
77
+ [ -z "$INPUT" ] && exit 0
78
+
79
+ LOG_FILE="${CC_AUTH_RECONF_LOG:-${HOME}/.claude/audit/authorized-reconfirmation.log}"
80
+
81
+ # Locate AskUserQuestion calls in the latest assistant turn.
82
+ # Transcript shape varies across Claude Code versions; try several keys.
83
+ AUQ_CALLS=$(printf '%s' "$INPUT" | jq -c '
84
+ def latest_assistant:
85
+ ([ .transcript[]? | select(.role == "assistant") ] | .[-1])
86
+ // .last_assistant_message
87
+ // {};
88
+ def auq_filter(arr):
89
+ [ arr[]?
90
+ | select((.name // .tool_name // "") == "AskUserQuestion")
91
+ | (.input // .tool_input // {}) ];
92
+ (latest_assistant) as $a
93
+ | (auq_filter($a.tool_calls // [])) as $from_tc
94
+ | (auq_filter($a.content // [])) as $from_content
95
+ | ($from_tc + $from_content)
96
+ ' 2>/dev/null)
97
+
98
+ # Nothing to measure if no AUQ this turn.
99
+ if [ -z "$AUQ_CALLS" ] || [ "$AUQ_CALLS" = "null" ] || [ "$AUQ_CALLS" = "[]" ]; then
100
+ exit 0
101
+ fi
102
+
103
+ # Find the most recent user (operator) message text.
104
+ USER_TEXT=$(printf '%s' "$INPUT" | jq -r '
105
+ ([ .transcript[]? | select(.role == "user") ] | .[-1]) as $u
106
+ | ($u.content
107
+ | if type == "string" then .
108
+ elif type == "array" then [ .[]? | (.text // .content // "") ] | join(" ")
109
+ else "" end)
110
+ ' 2>/dev/null)
111
+
112
+ if [ -z "$USER_TEXT" ] || [ "$USER_TEXT" = "null" ]; then
113
+ USER_TEXT=$(printf '%s' "$INPUT" | jq -r '.last_user_message // empty' 2>/dev/null)
114
+ fi
115
+
116
+ # No user text → cannot compare → silent exit.
117
+ if [ -z "$USER_TEXT" ] || [ "$USER_TEXT" = "null" ]; then
118
+ exit 0
119
+ fi
120
+
121
+ mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null || true
122
+
123
+ # Lowercase the user text once.
124
+ UT=$(printf '%s' "$USER_TEXT" | tr '[:upper:]' '[:lower:]')
125
+
126
+ STOPWORDS='^(should|would|could|with|that|this|from|into|your|have|will|been|were|then|than|when|what|which|while|where|there|please|claude|about|just|like|some|also|even|only|over|under|after|before|both|each|same|other|those|these|right|wrong|maybe|going|doing|done|need|want|sure|okay|yeah|nope|true|false)$'
127
+
128
+ # Walk each AUQ call.
129
+ printf '%s' "$AUQ_CALLS" | jq -c '.[]' 2>/dev/null | while read -r CALL; do
130
+ # Skip empty calls.
131
+ [ -z "$CALL" ] || [ "$CALL" = "null" ] && continue
132
+
133
+ # Recommended-option marker check.
134
+ HAS_RECOMMENDED=$(printf '%s' "$CALL" | jq -r '
135
+ (.questions // []) | .[]? | (.options // []) | .[]?
136
+ | ((.label // "") + " " + (.description // ""))
137
+ ' 2>/dev/null | grep -ciE '\(recommended\)|推奨|^recommended\b|\brecommended:' || true)
138
+ HAS_RECOMMENDED=${HAS_RECOMMENDED:-0}
139
+
140
+ # No recommended marker → likely case (1) genuine fork. Skip.
141
+ [ "$HAS_RECOMMENDED" -eq 0 ] && continue
142
+
143
+ # Enumerate every question text in this call.
144
+ QUESTIONS=$(printf '%s' "$CALL" | jq -r '
145
+ (.questions // [{question: (.question // "")}])
146
+ | .[]? | (.question // "")
147
+ | select(length > 0)
148
+ ' 2>/dev/null)
149
+
150
+ [ -z "$QUESTIONS" ] && continue
151
+
152
+ while IFS= read -r Q; do
153
+ [ -z "$Q" ] && continue
154
+
155
+ # Content words (length >= 4, alpha) from the AUQ question.
156
+ QWORDS=$(printf '%s' "$Q" | tr '[:upper:]' '[:lower:]' \
157
+ | grep -oE '[a-z]{4,}' | sort -u \
158
+ | grep -vE "$STOPWORDS" || true)
159
+
160
+ [ -z "$QWORDS" ] && continue
161
+
162
+ # Find at least one content word that also appears in the user
163
+ # message.
164
+ MATCHED_WORD=""
165
+ while IFS= read -r W; do
166
+ [ -z "$W" ] && continue
167
+ if printf '%s' "$UT" | grep -qw "$W"; then
168
+ MATCHED_WORD="$W"
169
+ break
170
+ fi
171
+ done <<< "$QWORDS"
172
+
173
+ [ -z "$MATCHED_WORD" ] && continue
174
+
175
+ # Detected. Emit a structured log line.
176
+ TS=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
177
+ USER_EXCERPT=$(printf '%s' "$USER_TEXT" | tr '\n' ' ' | head -c 240)
178
+ ENTRY=$(jq -nc \
179
+ --arg ts "$TS" \
180
+ --arg q "$Q" \
181
+ --arg word "$MATCHED_WORD" \
182
+ --arg user_excerpt "$USER_EXCERPT" \
183
+ '{
184
+ timestamp: $ts,
185
+ event: "authorized_reconfirmation_detected",
186
+ auq_question: $q,
187
+ matched_word: $word,
188
+ user_excerpt: $user_excerpt
189
+ }' 2>/dev/null)
190
+
191
+ [ -n "$ENTRY" ] && echo "$ENTRY" >> "$LOG_FILE"
192
+ done <<< "$QUESTIONS"
193
+ done
194
+
195
+ exit 0
@@ -24,6 +24,45 @@ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
24
24
  CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
25
25
  [ -z "$CMD" ] && exit 0
26
26
 
27
+ # Approve only when EVERY command position qualifies.
28
+ #
29
+ # The patterns below were anchored at `^\s*` and matched against the whole
30
+ # command string, so only the first command position was examined and the
31
+ # approval was then handed to the entire line: `npm test && sudo rm -rf app` was
32
+ # approved on the strength of its first word. Measured 2026-08-03 against the
33
+ # shipped copy. Same defect as PR #937 (allowlist.sh) and PR #940
34
+ # (cd-git-allow.sh), here on the approving side, where the decision is an
35
+ # explicit approval rather than a missed block.
36
+ #
37
+ # Splitting on the separator characters is approximate — quotes are not parsed —
38
+ # so anything that can hide a command from a string-level read (command
39
+ # substitution, backticks) disqualifies the line outright. A line that does not
40
+ # qualify gets no decision, which leaves it to the normal permission flow. This
41
+ # hook only ever adds approval; it never blocks.
42
+ #
43
+ # The gate uses the union of the three patterns, so a chain of different
44
+ # approved kinds (`npm ci && npm test`) still passes; the if-chain below only
45
+ # picks which branch reports the approval.
46
+ cc_every_segment_matches() {
47
+ local pat="$1" cmd="$2" seg
48
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
49
+ while IFS= read -r seg; do
50
+ seg="${seg#"${seg%%[![:space:]]*}"}"
51
+ seg="${seg%"${seg##*[![:space:]]}"}"
52
+ [ -z "$seg" ] && continue
53
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
54
+ done <<EOF
55
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
56
+ EOF
57
+ return 0
58
+ }
59
+
60
+ BUILD_SAFE_RE='^\s*(npm|yarn|pnpm|bun|npx)\s+(run\s+)?(build|test|lint|check|typecheck|format|dev|start|ci)'
61
+ BUILD_SAFE_RE="$BUILD_SAFE_RE"'|^\s*(cargo\s+(build|test|check|clippy|fmt)|go\s+(build|test|vet|fmt)|make\s+(build|test|check|lint))'
62
+ BUILD_SAFE_RE="$BUILD_SAFE_RE"'|^\s*(python|python3)\s+(-m\s+)?(pytest|unittest|mypy|ruff|black|isort|flake8)'
63
+
64
+ cc_every_segment_matches "$BUILD_SAFE_RE" "$CMD" || exit 0
65
+
27
66
  # Auto-approve safe build/test/lint commands
28
67
  if echo "$CMD" | grep -qE '^\s*(npm|yarn|pnpm|bun|npx)\s+(run\s+)?(build|test|lint|check|typecheck|format|dev|start|ci)'; then
29
68
  echo '{"decision":"approve"}'
@@ -3,7 +3,37 @@
3
3
  # TRIGGER: PreToolUse MATCHER: "Bash"
4
4
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
5
5
  [ -z "$COMMAND" ] && exit 0
6
- if echo "$COMMAND" | grep -qE '^\s*cargo\s+(build|test|check|clippy|fmt|run|bench|doc|clean)(\s|$)'; then
6
+
7
+ # Approve only when EVERY command position qualifies.
8
+ #
9
+ # The pattern below was anchored at `^\s*` and matched against the whole command
10
+ # string, so only the first command position was examined and the approval was
11
+ # then handed to the entire line: `cargo build && sudo rm -rf app` was approved
12
+ # on the strength of its first word. Measured 2026-08-03 against the shipped
13
+ # copy. Same defect as PR #937 (allowlist.sh) and PR #940 (cd-git-allow.sh),
14
+ # here on the approving side, where the decision is an explicit approval rather
15
+ # than a missed block.
16
+ #
17
+ # Splitting on the separator characters is approximate — quotes are not parsed —
18
+ # so anything that can hide a command from a string-level read (command
19
+ # substitution, backticks) disqualifies the line outright. A line that does not
20
+ # qualify gets no decision, which leaves it to the normal permission flow. This
21
+ # hook only ever adds approval; it never blocks.
22
+ cc_every_segment_matches() {
23
+ local pat="$1" cmd="$2" seg
24
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
25
+ while IFS= read -r seg; do
26
+ seg="${seg#"${seg%%[![:space:]]*}"}"
27
+ seg="${seg%"${seg##*[![:space:]]}"}"
28
+ [ -z "$seg" ] && continue
29
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
30
+ done <<EOF
31
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
32
+ EOF
33
+ return 0
34
+ }
35
+
36
+ if cc_every_segment_matches '^\s*cargo\s+(build|test|check|clippy|fmt|run|bench|doc|clean)(\s|$)' "$COMMAND"; then
7
37
  jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"cargo command auto-approved"}}'
8
38
  fi
9
39
  exit 0
@@ -6,6 +6,41 @@ TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
6
6
  [ "$TOOL" != "Bash" ] && exit 0
7
7
  CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
8
8
  [ -z "$CMD" ] && exit 0
9
+
10
+ # Approve only when EVERY command position qualifies.
11
+ #
12
+ # The patterns below were anchored at `^\s*` and matched against the whole
13
+ # command string, so only the first command position was examined and the
14
+ # approval was then handed to the entire line: `docker ps && sudo rm -rf app`
15
+ # was approved on the strength of its first word. Measured 2026-08-03 against
16
+ # the shipped copy. Same defect as PR #937 (allowlist.sh) and PR #940
17
+ # (cd-git-allow.sh), here on the approving side, where the decision is an
18
+ # explicit approval rather than a missed block.
19
+ #
20
+ # Splitting on the separator characters is approximate — quotes are not parsed —
21
+ # so anything that can hide a command from a string-level read (command
22
+ # substitution, backticks) disqualifies the line outright. A line that does not
23
+ # qualify gets no decision, which leaves it to the normal permission flow. This
24
+ # hook only ever adds approval; it never blocks.
25
+ cc_every_segment_matches() {
26
+ local pat="$1" cmd="$2" seg
27
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
28
+ while IFS= read -r seg; do
29
+ seg="${seg#"${seg%%[![:space:]]*}"}"
30
+ seg="${seg%"${seg##*[![:space:]]}"}"
31
+ [ -z "$seg" ] && continue
32
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
33
+ done <<EOF
34
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
35
+ EOF
36
+ return 0
37
+ }
38
+
39
+ DOCKER_SAFE_RE='^\s*docker\s+(build|compose|ps|images|logs|inspect|network\s+ls|volume\s+ls|exec|run)'
40
+ DOCKER_SAFE_RE="$DOCKER_SAFE_RE"'|^\s*docker-compose\s+(up|down|build|logs|ps|restart)'
41
+
42
+ cc_every_segment_matches "$DOCKER_SAFE_RE" "$CMD" || exit 0
43
+
9
44
  if echo "$CMD" | grep -qE '^\s*docker\s+(build|compose|ps|images|logs|inspect|network\s+ls|volume\s+ls|exec|run)'; then
10
45
  echo '{"decision":"approve"}'
11
46
  exit 0
@@ -18,25 +18,48 @@ if [[ -z "$COMMAND" ]]; then
18
18
  exit 0
19
19
  fi
20
20
 
21
- # Match git read-only commands with optional -C flag
22
- if echo "$COMMAND" | grep -qE '^\s*git\s+(-C\s+\S+\s+)?(status|log|diff|branch|show|rev-parse|tag|remote)(\s|$)'; then
23
- jq -n '{
24
- hookSpecificOutput: {
25
- hookEventName: "PreToolUse",
26
- permissionDecision: "allow",
27
- permissionDecisionReason: "git read-only auto-approved"
28
- }
29
- }'
30
- exit 0
31
- fi
21
+ # Approve only when EVERY command position qualifies.
22
+ #
23
+ # Both patterns were anchored at `^\s*` and matched against the whole command
24
+ # string, so only the first command position was examined and the approval was
25
+ # then handed to the entire line: `git log && sudo rm -rf app` and
26
+ # `cd /repo && git status; curl http://… | sh` were both approved on the
27
+ # strength of what came first. Measured 2026-08-03. Same defect as PR #937 /
28
+ # #940 / #941, on the approving side, where the decision is an explicit approval
29
+ # rather than a missed block.
30
+ #
31
+ # Splitting on the separator characters is approximate — quotes are not parsed —
32
+ # so anything that can hide a command from a string-level read (command
33
+ # substitution, backticks) disqualifies the line outright. A line that does not
34
+ # qualify gets no decision, which leaves it to the normal permission flow. This
35
+ # hook only ever adds approval; it never blocks.
36
+ cc_every_segment_matches() {
37
+ local pat="$1" cmd="$2" seg
38
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
39
+ while IFS= read -r seg; do
40
+ seg="${seg#"${seg%%[![:space:]]*}"}"
41
+ seg="${seg%"${seg##*[![:space:]]}"}"
42
+ [ -z "$seg" ] && continue
43
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
44
+ done <<EOF
45
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
46
+ EOF
47
+ return 0
48
+ }
49
+
50
+ GIT_READ_RE='^\s*git\s+(-C\s+\S+\s+)?(status|log|diff|branch|show|rev-parse|tag|remote)(\s|$)'
51
+ # a leading `cd` is allowed as one of the segments, which is what the second
52
+ # pattern used to cover
53
+ SEG_RE="$GIT_READ_RE"'|^\s*cd(\s|$)'
32
54
 
33
- # Match cd + git read-only compounds
34
- if echo "$COMMAND" | grep -qE '^\s*cd\s+.*&&\s*git\s+(status|log|diff|branch|show|rev-parse)'; then
55
+ # and at least one segment has to actually be the git read
56
+ if cc_every_segment_matches "$SEG_RE" "$COMMAND" \
57
+ && printf '%s' "$COMMAND" | grep -qE '(^|[;&|])\s*git\s'; then
35
58
  jq -n '{
36
59
  hookSpecificOutput: {
37
60
  hookEventName: "PreToolUse",
38
61
  permissionDecision: "allow",
39
- permissionDecisionReason: "cd+git compound auto-approved"
62
+ permissionDecisionReason: "git read-only auto-approved"
40
63
  }
41
64
  }'
42
65
  exit 0
@@ -3,7 +3,36 @@
3
3
  # TRIGGER: PreToolUse MATCHER: "Bash"
4
4
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
5
5
  [ -z "$COMMAND" ] && exit 0
6
- if echo "$COMMAND" | grep -qE '^\s*go\s+(build|test|vet|fmt|mod|run|generate|install|clean)(\s|$)'; then
6
+ # Approve only when EVERY command position qualifies.
7
+ #
8
+ # The pattern below was anchored at `^\s*` and matched against the whole command
9
+ # string, so only the first command position was examined and the approval was
10
+ # then handed to the entire line: `go test ./... && sudo rm -rf app` was
11
+ # approved on the strength of its first word. Measured 2026-08-03 against the
12
+ # shipped copy. Same defect as PR #937 (allowlist.sh) and PR #940
13
+ # (cd-git-allow.sh), here on the approving side, where the decision is an
14
+ # explicit approval rather than a missed block.
15
+ #
16
+ # Splitting on the separator characters is approximate — quotes are not parsed —
17
+ # so anything that can hide a command from a string-level read (command
18
+ # substitution, backticks) disqualifies the line outright. A line that does not
19
+ # qualify gets no decision, which leaves it to the normal permission flow. This
20
+ # hook only ever adds approval; it never blocks.
21
+ cc_every_segment_matches() {
22
+ local pat="$1" cmd="$2" seg
23
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
24
+ while IFS= read -r seg; do
25
+ seg="${seg#"${seg%%[![:space:]]*}"}"
26
+ seg="${seg%"${seg##*[![:space:]]}"}"
27
+ [ -z "$seg" ] && continue
28
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
29
+ done <<EOF
30
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
31
+ EOF
32
+ return 0
33
+ }
34
+
35
+ if cc_every_segment_matches '^\s*go\s+(build|test|vet|fmt|mod|run|generate|install|clean)(\s|$)' "$COMMAND"; then
7
36
  jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"go command auto-approved"}}'
8
37
  fi
9
38
  exit 0
@@ -3,7 +3,35 @@
3
3
  # TRIGGER: PreToolUse MATCHER: "Bash"
4
4
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
5
5
  [ -z "$COMMAND" ] && exit 0
6
- if echo "$COMMAND" | grep -qE '^\s*(gradle|gradlew|./gradlew)\s+(build|test|check|assemble|clean|compileJava|compileKotlin|lint)(\s|$)'; then
6
+ # Approve only when EVERY command position qualifies.
7
+ #
8
+ # The pattern below was anchored at `^\s*` and matched against the whole command
9
+ # string, so only the first command position was examined and the approval was
10
+ # then handed to the entire line: `gradle build && sudo rm -rf app` was approved
11
+ # on the strength of its first word. Measured 2026-08-03. Same defect as
12
+ # PR #937 / #940 / #941, on the approving side, where the decision is an
13
+ # explicit approval rather than a missed block.
14
+ #
15
+ # Splitting on the separator characters is approximate — quotes are not parsed —
16
+ # so anything that can hide a command from a string-level read (command
17
+ # substitution, backticks) disqualifies the line outright. A line that does not
18
+ # qualify gets no decision, which leaves it to the normal permission flow. This
19
+ # hook only ever adds approval; it never blocks.
20
+ cc_every_segment_matches() {
21
+ local pat="$1" cmd="$2" seg
22
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
23
+ while IFS= read -r seg; do
24
+ seg="${seg#"${seg%%[![:space:]]*}"}"
25
+ seg="${seg%"${seg##*[![:space:]]}"}"
26
+ [ -z "$seg" ] && continue
27
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
28
+ done <<EOF
29
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
30
+ EOF
31
+ return 0
32
+ }
33
+
34
+ if cc_every_segment_matches '^\s*(gradle|gradlew|./gradlew)\s+(build|test|check|assemble|clean|compileJava|compileKotlin|lint)(\s|$)' "$COMMAND"; then
7
35
  jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"gradle command auto-approved"}}'
8
36
  fi
9
37
  exit 0
@@ -3,7 +3,35 @@
3
3
  # TRIGGER: PreToolUse MATCHER: "Bash"
4
4
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
5
5
  [ -z "$COMMAND" ] && exit 0
6
- if echo "$COMMAND" | grep -qE '^\s*make\s+(build|test|lint|format|check|clean|install|all|dev|start|run)(\s|$)'; then
6
+ # Approve only when EVERY command position qualifies.
7
+ #
8
+ # The pattern below was anchored at `^\s*` and matched against the whole command
9
+ # string, so only the first command position was examined and the approval was
10
+ # then handed to the entire line: `make test && sudo rm -rf app` was approved on
11
+ # the strength of its first word. Measured 2026-08-03. Same defect as
12
+ # PR #937 / #940 / #941, on the approving side, where the decision is an
13
+ # explicit approval rather than a missed block.
14
+ #
15
+ # Splitting on the separator characters is approximate — quotes are not parsed —
16
+ # so anything that can hide a command from a string-level read (command
17
+ # substitution, backticks) disqualifies the line outright. A line that does not
18
+ # qualify gets no decision, which leaves it to the normal permission flow. This
19
+ # hook only ever adds approval; it never blocks.
20
+ cc_every_segment_matches() {
21
+ local pat="$1" cmd="$2" seg
22
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
23
+ while IFS= read -r seg; do
24
+ seg="${seg#"${seg%%[![:space:]]*}"}"
25
+ seg="${seg%"${seg##*[![:space:]]}"}"
26
+ [ -z "$seg" ] && continue
27
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
28
+ done <<EOF
29
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
30
+ EOF
31
+ return 0
32
+ }
33
+
34
+ if cc_every_segment_matches '^\s*make\s+(build|test|lint|format|check|clean|install|all|dev|start|run)(\s|$)' "$COMMAND"; then
7
35
  jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"make target auto-approved"}}'
8
36
  fi
9
37
  exit 0
@@ -3,7 +3,35 @@
3
3
  # TRIGGER: PreToolUse MATCHER: "Bash"
4
4
  COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
5
5
  [ -z "$COMMAND" ] && exit 0
6
- if echo "$COMMAND" | grep -qE '^\s*(mvn|mvnw|./mvnw)\s+(compile|test|verify|package|clean|install)(\s|$)'; then
6
+ # Approve only when EVERY command position qualifies.
7
+ #
8
+ # The pattern below was anchored at `^\s*` and matched against the whole command
9
+ # string, so only the first command position was examined and the approval was
10
+ # then handed to the entire line: `mvn test && sudo rm -rf app` was approved on
11
+ # the strength of its first word. Measured 2026-08-03. Same defect as
12
+ # PR #937 / #940 / #941, on the approving side, where the decision is an
13
+ # explicit approval rather than a missed block.
14
+ #
15
+ # Splitting on the separator characters is approximate — quotes are not parsed —
16
+ # so anything that can hide a command from a string-level read (command
17
+ # substitution, backticks) disqualifies the line outright. A line that does not
18
+ # qualify gets no decision, which leaves it to the normal permission flow. This
19
+ # hook only ever adds approval; it never blocks.
20
+ cc_every_segment_matches() {
21
+ local pat="$1" cmd="$2" seg
22
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
23
+ while IFS= read -r seg; do
24
+ seg="${seg#"${seg%%[![:space:]]*}"}"
25
+ seg="${seg%"${seg##*[![:space:]]}"}"
26
+ [ -z "$seg" ] && continue
27
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
28
+ done <<EOF
29
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
30
+ EOF
31
+ return 0
32
+ }
33
+
34
+ if cc_every_segment_matches '^\s*(mvn|mvnw|./mvnw)\s+(compile|test|verify|package|clean|install)(\s|$)' "$COMMAND"; then
7
35
  jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"maven command auto-approved"}}'
8
36
  fi
9
37
  exit 0
@@ -15,13 +15,53 @@
15
15
  # }
16
16
  # }
17
17
  #
18
- # TRIGGER: PermissionRequest MATCHER: ""
18
+ # TRIGGER: PreToolUse MATCHER: "Bash"
19
19
 
20
20
  INPUT=$(cat)
21
21
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
22
22
 
23
23
  [[ -z "$COMMAND" ]] && exit 0
24
24
 
25
+ # Approve only when EVERY command position qualifies.
26
+ #
27
+ # The patterns below were anchored at `^\s*` and matched against the whole
28
+ # command string, so only the first command position was examined and the
29
+ # approval was then handed to the entire line: `pytest && sudo rm -rf app` was
30
+ # approved on the strength of its first word. Measured 2026-08-03 against the
31
+ # shipped copy. Same defect as PR #937 (allowlist.sh) and PR #940
32
+ # (cd-git-allow.sh), here on the approving side, where the decision is an
33
+ # explicit approval rather than a missed block.
34
+ #
35
+ # Splitting on the separator characters is approximate — quotes are not parsed —
36
+ # so anything that can hide a command from a string-level read (command
37
+ # substitution, backticks) disqualifies the line outright. A line that does not
38
+ # qualify gets no decision, which leaves it to the normal permission flow. This
39
+ # hook only ever adds approval; it never blocks.
40
+ #
41
+ # The gate uses the union of the four patterns, so a chain of different approved
42
+ # kinds (`ruff check . && pytest`) still passes; the if-chain below only picks
43
+ # which reason to report.
44
+ cc_every_segment_matches() {
45
+ local pat="$1" cmd="$2" seg
46
+ case "$cmd" in *'$('*|*'`'*) return 1 ;; esac
47
+ while IFS= read -r seg; do
48
+ seg="${seg#"${seg%%[![:space:]]*}"}"
49
+ seg="${seg%"${seg##*[![:space:]]}"}"
50
+ [ -z "$seg" ] && continue
51
+ printf '%s' "$seg" | grep -qE "$pat" || return 1
52
+ done <<EOF
53
+ $(printf '%s' "$cmd" | tr ';&|' '\n\n\n')
54
+ EOF
55
+ return 0
56
+ }
57
+
58
+ PY_SAFE_RE='^\s*(pytest|python\s+-m\s+pytest|python\s+-m\s+unittest)(\s|$)'
59
+ PY_SAFE_RE="$PY_SAFE_RE"'|^\s*(ruff\s+(check|format)|black\s|isort\s|flake8\s|pylint\s|mypy\s|pyright\s)'
60
+ PY_SAFE_RE="$PY_SAFE_RE"'|^\s*(pip\s+list|pip\s+show|pip\s+freeze|pipdeptree)(\s|$)'
61
+ PY_SAFE_RE="$PY_SAFE_RE"'|^\s*python3?\s+-m\s+py_compile\s'
62
+
63
+ cc_every_segment_matches "$PY_SAFE_RE" "$COMMAND" || exit 0
64
+
25
65
  # Python test runners
26
66
  if echo "$COMMAND" | grep -qE '^\s*(pytest|python\s+-m\s+pytest|python\s+-m\s+unittest)(\s|$)'; then
27
67
  jq -n '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"Python test auto-approved"}}'
@@ -1,3 +1,4 @@
1
+ #!/bin/bash
1
2
  #
2
3
  # TRIGGER: PermissionRequest MATCHER: ""
3
4
  INPUT=$(cat)