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,188 @@
1
+ #!/bin/bash
2
+ # memory-orphan-detector.sh — Detect Claude Code memory that may have been
3
+ # orphaned when the working directory was renamed.
4
+ #
5
+ # Solves: #61349 — "[BUG] Memory orphaned when working directory is renamed"
6
+ # Filed 2026-05-22 by adamcopley.
7
+ #
8
+ # Claude Code stores per-project memory at
9
+ # ~/.claude/projects/<encoded-working-dir>/memory/
10
+ # where <encoded-working-dir> is the absolute working directory path with
11
+ # every `/` and `.` rewritten as `-`.
12
+ #
13
+ # When the operator renames or moves a working directory, Claude Code does
14
+ # not migrate the memory. Instead, on next session start it silently creates
15
+ # a fresh empty memory directory at the new encoded path. The old memory
16
+ # directory remains on disk forever — orphaned, not loaded by any session,
17
+ # with no notification to the operator. The accumulated investment (user
18
+ # role, project conventions, validated feedback, references to external
19
+ # systems) is effectively lost.
20
+ #
21
+ # This hook runs on SessionStart and emits a warning when:
22
+ # (a) the CURRENT working directory's memory is empty (≤ N entries), AND
23
+ # (b) the current working directory has substantive git history (suggesting
24
+ # prior work in the project that would have accumulated memory), AND
25
+ # (c) one or more OTHER memory directories on disk have substantive content
26
+ # (≥ M entries or ≥ K bytes), making them candidate orphans
27
+ #
28
+ # All three signals together: high likelihood of an orphaning event. The hook
29
+ # does not block session start. It surfaces the candidate orphan directories
30
+ # so the operator can decide whether to migrate them manually.
31
+ #
32
+ # Path decoding is LOSSY (a `-` in the encoded path could have originated as
33
+ # either a `/` or a literal `-` in the working directory name). This hook
34
+ # does NOT attempt to decode and verify path existence; it uses encoded-form
35
+ # similarity heuristics instead.
36
+ #
37
+ # TRIGGER: SessionStart
38
+ # MATCHER: ""
39
+ #
40
+ # CONFIGURATION (environment variables):
41
+ # CC_PROJECTS_DIR default ~/.claude/projects
42
+ # CC_MEMORY_ORPHAN_DISABLE set to "1" to disable
43
+ # CC_MEMORY_EMPTY_THRESHOLD max entries to consider "empty" (default 1)
44
+ # CC_MEMORY_ORPHAN_THRESHOLD min entries for candidate orphan (default 5)
45
+ # CC_MEMORY_ORPHAN_MIN_BYTES min bytes for candidate orphan (default 2048)
46
+ #
47
+ # USAGE (settings.json):
48
+ # {
49
+ # "hooks": {
50
+ # "SessionStart": [{
51
+ # "matcher": "",
52
+ # "hooks": [{
53
+ # "type": "command",
54
+ # "command": "~/.claude/hooks/memory-orphan-detector.sh"
55
+ # }]
56
+ # }]
57
+ # }
58
+ # }
59
+
60
+ set -uo pipefail
61
+
62
+ [ "${CC_MEMORY_ORPHAN_DISABLE:-0}" = "1" ] && exit 0
63
+
64
+ PROJECTS_DIR="${CC_PROJECTS_DIR:-$HOME/.claude/projects}"
65
+ EMPTY_THRESHOLD="${CC_MEMORY_EMPTY_THRESHOLD:-1}"
66
+ ORPHAN_THRESHOLD="${CC_MEMORY_ORPHAN_THRESHOLD:-5}"
67
+ ORPHAN_MIN_BYTES="${CC_MEMORY_ORPHAN_MIN_BYTES:-2048}"
68
+
69
+ [ ! -d "$PROJECTS_DIR" ] && exit 0
70
+
71
+ CWD="$(pwd)"
72
+
73
+ # Compute the encoded form of the current working directory.
74
+ encode_path() {
75
+ # / → -, . → -
76
+ printf '%s' "$1" | tr '/.' '--'
77
+ }
78
+ CWD_ENCODED="$(encode_path "$CWD")"
79
+ CURRENT_MEMORY_DIR="$PROJECTS_DIR/${CWD_ENCODED}/memory"
80
+
81
+ # (a) Is current memory empty?
82
+ CURRENT_COUNT=0
83
+ if [ -d "$CURRENT_MEMORY_DIR" ]; then
84
+ CURRENT_COUNT=$(find "$CURRENT_MEMORY_DIR" -maxdepth 1 -type f 2>/dev/null | wc -l)
85
+ fi
86
+
87
+ # Not empty → likely fine. Exit silently.
88
+ if [ "$CURRENT_COUNT" -gt "$EMPTY_THRESHOLD" ]; then
89
+ exit 0
90
+ fi
91
+
92
+ # (b) Does current working directory have git history?
93
+ HAS_GIT_HISTORY=0
94
+ if [ -d "$CWD/.git" ] || git -C "$CWD" rev-parse --git-dir > /dev/null 2>&1; then
95
+ COMMITS=$(git -C "$CWD" rev-list --count HEAD 2>/dev/null || echo 0)
96
+ if [ "$COMMITS" -gt 5 ]; then
97
+ HAS_GIT_HISTORY=1
98
+ fi
99
+ fi
100
+
101
+ # No git history → not a strong signal of prior work. Exit silently.
102
+ if [ "$HAS_GIT_HISTORY" -eq 0 ]; then
103
+ exit 0
104
+ fi
105
+
106
+ # (c) Find candidate orphans: other memory directories with content.
107
+ ORPHAN_CANDIDATES=()
108
+ for d in "$PROJECTS_DIR"/*/; do
109
+ [ -d "$d" ] || continue
110
+ base="${d%/}"
111
+ base="${base##*/}"
112
+ # Skip current
113
+ if [ "$base" = "$CWD_ENCODED" ]; then continue; fi
114
+ mem_dir="$d/memory"
115
+ [ ! -d "$mem_dir" ] && continue
116
+ cnt=$(find "$mem_dir" -maxdepth 1 -type f 2>/dev/null | wc -l)
117
+ bytes=$(du -sb "$mem_dir" 2>/dev/null | awk '{print $1}')
118
+ bytes="${bytes:-0}"
119
+ if [ "$cnt" -ge "$ORPHAN_THRESHOLD" ] && [ "$bytes" -ge "$ORPHAN_MIN_BYTES" ]; then
120
+ # Compute encoded-form similarity: shared prefix length / longer length
121
+ # (very rough — but better than nothing without lossless decode)
122
+ ORPHAN_CANDIDATES+=("$base|$cnt|$bytes")
123
+ fi
124
+ done
125
+
126
+ # No candidate orphans → nothing to report.
127
+ if [ "${#ORPHAN_CANDIDATES[@]}" -eq 0 ]; then
128
+ exit 0
129
+ fi
130
+
131
+ # Limit output to top 5 candidates, sorted by byte size descending.
132
+ TOP=()
133
+ while IFS= read -r line; do
134
+ TOP+=("$line")
135
+ done < <(printf '%s\n' "${ORPHAN_CANDIDATES[@]}" | sort -t'|' -k3 -rn | head -5)
136
+
137
+ EXTRA=$(( ${#ORPHAN_CANDIDATES[@]} - ${#TOP[@]} ))
138
+
139
+ cat >&2 <<EOF
140
+ <system-reminder>
141
+ POSSIBLE MEMORY ORPHANING DETECTED — the current working directory's memory
142
+ is empty, but this project has substantive git history AND there are other
143
+ memory directories on disk with non-trivial content. One of them may be the
144
+ prior version of this project's memory that was orphaned by a directory
145
+ rename, move, or symlink change.
146
+
147
+ This is the failure mode documented in anthropics/claude-code#61349. Claude
148
+ Code derives memory location from the encoded working-directory path
149
+ (everything in / and . becomes -). Renaming the directory produces a
150
+ different encoded form, so a fresh empty memory directory is created at
151
+ the new path while the old memory stays on disk, unreferenced.
152
+
153
+ Current working directory: $CWD
154
+ Encoded form: $CWD_ENCODED
155
+ Current memory: $CURRENT_COUNT file(s) at $CURRENT_MEMORY_DIR
156
+
157
+ Candidate orphan memory directories (top 5 by size):
158
+ EOF
159
+ for entry in "${TOP[@]}"; do
160
+ IFS='|' read -r b c bytes <<< "$entry"
161
+ # Print bytes in KB for readability
162
+ kb=$(( bytes / 1024 ))
163
+ echo " $PROJECTS_DIR/$b/memory/ ($c files, ${kb}KB)" >&2
164
+ done
165
+ if [ "$EXTRA" -gt 0 ]; then
166
+ echo " ... and $EXTRA more" >&2
167
+ fi
168
+ cat >&2 <<EOF
169
+
170
+ Recommended next actions for the operator (NOT for the model to perform
171
+ automatically):
172
+ 1. Inspect the candidate directories. The encoded path is the original
173
+ working directory's absolute path with every / and . replaced by -.
174
+ Note that this encoding is LOSSY — a - in the encoded form could be a
175
+ literal - or a / in the original path. Decode by trying both.
176
+ 2. If you recognize an orphan that corresponds to a previous location of
177
+ this project (before a rename/move), copy its memory files into the
178
+ current memory directory: cp -r <orphan>/memory/* $CURRENT_MEMORY_DIR/
179
+ 3. To prevent future orphaning, version-control the memory directory:
180
+ store memory in the project's git tree (e.g., .claude-memory/) and
181
+ symlink the system memory directory to it. Renames preserve the link.
182
+
183
+ To disable this detector, set CC_MEMORY_ORPHAN_DISABLE=1.
184
+ </system-reminder>
185
+ EOF
186
+
187
+ # Exit 0 — detection-only.
188
+ exit 0
@@ -1,40 +1,122 @@
1
1
  #!/bin/bash
2
2
  # ================================================================
3
- # memory-write-guard.sh — Log writes to ~/.claude/ directory
3
+ # memory-write-guard.sh — See, approve, or block silent memory writes
4
4
  # ================================================================
5
5
  # PURPOSE:
6
- # Claude auto-writes to ~/.claude/projects/*/memory/ without
7
- # user visibility. This hook logs all writes to ~/.claude/ paths
8
- # so users know what's being stored.
6
+ # Claude Code writes to its memory without asking: it edits CLAUDE.md
7
+ # and silently creates/updates/deletes files under
8
+ # ~/.claude/projects/*/memory/. Users report having to re-check those
9
+ # files after every session to find changes they never approved.
9
10
  #
10
- # TRIGGER: PreToolUse MATCHER: "Write|Edit"
11
+ # This hook gives the operator control over those writes. By default it
12
+ # only makes them VISIBLE (logs + a stderr note), which is non-intrusive
13
+ # and safe for automated runs. Opt in to an approval prompt — or a hard
14
+ # block — when you want every memory change to pass through you first.
11
15
  #
12
- # Born from: https://github.com/anthropics/claude-code/issues/38040
13
- # "No way to enforce approval on all file modifications"
16
+ # WHAT COUNTS AS A "MEMORY" WRITE (Write/Edit/MultiEdit on):
17
+ # - any CLAUDE.md / CLAUDE.local.md (project or user memory)
18
+ # - anything under a .claude/ directory, which includes the auto-memory
19
+ # store ~/.claude/projects/*/memory/ and ~/.claude/settings.json
20
+ #
21
+ # MODE (env var CC_MEMORY_WRITE_APPROVAL):
22
+ # off (default) — log + warn, never interrupt (backward compatible)
23
+ # ask — require interactive approval for each memory write
24
+ # block — refuse all memory writes
25
+ #
26
+ # WHY OPT-IN: existing installs and headless/CI runs must keep working
27
+ # unchanged, so the prompt is never on unless the operator asks for it.
28
+ #
29
+ # VERSION NOTE (measured 2026-08-13 on 2.1.228, corrects an earlier note here):
30
+ # #77212 reported that under bypassPermissions an "ask" decision is silently
31
+ # auto-approved and does not gate the write. This comment used to repeat that
32
+ # as current behaviour. It does not reproduce on 2.1.228: run interactively in
33
+ # an isolated HOME, the confirmation appears both under
34
+ # --dangerously-skip-permissions and under --permission-mode auto, carrying
35
+ # this hook's permissionDecisionReason. Control: with the hook removed, both
36
+ # modes ran the same command with no prompt at all, so the permissive mode was
37
+ # genuinely in effect. Non-interactively (claude -p) the call is refused
38
+ # rather than approved. Older builds may still match the report — verify on
39
+ # your own version with `--version` before relying on either behaviour.
40
+ # Independent of all this: an "ask" needs somebody present to answer, so for
41
+ # fully unattended runs use CC_MEMORY_WRITE_APPROVAL=block (exit 2), which is
42
+ # enforced regardless of permission mode.
43
+ #
44
+ # TRIGGER: PreToolUse MATCHER: "Write|Edit|MultiEdit"
45
+ #
46
+ # Born from:
47
+ # https://github.com/anthropics/claude-code/issues/38040
48
+ # "No way to enforce approval on all file modifications"
49
+ # https://github.com/anthropics/claude-code/issues/65064
50
+ # "claude code writes memory without asking for permission"
14
51
  # ================================================================
15
52
 
53
+ set -u
54
+
55
+ # Without jq, the parse below silently yields empty and this hook stops
56
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
57
+ # here: blocking would halt every tool call, and exiting 0 would change
58
+ # the behaviour of guards that do not depend on the parsed value.
59
+ if ! command -v jq >/dev/null 2>&1; then
60
+ _nojq_warned="/tmp/cc-nojq-warned-memory-write-guard-$PPID"
61
+ [ -f "$_nojq_warned" ] || {
62
+ echo "WARNING [memory-write-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
63
+ : > "$_nojq_warned"
64
+ }
65
+ fi
66
+
16
67
  INPUT=$(cat)
17
68
  FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
18
69
  [ -z "$FILE" ] && exit 0
19
70
 
20
- # Check if targeting ~/.claude/
71
+ # Is this a memory file? Match the auto-memory/.claude store and CLAUDE.md
72
+ # files anywhere (project ./CLAUDE.md as well as ~/.claude/CLAUDE.md).
73
+ BASENAME=$(basename "$FILE")
74
+ IS_MEMORY=0
21
75
  case "$FILE" in
22
- */.claude/*|~/.claude/*)
23
- # Log the write
24
- LOG="$HOME/.claude/memory-writes.log"
25
- echo "[$(date -Iseconds)] Write to: $FILE" >> "$LOG" 2>/dev/null
76
+ */.claude/*|~/.claude/*) IS_MEMORY=1 ;;
77
+ esac
78
+ case "$BASENAME" in
79
+ CLAUDE.md|CLAUDE.local.md) IS_MEMORY=1 ;;
80
+ esac
81
+ [ "$IS_MEMORY" -eq 0 ] && exit 0
82
+
83
+ # Record every memory write so the operator can audit what was stored.
84
+ LOG="$HOME/.claude/memory-writes.log"
85
+ echo "[$(date -Iseconds)] Write to: $FILE" >> "$LOG" 2>/dev/null
26
86
 
27
- # Only warn (don't block) — memory writes are usually intentional
28
- echo "NOTE: Writing to Claude config directory: $FILE" >&2
87
+ MODE="${CC_MEMORY_WRITE_APPROVAL:-off}"
29
88
 
30
- # Block writes to settings.json unless explicitly allowed
89
+ case "$MODE" in
90
+ ask)
91
+ # Emit a PreToolUse permission decision. In an interactive session
92
+ # this surfaces an approve/deny prompt — including under
93
+ # bypassPermissions and auto mode, measured on 2.1.228 (see the
94
+ # VERSION NOTE at the top; #77212 reported otherwise on older builds).
95
+ # Use =block when nobody is present to answer the prompt.
96
+ jq -n --arg f "$FILE" '{
97
+ hookSpecificOutput: {
98
+ hookEventName: "PreToolUse",
99
+ permissionDecision: "ask",
100
+ permissionDecisionReason: ("Approve write to memory file: " + $f)
101
+ }
102
+ }'
103
+ exit 0
104
+ ;;
105
+ block)
106
+ echo "BLOCKED: memory write refused by memory-write-guard." >&2
107
+ echo "File: $FILE" >&2
108
+ echo "Set CC_MEMORY_WRITE_APPROVAL=ask to approve per-write, or =off to only log." >&2
109
+ exit 2
110
+ ;;
111
+ *)
112
+ # off (default): only make the write visible.
113
+ echo "NOTE: Writing to Claude memory: $FILE" >&2
31
114
  case "$FILE" in
32
115
  */settings.json|*/settings.local.json)
33
116
  echo "WARNING: Modifying Claude Code settings file." >&2
34
117
  echo "Verify this change is intentional." >&2
35
118
  ;;
36
119
  esac
120
+ exit 0
37
121
  ;;
38
122
  esac
39
-
40
- exit 0
@@ -14,6 +14,18 @@
14
14
 
15
15
  set -euo pipefail
16
16
 
17
+ # Without jq, the parse below silently yields empty and this hook stops
18
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
19
+ # here: blocking would halt every tool call, and exiting 0 would change
20
+ # the behaviour of guards that do not depend on the parsed value.
21
+ if ! command -v jq >/dev/null 2>&1; then
22
+ _nojq_warned="/tmp/cc-nojq-warned-migration-verify-guard-$PPID"
23
+ [ -f "$_nojq_warned" ] || {
24
+ echo "WARNING [migration-verify-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
25
+ : > "$_nojq_warned"
26
+ }
27
+ fi
28
+
17
29
  INPUT=$(cat)
18
30
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
19
31
  [ -z "$COMMAND" ] && exit 0
@@ -0,0 +1,177 @@
1
+ #!/bin/bash
2
+ # model-swap-suggester.sh — Evidence-driven swap recommendation for the AUP false-positive cluster
3
+ #
4
+ # Background:
5
+ # Cluster 9 (Usage Policy classifier over-trigger) accumulated 25+ open GitHub issues
6
+ # between 2026-05-18 and 2026-05-27, with Opus 4.7 / 4.6 / 1M variants over-triggering
7
+ # on benign Claude Code prompts (English, Russian, Polish, Spanish; kernel security,
8
+ # biomedical, FPGA, plain greetings — context-independent). Sonnet variants are reported
9
+ # unaffected.
10
+ #
11
+ # Two defense hooks ship today:
12
+ # - aup-false-positive-helper.sh (SessionStart, opt-in, generic awareness)
13
+ # - aup-block-pattern-logger.sh (PostToolUse, on-by-default, records each block)
14
+ #
15
+ # The gap they leave: the operator who is actively being blocked needs an evidence-driven
16
+ # recommendation at the right moment — "you have been blocked N times in the last hour
17
+ # on Opus, here is the exact swap command." The helper hook is generic and fires on every
18
+ # Opus session; the logger collects evidence but does not act on it.
19
+ #
20
+ # This hook closes that loop. On SessionStart, it reads the block log written by the
21
+ # logger, counts Opus blocks in a recent time window, and emits a concrete swap-to-Sonnet
22
+ # advisory only when the count crosses a threshold. Silent otherwise.
23
+ #
24
+ # Reference: https://gist.github.com/yurukusa/4fa4751044be45bd83345601ee79c2db
25
+ #
26
+ # What this hook does:
27
+ # On SessionStart, if ANTHROPIC_MODEL is pinned to an Opus variant AND the AUP block log
28
+ # shows N or more blocks on any Opus model in the last M minutes, emit a one-time advisory
29
+ # with the exact swap command for the current session. Silent in every other case.
30
+ #
31
+ # When this hook does NOT emit anything:
32
+ # - CC_MODEL_SWAP_SUGGESTER_DISABLE=1
33
+ # - CC_MODEL_SWAP_SUGGESTER_QUIET=1
34
+ # - ANTHROPIC_MODEL unset (default routing)
35
+ # - ANTHROPIC_MODEL pinned to a non-Opus variant (Sonnet / Haiku unaffected)
36
+ # - aup-block log missing, empty, or unreadable
37
+ # - Opus blocks in the configured window < threshold
38
+ #
39
+ # Hook config (settings.json):
40
+ # {
41
+ # "hooks": {
42
+ # "SessionStart": [{
43
+ # "matcher": "",
44
+ # "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/model-swap-suggester.sh" }]
45
+ # }]
46
+ # }
47
+ # }
48
+ #
49
+ # Env vars:
50
+ # CC_MODEL_SWAP_SUGGESTER_DISABLE=1 — never emit
51
+ # CC_MODEL_SWAP_SUGGESTER_QUIET=1 — silent (post-acknowledgment)
52
+ # CC_MODEL_SWAP_SUGGESTER_THRESHOLD=<n> — Opus block count threshold (default 3)
53
+ # CC_MODEL_SWAP_SUGGESTER_WINDOW_MIN=<n> — lookback window in minutes (default 60)
54
+ # CC_MODEL_SWAP_SUGGESTER_TARGET=<model> — target Sonnet model (default claude-sonnet-4-7)
55
+ # CC_AUP_BLOCK_LOG_PATH=<path> — log path (shared with logger; default ~/.claude/aup-block-history.log)
56
+ #
57
+ # Design notes:
58
+ # - Evidence-driven, not opt-in. The advisory only fires when real blocks have happened,
59
+ # so it never adds noise for users who haven't been affected.
60
+ # - Counts Opus blocks across all Opus variants in the log (not just the currently pinned
61
+ # model), because the cluster signature is Opus-family-wide. If you swapped from
62
+ # opus-4-7 to opus-4-6 mid-day and both blocked, both count toward the threshold.
63
+ # - Window is timestamp-based, not last-N-lines, so a quiet session with stale entries
64
+ # does not trigger the advisory.
65
+ # - Never blocks. All failure paths exit 0 so a corrupt log or missing date utility
66
+ # cannot break the session.
67
+
68
+ set -u
69
+
70
+ # Disable path
71
+ if [ "${CC_MODEL_SWAP_SUGGESTER_DISABLE:-0}" = "1" ]; then
72
+ exit 0
73
+ fi
74
+
75
+ # Quiet path
76
+ if [ "${CC_MODEL_SWAP_SUGGESTER_QUIET:-0}" = "1" ]; then
77
+ exit 0
78
+ fi
79
+
80
+ # Model unset → default routing, no specific advisory
81
+ if [ -z "${ANTHROPIC_MODEL:-}" ]; then
82
+ exit 0
83
+ fi
84
+
85
+ # Non-Opus model → unaffected by the cluster
86
+ case "$ANTHROPIC_MODEL" in
87
+ *opus*|*Opus*|*OPUS*) : ;;
88
+ *) exit 0 ;;
89
+ esac
90
+
91
+ LOG_PATH="${CC_AUP_BLOCK_LOG_PATH:-$HOME/.claude/aup-block-history.log}"
92
+ [ -f "$LOG_PATH" ] || exit 0
93
+ [ -r "$LOG_PATH" ] || exit 0
94
+ [ -s "$LOG_PATH" ] || exit 0
95
+
96
+ THRESHOLD="${CC_MODEL_SWAP_SUGGESTER_THRESHOLD:-3}"
97
+ WINDOW_MIN="${CC_MODEL_SWAP_SUGGESTER_WINDOW_MIN:-60}"
98
+ TARGET="${CC_MODEL_SWAP_SUGGESTER_TARGET:-claude-sonnet-4-7}"
99
+
100
+ # Validate numeric env vars; fall back to defaults on garbage input.
101
+ case "$THRESHOLD" in
102
+ ''|*[!0-9]*) THRESHOLD=3 ;;
103
+ esac
104
+ case "$WINDOW_MIN" in
105
+ ''|*[!0-9]*) WINDOW_MIN=60 ;;
106
+ esac
107
+
108
+ # Compute cutoff epoch (now - window_min * 60). Use GNU date first, then BSD date.
109
+ NOW=$(date -u '+%s' 2>/dev/null) || exit 0
110
+ CUTOFF=$((NOW - WINDOW_MIN * 60))
111
+
112
+ ts_to_epoch() {
113
+ local ts="$1"
114
+ date -u -d "$ts" '+%s' 2>/dev/null \
115
+ || date -j -u -f '%Y-%m-%dT%H:%M:%SZ' "$ts" '+%s' 2>/dev/null
116
+ }
117
+
118
+ # Count Opus blocks in the window. The log schema is:
119
+ # ISO8601_UTC | MODEL | TOOL | PATTERN_KIND | EXCERPT
120
+ # We only count rows whose model field matches an Opus variant and whose timestamp falls
121
+ # inside the cutoff window. Rows with unparseable timestamps are skipped silently.
122
+ COUNT=0
123
+ while IFS='|' read -r LOG_TS LOG_MODEL _LOG_TOOL _LOG_KIND _LOG_EXCERPT; do
124
+ [ -z "$LOG_TS" ] && continue
125
+ [ -z "$LOG_MODEL" ] && continue
126
+ case "$LOG_MODEL" in
127
+ *opus*|*Opus*|*OPUS*) : ;;
128
+ *) continue ;;
129
+ esac
130
+ LOG_EPOCH=$(ts_to_epoch "$LOG_TS")
131
+ [ -z "$LOG_EPOCH" ] && continue
132
+ case "$LOG_EPOCH" in
133
+ *[!0-9]*) continue ;;
134
+ esac
135
+ if [ "$LOG_EPOCH" -ge "$CUTOFF" ] 2>/dev/null; then
136
+ COUNT=$((COUNT + 1))
137
+ fi
138
+ done < "$LOG_PATH"
139
+
140
+ if [ "$COUNT" -lt "$THRESHOLD" ] 2>/dev/null; then
141
+ exit 0
142
+ fi
143
+
144
+ # Threshold crossed → emit one-time advisory. The advisory is deliberately concrete:
145
+ # exact swap command, exact env-var suppression command, and pointers to the partner hooks
146
+ # the operator can lean on after swapping.
147
+ cat >&2 <<EOF
148
+ [model-swap-suggester] $COUNT Usage Policy block(s) recorded on Opus models in the last $WINDOW_MIN minutes.
149
+
150
+ Current model: $ANTHROPIC_MODEL
151
+ Log file: $LOG_PATH
152
+
153
+ The Anthropic Usage Policy classifier has been over-triggering on benign prompts on Opus
154
+ variants since 2026-05-18. Sonnet variants are reportedly unaffected. Recommended swap
155
+ for this session:
156
+
157
+ export ANTHROPIC_MODEL=$TARGET
158
+
159
+ After swapping, the false-positive helper will go silent automatically (Sonnet is treated
160
+ as unaffected). Re-pin Opus once the upstream classifier stabilises.
161
+
162
+ Related hooks (already shipped):
163
+ aup-false-positive-helper.sh — generic awareness advisory (opt-in via CC_AUP_FALSE_POSITIVE_HELPER_REMIND=1)
164
+ aup-block-pattern-logger.sh — records each block to $LOG_PATH
165
+
166
+ To silence this advisory permanently for the current session, even when blocks continue:
167
+ export CC_MODEL_SWAP_SUGGESTER_QUIET=1
168
+
169
+ To raise the threshold instead of silencing:
170
+ export CC_MODEL_SWAP_SUGGESTER_THRESHOLD=10 # only suggest after 10 blocks in $WINDOW_MIN min
171
+
172
+ GitHub tracker (25+ independent reports, 2026-05-18 through 2026-05-27):
173
+ https://github.com/anthropics/claude-code/issues/60366
174
+ https://github.com/anthropics/claude-code/issues/62190
175
+ EOF
176
+
177
+ exit 0
@@ -1,3 +1,4 @@
1
+ #!/bin/bash
1
2
  INPUT=$(cat)
2
3
  COUNTER_FILE="/tmp/.cc-model-check-counter"
3
4
  COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
@@ -6,7 +7,10 @@ echo "$COUNT" > "$COUNTER_FILE"
6
7
  if [ $((COUNT % 50)) -ne 0 ]; then
7
8
  exit 0
8
9
  fi
9
- SESSION_FILE=$(ls -t ~/.claude/projects/*/session.jsonl 2>/dev/null | head -1)
10
+ # 記録の場所を推測しない(旧: projects/*/session.jsonl は実在せず、
11
+ # glob が空のまま黙って一度も警告しなかった)。
12
+ SESSION_FILE=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
13
+ [ -f "$SESSION_FILE" ] || SESSION_FILE=$(ls -t "$HOME"/.claude/projects/*/*.jsonl 2>/dev/null | head -1)
10
14
  if [ -n "$SESSION_FILE" ]; then
11
15
  MODEL=$(grep -o '"model":"[^"]*"' "$SESSION_FILE" 2>/dev/null | tail -1 | cut -d'"' -f4)
12
16
  if echo "$MODEL" | grep -qi "opus-4-7\|opus-4.7"; then
@@ -0,0 +1,63 @@
1
+ #!/bin/bash
2
+ # model-version-lock.sh — silent mid-session downgrade detector (Incident 4)
3
+ # Why: Opus 4.7 sessions sometimes migrate mid-session to a different model
4
+ # (for example the 1M-context automatic switch, #49541) with no client-
5
+ # visible announcement. The downgrade silently changes token accounting,
6
+ # context window, and quality. This hook writes a lock file containing
7
+ # the model id seen on the first turn of the session and emits a stderr
8
+ # banner whenever a later turn reports a different model id.
9
+ # Event: PostToolUse MATCHER: "*"
10
+ # Action: First per-session call creates
11
+ # ~/.claude/logs/model-locks/<session-id>.model. Subsequent calls read
12
+ # the lock and compare. Mismatch → banner. /model is the expected
13
+ # user path for intentional switches, so the banner says so.
14
+ #
15
+ # To reset: rm -rf ~/.claude/logs/model-locks/ (between sessions that
16
+ # deliberately switch models, otherwise locks accumulate)
17
+
18
+ set -u
19
+
20
+ LOG_DIR="${HOME}/.claude/logs"
21
+ LOCK_DIR="${LOG_DIR}/model-locks"
22
+ mkdir -p "$LOCK_DIR" 2>/dev/null
23
+
24
+ INPUT=$(cat)
25
+
26
+ SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
27
+ [ "$SESSION_ID" = "unknown" ] && exit 0
28
+
29
+ # Resolve the current model. PostToolUse payload rarely has it directly, so
30
+ # read the last assistant turn from the transcript for its "model" field.
31
+ MODEL=""
32
+ TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
33
+ if [ -n "$TRANSCRIPT" ] && [ -r "$TRANSCRIPT" ]; then
34
+ MODEL=$(tac "$TRANSCRIPT" 2>/dev/null \
35
+ | grep -m1 '"model"' \
36
+ | jq -r '.message.model // .model // empty' 2>/dev/null)
37
+ fi
38
+
39
+ # Fallback: environment variable (used by some wrappers and tests).
40
+ if [ -z "$MODEL" ] && [ -n "${CLAUDE_MODEL:-}" ]; then
41
+ MODEL="$CLAUDE_MODEL"
42
+ fi
43
+
44
+ # If we still do not know the model, do nothing — no false positives.
45
+ [ -z "$MODEL" ] && exit 0
46
+
47
+ LOCK_FILE="${LOCK_DIR}/${SESSION_ID}.model"
48
+
49
+ if [ ! -s "$LOCK_FILE" ]; then
50
+ printf '%s\n' "$MODEL" > "$LOCK_FILE"
51
+ exit 0
52
+ fi
53
+
54
+ LOCKED=$(cat "$LOCK_FILE" 2>/dev/null)
55
+ if [ -n "$LOCKED" ] && [ "$LOCKED" != "$MODEL" ]; then
56
+ echo "⚠ model-version-lock: $LOCKED → $MODEL (session $SESSION_ID)" >&2
57
+ echo " Use /model to switch intentionally. Silent migrations (#49541) change token accounting and quality." >&2
58
+ # Update the lock so we do not emit again for the same transition this
59
+ # session. Users who want to see every transition can remove this line.
60
+ printf '%s\n' "$MODEL" > "$LOCK_FILE"
61
+ fi
62
+
63
+ exit 0
@@ -20,6 +20,18 @@
20
20
 
21
21
  set -euo pipefail
22
22
 
23
+ # Without jq, the parse below silently yields empty and this hook stops
24
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
25
+ # here: blocking would halt every tool call, and exiting 0 would change
26
+ # the behaviour of guards that do not depend on the parsed value.
27
+ if ! command -v jq >/dev/null 2>&1; then
28
+ _nojq_warned="/tmp/cc-nojq-warned-move-delete-sequence-guard-$PPID"
29
+ [ -f "$_nojq_warned" ] || {
30
+ echo "WARNING [move-delete-sequence-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
31
+ : > "$_nojq_warned"
32
+ }
33
+ fi
34
+
23
35
  INPUT=$(cat)
24
36
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
25
37
  [ -z "$COMMAND" ] && exit 0
@@ -33,10 +45,29 @@ fi
33
45
  # Pattern: mv <src> <dst> [&&;||] rm [-rf] <target>
34
46
  # We check if the rm target is a parent of, or the same as, the mv source
35
47
 
48
+ # The extraction below used grep -oP, which is GNU-only. BSD grep (macOS)
49
+ # rejects -P outright, so both variables came back empty, and the two [ -z ]
50
+ # checks under this block read that as "nothing to compare" and exited 0 —
51
+ # the guard was off on macOS with no sign of it. Keep the GNU path exactly as
52
+ # it was and add an equivalent for platforms without PCRE.
53
+ if echo x | grep -qP x 2>/dev/null; then HAS_PCRE=1; else HAS_PCRE=0; fi
54
+
55
+ # Reads a command line on stdin, prints the first argument after $1 and its flags.
56
+ # \b and \K have no POSIX equivalent, so the fallback matches the command word
57
+ # with its leading boundary and strips that prefix afterwards.
58
+ extract_operand() {
59
+ if [ "$HAS_PCRE" = 1 ]; then
60
+ grep -oP "\\b$1\\s+(-[a-zA-Z]+\\s+)*\\K\\S+" 2>/dev/null || true
61
+ else
62
+ grep -oE "(^|[^a-zA-Z])$1[[:space:]]+(-[a-zA-Z]+[[:space:]]+)*[^[:space:]]+" 2>/dev/null \
63
+ | sed -E "s/^[^a-zA-Z]?$1[[:space:]]+(-[a-zA-Z]+[[:space:]]+)*//" || true
64
+ fi
65
+ }
66
+
36
67
  # Get all mv source paths (first arg after mv and optional flags)
37
- MV_SOURCES=$(echo "$COMMAND" | grep -oP '\bmv\s+(-[a-zA-Z]+\s+)*\K\S+' 2>/dev/null || true)
68
+ MV_SOURCES=$(echo "$COMMAND" | extract_operand mv)
38
69
  # Get all rm targets
39
- RM_TARGETS=$(echo "$COMMAND" | grep -oP '\brm\s+(-[a-zA-Z]+\s+)*\K\S+' 2>/dev/null || true)
70
+ RM_TARGETS=$(echo "$COMMAND" | extract_operand rm)
40
71
 
41
72
  [ -z "$MV_SOURCES" ] && exit 0
42
73
  [ -z "$RM_TARGETS" ] && exit 0