cc-safe-setup 29.8.0 → 30.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1017) hide show
  1. package/.claude-plugin/marketplace.json +72 -19
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CONTRIBUTING.md +7 -2
  4. package/COOKBOOK.md +50 -46
  5. package/LICENSE +21 -0
  6. package/MIGRATION.md +8 -8
  7. package/README.md +419 -512
  8. package/SAFETY_CHECKLIST.md +15 -7
  9. package/SERVICES.md +194 -0
  10. package/SETTINGS_REFERENCE.md +236 -17
  11. package/SKILL.md +5 -5
  12. package/TROUBLESHOOTING.md +35 -14
  13. package/action.yml +12 -4
  14. package/audit/README.md +84 -0
  15. package/audit/audit-checklist.md +152 -0
  16. package/audit/boundary-selftest.sh +85 -0
  17. package/audit/boundary.sh +123 -0
  18. package/audit/count-hooks.py +42 -0
  19. package/audit/find-dead-hooks.sh +82 -0
  20. package/audit/find-unfirable-rules.sh +142 -0
  21. package/audit/fire.sh +97 -0
  22. package/audit/selftest.sh +42 -0
  23. package/audit/unfirable-selftest.sh +81 -0
  24. package/audit-web/index.html +9 -9
  25. package/examples/README.md +54 -17
  26. package/examples/account-billing-log.sh +98 -0
  27. package/examples/account-routing-preflight.sh +123 -0
  28. package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
  29. package/examples/agent-view-quota-decrement.sh +32 -0
  30. package/examples/agent-view-quota-warn.sh +94 -0
  31. package/examples/agents-md-edit-drift-warner.sh +223 -0
  32. package/examples/agents-md-loader.sh +160 -0
  33. package/examples/agents-md-sync-checker.sh +102 -0
  34. package/examples/ai-slop-punctuation-arrest.sh +210 -0
  35. package/examples/allowlist.sh +70 -10
  36. package/examples/always-allow-pattern-suggester.sh +125 -0
  37. package/examples/ansible-vault-guard.sh +2 -1
  38. package/examples/anthropic-base-url-guard.sh +76 -0
  39. package/examples/api-busyloop-guard.sh +123 -0
  40. package/examples/api-endpoint-guard.sh +12 -0
  41. package/examples/api-key-in-url-guard.sh +17 -1
  42. package/examples/api-rate-limit-guard.sh +36 -1
  43. package/examples/api-rate-limit-tracker.sh +12 -0
  44. package/examples/articulated-scope-capture.sh +101 -0
  45. package/examples/askuserquestion-autonomy-gate.sh +102 -0
  46. package/examples/attachment-traversal-guard.sh +118 -0
  47. package/examples/aup-block-pattern-logger.sh +161 -0
  48. package/examples/aup-false-positive-helper.sh +124 -0
  49. package/examples/aup-large-tool-output-warner.sh +282 -0
  50. package/examples/aup-retry-loop-guard.sh +229 -0
  51. package/examples/auth-expiry-reminder.sh +157 -0
  52. package/examples/auth-macos-sleep-detector.sh +185 -0
  53. package/examples/auth-path-detector.sh +171 -0
  54. package/examples/auth-status-checker.sh +157 -0
  55. package/examples/authorized-reconfirmation-detector.sh +195 -0
  56. package/examples/auto-approve-build.sh +39 -0
  57. package/examples/auto-approve-cargo.sh +31 -1
  58. package/examples/auto-approve-docker.sh +35 -0
  59. package/examples/auto-approve-git-read.sh +37 -14
  60. package/examples/auto-approve-go.sh +30 -1
  61. package/examples/auto-approve-gradle.sh +29 -1
  62. package/examples/auto-approve-make.sh +29 -1
  63. package/examples/auto-approve-maven.sh +29 -1
  64. package/examples/auto-approve-python.sh +41 -1
  65. package/examples/auto-approve-readonly-tools.sh +1 -0
  66. package/examples/auto-approve-readonly.sh +110 -33
  67. package/examples/auto-approve-ssh.sh +30 -1
  68. package/examples/auto-approve-test.sh +44 -0
  69. package/examples/auto-checkpoint.sh +1 -1
  70. package/examples/auto-compact-prep.sh +0 -0
  71. package/examples/auto-git-checkpoint.sh +0 -0
  72. package/examples/auto-mode-safe-commands.sh +53 -1
  73. package/examples/auto-mode-safety-enforcer.sh +151 -4
  74. package/examples/auto-push-session-branch.sh +22 -0
  75. package/examples/aws-production-guard.sh +13 -1
  76. package/examples/aws-region-guard.sh +1 -1
  77. package/examples/background-cost-launch-guard.sh +82 -0
  78. package/examples/background-task-guard.sh +12 -0
  79. package/examples/backup-before-refactor.sh +0 -0
  80. package/examples/banned-command-guard.sh +12 -0
  81. package/examples/bash-allowlist-secondary-check.sh +157 -0
  82. package/examples/bash-domain-allowlist.sh +12 -0
  83. package/examples/bash-fanout-bounded-rewriter.sh +191 -0
  84. package/examples/bash-heuristic-approver.sh +112 -10
  85. package/examples/bash-project-fence.sh +194 -0
  86. package/examples/bash-safety-auto-deny.sh +12 -0
  87. package/examples/bash-secret-output-detector.sh +44 -3
  88. package/examples/bash-trace-guard.sh +12 -0
  89. package/examples/bashrc-safety-check.sh +0 -0
  90. package/examples/bg-permission-prompt-warner.sh +182 -0
  91. package/examples/bg-task-cooldown-guard.sh +12 -0
  92. package/examples/binary-read-detector.sh +135 -0
  93. package/examples/binary-upload-guard.sh +12 -0
  94. package/examples/block-database-wipe.sh +35 -10
  95. package/examples/branch-name-check.sh +8 -3
  96. package/examples/branch-naming-convention.sh +0 -0
  97. package/examples/broad-find-guard.sh +12 -0
  98. package/examples/broad-prefix-session-trap-warner.sh +106 -0
  99. package/examples/bulk-file-delete-guard.sh +45 -0
  100. package/examples/bypass-mode-effective-verifier.sh +203 -0
  101. package/examples/cache-creation-drift-detector.sh +120 -0
  102. package/examples/cache-residue-detector.sh +195 -0
  103. package/examples/cache-tier-logger.sh +70 -0
  104. package/examples/cache-ttl-eviction-detector.sh +149 -0
  105. package/examples/cargo-publish-guard.sh +14 -1
  106. package/examples/case-insensitive-path-guard.sh +21 -2
  107. package/examples/case-sensitive-guard.sh +23 -2
  108. package/examples/cch-cache-guard.sh +0 -0
  109. package/examples/cch-sentinel-precommit-guard.sh +47 -0
  110. package/examples/check-abort-controller.sh +1 -1
  111. package/examples/check-accessibility.sh +0 -0
  112. package/examples/check-aria-labels.sh +0 -0
  113. package/examples/check-before-act-enforcer.sh +12 -0
  114. package/examples/check-charset-meta.sh +0 -0
  115. package/examples/check-cookie-flags.sh +0 -0
  116. package/examples/check-cors-config.sh +0 -0
  117. package/examples/check-csp-headers.sh +0 -0
  118. package/examples/check-csrf-protection.sh +0 -0
  119. package/examples/check-debounce.sh +1 -1
  120. package/examples/check-dependency-age.sh +0 -0
  121. package/examples/check-dependency-license.sh +0 -0
  122. package/examples/check-dockerfile-best-practice.sh +0 -0
  123. package/examples/check-error-boundaries.sh +0 -0
  124. package/examples/check-error-class.sh +1 -1
  125. package/examples/check-error-handling.sh +0 -0
  126. package/examples/check-error-logging.sh +1 -1
  127. package/examples/check-error-message.sh +0 -0
  128. package/examples/check-error-stack.sh +0 -0
  129. package/examples/check-favicon.sh +0 -0
  130. package/examples/check-git-hooks-compat.sh +0 -0
  131. package/examples/check-gitattributes.sh +0 -0
  132. package/examples/check-https-redirect.sh +0 -0
  133. package/examples/check-input-validation.sh +0 -0
  134. package/examples/check-lang-attribute.sh +0 -0
  135. package/examples/check-npm-scripts-exist.sh +0 -0
  136. package/examples/check-package-size.sh +0 -0
  137. package/examples/check-port-availability.sh +0 -0
  138. package/examples/check-promise-all.sh +1 -1
  139. package/examples/check-rate-limiting.sh +0 -0
  140. package/examples/check-return-types.sh +0 -0
  141. package/examples/check-semantic-versioning.sh +0 -0
  142. package/examples/check-suspense-fallback.sh +1 -1
  143. package/examples/check-test-exists.sh +0 -0
  144. package/examples/check-test-naming.sh +0 -0
  145. package/examples/check-timeout-cleanup.sh +1 -1
  146. package/examples/check-tls-version.sh +0 -0
  147. package/examples/check-unsubscribe.sh +1 -1
  148. package/examples/check-viewport-meta.sh +0 -0
  149. package/examples/check-worker-terminate.sh +1 -1
  150. package/examples/checkpoint-tamper-guard.sh +12 -0
  151. package/examples/chmod-guard.sh +12 -0
  152. package/examples/chown-guard.sh +24 -0
  153. package/examples/ci-workflow-guard.sh +6 -1
  154. package/examples/claim-verify-detector.sh +109 -0
  155. package/examples/claim-vs-caveat-checker.sh +77 -0
  156. package/examples/classifier-fallback-allow.sh +114 -40
  157. package/examples/claude-cache-gc.sh +1 -0
  158. package/examples/claude-code-version-pin-advisor.sh +183 -0
  159. package/examples/claude-md-reinjector.sh +129 -0
  160. package/examples/claude-md-size-monitor.sh +66 -0
  161. package/examples/claude-update-budget-guard.sh +123 -0
  162. package/examples/claude-update-smart.sh +113 -0
  163. package/examples/claudeignore-enforce-guard.sh +12 -0
  164. package/examples/claudemd-enforcer.sh +0 -0
  165. package/examples/claudemd-tool-prohibition.sh +128 -0
  166. package/examples/clear-command-confirm-guard.sh +32 -15
  167. package/examples/cli-config-pinning-detector.sh +162 -0
  168. package/examples/cliff-countdown-advisor.sh +96 -0
  169. package/examples/clipboard-secret-guard.sh +12 -0
  170. package/examples/closure-word-verify-gate.sh +150 -0
  171. package/examples/cloud-cli-guard.sh +39 -2
  172. package/examples/commit-all-scope-guard.sh +44 -0
  173. package/examples/commit-message-check.sh +1 -1
  174. package/examples/commit-message-quality.sh +6 -1
  175. package/examples/commitment-carry-forward-arrest.sh +361 -0
  176. package/examples/compact-alert-notification.sh +0 -0
  177. package/examples/compact-dispatch-watchdog.sh +149 -0
  178. package/examples/completion-claim-without-verification-detector.sh +207 -0
  179. package/examples/composer-guard.sh +12 -0
  180. package/examples/compound-bash-permission-resolver.sh +156 -0
  181. package/examples/compound-command-allow.sh +1 -1
  182. package/examples/compound-command-deny-enforcer.sh +183 -0
  183. package/examples/compound-inject-guard.sh +12 -0
  184. package/examples/concurrent-edit-lock.sh +12 -0
  185. package/examples/conflict-marker-guard.sh +12 -0
  186. package/examples/consecutive-error-breaker.sh +0 -0
  187. package/examples/console-log-count.sh +1 -0
  188. package/examples/context-compact-advisor.sh +29 -2
  189. package/examples/context-length-budget.sh +69 -0
  190. package/examples/context-threshold-alert.sh +12 -0
  191. package/examples/context-usage-drift-alert.sh +41 -13
  192. package/examples/conversation-history-guard.sh +12 -0
  193. package/examples/core-file-protect-guard.sh +12 -0
  194. package/examples/cors-star-warn.sh +0 -0
  195. package/examples/cost-incident-self-audit.sh +162 -0
  196. package/examples/cowork-claude-md-load-checker.sh +100 -0
  197. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  198. package/examples/cowork-hook-absence-warner.sh +167 -0
  199. package/examples/cowork-model-picker-advisor.sh +115 -0
  200. package/examples/credential-exfil-guard.sh +65 -4
  201. package/examples/credential-file-cat-guard.sh +17 -1
  202. package/examples/cron-create-receipt.sh +112 -0
  203. package/examples/cron-modification-guard.sh +12 -0
  204. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  205. package/examples/cwd-project-boundary-guard.sh +0 -0
  206. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  207. package/examples/daily-cost-guard.sh +164 -0
  208. package/examples/daily-usage-tracker.sh +0 -0
  209. package/examples/dangerous-pip-flag-guard.sh +12 -0
  210. package/examples/db-connect-guard.sh +13 -1
  211. package/examples/denied-action-retry-guard.sh +12 -0
  212. package/examples/deny-bypass-detector.sh +12 -0
  213. package/examples/deny-rule-integrity-verifier.sh +181 -0
  214. package/examples/dependency-install-guard.sh +12 -0
  215. package/examples/deploy-guard.sh +14 -2
  216. package/examples/deploy-path-verify-guard.sh +12 -0
  217. package/examples/deployment-readback-gate.sh +135 -0
  218. package/examples/deployment-readback-gh-adapter.sh +247 -0
  219. package/examples/deployment-verify-guard.sh +25 -2
  220. package/examples/destructive-db-script-write-guard.sh +166 -0
  221. package/examples/destructive-migration-write-guard.sh +163 -0
  222. package/examples/diff-size-guard.sh +12 -0
  223. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  224. package/examples/disk-partition-guard.sh +12 -0
  225. package/examples/dispatch-allowlist-preflight.sh +301 -0
  226. package/examples/dispatch-liveness-watchdog.sh +216 -0
  227. package/examples/dispatch-receipt.sh +174 -0
  228. package/examples/django-migrate-guard.sh +12 -0
  229. package/examples/dns-config-guard.sh +12 -0
  230. package/examples/docker-dangerous-guard.sh +12 -0
  231. package/examples/docker-volume-guard.sh +0 -0
  232. package/examples/dockerfile-latest-guard.sh +1 -0
  233. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  234. package/examples/dotenv-commit-guard.sh +12 -0
  235. package/examples/dotenv-read-guard.sh +12 -0
  236. package/examples/dotfile-protection-guard.sh +12 -0
  237. package/examples/dotnet-build-on-edit.sh +1 -1
  238. package/examples/drizzle-migrate-guard.sh +27 -2
  239. package/examples/echo-probe-spam-detector.sh +176 -0
  240. package/examples/edit-counter-test-gate.sh +12 -0
  241. package/examples/edit-error-counter.sh +1 -1
  242. package/examples/edit-guard.sh +12 -0
  243. package/examples/edit-old-string-validator.sh +12 -0
  244. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  245. package/examples/edit-retry-loop-guard.sh +0 -0
  246. package/examples/edit-verify.sh +0 -0
  247. package/examples/env-inline-secret-guard.sh +14 -2
  248. package/examples/env-naming-convention.sh +0 -0
  249. package/examples/env-prod-guard.sh +0 -0
  250. package/examples/env-required-check.sh +0 -0
  251. package/examples/env-source-guard.sh +12 -0
  252. package/examples/env-var-check.sh +24 -1
  253. package/examples/ephemeral-container-detector.sh +147 -0
  254. package/examples/error-memory-guard.sh +12 -0
  255. package/examples/evidence-claim-gate.sh +187 -0
  256. package/examples/exploration-budget-guard.sh +12 -0
  257. package/examples/expo-eject-guard.sh +13 -0
  258. package/examples/extended-thinking-loop-guard.sh +139 -0
  259. package/examples/extended-thinking-resume-warning.sh +119 -0
  260. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  261. package/examples/fabricated-command-detector.sh +145 -0
  262. package/examples/false-disk-full-guard.sh +63 -0
  263. package/examples/feature-deprecation-detector.sh +109 -0
  264. package/examples/file-change-tracker.sh +1 -1
  265. package/examples/file-change-undo-tracker.sh +0 -0
  266. package/examples/file-edit-backup.sh +63 -14
  267. package/examples/file-reference-check.sh +0 -0
  268. package/examples/file-size-limit.sh +12 -0
  269. package/examples/financial-operation-guard.sh +12 -0
  270. package/examples/firewall-guard.sh +12 -0
  271. package/examples/fish-shell-wrapper.sh +125 -7
  272. package/examples/five-hundred-milestone.sh +1 -0
  273. package/examples/flask-static-route-guard.sh +89 -0
  274. package/examples/forbidden-response-phrase-detector.sh +161 -0
  275. package/examples/gem-push-guard.sh +13 -0
  276. package/examples/gh-cli-destructive-guard.sh +13 -1
  277. package/examples/git-checkout-safety-guard.sh +12 -0
  278. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  279. package/examples/git-config-guard.sh +12 -0
  280. package/examples/git-crypt-worktree-guard.sh +12 -0
  281. package/examples/git-filter-repo-guard.sh +56 -0
  282. package/examples/git-history-rewrite-guard.sh +12 -0
  283. package/examples/git-hook-bypass-guard.sh +0 -0
  284. package/examples/git-maintenance-guard.sh +83 -0
  285. package/examples/git-merge-conflict-prevent.sh +0 -0
  286. package/examples/git-message-length-check.sh +0 -0
  287. package/examples/git-message-length.sh +0 -0
  288. package/examples/git-operations-require-approval.sh +68 -14
  289. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  290. package/examples/git-push-blast-radius-guard.sh +218 -0
  291. package/examples/git-remote-guard.sh +24 -3
  292. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  293. package/examples/git-stash-before-checkout.sh +12 -0
  294. package/examples/git-stash-before-danger.sh +0 -0
  295. package/examples/git-submodule-guard.sh +69 -2
  296. package/examples/git-tag-guard.sh +12 -0
  297. package/examples/github-actions-secret-guard.sh +0 -0
  298. package/examples/gitignore-check.sh +0 -0
  299. package/examples/gitops-drift-guard.sh +12 -0
  300. package/examples/go-mod-tidy-warn.sh +1 -0
  301. package/examples/go-vet-after-edit.sh +12 -0
  302. package/examples/goal-iteration-limit-warner.sh +152 -0
  303. package/examples/grep-nul-false-negative-guard.sh +30 -0
  304. package/examples/growthbook-flag-monitor.sh +257 -0
  305. package/examples/hallucination-url-check.sh +1 -1
  306. package/examples/halt-signal-detector.sh +135 -0
  307. package/examples/handoff-on-clear.sh +65 -0
  308. package/examples/hardcoded-ip-guard.sh +1 -0
  309. package/examples/headless-empty-result-guard.sh +0 -0
  310. package/examples/headless-stop-guard.sh +0 -0
  311. package/examples/helm-install-guard.sh +2 -1
  312. package/examples/home-critical-bash-guard.sh +17 -1
  313. package/examples/hook-debug-wrapper.sh +6 -2
  314. package/examples/hook-permission-fixer.sh +0 -0
  315. package/examples/hook-self-disable-detector.sh +99 -0
  316. package/examples/hook-stdout-sanitizer.sh +6 -2
  317. package/examples/hook-tamper-guard.sh +12 -0
  318. package/examples/idle-session-cost-alert.sh +0 -0
  319. package/examples/image-dimension-guard.sh +109 -0
  320. package/examples/image-file-validator.sh +0 -0
  321. package/examples/iteration-quality-degradation-detector.sh +170 -0
  322. package/examples/java-compile-on-edit.sh +1 -1
  323. package/examples/json-syntax-check.sh +0 -0
  324. package/examples/k8s-production-guard.sh +13 -1
  325. package/examples/kill-process-guard.sh +12 -0
  326. package/examples/kubernetes-guard.sh +13 -1
  327. package/examples/laravel-artisan-guard.sh +13 -0
  328. package/examples/large-file-guard.sh +1 -1
  329. package/examples/log-level-guard.sh +0 -0
  330. package/examples/log-truncation-guard.sh +12 -0
  331. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  332. package/examples/loop-detector.sh +12 -0
  333. package/examples/magic-number-warn.sh +1 -0
  334. package/examples/main-branch-warn.sh +12 -0
  335. package/examples/markdown-link-check.sh +0 -0
  336. package/examples/max-concurrent-agents.sh +12 -0
  337. package/examples/max-edit-size-guard.sh +13 -0
  338. package/examples/max-file-count-guard.sh +0 -0
  339. package/examples/max-file-delete-count.sh +0 -0
  340. package/examples/max-function-length.sh +1 -0
  341. package/examples/max-import-count.sh +0 -0
  342. package/examples/max-subagent-count.sh +0 -0
  343. package/examples/mcp-config-freeze.sh +12 -0
  344. package/examples/mcp-config-poisoning-audit.sh +150 -0
  345. package/examples/mcp-data-boundary.sh +1 -1
  346. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  347. package/examples/mcp-orphan-leak-warner.sh +49 -0
  348. package/examples/mcp-permissions-ask-warner.sh +151 -0
  349. package/examples/mcp-routine-approval-detector.sh +154 -0
  350. package/examples/mcp-server-allowlist.sh +12 -0
  351. package/examples/mcp-server-guard.sh +12 -0
  352. package/examples/mcp-startup-bloat-detector.sh +87 -0
  353. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  354. package/examples/mcp-tool-audit-log.sh +0 -0
  355. package/examples/mcp-tool-guard.sh +101 -1
  356. package/examples/mcp-warmup-wait.sh +0 -0
  357. package/examples/memory-chain-audit.sh +56 -0
  358. package/examples/memory-orphan-detector.sh +188 -0
  359. package/examples/memory-write-guard.sh +99 -17
  360. package/examples/migration-verify-guard.sh +12 -0
  361. package/examples/model-swap-suggester.sh +177 -0
  362. package/examples/model-version-alert.sh +5 -1
  363. package/examples/model-version-lock.sh +63 -0
  364. package/examples/move-delete-sequence-guard.sh +33 -2
  365. package/examples/multi-file-plan-routing-gate.sh +192 -0
  366. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  367. package/examples/multi-window-auth-drift-detector.sh +183 -0
  368. package/examples/multiline-command-approver.sh +161 -23
  369. package/examples/nested-background-agent-guard.sh +109 -0
  370. package/examples/nested-spawn-inflight-guard.sh +178 -0
  371. package/examples/network-exfil-guard.sh +12 -0
  372. package/examples/network-guard.sh +12 -0
  373. package/examples/network-interface-guard.sh +12 -0
  374. package/examples/nextjs-env-guard.sh +1 -1
  375. package/examples/no-absolute-import.sh +0 -0
  376. package/examples/no-alert-confirm-prompt.sh +0 -0
  377. package/examples/no-anonymous-default-export.sh +0 -0
  378. package/examples/no-any-type.sh +0 -0
  379. package/examples/no-any-typescript.sh +1 -0
  380. package/examples/no-ask-human.sh +12 -0
  381. package/examples/no-assignment-in-condition.sh +0 -0
  382. package/examples/no-base64-exfil.sh +12 -0
  383. package/examples/no-callback-hell.sh +0 -0
  384. package/examples/no-circular-dependency.sh +0 -0
  385. package/examples/no-cleartext-storage.sh +0 -0
  386. package/examples/no-commented-code.sh +0 -0
  387. package/examples/no-commit-fixup.sh +0 -0
  388. package/examples/no-console-assert.sh +0 -0
  389. package/examples/no-console-error-swallow.sh +0 -0
  390. package/examples/no-console-in-prod.sh +0 -0
  391. package/examples/no-console-log-commit.sh +12 -0
  392. package/examples/no-console-log.sh +0 -0
  393. package/examples/no-console-time.sh +0 -0
  394. package/examples/no-cors-wildcard.sh +4 -1
  395. package/examples/no-curl-upload.sh +0 -0
  396. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  397. package/examples/no-dangling-await.sh +1 -0
  398. package/examples/no-debug-commit.sh +12 -0
  399. package/examples/no-debug-in-commit.sh +0 -0
  400. package/examples/no-deep-nesting.sh +0 -0
  401. package/examples/no-deep-relative-import.sh +1 -0
  402. package/examples/no-default-credentials.sh +0 -0
  403. package/examples/no-deploy-friday.sh +13 -1
  404. package/examples/no-disabled-test.sh +0 -0
  405. package/examples/no-document-write.sh +0 -0
  406. package/examples/no-empty-function.sh +0 -0
  407. package/examples/no-eval-in-template.sh +0 -0
  408. package/examples/no-eval-template.sh +3 -1
  409. package/examples/no-eval.sh +0 -0
  410. package/examples/no-exec-user-input.sh +0 -0
  411. package/examples/no-fixme-ship.sh +12 -0
  412. package/examples/no-floating-promises.sh +0 -0
  413. package/examples/no-force-flag.sh +22 -5
  414. package/examples/no-force-install.sh +0 -0
  415. package/examples/no-git-amend.sh +12 -0
  416. package/examples/no-git-rebase-public.sh +0 -0
  417. package/examples/no-global-install.sh +12 -0
  418. package/examples/no-global-state.sh +0 -0
  419. package/examples/no-hardcoded-port.sh +1 -0
  420. package/examples/no-hardcoded-url.sh +0 -0
  421. package/examples/no-helmet-missing.sh +0 -0
  422. package/examples/no-http-url.sh +1 -0
  423. package/examples/no-http-without-https.sh +0 -0
  424. package/examples/no-inline-style.sh +0 -0
  425. package/examples/no-inline-styles.sh +1 -0
  426. package/examples/no-innerhtml.sh +0 -0
  427. package/examples/no-install-global.sh +12 -0
  428. package/examples/no-jwt-in-url.sh +0 -0
  429. package/examples/no-large-commit.sh +0 -0
  430. package/examples/no-localhost-expose.sh +0 -0
  431. package/examples/no-magic-number.sh +0 -0
  432. package/examples/no-md5-sha1.sh +0 -0
  433. package/examples/no-mixed-line-endings.sh +8 -1
  434. package/examples/no-mutation-in-reducer.sh +0 -0
  435. package/examples/no-nested-ternary.sh +0 -0
  436. package/examples/no-network-exfil.sh +0 -0
  437. package/examples/no-open-redirect.sh +0 -0
  438. package/examples/no-output-truncation.sh +12 -0
  439. package/examples/no-package-downgrade.sh +0 -0
  440. package/examples/no-package-lock-edit.sh +12 -0
  441. package/examples/no-path-join-user-input.sh +0 -0
  442. package/examples/no-port-bind.sh +0 -0
  443. package/examples/no-process-exit.sh +0 -0
  444. package/examples/no-prototype-pollution.sh +0 -0
  445. package/examples/no-push-without-ci.sh +0 -0
  446. package/examples/no-push-without-tests.sh +12 -0
  447. package/examples/no-raw-password-in-url.sh +0 -0
  448. package/examples/no-root-user-docker.sh +1 -0
  449. package/examples/no-root-write.sh +12 -0
  450. package/examples/no-secrets-in-args.sh +4 -1
  451. package/examples/no-secrets-in-logs.sh +0 -0
  452. package/examples/no-sensitive-log.sh +0 -0
  453. package/examples/no-sleep-in-hooks.sh +0 -0
  454. package/examples/no-star-import-python.sh +1 -0
  455. package/examples/no-string-concat-sql.sh +0 -0
  456. package/examples/no-sudo-guard.sh +12 -0
  457. package/examples/no-sync-fs.sh +0 -0
  458. package/examples/no-todo-in-merge.sh +0 -0
  459. package/examples/no-todo-in-production.sh +1 -0
  460. package/examples/no-todo-without-issue.sh +0 -0
  461. package/examples/no-unused-import.sh +0 -0
  462. package/examples/no-var-keyword.sh +0 -0
  463. package/examples/no-verify-blocker.sh +12 -0
  464. package/examples/no-wget-piped-bash.sh +12 -0
  465. package/examples/no-wildcard-cors.sh +0 -0
  466. package/examples/no-wildcard-delete.sh +0 -0
  467. package/examples/no-wildcard-import.sh +0 -0
  468. package/examples/no-with-statement.sh +0 -0
  469. package/examples/no-write-outside-src.sh +0 -0
  470. package/examples/no-xml-external-entity.sh +0 -0
  471. package/examples/non-english-quality-warner.sh +156 -0
  472. package/examples/notify-waiting.sh +1 -1
  473. package/examples/npm-audit-warn.sh +0 -0
  474. package/examples/npm-global-install-guard.sh +12 -0
  475. package/examples/npm-publish-guard.sh +12 -0
  476. package/examples/npm-script-injection.sh +0 -0
  477. package/examples/npm-supply-chain-guard.sh +0 -0
  478. package/examples/nuxt-config-guard.sh +1 -0
  479. package/examples/oauth-refresh-monitor.sh +210 -0
  480. package/examples/opus-degradation-tracker.sh +187 -0
  481. package/examples/opus48-routine-task-warning.sh +196 -0
  482. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  483. package/examples/output-credential-scan.sh +1 -1
  484. package/examples/output-secret-mask.sh +31 -9
  485. package/examples/output-token-spike-detector.sh +145 -0
  486. package/examples/package-json-guard.sh +12 -0
  487. package/examples/package-lock-frozen.sh +12 -0
  488. package/examples/parallel-batch-size-limiter.sh +121 -0
  489. package/examples/parallel-cascade-detector.sh +116 -0
  490. package/examples/partial-view-claim-arrest.sh +174 -0
  491. package/examples/path-deny-bash-guard.sh +12 -0
  492. package/examples/path-traversal-guard.sh +12 -0
  493. package/examples/per-prompt-token-cap.sh +124 -0
  494. package/examples/permission-audit-log.sh +1 -1
  495. package/examples/permission-denial-enforcer.sh +12 -0
  496. package/examples/permission-entry-validator.sh +0 -0
  497. package/examples/persisted-1m-model-advisor.sh +88 -0
  498. package/examples/php-lint-on-edit.sh +1 -1
  499. package/examples/pii-upload-guard.sh +12 -0
  500. package/examples/pip-publish-guard.sh +13 -0
  501. package/examples/pip-requirements-guard.sh +12 -0
  502. package/examples/pip-venv-required.sh +12 -0
  503. package/examples/plan-mode-edit-guard.sh +12 -0
  504. package/examples/plan-mode-enforcer.sh +12 -0
  505. package/examples/plan-mode-strict-guard.sh +12 -0
  506. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  507. package/examples/plugin-process-cleanup.sh +0 -0
  508. package/examples/polyglot-rm-guard.sh +12 -0
  509. package/examples/post-compact-safety.sh +12 -0
  510. package/examples/post-edit-disk-verify.sh +152 -0
  511. package/examples/powershell-remove-item-guard.sh +85 -0
  512. package/examples/pr-description-check.sh +0 -0
  513. package/examples/pr-duplicate-guard.sh +13 -0
  514. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  515. package/examples/pre-compact-knowledge-save.sh +0 -0
  516. package/examples/pre-compact-transcript-backup.sh +0 -0
  517. package/examples/pre-execution-claim-detector.sh +179 -0
  518. package/examples/prefer-builtin-tools.sh +10 -1
  519. package/examples/prefer-const.sh +0 -0
  520. package/examples/prefer-dedicated-tools.sh +12 -0
  521. package/examples/prefer-optional-chaining.sh +0 -0
  522. package/examples/prisma-migrate-guard.sh +24 -7
  523. package/examples/production-port-kill-guard.sh +12 -0
  524. package/examples/prompt-injection-guard.sh +2 -1
  525. package/examples/prompt-usage-logger.sh +0 -0
  526. package/examples/protect-claudemd.sh +12 -0
  527. package/examples/protect-dotfiles.sh +12 -0
  528. package/examples/proxy-capture-suggester.sh +159 -0
  529. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  530. package/examples/public-repo-push-guard.sh +12 -0
  531. package/examples/push-requires-test-pass-record.sh +0 -0
  532. package/examples/push-requires-test-pass.sh +12 -0
  533. package/examples/quota-anomaly-detector.sh +173 -0
  534. package/examples/quota-reset-audit.sh +58 -0
  535. package/examples/quoted-flag-approver.sh +99 -10
  536. package/examples/rails-migration-guard.sh +12 -0
  537. package/examples/rate-limit-guard.sh +0 -0
  538. package/examples/read-all-files-enforcer.sh +0 -0
  539. package/examples/read-budget-guard.sh +12 -0
  540. package/examples/read-loop-detector.sh +59 -0
  541. package/examples/read-once-guard.sh +96 -0
  542. package/examples/read-only-mode.sh +12 -0
  543. package/examples/readme-exists-check.sh +0 -0
  544. package/examples/record-read-coverage.sh +73 -0
  545. package/examples/redirect-fragment-warner.sh +149 -0
  546. package/examples/redis-flushall-guard.sh +13 -0
  547. package/examples/redundant-read-blocker.sh +132 -0
  548. package/examples/refusal-arrest-gate.sh +248 -0
  549. package/examples/registry-publish-guard.sh +13 -1
  550. package/examples/remote-control-billing-classifier.sh +135 -0
  551. package/examples/replace-all-guard.sh +12 -0
  552. package/examples/repo-visibility-guard.sh +12 -0
  553. package/examples/reroute-after-block-guard.sh +150 -0
  554. package/examples/response-budget-guard.sh +0 -0
  555. package/examples/resume-drift-watcher.sh +57 -0
  556. package/examples/rg-replace-flag-detector.sh +125 -0
  557. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  558. package/examples/ripgrep-permission-fix.sh +0 -0
  559. package/examples/rm-safety-net.sh +151 -8
  560. package/examples/role-tool-guard.sh +12 -0
  561. package/examples/route-handler-emptiness-gate.sh +324 -0
  562. package/examples/ruby-lint-on-edit.sh +1 -1
  563. package/examples/runtime-binary-change-detector.sh +102 -0
  564. package/examples/same-command-repeat-detector.sh +196 -0
  565. package/examples/same-correction-arrest.sh +169 -0
  566. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  567. package/examples/sandbox-relative-path-audit.sh +83 -25
  568. package/examples/sandbox-write-verify.sh +12 -0
  569. package/examples/schema-migration-guard.sh +0 -0
  570. package/examples/scope-expansion-receipt.sh +178 -0
  571. package/examples/scope-guard.sh +88 -9
  572. package/examples/secret-file-read-guard.sh +12 -0
  573. package/examples/secret-file-write-guard.sh +150 -0
  574. package/examples/self-modify-bypass-guard.sh +0 -0
  575. package/examples/sensitive-file-read-guard.sh +23 -3
  576. package/examples/sensitive-log-guard.sh +1 -0
  577. package/examples/server-side-prompt-injection-detector.sh +69 -0
  578. package/examples/session-agent-cost-limiter.sh +12 -0
  579. package/examples/session-backup-on-start.sh +1 -1
  580. package/examples/session-cost-alert.sh +12 -0
  581. package/examples/session-drift-guard.sh +12 -0
  582. package/examples/session-duration-guard.sh +25 -2
  583. package/examples/session-end-logger.sh +0 -0
  584. package/examples/session-health-monitor.sh +0 -0
  585. package/examples/session-index-repair.sh +1 -1
  586. package/examples/session-memory-watchdog.sh +1 -0
  587. package/examples/session-permission-reset-guard.sh +12 -0
  588. package/examples/session-persistence-verifier.sh +93 -0
  589. package/examples/session-plugin-pin-watch.sh +68 -0
  590. package/examples/session-rate-monitor.sh +176 -0
  591. package/examples/session-resume-env-fix.sh +0 -0
  592. package/examples/session-start-quota-status.sh +193 -0
  593. package/examples/session-start-safety-check.sh +55 -3
  594. package/examples/session-state-saver.sh +0 -0
  595. package/examples/session-summary-stop.sh +1 -1
  596. package/examples/session-summary.sh +0 -0
  597. package/examples/session-token-counter.sh +1 -1
  598. package/examples/settings-hooks-key-restorer.sh +99 -0
  599. package/examples/settings-json-health-check.sh +57 -0
  600. package/examples/settings-json-model-guard.sh +0 -0
  601. package/examples/settings-regression-tester.sh +188 -0
  602. package/examples/shell-config-truncation-guard.sh +12 -0
  603. package/examples/shell-wrapper-guard.sh +12 -0
  604. package/examples/skill-cumulative-size-detector.sh +104 -0
  605. package/examples/skill-description-drop-detector.sh +148 -0
  606. package/examples/skill-gate.sh +0 -0
  607. package/examples/skill-truncation-detector.sh +154 -0
  608. package/examples/skills-context-recorder.sh +167 -0
  609. package/examples/skills-load-verifier.sh +96 -0
  610. package/examples/skills-settings-validator.sh +139 -0
  611. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  612. package/examples/spec-file-scope-guard.sh +12 -0
  613. package/examples/spring-profile-guard.sh +1 -0
  614. package/examples/spurious-malformed-notice-detector.sh +247 -0
  615. package/examples/sql-bulk-delete-warn.sh +88 -0
  616. package/examples/sql-injection-detect.sh +0 -0
  617. package/examples/ssh-key-protect.sh +12 -0
  618. package/examples/staged-secret-scan.sh +22 -1
  619. package/examples/stale-temp-settings-detector.sh +86 -0
  620. package/examples/standing-rule-session-surfacer.sh +137 -0
  621. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  622. package/examples/stop-transcript-write-health.sh +64 -0
  623. package/examples/strict-allowlist.sh +57 -15
  624. package/examples/strip-coauthored-by.sh +50 -10
  625. package/examples/subagent-blast-radius-guard.sh +184 -0
  626. package/examples/subagent-boundary-precheck.sh +126 -0
  627. package/examples/subagent-budget-guard.sh +12 -0
  628. package/examples/subagent-claudemd-inject.sh +0 -0
  629. package/examples/subagent-closure-verify-gate.sh +164 -0
  630. package/examples/subagent-destructive-git-guard.sh +120 -0
  631. package/examples/subagent-error-detector.sh +0 -0
  632. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  633. package/examples/subagent-identity-leak-guard.sh +102 -0
  634. package/examples/subagent-identity-reassertion.sh +51 -0
  635. package/examples/subagent-inheritance-tester.sh +179 -0
  636. package/examples/subagent-permission-mode-guard.sh +110 -0
  637. package/examples/subagent-scope-guard.sh +12 -0
  638. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  639. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  640. package/examples/subagent-tool-call-limiter.sh +87 -15
  641. package/examples/subcommand-chain-guard.sh +12 -0
  642. package/examples/subscription-api-billing-warner.sh +160 -0
  643. package/examples/subscription-bypass-detector.sh +152 -0
  644. package/examples/svelte-lint-on-edit.sh +1 -0
  645. package/examples/swift-build-on-edit.sh +1 -1
  646. package/examples/symlink-guard.sh +27 -2
  647. package/examples/symlink-protect.sh +1 -0
  648. package/examples/system-dir-protection-guard.sh +73 -8
  649. package/examples/system-message-workaround.sh +38 -13
  650. package/examples/system-package-guard.sh +12 -0
  651. package/examples/systemd-service-guard.sh +12 -0
  652. package/examples/task-integrity-guard.sh +12 -0
  653. package/examples/temp-file-cleanup.sh +1 -1
  654. package/examples/temporal-suggestion-detector.sh +135 -0
  655. package/examples/terraform-guard.sh +27 -6
  656. package/examples/test-after-edit.sh +1 -1
  657. package/examples/test-before-push.sh +12 -0
  658. package/examples/test-coverage-reminder.sh +24 -1
  659. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  660. package/examples/timezone-guard.sh +0 -0
  661. package/examples/tmp-output-size-guard.sh +0 -0
  662. package/examples/todo-check.sh +1 -1
  663. package/examples/token-budget-guard.sh +12 -0
  664. package/examples/token-budget-per-task.sh +12 -0
  665. package/examples/token-usage-tracker.sh +7 -1
  666. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  667. package/examples/tokenizer-ratio-alert.sh +104 -0
  668. package/examples/tool-call-rate-limiter.sh +0 -0
  669. package/examples/tool-result-correlation-checker.sh +167 -0
  670. package/examples/tool-result-size-guard.sh +132 -0
  671. package/examples/tool-retry-budget-guard.sh +12 -0
  672. package/examples/transcript-contamination-detector.sh +138 -0
  673. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  674. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  675. package/examples/unbounded-output-guard.sh +94 -0
  676. package/examples/uncommitted-changes-stop.sh +1 -0
  677. package/examples/uncommitted-discard-guard.sh +23 -5
  678. package/examples/uncommitted-work-guard.sh +12 -0
  679. package/examples/usage-warn.sh +0 -0
  680. package/examples/user-account-guard.sh +12 -0
  681. package/examples/userprompt-submit-receipt.sh +123 -0
  682. package/examples/variable-expansion-guard.sh +12 -0
  683. package/examples/verify-after-publish-reminder.sh +93 -0
  684. package/examples/verify-before-commit.sh +12 -0
  685. package/examples/version-bump-detector.sh +156 -0
  686. package/examples/version-regression-warner.sh +144 -0
  687. package/examples/vue-lint-on-edit.sh +1 -0
  688. package/examples/warn-cron-cost-trap.sh +173 -0
  689. package/examples/webfetch-runaway-guard.sh +89 -0
  690. package/examples/wellness-break-reminder.sh +118 -0
  691. package/examples/windows-destructive-command-guard.sh +177 -0
  692. package/examples/windows-path-guard.sh +12 -0
  693. package/examples/windows-python-stub-detector.sh +63 -0
  694. package/examples/work-hours-guard.sh +12 -0
  695. package/examples/working-directory-fence.sh +12 -0
  696. package/examples/workspace-lease-guard.sh +205 -0
  697. package/examples/worktree-create-log.sh +1 -0
  698. package/examples/worktree-delete-guard.sh +12 -0
  699. package/examples/worktree-edit-boundary-guard.sh +127 -0
  700. package/examples/worktree-escape-write-guard.sh +114 -0
  701. package/examples/worktree-hook-linker.sh +0 -0
  702. package/examples/worktree-hooks-path-fix.sh +111 -0
  703. package/examples/worktree-parent-write-guard.sh +43 -0
  704. package/examples/worktree-project-unify.sh +2 -1
  705. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  706. package/examples/worktree-unmerged-guard.sh +7 -1
  707. package/examples/write-byte-integrity-verifier.sh +190 -0
  708. package/examples/write-empty-content-guard.sh +67 -0
  709. package/examples/write-nul-corruption-detector.sh +61 -0
  710. package/examples/write-overwrite-confirm.sh +160 -14
  711. package/examples/write-secret-guard.sh +27 -5
  712. package/examples/write-shrink-guard.sh +12 -0
  713. package/examples/write-test-ratio.sh +0 -0
  714. package/examples/wsl-host-disk-space-guard.sh +97 -0
  715. package/examples/xml-format-leak-detector.sh +266 -0
  716. package/examples/yaml-syntax-check.sh +12 -0
  717. package/hooks/hooks.json +6 -6
  718. package/index.mjs +1699 -183
  719. package/mission.md +2 -0
  720. package/package.json +4 -4
  721. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  722. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  723. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  724. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  725. package/scripts/agents-md-sync-setup.sh +156 -0
  726. package/scripts/autonomy-blocked-summary.sh +148 -0
  727. package/scripts/build-search-index.py +43 -0
  728. package/scripts/build-sitemap.py +119 -0
  729. package/scripts/cc-doctor.sh +192 -0
  730. package/scripts/check-hook-event-names.py +127 -0
  731. package/scripts/check-misfire-instrument.sh +64 -0
  732. package/scripts/claim-verify-audit.sh +467 -0
  733. package/scripts/cowork-claudemd-helper.sh +136 -0
  734. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  735. package/scripts/measure-heredoc-shapes.sh +67 -0
  736. package/scripts/measure-literal-match-misfire.sh +110 -0
  737. package/scripts/probe-scope-guard-branches.sh +48 -0
  738. package/scripts/probe-skip-line-both-ways.sh +65 -0
  739. package/scripts/receipts-aggregate.py +199 -0
  740. package/scripts/session-forensic-audit.py +360 -0
  741. package/scripts.json +9 -9
  742. package/scripts.json.bak-2026-07-27-find +13 -0
  743. package/skills/safety-setup/SKILL.md +5 -5
  744. package/tests/approve-side-remaining-two.test.sh +129 -0
  745. package/tests/approver-list-granularity.test.sh +145 -0
  746. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  747. package/tests/audit-ci-gate.test.sh +87 -0
  748. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  749. package/tests/audit-fail-open-parse.test.sh +100 -0
  750. package/tests/auto-approve-compound-tail.test.sh +194 -0
  751. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  752. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  753. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  754. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  755. package/tests/blindspots-cross-layer.test.sh +177 -0
  756. package/tests/block-database-wipe.test.sh +64 -0
  757. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  758. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  759. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  760. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  761. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  762. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  763. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  764. package/tests/destructive-guard-every-operand.test.sh +100 -0
  765. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  766. package/tests/destructive-guard-flag-order.test.sh +106 -0
  767. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  768. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  769. package/tests/destructive-guard-separators.test.sh +105 -0
  770. package/tests/destructive-guard-variable-target.test.sh +98 -0
  771. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  772. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  773. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  774. package/tests/example-guards-wrapped-command.test.sh +169 -0
  775. package/tests/file-edit-backup.test.sh +93 -0
  776. package/tests/git-filter-repo-guard.test.sh +60 -0
  777. package/tests/git-global-options-bypass.test.sh +141 -0
  778. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  779. package/tests/git-maintenance-guard.test.sh +83 -0
  780. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  781. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  782. package/tests/git-submodule-guard.test.sh +50 -0
  783. package/tests/grep-pcre-portability.test.sh +155 -0
  784. package/tests/hook-registration-matches-input.test.sh +73 -0
  785. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  786. package/tests/install-does-not-claim-protection.test.sh +110 -0
  787. package/tests/install-example-standalone-tools.test.sh +139 -0
  788. package/tests/line-continuation-bypass.test.sh +114 -0
  789. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  790. package/tests/nested-background-agent-guard.test.sh +58 -0
  791. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  792. package/tests/option-eating-grep-patterns.test.sh +130 -0
  793. package/tests/outdated-core-guards.test.sh +134 -0
  794. package/tests/outdated-report.test.sh +155 -0
  795. package/tests/output-secret-mask-warns.test.sh +73 -0
  796. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  797. package/tests/plugins-word-order.test.sh +126 -0
  798. package/tests/powershell-remove-item-guard.test.sh +85 -0
  799. package/tests/project-dir-naming.test.sh +103 -0
  800. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  801. package/tests/reroute-after-block-guard.test.sh +104 -0
  802. package/tests/secret-guard-documented-promises.test.sh +97 -0
  803. package/tests/session-plugin-pin-watch.test.sh +45 -0
  804. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  805. package/tests/shield-no-silent-adoption.test.py +110 -0
  806. package/tests/shield-no-silent-adoption.test.sh +46 -0
  807. package/tests/stop-transcript-write-health.test.sh +46 -0
  808. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  809. package/tests/test-account-billing-log.sh +100 -0
  810. package/tests/test-account-routing-preflight.sh +77 -0
  811. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  812. package/tests/test-agent-view-quota-warn.sh +184 -0
  813. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  814. package/tests/test-agents-md-loader.sh +204 -0
  815. package/tests/test-agents-md-sync-checker.sh +125 -0
  816. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  817. package/tests/test-allowlist.sh +60 -0
  818. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  819. package/tests/test-anthropic-base-url-guard.sh +88 -0
  820. package/tests/test-articulated-scope-capture.sh +139 -0
  821. package/tests/test-attachment-traversal-guard.sh +168 -0
  822. package/tests/test-aup-block-pattern-logger.sh +315 -0
  823. package/tests/test-aup-false-positive-helper.sh +188 -0
  824. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  825. package/tests/test-aup-retry-loop-guard.sh +341 -0
  826. package/tests/test-auth-expiry-reminder.sh +303 -0
  827. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  828. package/tests/test-auth-path-detector.sh +232 -0
  829. package/tests/test-auth-status-checker.sh +233 -0
  830. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  831. package/tests/test-background-cost-launch-guard.sh +62 -0
  832. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  833. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  834. package/tests/test-bash-project-fence.sh +127 -0
  835. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  836. package/tests/test-binary-read-detector.sh +173 -0
  837. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  838. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  839. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  840. package/tests/test-cache-creation-drift-detector.sh +244 -0
  841. package/tests/test-cache-residue-detector.sh +429 -0
  842. package/tests/test-cache-tier-logger.sh +59 -0
  843. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  844. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  845. package/tests/test-claim-verify-detector.sh +222 -0
  846. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  847. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  848. package/tests/test-claude-md-reinjector.sh +173 -0
  849. package/tests/test-claude-md-size-monitor.sh +107 -0
  850. package/tests/test-claude-update-budget-guard.sh +132 -0
  851. package/tests/test-claude-update-smart.sh +91 -0
  852. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  853. package/tests/test-cli-config-pinning-detector.sh +233 -0
  854. package/tests/test-cliff-countdown-advisor.sh +138 -0
  855. package/tests/test-closure-word-verify-gate.sh +158 -0
  856. package/tests/test-commit-all-scope-guard.sh +73 -0
  857. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  858. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  859. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  860. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  861. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  862. package/tests/test-context-length-budget.sh +68 -0
  863. package/tests/test-context-usage-drift-alert.sh +52 -22
  864. package/tests/test-cost-incident-self-audit.sh +94 -0
  865. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  866. package/tests/test-cowork-claudemd-helper.sh +141 -0
  867. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  868. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  869. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  870. package/tests/test-credential-exfil-guard.sh +62 -0
  871. package/tests/test-cron-create-receipt.sh +165 -0
  872. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  873. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  874. package/tests/test-daily-cost-guard.sh +131 -0
  875. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  876. package/tests/test-deployment-readback-gate.sh +92 -0
  877. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  878. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  879. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  880. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  881. package/tests/test-dispatch-receipt.sh +314 -0
  882. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  883. package/tests/test-echo-probe-spam-detector.sh +143 -0
  884. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  885. package/tests/test-ephemeral-container-detector.sh +251 -0
  886. package/tests/test-evidence-claim-gate.sh +291 -0
  887. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  888. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  889. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  890. package/tests/test-fabricated-command-detector.sh +296 -0
  891. package/tests/test-false-disk-full-guard.sh +36 -0
  892. package/tests/test-feature-deprecation-detector.sh +117 -0
  893. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  894. package/tests/test-git-operations-require-approval.sh +53 -0
  895. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  896. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  897. package/tests/test-growthbook-flag-monitor.sh +428 -0
  898. package/tests/test-halt-signal-detector.sh +120 -0
  899. package/tests/test-hook-self-disable-detector.sh +232 -0
  900. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  901. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  902. package/tests/test-marketplace-plugins.sh +193 -0
  903. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  904. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  905. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  906. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  907. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  908. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  909. package/tests/test-memory-chain-audit.sh +59 -0
  910. package/tests/test-memory-orphan-detector.sh +227 -0
  911. package/tests/test-model-swap-suggester.sh +368 -0
  912. package/tests/test-model-version-lock.sh +83 -0
  913. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  914. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  915. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  916. package/tests/test-no-force-flag.sh +49 -0
  917. package/tests/test-non-english-quality-warner.sh +229 -0
  918. package/tests/test-oauth-refresh-monitor.sh +311 -0
  919. package/tests/test-opus-degradation-tracker.sh +274 -0
  920. package/tests/test-opus48-routine-task-warning.sh +201 -0
  921. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  922. package/tests/test-output-token-spike-detector.sh +315 -0
  923. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  924. package/tests/test-parallel-cascade-detector.sh +191 -0
  925. package/tests/test-partial-view-claim-arrest.sh +272 -0
  926. package/tests/test-per-prompt-token-cap.sh +136 -0
  927. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  928. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  929. package/tests/test-post-edit-disk-verify.sh +294 -0
  930. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  931. package/tests/test-pre-execution-claim-detector.sh +366 -0
  932. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  933. package/tests/test-proxy-capture-suggester.sh +214 -0
  934. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  935. package/tests/test-quota-anomaly-detector.sh +321 -0
  936. package/tests/test-quota-reset-audit.sh +81 -0
  937. package/tests/test-read-loop-detector.sh +137 -0
  938. package/tests/test-read-once-guard.sh +85 -0
  939. package/tests/test-receipts-aggregate.sh +143 -0
  940. package/tests/test-redirect-fragment-warner.sh +130 -0
  941. package/tests/test-redundant-read-blocker.sh +155 -0
  942. package/tests/test-refusal-arrest-gate.sh +303 -0
  943. package/tests/test-remote-control-billing-classifier.sh +125 -0
  944. package/tests/test-resume-drift-watcher.sh +65 -0
  945. package/tests/test-rg-replace-flag-detector.sh +175 -0
  946. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  947. package/tests/test-rm-safety-net.sh +115 -0
  948. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  949. package/tests/test-runtime-binary-change-detector.sh +196 -0
  950. package/tests/test-same-command-repeat-detector.sh +165 -0
  951. package/tests/test-same-correction-arrest.sh +165 -0
  952. package/tests/test-scope-expansion-receipt.sh +207 -0
  953. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  954. package/tests/test-session-persistence-verifier.sh +128 -0
  955. package/tests/test-session-rate-monitor.sh +284 -0
  956. package/tests/test-session-start-quota-status.sh +210 -0
  957. package/tests/test-session-start-safety-check.sh +138 -0
  958. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  959. package/tests/test-settings-json-health-check.sh +70 -0
  960. package/tests/test-settings-regression-tester.sh +197 -0
  961. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  962. package/tests/test-skill-description-drop-detector.sh +236 -0
  963. package/tests/test-skill-truncation-detector.sh +263 -0
  964. package/tests/test-skills-context-recorder.sh +329 -0
  965. package/tests/test-skills-load-verifier.sh +184 -0
  966. package/tests/test-skills-settings-validator.sh +242 -0
  967. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  968. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  969. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  970. package/tests/test-ssh-key-protect.sh +81 -0
  971. package/tests/test-stale-temp-settings-detector.sh +161 -0
  972. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  973. package/tests/test-starter-hooks-manifest.sh +96 -0
  974. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  975. package/tests/test-strict-allowlist.sh +72 -0
  976. package/tests/test-subagent-boundary-precheck.sh +137 -0
  977. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  978. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  979. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  980. package/tests/test-subagent-identity-reassertion.sh +61 -0
  981. package/tests/test-subagent-inheritance-tester.sh +319 -0
  982. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  983. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  984. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  985. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  986. package/tests/test-subscription-api-billing-warner.sh +138 -0
  987. package/tests/test-subscription-bypass-detector.sh +255 -0
  988. package/tests/test-temporal-suggestion-detector.sh +183 -0
  989. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  990. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  991. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  992. package/tests/test-tool-result-correlation-checker.sh +264 -0
  993. package/tests/test-tool-result-size-guard.sh +121 -0
  994. package/tests/test-transcript-contamination-detector.sh +264 -0
  995. package/tests/test-trigger-header-parsing.sh +151 -0
  996. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  997. package/tests/test-userprompt-submit-receipt.sh +181 -0
  998. package/tests/test-verify-after-publish-reminder.sh +184 -0
  999. package/tests/test-version-bump-detector.sh +212 -0
  1000. package/tests/test-version-regression-warner.sh +165 -0
  1001. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1002. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1003. package/tests/test-wellness-break-reminder.sh +138 -0
  1004. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1005. package/tests/test-windows-python-stub-detector.sh +146 -0
  1006. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1007. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1008. package/tests/test-xml-format-leak-detector.sh +299 -0
  1009. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1010. package/tests/workspace-lease-guard.test.sh +144 -0
  1011. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1012. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1013. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1014. package/tests/write-empty-content-guard.test.sh +39 -0
  1015. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1016. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1017. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,246 @@
1
+ #!/bin/bash
2
+ # Tests for forbidden-response-phrase-detector.sh
3
+ # Run: bash tests/test-forbidden-response-phrase-detector.sh
4
+ set -uo pipefail
5
+
6
+ HOOK="$(dirname "$0")/../examples/forbidden-response-phrase-detector.sh"
7
+ PASS=0 FAIL=0
8
+
9
+ # Helper: build a temp transcript with one assistant response, run the hook with
10
+ # an explicit CLAUDE.md path, assert the exit code.
11
+ run_test() {
12
+ local desc="$1" expected_exit="$2" response="$3" claudemd_content="$4" envvars="${5:-}"
13
+ local tmpdir transcript claudemd actual_exit input
14
+ tmpdir=$(mktemp -d)
15
+ transcript="${tmpdir}/transcript.jsonl"
16
+ claudemd="${tmpdir}/CLAUDE.md"
17
+ printf '%s' "$claudemd_content" > "$claudemd"
18
+
19
+ jq -nc --arg text "$response" '{
20
+ "role": "assistant",
21
+ "message": {"role": "assistant", "content": [{"type": "text", "text": $text}]}
22
+ }' > "$transcript"
23
+
24
+ input=$(jq -nc --arg t "$transcript" '{"transcript_path": $t}')
25
+
26
+ if [ -n "$envvars" ]; then
27
+ actual_exit=$(echo "$input" | env CC_CLAUDEMD_PATH="$claudemd" $envvars bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
28
+ else
29
+ echo "$input" | CC_CLAUDEMD_PATH="$claudemd" bash "$HOOK" >/dev/null 2>/dev/null
30
+ actual_exit=$?
31
+ fi
32
+
33
+ rm -rf "$tmpdir"
34
+
35
+ if [ "$actual_exit" -eq "$expected_exit" ]; then
36
+ echo " PASS: $desc"
37
+ PASS=$((PASS + 1))
38
+ else
39
+ echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
40
+ FAIL=$((FAIL + 1))
41
+ fi
42
+ }
43
+
44
+ expect_stderr_contains() {
45
+ local desc="$1" response="$2" claudemd_content="$3" expect="$4" envvars="${5:-}"
46
+ local tmpdir transcript claudemd stderr_out input
47
+ tmpdir=$(mktemp -d)
48
+ transcript="${tmpdir}/transcript.jsonl"
49
+ claudemd="${tmpdir}/CLAUDE.md"
50
+ printf '%s' "$claudemd_content" > "$claudemd"
51
+
52
+ jq -nc --arg text "$response" '{
53
+ "role": "assistant",
54
+ "message": {"role": "assistant", "content": [{"type": "text", "text": $text}]}
55
+ }' > "$transcript"
56
+
57
+ input=$(jq -nc --arg t "$transcript" '{"transcript_path": $t}')
58
+
59
+ if [ -n "$envvars" ]; then
60
+ stderr_out=$(echo "$input" | env CC_CLAUDEMD_PATH="$claudemd" $envvars bash "$HOOK" 2>&1 >/dev/null)
61
+ else
62
+ stderr_out=$(echo "$input" | CC_CLAUDEMD_PATH="$claudemd" bash "$HOOK" 2>&1 >/dev/null)
63
+ fi
64
+
65
+ rm -rf "$tmpdir"
66
+
67
+ if echo "$stderr_out" | grep -q -- "$expect"; then
68
+ echo " PASS: $desc"
69
+ PASS=$((PASS + 1))
70
+ else
71
+ echo " FAIL: $desc (stderr missing '$expect')"
72
+ echo " got: $stderr_out"
73
+ FAIL=$((FAIL + 1))
74
+ fi
75
+ }
76
+
77
+ echo "Testing forbidden-response-phrase-detector.sh"
78
+ echo "============================================="
79
+
80
+ # --- BASELINE ---
81
+ run_test "no CLAUDE.md → exit 0" 0 "Some response" ""
82
+ run_test "CLAUDE.md without prohibitions → exit 0" 0 "You're right that the issue is..." "# project notes\nuse anything"
83
+
84
+ # --- PROSE PROHIBITIONS ---
85
+ run_test "Do NOT open with You're right blocks" \
86
+ 0 "You're right that the issue is here." \
87
+ "Do NOT open replies with \`You're right\`."
88
+
89
+ run_test "never say I apologize warns" \
90
+ 0 "I apologize for the confusion." \
91
+ "never say \`I apologize\` in responses."
92
+
93
+ run_test "do not use Great point blocks" \
94
+ 0 "Great point about that." \
95
+ "Do not use \`Great point\` as an opener."
96
+
97
+ # --- BLOCK MODE ---
98
+ run_test "BLOCK=1 with violation exits 2" \
99
+ 2 "You're right that..." \
100
+ "Do NOT open with \`You're right\`." \
101
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
102
+
103
+ run_test "BLOCK=1 with clean response exits 0" \
104
+ 0 "Looking at the code, I see the issue is..." \
105
+ "Do NOT open with \`You're right\`." \
106
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
107
+
108
+ # --- DISABLE ---
109
+ run_test "DISABLE=1 short-circuits" \
110
+ 0 "You're right" \
111
+ "Do NOT use \`You're right\`." \
112
+ "CC_FORBIDDEN_PHRASE_DISABLE=1"
113
+
114
+ # --- OPEN_ONLY ---
115
+ # Response is 250+ chars; "Great point" appears at char ~210, JUST past the 200-char window
116
+ LONG_RESPONSE_OPEN_ONLY="Here is a thorough analysis of the existing implementation that covers all the edge cases we have observed in production over the past several weeks of operation since the deployment of the most recent revision. Great point about backwards compatibility."
117
+ run_test "OPEN_ONLY=1 limits scope to first 200 chars (violation outside window)" \
118
+ 0 "$LONG_RESPONSE_OPEN_ONLY" \
119
+ "Do NOT say \`Great point\` in opening." \
120
+ "CC_FORBIDDEN_PHRASE_OPEN_ONLY=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
121
+
122
+ run_test "OPEN_ONLY=1 catches violation in first 200 chars" \
123
+ 2 "Great point about that. Let me look at the code." \
124
+ "Do NOT say \`Great point\` in opening." \
125
+ "CC_FORBIDDEN_PHRASE_OPEN_ONLY=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
126
+
127
+ # --- CASE SENSITIVITY ---
128
+ run_test "case-insensitive (default) matches mixed-case violation" \
129
+ 2 "you're right that we need to fix this." \
130
+ "Do NOT open with \`You're right\`." \
131
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
132
+
133
+ run_test "CASE_SENSITIVE=1 does not match lowercase" \
134
+ 0 "you're right that we need to fix this." \
135
+ "Do NOT open with \`You're right\`." \
136
+ "CC_FORBIDDEN_PHRASE_CASE_SENSITIVE=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
137
+
138
+ run_test "CASE_SENSITIVE=1 matches exact case" \
139
+ 2 "You're right that we need to fix this." \
140
+ "Do NOT open with \`You're right\`." \
141
+ "CC_FORBIDDEN_PHRASE_CASE_SENSITIVE=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
142
+
143
+ # --- HEADER LIST FORMAT ---
144
+ run_test "Forbidden Response Phrases header list blocks violation" \
145
+ 2 "You're right that this needs work." \
146
+ "## Forbidden Response Phrases
147
+
148
+ - \`You're right\`
149
+ - \`Great point\`
150
+ - \`I apologize\`" \
151
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
152
+
153
+ run_test "Filler Phrases header list blocks violation" \
154
+ 2 "Great point — let me investigate." \
155
+ "## Filler Phrases
156
+
157
+ - \`Great point\`
158
+ - \`Exactly\`" \
159
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
160
+
161
+ # --- JAPANESE ---
162
+ run_test "Japanese: 了解しました prohibition blocks" \
163
+ 2 "了解しました。 修正を行います。" \
164
+ "\`了解しました\` を返信の冒頭で使うな。" \
165
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
166
+
167
+ run_test "Japanese: header 禁止する応答 list blocks" \
168
+ 2 "はい、その通りです。" \
169
+ "## 禁止する応答
170
+
171
+ - \`はい、その通りです\`
172
+ - \`了解しました\`" \
173
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
174
+
175
+ # --- NEGATIVE CASES ---
176
+ run_test "Phrase not in response → exit 0" \
177
+ 0 "Let me look at the code and analyse the issue." \
178
+ "Do NOT use \`You're right\`."
179
+
180
+ run_test "Different phrase in prohibition does not match different phrase in response" \
181
+ 0 "Great point about that." \
182
+ "Do NOT use \`You're absolutely correct\`."
183
+
184
+ # --- STDERR ---
185
+ expect_stderr_contains \
186
+ "stderr names the violated phrase" \
187
+ "You're right that..." \
188
+ "Do NOT open with \`You're right\`." \
189
+ "You're right"
190
+
191
+ expect_stderr_contains \
192
+ "stderr cites issue #60339" \
193
+ "You're right" \
194
+ "Do NOT open with \`You're right\`." \
195
+ "#60339"
196
+
197
+ expect_stderr_contains \
198
+ "stderr says detector header" \
199
+ "You're right" \
200
+ "Do NOT open with \`You're right\`." \
201
+ "forbidden-response-phrase-detector"
202
+
203
+ # --- COMBINED FORMATS ---
204
+ run_test "combined prose + header list works" \
205
+ 2 "You're absolutely correct here." \
206
+ "## Forbidden Response Phrases
207
+ - \`I apologize\`
208
+
209
+ Also do NOT say \`You're absolutely correct\`." \
210
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
211
+
212
+ # --- EDGE CASES ---
213
+ run_test "phrase requires backticks; bare mention does not parse" \
214
+ 0 "You're right" \
215
+ "Do NOT say You're right (no backticks here)."
216
+
217
+ run_test "empty response → exit 0" \
218
+ 0 "" \
219
+ "Do NOT use \`You're right\`."
220
+
221
+ run_test "phrase appearing in code block (legitimate code, not natural-language)" \
222
+ 2 "Here is some code: \`You're right\` — but this is just text matching." \
223
+ "Do NOT use \`You're right\`." \
224
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
225
+
226
+ # Note: the hook intentionally does not try to distinguish code blocks from
227
+ # narrative text. The operator's CLAUDE.md should be specific enough that
228
+ # inadvertent matches are rare. If false positives become an issue, the
229
+ # operator can refine the phrase list or use CASE_SENSITIVE mode.
230
+
231
+ # --- #60339 REPRODUCTION ---
232
+ RESPONSE_FROM_60339="You are right that the issue with hook execution is..."
233
+ CLAUDEMD_60339="## Response style rules
234
+
235
+ Do NOT open replies with filler phrases like \`You are right\`, \`Great point\`, or \`I apologize\`."
236
+
237
+ run_test "#60339 reproduction: forbidden opener blocks" \
238
+ 2 "$RESPONSE_FROM_60339" "$CLAUDEMD_60339" \
239
+ "CC_FORBIDDEN_PHRASE_BLOCK=1"
240
+
241
+ run_test "#60339 reproduction with clean response passes" \
242
+ 0 "Looking at the hook configuration, the issue is..." "$CLAUDEMD_60339"
243
+
244
+ echo ""
245
+ echo "Result: $PASS passed, $FAIL failed"
246
+ [ "$FAIL" -eq 0 ]
@@ -59,6 +59,59 @@ test_hook '{"tool_input":{"command":"printf git push"}}' 0 "printf git push not
59
59
  test_hook '{"tool_input":{"command":""}}' 0 "empty command passes"
60
60
  test_hook '{}' 0 "empty input passes"
61
61
 
62
+
63
+ # --- git's own global options between `git` and the verb (#1117) ---
64
+ # git -C <dir> push does exactly what git push does. Matching the two as
65
+ # adjacent words missed every shape below; all of them ran a real push.
66
+ test_hook '{"tool_input":{"command":"git -C /tmp/repo push --force origin main"}}' 2 "git -C <dir> push blocked"
67
+ test_hook '{"tool_input":{"command":"git --git-dir=/tmp/r/repo.d push origin main"}}' 2 "git --git-dir=<path> push blocked"
68
+ test_hook '{"tool_input":{"command":"git --git-dir /tmp/r/repo.d push origin main"}}' 2 "git --git-dir <path> (separate value) push blocked"
69
+ test_hook '{"tool_input":{"command":"git --work-tree=/tmp/w --git-dir=/tmp/r/repo.d push origin main"}}' 2 "two global options before push blocked"
70
+ test_hook '{"tool_input":{"command":"git -c user.name=x commit -m x"}}' 2 "git -c <k=v> commit blocked"
71
+ test_hook '{"tool_input":{"command":"git -C /tmp/r checkout -b feature"}}' 2 "git -C <dir> checkout -b blocked"
72
+ test_hook '{"tool_input":{"command":"git -C /tmp/r switch -c feature"}}' 2 "git -C <dir> switch -c blocked"
73
+ test_hook '{"tool_input":{"command":"git -C /tmp/r branch feature"}}' 2 "git -C <dir> branch <name> blocked"
74
+ test_hook '{"tool_input":{"command":"git -C /tmp/r branch -a"}}' 0 "git -C <dir> branch -a still a listing"
75
+ test_hook '{"tool_input":{"command":"git --no-pager push origin main"}}' 2 "git --no-pager push blocked"
76
+ test_hook '{"tool_input":{"command":"/usr/bin/git push origin main"}}' 2 "git invoked by absolute path blocked"
77
+
78
+ # --- the plumbing form of push ---
79
+ test_hook '{"tool_input":{"command":"git send-pack origin main"}}' 2 "git send-pack blocked"
80
+ test_hook '{"tool_input":{"command":"git -C /tmp/r send-pack origin main"}}' 2 "git -C <dir> send-pack blocked"
81
+
82
+ # --- the read-only exemption must cover its own segment only ---
83
+ # `^\s*(echo|printf)\s` used to exempt the WHOLE command, so everything after
84
+ # a harmless first segment ran unguarded.
85
+ test_hook '{"tool_input":{"command":"echo hi && git push origin main"}}' 2 "echo first segment does not exempt a later push"
86
+ test_hook '{"tool_input":{"command":"echo start; git push origin main"}}' 2 "echo before ; does not exempt a later push"
87
+ test_hook '{"tool_input":{"command":"printf x && git commit -m x"}}' 2 "printf first segment does not exempt a later commit"
88
+ test_hook '{"tool_input":{"command":"grep -r \"git push\" ./docs"}}' 0 "grep for the words is not an invocation"
89
+
90
+ # --- a single pipe is a separator too (2026-09-15) ---
91
+ # The splitter knew && ; and || but not `|`, so a read-only command piped into
92
+ # a git write arrived as ONE segment whose first word was the reader.
93
+ # READ_ONLY_RE exempted the whole segment and the write on the right of the
94
+ # pipe was never examined. Measured on the published file: these four exited 0.
95
+ test_hook '{"tool_input":{"command":"echo x | git push origin main"}}' 2 "echo piped into push blocked"
96
+ test_hook '{"tool_input":{"command":"cat f | git commit -m x"}}' 2 "cat piped into commit blocked"
97
+ test_hook '{"tool_input":{"command":"grep q f | git push origin main"}}' 2 "grep piped into push blocked"
98
+ test_hook '{"tool_input":{"command":"head -1 f | git checkout -b feature"}}' 2 "head piped into checkout -b blocked"
99
+
100
+ # The same change must not start blocking ordinary pipes. A tightening fix
101
+ # looks green on the blocking table while quietly breaking normal work, so the
102
+ # passing side is listed here on purpose. `git branch | grep main` is here
103
+ # because the pre-fix file refused it: unsplit, it read as `git branch <name>`.
104
+ test_hook '{"tool_input":{"command":"git log | head -20"}}' 0 "git log piped to head still passes"
105
+ test_hook '{"tool_input":{"command":"git diff | grep push"}}' 0 "git diff piped to grep still passes"
106
+ test_hook '{"tool_input":{"command":"git branch | grep main"}}' 0 "git branch listing piped still passes"
107
+ test_hook '{"tool_input":{"command":"echo \"a|b\""}}' 0 "a pipe inside quotes is not a separator"
108
+
109
+ # --- the .git path coincidence ---
110
+ # `git --git-dir=/tmp/r/.git push` used to match only because the PATH ended in
111
+ # `.git`; the same command with any other git-dir name went through.
112
+ test_hook '{"tool_input":{"command":"git --git-dir=/tmp/r/.git push origin main"}}' 2 "git-dir named .git blocked"
113
+ test_hook '{"tool_input":{"command":"ls /tmp/r/.git"}}' 0 "a path containing .git is not a push"
114
+
62
115
  echo ""
63
116
  echo "Results: $PASS passed, $FAIL failed"
64
117
  [ "$FAIL" -gt 0 ] && exit 1
@@ -0,0 +1,115 @@
1
+ #!/bin/bash
2
+ # Tests for git-push-blast-radius-guard.sh
3
+ HOOK="examples/git-push-blast-radius-guard.sh"
4
+ # Allow running from /tmp during development: fall back to an absolute path.
5
+ [ -f "$HOOK" ] || HOOK="/tmp/ccps/git-push-blast-radius-guard.sh"
6
+ PASS=0 FAIL=0
7
+
8
+ assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3' in output)"; fi; }
9
+ assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
10
+
11
+ DIR="/tmp/cc-push-blast-test-$$"
12
+ export CC_PUSH_BLAST_DIR="$DIR"
13
+ export CC_PUSH_BLAST_WARN=3
14
+ export CC_PUSH_BLAST_BLOCK=6
15
+ export CC_PUSH_BLAST_WINDOW=3600
16
+
17
+ fresh() { rm -rf "$DIR"; }
18
+ # Build a Bash PreToolUse payload pushing to a named branch.
19
+ push() { printf '{"tool_name":"Bash","session_id":"%s","tool_input":{"command":"git push origin %s"}}' "$1" "$2"; }
20
+ # Record a push by actually running it through the hook (output discarded).
21
+ rec() { push "$1" "$2" | bash "$HOOK" >/dev/null 2>&1; }
22
+
23
+ # Test 1: non-Bash tool passes through silently
24
+ fresh
25
+ OUT=$(echo '{"tool_name":"WebFetch","tool_input":{"url":"https://x"}}' | bash "$HOOK" 2>&1)
26
+ assert_not_contains "non-Bash passthrough" "$OUT" "git-push-blast-radius-guard"
27
+ assert_not_contains "non-Bash no block" "$OUT" "decision"
28
+
29
+ # Test 2: a Bash command that is not a push passes through
30
+ fresh
31
+ OUT=$(echo '{"tool_name":"Bash","session_id":"s1","tool_input":{"command":"git status"}}' | bash "$HOOK" 2>&1)
32
+ assert_not_contains "non-push passthrough" "$OUT" "git-push-blast-radius-guard"
33
+
34
+ # Test 3: first two distinct branches are silent (below WARN)
35
+ fresh
36
+ for b in b1 b2; do
37
+ OUT=$(push s1 "$b" | bash "$HOOK" 2>&1)
38
+ assert_not_contains "push $b silent" "$OUT" "git-push-blast-radius-guard"
39
+ done
40
+
41
+ # Test 4: at WARN (3rd distinct branch) -> stderr warning, no block
42
+ OUT=$(push s1 b3 | bash "$HOOK" 2>&1)
43
+ assert_contains "3rd distinct warns" "$OUT" "git-push-blast-radius-guard"
44
+ STDOUT=$(push s1 b4 | bash "$HOOK" 2>/dev/null)
45
+ assert_not_contains "4th no block on stdout" "$STDOUT" "decision"
46
+
47
+ # Test 5: at BLOCK (6th distinct) -> block decision JSON on stdout, exit 0
48
+ rec s1 b5
49
+ STDOUT=$(push s1 b6 | bash "$HOOK" 2>/dev/null)
50
+ RC=$?
51
+ assert_contains "6th distinct blocks" "$STDOUT" '"decision": "block"'
52
+ assert_contains "block reason references issue" "$STDOUT" "65944"
53
+ [ "$RC" -eq 0 ] && PASS=$((PASS+1)) || { FAIL=$((FAIL+1)); echo "FAIL: block exits 0 (got $RC)"; }
54
+
55
+ # Test 6: re-pushing the SAME branch many times never trips (distinct stays 1)
56
+ fresh
57
+ for i in 1 2 3 4 5 6 7 8 9 10; do
58
+ STDOUT=$(push s2 feature | bash "$HOOK" 2>/dev/null)
59
+ assert_not_contains "re-push same branch #$i no block" "$STDOUT" "decision"
60
+ done
61
+
62
+ # Test 7: git push --all is an immediate trip (whole-repo fan-out)
63
+ fresh
64
+ STDOUT=$(echo '{"tool_name":"Bash","session_id":"s3","tool_input":{"command":"git push --all origin"}}' | bash "$HOOK" 2>/dev/null)
65
+ assert_contains "--all blocks immediately" "$STDOUT" '"decision": "block"'
66
+
67
+ # Test 8: off mode passes through even over the limit
68
+ fresh
69
+ for b in c1 c2 c3 c4 c5 c6; do rec s4 "$b"; done
70
+ OUT=$(push s4 c7 | CC_PUSH_BLAST_GUARD=off bash "$HOOK" 2>&1)
71
+ assert_not_contains "off mode no block" "$OUT" "decision"
72
+
73
+ # Test 9: warn mode never emits a block decision, only stderr
74
+ fresh
75
+ for b in d1 d2 d3 d4 d5; do rec s5 "$b"; done
76
+ OUT=$(push s5 d6 | CC_PUSH_BLAST_GUARD=warn bash "$HOOK" 2>&1)
77
+ assert_not_contains "warn mode no block decision" "$OUT" '"decision"'
78
+ assert_contains "warn mode warns" "$OUT" "git-push-blast-radius-guard"
79
+
80
+ # Test 10: window expiry prunes old branches -> count resets below warn
81
+ fresh
82
+ mkdir -p "$DIR"
83
+ OLD=$(( $(date +%s) - 7200 ))
84
+ for i in 1 2 3 4 5; do printf '%s\told%s\n' "$OLD" "$i" >> "$DIR/s6"; done
85
+ OUT=$(push s6 newbranch | bash "$HOOK" 2>&1)
86
+ assert_not_contains "expired window resets, no warn" "$OUT" "git-push-blast-radius-guard"
87
+
88
+ # Test 11: per-session isolation -- another session has its own counter
89
+ fresh
90
+ for b in e1 e2 e3 e4 e5 e6; do rec s7 "$b"; done # s7 now blocking
91
+ STDOUT=$(push s8 e1 | bash "$HOOK" 2>/dev/null)
92
+ assert_not_contains "separate session not blocked" "$STDOUT" "decision"
93
+
94
+ # Test 12: malformed input fails open (no crash, no block)
95
+ fresh
96
+ OUT=$(echo 'not json' | bash "$HOOK" 2>&1)
97
+ assert_not_contains "malformed input fails open" "$OUT" "decision"
98
+
99
+ # Test 13: HEAD:branch refspec counts the destination branch
100
+ fresh
101
+ for i in 1 2 3 4 5; do rec s9 "f$i"; done
102
+ STDOUT=$(echo '{"tool_name":"Bash","session_id":"s9","tool_input":{"command":"git push origin HEAD:f6"}}' | bash "$HOOK" 2>/dev/null)
103
+ assert_contains "HEAD:dst counts destination -> blocks at 6th" "$STDOUT" '"decision": "block"'
104
+
105
+ # Test 14: pushing two branches in one command counts both
106
+ fresh
107
+ rec s10 g1
108
+ rec s10 g2
109
+ rec s10 g3
110
+ STDOUT=$(echo '{"tool_name":"Bash","session_id":"s10","tool_input":{"command":"git push origin g4 g5 g6"}}' | bash "$HOOK" 2>/dev/null)
111
+ assert_contains "multi-branch single push counts all -> blocks" "$STDOUT" '"decision": "block"'
112
+
113
+ rm -rf "$DIR"
114
+ echo "Results: $PASS passed, $FAIL failed"
115
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,128 @@
1
+ #!/bin/bash
2
+ # Tests for goal-iteration-limit-warner.sh
3
+
4
+ HOOK="$(dirname "$0")/../examples/goal-iteration-limit-warner.sh"
5
+ PASS=0 FAIL=0
6
+
7
+ TMPROOT="$(mktemp -d -t cc-goal-warn-test.XXXXXX)"
8
+ trap 'rm -rf "$TMPROOT"' EXIT
9
+
10
+ run_test() {
11
+ local desc="$1" expected_exit="$2" prompt="$3" extra_env="$4"
12
+ local logfile="$TMPROOT/log-$RANDOM"
13
+ local actual_exit
14
+ local payload
15
+ payload=$(jq -nc --arg p "$prompt" '{prompt:$p}')
16
+ if [ -n "$extra_env" ]; then
17
+ actual_exit=$(printf '%s' "$payload" | env CC_GOAL_WARN_LOG="$logfile" $extra_env bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
18
+ else
19
+ actual_exit=$(printf '%s' "$payload" | env CC_GOAL_WARN_LOG="$logfile" bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
20
+ fi
21
+ if [ "$actual_exit" -eq "$expected_exit" ]; then
22
+ echo " PASS: $desc"
23
+ PASS=$((PASS+1))
24
+ else
25
+ echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
26
+ FAIL=$((FAIL+1))
27
+ fi
28
+ }
29
+
30
+ echo "Testing goal-iteration-limit-warner.sh"
31
+ echo "======================================"
32
+
33
+ # 1. Empty prompt → pass
34
+ PAYLOAD='{"prompt":""}'
35
+ EXIT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
36
+ [ "$EXIT" -eq 0 ] && { echo " PASS: empty prompt passes"; PASS=$((PASS+1)); } || { echo " FAIL: empty prompt"; FAIL=$((FAIL+1)); }
37
+
38
+ # 2. Non-/goal prompt → pass
39
+ run_test "regular prompt passes" 0 "please write a poem about cats"
40
+
41
+ # 3. /goal with no termination clause → warn (exit 0)
42
+ run_test "/goal without limit warns (default)" 0 "/goal find the death certificate for John Smith"
43
+
44
+ # 4. /goal with no termination clause in block mode → exit 2
45
+ run_test "/goal without limit blocks when action=block" 2 "/goal find the death certificate for John Smith" "CC_GOAL_WARN_ACTION=block"
46
+
47
+ # 5. /goal clear → pass silently
48
+ run_test "/goal clear passes silently" 0 "/goal clear"
49
+
50
+ # 6. /goal status → pass silently
51
+ run_test "/goal status passes silently" 0 "/goal status"
52
+
53
+ # 7. /goal evaluate-once → pass silently
54
+ run_test "/goal evaluate-once passes silently" 0 "/goal evaluate-once"
55
+
56
+ # 8. /goal with 'or stop after 20 turns' → pass
57
+ run_test "/goal with 'or stop after N turns' passes" 0 "/goal find the death certificate or stop after 20 turns"
58
+
59
+ # 9. /goal with 'max 15 iterations' → pass
60
+ run_test "/goal with 'max N iterations' passes" 0 "/goal find the source, max 15 iterations"
61
+
62
+ # 10. /goal with 'within 10 turns' → pass
63
+ run_test "/goal with 'within N turns' passes" 0 "/goal find it within 10 turns"
64
+
65
+ # 11. /goal with 'after 5 attempts' → pass
66
+ run_test "/goal with 'after N attempts' passes" 0 "/goal find it, give up after 5 attempts"
67
+
68
+ # 12. Bare /goal (just the command) → pass (informational)
69
+ run_test "/goal alone passes (informational)" 0 "/goal"
70
+
71
+ # 13. /goal help → pass
72
+ run_test "/goal help passes silently" 0 "/goal help"
73
+
74
+ # 14. /goal with embedded newlines → still detected
75
+ PAYLOAD=$(jq -nc '{prompt:"some context\n/goal find rare manuscript\nmore context"}')
76
+ EXIT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
77
+ [ "$EXIT" -eq 0 ] && { echo " PASS: /goal on a line within multi-line prompt detected"; PASS=$((PASS+1)); } || { echo " FAIL: multi-line /goal"; FAIL=$((FAIL+1)); }
78
+
79
+ # 15. Disabled via env var → pass silently
80
+ run_test "CC_GOAL_WARN_DISABLE=1 disables hook" 0 "/goal find anything" "CC_GOAL_WARN_DISABLE=1"
81
+
82
+ # 16. Warning to stderr, stdout empty
83
+ PAYLOAD=$(jq -nc '{prompt:"/goal find a rare book"}')
84
+ STDOUT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" 2>/dev/null)
85
+ STDERR=$(printf '%s' "$PAYLOAD" | bash "$HOOK" 2>&1 >/dev/null)
86
+ if [ -z "$STDOUT" ] && echo "$STDERR" | grep -q "without a termination clause"; then
87
+ echo " PASS: stdout empty, stderr has warning"
88
+ PASS=$((PASS+1))
89
+ else
90
+ echo " FAIL: stdout/stderr separation"
91
+ FAIL=$((FAIL+1))
92
+ fi
93
+
94
+ # 17. Log file is created
95
+ LOG="$TMPROOT/goal.log"
96
+ PAYLOAD=$(jq -nc '{prompt:"/goal find something obscure"}')
97
+ printf '%s' "$PAYLOAD" | env CC_GOAL_WARN_LOG="$LOG" bash "$HOOK" >/dev/null 2>/dev/null
98
+ if [ -f "$LOG" ] && grep -q "goal_without_limit" "$LOG"; then
99
+ echo " PASS: log file written"
100
+ PASS=$((PASS+1))
101
+ else
102
+ echo " FAIL: log file missing"
103
+ FAIL=$((FAIL+1))
104
+ fi
105
+
106
+ # 18. CC_GOAL_WARN_MAX_TURNS reflected in message
107
+ PAYLOAD=$(jq -nc '{prompt:"/goal find something"}')
108
+ STDERR=$(printf '%s' "$PAYLOAD" | env CC_GOAL_WARN_MAX_TURNS=42 bash "$HOOK" 2>&1 >/dev/null)
109
+ if echo "$STDERR" | grep -q "stop after 42 turns"; then
110
+ echo " PASS: custom max turns reflected in suggestion"
111
+ PASS=$((PASS+1))
112
+ else
113
+ echo " FAIL: max turns env not reflected"
114
+ FAIL=$((FAIL+1))
115
+ fi
116
+
117
+ # 19. /goal with uppercase 'STOP AFTER' → still recognized (case-insensitive)
118
+ run_test "/goal with 'STOP AFTER' (uppercase) passes" 0 "/goal find it OR STOP AFTER 10 TURNS"
119
+
120
+ # 20. /goal with extra spacing → still detected
121
+ run_test "/goal with multiple spaces detected" 0 "/goal find rare information"
122
+
123
+ # 21. Prompt without /goal anywhere → pass
124
+ run_test "prompt containing 'goal' as a word passes" 0 "my goal here is to write good code"
125
+
126
+ echo "======================================"
127
+ echo "Result: PASS=$PASS FAIL=$FAIL"
128
+ [ "$FAIL" -eq 0 ]