cc-safe-setup 29.7.0 → 30.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1022) hide show
  1. package/.claude-plugin/marketplace.json +72 -19
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CONTRIBUTING.md +7 -2
  4. package/COOKBOOK.md +50 -46
  5. package/LICENSE +21 -0
  6. package/MIGRATION.md +8 -8
  7. package/README.md +419 -512
  8. package/SAFETY_CHECKLIST.md +15 -7
  9. package/SERVICES.md +194 -0
  10. package/SETTINGS_REFERENCE.md +236 -17
  11. package/SKILL.md +5 -5
  12. package/TROUBLESHOOTING.md +35 -14
  13. package/action.yml +12 -4
  14. package/audit/README.md +84 -0
  15. package/audit/audit-checklist.md +152 -0
  16. package/audit/boundary-selftest.sh +85 -0
  17. package/audit/boundary.sh +123 -0
  18. package/audit/count-hooks.py +42 -0
  19. package/audit/find-dead-hooks.sh +82 -0
  20. package/audit/find-unfirable-rules.sh +142 -0
  21. package/audit/fire.sh +97 -0
  22. package/audit/selftest.sh +42 -0
  23. package/audit/unfirable-selftest.sh +81 -0
  24. package/audit-web/index.html +9 -9
  25. package/examples/README.md +54 -17
  26. package/examples/account-billing-log.sh +98 -0
  27. package/examples/account-routing-preflight.sh +123 -0
  28. package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
  29. package/examples/agent-view-quota-decrement.sh +32 -0
  30. package/examples/agent-view-quota-warn.sh +94 -0
  31. package/examples/agents-md-edit-drift-warner.sh +223 -0
  32. package/examples/agents-md-loader.sh +160 -0
  33. package/examples/agents-md-sync-checker.sh +102 -0
  34. package/examples/ai-slop-punctuation-arrest.sh +210 -0
  35. package/examples/allowlist.sh +70 -10
  36. package/examples/always-allow-pattern-suggester.sh +125 -0
  37. package/examples/ansible-vault-guard.sh +2 -1
  38. package/examples/anthropic-base-url-guard.sh +76 -0
  39. package/examples/api-busyloop-guard.sh +123 -0
  40. package/examples/api-endpoint-guard.sh +12 -0
  41. package/examples/api-key-in-url-guard.sh +17 -1
  42. package/examples/api-rate-limit-guard.sh +36 -1
  43. package/examples/api-rate-limit-tracker.sh +12 -0
  44. package/examples/articulated-scope-capture.sh +101 -0
  45. package/examples/askuserquestion-autonomy-gate.sh +102 -0
  46. package/examples/attachment-traversal-guard.sh +118 -0
  47. package/examples/aup-block-pattern-logger.sh +161 -0
  48. package/examples/aup-false-positive-helper.sh +124 -0
  49. package/examples/aup-large-tool-output-warner.sh +282 -0
  50. package/examples/aup-retry-loop-guard.sh +229 -0
  51. package/examples/auth-expiry-reminder.sh +157 -0
  52. package/examples/auth-macos-sleep-detector.sh +185 -0
  53. package/examples/auth-path-detector.sh +171 -0
  54. package/examples/auth-status-checker.sh +157 -0
  55. package/examples/authorized-reconfirmation-detector.sh +195 -0
  56. package/examples/auto-approve-build.sh +39 -0
  57. package/examples/auto-approve-cargo.sh +31 -1
  58. package/examples/auto-approve-docker.sh +35 -0
  59. package/examples/auto-approve-git-read.sh +37 -14
  60. package/examples/auto-approve-go.sh +30 -1
  61. package/examples/auto-approve-gradle.sh +29 -1
  62. package/examples/auto-approve-make.sh +29 -1
  63. package/examples/auto-approve-maven.sh +29 -1
  64. package/examples/auto-approve-python.sh +41 -1
  65. package/examples/auto-approve-readonly-tools.sh +1 -0
  66. package/examples/auto-approve-readonly.sh +110 -33
  67. package/examples/auto-approve-ssh.sh +30 -1
  68. package/examples/auto-approve-test.sh +44 -0
  69. package/examples/auto-checkpoint.sh +1 -1
  70. package/examples/auto-compact-prep.sh +0 -0
  71. package/examples/auto-git-checkpoint.sh +0 -0
  72. package/examples/auto-mode-safe-commands.sh +53 -1
  73. package/examples/auto-mode-safety-enforcer.sh +151 -4
  74. package/examples/auto-push-session-branch.sh +22 -0
  75. package/examples/aws-production-guard.sh +13 -1
  76. package/examples/aws-region-guard.sh +1 -1
  77. package/examples/background-cost-launch-guard.sh +82 -0
  78. package/examples/background-task-guard.sh +12 -0
  79. package/examples/backup-before-refactor.sh +0 -0
  80. package/examples/banned-command-guard.sh +12 -0
  81. package/examples/bash-allowlist-secondary-check.sh +157 -0
  82. package/examples/bash-domain-allowlist.sh +12 -0
  83. package/examples/bash-fanout-bounded-rewriter.sh +191 -0
  84. package/examples/bash-heuristic-approver.sh +112 -10
  85. package/examples/bash-project-fence.sh +194 -0
  86. package/examples/bash-safety-auto-deny.sh +12 -0
  87. package/examples/bash-secret-output-detector.sh +44 -3
  88. package/examples/bash-trace-guard.sh +12 -0
  89. package/examples/bashrc-safety-check.sh +0 -0
  90. package/examples/bg-permission-prompt-warner.sh +182 -0
  91. package/examples/bg-task-cooldown-guard.sh +12 -0
  92. package/examples/binary-read-detector.sh +135 -0
  93. package/examples/binary-upload-guard.sh +12 -0
  94. package/examples/block-database-wipe.sh +35 -10
  95. package/examples/branch-name-check.sh +8 -3
  96. package/examples/branch-naming-convention.sh +0 -0
  97. package/examples/broad-find-guard.sh +12 -0
  98. package/examples/broad-prefix-session-trap-warner.sh +106 -0
  99. package/examples/bulk-file-delete-guard.sh +45 -0
  100. package/examples/bypass-mode-effective-verifier.sh +203 -0
  101. package/examples/cache-creation-drift-detector.sh +120 -0
  102. package/examples/cache-residue-detector.sh +195 -0
  103. package/examples/cache-tier-logger.sh +70 -0
  104. package/examples/cache-ttl-eviction-detector.sh +149 -0
  105. package/examples/cargo-publish-guard.sh +14 -1
  106. package/examples/case-insensitive-path-guard.sh +21 -2
  107. package/examples/case-sensitive-guard.sh +23 -2
  108. package/examples/cch-cache-guard.sh +0 -0
  109. package/examples/cch-sentinel-precommit-guard.sh +47 -0
  110. package/examples/check-abort-controller.sh +1 -1
  111. package/examples/check-accessibility.sh +0 -0
  112. package/examples/check-aria-labels.sh +0 -0
  113. package/examples/check-before-act-enforcer.sh +12 -0
  114. package/examples/check-charset-meta.sh +0 -0
  115. package/examples/check-cookie-flags.sh +0 -0
  116. package/examples/check-cors-config.sh +0 -0
  117. package/examples/check-csp-headers.sh +0 -0
  118. package/examples/check-csrf-protection.sh +0 -0
  119. package/examples/check-debounce.sh +1 -1
  120. package/examples/check-dependency-age.sh +0 -0
  121. package/examples/check-dependency-license.sh +0 -0
  122. package/examples/check-dockerfile-best-practice.sh +0 -0
  123. package/examples/check-error-boundaries.sh +0 -0
  124. package/examples/check-error-class.sh +1 -1
  125. package/examples/check-error-handling.sh +0 -0
  126. package/examples/check-error-logging.sh +1 -1
  127. package/examples/check-error-message.sh +0 -0
  128. package/examples/check-error-stack.sh +0 -0
  129. package/examples/check-favicon.sh +0 -0
  130. package/examples/check-git-hooks-compat.sh +0 -0
  131. package/examples/check-gitattributes.sh +0 -0
  132. package/examples/check-https-redirect.sh +0 -0
  133. package/examples/check-input-validation.sh +0 -0
  134. package/examples/check-lang-attribute.sh +0 -0
  135. package/examples/check-npm-scripts-exist.sh +0 -0
  136. package/examples/check-package-size.sh +0 -0
  137. package/examples/check-port-availability.sh +0 -0
  138. package/examples/check-promise-all.sh +1 -1
  139. package/examples/check-rate-limiting.sh +0 -0
  140. package/examples/check-return-types.sh +0 -0
  141. package/examples/check-semantic-versioning.sh +0 -0
  142. package/examples/check-suspense-fallback.sh +1 -1
  143. package/examples/check-test-exists.sh +0 -0
  144. package/examples/check-test-naming.sh +0 -0
  145. package/examples/check-timeout-cleanup.sh +1 -1
  146. package/examples/check-tls-version.sh +0 -0
  147. package/examples/check-unsubscribe.sh +1 -1
  148. package/examples/check-viewport-meta.sh +0 -0
  149. package/examples/check-worker-terminate.sh +1 -1
  150. package/examples/checkpoint-tamper-guard.sh +12 -0
  151. package/examples/chmod-guard.sh +12 -0
  152. package/examples/chown-guard.sh +24 -0
  153. package/examples/ci-workflow-guard.sh +6 -1
  154. package/examples/claim-verify-detector.sh +109 -0
  155. package/examples/claim-vs-caveat-checker.sh +77 -0
  156. package/examples/classifier-fallback-allow.sh +114 -40
  157. package/examples/claude-cache-gc.sh +1 -0
  158. package/examples/claude-code-version-pin-advisor.sh +183 -0
  159. package/examples/claude-md-reinjector.sh +129 -0
  160. package/examples/claude-md-size-monitor.sh +66 -0
  161. package/examples/claude-update-budget-guard.sh +123 -0
  162. package/examples/claude-update-smart.sh +113 -0
  163. package/examples/claudeignore-enforce-guard.sh +12 -0
  164. package/examples/claudemd-enforcer.sh +0 -0
  165. package/examples/claudemd-tool-prohibition.sh +128 -0
  166. package/examples/clear-command-confirm-guard.sh +32 -15
  167. package/examples/cli-config-pinning-detector.sh +162 -0
  168. package/examples/cliff-countdown-advisor.sh +96 -0
  169. package/examples/clipboard-secret-guard.sh +12 -0
  170. package/examples/closure-word-verify-gate.sh +150 -0
  171. package/examples/cloud-cli-guard.sh +39 -2
  172. package/examples/commit-all-scope-guard.sh +44 -0
  173. package/examples/commit-message-check.sh +1 -1
  174. package/examples/commit-message-quality.sh +6 -1
  175. package/examples/commitment-carry-forward-arrest.sh +361 -0
  176. package/examples/compact-alert-notification.sh +0 -0
  177. package/examples/compact-circuit-breaker.sh +72 -0
  178. package/examples/compact-dispatch-watchdog.sh +149 -0
  179. package/examples/completion-claim-without-verification-detector.sh +207 -0
  180. package/examples/composer-guard.sh +12 -0
  181. package/examples/compound-bash-permission-resolver.sh +156 -0
  182. package/examples/compound-command-allow.sh +1 -1
  183. package/examples/compound-command-deny-enforcer.sh +183 -0
  184. package/examples/compound-inject-guard.sh +12 -0
  185. package/examples/concurrent-edit-lock.sh +12 -0
  186. package/examples/conflict-marker-guard.sh +12 -0
  187. package/examples/consecutive-error-breaker.sh +0 -0
  188. package/examples/console-log-count.sh +1 -0
  189. package/examples/context-compact-advisor.sh +29 -2
  190. package/examples/context-length-budget.sh +69 -0
  191. package/examples/context-threshold-alert.sh +12 -0
  192. package/examples/context-usage-drift-alert.sh +41 -13
  193. package/examples/conversation-history-guard.sh +12 -0
  194. package/examples/core-file-protect-guard.sh +12 -0
  195. package/examples/cors-star-warn.sh +0 -0
  196. package/examples/cost-incident-self-audit.sh +162 -0
  197. package/examples/cowork-claude-md-load-checker.sh +100 -0
  198. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  199. package/examples/cowork-hook-absence-warner.sh +167 -0
  200. package/examples/cowork-model-picker-advisor.sh +115 -0
  201. package/examples/credential-exfil-guard.sh +65 -4
  202. package/examples/credential-file-cat-guard.sh +17 -1
  203. package/examples/cron-create-receipt.sh +112 -0
  204. package/examples/cron-modification-guard.sh +12 -0
  205. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  206. package/examples/cwd-project-boundary-guard.sh +0 -0
  207. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  208. package/examples/daily-cost-guard.sh +164 -0
  209. package/examples/daily-usage-tracker.sh +0 -0
  210. package/examples/dangerous-pip-flag-guard.sh +12 -0
  211. package/examples/db-connect-guard.sh +13 -1
  212. package/examples/denied-action-retry-guard.sh +12 -0
  213. package/examples/deny-bypass-detector.sh +12 -0
  214. package/examples/deny-rule-integrity-verifier.sh +181 -0
  215. package/examples/dependency-install-guard.sh +12 -0
  216. package/examples/deploy-guard.sh +14 -2
  217. package/examples/deploy-path-verify-guard.sh +12 -0
  218. package/examples/deployment-readback-gate.sh +135 -0
  219. package/examples/deployment-readback-gh-adapter.sh +247 -0
  220. package/examples/deployment-verify-guard.sh +25 -2
  221. package/examples/destructive-db-script-write-guard.sh +166 -0
  222. package/examples/destructive-migration-write-guard.sh +163 -0
  223. package/examples/diff-size-guard.sh +12 -0
  224. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  225. package/examples/disk-partition-guard.sh +12 -0
  226. package/examples/dispatch-allowlist-preflight.sh +301 -0
  227. package/examples/dispatch-liveness-watchdog.sh +216 -0
  228. package/examples/dispatch-receipt.sh +174 -0
  229. package/examples/django-migrate-guard.sh +12 -0
  230. package/examples/dns-config-guard.sh +12 -0
  231. package/examples/docker-dangerous-guard.sh +12 -0
  232. package/examples/docker-volume-guard.sh +0 -0
  233. package/examples/dockerfile-latest-guard.sh +1 -0
  234. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  235. package/examples/dotenv-commit-guard.sh +12 -0
  236. package/examples/dotenv-read-guard.sh +12 -0
  237. package/examples/dotfile-protection-guard.sh +12 -0
  238. package/examples/dotnet-build-on-edit.sh +1 -1
  239. package/examples/drizzle-migrate-guard.sh +27 -2
  240. package/examples/echo-probe-spam-detector.sh +176 -0
  241. package/examples/edit-counter-test-gate.sh +12 -0
  242. package/examples/edit-error-counter.sh +1 -1
  243. package/examples/edit-guard.sh +12 -0
  244. package/examples/edit-old-string-validator.sh +12 -0
  245. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  246. package/examples/edit-retry-loop-guard.sh +0 -0
  247. package/examples/edit-verify.sh +0 -0
  248. package/examples/env-inline-secret-guard.sh +14 -2
  249. package/examples/env-naming-convention.sh +0 -0
  250. package/examples/env-prod-guard.sh +0 -0
  251. package/examples/env-required-check.sh +0 -0
  252. package/examples/env-source-guard.sh +12 -0
  253. package/examples/env-var-check.sh +24 -1
  254. package/examples/ephemeral-container-detector.sh +147 -0
  255. package/examples/error-memory-guard.sh +12 -0
  256. package/examples/evidence-claim-gate.sh +187 -0
  257. package/examples/exploration-budget-guard.sh +89 -0
  258. package/examples/expo-eject-guard.sh +13 -0
  259. package/examples/extended-thinking-loop-guard.sh +139 -0
  260. package/examples/extended-thinking-resume-warning.sh +119 -0
  261. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  262. package/examples/fabricated-command-detector.sh +145 -0
  263. package/examples/false-disk-full-guard.sh +63 -0
  264. package/examples/feature-deprecation-detector.sh +109 -0
  265. package/examples/file-change-tracker.sh +1 -1
  266. package/examples/file-change-undo-tracker.sh +0 -0
  267. package/examples/file-edit-backup.sh +63 -14
  268. package/examples/file-reference-check.sh +0 -0
  269. package/examples/file-size-limit.sh +12 -0
  270. package/examples/financial-operation-guard.sh +12 -0
  271. package/examples/firewall-guard.sh +12 -0
  272. package/examples/fish-shell-wrapper.sh +125 -7
  273. package/examples/five-hundred-milestone.sh +1 -0
  274. package/examples/flask-static-route-guard.sh +89 -0
  275. package/examples/forbidden-response-phrase-detector.sh +161 -0
  276. package/examples/gem-push-guard.sh +13 -0
  277. package/examples/gh-cli-destructive-guard.sh +13 -1
  278. package/examples/git-checkout-safety-guard.sh +12 -0
  279. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  280. package/examples/git-config-guard.sh +12 -0
  281. package/examples/git-crypt-worktree-guard.sh +12 -0
  282. package/examples/git-filter-repo-guard.sh +56 -0
  283. package/examples/git-history-rewrite-guard.sh +12 -0
  284. package/examples/git-hook-bypass-guard.sh +0 -0
  285. package/examples/git-maintenance-guard.sh +83 -0
  286. package/examples/git-merge-conflict-prevent.sh +0 -0
  287. package/examples/git-message-length-check.sh +0 -0
  288. package/examples/git-message-length.sh +0 -0
  289. package/examples/git-operations-require-approval.sh +68 -14
  290. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  291. package/examples/git-push-blast-radius-guard.sh +218 -0
  292. package/examples/git-remote-guard.sh +24 -3
  293. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  294. package/examples/git-stash-before-checkout.sh +12 -0
  295. package/examples/git-stash-before-danger.sh +0 -0
  296. package/examples/git-submodule-guard.sh +69 -2
  297. package/examples/git-tag-guard.sh +12 -0
  298. package/examples/github-actions-secret-guard.sh +0 -0
  299. package/examples/gitignore-check.sh +0 -0
  300. package/examples/gitops-drift-guard.sh +12 -0
  301. package/examples/go-mod-tidy-warn.sh +1 -0
  302. package/examples/go-vet-after-edit.sh +12 -0
  303. package/examples/goal-iteration-limit-warner.sh +152 -0
  304. package/examples/grep-nul-false-negative-guard.sh +30 -0
  305. package/examples/growthbook-flag-monitor.sh +257 -0
  306. package/examples/hallucination-url-check.sh +1 -1
  307. package/examples/halt-signal-detector.sh +135 -0
  308. package/examples/handoff-on-clear.sh +65 -0
  309. package/examples/hardcoded-ip-guard.sh +1 -0
  310. package/examples/headless-empty-result-guard.sh +0 -0
  311. package/examples/headless-stop-guard.sh +0 -0
  312. package/examples/helm-install-guard.sh +2 -1
  313. package/examples/home-critical-bash-guard.sh +17 -1
  314. package/examples/hook-debug-wrapper.sh +6 -2
  315. package/examples/hook-permission-fixer.sh +0 -0
  316. package/examples/hook-self-disable-detector.sh +99 -0
  317. package/examples/hook-stdout-sanitizer.sh +6 -2
  318. package/examples/hook-tamper-guard.sh +12 -0
  319. package/examples/idle-session-cost-alert.sh +0 -0
  320. package/examples/image-dimension-guard.sh +109 -0
  321. package/examples/image-file-validator.sh +0 -0
  322. package/examples/iteration-quality-degradation-detector.sh +170 -0
  323. package/examples/java-compile-on-edit.sh +1 -1
  324. package/examples/json-syntax-check.sh +0 -0
  325. package/examples/k8s-production-guard.sh +13 -1
  326. package/examples/kill-process-guard.sh +12 -0
  327. package/examples/kubernetes-guard.sh +13 -1
  328. package/examples/laravel-artisan-guard.sh +13 -0
  329. package/examples/large-file-guard.sh +1 -1
  330. package/examples/log-level-guard.sh +0 -0
  331. package/examples/log-truncation-guard.sh +12 -0
  332. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  333. package/examples/loop-detector.sh +12 -0
  334. package/examples/magic-number-warn.sh +1 -0
  335. package/examples/main-branch-warn.sh +12 -0
  336. package/examples/markdown-link-check.sh +0 -0
  337. package/examples/max-concurrent-agents.sh +12 -0
  338. package/examples/max-edit-size-guard.sh +13 -0
  339. package/examples/max-file-count-guard.sh +0 -0
  340. package/examples/max-file-delete-count.sh +0 -0
  341. package/examples/max-function-length.sh +1 -0
  342. package/examples/max-import-count.sh +0 -0
  343. package/examples/max-subagent-count.sh +0 -0
  344. package/examples/mcp-config-freeze.sh +12 -0
  345. package/examples/mcp-config-poisoning-audit.sh +150 -0
  346. package/examples/mcp-data-boundary.sh +1 -1
  347. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  348. package/examples/mcp-orphan-leak-warner.sh +49 -0
  349. package/examples/mcp-permissions-ask-warner.sh +151 -0
  350. package/examples/mcp-routine-approval-detector.sh +154 -0
  351. package/examples/mcp-server-allowlist.sh +12 -0
  352. package/examples/mcp-server-guard.sh +12 -0
  353. package/examples/mcp-startup-bloat-detector.sh +87 -0
  354. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  355. package/examples/mcp-tool-audit-log.sh +0 -0
  356. package/examples/mcp-tool-guard.sh +101 -1
  357. package/examples/mcp-warmup-wait.sh +0 -0
  358. package/examples/memory-chain-audit.sh +56 -0
  359. package/examples/memory-orphan-detector.sh +188 -0
  360. package/examples/memory-write-guard.sh +99 -17
  361. package/examples/migration-verify-guard.sh +12 -0
  362. package/examples/model-swap-suggester.sh +177 -0
  363. package/examples/model-version-alert.sh +5 -1
  364. package/examples/model-version-lock.sh +63 -0
  365. package/examples/move-delete-sequence-guard.sh +33 -2
  366. package/examples/multi-file-plan-routing-gate.sh +192 -0
  367. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  368. package/examples/multi-window-auth-drift-detector.sh +183 -0
  369. package/examples/multiline-command-approver.sh +161 -23
  370. package/examples/nested-background-agent-guard.sh +109 -0
  371. package/examples/nested-spawn-inflight-guard.sh +178 -0
  372. package/examples/network-exfil-guard.sh +12 -0
  373. package/examples/network-guard.sh +12 -0
  374. package/examples/network-interface-guard.sh +12 -0
  375. package/examples/nextjs-env-guard.sh +1 -1
  376. package/examples/no-absolute-import.sh +0 -0
  377. package/examples/no-alert-confirm-prompt.sh +0 -0
  378. package/examples/no-anonymous-default-export.sh +0 -0
  379. package/examples/no-any-type.sh +0 -0
  380. package/examples/no-any-typescript.sh +1 -0
  381. package/examples/no-ask-human.sh +12 -0
  382. package/examples/no-assignment-in-condition.sh +0 -0
  383. package/examples/no-base64-exfil.sh +12 -0
  384. package/examples/no-callback-hell.sh +0 -0
  385. package/examples/no-circular-dependency.sh +0 -0
  386. package/examples/no-cleartext-storage.sh +0 -0
  387. package/examples/no-commented-code.sh +0 -0
  388. package/examples/no-commit-fixup.sh +0 -0
  389. package/examples/no-console-assert.sh +0 -0
  390. package/examples/no-console-error-swallow.sh +0 -0
  391. package/examples/no-console-in-prod.sh +0 -0
  392. package/examples/no-console-log-commit.sh +12 -0
  393. package/examples/no-console-log.sh +0 -0
  394. package/examples/no-console-time.sh +0 -0
  395. package/examples/no-cors-wildcard.sh +4 -1
  396. package/examples/no-curl-upload.sh +0 -0
  397. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  398. package/examples/no-dangling-await.sh +1 -0
  399. package/examples/no-debug-commit.sh +12 -0
  400. package/examples/no-debug-in-commit.sh +0 -0
  401. package/examples/no-deep-nesting.sh +0 -0
  402. package/examples/no-deep-relative-import.sh +1 -0
  403. package/examples/no-default-credentials.sh +0 -0
  404. package/examples/no-deploy-friday.sh +13 -1
  405. package/examples/no-disabled-test.sh +0 -0
  406. package/examples/no-document-write.sh +0 -0
  407. package/examples/no-empty-function.sh +0 -0
  408. package/examples/no-eval-in-template.sh +0 -0
  409. package/examples/no-eval-template.sh +3 -1
  410. package/examples/no-eval.sh +0 -0
  411. package/examples/no-exec-user-input.sh +0 -0
  412. package/examples/no-fixme-ship.sh +12 -0
  413. package/examples/no-floating-promises.sh +0 -0
  414. package/examples/no-force-flag.sh +22 -5
  415. package/examples/no-force-install.sh +0 -0
  416. package/examples/no-git-amend.sh +12 -0
  417. package/examples/no-git-rebase-public.sh +0 -0
  418. package/examples/no-global-install.sh +12 -0
  419. package/examples/no-global-state.sh +0 -0
  420. package/examples/no-hardcoded-port.sh +1 -0
  421. package/examples/no-hardcoded-url.sh +0 -0
  422. package/examples/no-helmet-missing.sh +0 -0
  423. package/examples/no-http-url.sh +1 -0
  424. package/examples/no-http-without-https.sh +0 -0
  425. package/examples/no-inline-style.sh +0 -0
  426. package/examples/no-inline-styles.sh +1 -0
  427. package/examples/no-innerhtml.sh +0 -0
  428. package/examples/no-install-global.sh +12 -0
  429. package/examples/no-jwt-in-url.sh +0 -0
  430. package/examples/no-large-commit.sh +0 -0
  431. package/examples/no-localhost-expose.sh +0 -0
  432. package/examples/no-magic-number.sh +0 -0
  433. package/examples/no-md5-sha1.sh +0 -0
  434. package/examples/no-mixed-line-endings.sh +8 -1
  435. package/examples/no-mutation-in-reducer.sh +0 -0
  436. package/examples/no-nested-ternary.sh +0 -0
  437. package/examples/no-network-exfil.sh +0 -0
  438. package/examples/no-open-redirect.sh +0 -0
  439. package/examples/no-output-truncation.sh +12 -0
  440. package/examples/no-package-downgrade.sh +0 -0
  441. package/examples/no-package-lock-edit.sh +12 -0
  442. package/examples/no-path-join-user-input.sh +0 -0
  443. package/examples/no-port-bind.sh +0 -0
  444. package/examples/no-process-exit.sh +0 -0
  445. package/examples/no-prototype-pollution.sh +0 -0
  446. package/examples/no-push-without-ci.sh +0 -0
  447. package/examples/no-push-without-tests.sh +12 -0
  448. package/examples/no-raw-password-in-url.sh +0 -0
  449. package/examples/no-root-user-docker.sh +1 -0
  450. package/examples/no-root-write.sh +12 -0
  451. package/examples/no-secrets-in-args.sh +4 -1
  452. package/examples/no-secrets-in-logs.sh +0 -0
  453. package/examples/no-sensitive-log.sh +0 -0
  454. package/examples/no-sleep-in-hooks.sh +0 -0
  455. package/examples/no-star-import-python.sh +1 -0
  456. package/examples/no-string-concat-sql.sh +0 -0
  457. package/examples/no-sudo-guard.sh +12 -0
  458. package/examples/no-sync-fs.sh +0 -0
  459. package/examples/no-todo-in-merge.sh +0 -0
  460. package/examples/no-todo-in-production.sh +1 -0
  461. package/examples/no-todo-without-issue.sh +0 -0
  462. package/examples/no-unused-import.sh +0 -0
  463. package/examples/no-var-keyword.sh +0 -0
  464. package/examples/no-verify-blocker.sh +12 -0
  465. package/examples/no-wget-piped-bash.sh +12 -0
  466. package/examples/no-wildcard-cors.sh +0 -0
  467. package/examples/no-wildcard-delete.sh +0 -0
  468. package/examples/no-wildcard-import.sh +0 -0
  469. package/examples/no-with-statement.sh +0 -0
  470. package/examples/no-write-outside-src.sh +0 -0
  471. package/examples/no-xml-external-entity.sh +0 -0
  472. package/examples/non-english-quality-warner.sh +156 -0
  473. package/examples/notify-waiting.sh +1 -1
  474. package/examples/npm-audit-warn.sh +0 -0
  475. package/examples/npm-global-install-guard.sh +12 -0
  476. package/examples/npm-publish-guard.sh +12 -0
  477. package/examples/npm-script-injection.sh +0 -0
  478. package/examples/npm-supply-chain-guard.sh +0 -0
  479. package/examples/nuxt-config-guard.sh +1 -0
  480. package/examples/oauth-refresh-monitor.sh +210 -0
  481. package/examples/opus-degradation-tracker.sh +187 -0
  482. package/examples/opus48-routine-task-warning.sh +196 -0
  483. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  484. package/examples/output-credential-scan.sh +1 -1
  485. package/examples/output-secret-mask.sh +31 -9
  486. package/examples/output-token-spike-detector.sh +145 -0
  487. package/examples/package-json-guard.sh +12 -0
  488. package/examples/package-lock-frozen.sh +12 -0
  489. package/examples/parallel-batch-size-limiter.sh +121 -0
  490. package/examples/parallel-cascade-detector.sh +116 -0
  491. package/examples/partial-view-claim-arrest.sh +174 -0
  492. package/examples/path-deny-bash-guard.sh +12 -0
  493. package/examples/path-traversal-guard.sh +12 -0
  494. package/examples/per-prompt-token-cap.sh +124 -0
  495. package/examples/permission-audit-log.sh +1 -1
  496. package/examples/permission-denial-enforcer.sh +12 -0
  497. package/examples/permission-entry-validator.sh +0 -0
  498. package/examples/persisted-1m-model-advisor.sh +88 -0
  499. package/examples/php-lint-on-edit.sh +1 -1
  500. package/examples/pii-upload-guard.sh +12 -0
  501. package/examples/pip-publish-guard.sh +13 -0
  502. package/examples/pip-requirements-guard.sh +12 -0
  503. package/examples/pip-venv-required.sh +12 -0
  504. package/examples/plan-mode-edit-guard.sh +12 -0
  505. package/examples/plan-mode-enforcer.sh +12 -0
  506. package/examples/plan-mode-strict-guard.sh +12 -0
  507. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  508. package/examples/plugin-process-cleanup.sh +0 -0
  509. package/examples/polyglot-rm-guard.sh +12 -0
  510. package/examples/post-compact-safety.sh +12 -0
  511. package/examples/post-edit-disk-verify.sh +152 -0
  512. package/examples/powershell-remove-item-guard.sh +85 -0
  513. package/examples/pr-description-check.sh +0 -0
  514. package/examples/pr-duplicate-guard.sh +13 -0
  515. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  516. package/examples/pre-compact-knowledge-save.sh +0 -0
  517. package/examples/pre-compact-transcript-backup.sh +0 -0
  518. package/examples/pre-execution-claim-detector.sh +179 -0
  519. package/examples/prefer-builtin-tools.sh +10 -1
  520. package/examples/prefer-const.sh +0 -0
  521. package/examples/prefer-dedicated-tools.sh +12 -0
  522. package/examples/prefer-optional-chaining.sh +0 -0
  523. package/examples/prisma-migrate-guard.sh +24 -7
  524. package/examples/production-port-kill-guard.sh +12 -0
  525. package/examples/prompt-injection-guard.sh +2 -1
  526. package/examples/prompt-usage-logger.sh +0 -0
  527. package/examples/protect-claudemd.sh +12 -0
  528. package/examples/protect-dotfiles.sh +12 -0
  529. package/examples/proxy-capture-suggester.sh +159 -0
  530. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  531. package/examples/public-repo-push-guard.sh +12 -0
  532. package/examples/push-requires-test-pass-record.sh +0 -0
  533. package/examples/push-requires-test-pass.sh +12 -0
  534. package/examples/quota-anomaly-detector.sh +173 -0
  535. package/examples/quota-reset-audit.sh +58 -0
  536. package/examples/quoted-flag-approver.sh +99 -10
  537. package/examples/rails-migration-guard.sh +12 -0
  538. package/examples/rate-limit-guard.sh +0 -0
  539. package/examples/read-all-files-enforcer.sh +0 -0
  540. package/examples/read-budget-guard.sh +12 -0
  541. package/examples/read-loop-detector.sh +59 -0
  542. package/examples/read-once-guard.sh +96 -0
  543. package/examples/read-only-mode.sh +12 -0
  544. package/examples/readme-exists-check.sh +0 -0
  545. package/examples/record-read-coverage.sh +73 -0
  546. package/examples/redirect-fragment-warner.sh +149 -0
  547. package/examples/redis-flushall-guard.sh +13 -0
  548. package/examples/redundant-read-blocker.sh +132 -0
  549. package/examples/refusal-arrest-gate.sh +248 -0
  550. package/examples/registry-publish-guard.sh +13 -1
  551. package/examples/remote-control-billing-classifier.sh +135 -0
  552. package/examples/replace-all-guard.sh +12 -0
  553. package/examples/repo-visibility-guard.sh +12 -0
  554. package/examples/reroute-after-block-guard.sh +150 -0
  555. package/examples/response-budget-guard.sh +0 -0
  556. package/examples/resume-drift-watcher.sh +57 -0
  557. package/examples/rg-replace-flag-detector.sh +125 -0
  558. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  559. package/examples/ripgrep-permission-fix.sh +0 -0
  560. package/examples/rm-safety-net.sh +151 -8
  561. package/examples/role-tool-guard.sh +12 -0
  562. package/examples/route-handler-emptiness-gate.sh +324 -0
  563. package/examples/ruby-lint-on-edit.sh +1 -1
  564. package/examples/runtime-binary-change-detector.sh +102 -0
  565. package/examples/same-command-repeat-detector.sh +196 -0
  566. package/examples/same-correction-arrest.sh +169 -0
  567. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  568. package/examples/sandbox-relative-path-audit.sh +83 -25
  569. package/examples/sandbox-write-verify.sh +12 -0
  570. package/examples/schema-migration-guard.sh +0 -0
  571. package/examples/scope-expansion-receipt.sh +178 -0
  572. package/examples/scope-guard.sh +88 -9
  573. package/examples/secret-file-read-guard.sh +12 -0
  574. package/examples/secret-file-write-guard.sh +150 -0
  575. package/examples/self-modify-bypass-guard.sh +0 -0
  576. package/examples/sensitive-file-read-guard.sh +23 -3
  577. package/examples/sensitive-log-guard.sh +1 -0
  578. package/examples/server-side-prompt-injection-detector.sh +69 -0
  579. package/examples/session-agent-cost-limiter.sh +12 -0
  580. package/examples/session-backup-on-start.sh +1 -1
  581. package/examples/session-cost-alert.sh +12 -0
  582. package/examples/session-drift-guard.sh +12 -0
  583. package/examples/session-duration-guard.sh +25 -2
  584. package/examples/session-end-logger.sh +0 -0
  585. package/examples/session-health-monitor.sh +0 -0
  586. package/examples/session-index-repair.sh +1 -1
  587. package/examples/session-memory-watchdog.sh +1 -0
  588. package/examples/session-permission-reset-guard.sh +12 -0
  589. package/examples/session-persistence-verifier.sh +93 -0
  590. package/examples/session-plugin-pin-watch.sh +68 -0
  591. package/examples/session-rate-monitor.sh +176 -0
  592. package/examples/session-resume-env-fix.sh +0 -0
  593. package/examples/session-start-quota-status.sh +193 -0
  594. package/examples/session-start-safety-check.sh +55 -3
  595. package/examples/session-state-saver.sh +0 -0
  596. package/examples/session-summary-stop.sh +1 -1
  597. package/examples/session-summary.sh +0 -0
  598. package/examples/session-token-counter.sh +1 -1
  599. package/examples/settings-hooks-key-restorer.sh +99 -0
  600. package/examples/settings-json-health-check.sh +57 -0
  601. package/examples/settings-json-model-guard.sh +0 -0
  602. package/examples/settings-regression-tester.sh +188 -0
  603. package/examples/shell-config-truncation-guard.sh +12 -0
  604. package/examples/shell-wrapper-guard.sh +12 -0
  605. package/examples/skill-cumulative-size-detector.sh +104 -0
  606. package/examples/skill-description-drop-detector.sh +148 -0
  607. package/examples/skill-gate.sh +0 -0
  608. package/examples/skill-truncation-detector.sh +154 -0
  609. package/examples/skills-context-recorder.sh +167 -0
  610. package/examples/skills-load-verifier.sh +96 -0
  611. package/examples/skills-settings-validator.sh +139 -0
  612. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  613. package/examples/spec-file-scope-guard.sh +12 -0
  614. package/examples/spring-profile-guard.sh +1 -0
  615. package/examples/spurious-malformed-notice-detector.sh +247 -0
  616. package/examples/sql-bulk-delete-warn.sh +88 -0
  617. package/examples/sql-injection-detect.sh +0 -0
  618. package/examples/ssh-key-protect.sh +12 -0
  619. package/examples/staged-secret-scan.sh +22 -1
  620. package/examples/stale-temp-settings-detector.sh +86 -0
  621. package/examples/standing-rule-session-surfacer.sh +137 -0
  622. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  623. package/examples/stop-transcript-write-health.sh +64 -0
  624. package/examples/strict-allowlist.sh +57 -15
  625. package/examples/strip-coauthored-by.sh +50 -10
  626. package/examples/subagent-blast-radius-guard.sh +184 -0
  627. package/examples/subagent-boundary-precheck.sh +126 -0
  628. package/examples/subagent-budget-guard.sh +12 -0
  629. package/examples/subagent-claudemd-inject.sh +0 -0
  630. package/examples/subagent-closure-verify-gate.sh +164 -0
  631. package/examples/subagent-destructive-git-guard.sh +120 -0
  632. package/examples/subagent-error-detector.sh +0 -0
  633. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  634. package/examples/subagent-identity-leak-guard.sh +102 -0
  635. package/examples/subagent-identity-reassertion.sh +51 -0
  636. package/examples/subagent-inheritance-tester.sh +179 -0
  637. package/examples/subagent-permission-mode-guard.sh +110 -0
  638. package/examples/subagent-scope-guard.sh +12 -0
  639. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  640. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  641. package/examples/subagent-tool-call-limiter.sh +87 -15
  642. package/examples/subcommand-chain-guard.sh +12 -0
  643. package/examples/subscription-api-billing-warner.sh +160 -0
  644. package/examples/subscription-bypass-detector.sh +152 -0
  645. package/examples/svelte-lint-on-edit.sh +1 -0
  646. package/examples/swift-build-on-edit.sh +1 -1
  647. package/examples/symlink-guard.sh +27 -2
  648. package/examples/symlink-protect.sh +1 -0
  649. package/examples/system-dir-protection-guard.sh +73 -8
  650. package/examples/system-message-workaround.sh +38 -13
  651. package/examples/system-package-guard.sh +12 -0
  652. package/examples/systemd-service-guard.sh +12 -0
  653. package/examples/task-integrity-guard.sh +12 -0
  654. package/examples/temp-file-cleanup.sh +1 -1
  655. package/examples/temporal-suggestion-detector.sh +135 -0
  656. package/examples/terraform-guard.sh +27 -6
  657. package/examples/test-after-edit.sh +1 -1
  658. package/examples/test-before-push.sh +12 -0
  659. package/examples/test-coverage-reminder.sh +24 -1
  660. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  661. package/examples/thinking-stall-detector.sh +61 -0
  662. package/examples/timezone-guard.sh +0 -0
  663. package/examples/tmp-output-size-guard.sh +0 -0
  664. package/examples/todo-check.sh +1 -1
  665. package/examples/token-budget-guard.sh +12 -0
  666. package/examples/token-budget-per-task.sh +12 -0
  667. package/examples/token-usage-tracker.sh +7 -1
  668. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  669. package/examples/tokenizer-ratio-alert.sh +104 -0
  670. package/examples/tool-call-rate-limiter.sh +0 -0
  671. package/examples/tool-result-correlation-checker.sh +167 -0
  672. package/examples/tool-result-size-guard.sh +132 -0
  673. package/examples/tool-retry-budget-guard.sh +12 -0
  674. package/examples/transcript-contamination-detector.sh +138 -0
  675. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  676. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  677. package/examples/unbounded-output-guard.sh +94 -0
  678. package/examples/uncommitted-changes-stop.sh +1 -0
  679. package/examples/uncommitted-discard-guard.sh +23 -5
  680. package/examples/uncommitted-work-guard.sh +12 -0
  681. package/examples/usage-warn.sh +0 -0
  682. package/examples/user-account-guard.sh +12 -0
  683. package/examples/userprompt-submit-receipt.sh +123 -0
  684. package/examples/variable-expansion-guard.sh +12 -0
  685. package/examples/verify-after-publish-reminder.sh +93 -0
  686. package/examples/verify-before-commit.sh +12 -0
  687. package/examples/version-bump-detector.sh +156 -0
  688. package/examples/version-regression-warner.sh +144 -0
  689. package/examples/vue-lint-on-edit.sh +1 -0
  690. package/examples/warn-cron-cost-trap.sh +173 -0
  691. package/examples/webfetch-runaway-guard.sh +89 -0
  692. package/examples/wellness-break-reminder.sh +118 -0
  693. package/examples/windows-destructive-command-guard.sh +177 -0
  694. package/examples/windows-path-guard.sh +12 -0
  695. package/examples/windows-python-stub-detector.sh +63 -0
  696. package/examples/work-hours-guard.sh +12 -0
  697. package/examples/working-directory-fence.sh +12 -0
  698. package/examples/workspace-lease-guard.sh +205 -0
  699. package/examples/worktree-create-log.sh +1 -0
  700. package/examples/worktree-delete-guard.sh +12 -0
  701. package/examples/worktree-edit-boundary-guard.sh +127 -0
  702. package/examples/worktree-escape-write-guard.sh +114 -0
  703. package/examples/worktree-hook-linker.sh +0 -0
  704. package/examples/worktree-hooks-path-fix.sh +111 -0
  705. package/examples/worktree-parent-write-guard.sh +43 -0
  706. package/examples/worktree-project-unify.sh +2 -1
  707. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  708. package/examples/worktree-unmerged-guard.sh +7 -1
  709. package/examples/write-byte-integrity-verifier.sh +190 -0
  710. package/examples/write-empty-content-guard.sh +67 -0
  711. package/examples/write-nul-corruption-detector.sh +61 -0
  712. package/examples/write-overwrite-confirm.sh +160 -14
  713. package/examples/write-secret-guard.sh +27 -5
  714. package/examples/write-shrink-guard.sh +12 -0
  715. package/examples/write-test-ratio.sh +0 -0
  716. package/examples/wsl-host-disk-space-guard.sh +97 -0
  717. package/examples/xml-format-leak-detector.sh +266 -0
  718. package/examples/yaml-syntax-check.sh +12 -0
  719. package/hooks/hooks.json +6 -6
  720. package/index.mjs +1699 -183
  721. package/mission.md +2 -0
  722. package/package.json +4 -4
  723. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  724. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  725. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  726. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  727. package/scripts/agents-md-sync-setup.sh +156 -0
  728. package/scripts/autonomy-blocked-summary.sh +148 -0
  729. package/scripts/build-search-index.py +43 -0
  730. package/scripts/build-sitemap.py +119 -0
  731. package/scripts/cc-doctor.sh +192 -0
  732. package/scripts/check-hook-event-names.py +127 -0
  733. package/scripts/check-misfire-instrument.sh +64 -0
  734. package/scripts/claim-verify-audit.sh +467 -0
  735. package/scripts/cowork-claudemd-helper.sh +136 -0
  736. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  737. package/scripts/measure-heredoc-shapes.sh +67 -0
  738. package/scripts/measure-literal-match-misfire.sh +110 -0
  739. package/scripts/probe-scope-guard-branches.sh +48 -0
  740. package/scripts/probe-skip-line-both-ways.sh +65 -0
  741. package/scripts/receipts-aggregate.py +199 -0
  742. package/scripts/session-forensic-audit.py +360 -0
  743. package/scripts.json +9 -9
  744. package/scripts.json.bak-2026-07-27-find +13 -0
  745. package/skills/safety-setup/SKILL.md +5 -5
  746. package/tests/approve-side-remaining-two.test.sh +129 -0
  747. package/tests/approver-list-granularity.test.sh +145 -0
  748. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  749. package/tests/audit-ci-gate.test.sh +87 -0
  750. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  751. package/tests/audit-fail-open-parse.test.sh +100 -0
  752. package/tests/auto-approve-compound-tail.test.sh +194 -0
  753. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  754. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  755. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  756. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  757. package/tests/blindspots-cross-layer.test.sh +177 -0
  758. package/tests/block-database-wipe.test.sh +64 -0
  759. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  760. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  761. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  762. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  763. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  764. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  765. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  766. package/tests/destructive-guard-every-operand.test.sh +100 -0
  767. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  768. package/tests/destructive-guard-flag-order.test.sh +106 -0
  769. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  770. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  771. package/tests/destructive-guard-separators.test.sh +105 -0
  772. package/tests/destructive-guard-variable-target.test.sh +98 -0
  773. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  774. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  775. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  776. package/tests/example-guards-wrapped-command.test.sh +169 -0
  777. package/tests/file-edit-backup.test.sh +93 -0
  778. package/tests/git-filter-repo-guard.test.sh +60 -0
  779. package/tests/git-global-options-bypass.test.sh +141 -0
  780. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  781. package/tests/git-maintenance-guard.test.sh +83 -0
  782. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  783. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  784. package/tests/git-submodule-guard.test.sh +50 -0
  785. package/tests/grep-pcre-portability.test.sh +155 -0
  786. package/tests/hook-registration-matches-input.test.sh +73 -0
  787. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  788. package/tests/install-does-not-claim-protection.test.sh +110 -0
  789. package/tests/install-example-standalone-tools.test.sh +139 -0
  790. package/tests/line-continuation-bypass.test.sh +114 -0
  791. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  792. package/tests/nested-background-agent-guard.test.sh +58 -0
  793. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  794. package/tests/option-eating-grep-patterns.test.sh +130 -0
  795. package/tests/outdated-core-guards.test.sh +134 -0
  796. package/tests/outdated-report.test.sh +155 -0
  797. package/tests/output-secret-mask-warns.test.sh +73 -0
  798. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  799. package/tests/plugins-word-order.test.sh +126 -0
  800. package/tests/powershell-remove-item-guard.test.sh +85 -0
  801. package/tests/project-dir-naming.test.sh +103 -0
  802. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  803. package/tests/reroute-after-block-guard.test.sh +104 -0
  804. package/tests/secret-guard-documented-promises.test.sh +97 -0
  805. package/tests/session-plugin-pin-watch.test.sh +45 -0
  806. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  807. package/tests/shield-no-silent-adoption.test.py +110 -0
  808. package/tests/shield-no-silent-adoption.test.sh +46 -0
  809. package/tests/stop-transcript-write-health.test.sh +46 -0
  810. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  811. package/tests/test-account-billing-log.sh +100 -0
  812. package/tests/test-account-routing-preflight.sh +77 -0
  813. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  814. package/tests/test-agent-view-quota-warn.sh +184 -0
  815. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  816. package/tests/test-agents-md-loader.sh +204 -0
  817. package/tests/test-agents-md-sync-checker.sh +125 -0
  818. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  819. package/tests/test-allowlist.sh +60 -0
  820. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  821. package/tests/test-anthropic-base-url-guard.sh +88 -0
  822. package/tests/test-articulated-scope-capture.sh +139 -0
  823. package/tests/test-attachment-traversal-guard.sh +168 -0
  824. package/tests/test-aup-block-pattern-logger.sh +315 -0
  825. package/tests/test-aup-false-positive-helper.sh +188 -0
  826. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  827. package/tests/test-aup-retry-loop-guard.sh +341 -0
  828. package/tests/test-auth-expiry-reminder.sh +303 -0
  829. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  830. package/tests/test-auth-path-detector.sh +232 -0
  831. package/tests/test-auth-status-checker.sh +233 -0
  832. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  833. package/tests/test-background-cost-launch-guard.sh +62 -0
  834. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  835. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  836. package/tests/test-bash-project-fence.sh +127 -0
  837. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  838. package/tests/test-binary-read-detector.sh +173 -0
  839. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  840. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  841. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  842. package/tests/test-cache-creation-drift-detector.sh +244 -0
  843. package/tests/test-cache-residue-detector.sh +429 -0
  844. package/tests/test-cache-tier-logger.sh +59 -0
  845. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  846. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  847. package/tests/test-claim-verify-detector.sh +222 -0
  848. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  849. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  850. package/tests/test-claude-md-reinjector.sh +173 -0
  851. package/tests/test-claude-md-size-monitor.sh +107 -0
  852. package/tests/test-claude-update-budget-guard.sh +132 -0
  853. package/tests/test-claude-update-smart.sh +91 -0
  854. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  855. package/tests/test-cli-config-pinning-detector.sh +233 -0
  856. package/tests/test-cliff-countdown-advisor.sh +138 -0
  857. package/tests/test-closure-word-verify-gate.sh +158 -0
  858. package/tests/test-commit-all-scope-guard.sh +73 -0
  859. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  860. package/tests/test-compact-circuit-breaker.sh +134 -0
  861. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  862. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  863. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  864. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  865. package/tests/test-context-length-budget.sh +68 -0
  866. package/tests/test-context-usage-drift-alert.sh +52 -22
  867. package/tests/test-cost-incident-self-audit.sh +94 -0
  868. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  869. package/tests/test-cowork-claudemd-helper.sh +141 -0
  870. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  871. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  872. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  873. package/tests/test-credential-exfil-guard.sh +62 -0
  874. package/tests/test-cron-create-receipt.sh +165 -0
  875. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  876. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  877. package/tests/test-daily-cost-guard.sh +131 -0
  878. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  879. package/tests/test-deployment-readback-gate.sh +92 -0
  880. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  881. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  882. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  883. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  884. package/tests/test-dispatch-receipt.sh +314 -0
  885. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  886. package/tests/test-echo-probe-spam-detector.sh +143 -0
  887. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  888. package/tests/test-ephemeral-container-detector.sh +251 -0
  889. package/tests/test-evidence-claim-gate.sh +291 -0
  890. package/tests/test-exploration-budget-guard.sh +164 -0
  891. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  892. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  893. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  894. package/tests/test-fabricated-command-detector.sh +296 -0
  895. package/tests/test-false-disk-full-guard.sh +36 -0
  896. package/tests/test-feature-deprecation-detector.sh +117 -0
  897. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  898. package/tests/test-git-operations-require-approval.sh +53 -0
  899. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  900. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  901. package/tests/test-growthbook-flag-monitor.sh +428 -0
  902. package/tests/test-halt-signal-detector.sh +120 -0
  903. package/tests/test-hook-self-disable-detector.sh +232 -0
  904. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  905. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  906. package/tests/test-marketplace-plugins.sh +193 -0
  907. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  908. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  909. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  910. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  911. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  912. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  913. package/tests/test-memory-chain-audit.sh +59 -0
  914. package/tests/test-memory-orphan-detector.sh +227 -0
  915. package/tests/test-model-swap-suggester.sh +368 -0
  916. package/tests/test-model-version-lock.sh +83 -0
  917. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  918. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  919. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  920. package/tests/test-no-force-flag.sh +49 -0
  921. package/tests/test-non-english-quality-warner.sh +229 -0
  922. package/tests/test-oauth-refresh-monitor.sh +311 -0
  923. package/tests/test-opus-degradation-tracker.sh +274 -0
  924. package/tests/test-opus48-routine-task-warning.sh +201 -0
  925. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  926. package/tests/test-output-token-spike-detector.sh +315 -0
  927. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  928. package/tests/test-parallel-cascade-detector.sh +191 -0
  929. package/tests/test-partial-view-claim-arrest.sh +272 -0
  930. package/tests/test-per-prompt-token-cap.sh +136 -0
  931. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  932. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  933. package/tests/test-post-edit-disk-verify.sh +294 -0
  934. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  935. package/tests/test-pre-execution-claim-detector.sh +366 -0
  936. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  937. package/tests/test-proxy-capture-suggester.sh +214 -0
  938. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  939. package/tests/test-quota-anomaly-detector.sh +321 -0
  940. package/tests/test-quota-reset-audit.sh +81 -0
  941. package/tests/test-read-loop-detector.sh +137 -0
  942. package/tests/test-read-once-guard.sh +85 -0
  943. package/tests/test-receipts-aggregate.sh +143 -0
  944. package/tests/test-redirect-fragment-warner.sh +130 -0
  945. package/tests/test-redundant-read-blocker.sh +155 -0
  946. package/tests/test-refusal-arrest-gate.sh +303 -0
  947. package/tests/test-remote-control-billing-classifier.sh +125 -0
  948. package/tests/test-resume-drift-watcher.sh +65 -0
  949. package/tests/test-rg-replace-flag-detector.sh +175 -0
  950. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  951. package/tests/test-rm-safety-net.sh +115 -0
  952. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  953. package/tests/test-runtime-binary-change-detector.sh +196 -0
  954. package/tests/test-same-command-repeat-detector.sh +165 -0
  955. package/tests/test-same-correction-arrest.sh +165 -0
  956. package/tests/test-scope-expansion-receipt.sh +207 -0
  957. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  958. package/tests/test-session-persistence-verifier.sh +128 -0
  959. package/tests/test-session-rate-monitor.sh +284 -0
  960. package/tests/test-session-start-quota-status.sh +210 -0
  961. package/tests/test-session-start-safety-check.sh +138 -0
  962. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  963. package/tests/test-settings-json-health-check.sh +70 -0
  964. package/tests/test-settings-regression-tester.sh +197 -0
  965. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  966. package/tests/test-skill-description-drop-detector.sh +236 -0
  967. package/tests/test-skill-truncation-detector.sh +263 -0
  968. package/tests/test-skills-context-recorder.sh +329 -0
  969. package/tests/test-skills-load-verifier.sh +184 -0
  970. package/tests/test-skills-settings-validator.sh +242 -0
  971. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  972. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  973. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  974. package/tests/test-ssh-key-protect.sh +81 -0
  975. package/tests/test-stale-temp-settings-detector.sh +161 -0
  976. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  977. package/tests/test-starter-hooks-manifest.sh +96 -0
  978. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  979. package/tests/test-strict-allowlist.sh +72 -0
  980. package/tests/test-subagent-boundary-precheck.sh +137 -0
  981. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  982. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  983. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  984. package/tests/test-subagent-identity-reassertion.sh +61 -0
  985. package/tests/test-subagent-inheritance-tester.sh +319 -0
  986. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  987. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  988. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  989. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  990. package/tests/test-subscription-api-billing-warner.sh +138 -0
  991. package/tests/test-subscription-bypass-detector.sh +255 -0
  992. package/tests/test-temporal-suggestion-detector.sh +183 -0
  993. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  994. package/tests/test-thinking-stall-detector.sh +151 -0
  995. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  996. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  997. package/tests/test-tool-result-correlation-checker.sh +264 -0
  998. package/tests/test-tool-result-size-guard.sh +121 -0
  999. package/tests/test-transcript-contamination-detector.sh +264 -0
  1000. package/tests/test-trigger-header-parsing.sh +151 -0
  1001. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  1002. package/tests/test-userprompt-submit-receipt.sh +181 -0
  1003. package/tests/test-verify-after-publish-reminder.sh +184 -0
  1004. package/tests/test-version-bump-detector.sh +212 -0
  1005. package/tests/test-version-regression-warner.sh +165 -0
  1006. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1007. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1008. package/tests/test-wellness-break-reminder.sh +138 -0
  1009. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1010. package/tests/test-windows-python-stub-detector.sh +146 -0
  1011. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1012. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1013. package/tests/test-xml-format-leak-detector.sh +299 -0
  1014. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1015. package/tests/workspace-lease-guard.test.sh +144 -0
  1016. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1017. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1018. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1019. package/tests/write-empty-content-guard.test.sh +39 -0
  1020. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1021. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1022. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,143 @@
1
+ #!/bin/bash
2
+ # Tests for bash-allowlist-secondary-check.sh (Issue #56117 prevention)
3
+ HOOK="examples/bash-allowlist-secondary-check.sh"
4
+ PASS=0 FAIL=0
5
+
6
+ assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; echo " output: $2"; fi; }
7
+ assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; echo " output: $2"; fi; }
8
+ assert_exit() { if [ "$2" = "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
9
+
10
+ # Use a temp directory with a controlled settings.json so the test does not
11
+ # depend on the host's user-level ~/.claude/settings.json.
12
+ TMPDIR=$(mktemp -d)
13
+ mkdir -p "$TMPDIR/.claude"
14
+ HOOK_ABS="$(pwd)/$HOOK"
15
+
16
+ cat > "$TMPDIR/.claude/settings.json" <<'EOF'
17
+ {
18
+ "permissions": {
19
+ "allow": [
20
+ "Bash(git diff)",
21
+ "Bash(git log:*)",
22
+ "Bash(git status)",
23
+ "Bash(npm test:*)",
24
+ "Read(*)"
25
+ ]
26
+ }
27
+ }
28
+ EOF
29
+
30
+ # Avoid leaking the host's user-level settings into the matcher.
31
+ export HOME_BACKUP="$HOME"
32
+ export HOME="$TMPDIR"
33
+
34
+ cd "$TMPDIR" || exit 1
35
+
36
+ # Test 1: empty command — silent pass
37
+ OUT=$(echo '{"tool_input":{"command":""}}' | bash "$HOOK_ABS" 2>&1)
38
+ RC=$?
39
+ assert_not_contains "empty command no warning" "$OUT" "not matched"
40
+ assert_exit "empty command exit 0" "$RC" "0"
41
+
42
+ # Test 2: exact match
43
+ OUT=$(echo '{"tool_input":{"command":"git diff"}}' | bash "$HOOK_ABS" 2>&1)
44
+ RC=$?
45
+ assert_not_contains "exact match no warning" "$OUT" "not matched"
46
+ assert_exit "exact match exit 0" "$RC" "0"
47
+
48
+ # Test 3: prefix match for "git log:*"
49
+ OUT=$(echo '{"tool_input":{"command":"git log -10 --oneline"}}' | bash "$HOOK_ABS" 2>&1)
50
+ RC=$?
51
+ assert_not_contains "prefix match no warning" "$OUT" "not matched"
52
+ assert_exit "prefix match exit 0" "$RC" "0"
53
+
54
+ # Test 4: prefix match for "npm test:*"
55
+ OUT=$(echo '{"tool_input":{"command":"npm test --watch"}}' | bash "$HOOK_ABS" 2>&1)
56
+ RC=$?
57
+ assert_not_contains "npm test prefix no warning" "$OUT" "not matched"
58
+ assert_exit "npm test prefix exit 0" "$RC" "0"
59
+
60
+ # Test 5: not in allowlist — Issue #56117 case (git push)
61
+ OUT=$(echo '{"tool_input":{"command":"git push origin main"}}' | bash "$HOOK_ABS" 2>&1)
62
+ RC=$?
63
+ assert_contains "git push warns" "$OUT" "not matched by any settings.json allow pattern"
64
+ assert_contains "git push references issue" "$OUT" "#56117"
65
+ assert_contains "git push includes the command" "$OUT" "git push origin main"
66
+ assert_exit "git push exit 0 advisory" "$RC" "0"
67
+
68
+ # Test 6: not in allowlist — git add (also #56117 case)
69
+ OUT=$(echo '{"tool_input":{"command":"git add -A"}}' | bash "$HOOK_ABS" 2>&1)
70
+ RC=$?
71
+ assert_contains "git add warns" "$OUT" "not matched"
72
+ assert_exit "git add advisory exit 0" "$RC" "0"
73
+
74
+ # Test 7: strict mode blocks
75
+ OUT=$(echo '{"tool_input":{"command":"git push origin main"}}' | CC_BASH_ALLOWLIST_STRICT=1 bash "$HOOK_ABS" 2>&1)
76
+ RC=$?
77
+ assert_contains "strict still warns" "$OUT" "not matched"
78
+ assert_exit "strict mode exit 2" "$RC" "2"
79
+
80
+ # Test 8: quiet mode silences warning but still blocks in strict
81
+ OUT=$(echo '{"tool_input":{"command":"git push origin main"}}' | CC_BASH_ALLOWLIST_QUIET=1 CC_BASH_ALLOWLIST_STRICT=1 bash "$HOOK_ABS" 2>&1)
82
+ RC=$?
83
+ assert_not_contains "quiet strict no stderr" "$OUT" "not matched"
84
+ assert_exit "quiet strict exit 2" "$RC" "2"
85
+
86
+ # Test 9: quiet alone is silent advisory
87
+ OUT=$(echo '{"tool_input":{"command":"git push origin main"}}' | CC_BASH_ALLOWLIST_QUIET=1 bash "$HOOK_ABS" 2>&1)
88
+ RC=$?
89
+ assert_not_contains "quiet alone no stderr" "$OUT" "not matched"
90
+ assert_exit "quiet alone exit 0" "$RC" "0"
91
+
92
+ # Test 10: Bash(*) wildcard allows everything
93
+ cat > "$TMPDIR/.claude/settings.json" <<'EOF'
94
+ { "permissions": { "allow": ["Bash(*)"] } }
95
+ EOF
96
+ OUT=$(echo '{"tool_input":{"command":"rm -rf /tmp/foo"}}' | bash "$HOOK_ABS" 2>&1)
97
+ RC=$?
98
+ assert_not_contains "wildcard allow no warning" "$OUT" "not matched"
99
+ assert_exit "wildcard allow exit 0" "$RC" "0"
100
+
101
+ # Test 11: empty allowlist — everything warns
102
+ cat > "$TMPDIR/.claude/settings.json" <<'EOF'
103
+ { "permissions": { "allow": [] } }
104
+ EOF
105
+ OUT=$(echo '{"tool_input":{"command":"echo hello"}}' | bash "$HOOK_ABS" 2>&1)
106
+ RC=$?
107
+ assert_contains "empty allowlist warns" "$OUT" "not matched"
108
+ assert_exit "empty allowlist advisory exit 0" "$RC" "0"
109
+
110
+ # Test 12: missing settings file — silent pass (no allowlist to compare against)
111
+ rm "$TMPDIR/.claude/settings.json"
112
+ OUT=$(echo '{"tool_input":{"command":"echo hello"}}' | bash "$HOOK_ABS" 2>&1)
113
+ RC=$?
114
+ assert_contains "missing settings still warns (no patterns)" "$OUT" "not matched"
115
+ assert_exit "missing settings exit 0" "$RC" "0"
116
+
117
+ # Test 13: local settings file is also read
118
+ cat > "$TMPDIR/.claude/settings.local.json" <<'EOF'
119
+ { "permissions": { "allow": ["Bash(echo:*)"] } }
120
+ EOF
121
+ OUT=$(echo '{"tool_input":{"command":"echo hello"}}' | bash "$HOOK_ABS" 2>&1)
122
+ RC=$?
123
+ assert_not_contains "local settings allow no warning" "$OUT" "not matched"
124
+ assert_exit "local settings exit 0" "$RC" "0"
125
+
126
+ # Test 14: non-Bash patterns (e.g. Read) are ignored
127
+ cat > "$TMPDIR/.claude/settings.json" <<'EOF'
128
+ { "permissions": { "allow": ["Read(*)", "Edit(*)"] } }
129
+ EOF
130
+ rm -f "$TMPDIR/.claude/settings.local.json"
131
+ OUT=$(echo '{"tool_input":{"command":"git push"}}' | bash "$HOOK_ABS" 2>&1)
132
+ RC=$?
133
+ assert_contains "non-Bash patterns ignored — git push warns" "$OUT" "not matched"
134
+ assert_exit "non-Bash patterns advisory exit 0" "$RC" "0"
135
+
136
+ # Restore HOME and clean up
137
+ export HOME="$HOME_BACKUP"
138
+ cd / && rm -rf "$TMPDIR"
139
+
140
+ echo
141
+ echo "Passed: $PASS"
142
+ echo "Failed: $FAIL"
143
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,186 @@
1
+ #!/bin/bash
2
+ # Tests for bash-fanout-bounded-rewriter.sh
3
+ # Covers: 7 fan-out detection patterns, 5 safe-pass patterns,
4
+ # override / disable env toggles, suggested-rewrite content,
5
+ # fail-open on malformed input.
6
+
7
+ HOOK="examples/bash-fanout-bounded-rewriter.sh"
8
+ PASS=0 FAIL=0
9
+
10
+ run_hook() {
11
+ local payload="$1"; shift
12
+ env -u CC_BASH_FANOUT_DISABLE -u CC_BASH_FANOUT_OVERRIDE \
13
+ -u CC_BASH_FANOUT_PARALLEL_BOUND \
14
+ "$@" bash "$HOOK" <<< "$payload" 2>&1
15
+ # bash exit status passes through; capture in caller via $?
16
+ }
17
+
18
+ assert_contains() { if echo "$2" | grep -qF "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; fi; }
19
+ assert_not_contains() { if ! echo "$2" | grep -qF "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
20
+ assert_exit() { if [ "$2" = "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
21
+
22
+ run_and_capture() {
23
+ local payload="$1"; shift
24
+ env -u CC_BASH_FANOUT_DISABLE -u CC_BASH_FANOUT_OVERRIDE \
25
+ -u CC_BASH_FANOUT_PARALLEL_BOUND \
26
+ "$@" bash "$HOOK" <<< "$payload" 2>&1
27
+ LAST_RC=$?
28
+ }
29
+
30
+ # Test 1: empty input — pass through
31
+ run_and_capture '{}'
32
+ assert_exit "empty input pass" "$LAST_RC" "0"
33
+
34
+ # Test 2: safe command (ls -la) — pass through silently
35
+ run_and_capture '{"tool_input":{"command":"ls -la"}}'
36
+ assert_exit "ls -la pass" "$LAST_RC" "0"
37
+
38
+ # Test 3: find -exec — blocked
39
+ run_and_capture '{"tool_input":{"command":"find . -name *.py -exec wc -l {} +"}}'
40
+ assert_exit "find -exec blocked" "$LAST_RC" "2"
41
+ OUT=$(run_hook '{"tool_input":{"command":"find . -name *.py -exec wc -l {} +"}}')
42
+ assert_contains "find -exec advisory" "$OUT" "Unbounded fan-out detected"
43
+ assert_contains "find -exec names pattern" "$OUT" "find ... -exec"
44
+ assert_contains "find -exec references #62193" "$OUT" "#62193"
45
+ assert_contains "find -exec suggests xargs -P rewrite" "$OUT" "xargs -0 -P 8"
46
+
47
+ # Test 4: for ... in $(...) — blocked
48
+ run_and_capture '{"tool_input":{"command":"for f in $(ls *.txt); do wc -l \"$f\"; done"}}'
49
+ assert_exit "for in dollar paren blocked" "$LAST_RC" "2"
50
+ OUT=$(run_hook '{"tool_input":{"command":"for f in $(ls *.txt); do wc -l \"$f\"; done"}}')
51
+ assert_contains "for advisory" "$OUT" "for ... in"
52
+
53
+ # Test 5: for in literal static list — pass through
54
+ run_and_capture '{"tool_input":{"command":"for i in 1 2 3; do echo $i; done"}}'
55
+ assert_exit "for in 1 2 3 pass" "$LAST_RC" "0"
56
+
57
+ # Test 6: for ... in $VAR — blocked
58
+ run_and_capture '{"tool_input":{"command":"for f in $FILES; do echo $f; done"}}'
59
+ assert_exit "for in dollar var blocked" "$LAST_RC" "2"
60
+
61
+ # Test 7: for ... in glob — blocked
62
+ run_and_capture '{"tool_input":{"command":"for f in *.log; do tail -1 $f; done"}}'
63
+ assert_exit "for in glob blocked" "$LAST_RC" "2"
64
+
65
+ # Test 8: while read — blocked
66
+ run_and_capture '{"tool_input":{"command":"cat list.txt | while read line; do process $line; done"}}'
67
+ assert_exit "while read blocked" "$LAST_RC" "2"
68
+ OUT=$(run_hook '{"tool_input":{"command":"cat list.txt | while read line; do process $line; done"}}')
69
+ assert_contains "while read advisory" "$OUT" "while read"
70
+
71
+ # Test 9: xargs without -P (serial xargs is safe) — pass through
72
+ run_and_capture '{"tool_input":{"command":"cat list.txt | xargs grep foo"}}'
73
+ assert_exit "xargs serial pass" "$LAST_RC" "0"
74
+
75
+ # Test 10: parallel without -j — blocked
76
+ run_and_capture '{"tool_input":{"command":"ls | parallel wc -l"}}'
77
+ assert_exit "parallel no -j blocked" "$LAST_RC" "2"
78
+ OUT=$(run_hook '{"tool_input":{"command":"ls | parallel wc -l"}}')
79
+ assert_contains "parallel advisory" "$OUT" "parallel"
80
+ assert_contains "parallel suggests -j" "$OUT" "parallel -j 8"
81
+
82
+ # Test 11: parallel -j 4 — pass through (already bounded)
83
+ run_and_capture '{"tool_input":{"command":"ls | parallel -j 4 wc -l"}}'
84
+ assert_exit "parallel -j N pass" "$LAST_RC" "0"
85
+
86
+ # Test 12: make -j (no number) — blocked
87
+ run_and_capture '{"tool_input":{"command":"make -j all"}}'
88
+ assert_exit "make -j blocked" "$LAST_RC" "2"
89
+ OUT=$(run_hook '{"tool_input":{"command":"make -j all"}}')
90
+ assert_contains "make -j advisory" "$OUT" "make -j without N"
91
+
92
+ # Test 13: make -j4 — pass through
93
+ run_and_capture '{"tool_input":{"command":"make -j4 all"}}'
94
+ assert_exit "make -j4 pass" "$LAST_RC" "0"
95
+
96
+ # Test 14: make -j 8 — pass through
97
+ run_and_capture '{"tool_input":{"command":"make -j 8 all"}}'
98
+ assert_exit "make -j 8 pass" "$LAST_RC" "0"
99
+
100
+ # Test 15: seq 1000 piped to while — blocked (while-read pattern fires first, which is the correct earlier-pattern preemption)
101
+ run_and_capture '{"tool_input":{"command":"seq 1000 | while read i; do echo $i; done"}}'
102
+ assert_exit "seq 1000 to while blocked" "$LAST_RC" "2"
103
+ OUT=$(run_hook '{"tool_input":{"command":"seq 1000 | while read i; do echo $i; done"}}')
104
+ assert_contains "seq+while-read pattern names while" "$OUT" "while read"
105
+
106
+ # Test 15b: seq 1000 piped to xargs serial — pattern 7 fires (no while-read precursor)
107
+ # Note: seq + xargs is actually serial xargs (no -P), so it passes through.
108
+ # To test pattern 7 in isolation we need a high-N seq without earlier-matching patterns.
109
+ # An unusual but valid case: seq 1000 piped directly to a parallel command.
110
+ run_and_capture '{"tool_input":{"command":"seq 1000 | parallel echo"}}'
111
+ # This hits parallel-without-j pattern first.
112
+ assert_exit "seq 1000 to parallel blocked" "$LAST_RC" "2"
113
+
114
+ # Test 16: seq 5 piped to while — pass through (N <= 100)
115
+ run_and_capture '{"tool_input":{"command":"seq 5 | while read i; do echo $i; done"}}'
116
+ # Note: this one will hit while read pattern first; let's verify
117
+ # The 'while read' check is earlier than seq, so seq is unreachable for low N.
118
+ # But the while-read check is still active. Both should result in block.
119
+ assert_exit "seq 5 to while still blocked by while pattern" "$LAST_RC" "2"
120
+
121
+ # Test 17: seq 5 piped to xargs — pass through (serial xargs)
122
+ run_and_capture '{"tool_input":{"command":"seq 5 | xargs echo"}}'
123
+ assert_exit "seq 5 to xargs pass" "$LAST_RC" "0"
124
+
125
+ # Test 18: DISABLE env suppresses all checks
126
+ run_and_capture '{"tool_input":{"command":"find . -exec rm {} +"}}' CC_BASH_FANOUT_DISABLE=1
127
+ assert_exit "disable env pass" "$LAST_RC" "0"
128
+
129
+ # Test 19: OVERRIDE env allows one fan-out call
130
+ run_and_capture '{"tool_input":{"command":"find . -exec rm {} +"}}' CC_BASH_FANOUT_OVERRIDE=1
131
+ assert_exit "override env pass" "$LAST_RC" "0"
132
+
133
+ # Test 20: PARALLEL_BOUND env changes suggested rewrite
134
+ OUT=$(run_hook '{"tool_input":{"command":"find . -exec rm {} +"}}' CC_BASH_FANOUT_PARALLEL_BOUND=4)
135
+ assert_contains "custom bound 4 in rewrite" "$OUT" "xargs -0 -P 4"
136
+
137
+ # Test 21: malformed JSON — fail-open
138
+ run_and_capture 'not-json'
139
+ assert_exit "malformed input pass" "$LAST_RC" "0"
140
+
141
+ # Test 22: missing tool_input — fail-open
142
+ run_and_capture '{"other":"field"}'
143
+ assert_exit "missing tool_input pass" "$LAST_RC" "0"
144
+
145
+ # Test 23: empty command — fail-open
146
+ run_and_capture '{"tool_input":{"command":""}}'
147
+ assert_exit "empty command pass" "$LAST_RC" "0"
148
+
149
+ # Test 24: advisory references PreToolUse layer vs cgroup
150
+ OUT=$(run_hook '{"tool_input":{"command":"find . -exec rm {} +"}}')
151
+ assert_contains "advisory names cgroup layer" "$OUT" "cgroup TasksMax"
152
+ assert_contains "advisory explains layer choice" "$OUT" "rendering the tool useless"
153
+ assert_contains "advisory gives override path" "$OUT" "CC_BASH_FANOUT_OVERRIDE=1"
154
+
155
+ # Test 25: regular git commands pass through
156
+ run_and_capture '{"tool_input":{"command":"git status"}}'
157
+ assert_exit "git status pass" "$LAST_RC" "0"
158
+ run_and_capture '{"tool_input":{"command":"git log --oneline -10"}}'
159
+ assert_exit "git log pass" "$LAST_RC" "0"
160
+
161
+ # Test 26: rm without fan-out passes through (deny is a different hook's job)
162
+ run_and_capture '{"tool_input":{"command":"rm /tmp/file.txt"}}'
163
+ assert_exit "rm simple pass" "$LAST_RC" "0"
164
+
165
+ # Test 27: xargs -P 4 — pass through (already bounded)
166
+ run_and_capture '{"tool_input":{"command":"cat list.txt | xargs -P 4 -n 1 process"}}'
167
+ assert_exit "xargs -P 4 pass" "$LAST_RC" "0"
168
+
169
+ # Test 28: find without -exec — pass through (find itself is fine)
170
+ run_and_capture '{"tool_input":{"command":"find . -name *.py"}}'
171
+ assert_exit "find without exec pass" "$LAST_RC" "0"
172
+
173
+ # Test 29: find piped to xargs -P — pass through
174
+ run_and_capture '{"tool_input":{"command":"find . -name *.py -print0 | xargs -0 -P 8 wc -l"}}'
175
+ assert_exit "find piped to xargs -P pass" "$LAST_RC" "0"
176
+
177
+ # Test 30: error message contains all four required sections
178
+ OUT=$(run_hook '{"tool_input":{"command":"find . -exec rm {} +"}}')
179
+ assert_contains "error has detection block" "$OUT" "Unbounded fan-out detected"
180
+ assert_contains "error has rewrite block" "$OUT" "Bounded rewrite:"
181
+ assert_contains "error has override path" "$OUT" "Override for this one call"
182
+ assert_contains "error has disable path" "$OUT" "Disable entirely"
183
+
184
+ echo ""
185
+ echo "Results: $PASS passed, $FAIL failed"
186
+ [ "$FAIL" = "0" ] && exit 0 || exit 1
@@ -0,0 +1,127 @@
1
+ #!/bin/bash
2
+ # Tests for bash-project-fence.sh
3
+ HOOK="$(dirname "$0")/../examples/bash-project-fence.sh"
4
+ PASS=0 FAIL=0
5
+
6
+ # Set up a fake project root in /tmp (already in default allow list, so we
7
+ # override CC_BASH_FENCE_ALLOW empty in tests that need /tmp as project root)
8
+ PROJECT_ROOT="/tmp/test-bash-project-fence-$$"
9
+ mkdir -p "$PROJECT_ROOT/src"
10
+ mkdir -p "$PROJECT_ROOT/docs"
11
+ trap 'rm -rf "$PROJECT_ROOT"' EXIT
12
+
13
+ run_test() {
14
+ local desc="$1" expected_exit="$2" cmd="$3"
15
+ shift 3
16
+ local actual_exit
17
+ echo "{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":$(printf '%s' "$cmd" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))')}}" \
18
+ | env CLAUDE_PROJECT_DIR="$PROJECT_ROOT" "$@" bash "$HOOK" >/dev/null 2>/dev/null
19
+ actual_exit=$?
20
+ if [ "$actual_exit" -eq "$expected_exit" ]; then
21
+ echo " PASS: $desc"
22
+ PASS=$((PASS+1))
23
+ else
24
+ echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
25
+ FAIL=$((FAIL+1))
26
+ fi
27
+ }
28
+
29
+ echo "Testing bash-project-fence.sh"
30
+ echo "============================="
31
+
32
+ # 1. Empty command — pass
33
+ run_test "empty command passes" 0 ""
34
+
35
+ # 2. Relative path — pass (no absolute path tokens)
36
+ run_test "relative path passes" 0 "cat src/file.txt"
37
+
38
+ # 3. Absolute path inside project root — pass
39
+ run_test "absolute path inside project root passes" 0 "cat ${PROJECT_ROOT}/src/file.txt"
40
+
41
+ # 4. find inside project root — pass
42
+ run_test "find inside project root passes" 0 "find ${PROJECT_ROOT}/src -name '*.py'"
43
+
44
+ # 5. /tmp path — pass (default allow list includes /tmp)
45
+ run_test "/tmp path passes (default allow)" 0 "cat /tmp/something.txt"
46
+
47
+ # 6. /dev/null — pass (default allow list)
48
+ run_test "/dev/null passes (default allow)" 0 "command > /dev/null 2>&1"
49
+
50
+ # 7. Issue #56739 reproduction: find across Desktop — BLOCK
51
+ run_test "find across /Users Desktop blocks (#56739)" 2 \
52
+ "find /Users/admin/Desktop -name '*.png'"
53
+
54
+ # 8. cat outside project — BLOCK
55
+ run_test "cat /etc/passwd blocks" 2 "cat /etc/passwd"
56
+
57
+ # 9. cp outside project — BLOCK (source outside)
58
+ run_test "cp /etc/hosts to project blocks" 2 \
59
+ "cp /etc/hosts ${PROJECT_ROOT}/hosts.bak"
60
+
61
+ # 10. cp to outside project — BLOCK (destination outside)
62
+ run_test "cp project to /etc blocks" 2 \
63
+ "cp ${PROJECT_ROOT}/file.txt /etc/file.txt"
64
+
65
+ # 11. ls outside project — BLOCK
66
+ run_test "ls /home/user/Documents blocks" 2 "ls /home/user/Documents"
67
+
68
+ # 12. grep outside project — BLOCK
69
+ run_test "grep on /var/log blocks" 2 "grep error /var/log/syslog"
70
+
71
+ # 13. Multiple paths, one outside — BLOCK
72
+ run_test "command with mixed paths blocks if any outside" 2 \
73
+ "cp ${PROJECT_ROOT}/a /home/other/b"
74
+
75
+ # 14. CC_BASH_FENCE_ALLOW expansion allows specific path
76
+ run_test "CC_BASH_FENCE_ALLOW permits specified path" 0 \
77
+ "cat /home/user/config.json" CC_BASH_FENCE_ALLOW="/home/user"
78
+
79
+ # 15. CC_BASH_FENCE_ACTION=warn returns 0 even when outside
80
+ run_test "warn action passes (exit 0) but emits warning" 0 \
81
+ "cat /etc/passwd" CC_BASH_FENCE_ACTION=warn
82
+
83
+ # 16. CC_BASH_FENCE_OFF=1 disables hook
84
+ run_test "CC_BASH_FENCE_OFF=1 disables hook" 0 \
85
+ "cat /etc/passwd" CC_BASH_FENCE_OFF=1
86
+
87
+ # 17. Tilde expansion to $HOME outside project
88
+ run_test "tilde-expanded HOME outside project blocks" 2 \
89
+ "cat ~/Desktop/secret.png"
90
+
91
+ # 18. URL is skipped (not treated as path)
92
+ run_test "URL with absolute path scheme is skipped" 0 \
93
+ "curl https://example.com/api"
94
+
95
+ # 19. Flag-like absolute argument is NOT skipped if it resolves outside.
96
+ # This is a documented limitation — operators should not use absolute paths
97
+ # as flag values pointing outside the project. The hook errs on the side of
98
+ # blocking. We assert the block here for clarity.
99
+ run_test "absolute path as command argument always checked" 2 \
100
+ "find / -type f -name '*.key'"
101
+
102
+ # 20. find with -path option inside project — pass
103
+ run_test "find with relative -path option passes" 0 \
104
+ "find ${PROJECT_ROOT} -path '*/docs/*'"
105
+
106
+ # 21. Output redirect target outside project — BLOCK
107
+ run_test "output redirect to /etc blocks" 2 \
108
+ "echo data > /etc/somefile"
109
+
110
+ # 22. /proc/self/fd is in default allow list
111
+ run_test "/proc/self/fd passes (default allow)" 0 \
112
+ "cat /proc/self/fd/0"
113
+
114
+ # 23. Trailing slash on outside path — BLOCK
115
+ run_test "trailing-slash outside path blocks" 2 "ls /home/user/"
116
+
117
+ # 24. Quoted absolute path outside — BLOCK (after quote strip)
118
+ run_test "quoted outside path blocks" 2 \
119
+ "cat \"/var/log/secure\""
120
+
121
+ # 25. Path with .. that resolves outside — BLOCK
122
+ run_test "../traversal to outside blocks" 2 \
123
+ "cat ${PROJECT_ROOT}/../../../etc/passwd"
124
+
125
+ echo
126
+ echo "Results: $PASS passed, $FAIL failed"
127
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,221 @@
1
+ #!/bin/bash
2
+ # test-bg-permission-prompt-warner.sh — Tests for bg-permission-prompt-warner.sh
3
+
4
+ set -u
5
+
6
+ HOOK="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/examples/bg-permission-prompt-warner.sh"
7
+
8
+ PASS=0
9
+ FAIL=0
10
+ FAILED_TESTS=()
11
+
12
+ run_test() {
13
+ local name="$1"
14
+ local expected_exit="$2"
15
+ local expected_pattern="$3"
16
+ shift 3
17
+ local stderr_file
18
+ stderr_file=$(mktemp)
19
+ local actual_exit
20
+ "$@" 2>"$stderr_file"
21
+ actual_exit=$?
22
+ local stderr_content
23
+ stderr_content=$(cat "$stderr_file")
24
+ rm -f "$stderr_file"
25
+
26
+ local exit_ok=false
27
+ if [[ "$actual_exit" == "$expected_exit" ]]; then
28
+ exit_ok=true
29
+ fi
30
+
31
+ local pattern_ok=false
32
+ if [[ -z "$expected_pattern" ]]; then
33
+ if [[ -z "$stderr_content" ]]; then
34
+ pattern_ok=true
35
+ fi
36
+ elif [[ "$expected_pattern" == "ANY" ]]; then
37
+ pattern_ok=true
38
+ else
39
+ if echo "$stderr_content" | grep -q "$expected_pattern"; then
40
+ pattern_ok=true
41
+ fi
42
+ fi
43
+
44
+ if [[ "$exit_ok" == "true" && "$pattern_ok" == "true" ]]; then
45
+ echo "✓ $name"
46
+ PASS=$((PASS + 1))
47
+ else
48
+ echo "✗ $name (exit: $actual_exit/$expected_exit, pattern: ${expected_pattern})"
49
+ if [[ -n "$stderr_content" ]]; then
50
+ echo " stderr: $(echo "$stderr_content" | head -3 | tr '\n' ' ')"
51
+ fi
52
+ FAIL=$((FAIL + 1))
53
+ FAILED_TESTS+=("$name")
54
+ fi
55
+ }
56
+
57
+ STATE_DIR=$(mktemp -d)
58
+ export CC_BG_WARN_STATE_DIR="$STATE_DIR"
59
+
60
+ # Test 1: Disable switch
61
+ run_test "disable switch silences hook" \
62
+ "0" "" \
63
+ env CC_BG_WARN_DISABLE=1 \
64
+ CC_BG_WARN_FORCE=1 \
65
+ CC_BG_WARN_SESSION_ID=test1 \
66
+ bash "$HOOK"
67
+
68
+ # Test 2: Quiet mode emits nothing
69
+ run_test "quiet mode emits nothing" \
70
+ "0" "" \
71
+ env CC_BG_WARN_QUIET=1 \
72
+ CC_BG_WARN_FORCE=1 \
73
+ CC_BG_WARN_SESSION_ID=test2 \
74
+ bash "$HOOK"
75
+
76
+ # Test 3: No parent cmd, no force — exits silently
77
+ run_test "no parent cmd no force exits silently" \
78
+ "0" "" \
79
+ env -u CC_BG_WARN_FORCE \
80
+ CC_BG_WARN_PARENT_CMD="" \
81
+ CC_BG_WARN_SESSION_ID=test3 \
82
+ bash "$HOOK"
83
+
84
+ # Test 4: Parent cmd without --bg — exits silently
85
+ run_test "parent cmd without --bg exits silently" \
86
+ "0" "" \
87
+ env -u CC_BG_WARN_FORCE \
88
+ CC_BG_WARN_PARENT_CMD="node /usr/local/bin/claude --print" \
89
+ CC_BG_WARN_SESSION_ID=test4 \
90
+ bash "$HOOK"
91
+
92
+ # Test 5: Parent cmd with --bg — emits advisory
93
+ run_test "parent cmd with --bg emits advisory" \
94
+ "0" "Cluster 24 axis 24A" \
95
+ env CC_BG_WARN_PARENT_CMD="node /usr/local/bin/claude --bg --model opus --name test" \
96
+ CC_BG_WARN_SESSION_ID=test5 \
97
+ bash "$HOOK"
98
+
99
+ # Test 6: Parent cmd with --background — emits advisory
100
+ run_test "parent cmd with --background emits advisory" \
101
+ "0" "Cluster 24 axis 24A" \
102
+ env CC_BG_WARN_PARENT_CMD="claude --background work" \
103
+ CC_BG_WARN_SESSION_ID=test6 \
104
+ bash "$HOOK"
105
+
106
+ # Test 7: Advisory references anchor #64271
107
+ run_test "advisory references #64271" \
108
+ "0" "64271" \
109
+ env CC_BG_WARN_PARENT_CMD="claude --bg work" \
110
+ CC_BG_WARN_SESSION_ID=test7 \
111
+ bash "$HOOK"
112
+
113
+ # Test 8: Advisory mentions acceptEdits
114
+ run_test "advisory mentions acceptEdits" \
115
+ "0" "acceptEdits" \
116
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
117
+ CC_BG_WARN_SESSION_ID=test8 \
118
+ bash "$HOOK"
119
+
120
+ # Test 9: Advisory mentions the three sibling axes
121
+ run_test "advisory mentions 24B sibling axis" \
122
+ "0" "24B" \
123
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
124
+ CC_BG_WARN_SESSION_ID=test9 \
125
+ bash "$HOOK"
126
+
127
+ run_test "advisory mentions 24C sibling axis" \
128
+ "0" "24C" \
129
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
130
+ CC_BG_WARN_SESSION_ID=test9c \
131
+ bash "$HOOK"
132
+
133
+ run_test "advisory mentions 24D sibling axis" \
134
+ "0" "24D" \
135
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
136
+ CC_BG_WARN_SESSION_ID=test9d \
137
+ bash "$HOOK"
138
+
139
+ # Test 10: One-shot per session — second invocation does not re-fire
140
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
141
+ CC_BG_WARN_SESSION_ID=test10 \
142
+ bash "$HOOK" 2>/dev/null
143
+ run_test "second invocation does not re-fire" \
144
+ "0" "" \
145
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
146
+ CC_BG_WARN_SESSION_ID=test10 \
147
+ bash "$HOOK"
148
+
149
+ # Test 11: Force flag bypasses parent detection
150
+ run_test "FORCE flag emits without parent cmdline match" \
151
+ "0" "Cluster 24 axis 24A" \
152
+ env CC_BG_WARN_FORCE=1 \
153
+ CC_BG_WARN_PARENT_CMD="" \
154
+ CC_BG_WARN_SESSION_ID=test11 \
155
+ bash "$HOOK"
156
+
157
+ # Test 12: Different session id fires independently
158
+ run_test "different session id fires independently" \
159
+ "0" "Cluster 24 axis 24A" \
160
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
161
+ CC_BG_WARN_SESSION_ID=test12 \
162
+ bash "$HOOK"
163
+
164
+ # Test 13: Quiet mode still marks guard
165
+ env CC_BG_WARN_QUIET=1 \
166
+ CC_BG_WARN_FORCE=1 \
167
+ CC_BG_WARN_SESSION_ID=test13 \
168
+ bash "$HOOK"
169
+ run_test "quiet mode marks guard so non-quiet later does not fire" \
170
+ "0" "" \
171
+ env CC_BG_WARN_FORCE=1 \
172
+ CC_BG_WARN_SESSION_ID=test13 \
173
+ bash "$HOOK"
174
+
175
+ # Test 14: Advisory references disable env var
176
+ run_test "advisory mentions CC_BG_WARN_DISABLE" \
177
+ "0" "CC_BG_WARN_DISABLE" \
178
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
179
+ CC_BG_WARN_SESSION_ID=test14 \
180
+ bash "$HOOK"
181
+
182
+ # Test 15: Substring match in middle of cmdline
183
+ run_test "--bg in middle of cmdline matches" \
184
+ "0" "Cluster 24 axis 24A" \
185
+ env CC_BG_WARN_PARENT_CMD="env FOO=bar node claude --bg --model opus extra-args" \
186
+ CC_BG_WARN_SESSION_ID=test15 \
187
+ bash "$HOOK"
188
+
189
+ # Test 16: --bgwhatever should NOT match (word boundary)
190
+ run_test "--bgsomething does not falsely match" \
191
+ "0" "" \
192
+ env -u CC_BG_WARN_FORCE \
193
+ CC_BG_WARN_PARENT_CMD="claude --bgsomething-suffix" \
194
+ CC_BG_WARN_SESSION_ID=test16 \
195
+ bash "$HOOK"
196
+
197
+ # Test 17: Advisory references workaround steps
198
+ run_test "advisory includes terminal-attached workaround" \
199
+ "0" "terminal attached" \
200
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
201
+ CC_BG_WARN_SESSION_ID=test17 \
202
+ bash "$HOOK"
203
+
204
+ # Test 18: Advisory mentions audit tool-call distribution workaround
205
+ run_test "advisory mentions tool-call distribution audit" \
206
+ "0" "tool-call distribution" \
207
+ env CC_BG_WARN_PARENT_CMD="claude --bg" \
208
+ CC_BG_WARN_SESSION_ID=test18 \
209
+ bash "$HOOK"
210
+
211
+ # Cleanup
212
+ rm -rf "$STATE_DIR"
213
+
214
+ echo ""
215
+ echo "─────────────────────────────"
216
+ echo "Tests: $((PASS + FAIL)) | Pass: $PASS | Fail: $FAIL"
217
+ if [[ $FAIL -gt 0 ]]; then
218
+ echo "Failed: ${FAILED_TESTS[*]}"
219
+ exit 1
220
+ fi
221
+ exit 0