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,181 @@
1
+ #!/bin/bash
2
+ # deny-rule-integrity-verifier.sh — Catch deny-rule bypasses through whitespace normalization
3
+ #
4
+ # Solves: Cluster 6 Axis 5 — deny rules don't enforce the safety constraints
5
+ # users configure. A deny pattern Bash(rm -rf:*) catches `rm -rf /`
6
+ # but is silently bypassed by:
7
+ # - extra whitespace (`rm -rf /`)
8
+ # - backslash-newline line continuations (`rm \<newline>-rf /`)
9
+ # - tab characters in place of spaces (`rm -rf /`)
10
+ # The matching engine compares the raw command string against the
11
+ # pattern body literally, so any whitespace anomaly slips past.
12
+ #
13
+ # Issues addressed: meta-issue #30519 Axis 5 (deny rules have same bugs as
14
+ # allow rules), #35954 (backslash-escaped whitespace warning
15
+ # framework), and the broader pattern that whitespace-sensitive
16
+ # literal matching can be defeated trivially.
17
+ #
18
+ # How it works: PreToolUse hook on Bash. For each Bash() deny pattern in
19
+ # permissions.deny across the four standard settings locations, the
20
+ # hook checks:
21
+ # 1. Does the RAW command match the pattern? (the matching engine
22
+ # catches this case; if yes, this hook does nothing)
23
+ # 2. Does the NORMALIZED command match the pattern? (whitespace
24
+ # collapsed, line continuations joined)
25
+ # If raw misses and normalized hits — that is the bypass. The hook
26
+ # blocks with exit code 2 by default; CC_DENY_INTEGRITY_WARN_ONLY=1
27
+ # converts the block to a stderr advisory while letting the command
28
+ # through.
29
+ #
30
+ # Pattern extraction supports the three Claude Code Bash() shapes:
31
+ # Bash(<exact>) — exact match
32
+ # Bash(<prefix>:*) — prefix match (the common form)
33
+ # Bash(*) — wildcard — skipped (already matches raw)
34
+ #
35
+ # Scope of normalization (v1):
36
+ # - Strip backslash-newline line continuations (`\<newline>` → ` `)
37
+ # - Collapse any whitespace run (spaces, tabs, newlines) to a single space
38
+ # - Trim leading and trailing whitespace
39
+ # Flag combination/reordering normalization (`-rf` vs `-r -f` vs `-fr`)
40
+ # is OUT OF SCOPE for v1 — those bypass shapes need command-aware logic
41
+ # beyond uniform string normalization and warrant a separate hook.
42
+ #
43
+ # Environment variables:
44
+ # CC_DENY_INTEGRITY_DISABLE=1 — disable verification entirely
45
+ # CC_DENY_INTEGRITY_WARN_ONLY=1 — log the bypass to stderr but do not block
46
+ #
47
+ # TRIGGER: PreToolUse
48
+ # MATCHER: "Bash"
49
+
50
+ set -uo pipefail
51
+
52
+ # Without jq, the parse below silently yields empty and this hook stops
53
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
54
+ # here: blocking would halt every tool call, and exiting 0 would change
55
+ # the behaviour of guards that do not depend on the parsed value.
56
+ if ! command -v jq >/dev/null 2>&1; then
57
+ _nojq_warned="/tmp/cc-nojq-warned-deny-rule-integrity-verifier-$PPID"
58
+ [ -f "$_nojq_warned" ] || {
59
+ echo "WARNING [deny-rule-integrity-verifier]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
60
+ : > "$_nojq_warned"
61
+ }
62
+ fi
63
+
64
+ INPUT=$(cat)
65
+
66
+ COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
67
+ [ -z "$COMMAND" ] && exit 0
68
+ [ "${CC_DENY_INTEGRITY_DISABLE:-0}" = "1" ] && exit 0
69
+
70
+ # Collect Bash() deny patterns from all four standard settings locations.
71
+ DENY_FILE=$(mktemp)
72
+ trap 'rm -f "$DENY_FILE"' EXIT
73
+ for CFG in \
74
+ "${HOME}/.claude/settings.json" \
75
+ "${HOME}/.claude/settings.local.json" \
76
+ "./.claude/settings.json" \
77
+ "./.claude/settings.local.json"; do
78
+ [ -f "$CFG" ] || continue
79
+ jq -r '.permissions.deny // [] | .[] | select(type == "string" and startswith("Bash("))' \
80
+ "$CFG" 2>/dev/null >> "$DENY_FILE" || true
81
+ done
82
+
83
+ [ ! -s "$DENY_FILE" ] && exit 0
84
+
85
+ # Normalize: strip backslash-newline (line continuation), collapse all
86
+ # whitespace to single space, trim.
87
+ NORMALIZED=$(printf '%s' "$COMMAND" \
88
+ | sed -E ':a;N;$!ba;s/\\\n/ /g' \
89
+ | tr '\t\n' ' ' \
90
+ | sed -E 's/[[:space:]]+/ /g; s/^[[:space:]]+//; s/[[:space:]]+$//')
91
+
92
+ # If normalization is a no-op, nothing to do — the standard matcher
93
+ # already handles this command.
94
+ if [ "$NORMALIZED" = "$COMMAND" ]; then
95
+ exit 0
96
+ fi
97
+
98
+ # Check each deny pattern.
99
+ while IFS= read -r PATTERN; do
100
+ [ -z "$PATTERN" ] && continue
101
+
102
+ # Extract pattern body. Handles:
103
+ # Bash(<body>) → BODY=<body>, SUFFIX_GLOB=0
104
+ # Bash(<body>:*) → BODY=<body>, SUFFIX_GLOB=1
105
+ BODY=""
106
+ SUFFIX_GLOB=0
107
+ if [[ "$PATTERN" =~ ^Bash\((.+):\*\)$ ]]; then
108
+ BODY="${BASH_REMATCH[1]}"
109
+ SUFFIX_GLOB=1
110
+ elif [[ "$PATTERN" =~ ^Bash\((.+)\)$ ]]; then
111
+ BODY="${BASH_REMATCH[1]}"
112
+ SUFFIX_GLOB=0
113
+ fi
114
+ [ -z "$BODY" ] && continue
115
+
116
+ # Bash(*) — wildcard pattern — would match raw already.
117
+ [ "$BODY" = "*" ] && continue
118
+
119
+ # Match logic: a command matches the pattern if it equals BODY exactly
120
+ # or (when the pattern has the :* glob suffix) if it starts with BODY
121
+ # at a word boundary. The boundary rule:
122
+ # - If BODY ends in an alphanumeric char (rm, git, curl) the next
123
+ # character must be a space — otherwise `Bash(rm:*)` would block
124
+ # `rmdir`.
125
+ # - If BODY ends in a non-alphanumeric char (=, -, /, .) the next
126
+ # character can be attached — `Bash(dd if=:*)` should match
127
+ # `dd if=/dev/zero ...`.
128
+ raw_matches() {
129
+ local CMD="$1" BDY="$2" GLOB="$3"
130
+ if [ "$CMD" = "$BDY" ]; then
131
+ return 0
132
+ fi
133
+ if [ "$GLOB" = "1" ]; then
134
+ local LAST_CHAR="${BDY: -1}"
135
+ if [[ "$LAST_CHAR" =~ [a-zA-Z0-9] ]]; then
136
+ case "$CMD" in
137
+ "$BDY "*) return 0 ;;
138
+ esac
139
+ else
140
+ case "$CMD" in
141
+ "$BDY"*) return 0 ;;
142
+ esac
143
+ fi
144
+ fi
145
+ return 1
146
+ }
147
+
148
+ if raw_matches "$COMMAND" "$BODY" "$SUFFIX_GLOB"; then
149
+ # Standard matcher already catches this — nothing for us to do.
150
+ continue
151
+ fi
152
+
153
+ if raw_matches "$NORMALIZED" "$BODY" "$SUFFIX_GLOB"; then
154
+ # BYPASS DETECTED.
155
+ CMD_SAFE_PRINT=$(printf '%s' "$COMMAND" | head -c 300 | tr -d '\000')
156
+ {
157
+ echo "[deny-rule-integrity-verifier] Deny-rule bypass detected."
158
+ echo ""
159
+ echo " Configured deny pattern : $PATTERN"
160
+ echo " Raw command (excerpt) : $CMD_SAFE_PRINT"
161
+ echo " Normalized command : $NORMALIZED"
162
+ echo ""
163
+ echo "The normalized form matches your configured deny pattern, but the raw"
164
+ echo "command bypasses literal matching through whitespace anomalies"
165
+ echo "(extra spaces, tab characters, or backslash-newline line continuations)."
166
+ echo "Cluster 6 Axis 5 — meta-issue #30519 (Claude Code permission matching)."
167
+ } >&2
168
+ if [ "${CC_DENY_INTEGRITY_WARN_ONLY:-0}" = "1" ]; then
169
+ echo "" >&2
170
+ echo "(CC_DENY_INTEGRITY_WARN_ONLY=1 is set — command will proceed)" >&2
171
+ exit 0
172
+ else
173
+ echo "" >&2
174
+ echo "Blocking. Set CC_DENY_INTEGRITY_WARN_ONLY=1 to convert this to a" >&2
175
+ echo "warning, or CC_DENY_INTEGRITY_DISABLE=1 to silence the hook." >&2
176
+ exit 2
177
+ fi
178
+ fi
179
+ done < "$DENY_FILE"
180
+
181
+ 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-dependency-install-guard-$PPID"
28
+ [ -f "$_nojq_warned" ] || {
29
+ echo "WARNING [dependency-install-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
  [ -z "$COMMAND" ] && exit 0
@@ -12,13 +12,25 @@
12
12
  # {
13
13
  # "hooks": {
14
14
  # "PreToolUse": [{
15
- # "matcher": "Bash",
15
+ # "matcher": "Bash|PowerShell",
16
16
  # "hooks": [{ "type": "command", "command": "~/.claude/hooks/deploy-guard.sh" }]
17
17
  # }]
18
18
  # }
19
19
  # }
20
20
  #
21
- # TRIGGER: PreToolUse MATCHER: "Bash"
21
+ # TRIGGER: PreToolUse MATCHER: "Bash|PowerShell"
22
+
23
+ # Without jq, the parse below silently yields empty and this hook stops
24
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
25
+ # here: blocking would halt every tool call, and exiting 0 would change
26
+ # the behaviour of guards that do not depend on the parsed value.
27
+ if ! command -v jq >/dev/null 2>&1; then
28
+ _nojq_warned="/tmp/cc-nojq-warned-deploy-guard-$PPID"
29
+ [ -f "$_nojq_warned" ] || {
30
+ echo "WARNING [deploy-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
31
+ : > "$_nojq_warned"
32
+ }
33
+ fi
22
34
 
23
35
  INPUT=$(cat)
24
36
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
@@ -18,6 +18,18 @@
18
18
 
19
19
  set -euo pipefail
20
20
 
21
+ # Without jq, the parse below silently yields empty and this hook stops
22
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
23
+ # here: blocking would halt every tool call, and exiting 0 would change
24
+ # the behaviour of guards that do not depend on the parsed value.
25
+ if ! command -v jq >/dev/null 2>&1; then
26
+ _nojq_warned="/tmp/cc-nojq-warned-deploy-path-verify-guard-$PPID"
27
+ [ -f "$_nojq_warned" ] || {
28
+ echo "WARNING [deploy-path-verify-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
29
+ : > "$_nojq_warned"
30
+ }
31
+ fi
32
+
21
33
  INPUT=$(cat)
22
34
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
23
35
 
@@ -0,0 +1,135 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # deployment-readback-gate.sh — Refuse a deployment-completion claim
4
+ # unless an authority confirms it, recently
5
+ # ================================================================
6
+ # PURPOSE:
7
+ # Turn a "deployment complete" claim into a refusable, auditable trust
8
+ # artifact. This is the GENERIC decision core: it consumes a *normalized
9
+ # readback receipt* (produced by a provider adapter — gh deployments,
10
+ # Vercel, k8s, ...) and decides allow / refuse-mismatch / refuse-query-
11
+ # failure / refuse-stale. It contains no provider knowledge.
12
+ #
13
+ # Spec: docs/deployment-readback-gate-spec.md (issue #313)
14
+ # Motivating incident: anthropics/claude-code#61699 (model claimed
15
+ # "deployment complete" while the real deployment state diverged).
16
+ #
17
+ # TRIGGER: Stop
18
+ #
19
+ # INPUT (stdin): a normalized readback receipt JSON. Required fields:
20
+ # claim_span, claim_time (ISO 8601), claimed_ref, authority,
21
+ # queried_ref, queried_state, readback_time (ISO 8601, from the
22
+ # authority's own response), stale_if_older_than_ms (integer).
23
+ # queried_state is the authority's state ("success" = confirmed) or
24
+ # the literal "query-failure" when the adapter could not reach the
25
+ # authority.
26
+ #
27
+ # DECISION (and exit code):
28
+ # refuse-query-failure (exit 2) — authority unreachable / readback errored.
29
+ # FAIL CLOSED. Never coerced to allow. Distinct incident class from a
30
+ # mismatch: truth was never established (the claim *might* be correct).
31
+ # refuse-mismatch (exit 2) — queried_ref != claimed_ref, or
32
+ # queried_state != "success". Truth established, claim was wrong.
33
+ # refuse-stale (exit 2) — claim_time - readback_time exceeds
34
+ # stale_if_older_than_ms. A cached/replayed "success" must not ratify
35
+ # a fresh claim. Staleness is anchored to the CLAIM, not wall-clock.
36
+ # allow (exit 0) — fresh AND matching AND success.
37
+ #
38
+ # Missing required fields or unparseable timestamps also FAIL CLOSED
39
+ # (refuse-query-failure): an unauditable receipt is not a confirmation.
40
+ #
41
+ # WHAT IT WRITES:
42
+ # $CC_READBACK_RECEIPT_DIR/<timestamp>-<pid>.json (decision filled in)
43
+ # default: ~/.claude/state/deployments/readback/
44
+ # The receipt is written OUTSIDE the transcript, so the audit unit
45
+ # survives a lost or rewound session.
46
+ #
47
+ # USAGE (settings.json):
48
+ # { "hooks": { "Stop": [{ "hooks": [{ "type": "command",
49
+ # "command": "<adapter> | ~/.claude/hooks/deployment-readback-gate.sh" }] }] } }
50
+ # The adapter emits the normalized receipt on stdout; this gate decides.
51
+ # ================================================================
52
+
53
+ set -uo pipefail
54
+
55
+ RECEIPT_DIR="${CC_READBACK_RECEIPT_DIR:-$HOME/.claude/state/deployments/readback}"
56
+
57
+ INPUT=$(cat)
58
+
59
+ # This gate only acts on a normalized readback receipt produced by an adapter.
60
+ # Empty stdin, "{}", or unrelated input means no deployment claim is being
61
+ # gated here — pass through. Hooks must not block on irrelevant input.
62
+ if ! printf '%s' "$INPUT" | grep -qE '"(claimed_ref|authority|queried_state|claim_span)"'; then
63
+ exit 0
64
+ fi
65
+
66
+ # A receipt is present; jq is required to evaluate it.
67
+ if ! command -v jq >/dev/null 2>&1; then
68
+ echo "deployment-readback-gate: jq not found; cannot audit a present receipt — failing closed" >&2
69
+ exit 2
70
+ fi
71
+
72
+ # Extract fields (empty if absent).
73
+ field() { printf '%s' "$INPUT" | jq -r "(.$1 // empty)" 2>/dev/null; }
74
+
75
+ CLAIM_SPAN=$(field claim_span)
76
+ CLAIM_TIME=$(field claim_time)
77
+ CLAIMED_REF=$(field claimed_ref)
78
+ AUTHORITY=$(field authority)
79
+ QUERIED_REF=$(field queried_ref)
80
+ QUERIED_STATE=$(field queried_state)
81
+ READBACK_TIME=$(field readback_time)
82
+ STALE_MS=$(field stale_if_older_than_ms)
83
+
84
+ decision=""
85
+ reason=""
86
+
87
+ # to_ms: ISO 8601 -> epoch milliseconds, or empty on parse failure.
88
+ to_ms() { date -d "$1" +%s%3N 2>/dev/null; }
89
+
90
+ # --- fail closed on an unauditable receipt -------------------------------
91
+ if [ -z "$AUTHORITY" ] || [ -z "$READBACK_TIME" ] || [ -z "$STALE_MS" ] \
92
+ || [ -z "$CLAIM_TIME" ] || [ -z "$CLAIMED_REF" ] || [ -z "$QUERIED_STATE" ]; then
93
+ decision="refuse-query-failure"
94
+ reason="receipt missing required fields (authority/readback_time/stale_if_older_than_ms/claim_time/claimed_ref/queried_state) — cannot establish truth"
95
+ elif [ "$QUERIED_STATE" = "query-failure" ]; then
96
+ decision="refuse-query-failure"
97
+ reason="authority '$AUTHORITY' was not reached — deployment NOT confirmed (failing closed)"
98
+ else
99
+ claim_ms=$(to_ms "$CLAIM_TIME")
100
+ read_ms=$(to_ms "$READBACK_TIME")
101
+ if [ -z "$claim_ms" ] || [ -z "$read_ms" ]; then
102
+ decision="refuse-query-failure"
103
+ reason="unparseable claim_time/readback_time — cannot verify freshness (failing closed)"
104
+ elif [ "$QUERIED_REF" != "$CLAIMED_REF" ] || [ "$QUERIED_STATE" != "success" ]; then
105
+ decision="refuse-mismatch"
106
+ reason="claim ref/state ($CLAIMED_REF/success) != authority ($QUERIED_REF/$QUERIED_STATE)"
107
+ elif [ $(( claim_ms - read_ms )) -gt "$STALE_MS" ]; then
108
+ decision="refuse-stale"
109
+ reason="readback is $(( claim_ms - read_ms ))ms older than the claim (> ${STALE_MS}ms) — possible replay/cache, not ratifying"
110
+ else
111
+ decision="allow"
112
+ reason="confirmed by $AUTHORITY: $QUERIED_REF/$QUERIED_STATE, fresh within ${STALE_MS}ms"
113
+ fi
114
+ fi
115
+
116
+ # --- write the receipt (audit artifact, outside the transcript) ----------
117
+ mkdir -p "$RECEIPT_DIR" 2>/dev/null
118
+ ts=$(date -u +%Y%m%dT%H%M%S%3NZ 2>/dev/null || date -u +%Y%m%dT%H%M%SZ)
119
+ receipt_path="$RECEIPT_DIR/${ts}-$$.json"
120
+ printf '%s' "$INPUT" \
121
+ | jq --arg d "$decision" --arg r "$reason" --arg w "$ts" \
122
+ '. + {decision: $d, decision_reason: $r, decided_at: $w}' \
123
+ > "$receipt_path" 2>/dev/null \
124
+ || printf '{"decision":"%s","decision_reason":"%s","raw":true}\n' "$decision" "$reason" > "$receipt_path"
125
+
126
+ # --- emit decision -------------------------------------------------------
127
+ if [ "$decision" = "allow" ]; then
128
+ exit 0
129
+ fi
130
+
131
+ # Stop hook: exit 2 surfaces the reason and blocks the stop so the claim
132
+ # is corrected instead of standing.
133
+ echo "deployment-readback-gate: $decision — $reason" >&2
134
+ echo " receipt: $receipt_path" >&2
135
+ exit 2
@@ -0,0 +1,247 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # deployment-readback-gh-adapter.sh — `gh` deployments provider adapter
4
+ # for deployment-readback-gate
5
+ # ================================================================
6
+ # PURPOSE:
7
+ # The PROVIDER ADAPTER half of the deployment-readback-gate (issue
8
+ # #313). It owns all GitHub-specific knowledge: given a Stop event,
9
+ # it detects a deployment-completion claim in the assistant's
10
+ # closeout, reads the GitHub Deployments API for the *authoritative*
11
+ # state of that deploy, and emits the NORMALIZED readback receipt on
12
+ # stdout. The generic gate (examples/deployment-readback-gate.sh)
13
+ # consumes that receipt and decides allow / refuse-*.
14
+ #
15
+ # Spec: docs/deployment-readback-gate-spec.md
16
+ # Gate: examples/deployment-readback-gate.sh (provider-agnostic core)
17
+ # Incident: anthropics/claude-code#61699 (model claimed "deployment
18
+ # complete" while the real deploy state diverged).
19
+ #
20
+ # The adapter knows the provider; the gate knows the decision. A new
21
+ # authority (Vercel, Cloud Run, k8s, ...) is added by writing another
22
+ # adapter to this same output contract — never by touching the gate.
23
+ #
24
+ # TRIGGER: Stop
25
+ #
26
+ # INSTALL (settings.json) — adapter piped into the gate:
27
+ # { "hooks": { "Stop": [{ "hooks": [{ "type": "command",
28
+ # "command": "~/.claude/hooks/deployment-readback-gh-adapter.sh | ~/.claude/hooks/deployment-readback-gate.sh",
29
+ # "env": { "DRG_REPO": "owner/repo", "DRG_ENVIRONMENT": "production" } }] }] } }
30
+ #
31
+ # INPUT (stdin): the Stop event JSON. The adapter reads the last
32
+ # assistant message from `transcript_path` to find the claim. For
33
+ # deterministic use/testing, DRG_CLAIM_TEXT overrides the transcript.
34
+ #
35
+ # OUTPUT (stdout): exactly one of —
36
+ # * `{}` — no deployment claim here (or an
37
+ # unresolvable target in advisory mode). The gate passes through.
38
+ # * a normalized readback receipt — fields per the spec:
39
+ # claim_span, claim_time, target, claimed_ref, authority,
40
+ # readback_query, queried_ref, queried_state, readback_time,
41
+ # stale_if_older_than_ms
42
+ # `queried_state` is the authority's deployment-status state, or the
43
+ # literal "query-failure" when the API could not be reached.
44
+ #
45
+ # CONFIG (env):
46
+ # DRG_REPO owner/repo. If unset, derived from `gh repo view`.
47
+ # DRG_ENVIRONMENT deployment environment to query (default: production)
48
+ # DRG_CLAIMED_REF the claimed commit/ref. If unset, parsed from the
49
+ # claim text (`@<sha>` or a bare 7–40 hex token).
50
+ # DRG_PHRASE_LIST comma-separated claim phrases (case-insensitive).
51
+ # default: deployed,deployment complete,shipped to
52
+ # production,rolled out,deploy succeeded,live in production
53
+ # DRG_STALE_MS staleness window in ms (default: 300000 = 5 min)
54
+ # DRG_STRICT "1" → a deployment claim with an unresolvable
55
+ # target emits a query-failure receipt (gate refuses)
56
+ # instead of passing through. default: advisory (0).
57
+ # DRG_GH_CMD gh binary to invoke (default: gh). Overridable so
58
+ # the API layer can be mocked under test.
59
+ #
60
+ # WHY A SEPARATE ADAPTER:
61
+ # readback_time must come from the AUTHORITY's own response (the
62
+ # deployment status `created_at`), not from when the hook ran — that
63
+ # is what closes the replay/cache gap the gate's staleness check
64
+ # depends on. Only the provider adapter can source it, so provider
65
+ # I/O is isolated here and the gate stays pure and deterministic.
66
+ # ================================================================
67
+
68
+ set -uo pipefail
69
+
70
+ EVENT_INPUT=$(cat)
71
+
72
+ # --- config --------------------------------------------------------------
73
+ GH="${DRG_GH_CMD:-gh}"
74
+ ENVIRONMENT="${DRG_ENVIRONMENT:-production}"
75
+ STALE_MS="${DRG_STALE_MS:-300000}"
76
+ STRICT="${DRG_STRICT:-0}"
77
+ PHRASE_LIST="${DRG_PHRASE_LIST:-deployed,deployment complete,shipped to production,rolled out,deploy succeeded,live in production}"
78
+ AUTHORITY="github_deployments_api"
79
+
80
+ now_iso() { date -u +%Y-%m-%dT%H:%M:%S.%3NZ 2>/dev/null || date -u +%Y-%m-%dT%H:%M:%SZ; }
81
+
82
+ # Emit a bare pass-through and leave: this Stop is not gating a deploy claim.
83
+ pass_through() { printf '{}\n'; exit 0; }
84
+
85
+ # A receipt is meaningless without jq to build it; without it we cannot
86
+ # safely emit the contract, so pass through rather than emit malformed JSON.
87
+ command -v jq >/dev/null 2>&1 || pass_through
88
+
89
+ # --- 1. obtain the closeout text -----------------------------------------
90
+ # DRG_CLAIM_TEXT wins (deterministic). Otherwise read the last assistant
91
+ # message from the transcript named in the Stop event.
92
+ CLAIM_TEXT="${DRG_CLAIM_TEXT:-}"
93
+ if [ -z "$CLAIM_TEXT" ]; then
94
+ TRANSCRIPT=$(printf '%s' "$EVENT_INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
95
+ if [ -n "$TRANSCRIPT" ] && [ -f "$TRANSCRIPT" ]; then
96
+ CLAIM_TEXT=$(python3 - "$TRANSCRIPT" <<'PY' 2>/dev/null || true
97
+ import sys, json
98
+ last = ""
99
+ try:
100
+ with open(sys.argv[1]) as f:
101
+ for line in f:
102
+ line = line.strip()
103
+ if not line:
104
+ continue
105
+ try:
106
+ d = json.loads(line)
107
+ except Exception:
108
+ continue
109
+ if d.get("type") != "assistant":
110
+ continue
111
+ msg = d.get("message", d)
112
+ content = msg.get("content", "")
113
+ if isinstance(content, str):
114
+ text = content
115
+ elif isinstance(content, list):
116
+ text = " ".join(
117
+ b.get("text", "") for b in content
118
+ if isinstance(b, dict) and b.get("type") == "text"
119
+ )
120
+ else:
121
+ text = ""
122
+ if text.strip():
123
+ last = text
124
+ except Exception:
125
+ pass
126
+ print(last)
127
+ PY
128
+ )
129
+ fi
130
+ fi
131
+ [ -n "$CLAIM_TEXT" ] || pass_through
132
+
133
+ # --- 2. detect a (non-benign) deployment-completion claim ----------------
134
+ # Returns the matched claim phrase/span, or empty. A phrase inside a benign
135
+ # context ("deployed locally", "shipped to my machine", "in dev only") is
136
+ # not a production-deployment claim and must not trip the gate.
137
+ CLAIM_SPAN=$(CLAIM_TEXT="$CLAIM_TEXT" PHRASE_LIST="$PHRASE_LIST" python3 <<'PY' 2>/dev/null || true
138
+ import os, re
139
+ text = os.environ["CLAIM_TEXT"]
140
+ low = text.lower()
141
+ phrases = [p.strip().lower() for p in os.environ["PHRASE_LIST"].split(",") if p.strip()]
142
+ benign = ("local", "localhost", "my machine", "in dev", "dev only",
143
+ "staging only", "dry run", "dry-run", "would deploy", "about to deploy",
144
+ "going to deploy", "preview deploy")
145
+ best = ""
146
+ for p in phrases:
147
+ for m in re.finditer(re.escape(p), low):
148
+ s, e = m.start(), m.end()
149
+ window = low[max(0, s - 50):min(len(low), e + 50)]
150
+ if any(b in window for b in benign):
151
+ continue
152
+ # span = the surrounding clause, trimmed, from the original-case text
153
+ cs = max(0, s - 30)
154
+ ce = min(len(text), e + 30)
155
+ span = text[cs:ce].strip()
156
+ span = re.sub(r"\s+", " ", span)
157
+ if span:
158
+ best = span[:120]
159
+ break
160
+ if best:
161
+ break
162
+ print(best)
163
+ PY
164
+ )
165
+ [ -n "$CLAIM_SPAN" ] || pass_through
166
+
167
+ # --- 3. resolve the target (repo + claimed ref) --------------------------
168
+ REPO="${DRG_REPO:-}"
169
+ if [ -z "$REPO" ]; then
170
+ REPO=$("$GH" repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || true)
171
+ fi
172
+
173
+ CLAIMED_REF="${DRG_CLAIMED_REF:-}"
174
+ if [ -z "$CLAIMED_REF" ]; then
175
+ # `@<sha>` first (e.g. "api@abc1234"), else a bare 7–40 hex token.
176
+ CLAIMED_REF=$(printf '%s' "$CLAIM_SPAN" | grep -oiE '@[0-9a-f]{7,40}' | head -1 | tr -d '@')
177
+ [ -n "$CLAIMED_REF" ] || CLAIMED_REF=$(printf '%s' "$CLAIM_SPAN" | grep -oiE '\b[0-9a-f]{7,40}\b' | head -1)
178
+ fi
179
+
180
+ CLAIM_TIME=$(now_iso)
181
+ READBACK_QUERY="repos/${REPO:-?}/deployments?environment=${ENVIRONMENT}&sha=${CLAIMED_REF:-?}&per_page=1 + /statuses"
182
+
183
+ # emit_receipt <queried_ref> <queried_state> <readback_time> <target>
184
+ emit_receipt() {
185
+ jq -n \
186
+ --arg cs "$CLAIM_SPAN" --arg ct "$CLAIM_TIME" --arg tg "$4" \
187
+ --arg cr "$CLAIMED_REF" --arg au "$AUTHORITY" --arg rq "$READBACK_QUERY" \
188
+ --arg qr "$1" --arg qs "$2" --arg rt "$3" \
189
+ --argjson sm "$STALE_MS" \
190
+ '{claim_span:$cs, claim_time:$ct, target:$tg, claimed_ref:$cr,
191
+ authority:$au, readback_query:$rq, queried_ref:$qr, queried_state:$qs,
192
+ readback_time:$rt, stale_if_older_than_ms:$sm}'
193
+ }
194
+
195
+ TARGET="${REPO:-?}/${ENVIRONMENT}"
196
+
197
+ # A deployment claim with no resolvable target: advisory passes through,
198
+ # strict fails closed (a named-but-unverifiable deploy is the spec's
199
+ # "strict mode refuses any closeout with a deployment phrase but no
200
+ # resolvable target").
201
+ if [ -z "$REPO" ] || [ -z "$CLAIMED_REF" ]; then
202
+ if [ "$STRICT" = "1" ]; then
203
+ emit_receipt "" "query-failure" "$(now_iso)" "$TARGET"
204
+ exit 0
205
+ fi
206
+ pass_through
207
+ fi
208
+
209
+ # --- 4. read the authority: GitHub Deployments API -----------------------
210
+ DEPLOYMENTS=$("$GH" api "repos/$REPO/deployments?environment=$ENVIRONMENT&sha=$CLAIMED_REF&per_page=1" 2>/dev/null)
211
+ if [ $? -ne 0 ] || [ -z "$DEPLOYMENTS" ]; then
212
+ # Authority unreachable / errored → truth never established. Fail closed.
213
+ emit_receipt "" "query-failure" "$(now_iso)" "$TARGET"
214
+ exit 0
215
+ fi
216
+
217
+ DEP_ID=$(printf '%s' "$DEPLOYMENTS" | jq -r 'if type=="array" then (.[0].id // empty) else (.id // empty) end' 2>/dev/null)
218
+ DEP_SHA=$(printf '%s' "$DEPLOYMENTS" | jq -r 'if type=="array" then (.[0].sha // empty) else (.sha // empty) end' 2>/dev/null)
219
+
220
+ if [ -z "$DEP_ID" ]; then
221
+ # Authority reached, but it reports no deployment for this ref/env.
222
+ # Truth established: the claimed deploy is not on record → mismatch.
223
+ emit_receipt "" "not_found" "$(now_iso)" "$TARGET"
224
+ exit 0
225
+ fi
226
+
227
+ STATUSES=$("$GH" api "repos/$REPO/deployments/$DEP_ID/statuses?per_page=1" 2>/dev/null)
228
+ if [ $? -ne 0 ] || [ -z "$STATUSES" ]; then
229
+ emit_receipt "$DEP_SHA" "query-failure" "$(now_iso)" "$TARGET"
230
+ exit 0
231
+ fi
232
+
233
+ STATE=$(printf '%s' "$STATUSES" | jq -r 'if type=="array" then (.[0].state // empty) else (.state // empty) end' 2>/dev/null)
234
+ CREATED_AT=$(printf '%s' "$STATUSES" | jq -r 'if type=="array" then (.[0].created_at // empty) else (.created_at // empty) end' 2>/dev/null)
235
+
236
+ if [ -z "$STATE" ]; then
237
+ # Deployment exists but has no status yet → not confirmed.
238
+ emit_receipt "$DEP_SHA" "no_status" "$(now_iso)" "$TARGET"
239
+ exit 0
240
+ fi
241
+
242
+ # readback_time MUST be the authority's own timestamp (the status
243
+ # created_at), so the gate's staleness check is anchored to when the
244
+ # authority observed the state — not to when this hook ran.
245
+ [ -n "$CREATED_AT" ] || CREATED_AT=$(now_iso)
246
+ emit_receipt "$DEP_SHA" "$STATE" "$CREATED_AT" "$TARGET"
247
+ exit 0
@@ -16,7 +16,7 @@
16
16
  #
17
17
  # See: https://github.com/anthropics/claude-code/issues/40861
18
18
  #
19
- # TRIGGER: PreToolUse MATCHER: "Bash"
19
+ # TRIGGER: PreToolUse MATCHER: "Bash|PowerShell"
20
20
  #
21
21
  # Configuration:
22
22
  # CC_DEPLOY_COMMANDS — regex pattern for deploy commands
@@ -27,11 +27,34 @@
27
27
  # ================================================================
28
28
 
29
29
  INPUT=$(cat)
30
+ __CC_HOOK_INPUT="$INPUT"
31
+ # --- セッション識別子でファイルを分ける (2026-08-09 修正) ---
32
+ # 旧実装は "$$" を使っていたが、$$ はこのスクリプト自身のPIDで呼び出しごとに変わるため、
33
+ # 状態が一度も持続しなかった(実測: 200回呼ぶとファイルが200個でき、中身は全部 1)。
34
+ __CC_SID=""
35
+ if [ -n "${__CC_HOOK_INPUT:-}" ]; then
36
+ if command -v jq >/dev/null 2>&1; then
37
+ __CC_SID=$(printf '%s' "$__CC_HOOK_INPUT" | jq -r '.session_id // .sessionId // empty' 2>/dev/null)
38
+ fi
39
+ if [ -z "$__CC_SID" ] && command -v python3 >/dev/null 2>&1; then
40
+ __CC_SID=$(printf '%s' "$__CC_HOOK_INPUT" | python3 -c 'import sys,json
41
+ try:
42
+ d=json.load(sys.stdin); print(d.get("session_id") or d.get("sessionId") or "")
43
+ except Exception: print("")' 2>/dev/null)
44
+ fi
45
+ fi
46
+ if [ -n "$__CC_SID" ]; then
47
+ __CC_KEY=$(printf '%s' "$__CC_SID" | tr -c 'A-Za-z0-9_-' '_' | cut -c1-64)
48
+ else
49
+ __CC_KEY="nosession-$(date +%Y%m%d)"
50
+ fi
51
+ # --- ここまで ---
52
+
30
53
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
31
54
 
32
55
  [ -z "$COMMAND" ] && exit 0
33
56
 
34
- MARKER="/tmp/cc-deploy-pending-$$"
57
+ MARKER="/tmp/cc-deploy-pending-$__CC_KEY"
35
58
 
36
59
  # Configurable deploy command patterns
37
60
  DEPLOY_PATTERN="${CC_DEPLOY_COMMANDS:-systemctl\s+restart|docker\s+restart|docker-compose\s+up|docker\s+compose\s+up|\bdeploy\b|kubectl\s+apply|terraform\s+apply|heroku\s+.*push|fly\s+deploy}"