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,134 @@
1
+ #!/bin/bash
2
+ # Tests for claim-vs-caveat-checker.sh — verifies that confident
3
+ # claims overlapping with earlier caveats in the same transcript
4
+ # emit a non-blocking note (or block when CLAIM_CAVEAT_BLOCK=1).
5
+ HOOK="examples/claim-vs-caveat-checker.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: $2)"; fi; }
9
+ assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3' in: $2)"; fi; }
10
+ assert_exit() { if [ "$2" -eq "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (exit $2, expected $3)"; fi; }
11
+
12
+ # Setup temp transcript
13
+ TMPDIR=$(mktemp -d)
14
+ TRAP_FILE="$TMPDIR/transcript.jsonl"
15
+
16
+ make_input() {
17
+ jq -n --arg t "$1" '{transcript_path: $t}'
18
+ }
19
+
20
+ write_transcript() {
21
+ : > "$TRAP_FILE"
22
+ for line in "$@"; do
23
+ echo "$line" >> "$TRAP_FILE"
24
+ done
25
+ }
26
+
27
+ # Test 1: empty transcript_path → exit 0 silently
28
+ INPUT=$(jq -n '{}')
29
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
30
+ RC=$?
31
+ assert_exit "empty transcript_path exits 0" "$RC" 0
32
+ assert_not_contains "empty transcript no output" "$OUT" "claim-vs-caveat"
33
+
34
+ # Test 2: missing transcript file → exit 0 silently
35
+ INPUT=$(make_input "/nonexistent/path.jsonl")
36
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
37
+ RC=$?
38
+ assert_exit "missing transcript exits 0" "$RC" 0
39
+
40
+ # Test 3: transcript with only confident claim, no caveat → no warning
41
+ write_transcript \
42
+ '{"role":"user","content":"check the trade"}' \
43
+ '{"role":"assistant","content":"The trade is guaranteed to succeed."}'
44
+ INPUT=$(make_input "$TRAP_FILE")
45
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
46
+ RC=$?
47
+ assert_exit "claim-only exits 0" "$RC" 0
48
+ assert_not_contains "claim-only no warning" "$OUT" "claim-vs-caveat"
49
+
50
+ # Test 4: transcript with only caveat, no claim → no warning
51
+ write_transcript \
52
+ '{"role":"user","content":"check the trade"}' \
53
+ '{"role":"assistant","content":"There is a slippage risk."}'
54
+ INPUT=$(make_input "$TRAP_FILE")
55
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
56
+ RC=$?
57
+ assert_exit "caveat-only exits 0" "$RC" 0
58
+ assert_not_contains "caveat-only no warning" "$OUT" "claim-vs-caveat"
59
+
60
+ # Test 5: caveat earlier + confident claim later → warning emitted
61
+ write_transcript \
62
+ '{"role":"user","content":"check the trade"}' \
63
+ '{"role":"assistant","content":"There is a slippage risk on this position."}' \
64
+ '{"role":"user","content":"deploy the fix"}' \
65
+ '{"role":"assistant","content":"The fix is guaranteed to handle the slippage."}'
66
+ INPUT=$(make_input "$TRAP_FILE")
67
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
68
+ RC=$?
69
+ assert_exit "claim+caveat exits 0 in warn-only" "$RC" 0
70
+ assert_contains "claim+caveat warns" "$OUT" "claim-vs-caveat"
71
+ assert_contains "warning includes claim term" "$OUT" "guaranteed"
72
+
73
+ # Test 6: same setup with CLAIM_CAVEAT_BLOCK=1 → block JSON
74
+ INPUT=$(make_input "$TRAP_FILE")
75
+ OUT=$(printf '%s' "$INPUT" | CLAIM_CAVEAT_BLOCK=1 bash "$HOOK" 2>&1)
76
+ RC=$?
77
+ assert_exit "block mode exits 0 (decision-block)" "$RC" 0
78
+ assert_contains "block mode emits decision-block" "$OUT" '"decision":"block"'
79
+ assert_contains "block JSON has reason" "$OUT" '"reason"'
80
+
81
+ # Test 7: Japanese claim + caveat
82
+ write_transcript \
83
+ '{"role":"user","content":"取引の点検"}' \
84
+ '{"role":"assistant","content":"この銘柄には滑りの危険があります。"}' \
85
+ '{"role":"user","content":"修正を出荷"}' \
86
+ '{"role":"assistant","content":"修正で完璧に直った状態です。"}'
87
+ INPUT=$(make_input "$TRAP_FILE")
88
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
89
+ RC=$?
90
+ assert_exit "JP claim+caveat exits 0" "$RC" 0
91
+ assert_contains "JP claim+caveat warns" "$OUT" "claim-vs-caveat"
92
+
93
+ # Test 8: window respects CLAIM_CAVEAT_WINDOW (caveat outside window → no warn)
94
+ > "$TRAP_FILE"
95
+ for i in $(seq 1 60); do
96
+ echo '{"role":"user","content":"filler"}' >> "$TRAP_FILE"
97
+ echo '{"role":"assistant","content":"filler reply"}' >> "$TRAP_FILE"
98
+ done
99
+ echo '{"role":"assistant","content":"There is a slippage risk."}' >> "$TRAP_FILE"
100
+ echo '{"role":"user","content":"deploy"}' >> "$TRAP_FILE"
101
+ echo '{"role":"assistant","content":"The fix is guaranteed."}' >> "$TRAP_FILE"
102
+ INPUT=$(make_input "$TRAP_FILE")
103
+ OUT=$(printf '%s' "$INPUT" | CLAIM_CAVEAT_WINDOW=2 bash "$HOOK" 2>&1)
104
+ RC=$?
105
+ assert_exit "narrow window exits 0" "$RC" 0
106
+ assert_not_contains "narrow window suppresses old caveat" "$OUT" "claim-vs-caveat"
107
+
108
+ # Test 9: wide window picks up the caveat
109
+ INPUT=$(make_input "$TRAP_FILE")
110
+ OUT=$(printf '%s' "$INPUT" | CLAIM_CAVEAT_WINDOW=10 bash "$HOOK" 2>&1)
111
+ RC=$?
112
+ assert_exit "wide window exits 0" "$RC" 0
113
+ assert_contains "wide window detects" "$OUT" "claim-vs-caveat"
114
+
115
+ # Test 10: real-world #57288 reproduction — agent's words from the trade case
116
+ write_transcript \
117
+ '{"role":"user","content":"check the position"}' \
118
+ '{"role":"assistant","content":"After the modification, the SL is close to the entry price (+0.11%). On a fast move, slippage on the small protective margin may be noticeable."}' \
119
+ '{"role":"user","content":"deploy"}' \
120
+ '{"role":"assistant","content":"1INCHUSDT cannot close at a loss now."}'
121
+ INPUT=$(make_input "$TRAP_FILE")
122
+ OUT=$(printf '%s' "$INPUT" | bash "$HOOK" 2>&1)
123
+ RC=$?
124
+ assert_exit "57288 repro exits 0" "$RC" 0
125
+ assert_contains "57288 repro warns" "$OUT" "claim-vs-caveat"
126
+ assert_contains "57288 mentions slippage" "$OUT" "slippage"
127
+
128
+ # Cleanup
129
+ rm -rf "$TMPDIR"
130
+
131
+ echo ""
132
+ echo "PASS: $PASS"
133
+ echo "FAIL: $FAIL"
134
+ [ "$FAIL" -eq 0 ] && echo "OK" || exit 1
@@ -0,0 +1,353 @@
1
+ #!/bin/bash
2
+ # Tests for claude-code-version-pin-advisor.sh
3
+ HOOK="$(dirname "$0")/../examples/claude-code-version-pin-advisor.sh"
4
+ PASS=0
5
+ FAIL=0
6
+
7
+ run_test() {
8
+ local desc="$1"
9
+ local result="$2"
10
+ if [ "$result" = "pass" ]; then
11
+ echo " PASS: $desc"
12
+ PASS=$((PASS + 1))
13
+ else
14
+ echo " FAIL: $desc"
15
+ FAIL=$((FAIL + 1))
16
+ fi
17
+ }
18
+
19
+ # Provide a fake claude binary via CC_VERSION_PIN_ADVISOR_CLAUDE_BIN for tests
20
+ # that exercise the binary-detection path. Most tests use CLAUDE_CODE_VERSION
21
+ # directly which is faster and deterministic.
22
+
23
+ TMPDIR_RUN="$(mktemp -d)"
24
+ trap 'rm -rf "$TMPDIR_RUN"' EXIT
25
+
26
+ # Fake claude binary that prints a fixed version
27
+ FAKE_CLAUDE="$TMPDIR_RUN/fake-claude"
28
+ cat > "$FAKE_CLAUDE" <<'EOF'
29
+ #!/bin/bash
30
+ if [ "$1" = "--version" ]; then
31
+ echo "2.1.156 (Claude Code)"
32
+ fi
33
+ EOF
34
+ chmod +x "$FAKE_CLAUDE"
35
+
36
+ # Fake claude binary that returns malformed output
37
+ MALFORMED_CLAUDE="$TMPDIR_RUN/malformed-claude"
38
+ cat > "$MALFORMED_CLAUDE" <<'EOF'
39
+ #!/bin/bash
40
+ echo "Claude Code - latest"
41
+ EOF
42
+ chmod +x "$MALFORMED_CLAUDE"
43
+
44
+ # Fake claude binary that returns nothing
45
+ SILENT_CLAUDE="$TMPDIR_RUN/silent-claude"
46
+ cat > "$SILENT_CLAUDE" <<'EOF'
47
+ #!/bin/bash
48
+ exit 0
49
+ EOF
50
+ chmod +x "$SILENT_CLAUDE"
51
+
52
+ echo "Testing claude-code-version-pin-advisor.sh"
53
+ echo "==========================================="
54
+
55
+ # Test 1: version below threshold (2.1.153) → silent exit 0
56
+ OUT=$(CLAUDE_CODE_VERSION=2.1.153 bash "$HOOK" 2>&1)
57
+ EXIT=$?
58
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
59
+ run_test "version 2.1.153 (below threshold) → silent exit 0" pass
60
+ else
61
+ run_test "version 2.1.153 → silent (exit=$EXIT, out=$OUT)" fail
62
+ fi
63
+
64
+ # Test 2: version at threshold (2.1.154) → advisory printed
65
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
66
+ EXIT=$?
67
+ if [ "$EXIT" = "0" ] && echo "$OUT" | grep -q "ADVISORY"; then
68
+ run_test "version 2.1.154 (at threshold) → advisory printed" pass
69
+ else
70
+ run_test "version 2.1.154 → advisory (exit=$EXIT, out=$OUT)" fail
71
+ fi
72
+
73
+ # Test 3: version above threshold (2.1.156) → advisory printed
74
+ OUT=$(CLAUDE_CODE_VERSION=2.1.156 bash "$HOOK" 2>&1)
75
+ EXIT=$?
76
+ if [ "$EXIT" = "0" ] && echo "$OUT" | grep -q "ADVISORY" && echo "$OUT" | grep -q "2.1.156"; then
77
+ run_test "version 2.1.156 (above threshold) → advisory mentions actual version" pass
78
+ else
79
+ run_test "version 2.1.156 → advisory (exit=$EXIT, out=$OUT)" fail
80
+ fi
81
+
82
+ # Test 4: version far above threshold (2.2.0) → advisory printed
83
+ OUT=$(CLAUDE_CODE_VERSION=2.2.0 bash "$HOOK" 2>&1)
84
+ if [ -n "$(echo "$OUT" | grep ADVISORY)" ]; then
85
+ run_test "version 2.2.0 (major.minor jump) → advisory" pass
86
+ else
87
+ run_test "version 2.2.0 → advisory (got: $OUT)" fail
88
+ fi
89
+
90
+ # Test 5: version 2.1.100 (well below) → silent
91
+ OUT=$(CLAUDE_CODE_VERSION=2.1.100 bash "$HOOK" 2>&1)
92
+ EXIT=$?
93
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
94
+ run_test "version 2.1.100 (well below threshold) → silent" pass
95
+ else
96
+ run_test "version 2.1.100 → silent (exit=$EXIT, out=$OUT)" fail
97
+ fi
98
+
99
+ # Test 6: DISABLE=1 silences regardless of version
100
+ OUT=$(CLAUDE_CODE_VERSION=2.1.156 CC_VERSION_PIN_ADVISOR_DISABLE=1 bash "$HOOK" 2>&1)
101
+ EXIT=$?
102
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
103
+ run_test "DISABLE=1 silences even when version triggers advisory" pass
104
+ else
105
+ run_test "DISABLE=1 silences (exit=$EXIT, out=$OUT)" fail
106
+ fi
107
+
108
+ # Test 7: QUIET=1 silences regardless of version
109
+ OUT=$(CLAUDE_CODE_VERSION=2.1.156 CC_VERSION_PIN_ADVISOR_QUIET=1 bash "$HOOK" 2>&1)
110
+ EXIT=$?
111
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
112
+ run_test "QUIET=1 silences even when version triggers advisory" pass
113
+ else
114
+ run_test "QUIET=1 silences (exit=$EXIT, out=$OUT)" fail
115
+ fi
116
+
117
+ # Test 8: custom THRESHOLD override (2.1.150 lower threshold)
118
+ OUT=$(CLAUDE_CODE_VERSION=2.1.151 CC_VERSION_PIN_ADVISOR_THRESHOLD=2.1.150 bash "$HOOK" 2>&1)
119
+ if echo "$OUT" | grep -q "ADVISORY"; then
120
+ run_test "custom THRESHOLD=2.1.150 triggers for 2.1.151" pass
121
+ else
122
+ run_test "custom THRESHOLD=2.1.150 for 2.1.151 (got: $OUT)" fail
123
+ fi
124
+
125
+ # Test 9: custom THRESHOLD override (2.1.200 higher threshold)
126
+ OUT=$(CLAUDE_CODE_VERSION=2.1.156 CC_VERSION_PIN_ADVISOR_THRESHOLD=2.1.200 bash "$HOOK" 2>&1)
127
+ EXIT=$?
128
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
129
+ run_test "custom THRESHOLD=2.1.200 silences for 2.1.156" pass
130
+ else
131
+ run_test "custom THRESHOLD=2.1.200 silences (exit=$EXIT, out=$OUT)" fail
132
+ fi
133
+
134
+ # Test 10: claude binary not found → fail-open silent
135
+ # PATH with only /bin and /usr/bin (no claude installed there) means
136
+ # command -v claude returns nothing. We need /bin and /usr/bin so that
137
+ # env -i can find bash itself.
138
+ OUT=$(env -i HOME="$HOME" PATH="$TMPDIR_RUN/empty-bin:/bin:/usr/bin" bash "$HOOK" 2>&1)
139
+ EXIT=$?
140
+ # In test environments where claude IS in /usr/bin or /bin, this test may
141
+ # not be deterministic. Use CC_VERSION_PIN_ADVISOR_CLAUDE_BIN pointing at
142
+ # a nonexistent file as the deterministic path.
143
+ OUT=$(env -i HOME="$HOME" PATH="/bin:/usr/bin" \
144
+ CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$TMPDIR_RUN/does-not-exist" \
145
+ bash "$HOOK" 2>&1)
146
+ EXIT=$?
147
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
148
+ run_test "claude binary not found → fail-open silent" pass
149
+ else
150
+ run_test "claude binary not found (exit=$EXIT, out=$OUT)" fail
151
+ fi
152
+
153
+ # Test 11: malformed version output → fail-open silent
154
+ OUT=$(CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$MALFORMED_CLAUDE" \
155
+ env -i HOME="$HOME" PATH="/usr/bin:/bin" \
156
+ CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$MALFORMED_CLAUDE" \
157
+ bash "$HOOK" 2>&1)
158
+ EXIT=$?
159
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
160
+ run_test "malformed version output → fail-open silent" pass
161
+ else
162
+ run_test "malformed version output → fail-open (exit=$EXIT, out=$OUT)" fail
163
+ fi
164
+
165
+ # Test 12: silent claude binary (no version) → fail-open silent
166
+ OUT=$(env -i HOME="$HOME" PATH="/usr/bin:/bin" \
167
+ CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$SILENT_CLAUDE" \
168
+ bash "$HOOK" 2>&1)
169
+ EXIT=$?
170
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
171
+ run_test "silent claude binary → fail-open silent" pass
172
+ else
173
+ run_test "silent claude binary → fail-open (exit=$EXIT, out=$OUT)" fail
174
+ fi
175
+
176
+ # Test 13: detection via CC_VERSION_PIN_ADVISOR_CLAUDE_BIN (fake binary at 2.1.156)
177
+ OUT=$(env -i HOME="$HOME" PATH="/usr/bin:/bin" \
178
+ CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$FAKE_CLAUDE" \
179
+ bash "$HOOK" 2>&1)
180
+ if echo "$OUT" | grep -q "2.1.156" && echo "$OUT" | grep -q "ADVISORY"; then
181
+ run_test "fake claude binary at 2.1.156 → advisory mentions version" pass
182
+ else
183
+ run_test "fake claude binary detection (got: $OUT)" fail
184
+ fi
185
+
186
+ # Test 14: CLAUDE_CODE_VERSION env var preferred over claude --version
187
+ # Even with binary at 2.1.156, env var at 2.1.153 should silence
188
+ OUT=$(env -i HOME="$HOME" PATH="/usr/bin:/bin" \
189
+ CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$FAKE_CLAUDE" \
190
+ CLAUDE_CODE_VERSION=2.1.153 \
191
+ bash "$HOOK" 2>&1)
192
+ EXIT=$?
193
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
194
+ run_test "CLAUDE_CODE_VERSION env var preferred over binary detection" pass
195
+ else
196
+ run_test "env var preferred (exit=$EXIT, out=$OUT)" fail
197
+ fi
198
+
199
+ # Test 15: advisory names sub-pattern 16A
200
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
201
+ if echo "$OUT" | grep -q "16A" && echo "$OUT" | grep -q "Custom agents"; then
202
+ run_test "advisory names sub-pattern 16A (custom agents)" pass
203
+ else
204
+ run_test "advisory names 16A (got: $OUT)" fail
205
+ fi
206
+
207
+ # Test 16: advisory names sub-pattern 16B
208
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
209
+ if echo "$OUT" | grep -q "16B" && echo "$OUT" | grep -q "Anthropic-compatible"; then
210
+ run_test "advisory names sub-pattern 16B (Anthropic-compatible)" pass
211
+ else
212
+ run_test "advisory names 16B (got: $OUT)" fail
213
+ fi
214
+
215
+ # Test 17: advisory names sub-pattern 16C
216
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
217
+ if echo "$OUT" | grep -q "16C" && echo "$OUT" | grep -q "VS Code"; then
218
+ run_test "advisory names sub-pattern 16C (VS Code)" pass
219
+ else
220
+ run_test "advisory names 16C (got: $OUT)" fail
221
+ fi
222
+
223
+ # Test 18: advisory names sub-pattern 16D
224
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
225
+ if echo "$OUT" | grep -q "16D" && echo "$OUT" | grep -q "context operations"; then
226
+ run_test "advisory names sub-pattern 16D (context operations)" pass
227
+ else
228
+ run_test "advisory names 16D (got: $OUT)" fail
229
+ fi
230
+
231
+ # Test 19: advisory includes pin command
232
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
233
+ if echo "$OUT" | grep -q "npm install -g @anthropic-ai/claude-code@2.1.153"; then
234
+ run_test "advisory includes pin command" pass
235
+ else
236
+ run_test "advisory includes pin command (got: $OUT)" fail
237
+ fi
238
+
239
+ # Test 20: advisory includes auto-update suppression
240
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
241
+ if echo "$OUT" | grep -q "CLAUDE_CODE_DISABLE_AUTO_UPDATE=1"; then
242
+ run_test "advisory includes auto-update suppression" pass
243
+ else
244
+ run_test "advisory includes auto-update suppression (got: $OUT)" fail
245
+ fi
246
+
247
+ # Test 21: advisory references anchor issue #63469
248
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
249
+ if echo "$OUT" | grep -q "63469"; then
250
+ run_test "advisory references anchor issue #63469" pass
251
+ else
252
+ run_test "advisory references #63469 (got: $OUT)" fail
253
+ fi
254
+
255
+ # Test 22: advisory references field guide Gist
256
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
257
+ if echo "$OUT" | grep -q "05c120466996734f7bc2ad6d41fdedec"; then
258
+ run_test "advisory references field guide Gist URL" pass
259
+ else
260
+ run_test "advisory references Gist (got: $OUT)" fail
261
+ fi
262
+
263
+ # Test 23: advisory mentions QUIET silence path
264
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
265
+ if echo "$OUT" | grep -q "CC_VERSION_PIN_ADVISOR_QUIET"; then
266
+ run_test "advisory mentions QUIET env var to silence" pass
267
+ else
268
+ run_test "advisory mentions QUIET (got: $OUT)" fail
269
+ fi
270
+
271
+ # Test 24: output written to stderr, stdout empty
272
+ STDOUT=$(CLAUDE_CODE_VERSION=2.1.156 bash "$HOOK" 2>/dev/null)
273
+ if [ -z "$STDOUT" ]; then
274
+ run_test "warning written to stderr, stdout empty" pass
275
+ else
276
+ run_test "warning to stderr (stdout was: $STDOUT)" fail
277
+ fi
278
+
279
+ # Test 25: ADVISORY prefix (not BLOCKED)
280
+ OUT=$(CLAUDE_CODE_VERSION=2.1.154 bash "$HOOK" 2>&1)
281
+ if echo "$OUT" | grep -q "^ADVISORY:"; then
282
+ run_test "uses ADVISORY prefix (non-blocking)" pass
283
+ else
284
+ run_test "uses ADVISORY prefix (got: $OUT)" fail
285
+ fi
286
+
287
+ # Test 26: malformed version (non-semver) → fail-open silent
288
+ OUT=$(CLAUDE_CODE_VERSION="latest" bash "$HOOK" 2>&1)
289
+ EXIT=$?
290
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
291
+ run_test "non-semver version 'latest' → fail-open silent" pass
292
+ else
293
+ run_test "non-semver 'latest' (exit=$EXIT, out=$OUT)" fail
294
+ fi
295
+
296
+ # Test 27: empty version string → fail-open silent
297
+ # Empty env var means falling back to binary detection; use
298
+ # CC_VERSION_PIN_ADVISOR_CLAUDE_BIN pointing at nonexistent file to
299
+ # deterministically force binary detection to fail.
300
+ OUT=$(env -i HOME="$HOME" PATH="/bin:/usr/bin" \
301
+ CC_VERSION_PIN_ADVISOR_CLAUDE_BIN="$TMPDIR_RUN/does-not-exist" \
302
+ CLAUDE_CODE_VERSION="" bash "$HOOK" 2>&1)
303
+ EXIT=$?
304
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
305
+ run_test "empty version + no claude binary → fail-open silent" pass
306
+ else
307
+ run_test "empty version + no binary (exit=$EXIT, out=$OUT)" fail
308
+ fi
309
+
310
+ # Test 28: version with suffix tag (2.1.154-beta) → advisory (suffix stripped)
311
+ OUT=$(CLAUDE_CODE_VERSION="2.1.154-beta" bash "$HOOK" 2>&1)
312
+ if echo "$OUT" | grep -q "ADVISORY"; then
313
+ run_test "version 2.1.154-beta (suffix stripped) → advisory" pass
314
+ else
315
+ run_test "version 2.1.154-beta → advisory (got: $OUT)" fail
316
+ fi
317
+
318
+ # Test 29: stdin JSON consumed (SessionStart hooks receive JSON)
319
+ OUT=$(echo '{"hook_event_name":"SessionStart"}' | \
320
+ CLAUDE_CODE_VERSION=2.1.153 bash "$HOOK" 2>&1)
321
+ EXIT=$?
322
+ if [ "$EXIT" = "0" ] && [ -z "$OUT" ]; then
323
+ run_test "stdin JSON consumed silently when version below threshold" pass
324
+ else
325
+ run_test "stdin JSON consumed (exit=$EXIT, out=$OUT)" fail
326
+ fi
327
+
328
+ # Test 30: exit code 0 in all configurations (non-blocking)
329
+ EXITS=()
330
+ for cfg in \
331
+ "CLAUDE_CODE_VERSION=2.1.153" \
332
+ "CLAUDE_CODE_VERSION=2.1.154" \
333
+ "CLAUDE_CODE_VERSION=2.1.156 CC_VERSION_PIN_ADVISOR_DISABLE=1" \
334
+ "CLAUDE_CODE_VERSION=2.1.156 CC_VERSION_PIN_ADVISOR_QUIET=1" \
335
+ "CLAUDE_CODE_VERSION=2.1.156 CC_VERSION_PIN_ADVISOR_THRESHOLD=2.1.200" \
336
+ "CLAUDE_CODE_VERSION=latest" \
337
+ "CLAUDE_CODE_VERSION=2.1.154-beta"; do
338
+ eval "env -i HOME=\"$HOME\" PATH=\"\$PATH\" $cfg bash \"$HOOK\" >/dev/null 2>&1"
339
+ EXITS+=("$?")
340
+ done
341
+ ALL_ZERO=1
342
+ for e in "${EXITS[@]}"; do
343
+ [ "$e" != "0" ] && ALL_ZERO=0
344
+ done
345
+ if [ "$ALL_ZERO" = "1" ]; then
346
+ run_test "exit code 0 in all 7 configurations (non-blocking)" pass
347
+ else
348
+ run_test "exit code 0 in all configs (got: ${EXITS[*]})" fail
349
+ fi
350
+
351
+ echo
352
+ echo "Results: $PASS passed, $FAIL failed"
353
+ [ "$FAIL" = "0" ]
@@ -0,0 +1,173 @@
1
+ #!/bin/bash
2
+ # Tests for claude-md-reinjector.sh
3
+ set -euo pipefail
4
+
5
+ HOOK="$(dirname "$0")/../examples/claude-md-reinjector.sh"
6
+ PASS=0
7
+ FAIL=0
8
+ STATE_DIR="/tmp/cc-md-reinject"
9
+ SESSION_ID="test-$$"
10
+ COUNT_FILE="$STATE_DIR/${SESSION_ID}.count"
11
+
12
+ setup() {
13
+ rm -f "$STATE_DIR"/*.count 2>/dev/null || true
14
+ mkdir -p "$STATE_DIR"
15
+ }
16
+
17
+ # Build a temp CLAUDE.md we can point the hook at
18
+ TMP_MD=$(mktemp /tmp/test-claude-md.XXXXXX)
19
+ cat > "$TMP_MD" <<'EOF'
20
+ # Project Rules
21
+ - Rule A: never commit secrets
22
+ - Rule B: small functions only
23
+ - Rule C: ask before deleting files
24
+ EOF
25
+
26
+ INPUT='{"session_id":"'"$SESSION_ID"'","tool_name":"Read"}'
27
+
28
+ run_hook() {
29
+ local every="${1:-50}"
30
+ echo "$INPUT" | CC_MD_REINJECT_EVERY="$every" CC_MD_REINJECT_PATH="$TMP_MD" bash "$HOOK" 2>&1 || true
31
+ }
32
+
33
+ # --- Test 1: First call under threshold does NOT inject ---
34
+ setup
35
+ output=$(run_hook 50)
36
+ if echo "$output" | grep -q "re-injecting"; then
37
+ echo " FAIL: first call should not inject (count=1, every=50)"
38
+ FAIL=$((FAIL + 1))
39
+ else
40
+ echo " PASS: first call does not inject"
41
+ PASS=$((PASS + 1))
42
+ fi
43
+
44
+ # --- Test 2: Counter increments ---
45
+ setup
46
+ run_hook 50 >/dev/null 2>&1
47
+ run_hook 50 >/dev/null 2>&1
48
+ run_hook 50 >/dev/null 2>&1
49
+ count=$(cat "$COUNT_FILE" 2>/dev/null || echo 0)
50
+ if [ "$count" = "3" ]; then
51
+ echo " PASS: counter increments to 3"
52
+ PASS=$((PASS + 1))
53
+ else
54
+ echo " FAIL: counter should be 3, got $count"
55
+ FAIL=$((FAIL + 1))
56
+ fi
57
+
58
+ # --- Test 3: Inject fires on the N-th call ---
59
+ setup
60
+ # Set count to 1 already, N=2 → second call should inject
61
+ run_hook 2 >/dev/null 2>&1
62
+ output=$(run_hook 2)
63
+ if echo "$output" | grep -q "re-injecting"; then
64
+ echo " PASS: inject fires on N-th call (every=2)"
65
+ PASS=$((PASS + 1))
66
+ else
67
+ echo " FAIL: should have injected on call #2 with every=2"
68
+ echo " output: $output"
69
+ FAIL=$((FAIL + 1))
70
+ fi
71
+
72
+ # --- Test 4: Injected content contains CLAUDE.md rules ---
73
+ setup
74
+ run_hook 1 >/dev/null 2>&1 # first call injects (every=1)
75
+ output=$(echo "$INPUT" | CC_MD_REINJECT_EVERY=1 CC_MD_REINJECT_PATH="$TMP_MD" bash "$HOOK" 2>&1 || true)
76
+ if echo "$output" | grep -q "Rule A: never commit secrets"; then
77
+ echo " PASS: injected output contains CLAUDE.md content"
78
+ PASS=$((PASS + 1))
79
+ else
80
+ echo " FAIL: injected output missing CLAUDE.md rules"
81
+ FAIL=$((FAIL + 1))
82
+ fi
83
+
84
+ # --- Test 5: Inject output mentions issue #49244 ---
85
+ setup
86
+ output=$(echo "$INPUT" | CC_MD_REINJECT_EVERY=1 CC_MD_REINJECT_PATH="$TMP_MD" bash "$HOOK" 2>&1 || true)
87
+ if echo "$output" | grep -q "49244"; then
88
+ echo " PASS: header mentions issue #49244"
89
+ PASS=$((PASS + 1))
90
+ else
91
+ echo " FAIL: header should mention #49244"
92
+ FAIL=$((FAIL + 1))
93
+ fi
94
+
95
+ # --- Test 6: Missing CLAUDE.md exits 0 silently (no crash) ---
96
+ setup
97
+ GHOST_PATH="/tmp/does-not-exist-$$/CLAUDE.md"
98
+ set +e
99
+ output=$(echo "$INPUT" | CC_MD_REINJECT_EVERY=1 CC_MD_REINJECT_PATH="$GHOST_PATH" bash "$HOOK" 2>&1)
100
+ rc=$?
101
+ set -e
102
+ if [ "$rc" = "0" ] && ! echo "$output" | grep -q "re-injecting"; then
103
+ echo " PASS: missing CLAUDE.md exits 0 silently"
104
+ PASS=$((PASS + 1))
105
+ else
106
+ echo " FAIL: should exit 0 with no injection, rc=$rc output=$output"
107
+ FAIL=$((FAIL + 1))
108
+ fi
109
+
110
+ # --- Test 7: Invalid JSON on stdin doesn't crash ---
111
+ setup
112
+ set +e
113
+ output=$(echo "not-json" | CC_MD_REINJECT_EVERY=1 CC_MD_REINJECT_PATH="$TMP_MD" bash "$HOOK" 2>&1)
114
+ rc=$?
115
+ set -e
116
+ if [ "$rc" = "0" ]; then
117
+ echo " PASS: invalid JSON does not crash (uses default session)"
118
+ PASS=$((PASS + 1))
119
+ else
120
+ echo " FAIL: invalid JSON crashed with rc=$rc"
121
+ FAIL=$((FAIL + 1))
122
+ fi
123
+
124
+ # --- Test 8: Truncation honored ---
125
+ BIG_MD=$(mktemp /tmp/test-claude-md-big.XXXXXX)
126
+ python3 -c "print('x' * 5000)" > "$BIG_MD"
127
+ setup
128
+ output=$(echo "$INPUT" | CC_MD_REINJECT_EVERY=1 CC_MD_REINJECT_PATH="$BIG_MD" CC_MD_REINJECT_MAX_CHARS=500 bash "$HOOK" 2>&1 || true)
129
+ if echo "$output" | grep -q "truncated at 500 chars"; then
130
+ echo " PASS: truncation marker emitted for oversized CLAUDE.md"
131
+ PASS=$((PASS + 1))
132
+ else
133
+ echo " FAIL: truncation marker missing"
134
+ FAIL=$((FAIL + 1))
135
+ fi
136
+ rm -f "$BIG_MD"
137
+
138
+ # --- Test 9: Log file written when CC_MD_REINJECT_LOG set ---
139
+ LOG_FILE=$(mktemp /tmp/test-reinject-log.XXXXXX)
140
+ rm "$LOG_FILE"
141
+ setup
142
+ echo "$INPUT" | CC_MD_REINJECT_EVERY=1 CC_MD_REINJECT_PATH="$TMP_MD" CC_MD_REINJECT_LOG="$LOG_FILE" bash "$HOOK" >/dev/null 2>&1 || true
143
+ if [ -f "$LOG_FILE" ] && grep -q "session=$SESSION_ID" "$LOG_FILE"; then
144
+ echo " PASS: log file written with session id"
145
+ PASS=$((PASS + 1))
146
+ else
147
+ echo " FAIL: log file missing or malformed"
148
+ FAIL=$((FAIL + 1))
149
+ fi
150
+ rm -f "$LOG_FILE"
151
+
152
+ # --- Test 10: Different sessions have independent counters ---
153
+ setup
154
+ run_hook 50 >/dev/null 2>&1
155
+ INPUT_B='{"session_id":"other-'$$'","tool_name":"Read"}'
156
+ echo "$INPUT_B" | CC_MD_REINJECT_EVERY=50 CC_MD_REINJECT_PATH="$TMP_MD" bash "$HOOK" >/dev/null 2>&1 || true
157
+ count_a=$(cat "$STATE_DIR/${SESSION_ID}.count" 2>/dev/null || echo 0)
158
+ count_b=$(cat "$STATE_DIR/other-$$.count" 2>/dev/null || echo 0)
159
+ if [ "$count_a" = "1" ] && [ "$count_b" = "1" ]; then
160
+ echo " PASS: per-session counters isolated"
161
+ PASS=$((PASS + 1))
162
+ else
163
+ echo " FAIL: counters should be independent (a=$count_a b=$count_b)"
164
+ FAIL=$((FAIL + 1))
165
+ fi
166
+
167
+ # Cleanup
168
+ rm -f "$TMP_MD"
169
+ rm -f "$STATE_DIR"/*.count 2>/dev/null || true
170
+
171
+ echo ""
172
+ echo "Results: $PASS passed, $FAIL failed"
173
+ [ "$FAIL" -eq 0 ]