cc-safe-setup 29.8.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 (1017) 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-dispatch-watchdog.sh +149 -0
  178. package/examples/completion-claim-without-verification-detector.sh +207 -0
  179. package/examples/composer-guard.sh +12 -0
  180. package/examples/compound-bash-permission-resolver.sh +156 -0
  181. package/examples/compound-command-allow.sh +1 -1
  182. package/examples/compound-command-deny-enforcer.sh +183 -0
  183. package/examples/compound-inject-guard.sh +12 -0
  184. package/examples/concurrent-edit-lock.sh +12 -0
  185. package/examples/conflict-marker-guard.sh +12 -0
  186. package/examples/consecutive-error-breaker.sh +0 -0
  187. package/examples/console-log-count.sh +1 -0
  188. package/examples/context-compact-advisor.sh +29 -2
  189. package/examples/context-length-budget.sh +69 -0
  190. package/examples/context-threshold-alert.sh +12 -0
  191. package/examples/context-usage-drift-alert.sh +41 -13
  192. package/examples/conversation-history-guard.sh +12 -0
  193. package/examples/core-file-protect-guard.sh +12 -0
  194. package/examples/cors-star-warn.sh +0 -0
  195. package/examples/cost-incident-self-audit.sh +162 -0
  196. package/examples/cowork-claude-md-load-checker.sh +100 -0
  197. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  198. package/examples/cowork-hook-absence-warner.sh +167 -0
  199. package/examples/cowork-model-picker-advisor.sh +115 -0
  200. package/examples/credential-exfil-guard.sh +65 -4
  201. package/examples/credential-file-cat-guard.sh +17 -1
  202. package/examples/cron-create-receipt.sh +112 -0
  203. package/examples/cron-modification-guard.sh +12 -0
  204. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  205. package/examples/cwd-project-boundary-guard.sh +0 -0
  206. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  207. package/examples/daily-cost-guard.sh +164 -0
  208. package/examples/daily-usage-tracker.sh +0 -0
  209. package/examples/dangerous-pip-flag-guard.sh +12 -0
  210. package/examples/db-connect-guard.sh +13 -1
  211. package/examples/denied-action-retry-guard.sh +12 -0
  212. package/examples/deny-bypass-detector.sh +12 -0
  213. package/examples/deny-rule-integrity-verifier.sh +181 -0
  214. package/examples/dependency-install-guard.sh +12 -0
  215. package/examples/deploy-guard.sh +14 -2
  216. package/examples/deploy-path-verify-guard.sh +12 -0
  217. package/examples/deployment-readback-gate.sh +135 -0
  218. package/examples/deployment-readback-gh-adapter.sh +247 -0
  219. package/examples/deployment-verify-guard.sh +25 -2
  220. package/examples/destructive-db-script-write-guard.sh +166 -0
  221. package/examples/destructive-migration-write-guard.sh +163 -0
  222. package/examples/diff-size-guard.sh +12 -0
  223. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  224. package/examples/disk-partition-guard.sh +12 -0
  225. package/examples/dispatch-allowlist-preflight.sh +301 -0
  226. package/examples/dispatch-liveness-watchdog.sh +216 -0
  227. package/examples/dispatch-receipt.sh +174 -0
  228. package/examples/django-migrate-guard.sh +12 -0
  229. package/examples/dns-config-guard.sh +12 -0
  230. package/examples/docker-dangerous-guard.sh +12 -0
  231. package/examples/docker-volume-guard.sh +0 -0
  232. package/examples/dockerfile-latest-guard.sh +1 -0
  233. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  234. package/examples/dotenv-commit-guard.sh +12 -0
  235. package/examples/dotenv-read-guard.sh +12 -0
  236. package/examples/dotfile-protection-guard.sh +12 -0
  237. package/examples/dotnet-build-on-edit.sh +1 -1
  238. package/examples/drizzle-migrate-guard.sh +27 -2
  239. package/examples/echo-probe-spam-detector.sh +176 -0
  240. package/examples/edit-counter-test-gate.sh +12 -0
  241. package/examples/edit-error-counter.sh +1 -1
  242. package/examples/edit-guard.sh +12 -0
  243. package/examples/edit-old-string-validator.sh +12 -0
  244. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  245. package/examples/edit-retry-loop-guard.sh +0 -0
  246. package/examples/edit-verify.sh +0 -0
  247. package/examples/env-inline-secret-guard.sh +14 -2
  248. package/examples/env-naming-convention.sh +0 -0
  249. package/examples/env-prod-guard.sh +0 -0
  250. package/examples/env-required-check.sh +0 -0
  251. package/examples/env-source-guard.sh +12 -0
  252. package/examples/env-var-check.sh +24 -1
  253. package/examples/ephemeral-container-detector.sh +147 -0
  254. package/examples/error-memory-guard.sh +12 -0
  255. package/examples/evidence-claim-gate.sh +187 -0
  256. package/examples/exploration-budget-guard.sh +12 -0
  257. package/examples/expo-eject-guard.sh +13 -0
  258. package/examples/extended-thinking-loop-guard.sh +139 -0
  259. package/examples/extended-thinking-resume-warning.sh +119 -0
  260. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  261. package/examples/fabricated-command-detector.sh +145 -0
  262. package/examples/false-disk-full-guard.sh +63 -0
  263. package/examples/feature-deprecation-detector.sh +109 -0
  264. package/examples/file-change-tracker.sh +1 -1
  265. package/examples/file-change-undo-tracker.sh +0 -0
  266. package/examples/file-edit-backup.sh +63 -14
  267. package/examples/file-reference-check.sh +0 -0
  268. package/examples/file-size-limit.sh +12 -0
  269. package/examples/financial-operation-guard.sh +12 -0
  270. package/examples/firewall-guard.sh +12 -0
  271. package/examples/fish-shell-wrapper.sh +125 -7
  272. package/examples/five-hundred-milestone.sh +1 -0
  273. package/examples/flask-static-route-guard.sh +89 -0
  274. package/examples/forbidden-response-phrase-detector.sh +161 -0
  275. package/examples/gem-push-guard.sh +13 -0
  276. package/examples/gh-cli-destructive-guard.sh +13 -1
  277. package/examples/git-checkout-safety-guard.sh +12 -0
  278. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  279. package/examples/git-config-guard.sh +12 -0
  280. package/examples/git-crypt-worktree-guard.sh +12 -0
  281. package/examples/git-filter-repo-guard.sh +56 -0
  282. package/examples/git-history-rewrite-guard.sh +12 -0
  283. package/examples/git-hook-bypass-guard.sh +0 -0
  284. package/examples/git-maintenance-guard.sh +83 -0
  285. package/examples/git-merge-conflict-prevent.sh +0 -0
  286. package/examples/git-message-length-check.sh +0 -0
  287. package/examples/git-message-length.sh +0 -0
  288. package/examples/git-operations-require-approval.sh +68 -14
  289. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  290. package/examples/git-push-blast-radius-guard.sh +218 -0
  291. package/examples/git-remote-guard.sh +24 -3
  292. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  293. package/examples/git-stash-before-checkout.sh +12 -0
  294. package/examples/git-stash-before-danger.sh +0 -0
  295. package/examples/git-submodule-guard.sh +69 -2
  296. package/examples/git-tag-guard.sh +12 -0
  297. package/examples/github-actions-secret-guard.sh +0 -0
  298. package/examples/gitignore-check.sh +0 -0
  299. package/examples/gitops-drift-guard.sh +12 -0
  300. package/examples/go-mod-tidy-warn.sh +1 -0
  301. package/examples/go-vet-after-edit.sh +12 -0
  302. package/examples/goal-iteration-limit-warner.sh +152 -0
  303. package/examples/grep-nul-false-negative-guard.sh +30 -0
  304. package/examples/growthbook-flag-monitor.sh +257 -0
  305. package/examples/hallucination-url-check.sh +1 -1
  306. package/examples/halt-signal-detector.sh +135 -0
  307. package/examples/handoff-on-clear.sh +65 -0
  308. package/examples/hardcoded-ip-guard.sh +1 -0
  309. package/examples/headless-empty-result-guard.sh +0 -0
  310. package/examples/headless-stop-guard.sh +0 -0
  311. package/examples/helm-install-guard.sh +2 -1
  312. package/examples/home-critical-bash-guard.sh +17 -1
  313. package/examples/hook-debug-wrapper.sh +6 -2
  314. package/examples/hook-permission-fixer.sh +0 -0
  315. package/examples/hook-self-disable-detector.sh +99 -0
  316. package/examples/hook-stdout-sanitizer.sh +6 -2
  317. package/examples/hook-tamper-guard.sh +12 -0
  318. package/examples/idle-session-cost-alert.sh +0 -0
  319. package/examples/image-dimension-guard.sh +109 -0
  320. package/examples/image-file-validator.sh +0 -0
  321. package/examples/iteration-quality-degradation-detector.sh +170 -0
  322. package/examples/java-compile-on-edit.sh +1 -1
  323. package/examples/json-syntax-check.sh +0 -0
  324. package/examples/k8s-production-guard.sh +13 -1
  325. package/examples/kill-process-guard.sh +12 -0
  326. package/examples/kubernetes-guard.sh +13 -1
  327. package/examples/laravel-artisan-guard.sh +13 -0
  328. package/examples/large-file-guard.sh +1 -1
  329. package/examples/log-level-guard.sh +0 -0
  330. package/examples/log-truncation-guard.sh +12 -0
  331. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  332. package/examples/loop-detector.sh +12 -0
  333. package/examples/magic-number-warn.sh +1 -0
  334. package/examples/main-branch-warn.sh +12 -0
  335. package/examples/markdown-link-check.sh +0 -0
  336. package/examples/max-concurrent-agents.sh +12 -0
  337. package/examples/max-edit-size-guard.sh +13 -0
  338. package/examples/max-file-count-guard.sh +0 -0
  339. package/examples/max-file-delete-count.sh +0 -0
  340. package/examples/max-function-length.sh +1 -0
  341. package/examples/max-import-count.sh +0 -0
  342. package/examples/max-subagent-count.sh +0 -0
  343. package/examples/mcp-config-freeze.sh +12 -0
  344. package/examples/mcp-config-poisoning-audit.sh +150 -0
  345. package/examples/mcp-data-boundary.sh +1 -1
  346. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  347. package/examples/mcp-orphan-leak-warner.sh +49 -0
  348. package/examples/mcp-permissions-ask-warner.sh +151 -0
  349. package/examples/mcp-routine-approval-detector.sh +154 -0
  350. package/examples/mcp-server-allowlist.sh +12 -0
  351. package/examples/mcp-server-guard.sh +12 -0
  352. package/examples/mcp-startup-bloat-detector.sh +87 -0
  353. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  354. package/examples/mcp-tool-audit-log.sh +0 -0
  355. package/examples/mcp-tool-guard.sh +101 -1
  356. package/examples/mcp-warmup-wait.sh +0 -0
  357. package/examples/memory-chain-audit.sh +56 -0
  358. package/examples/memory-orphan-detector.sh +188 -0
  359. package/examples/memory-write-guard.sh +99 -17
  360. package/examples/migration-verify-guard.sh +12 -0
  361. package/examples/model-swap-suggester.sh +177 -0
  362. package/examples/model-version-alert.sh +5 -1
  363. package/examples/model-version-lock.sh +63 -0
  364. package/examples/move-delete-sequence-guard.sh +33 -2
  365. package/examples/multi-file-plan-routing-gate.sh +192 -0
  366. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  367. package/examples/multi-window-auth-drift-detector.sh +183 -0
  368. package/examples/multiline-command-approver.sh +161 -23
  369. package/examples/nested-background-agent-guard.sh +109 -0
  370. package/examples/nested-spawn-inflight-guard.sh +178 -0
  371. package/examples/network-exfil-guard.sh +12 -0
  372. package/examples/network-guard.sh +12 -0
  373. package/examples/network-interface-guard.sh +12 -0
  374. package/examples/nextjs-env-guard.sh +1 -1
  375. package/examples/no-absolute-import.sh +0 -0
  376. package/examples/no-alert-confirm-prompt.sh +0 -0
  377. package/examples/no-anonymous-default-export.sh +0 -0
  378. package/examples/no-any-type.sh +0 -0
  379. package/examples/no-any-typescript.sh +1 -0
  380. package/examples/no-ask-human.sh +12 -0
  381. package/examples/no-assignment-in-condition.sh +0 -0
  382. package/examples/no-base64-exfil.sh +12 -0
  383. package/examples/no-callback-hell.sh +0 -0
  384. package/examples/no-circular-dependency.sh +0 -0
  385. package/examples/no-cleartext-storage.sh +0 -0
  386. package/examples/no-commented-code.sh +0 -0
  387. package/examples/no-commit-fixup.sh +0 -0
  388. package/examples/no-console-assert.sh +0 -0
  389. package/examples/no-console-error-swallow.sh +0 -0
  390. package/examples/no-console-in-prod.sh +0 -0
  391. package/examples/no-console-log-commit.sh +12 -0
  392. package/examples/no-console-log.sh +0 -0
  393. package/examples/no-console-time.sh +0 -0
  394. package/examples/no-cors-wildcard.sh +4 -1
  395. package/examples/no-curl-upload.sh +0 -0
  396. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  397. package/examples/no-dangling-await.sh +1 -0
  398. package/examples/no-debug-commit.sh +12 -0
  399. package/examples/no-debug-in-commit.sh +0 -0
  400. package/examples/no-deep-nesting.sh +0 -0
  401. package/examples/no-deep-relative-import.sh +1 -0
  402. package/examples/no-default-credentials.sh +0 -0
  403. package/examples/no-deploy-friday.sh +13 -1
  404. package/examples/no-disabled-test.sh +0 -0
  405. package/examples/no-document-write.sh +0 -0
  406. package/examples/no-empty-function.sh +0 -0
  407. package/examples/no-eval-in-template.sh +0 -0
  408. package/examples/no-eval-template.sh +3 -1
  409. package/examples/no-eval.sh +0 -0
  410. package/examples/no-exec-user-input.sh +0 -0
  411. package/examples/no-fixme-ship.sh +12 -0
  412. package/examples/no-floating-promises.sh +0 -0
  413. package/examples/no-force-flag.sh +22 -5
  414. package/examples/no-force-install.sh +0 -0
  415. package/examples/no-git-amend.sh +12 -0
  416. package/examples/no-git-rebase-public.sh +0 -0
  417. package/examples/no-global-install.sh +12 -0
  418. package/examples/no-global-state.sh +0 -0
  419. package/examples/no-hardcoded-port.sh +1 -0
  420. package/examples/no-hardcoded-url.sh +0 -0
  421. package/examples/no-helmet-missing.sh +0 -0
  422. package/examples/no-http-url.sh +1 -0
  423. package/examples/no-http-without-https.sh +0 -0
  424. package/examples/no-inline-style.sh +0 -0
  425. package/examples/no-inline-styles.sh +1 -0
  426. package/examples/no-innerhtml.sh +0 -0
  427. package/examples/no-install-global.sh +12 -0
  428. package/examples/no-jwt-in-url.sh +0 -0
  429. package/examples/no-large-commit.sh +0 -0
  430. package/examples/no-localhost-expose.sh +0 -0
  431. package/examples/no-magic-number.sh +0 -0
  432. package/examples/no-md5-sha1.sh +0 -0
  433. package/examples/no-mixed-line-endings.sh +8 -1
  434. package/examples/no-mutation-in-reducer.sh +0 -0
  435. package/examples/no-nested-ternary.sh +0 -0
  436. package/examples/no-network-exfil.sh +0 -0
  437. package/examples/no-open-redirect.sh +0 -0
  438. package/examples/no-output-truncation.sh +12 -0
  439. package/examples/no-package-downgrade.sh +0 -0
  440. package/examples/no-package-lock-edit.sh +12 -0
  441. package/examples/no-path-join-user-input.sh +0 -0
  442. package/examples/no-port-bind.sh +0 -0
  443. package/examples/no-process-exit.sh +0 -0
  444. package/examples/no-prototype-pollution.sh +0 -0
  445. package/examples/no-push-without-ci.sh +0 -0
  446. package/examples/no-push-without-tests.sh +12 -0
  447. package/examples/no-raw-password-in-url.sh +0 -0
  448. package/examples/no-root-user-docker.sh +1 -0
  449. package/examples/no-root-write.sh +12 -0
  450. package/examples/no-secrets-in-args.sh +4 -1
  451. package/examples/no-secrets-in-logs.sh +0 -0
  452. package/examples/no-sensitive-log.sh +0 -0
  453. package/examples/no-sleep-in-hooks.sh +0 -0
  454. package/examples/no-star-import-python.sh +1 -0
  455. package/examples/no-string-concat-sql.sh +0 -0
  456. package/examples/no-sudo-guard.sh +12 -0
  457. package/examples/no-sync-fs.sh +0 -0
  458. package/examples/no-todo-in-merge.sh +0 -0
  459. package/examples/no-todo-in-production.sh +1 -0
  460. package/examples/no-todo-without-issue.sh +0 -0
  461. package/examples/no-unused-import.sh +0 -0
  462. package/examples/no-var-keyword.sh +0 -0
  463. package/examples/no-verify-blocker.sh +12 -0
  464. package/examples/no-wget-piped-bash.sh +12 -0
  465. package/examples/no-wildcard-cors.sh +0 -0
  466. package/examples/no-wildcard-delete.sh +0 -0
  467. package/examples/no-wildcard-import.sh +0 -0
  468. package/examples/no-with-statement.sh +0 -0
  469. package/examples/no-write-outside-src.sh +0 -0
  470. package/examples/no-xml-external-entity.sh +0 -0
  471. package/examples/non-english-quality-warner.sh +156 -0
  472. package/examples/notify-waiting.sh +1 -1
  473. package/examples/npm-audit-warn.sh +0 -0
  474. package/examples/npm-global-install-guard.sh +12 -0
  475. package/examples/npm-publish-guard.sh +12 -0
  476. package/examples/npm-script-injection.sh +0 -0
  477. package/examples/npm-supply-chain-guard.sh +0 -0
  478. package/examples/nuxt-config-guard.sh +1 -0
  479. package/examples/oauth-refresh-monitor.sh +210 -0
  480. package/examples/opus-degradation-tracker.sh +187 -0
  481. package/examples/opus48-routine-task-warning.sh +196 -0
  482. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  483. package/examples/output-credential-scan.sh +1 -1
  484. package/examples/output-secret-mask.sh +31 -9
  485. package/examples/output-token-spike-detector.sh +145 -0
  486. package/examples/package-json-guard.sh +12 -0
  487. package/examples/package-lock-frozen.sh +12 -0
  488. package/examples/parallel-batch-size-limiter.sh +121 -0
  489. package/examples/parallel-cascade-detector.sh +116 -0
  490. package/examples/partial-view-claim-arrest.sh +174 -0
  491. package/examples/path-deny-bash-guard.sh +12 -0
  492. package/examples/path-traversal-guard.sh +12 -0
  493. package/examples/per-prompt-token-cap.sh +124 -0
  494. package/examples/permission-audit-log.sh +1 -1
  495. package/examples/permission-denial-enforcer.sh +12 -0
  496. package/examples/permission-entry-validator.sh +0 -0
  497. package/examples/persisted-1m-model-advisor.sh +88 -0
  498. package/examples/php-lint-on-edit.sh +1 -1
  499. package/examples/pii-upload-guard.sh +12 -0
  500. package/examples/pip-publish-guard.sh +13 -0
  501. package/examples/pip-requirements-guard.sh +12 -0
  502. package/examples/pip-venv-required.sh +12 -0
  503. package/examples/plan-mode-edit-guard.sh +12 -0
  504. package/examples/plan-mode-enforcer.sh +12 -0
  505. package/examples/plan-mode-strict-guard.sh +12 -0
  506. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  507. package/examples/plugin-process-cleanup.sh +0 -0
  508. package/examples/polyglot-rm-guard.sh +12 -0
  509. package/examples/post-compact-safety.sh +12 -0
  510. package/examples/post-edit-disk-verify.sh +152 -0
  511. package/examples/powershell-remove-item-guard.sh +85 -0
  512. package/examples/pr-description-check.sh +0 -0
  513. package/examples/pr-duplicate-guard.sh +13 -0
  514. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  515. package/examples/pre-compact-knowledge-save.sh +0 -0
  516. package/examples/pre-compact-transcript-backup.sh +0 -0
  517. package/examples/pre-execution-claim-detector.sh +179 -0
  518. package/examples/prefer-builtin-tools.sh +10 -1
  519. package/examples/prefer-const.sh +0 -0
  520. package/examples/prefer-dedicated-tools.sh +12 -0
  521. package/examples/prefer-optional-chaining.sh +0 -0
  522. package/examples/prisma-migrate-guard.sh +24 -7
  523. package/examples/production-port-kill-guard.sh +12 -0
  524. package/examples/prompt-injection-guard.sh +2 -1
  525. package/examples/prompt-usage-logger.sh +0 -0
  526. package/examples/protect-claudemd.sh +12 -0
  527. package/examples/protect-dotfiles.sh +12 -0
  528. package/examples/proxy-capture-suggester.sh +159 -0
  529. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  530. package/examples/public-repo-push-guard.sh +12 -0
  531. package/examples/push-requires-test-pass-record.sh +0 -0
  532. package/examples/push-requires-test-pass.sh +12 -0
  533. package/examples/quota-anomaly-detector.sh +173 -0
  534. package/examples/quota-reset-audit.sh +58 -0
  535. package/examples/quoted-flag-approver.sh +99 -10
  536. package/examples/rails-migration-guard.sh +12 -0
  537. package/examples/rate-limit-guard.sh +0 -0
  538. package/examples/read-all-files-enforcer.sh +0 -0
  539. package/examples/read-budget-guard.sh +12 -0
  540. package/examples/read-loop-detector.sh +59 -0
  541. package/examples/read-once-guard.sh +96 -0
  542. package/examples/read-only-mode.sh +12 -0
  543. package/examples/readme-exists-check.sh +0 -0
  544. package/examples/record-read-coverage.sh +73 -0
  545. package/examples/redirect-fragment-warner.sh +149 -0
  546. package/examples/redis-flushall-guard.sh +13 -0
  547. package/examples/redundant-read-blocker.sh +132 -0
  548. package/examples/refusal-arrest-gate.sh +248 -0
  549. package/examples/registry-publish-guard.sh +13 -1
  550. package/examples/remote-control-billing-classifier.sh +135 -0
  551. package/examples/replace-all-guard.sh +12 -0
  552. package/examples/repo-visibility-guard.sh +12 -0
  553. package/examples/reroute-after-block-guard.sh +150 -0
  554. package/examples/response-budget-guard.sh +0 -0
  555. package/examples/resume-drift-watcher.sh +57 -0
  556. package/examples/rg-replace-flag-detector.sh +125 -0
  557. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  558. package/examples/ripgrep-permission-fix.sh +0 -0
  559. package/examples/rm-safety-net.sh +151 -8
  560. package/examples/role-tool-guard.sh +12 -0
  561. package/examples/route-handler-emptiness-gate.sh +324 -0
  562. package/examples/ruby-lint-on-edit.sh +1 -1
  563. package/examples/runtime-binary-change-detector.sh +102 -0
  564. package/examples/same-command-repeat-detector.sh +196 -0
  565. package/examples/same-correction-arrest.sh +169 -0
  566. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  567. package/examples/sandbox-relative-path-audit.sh +83 -25
  568. package/examples/sandbox-write-verify.sh +12 -0
  569. package/examples/schema-migration-guard.sh +0 -0
  570. package/examples/scope-expansion-receipt.sh +178 -0
  571. package/examples/scope-guard.sh +88 -9
  572. package/examples/secret-file-read-guard.sh +12 -0
  573. package/examples/secret-file-write-guard.sh +150 -0
  574. package/examples/self-modify-bypass-guard.sh +0 -0
  575. package/examples/sensitive-file-read-guard.sh +23 -3
  576. package/examples/sensitive-log-guard.sh +1 -0
  577. package/examples/server-side-prompt-injection-detector.sh +69 -0
  578. package/examples/session-agent-cost-limiter.sh +12 -0
  579. package/examples/session-backup-on-start.sh +1 -1
  580. package/examples/session-cost-alert.sh +12 -0
  581. package/examples/session-drift-guard.sh +12 -0
  582. package/examples/session-duration-guard.sh +25 -2
  583. package/examples/session-end-logger.sh +0 -0
  584. package/examples/session-health-monitor.sh +0 -0
  585. package/examples/session-index-repair.sh +1 -1
  586. package/examples/session-memory-watchdog.sh +1 -0
  587. package/examples/session-permission-reset-guard.sh +12 -0
  588. package/examples/session-persistence-verifier.sh +93 -0
  589. package/examples/session-plugin-pin-watch.sh +68 -0
  590. package/examples/session-rate-monitor.sh +176 -0
  591. package/examples/session-resume-env-fix.sh +0 -0
  592. package/examples/session-start-quota-status.sh +193 -0
  593. package/examples/session-start-safety-check.sh +55 -3
  594. package/examples/session-state-saver.sh +0 -0
  595. package/examples/session-summary-stop.sh +1 -1
  596. package/examples/session-summary.sh +0 -0
  597. package/examples/session-token-counter.sh +1 -1
  598. package/examples/settings-hooks-key-restorer.sh +99 -0
  599. package/examples/settings-json-health-check.sh +57 -0
  600. package/examples/settings-json-model-guard.sh +0 -0
  601. package/examples/settings-regression-tester.sh +188 -0
  602. package/examples/shell-config-truncation-guard.sh +12 -0
  603. package/examples/shell-wrapper-guard.sh +12 -0
  604. package/examples/skill-cumulative-size-detector.sh +104 -0
  605. package/examples/skill-description-drop-detector.sh +148 -0
  606. package/examples/skill-gate.sh +0 -0
  607. package/examples/skill-truncation-detector.sh +154 -0
  608. package/examples/skills-context-recorder.sh +167 -0
  609. package/examples/skills-load-verifier.sh +96 -0
  610. package/examples/skills-settings-validator.sh +139 -0
  611. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  612. package/examples/spec-file-scope-guard.sh +12 -0
  613. package/examples/spring-profile-guard.sh +1 -0
  614. package/examples/spurious-malformed-notice-detector.sh +247 -0
  615. package/examples/sql-bulk-delete-warn.sh +88 -0
  616. package/examples/sql-injection-detect.sh +0 -0
  617. package/examples/ssh-key-protect.sh +12 -0
  618. package/examples/staged-secret-scan.sh +22 -1
  619. package/examples/stale-temp-settings-detector.sh +86 -0
  620. package/examples/standing-rule-session-surfacer.sh +137 -0
  621. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  622. package/examples/stop-transcript-write-health.sh +64 -0
  623. package/examples/strict-allowlist.sh +57 -15
  624. package/examples/strip-coauthored-by.sh +50 -10
  625. package/examples/subagent-blast-radius-guard.sh +184 -0
  626. package/examples/subagent-boundary-precheck.sh +126 -0
  627. package/examples/subagent-budget-guard.sh +12 -0
  628. package/examples/subagent-claudemd-inject.sh +0 -0
  629. package/examples/subagent-closure-verify-gate.sh +164 -0
  630. package/examples/subagent-destructive-git-guard.sh +120 -0
  631. package/examples/subagent-error-detector.sh +0 -0
  632. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  633. package/examples/subagent-identity-leak-guard.sh +102 -0
  634. package/examples/subagent-identity-reassertion.sh +51 -0
  635. package/examples/subagent-inheritance-tester.sh +179 -0
  636. package/examples/subagent-permission-mode-guard.sh +110 -0
  637. package/examples/subagent-scope-guard.sh +12 -0
  638. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  639. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  640. package/examples/subagent-tool-call-limiter.sh +87 -15
  641. package/examples/subcommand-chain-guard.sh +12 -0
  642. package/examples/subscription-api-billing-warner.sh +160 -0
  643. package/examples/subscription-bypass-detector.sh +152 -0
  644. package/examples/svelte-lint-on-edit.sh +1 -0
  645. package/examples/swift-build-on-edit.sh +1 -1
  646. package/examples/symlink-guard.sh +27 -2
  647. package/examples/symlink-protect.sh +1 -0
  648. package/examples/system-dir-protection-guard.sh +73 -8
  649. package/examples/system-message-workaround.sh +38 -13
  650. package/examples/system-package-guard.sh +12 -0
  651. package/examples/systemd-service-guard.sh +12 -0
  652. package/examples/task-integrity-guard.sh +12 -0
  653. package/examples/temp-file-cleanup.sh +1 -1
  654. package/examples/temporal-suggestion-detector.sh +135 -0
  655. package/examples/terraform-guard.sh +27 -6
  656. package/examples/test-after-edit.sh +1 -1
  657. package/examples/test-before-push.sh +12 -0
  658. package/examples/test-coverage-reminder.sh +24 -1
  659. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  660. package/examples/timezone-guard.sh +0 -0
  661. package/examples/tmp-output-size-guard.sh +0 -0
  662. package/examples/todo-check.sh +1 -1
  663. package/examples/token-budget-guard.sh +12 -0
  664. package/examples/token-budget-per-task.sh +12 -0
  665. package/examples/token-usage-tracker.sh +7 -1
  666. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  667. package/examples/tokenizer-ratio-alert.sh +104 -0
  668. package/examples/tool-call-rate-limiter.sh +0 -0
  669. package/examples/tool-result-correlation-checker.sh +167 -0
  670. package/examples/tool-result-size-guard.sh +132 -0
  671. package/examples/tool-retry-budget-guard.sh +12 -0
  672. package/examples/transcript-contamination-detector.sh +138 -0
  673. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  674. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  675. package/examples/unbounded-output-guard.sh +94 -0
  676. package/examples/uncommitted-changes-stop.sh +1 -0
  677. package/examples/uncommitted-discard-guard.sh +23 -5
  678. package/examples/uncommitted-work-guard.sh +12 -0
  679. package/examples/usage-warn.sh +0 -0
  680. package/examples/user-account-guard.sh +12 -0
  681. package/examples/userprompt-submit-receipt.sh +123 -0
  682. package/examples/variable-expansion-guard.sh +12 -0
  683. package/examples/verify-after-publish-reminder.sh +93 -0
  684. package/examples/verify-before-commit.sh +12 -0
  685. package/examples/version-bump-detector.sh +156 -0
  686. package/examples/version-regression-warner.sh +144 -0
  687. package/examples/vue-lint-on-edit.sh +1 -0
  688. package/examples/warn-cron-cost-trap.sh +173 -0
  689. package/examples/webfetch-runaway-guard.sh +89 -0
  690. package/examples/wellness-break-reminder.sh +118 -0
  691. package/examples/windows-destructive-command-guard.sh +177 -0
  692. package/examples/windows-path-guard.sh +12 -0
  693. package/examples/windows-python-stub-detector.sh +63 -0
  694. package/examples/work-hours-guard.sh +12 -0
  695. package/examples/working-directory-fence.sh +12 -0
  696. package/examples/workspace-lease-guard.sh +205 -0
  697. package/examples/worktree-create-log.sh +1 -0
  698. package/examples/worktree-delete-guard.sh +12 -0
  699. package/examples/worktree-edit-boundary-guard.sh +127 -0
  700. package/examples/worktree-escape-write-guard.sh +114 -0
  701. package/examples/worktree-hook-linker.sh +0 -0
  702. package/examples/worktree-hooks-path-fix.sh +111 -0
  703. package/examples/worktree-parent-write-guard.sh +43 -0
  704. package/examples/worktree-project-unify.sh +2 -1
  705. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  706. package/examples/worktree-unmerged-guard.sh +7 -1
  707. package/examples/write-byte-integrity-verifier.sh +190 -0
  708. package/examples/write-empty-content-guard.sh +67 -0
  709. package/examples/write-nul-corruption-detector.sh +61 -0
  710. package/examples/write-overwrite-confirm.sh +160 -14
  711. package/examples/write-secret-guard.sh +27 -5
  712. package/examples/write-shrink-guard.sh +12 -0
  713. package/examples/write-test-ratio.sh +0 -0
  714. package/examples/wsl-host-disk-space-guard.sh +97 -0
  715. package/examples/xml-format-leak-detector.sh +266 -0
  716. package/examples/yaml-syntax-check.sh +12 -0
  717. package/hooks/hooks.json +6 -6
  718. package/index.mjs +1699 -183
  719. package/mission.md +2 -0
  720. package/package.json +4 -4
  721. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  722. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  723. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  724. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  725. package/scripts/agents-md-sync-setup.sh +156 -0
  726. package/scripts/autonomy-blocked-summary.sh +148 -0
  727. package/scripts/build-search-index.py +43 -0
  728. package/scripts/build-sitemap.py +119 -0
  729. package/scripts/cc-doctor.sh +192 -0
  730. package/scripts/check-hook-event-names.py +127 -0
  731. package/scripts/check-misfire-instrument.sh +64 -0
  732. package/scripts/claim-verify-audit.sh +467 -0
  733. package/scripts/cowork-claudemd-helper.sh +136 -0
  734. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  735. package/scripts/measure-heredoc-shapes.sh +67 -0
  736. package/scripts/measure-literal-match-misfire.sh +110 -0
  737. package/scripts/probe-scope-guard-branches.sh +48 -0
  738. package/scripts/probe-skip-line-both-ways.sh +65 -0
  739. package/scripts/receipts-aggregate.py +199 -0
  740. package/scripts/session-forensic-audit.py +360 -0
  741. package/scripts.json +9 -9
  742. package/scripts.json.bak-2026-07-27-find +13 -0
  743. package/skills/safety-setup/SKILL.md +5 -5
  744. package/tests/approve-side-remaining-two.test.sh +129 -0
  745. package/tests/approver-list-granularity.test.sh +145 -0
  746. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  747. package/tests/audit-ci-gate.test.sh +87 -0
  748. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  749. package/tests/audit-fail-open-parse.test.sh +100 -0
  750. package/tests/auto-approve-compound-tail.test.sh +194 -0
  751. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  752. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  753. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  754. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  755. package/tests/blindspots-cross-layer.test.sh +177 -0
  756. package/tests/block-database-wipe.test.sh +64 -0
  757. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  758. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  759. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  760. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  761. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  762. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  763. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  764. package/tests/destructive-guard-every-operand.test.sh +100 -0
  765. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  766. package/tests/destructive-guard-flag-order.test.sh +106 -0
  767. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  768. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  769. package/tests/destructive-guard-separators.test.sh +105 -0
  770. package/tests/destructive-guard-variable-target.test.sh +98 -0
  771. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  772. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  773. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  774. package/tests/example-guards-wrapped-command.test.sh +169 -0
  775. package/tests/file-edit-backup.test.sh +93 -0
  776. package/tests/git-filter-repo-guard.test.sh +60 -0
  777. package/tests/git-global-options-bypass.test.sh +141 -0
  778. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  779. package/tests/git-maintenance-guard.test.sh +83 -0
  780. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  781. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  782. package/tests/git-submodule-guard.test.sh +50 -0
  783. package/tests/grep-pcre-portability.test.sh +155 -0
  784. package/tests/hook-registration-matches-input.test.sh +73 -0
  785. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  786. package/tests/install-does-not-claim-protection.test.sh +110 -0
  787. package/tests/install-example-standalone-tools.test.sh +139 -0
  788. package/tests/line-continuation-bypass.test.sh +114 -0
  789. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  790. package/tests/nested-background-agent-guard.test.sh +58 -0
  791. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  792. package/tests/option-eating-grep-patterns.test.sh +130 -0
  793. package/tests/outdated-core-guards.test.sh +134 -0
  794. package/tests/outdated-report.test.sh +155 -0
  795. package/tests/output-secret-mask-warns.test.sh +73 -0
  796. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  797. package/tests/plugins-word-order.test.sh +126 -0
  798. package/tests/powershell-remove-item-guard.test.sh +85 -0
  799. package/tests/project-dir-naming.test.sh +103 -0
  800. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  801. package/tests/reroute-after-block-guard.test.sh +104 -0
  802. package/tests/secret-guard-documented-promises.test.sh +97 -0
  803. package/tests/session-plugin-pin-watch.test.sh +45 -0
  804. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  805. package/tests/shield-no-silent-adoption.test.py +110 -0
  806. package/tests/shield-no-silent-adoption.test.sh +46 -0
  807. package/tests/stop-transcript-write-health.test.sh +46 -0
  808. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  809. package/tests/test-account-billing-log.sh +100 -0
  810. package/tests/test-account-routing-preflight.sh +77 -0
  811. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  812. package/tests/test-agent-view-quota-warn.sh +184 -0
  813. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  814. package/tests/test-agents-md-loader.sh +204 -0
  815. package/tests/test-agents-md-sync-checker.sh +125 -0
  816. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  817. package/tests/test-allowlist.sh +60 -0
  818. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  819. package/tests/test-anthropic-base-url-guard.sh +88 -0
  820. package/tests/test-articulated-scope-capture.sh +139 -0
  821. package/tests/test-attachment-traversal-guard.sh +168 -0
  822. package/tests/test-aup-block-pattern-logger.sh +315 -0
  823. package/tests/test-aup-false-positive-helper.sh +188 -0
  824. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  825. package/tests/test-aup-retry-loop-guard.sh +341 -0
  826. package/tests/test-auth-expiry-reminder.sh +303 -0
  827. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  828. package/tests/test-auth-path-detector.sh +232 -0
  829. package/tests/test-auth-status-checker.sh +233 -0
  830. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  831. package/tests/test-background-cost-launch-guard.sh +62 -0
  832. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  833. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  834. package/tests/test-bash-project-fence.sh +127 -0
  835. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  836. package/tests/test-binary-read-detector.sh +173 -0
  837. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  838. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  839. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  840. package/tests/test-cache-creation-drift-detector.sh +244 -0
  841. package/tests/test-cache-residue-detector.sh +429 -0
  842. package/tests/test-cache-tier-logger.sh +59 -0
  843. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  844. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  845. package/tests/test-claim-verify-detector.sh +222 -0
  846. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  847. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  848. package/tests/test-claude-md-reinjector.sh +173 -0
  849. package/tests/test-claude-md-size-monitor.sh +107 -0
  850. package/tests/test-claude-update-budget-guard.sh +132 -0
  851. package/tests/test-claude-update-smart.sh +91 -0
  852. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  853. package/tests/test-cli-config-pinning-detector.sh +233 -0
  854. package/tests/test-cliff-countdown-advisor.sh +138 -0
  855. package/tests/test-closure-word-verify-gate.sh +158 -0
  856. package/tests/test-commit-all-scope-guard.sh +73 -0
  857. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  858. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  859. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  860. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  861. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  862. package/tests/test-context-length-budget.sh +68 -0
  863. package/tests/test-context-usage-drift-alert.sh +52 -22
  864. package/tests/test-cost-incident-self-audit.sh +94 -0
  865. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  866. package/tests/test-cowork-claudemd-helper.sh +141 -0
  867. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  868. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  869. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  870. package/tests/test-credential-exfil-guard.sh +62 -0
  871. package/tests/test-cron-create-receipt.sh +165 -0
  872. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  873. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  874. package/tests/test-daily-cost-guard.sh +131 -0
  875. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  876. package/tests/test-deployment-readback-gate.sh +92 -0
  877. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  878. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  879. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  880. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  881. package/tests/test-dispatch-receipt.sh +314 -0
  882. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  883. package/tests/test-echo-probe-spam-detector.sh +143 -0
  884. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  885. package/tests/test-ephemeral-container-detector.sh +251 -0
  886. package/tests/test-evidence-claim-gate.sh +291 -0
  887. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  888. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  889. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  890. package/tests/test-fabricated-command-detector.sh +296 -0
  891. package/tests/test-false-disk-full-guard.sh +36 -0
  892. package/tests/test-feature-deprecation-detector.sh +117 -0
  893. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  894. package/tests/test-git-operations-require-approval.sh +53 -0
  895. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  896. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  897. package/tests/test-growthbook-flag-monitor.sh +428 -0
  898. package/tests/test-halt-signal-detector.sh +120 -0
  899. package/tests/test-hook-self-disable-detector.sh +232 -0
  900. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  901. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  902. package/tests/test-marketplace-plugins.sh +193 -0
  903. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  904. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  905. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  906. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  907. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  908. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  909. package/tests/test-memory-chain-audit.sh +59 -0
  910. package/tests/test-memory-orphan-detector.sh +227 -0
  911. package/tests/test-model-swap-suggester.sh +368 -0
  912. package/tests/test-model-version-lock.sh +83 -0
  913. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  914. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  915. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  916. package/tests/test-no-force-flag.sh +49 -0
  917. package/tests/test-non-english-quality-warner.sh +229 -0
  918. package/tests/test-oauth-refresh-monitor.sh +311 -0
  919. package/tests/test-opus-degradation-tracker.sh +274 -0
  920. package/tests/test-opus48-routine-task-warning.sh +201 -0
  921. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  922. package/tests/test-output-token-spike-detector.sh +315 -0
  923. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  924. package/tests/test-parallel-cascade-detector.sh +191 -0
  925. package/tests/test-partial-view-claim-arrest.sh +272 -0
  926. package/tests/test-per-prompt-token-cap.sh +136 -0
  927. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  928. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  929. package/tests/test-post-edit-disk-verify.sh +294 -0
  930. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  931. package/tests/test-pre-execution-claim-detector.sh +366 -0
  932. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  933. package/tests/test-proxy-capture-suggester.sh +214 -0
  934. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  935. package/tests/test-quota-anomaly-detector.sh +321 -0
  936. package/tests/test-quota-reset-audit.sh +81 -0
  937. package/tests/test-read-loop-detector.sh +137 -0
  938. package/tests/test-read-once-guard.sh +85 -0
  939. package/tests/test-receipts-aggregate.sh +143 -0
  940. package/tests/test-redirect-fragment-warner.sh +130 -0
  941. package/tests/test-redundant-read-blocker.sh +155 -0
  942. package/tests/test-refusal-arrest-gate.sh +303 -0
  943. package/tests/test-remote-control-billing-classifier.sh +125 -0
  944. package/tests/test-resume-drift-watcher.sh +65 -0
  945. package/tests/test-rg-replace-flag-detector.sh +175 -0
  946. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  947. package/tests/test-rm-safety-net.sh +115 -0
  948. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  949. package/tests/test-runtime-binary-change-detector.sh +196 -0
  950. package/tests/test-same-command-repeat-detector.sh +165 -0
  951. package/tests/test-same-correction-arrest.sh +165 -0
  952. package/tests/test-scope-expansion-receipt.sh +207 -0
  953. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  954. package/tests/test-session-persistence-verifier.sh +128 -0
  955. package/tests/test-session-rate-monitor.sh +284 -0
  956. package/tests/test-session-start-quota-status.sh +210 -0
  957. package/tests/test-session-start-safety-check.sh +138 -0
  958. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  959. package/tests/test-settings-json-health-check.sh +70 -0
  960. package/tests/test-settings-regression-tester.sh +197 -0
  961. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  962. package/tests/test-skill-description-drop-detector.sh +236 -0
  963. package/tests/test-skill-truncation-detector.sh +263 -0
  964. package/tests/test-skills-context-recorder.sh +329 -0
  965. package/tests/test-skills-load-verifier.sh +184 -0
  966. package/tests/test-skills-settings-validator.sh +242 -0
  967. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  968. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  969. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  970. package/tests/test-ssh-key-protect.sh +81 -0
  971. package/tests/test-stale-temp-settings-detector.sh +161 -0
  972. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  973. package/tests/test-starter-hooks-manifest.sh +96 -0
  974. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  975. package/tests/test-strict-allowlist.sh +72 -0
  976. package/tests/test-subagent-boundary-precheck.sh +137 -0
  977. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  978. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  979. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  980. package/tests/test-subagent-identity-reassertion.sh +61 -0
  981. package/tests/test-subagent-inheritance-tester.sh +319 -0
  982. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  983. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  984. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  985. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  986. package/tests/test-subscription-api-billing-warner.sh +138 -0
  987. package/tests/test-subscription-bypass-detector.sh +255 -0
  988. package/tests/test-temporal-suggestion-detector.sh +183 -0
  989. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  990. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  991. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  992. package/tests/test-tool-result-correlation-checker.sh +264 -0
  993. package/tests/test-tool-result-size-guard.sh +121 -0
  994. package/tests/test-transcript-contamination-detector.sh +264 -0
  995. package/tests/test-trigger-header-parsing.sh +151 -0
  996. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  997. package/tests/test-userprompt-submit-receipt.sh +181 -0
  998. package/tests/test-verify-after-publish-reminder.sh +184 -0
  999. package/tests/test-version-bump-detector.sh +212 -0
  1000. package/tests/test-version-regression-warner.sh +165 -0
  1001. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1002. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1003. package/tests/test-wellness-break-reminder.sh +138 -0
  1004. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1005. package/tests/test-windows-python-stub-detector.sh +146 -0
  1006. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1007. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1008. package/tests/test-xml-format-leak-detector.sh +299 -0
  1009. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1010. package/tests/workspace-lease-guard.test.sh +144 -0
  1011. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1012. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1013. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1014. package/tests/write-empty-content-guard.test.sh +39 -0
  1015. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1016. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1017. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,232 @@
1
+ #!/bin/bash
2
+ # public-artefact-socratic-narrowing.sh — Inject a Socratic-narrowing prompt
3
+ # at the public-artefact emission boundary, asking the agent to re-engage the
4
+ # gradient on decisions in the artefact before it ships.
5
+ #
6
+ # Solves: #60226 (the structural-parent frame) — recognition-without-arrest at
7
+ # the public-artefact emission boundary, as operationalized in @beq00000's
8
+ # clean-state worked example (#60226, 2026-05-19 comment).
9
+ #
10
+ # In that comment, seven instances of recognition-without-arrest surfaced in a
11
+ # single non-drifted session. Three of the seven were caught at the public-
12
+ # artefact emission boundary by the operator's Socratic-narrowing intervention:
13
+ #
14
+ # "The form: not 'is this wrong' (binary question, eliciting binary defence),
15
+ # but 'is this verifiable / already-documented / what-would-actually-need-
16
+ # attention look like' (gradient question, forcing the model to re-engage
17
+ # the rank ordering the original output had flattened). The first form gets
18
+ # defended; the second gets re-decided."
19
+ #
20
+ # The operator-language form is implementable as session discipline today, but
21
+ # the gate fires only when the operator is present and noticing. This hook is
22
+ # the tooling-side form: PreToolUse on the public-artefact emission tools
23
+ # injects a Socratic-narrowing reminder at the boundary so the agent re-engages
24
+ # the gradient regardless of whether the operator is watching this turn.
25
+ #
26
+ # The hook deliberately does not check what the artefact says. Recognition-
27
+ # without-arrest cannot be solved by content classification (that is the
28
+ # failure mode being addressed). The gate's only job is to force one more
29
+ # pass over the artefact with the gradient framing applied. The agent's
30
+ # re-emission is what does the work.
31
+ #
32
+ # Related Issues / Reports:
33
+ # #60226 (@suwayama, 2026-05-18) — recognition-without-arrest framework
34
+ # comment thread → @beq00000 2026-05-19 clean-state worked
35
+ # example with seven instances and the Socratic-narrowing
36
+ # mitigation
37
+ # #60188 (@suwayama) — binary-collapse subhypothesis; the
38
+ # Socratic form re-introduces the gradient
39
+ # #60506 (@zean89, 2026-05-19) — six-day drift across PR-body emissions
40
+ # that survived multiple operator passes
41
+ #
42
+ # TRIGGER: PreToolUse
43
+ # MATCHER: Bash|Write|Edit
44
+ #
45
+ # HOW IT WORKS:
46
+ # 1. Reads PreToolUse input via stdin.
47
+ # 2. For Bash, matches the command against public-artefact emission patterns
48
+ # (gh pr create/edit, gh issue create/comment, gh release create,
49
+ # git commit -m '<long>', git tag -a, etc.).
50
+ # 3. For Write/Edit, matches the target path against public-artefact paths
51
+ # (.github/, CHANGELOG.md, README*.md, docs/, sales-page*.md, etc.).
52
+ # 4. If the artefact body / file content is below a length threshold
53
+ # (default 200 chars), allows it through silently — short artefacts are
54
+ # not where the binary-collapse failure surfaces.
55
+ # 5. Computes a content hash of the artefact body. If the same hash was
56
+ # seen within the cache window (default 600s), allows through — the
57
+ # agent has already re-engaged the gradient on this content.
58
+ # 6. Otherwise emits a Socratic-narrowing system-reminder via stderr and
59
+ # exits 2, blocking the emission until the agent re-emits.
60
+ #
61
+ # The hash-based cache is what makes the gate non-infinite. After the agent
62
+ # re-emits with the gradient applied (different content → new hash → re-fired
63
+ # once), or after deliberately re-emitting the same content (operator-
64
+ # approved → hash matches → passes through), the artefact ships.
65
+ #
66
+ # CONFIGURATION (environment variables):
67
+ # CC_SOCRATIC_DISABLE set to "1" to disable the gate entirely
68
+ # CC_SOCRATIC_STATE_DIR default /tmp/cc-socratic-cache
69
+ # CC_SOCRATIC_BODY_MIN_CHARS default 200 — artefacts shorter than this
70
+ # are not gated
71
+ # CC_SOCRATIC_CACHE_TTL_SECONDS default 600 — how long a hash counts as
72
+ # "already re-engaged"
73
+ # CC_SOCRATIC_BASH_PATTERNS default built-in — regex of Bash commands
74
+ # CC_SOCRATIC_FILE_PATTERNS default built-in — regex of file paths
75
+ #
76
+ # USAGE (settings.json):
77
+ # {
78
+ # "hooks": {
79
+ # "PreToolUse": [{
80
+ # "matcher": "Bash|Write|Edit",
81
+ # "hooks": [{
82
+ # "type": "command",
83
+ # "command": "~/.claude/hooks/public-artefact-socratic-narrowing.sh"
84
+ # }]
85
+ # }]
86
+ # }
87
+ # }
88
+
89
+ set -uo pipefail
90
+
91
+ # Without jq, the parse below silently yields empty and this hook stops
92
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
93
+ # here: blocking would halt every tool call, and exiting 0 would change
94
+ # the behaviour of guards that do not depend on the parsed value.
95
+ if ! command -v jq >/dev/null 2>&1; then
96
+ _nojq_warned="/tmp/cc-nojq-warned-public-artefact-socratic-narrowing-$PPID"
97
+ [ -f "$_nojq_warned" ] || {
98
+ echo "WARNING [public-artefact-socratic-narrowing]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
99
+ : > "$_nojq_warned"
100
+ }
101
+ fi
102
+
103
+ [ "${CC_SOCRATIC_DISABLE:-0}" = "1" ] && exit 0
104
+
105
+ # OPT-IN: this gate blocks every public-artefact emission (commits, PRs, docs
106
+ # edits) on first pass, which is high friction as a default. It is therefore
107
+ # off unless explicitly enabled. Set CC_SOCRATIC_ENABLE=1 to turn it on.
108
+ [ "${CC_SOCRATIC_ENABLE:-0}" = "1" ] || exit 0
109
+
110
+ INPUT=$(cat 2>/dev/null || true)
111
+ [ -z "$INPUT" ] && exit 0
112
+
113
+ STATE_DIR="${CC_SOCRATIC_STATE_DIR:-/tmp/cc-socratic-cache}"
114
+ BODY_MIN_CHARS="${CC_SOCRATIC_BODY_MIN_CHARS:-200}"
115
+ CACHE_TTL="${CC_SOCRATIC_CACHE_TTL_SECONDS:-600}"
116
+
117
+ DEFAULT_BASH_PATTERNS='gh[[:space:]]+pr[[:space:]]+(create|edit)|gh[[:space:]]+issue[[:space:]]+(create|comment)|gh[[:space:]]+release[[:space:]]+create|gh[[:space:]]+gist[[:space:]]+create|git[[:space:]]+commit[[:space:]]+.*-m|git[[:space:]]+tag[[:space:]]+-a|git[[:space:]]+notes[[:space:]]+add'
118
+ DEFAULT_FILE_PATTERNS='(^|/)\.github/|(^|/)CHANGELOG(\.[a-z]+)?|(^|/)README[^/]*$|(^|/)docs?/|(^|/)sales-page|(^|/)launch-|(^|/)RELEASE|(^|/)NOTICE|(^|/)CITATION'
119
+
120
+ BASH_PATTERNS="${CC_SOCRATIC_BASH_PATTERNS:-$DEFAULT_BASH_PATTERNS}"
121
+ FILE_PATTERNS="${CC_SOCRATIC_FILE_PATTERNS:-$DEFAULT_FILE_PATTERNS}"
122
+
123
+ mkdir -p "$STATE_DIR" 2>/dev/null || true
124
+
125
+ # Extract tool name and input from the PreToolUse payload
126
+ TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // .tool // empty' 2>/dev/null)
127
+ [ -z "$TOOL_NAME" ] && exit 0
128
+
129
+ ARTEFACT_BODY=""
130
+ ARTEFACT_KIND=""
131
+
132
+ case "$TOOL_NAME" in
133
+ Bash)
134
+ CMD=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
135
+ [ -z "$CMD" ] && exit 0
136
+ # Does the command match a public-artefact emission pattern?
137
+ printf '%s' "$CMD" | grep -Eiq "$BASH_PATTERNS" || exit 0
138
+ ARTEFACT_BODY="$CMD"
139
+ ARTEFACT_KIND="bash-command"
140
+ ;;
141
+ Write)
142
+ FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
143
+ [ -z "$FILE_PATH" ] && exit 0
144
+ printf '%s' "$FILE_PATH" | grep -Eiq "$FILE_PATTERNS" || exit 0
145
+ ARTEFACT_BODY=$(printf '%s' "$INPUT" | jq -r '.tool_input.content // empty' 2>/dev/null)
146
+ ARTEFACT_KIND="file-write:$FILE_PATH"
147
+ ;;
148
+ Edit)
149
+ FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
150
+ [ -z "$FILE_PATH" ] && exit 0
151
+ printf '%s' "$FILE_PATH" | grep -Eiq "$FILE_PATTERNS" || exit 0
152
+ ARTEFACT_BODY=$(printf '%s' "$INPUT" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
153
+ ARTEFACT_KIND="file-edit:$FILE_PATH"
154
+ ;;
155
+ *)
156
+ exit 0
157
+ ;;
158
+ esac
159
+
160
+ # Below threshold → not where the failure surfaces
161
+ BODY_LEN=${#ARTEFACT_BODY}
162
+ if [ "$BODY_LEN" -lt "$BODY_MIN_CHARS" ]; then
163
+ exit 0
164
+ fi
165
+
166
+ # Hash the artefact body. If we have seen this hash recently, the agent has
167
+ # already had one Socratic-narrowing pass on it — allow through.
168
+ HASH=$(printf '%s' "$ARTEFACT_BODY" | sha256sum 2>/dev/null | awk '{print $1}')
169
+ [ -z "$HASH" ] && exit 0
170
+
171
+ CACHE_FILE="$STATE_DIR/$HASH"
172
+ NOW=$(date +%s)
173
+
174
+ if [ -f "$CACHE_FILE" ]; then
175
+ CACHED_AT=$(cat "$CACHE_FILE" 2>/dev/null || echo 0)
176
+ AGE=$((NOW - CACHED_AT))
177
+ if [ "$AGE" -lt "$CACHE_TTL" ]; then
178
+ # Same content within window → agent has re-engaged → ship it
179
+ exit 0
180
+ fi
181
+ fi
182
+
183
+ # Record the hash so the re-emission passes through
184
+ echo "$NOW" > "$CACHE_FILE"
185
+
186
+ # Best-effort cache eviction: drop entries older than 24h
187
+ find "$STATE_DIR" -type f -mmin +1440 -delete 2>/dev/null || true
188
+
189
+ # Emit the Socratic-narrowing reminder and block the emission once
190
+ cat >&2 <<EOF
191
+ <system-reminder>
192
+ PUBLIC-ARTEFACT EMISSION BOUNDARY — about to emit $ARTEFACT_KIND
193
+ ($BODY_LEN chars). This is the boundary at which three of seven instances of
194
+ recognition-without-arrest surfaced in @beq00000's clean-state worked example
195
+ on #60226 (2026-05-19).
196
+
197
+ Before this artefact ships, re-engage the gradient on each decision in it.
198
+ The Socratic-narrowing form (per @beq00000) is the one that works:
199
+
200
+ Not "is any of this wrong?" — that question elicits binary defence and
201
+ the model defends the artefact as emitted.
202
+
203
+ Instead, ask of each list / each claim / each register choice in the
204
+ artefact:
205
+ (a) What is the gradient this decision sits on?
206
+ e.g. item-substantiveness, public-appropriateness, verifiable-vs-
207
+ speculative, novel-vs-already-documented, gradient-flag-quality.
208
+ (b) Which items in the artefact collapse into the substantive end of
209
+ the gradient on second-pass review? Which collapse into the trivial
210
+ end?
211
+ (c) Reproduce the artefact with the gradient applied — keep what
212
+ survives, drop or rephrase what does not.
213
+
214
+ Then re-emit. If the re-emitted artefact is structurally different from this
215
+ one, that is the gate working. If the re-emitted artefact is byte-identical
216
+ to this one and you have considered the gradient and stand by every decision,
217
+ re-running the same command within ${CACHE_TTL}s will ship it (the hash
218
+ matches and the gate passes through).
219
+
220
+ To disable this gate intentionally (for low-stakes commits, automated tooling,
221
+ non-public artefacts mis-classified as public), set CC_SOCRATIC_DISABLE=1 in
222
+ your environment, or refine CC_SOCRATIC_BASH_PATTERNS / CC_SOCRATIC_FILE_PATTERNS
223
+ to exclude the false-positive class.
224
+
225
+ Underlying mechanism (per @suwayama #60188): binary-collapse of decisions
226
+ that should sit on a gradient. The reminder above is the operator-language
227
+ intervention promoted to a tooling-side gate; the gradient framing is what
228
+ makes it work, not the blocking.
229
+ </system-reminder>
230
+ EOF
231
+
232
+ exit 2
@@ -17,6 +17,18 @@
17
17
 
18
18
  set -uo pipefail
19
19
 
20
+ # Without jq, the parse below silently yields empty and this hook stops
21
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
22
+ # here: blocking would halt every tool call, and exiting 0 would change
23
+ # the behaviour of guards that do not depend on the parsed value.
24
+ if ! command -v jq >/dev/null 2>&1; then
25
+ _nojq_warned="/tmp/cc-nojq-warned-public-repo-push-guard-$PPID"
26
+ [ -f "$_nojq_warned" ] || {
27
+ echo "WARNING [public-repo-push-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
28
+ : > "$_nojq_warned"
29
+ }
30
+ fi
31
+
20
32
  INPUT=$(cat)
21
33
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
22
34
  [ -z "$COMMAND" ] && exit 0
File without changes
@@ -27,6 +27,18 @@
27
27
  #
28
28
  # TRIGGER: PreToolUse MATCHER: "Bash"
29
29
 
30
+ # Without jq, the parse below silently yields empty and this hook stops
31
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
32
+ # here: blocking would halt every tool call, and exiting 0 would change
33
+ # the behaviour of guards that do not depend on the parsed value.
34
+ if ! command -v jq >/dev/null 2>&1; then
35
+ _nojq_warned="/tmp/cc-nojq-warned-push-requires-test-pass-$PPID"
36
+ [ -f "$_nojq_warned" ] || {
37
+ echo "WARNING [push-requires-test-pass]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
38
+ : > "$_nojq_warned"
39
+ }
40
+ fi
41
+
30
42
  INPUT=$(cat)
31
43
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
32
44
 
@@ -0,0 +1,173 @@
1
+ #!/bin/bash
2
+ # quota-anomaly-detector.sh — alert when token consumption rate diverges from your personal baseline
3
+ #
4
+ # Why: The Pro Max quota anomaly cluster (#16157 / #38335 / #45756 / #41788 / #29579
5
+ # / #19673 / cumulative ~1,600 reactions) reports the same operator-side symptom:
6
+ # the quota empties materially faster than the same workflow used to consume it,
7
+ # sometimes within minutes of the session starting. Four issues name a runtime
8
+ # version or date boundary (2026-03-23 / v2.1.89 / v2.1.100 / 2.1.1) so the
9
+ # shift is version-correlated.
10
+ #
11
+ # cache-creation-drift-detector.sh catches the *per-request* server-side
12
+ # inflation documented in #46917, but it cannot see the cross-request picture:
13
+ # a session that fires 40 small requests in 10 minutes burns the same quota as
14
+ # one large request, and only the rolling rate exposes it. This hook fills that
15
+ # gap by tracking total tokens-per-minute against a personal trailing baseline.
16
+ #
17
+ # Composes with cache-creation-drift-detector (per-request) and the existing
18
+ # session-quota-tracker.sh (raw tool-call count, no token weight).
19
+ #
20
+ # Event: PostToolUse MATCHER: "" (all tools)
21
+ # Action: Sum input_tokens + output_tokens + cache_read_input_tokens +
22
+ # cache_creation_input_tokens from the PostToolUse payload (or last
23
+ # assistant turn in the transcript as fallback). Append a timestamped
24
+ # sample to a rolling JSONL log. Compute the operator's tokens-per-minute
25
+ # over the trailing window. If the current window's rate exceeds the
26
+ # trailing baseline by a configurable multiplier, emit a one-line stderr
27
+ # warning. Advisory only (exit 0); does not block.
28
+ #
29
+ # Configuration (all optional):
30
+ # CC_QUOTA_ANOMALY_LOG Log path (default: ~/.cache/cc-safe-setup/quota-anomaly.jsonl)
31
+ # CC_QUOTA_ANOMALY_THRESHOLD Multiplier for alert (default: 1.5 = 50% above baseline rate)
32
+ # CC_QUOTA_ANOMALY_MIN_HISTORY Minimum samples before alerting (default: 30)
33
+ # CC_QUOTA_ANOMALY_WINDOW_MIN Current-rate window in minutes (default: 10)
34
+ # CC_QUOTA_ANOMALY_BASELINE_MIN Baseline window in minutes (default: 1440 = 24h)
35
+ # CC_QUOTA_ANOMALY_SILENT Set to "1" to suppress stderr (still logs)
36
+ #
37
+ # Inspect the log:
38
+ # tail -50 ~/.cache/cc-safe-setup/quota-anomaly.jsonl
39
+ # jq -s 'map(.total) | add' ~/.cache/cc-safe-setup/quota-anomaly.jsonl
40
+ #
41
+ # The registration was missing from this header. The installer reads TRIGGER
42
+ # and MATCHER from here and falls back to PreToolUse / Bash when both are
43
+ # absent, so this hook was being registered at a moment where the field it
44
+ # reads is always empty: it installed, it appeared in the settings, and it
45
+ # did nothing. Measured 2026-08-04 across examples/: 14 files were like this.
46
+ # TRIGGER: PostToolUse
47
+ # MATCHER: ""
48
+
49
+ set -u
50
+
51
+ LOG="${CC_QUOTA_ANOMALY_LOG:-${HOME}/.cache/cc-safe-setup/quota-anomaly.jsonl}"
52
+ THRESHOLD="${CC_QUOTA_ANOMALY_THRESHOLD:-1.5}"
53
+ MIN_HISTORY="${CC_QUOTA_ANOMALY_MIN_HISTORY:-30}"
54
+ WINDOW_MIN="${CC_QUOTA_ANOMALY_WINDOW_MIN:-10}"
55
+ BASELINE_MIN="${CC_QUOTA_ANOMALY_BASELINE_MIN:-1440}"
56
+ SILENT="${CC_QUOTA_ANOMALY_SILENT:-0}"
57
+
58
+ mkdir -p "$(dirname "$LOG")" 2>/dev/null
59
+
60
+ INPUT=$(cat)
61
+
62
+ extract_total() {
63
+ # $1 = jq path prefix to usage object
64
+ local prefix="$1"
65
+ printf '%s' "$INPUT" | jq -r --arg p "$prefix" '
66
+ def num(x): if (x | type) == "number" then x else 0 end;
67
+ ($p | split(".") | map(select(length > 0))) as $path |
68
+ (getpath($path)) as $u |
69
+ if $u == null then empty
70
+ else
71
+ (num($u.input_tokens) + num($u.output_tokens) +
72
+ num($u.cache_read_input_tokens) + num($u.cache_creation_input_tokens))
73
+ end
74
+ ' 2>/dev/null
75
+ }
76
+
77
+ # Try PostToolUse payload first.
78
+ TOTAL=$(extract_total ".tool_response.usage")
79
+
80
+ # Fallback: read the last assistant turn's usage from the transcript.
81
+ if [ -z "$TOTAL" ] || [ "$TOTAL" = "0" ]; then
82
+ TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
83
+ if [ -n "$TRANSCRIPT" ] && [ -r "$TRANSCRIPT" ]; then
84
+ LAST_USAGE_LINE=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"usage"' || true)
85
+ if [ -n "$LAST_USAGE_LINE" ]; then
86
+ TOTAL=$(printf '%s' "$LAST_USAGE_LINE" | jq -r '
87
+ def num(x): if (x | type) == "number" then x else 0 end;
88
+ (.message.usage // .usage // null) as $u |
89
+ if $u == null then empty
90
+ else
91
+ (num($u.input_tokens) + num($u.output_tokens) +
92
+ num($u.cache_read_input_tokens) + num($u.cache_creation_input_tokens))
93
+ end
94
+ ' 2>/dev/null)
95
+ fi
96
+ fi
97
+ fi
98
+
99
+ # No usable measurement.
100
+ if [ -z "$TOTAL" ] || [ "$TOTAL" = "0" ] || [ "$TOTAL" = "null" ]; then
101
+ exit 0
102
+ fi
103
+
104
+ # Validate positive integer.
105
+ case "$TOTAL" in
106
+ ''|*[!0-9]*) exit 0 ;;
107
+ esac
108
+
109
+ SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
110
+ NOW_EPOCH=$(date -u +%s)
111
+ TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
112
+
113
+ # Append sample.
114
+ printf '{"ts":"%s","epoch":%s,"session":"%s","total":%s}\n' \
115
+ "$TS" "$NOW_EPOCH" "$SESSION_ID" "$TOTAL" >> "$LOG"
116
+
117
+ # Need MIN_HISTORY samples before trusting the baseline.
118
+ SAMPLE_COUNT=$(wc -l < "$LOG" 2>/dev/null | tr -d ' ')
119
+ SAMPLE_COUNT="${SAMPLE_COUNT:-0}"
120
+ if [ "$SAMPLE_COUNT" -lt "$MIN_HISTORY" ]; then
121
+ exit 0
122
+ fi
123
+
124
+ # Compute current window sum and baseline window sum.
125
+ WINDOW_CUTOFF=$((NOW_EPOCH - WINDOW_MIN * 60))
126
+ BASELINE_CUTOFF=$((NOW_EPOCH - BASELINE_MIN * 60))
127
+
128
+ # Read once, compute both sums and counts.
129
+ SUMS=$(awk -v wc="$WINDOW_CUTOFF" -v bc="$BASELINE_CUTOFF" '
130
+ /"epoch":/ {
131
+ # Extract epoch and total via simple field parse (matches our writer format).
132
+ match($0, /"epoch":[0-9]+/)
133
+ e = substr($0, RSTART+8, RLENGTH-8) + 0
134
+ match($0, /"total":[0-9]+/)
135
+ t = substr($0, RSTART+8, RLENGTH-8) + 0
136
+ if (e >= bc) {
137
+ bs += t; bn++
138
+ if (e >= wc) { ws += t; wn++ }
139
+ }
140
+ }
141
+ END { printf "%d %d %d %d", ws, wn, bs, bn }
142
+ ' "$LOG" 2>/dev/null)
143
+
144
+ WINDOW_SUM=$(echo "$SUMS" | awk '{print $1}')
145
+ WINDOW_N=$(echo "$SUMS" | awk '{print $2}')
146
+ BASELINE_SUM=$(echo "$SUMS" | awk '{print $3}')
147
+ BASELINE_N=$(echo "$SUMS" | awk '{print $4}')
148
+
149
+ # Need enough activity in both windows.
150
+ if [ "${WINDOW_N:-0}" -lt 2 ] || [ "${BASELINE_N:-0}" -lt "$MIN_HISTORY" ]; then
151
+ exit 0
152
+ fi
153
+
154
+ # Compute rates: tokens per minute in each window.
155
+ RATIO=$(awk -v ws="$WINDOW_SUM" -v wm="$WINDOW_MIN" \
156
+ -v bs="$BASELINE_SUM" -v bm="$BASELINE_MIN" '
157
+ BEGIN {
158
+ wr = ws / wm
159
+ br = bs / bm
160
+ if (br > 0) printf "%.3f", wr / br; else print "0"
161
+ }')
162
+ EXCEEDS=$(awk -v r="$RATIO" -v t="$THRESHOLD" 'BEGIN { print (r > t) ? 1 : 0 }')
163
+
164
+ if [ "$EXCEEDS" = "1" ] && [ "$SILENT" != "1" ]; then
165
+ WIN_RATE=$(awk -v ws="$WINDOW_SUM" -v wm="$WINDOW_MIN" 'BEGIN { printf "%d", ws/wm }')
166
+ BASE_RATE=$(awk -v bs="$BASELINE_SUM" -v bm="$BASELINE_MIN" 'BEGIN { printf "%d", bs/bm }')
167
+ PCT=$(awk -v r="$RATIO" 'BEGIN { printf "%d", (r - 1) * 100 }')
168
+ echo "NOTICE: token consumption rate ~${WIN_RATE} tok/min over last ${WINDOW_MIN}min is ${PCT}% above your ${BASELINE_MIN}min baseline (~${BASE_RATE} tok/min)." >&2
169
+ echo " Pro Max quota anomaly cluster: anthropics/claude-code #16157 / #38335 / #45756." >&2
170
+ echo " Inspect ${LOG} or set CC_QUOTA_ANOMALY_SILENT=1 to suppress." >&2
171
+ fi
172
+
173
+ exit 0
@@ -0,0 +1,58 @@
1
+ #!/bin/bash
2
+ # quota-reset-audit.sh — weekly quota reset cluster logger (Incident 9)
3
+ # Why: On 2026-04-23 users reported /usage showing quota available while
4
+ # sessions were being rate-limited. Client-side vs server-side
5
+ # timezone handling of the weekly reset diverged. The dashboard's
6
+ # resets_at value is the only ground truth available to users, and
7
+ # a log of resets_at at each session start is the only way to prove
8
+ # "the dashboard said X, the actual reset happened Y."
9
+ # Event: SessionStart
10
+ # Action: Capture /usage --json at session start. Log the timestamp,
11
+ # resets_at, and percent-used to ~/.claude/logs/usage-audit.log.
12
+ # If /usage is unavailable (pre-v2.1.118) log a placeholder so the
13
+ # session never fails because of the hook.
14
+
15
+ set -u
16
+
17
+ LOG_DIR="${HOME}/.claude/logs"
18
+ LOG_FILE="${LOG_DIR}/usage-audit.log"
19
+ mkdir -p "$LOG_DIR" 2>/dev/null
20
+
21
+ INPUT=$(cat 2>/dev/null || true)
22
+ SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
23
+
24
+ TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
25
+
26
+ fetch_usage() {
27
+ # Prefer the claude CLI subcommand when available (v2.1.118+ shipped
28
+ # /usage with --json output). Fall back to `claude usage --json` which
29
+ # some earlier builds exposed. If neither works, return empty.
30
+ local out=""
31
+ if command -v claude >/dev/null 2>&1; then
32
+ out=$(timeout 5 claude /usage --json 2>/dev/null || true)
33
+ if [ -z "$out" ] || ! printf '%s' "$out" | jq -e . >/dev/null 2>&1; then
34
+ out=$(timeout 5 claude usage --json 2>/dev/null || true)
35
+ fi
36
+ fi
37
+ printf '%s' "$out"
38
+ }
39
+
40
+ USAGE_JSON=$(fetch_usage)
41
+
42
+ if [ -z "$USAGE_JSON" ] || ! printf '%s' "$USAGE_JSON" | jq -e . >/dev/null 2>&1; then
43
+ printf '%s\t%s\t%s\t%s\t%s\n' \
44
+ "$TS" "$SESSION_ID" "unavailable" "unavailable" "unavailable" \
45
+ >> "$LOG_FILE"
46
+ exit 0
47
+ fi
48
+
49
+ # Expected /usage fields vary by CC version. Pull common ones defensively.
50
+ RESETS_AT=$(printf '%s' "$USAGE_JSON" | jq -r '.weekly.resets_at // .resets_at // .weeklyResetsAt // "unknown"' 2>/dev/null)
51
+ PCT_USED=$(printf '%s' "$USAGE_JSON" | jq -r '.weekly.percent_used // .percent_used // .weeklyPercentUsed // "unknown"' 2>/dev/null)
52
+ TIER=$(printf '%s' "$USAGE_JSON" | jq -r '.tier // .plan // "unknown"' 2>/dev/null)
53
+
54
+ printf '%s\t%s\t%s\t%s\t%s\n' \
55
+ "$TS" "$SESSION_ID" "$TIER" "$RESETS_AT" "$PCT_USED" \
56
+ >> "$LOG_FILE"
57
+
58
+ exit 0
@@ -10,7 +10,7 @@
10
10
  # trigger a confirmation prompt even when they match allowlist patterns.
11
11
  #
12
12
  # This PermissionRequest hook auto-approves these prompts when:
13
- # 1. The base command is in a safe list
13
+ # 1. Every command position is in a safe list
14
14
  # 2. The only "issue" is quoted characters in flag values
15
15
  #
16
16
  # TRIGGER: PermissionRequest
@@ -25,6 +25,25 @@
25
25
  # }]
26
26
  # }
27
27
  # }
28
+ #
29
+ # Fixed 2026-08-03. The safe list held bare command *words* — `git`, `curl`,
30
+ # `chmod`, `sed`, `node`, `python3`, `npx` — and a word says nothing about what
31
+ # the command does. `git commit -m "fix"` and `git push --force origin main`
32
+ # have the same first word.
33
+ #
34
+ # Measured against the shipped copy, over 20 destructive or credential-reading
35
+ # commands with no separator in them at all: **15 were approved**, among them
36
+ # `git push --force`, `git reset --hard`, `git clean -fdx`, `chmod -R 777 /`,
37
+ # `curl … | sh`, `node -e '…rmSync…'` and `cat ~/.aws/credentials`.
38
+ #
39
+ # This is a different defect from the first-command-position one repaired in
40
+ # #937/#940/#941/#942/#943/#947, and mixing the two would produce a number that
41
+ # looks right and is not: nothing here was hiding past a separator. The
42
+ # granularity of the list was the problem. (The first-position defect was here
43
+ # too, and is fixed in the same pass.)
44
+ #
45
+ # Known limit: quotes are not parsed when splitting, so a separator inside a
46
+ # quoted string ends a segment early. That errs toward fewer approvals.
28
47
 
29
48
  INPUT=$(cat)
30
49
 
@@ -36,16 +55,86 @@ echo "$MESSAGE" | grep -qi "quoted characters in flag" || exit 0
36
55
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
37
56
  [ -z "$COMMAND" ] && exit 0
38
57
 
39
- # Safe base commands — customize for your project
40
- SAFE_COMMANDS="git|npm|npx|bun|yarn|pnpm|docker|make|cargo|go|pip|python3|node|tsc|eslint|prettier|jest|vitest|pytest|curl|wget|rsync|tar|zip|unzip|cp|mv|mkdir|cat|echo|grep|find|ls|chmod|sed|awk"
58
+ # A substitution or backtick carries a command no string-level read can see.
59
+ # This hook is about quoted flag values, not substitution, so it refuses them.
60
+ case "$COMMAND" in
61
+ *'$('*|*'`'*) exit 0 ;;
62
+ esac
63
+
64
+ # Command words that carry no destructive form of their own. Anything that
65
+ # takes code as an argument (`node -e`, `python3 -c`, `npx`) or fetches and runs
66
+ # (`curl`, `wget`) is deliberately absent: for those the word says nothing.
67
+ cc_base_ok() {
68
+ case "$1" in
69
+ cat|head|tail|less|more|wc|file|stat|du|df|ls|tree|\
70
+ which|whereis|type|realpath|readlink|basename|dirname|\
71
+ grep|rg|ag|ack|sort|uniq|tr|cut|column|nl|rev|awk|\
72
+ echo|printf|true|false|pwd|date|uname|hostname|whoami|id|\
73
+ jq|yq|cd|\
74
+ tsc|eslint|prettier|jest|vitest|pytest)
75
+ return 0 ;;
76
+ esac
77
+ return 1
78
+ }
79
+
80
+ # Build tool subcommands that neither destroy history nor run fetched code.
81
+ # One line on purpose: inside single quotes a trailing backslash is a literal
82
+ # backslash-newline, not a continuation, and the pattern silently stops matching.
83
+ CC_SUBCMD_RE='^[[:space:]]*(git[[:space:]]+(status|log|diff|show|add|commit|branch|remote|describe|rev-parse|blame|shortlog|ls-files|ls-tree|fetch|stash[[:space:]]+(list|push|save))|npm[[:space:]]+(test|run|ci|ls|view|outdated)|yarn[[:space:]]+(test|run|info|why)|pnpm[[:space:]]+(test|run|list|why)|bun[[:space:]]+(test|run)|cargo[[:space:]]+(build|test|check|fmt|clippy|tree)|go[[:space:]]+(build|test|vet|fmt|list)|docker[[:space:]]+(ps|images|logs|inspect|version|info)|make[[:space:]]+[A-Za-z0-9_.-]+|pip[[:space:]]+(list|show|freeze)|python3[[:space:]]+-m[[:space:]]+(pytest|unittest|pip[[:space:]]+(list|show|freeze)))([[:space:]]|$)'
84
+
85
+ cc_subcommand_ok() {
86
+ printf '%s' "$1" | grep -qE "$CC_SUBCMD_RE"
87
+ }
88
+
89
+ cc_segment_base() {
90
+ printf '%s' "$1" \
91
+ | sed -E 's/^[[:space:]]+//; s/^([A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*[[:space:]]+)*//' \
92
+ | awk '{print $1}' \
93
+ | sed 's|.*/||'
94
+ }
95
+
96
+ # `git branch` reads; `git branch -D main` deletes one. Same first two words.
97
+ CC_GIT_DESTRUCTIVE_RE='^[[:space:]]*git[[:space:]]+(branch|tag)[[:space:]]+-([dDmM]|-delete|-move)([[:space:]]|$)'
98
+
99
+ cc_segment_ok() {
100
+ local seg="$1" base
101
+ base=$(cc_segment_base "$seg")
102
+ [ -z "$base" ] && return 1
103
+
104
+ if [ "$base" = "find" ]; then
105
+ printf '%s' "$seg" \
106
+ | grep -qE '(^|[[:space:]])-(delete|exec|execdir|ok|okdir|fprintf?|fls|fprint0)([[:space:]]|$)' \
107
+ && return 1
108
+ return 0
109
+ fi
110
+ if [ "$base" = "sed" ]; then
111
+ printf '%s' "$seg" | grep -qE '(^|[[:space:]])-[a-zA-Z]*i' && return 1
112
+ return 0
113
+ fi
114
+
115
+ cc_base_ok "$base" && return 0
116
+ printf '%s' "$seg" | grep -qE "$CC_GIT_DESTRUCTIVE_RE" && return 1
117
+ cc_subcommand_ok "$seg" && return 0
118
+ return 1
119
+ }
120
+
121
+ # A redirection writes a file, whatever the command word says.
122
+ case "$COMMAND" in
123
+ *'>'*) exit 0 ;;
124
+ esac
41
125
 
42
- # Extract base command (first word, ignoring env vars and path)
43
- BASE_CMD=$(echo "$COMMAND" | sed 's/^[A-Z_]*=[^ ]* //' | awk '{print $1}' | sed 's|.*/||')
126
+ IDX=0
127
+ while IFS= read -r SEG; do
128
+ SEG="${SEG#"${SEG%%[![:space:]]*}"}"
129
+ SEG="${SEG%"${SEG##*[![:space:]]}"}"
130
+ [ -z "$SEG" ] && continue
131
+ cc_segment_ok "$SEG" || exit 0
132
+ IDX=$((IDX + 1))
133
+ done <<EOF
134
+ $(printf '%s' "$COMMAND" | tr ';&|' '\n\n\n')
135
+ EOF
44
136
 
45
- if echo "$BASE_CMD" | grep -qE "^($SAFE_COMMANDS)$"; then
46
- echo '{"permissionDecision":"allow"}'
47
- exit 0
48
- fi
137
+ [ "$IDX" -eq 0 ] && exit 0
49
138
 
50
- # Unknown command — let the prompt through
139
+ echo '{"permissionDecision":"allow"}'
51
140
  exit 0
@@ -19,6 +19,18 @@
19
19
  #
20
20
  # TRIGGER: PreToolUse MATCHER: "Bash"
21
21
 
22
+ # Without jq, the parse below silently yields empty and this hook stops
23
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
24
+ # here: blocking would halt every tool call, and exiting 0 would change
25
+ # the behaviour of guards that do not depend on the parsed value.
26
+ if ! command -v jq >/dev/null 2>&1; then
27
+ _nojq_warned="/tmp/cc-nojq-warned-rails-migration-guard-$PPID"
28
+ [ -f "$_nojq_warned" ] || {
29
+ echo "WARNING [rails-migration-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
30
+ : > "$_nojq_warned"
31
+ }
32
+ fi
33
+
22
34
  INPUT=$(cat)
23
35
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
24
36
 
File without changes
File without changes