cc-safe-setup 29.8.0 → 30.0.5

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 +421 -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 +1718 -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,315 @@
1
+ #!/bin/bash
2
+ # Tests for aup-block-pattern-logger.sh
3
+ HOOK="$(dirname "$0")/../examples/aup-block-pattern-logger.sh"
4
+ PASS=0
5
+ FAIL=0
6
+
7
+ run_test() {
8
+ local desc="$1"
9
+ local result="$2"
10
+ if [ "$result" = "pass" ]; then
11
+ echo " PASS: $desc"
12
+ PASS=$((PASS + 1))
13
+ else
14
+ echo " FAIL: $desc"
15
+ FAIL=$((FAIL + 1))
16
+ fi
17
+ }
18
+
19
+ # Per-test scratch log; cleaned between cases.
20
+ TMPDIR=$(mktemp -d)
21
+ trap 'rm -rf "$TMPDIR"' EXIT
22
+ LOG="$TMPDIR/aup-block.log"
23
+
24
+ reset_log() {
25
+ rm -f "$LOG"
26
+ unset CC_AUP_BLOCK_LOGGER_DISABLE
27
+ unset CC_AUP_BLOCK_LOGGER_QUIET
28
+ unset CC_AUP_BLOCK_LOGGER_MAX_LINES
29
+ }
30
+
31
+ echo "Testing aup-block-pattern-logger.sh"
32
+ echo "===================================="
33
+
34
+ # Test 1: DISABLE=1 silences entirely, no log file created
35
+ reset_log
36
+ INPUT='{"tool_name":"Bash","tool_output":"API Error: ...violate our Usage Policy. This request triggered cyber-related safeguards."}'
37
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOGGER_DISABLE=1 CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1)
38
+ EXIT=$?
39
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ] && [ ! -f "$LOG" ]; then
40
+ run_test "DISABLE=1 silences entirely, no log written" pass
41
+ else
42
+ run_test "DISABLE=1 silences (exit=$EXIT, out_len=${#OUT}, log_exists=$([ -f "$LOG" ] && echo yes || echo no))" fail
43
+ fi
44
+
45
+ # Test 2: Empty input → silent exit
46
+ reset_log
47
+ OUT=$(printf '' | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1)
48
+ EXIT=$?
49
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ] && [ ! -f "$LOG" ]; then
50
+ run_test "Empty stdin → silent, no log" pass
51
+ else
52
+ run_test "Empty stdin (exit=$EXIT, out_len=${#OUT})" fail
53
+ fi
54
+
55
+ # Test 3: Tool output without AUP pattern → no log, no warning
56
+ reset_log
57
+ INPUT='{"tool_name":"Bash","tool_output":"normal output, no errors here"}'
58
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1)
59
+ EXIT=$?
60
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ] && [ ! -f "$LOG" ]; then
61
+ run_test "Benign tool output → no log, no warning" pass
62
+ else
63
+ run_test "Benign output (exit=$EXIT, out_len=${#OUT}, log_exists=$([ -f "$LOG" ] && echo yes || echo no))" fail
64
+ fi
65
+
66
+ # Test 4: cyber-safeguards pattern → log line + advisory
67
+ reset_log
68
+ INPUT='{"tool_name":"Bash","tool_output":"API Error: ...violate our Usage Policy. This request triggered cyber-related safeguards."}'
69
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" 2>&1)
70
+ EXIT=$?
71
+ LINE_COUNT=$(wc -l < "$LOG" 2>/dev/null || echo 0)
72
+ if [ "$EXIT" = "0" ] && [ "$LINE_COUNT" = "1" ] && grep -q "cyber-safeguards" "$LOG" && echo "$OUT" | grep -q "block detected"; then
73
+ run_test "cyber-safeguards pattern → log + stderr advisory" pass
74
+ else
75
+ run_test "cyber-safeguards pattern (exit=$EXIT, lines=$LINE_COUNT)" fail
76
+ fi
77
+
78
+ # Test 5: safety-guardrails pattern → log with correct kind
79
+ reset_log
80
+ INPUT='{"tool_name":"Edit","tool_output":"This request triggered safety guardrails. Rephrase your prompt or rewind to continue."}'
81
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" 2>&1)
82
+ if grep -q "safety-guardrails" "$LOG"; then
83
+ run_test "safety-guardrails pattern recorded" pass
84
+ else
85
+ run_test "safety-guardrails pattern (log: $(cat "$LOG" 2>/dev/null))" fail
86
+ fi
87
+
88
+ # Test 6: rephrase-rewind variant (cyber clause absent) → rephrase-rewind kind
89
+ reset_log
90
+ INPUT='{"tool_name":"Read","tool_output":"Rephrase your prompt or rewind to continue with this session."}'
91
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
92
+ if grep -q "rephrase-rewind" "$LOG"; then
93
+ run_test "rephrase-rewind pattern recorded" pass
94
+ else
95
+ run_test "rephrase-rewind pattern (log: $(cat "$LOG" 2>/dev/null))" fail
96
+ fi
97
+
98
+ # Test 7: Generic API error fallback
99
+ reset_log
100
+ INPUT='{"tool_name":"Bash","tool_output":"API Error: Claude Code is unable to respond to this request right now."}'
101
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
102
+ if grep -q "usage-policy-api" "$LOG"; then
103
+ run_test "usage-policy-api fallback recorded" pass
104
+ else
105
+ run_test "usage-policy-api fallback (log: $(cat "$LOG" 2>/dev/null))" fail
106
+ fi
107
+
108
+ # Test 8: QUIET=1 suppresses stderr but still logs
109
+ reset_log
110
+ INPUT='{"tool_name":"Bash","tool_output":"This request triggered cyber-related safeguards."}'
111
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" 2>&1)
112
+ LINE_COUNT=$(wc -l < "$LOG" 2>/dev/null || echo 0)
113
+ if [ -z "$OUT" ] && [ "$LINE_COUNT" = "1" ]; then
114
+ run_test "QUIET=1 suppresses stderr but still logs" pass
115
+ else
116
+ run_test "QUIET=1 (out_len=${#OUT}, lines=$LINE_COUNT)" fail
117
+ fi
118
+
119
+ # Test 9: Log line schema — 5 pipe-delimited fields
120
+ reset_log
121
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
122
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" >/dev/null 2>&1
123
+ FIELDS=$(awk -F'|' '{print NF}' "$LOG" 2>/dev/null)
124
+ if [ "$FIELDS" = "5" ]; then
125
+ run_test "Log line has 5 pipe-delimited fields" pass
126
+ else
127
+ run_test "Log schema fields=$FIELDS (line: $(cat "$LOG" 2>/dev/null))" fail
128
+ fi
129
+
130
+ # Test 10: Model field defaults to "default-routing" when ANTHROPIC_MODEL unset
131
+ reset_log
132
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
133
+ unset ANTHROPIC_MODEL
134
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
135
+ if awk -F'|' '{print $2}' "$LOG" | grep -q "default-routing"; then
136
+ run_test "Model field is 'default-routing' when ANTHROPIC_MODEL unset" pass
137
+ else
138
+ run_test "Model field default (line: $(cat "$LOG" 2>/dev/null))" fail
139
+ fi
140
+
141
+ # Test 11: Model field reflects ANTHROPIC_MODEL when set
142
+ reset_log
143
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
144
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" >/dev/null 2>&1
145
+ if awk -F'|' '{print $2}' "$LOG" | grep -q "claude-opus-4-7"; then
146
+ run_test "Model field reflects ANTHROPIC_MODEL pin" pass
147
+ else
148
+ run_test "Model field pin (line: $(cat "$LOG" 2>/dev/null))" fail
149
+ fi
150
+
151
+ # Test 12: Cumulative count rises across invocations
152
+ reset_log
153
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
154
+ for _ in 1 2 3; do
155
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" >/dev/null 2>&1
156
+ done
157
+ LINE_COUNT=$(wc -l < "$LOG" 2>/dev/null || echo 0)
158
+ if [ "$LINE_COUNT" = "3" ]; then
159
+ run_test "Three invocations → three log lines (idempotent append)" pass
160
+ else
161
+ run_test "Cumulative log lines=$LINE_COUNT (expected 3)" fail
162
+ fi
163
+
164
+ # Test 13: Stderr advisory shows running count for the current model
165
+ reset_log
166
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
167
+ # Seed 4 prior entries silently
168
+ for _ in 1 2 3 4; do
169
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" >/dev/null 2>&1
170
+ done
171
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" 2>&1)
172
+ if echo "$OUT" | grep -qE "Cumulative blocks logged for this model: 5"; then
173
+ run_test "Advisory shows running count for current model" pass
174
+ else
175
+ run_test "Running count advisory (OUT: $OUT)" fail
176
+ fi
177
+
178
+ # Test 14: Log rotation when CC_AUP_BLOCK_LOGGER_MAX_LINES exceeded
179
+ reset_log
180
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
181
+ for _ in $(seq 1 12); do
182
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 CC_AUP_BLOCK_LOGGER_MAX_LINES=10 bash "$HOOK" >/dev/null 2>&1
183
+ done
184
+ LINE_COUNT=$(wc -l < "$LOG" 2>/dev/null || echo 0)
185
+ # After 12 invocations with rotation threshold 10, log should be rotated down (keep half = 5)
186
+ # So the count should be at most 10, but rotation triggers when > 10 so we expect <= 6 (5 rotated + 1 new) on the next round
187
+ # We allow any value in [5, 10] since rotation timing depends on the order of append-then-check.
188
+ if [ "$LINE_COUNT" -ge 5 ] 2>/dev/null && [ "$LINE_COUNT" -le 10 ] 2>/dev/null; then
189
+ run_test "Log rotation honors MAX_LINES (final lines=$LINE_COUNT, in [5,10])" pass
190
+ else
191
+ run_test "Log rotation (final lines=$LINE_COUNT, expected 5-10)" fail
192
+ fi
193
+
194
+ # Test 15: Tool name extracted into log
195
+ reset_log
196
+ INPUT='{"tool_name":"Edit","tool_output":"triggered cyber-related safeguards"}'
197
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
198
+ if awk -F'|' '{print $3}' "$LOG" | grep -q "^Edit$"; then
199
+ run_test "Tool name field extracted correctly" pass
200
+ else
201
+ run_test "Tool name extraction (line: $(cat "$LOG" 2>/dev/null))" fail
202
+ fi
203
+
204
+ # Test 16: Excerpt truncated to 120 chars max
205
+ reset_log
206
+ LONG=$(printf 'triggered cyber-related safeguards %.0s' $(seq 1 20))
207
+ INPUT="{\"tool_name\":\"Bash\",\"tool_output\":\"$LONG\"}"
208
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
209
+ EXCERPT=$(awk -F'|' '{print $5}' "$LOG")
210
+ EXCERPT_LEN=${#EXCERPT}
211
+ if [ "$EXCERPT_LEN" -le 120 ] 2>/dev/null; then
212
+ run_test "Excerpt truncated to <=120 chars (got=$EXCERPT_LEN)" pass
213
+ else
214
+ run_test "Excerpt length (got=$EXCERPT_LEN)" fail
215
+ fi
216
+
217
+ # Test 17: Pipe characters in output stripped from excerpt (schema safety)
218
+ reset_log
219
+ INPUT='{"tool_name":"Bash","tool_output":"line with | pipe | in it triggered cyber-related safeguards"}'
220
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
221
+ FIELDS=$(awk -F'|' '{print NF}' "$LOG")
222
+ if [ "$FIELDS" = "5" ]; then
223
+ run_test "Pipes stripped from excerpt → schema preserved (5 fields)" pass
224
+ else
225
+ run_test "Schema preserved with pipes in output (fields=$FIELDS)" fail
226
+ fi
227
+
228
+ # Test 18: Hook never blocks the tool (exit 0 in all paths)
229
+ reset_log
230
+ EXIT_CODES=""
231
+ for case in "disable" "empty" "benign" "block" "block+quiet"; do
232
+ case "$case" in
233
+ "disable") OUT=$(echo '{}' | CC_AUP_BLOCK_LOGGER_DISABLE=1 bash "$HOOK" 2>&1); EXIT=$? ;;
234
+ "empty") OUT=$(printf '' | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1); EXIT=$? ;;
235
+ "benign") OUT=$(echo '{"tool_name":"Bash","tool_output":"ok"}' | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1); EXIT=$? ;;
236
+ "block") OUT=$(echo '{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}' | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1); EXIT=$? ;;
237
+ "block+quiet") OUT=$(echo '{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}' | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" 2>&1); EXIT=$? ;;
238
+ esac
239
+ EXIT_CODES="$EXIT_CODES $EXIT"
240
+ done
241
+ NONZERO=$(echo "$EXIT_CODES" | tr ' ' '\n' | grep -v "^$" | grep -v "^0$" | head -1)
242
+ if [ -z "$NONZERO" ]; then
243
+ run_test "Hook never blocks (all 5 paths exit 0)" pass
244
+ else
245
+ run_test "Hook never blocks (exit codes: $EXIT_CODES)" fail
246
+ fi
247
+
248
+ # Test 19: Advisory mentions partner hook aup-false-positive-helper
249
+ reset_log
250
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
251
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1)
252
+ if echo "$OUT" | grep -q "aup-false-positive-helper"; then
253
+ run_test "Advisory references partner hook" pass
254
+ else
255
+ run_test "Partner hook reference (OUT: $OUT)" fail
256
+ fi
257
+
258
+ # Test 20: Advisory recommends Sonnet swap path
259
+ reset_log
260
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
261
+ OUT=$(printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" bash "$HOOK" 2>&1)
262
+ if echo "$OUT" | grep -qi "sonnet"; then
263
+ run_test "Advisory recommends Sonnet swap" pass
264
+ else
265
+ run_test "Advisory Sonnet swap (OUT: $OUT)" fail
266
+ fi
267
+
268
+ # Test 21: Pattern priority — cyber-safeguards wins over usage-policy when both present
269
+ reset_log
270
+ INPUT='{"tool_name":"Bash","tool_output":"violate our Usage Policy. This request triggered cyber-related safeguards."}'
271
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
272
+ KIND=$(awk -F'|' '{print $4}' "$LOG")
273
+ if [ "$KIND" = "cyber-safeguards" ]; then
274
+ run_test "Pattern priority: cyber-safeguards beats usage-policy" pass
275
+ else
276
+ run_test "Pattern priority (got kind=$KIND)" fail
277
+ fi
278
+
279
+ # Test 22: Custom CC_AUP_BLOCK_LOG_PATH honored
280
+ reset_log
281
+ CUSTOM_LOG="$TMPDIR/custom-aup.log"
282
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
283
+ printf '%s' "$INPUT" | CC_AUP_BLOCK_LOG_PATH="$CUSTOM_LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" >/dev/null 2>&1
284
+ if [ -f "$CUSTOM_LOG" ] && grep -q "cyber-safeguards" "$CUSTOM_LOG"; then
285
+ run_test "Custom log path honored" pass
286
+ else
287
+ run_test "Custom log path (exists=$([ -f "$CUSTOM_LOG" ] && echo yes || echo no))" fail
288
+ fi
289
+
290
+ # Test 23: Missing jq fallback (simulate by setting PATH without jq)
291
+ reset_log
292
+ INPUT='{"tool_name":"Bash","tool_output":"triggered cyber-related safeguards"}'
293
+ # Create a temp PATH that omits jq. Resolve real on-disk binaries via /usr/bin and
294
+ # /bin so shell functions/aliases don't shadow the lookup.
295
+ NOJQ_DIR=$(mktemp -d)
296
+ for bin in bash cat head tail grep awk sed mkdir wc tr date printf rm mv ls dirname; do
297
+ for candidate in /usr/bin/$bin /bin/$bin /usr/local/bin/$bin; do
298
+ if [ -x "$candidate" ]; then
299
+ ln -sf "$candidate" "$NOJQ_DIR/$bin"
300
+ break
301
+ fi
302
+ done
303
+ done
304
+ OUT=$(printf '%s' "$INPUT" | PATH="$NOJQ_DIR" CC_AUP_BLOCK_LOG_PATH="$LOG" CC_AUP_BLOCK_LOGGER_QUIET=1 bash "$HOOK" 2>&1)
305
+ EXIT=$?
306
+ rm -rf "$NOJQ_DIR"
307
+ if [ "$EXIT" = "0" ] && [ -f "$LOG" ] && grep -q "cyber-safeguards" "$LOG"; then
308
+ run_test "jq-missing fallback path → still logs (grep fallback)" pass
309
+ else
310
+ run_test "jq fallback (exit=$EXIT, log exists=$([ -f "$LOG" ] && echo yes || echo no))" fail
311
+ fi
312
+
313
+ echo "===================================="
314
+ echo "Results: $PASS passed, $FAIL failed"
315
+ [ "$FAIL" = "0" ] && exit 0 || exit 1
@@ -0,0 +1,188 @@
1
+ #!/bin/bash
2
+ # Tests for aup-false-positive-helper.sh
3
+ HOOK="$(dirname "$0")/../examples/aup-false-positive-helper.sh"
4
+ PASS=0
5
+ FAIL=0
6
+
7
+ run_test() {
8
+ local desc="$1"
9
+ local result="$2"
10
+ if [ "$result" = "pass" ]; then
11
+ echo " PASS: $desc"
12
+ PASS=$((PASS + 1))
13
+ else
14
+ echo " FAIL: $desc"
15
+ FAIL=$((FAIL + 1))
16
+ fi
17
+ }
18
+
19
+ echo "Testing aup-false-positive-helper.sh"
20
+ echo "===================================="
21
+
22
+ # Test 1: QUIET=1 always silences, regardless of other state
23
+ OUT=$(unset ANTHROPIC_MODEL; CC_AUP_FALSE_POSITIVE_HELPER_QUIET=1 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 \
24
+ ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" 2>&1)
25
+ EXIT=$?
26
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
27
+ run_test "QUIET=1 silences even when Opus + REMIND=1" pass
28
+ else
29
+ run_test "QUIET=1 silences (exit=$EXIT, out_len=${#OUT})" fail
30
+ fi
31
+
32
+ # Test 2: ANTHROPIC_MODEL unset → silent (default routing, no specific advisory)
33
+ OUT=$(unset ANTHROPIC_MODEL CC_AUP_FALSE_POSITIVE_HELPER_REMIND CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
34
+ bash "$HOOK" 2>&1)
35
+ EXIT=$?
36
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
37
+ run_test "ANTHROPIC_MODEL unset → silent" pass
38
+ else
39
+ run_test "ANTHROPIC_MODEL unset → silent (exit=$EXIT, out_len=${#OUT})" fail
40
+ fi
41
+
42
+ # Test 3: ANTHROPIC_MODEL=Sonnet variant → silent (unaffected by cluster)
43
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_REMIND CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
44
+ ANTHROPIC_MODEL=claude-sonnet-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
45
+ EXIT=$?
46
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
47
+ run_test "Sonnet pinned + REMIND=1 → silent (unaffected)" pass
48
+ else
49
+ run_test "Sonnet pinned silences (exit=$EXIT, out_len=${#OUT})" fail
50
+ fi
51
+
52
+ # Test 4: ANTHROPIC_MODEL=Sonnet 4.6 → silent
53
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_REMIND CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
54
+ ANTHROPIC_MODEL=claude-sonnet-4-6 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
55
+ EXIT=$?
56
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
57
+ run_test "Sonnet 4.6 pinned + REMIND=1 → silent" pass
58
+ else
59
+ run_test "Sonnet 4.6 silences (exit=$EXIT)" fail
60
+ fi
61
+
62
+ # Test 5: Opus pinned but REMIND unset → silent (opt-in only)
63
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_REMIND CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
64
+ ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" 2>&1)
65
+ EXIT=$?
66
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
67
+ run_test "Opus pinned, REMIND unset → silent (opt-in default off)" pass
68
+ else
69
+ run_test "Opus pinned, REMIND unset (exit=$EXIT, out_len=${#OUT})" fail
70
+ fi
71
+
72
+ # Test 6: Opus + REMIND=1 → emit advisory
73
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
74
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
75
+ EXIT=$?
76
+ if [ "$EXIT" = "0" ] && echo "$OUT" | grep -q "ANTHROPIC_MODEL is pinned"; then
77
+ run_test "Opus + REMIND=1 → advisory emitted" pass
78
+ else
79
+ run_test "Opus + REMIND=1 → advisory (exit=$EXIT, out_len=${#OUT})" fail
80
+ fi
81
+
82
+ # Test 7: Opus 4.6 1M variant + REMIND=1 → also emits (lowercase opus pattern)
83
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
84
+ ANTHROPIC_MODEL=claude-opus-4-6-1m CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
85
+ if echo "$OUT" | grep -q "ANTHROPIC_MODEL is pinned"; then
86
+ run_test "Opus 4.6 1M variant + REMIND=1 → advisory emitted" pass
87
+ else
88
+ run_test "Opus 4.6 1M emits advisory" fail
89
+ fi
90
+
91
+ # Test 8: Advisory mentions the four operator-side mitigation paths
92
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
93
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
94
+ if echo "$OUT" | grep -q "1\." && echo "$OUT" | grep -q "2\." && echo "$OUT" | grep -q "3\." && echo "$OUT" | grep -q "4\."; then
95
+ run_test "Advisory enumerates four mitigation paths" pass
96
+ else
97
+ run_test "Advisory enumerates four mitigation paths" fail
98
+ fi
99
+
100
+ # Test 9: Advisory mentions Sonnet as the model swap path
101
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
102
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
103
+ if echo "$OUT" | grep -qi "sonnet"; then
104
+ run_test "Advisory recommends Sonnet for model swap path" pass
105
+ else
106
+ run_test "Advisory mentions Sonnet" fail
107
+ fi
108
+
109
+ # Test 10: Advisory mentions CVP program
110
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
111
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
112
+ if echo "$OUT" | grep -qi "cyber.verification.program\|CVP"; then
113
+ run_test "Advisory references the Cyber Verification Program" pass
114
+ else
115
+ run_test "Advisory references CVP" fail
116
+ fi
117
+
118
+ # Test 11: Advisory mentions the QUIET suppress env var
119
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
120
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
121
+ if echo "$OUT" | grep -q "CC_AUP_FALSE_POSITIVE_HELPER_QUIET"; then
122
+ run_test "Advisory explains how to suppress with QUIET=1" pass
123
+ else
124
+ run_test "Advisory mentions QUIET" fail
125
+ fi
126
+
127
+ # Test 12: Advisory references the upstream GitHub tracker issues
128
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
129
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
130
+ if echo "$OUT" | grep -q "github.com/anthropics/claude-code/issues"; then
131
+ run_test "Advisory links upstream issue tracker entries" pass
132
+ else
133
+ run_test "Advisory links upstream tracker" fail
134
+ fi
135
+
136
+ # Test 13: ANTHROPIC_MODEL='' (empty) treated as unset → silent
137
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
138
+ ANTHROPIC_MODEL="" CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
139
+ EXIT=$?
140
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
141
+ run_test "ANTHROPIC_MODEL='' (empty) → silent (treated as unset)" pass
142
+ else
143
+ run_test "Empty ANTHROPIC_MODEL silences (exit=$EXIT, out_len=${#OUT})" fail
144
+ fi
145
+
146
+ # Test 14: Mixed-case Opus pattern (e.g., capitalized OPUS) → emits
147
+ OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
148
+ ANTHROPIC_MODEL=Claude-Opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
149
+ if echo "$OUT" | grep -q "ANTHROPIC_MODEL is pinned"; then
150
+ run_test "Mixed-case 'Opus' pattern → advisory emitted" pass
151
+ else
152
+ run_test "Mixed-case Opus emits" fail
153
+ fi
154
+
155
+ # Test 15: Idempotency — two invocations produce identical output
156
+ OUT1=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
157
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
158
+ OUT2=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; \
159
+ ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1)
160
+ if [ "$OUT1" = "$OUT2" ]; then
161
+ run_test "Idempotent: two invocations produce identical output" pass
162
+ else
163
+ run_test "Idempotent advisory output" fail
164
+ fi
165
+
166
+ # Test 16: Hook never blocks — all paths exit 0
167
+ EXIT_CODES=""
168
+ for case in "QUIET=1" "unset" "Sonnet+REMIND" "Opus-no-REMIND" "Opus+REMIND" "empty-model"; do
169
+ case "$case" in
170
+ "QUIET=1") OUT=$(CC_AUP_FALSE_POSITIVE_HELPER_QUIET=1 bash "$HOOK" 2>&1); EXIT=$? ;;
171
+ "unset") OUT=$(unset ANTHROPIC_MODEL CC_AUP_FALSE_POSITIVE_HELPER_REMIND CC_AUP_FALSE_POSITIVE_HELPER_QUIET; bash "$HOOK" 2>&1); EXIT=$? ;;
172
+ "Sonnet+REMIND") OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; ANTHROPIC_MODEL=claude-sonnet-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1); EXIT=$? ;;
173
+ "Opus-no-REMIND") OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_REMIND CC_AUP_FALSE_POSITIVE_HELPER_QUIET; ANTHROPIC_MODEL=claude-opus-4-7 bash "$HOOK" 2>&1); EXIT=$? ;;
174
+ "Opus+REMIND") OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; ANTHROPIC_MODEL=claude-opus-4-7 CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1); EXIT=$? ;;
175
+ "empty-model") OUT=$(unset CC_AUP_FALSE_POSITIVE_HELPER_QUIET; ANTHROPIC_MODEL="" CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1 bash "$HOOK" 2>&1); EXIT=$? ;;
176
+ esac
177
+ EXIT_CODES="$EXIT_CODES $EXIT"
178
+ done
179
+ NONZERO=$(echo "$EXIT_CODES" | tr ' ' '\n' | grep -v "^$" | grep -v "^0$" | head -1)
180
+ if [ -z "$NONZERO" ]; then
181
+ run_test "Hook never blocks (all 6 paths exit 0)" pass
182
+ else
183
+ run_test "Hook never blocks (exit codes: $EXIT_CODES)" fail
184
+ fi
185
+
186
+ echo "===================================="
187
+ echo "Results: $PASS passed, $FAIL failed"
188
+ [ "$FAIL" = "0" ] && exit 0 || exit 1