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.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-circuit-breaker.sh +72 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +89 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/thinking-stall-detector.sh +61 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-circuit-breaker.sh +134 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-exploration-budget-guard.sh +164 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-thinking-stall-detector.sh +151 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# persisted-1m-model-advisor.sh — Warn at SessionStart when a 1M-context model
|
|
3
|
+
# is PINNED in your settings or default-model env vars (the reason /clear and
|
|
4
|
+
# restarts don't reduce your usage)
|
|
5
|
+
#
|
|
6
|
+
# Solves: On Max/Team/Enterprise, Opus runs with a 1M context window. When you
|
|
7
|
+
# pick a 1M variant once (e.g. /model opus[1m]), v2.1.153+ persists it to the
|
|
8
|
+
# `model` field of your settings file, so every new session re-reads it — and a
|
|
9
|
+
# 1M window keeps far more context resident before compaction, so each turn
|
|
10
|
+
# reprocesses more tokens and the weekly/5h limit drains faster. Users report
|
|
11
|
+
# the limit gone in 2-2.5 days (#65678, $200/mo cancelled), "1M credits
|
|
12
|
+
# required" with usage still left (#65283), and /clear / restart not helping
|
|
13
|
+
# (#65283, #65545, #65329) — precisely because the pin lives in a file, not in
|
|
14
|
+
# the conversation.
|
|
15
|
+
#
|
|
16
|
+
# Gap this fills: cowork-model-picker-advisor.sh checks the ANTHROPIC_MODEL env
|
|
17
|
+
# var only; model-version-lock.sh detects a switch AFTER it happens. Neither
|
|
18
|
+
# reads the PERSISTED `model` field in settings.json or the
|
|
19
|
+
# ANTHROPIC_DEFAULT_OPUS_MODEL / ANTHROPIC_DEFAULT_SONNET_MODEL env vars, which
|
|
20
|
+
# are the sticky source `/clear` cannot clear. This hook inspects exactly those
|
|
21
|
+
# and names which one is pinning 1M, with the verified fixes.
|
|
22
|
+
#
|
|
23
|
+
# Honest scope: this is ADVISORY. The automatic 1M upgrade on Max happens
|
|
24
|
+
# platform-side with no tool event, so a hook cannot block that resolution — it
|
|
25
|
+
# can only surface a pin you control and the official off-switch. It never
|
|
26
|
+
# blocks; it only prints once at SessionStart.
|
|
27
|
+
#
|
|
28
|
+
# TRIGGER: SessionStart MATCHER: ""
|
|
29
|
+
# Config:
|
|
30
|
+
# CC_1M_ADVISOR=off disable entirely (default: on)
|
|
31
|
+
# CC_1M_ADVISOR_QUIET=1 stay silent when no 1M pin is found (default: silent anyway)
|
|
32
|
+
# Related: https://github.com/anthropics/claude-code/issues/65678 , #65283
|
|
33
|
+
|
|
34
|
+
[ "${CC_1M_ADVISOR:-on}" = "off" ] && exit 0
|
|
35
|
+
|
|
36
|
+
INPUT=$(cat 2>/dev/null)
|
|
37
|
+
|
|
38
|
+
# Resolve the project dir for project-level settings. Prefer the explicit env,
|
|
39
|
+
# fall back to the SessionStart payload's cwd. Fail open if neither is usable.
|
|
40
|
+
PROJ="${CLAUDE_PROJECT_DIR:-}"
|
|
41
|
+
if [ -z "$PROJ" ]; then
|
|
42
|
+
PROJ=$(printf '%s' "$INPUT" | jq -r '.cwd // empty' 2>/dev/null)
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# Read a settings file's top-level .model field, ignoring parse errors.
|
|
46
|
+
read_model_field() {
|
|
47
|
+
[ -r "$1" ] || return 0
|
|
48
|
+
jq -r '.model // empty' "$1" 2>/dev/null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
hits=""
|
|
52
|
+
|
|
53
|
+
add_hit() {
|
|
54
|
+
# $1 = source label, $2 = value; record only when value ends with [1m]
|
|
55
|
+
case "${2,,}" in
|
|
56
|
+
*'[1m]') hits="${hits} - ${1}: ${2}"$'\n' ;;
|
|
57
|
+
esac
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
add_hit "user settings (~/.claude/settings.json) model" "$(read_model_field "$HOME/.claude/settings.json")"
|
|
61
|
+
add_hit "user settings (settings.local.json) model" "$(read_model_field "$HOME/.claude/settings.local.json")"
|
|
62
|
+
if [ -n "$PROJ" ]; then
|
|
63
|
+
add_hit "project settings (.claude/settings.json) model" "$(read_model_field "$PROJ/.claude/settings.json")"
|
|
64
|
+
add_hit "project settings (.claude/settings.local.json) model" "$(read_model_field "$PROJ/.claude/settings.local.json")"
|
|
65
|
+
fi
|
|
66
|
+
add_hit "env ANTHROPIC_DEFAULT_OPUS_MODEL" "${ANTHROPIC_DEFAULT_OPUS_MODEL:-}"
|
|
67
|
+
add_hit "env ANTHROPIC_DEFAULT_SONNET_MODEL" "${ANTHROPIC_DEFAULT_SONNET_MODEL:-}"
|
|
68
|
+
add_hit "env ANTHROPIC_MODEL" "${ANTHROPIC_MODEL:-}"
|
|
69
|
+
|
|
70
|
+
if [ -z "$hits" ]; then
|
|
71
|
+
# No persisted 1M pin found — stay silent (advisory hooks should not add noise).
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
{
|
|
76
|
+
echo "persisted-1m-model-advisor: a 1M-context model is PINNED in your config:"
|
|
77
|
+
printf '%s' "$hits"
|
|
78
|
+
echo "This persists across /clear and restarts, so it keeps draining your weekly/5h"
|
|
79
|
+
echo "limit faster (a 1M window holds more context before compaction = more tokens"
|
|
80
|
+
echo "reprocessed per turn). To stop it, do any of:"
|
|
81
|
+
echo " - /model <a non-[1m] model> then Enter to save it as the default, or"
|
|
82
|
+
echo " - remove the [1m] suffix from the settings 'model' field / the env var above, or"
|
|
83
|
+
echo " - set CLAUDE_CODE_DISABLE_1M_CONTEXT=1 to remove 1M variants entirely."
|
|
84
|
+
echo "On Max, Opus 1M is included (no premium), so this is about token volume against"
|
|
85
|
+
echo "your limit, not a surcharge. Set CC_1M_ADVISOR=off to silence this notice."
|
|
86
|
+
} >&2
|
|
87
|
+
|
|
88
|
+
exit 0
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
# }
|
|
18
18
|
# ================================================================
|
|
19
19
|
#
|
|
20
|
-
# TRIGGER:
|
|
20
|
+
# TRIGGER: PostToolUse MATCHER: "Edit|Write"
|
|
21
21
|
|
|
22
22
|
INPUT=$(cat)
|
|
23
23
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -15,6 +15,18 @@
|
|
|
15
15
|
|
|
16
16
|
set -euo pipefail
|
|
17
17
|
|
|
18
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
19
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
20
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
21
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
22
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
23
|
+
_nojq_warned="/tmp/cc-nojq-warned-pii-upload-guard-$PPID"
|
|
24
|
+
[ -f "$_nojq_warned" ] || {
|
|
25
|
+
echo "WARNING [pii-upload-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
26
|
+
: > "$_nojq_warned"
|
|
27
|
+
}
|
|
28
|
+
fi
|
|
29
|
+
|
|
18
30
|
INPUT=$(cat)
|
|
19
31
|
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
20
32
|
[ -z "$CMD" ] && exit 0
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
#!/bin/bash
|
|
1
2
|
#
|
|
2
3
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
4
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
5
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
6
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
7
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
8
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
9
|
+
_nojq_warned="/tmp/cc-nojq-warned-pip-publish-guard-$PPID"
|
|
10
|
+
[ -f "$_nojq_warned" ] || {
|
|
11
|
+
echo "WARNING [pip-publish-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
12
|
+
: > "$_nojq_warned"
|
|
13
|
+
}
|
|
14
|
+
fi
|
|
15
|
+
|
|
3
16
|
INPUT=$(cat)
|
|
4
17
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
5
18
|
[[ -z "$COMMAND" ]] && exit 0
|
|
@@ -19,6 +19,18 @@
|
|
|
19
19
|
#
|
|
20
20
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
21
21
|
|
|
22
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
23
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
24
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
25
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
26
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
27
|
+
_nojq_warned="/tmp/cc-nojq-warned-pip-requirements-guard-$PPID"
|
|
28
|
+
[ -f "$_nojq_warned" ] || {
|
|
29
|
+
echo "WARNING [pip-requirements-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
30
|
+
: > "$_nojq_warned"
|
|
31
|
+
}
|
|
32
|
+
fi
|
|
33
|
+
|
|
22
34
|
INPUT=$(cat)
|
|
23
35
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
24
36
|
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
# }
|
|
18
18
|
# }
|
|
19
19
|
|
|
20
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
21
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
22
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
23
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
24
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
25
|
+
_nojq_warned="/tmp/cc-nojq-warned-pip-venv-required-$PPID"
|
|
26
|
+
[ -f "$_nojq_warned" ] || {
|
|
27
|
+
echo "WARNING [pip-venv-required]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
28
|
+
: > "$_nojq_warned"
|
|
29
|
+
}
|
|
30
|
+
fi
|
|
31
|
+
|
|
20
32
|
INPUT=$(cat)
|
|
21
33
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
22
34
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -21,6 +21,18 @@
|
|
|
21
21
|
#
|
|
22
22
|
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
23
23
|
|
|
24
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
25
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
26
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
27
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
28
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
29
|
+
_nojq_warned="/tmp/cc-nojq-warned-plan-mode-edit-guard-$PPID"
|
|
30
|
+
[ -f "$_nojq_warned" ] || {
|
|
31
|
+
echo "WARNING [plan-mode-edit-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
32
|
+
: > "$_nojq_warned"
|
|
33
|
+
}
|
|
34
|
+
fi
|
|
35
|
+
|
|
24
36
|
INPUT=$(cat)
|
|
25
37
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
26
38
|
|
|
@@ -30,6 +30,18 @@
|
|
|
30
30
|
#
|
|
31
31
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
32
32
|
|
|
33
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
34
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
35
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
36
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
37
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
38
|
+
_nojq_warned="/tmp/cc-nojq-warned-plan-mode-enforcer-$PPID"
|
|
39
|
+
[ -f "$_nojq_warned" ] || {
|
|
40
|
+
echo "WARNING [plan-mode-enforcer]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
41
|
+
: > "$_nojq_warned"
|
|
42
|
+
}
|
|
43
|
+
fi
|
|
44
|
+
|
|
33
45
|
STATE_FILE="/tmp/.cc-plan-mode-active"
|
|
34
46
|
[ -f "$STATE_FILE" ] || exit 0
|
|
35
47
|
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
# TRIGGER: PreToolUse
|
|
18
18
|
# MATCHER: "Edit|Write|Bash"
|
|
19
19
|
|
|
20
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
21
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
22
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
23
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
24
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
25
|
+
_nojq_warned="/tmp/cc-nojq-warned-plan-mode-strict-guard-$PPID"
|
|
26
|
+
[ -f "$_nojq_warned" ] || {
|
|
27
|
+
echo "WARNING [plan-mode-strict-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
28
|
+
: > "$_nojq_warned"
|
|
29
|
+
}
|
|
30
|
+
fi
|
|
31
|
+
|
|
20
32
|
INPUT=$(cat)
|
|
21
33
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
22
34
|
[ -z "$TOOL" ] && exit 0
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# plugin-hooks-json-bloat-detector.sh — Detect duplicated hook
|
|
4
|
+
# registrations inside plugin hooks.json files (additive growth
|
|
5
|
+
# from the multi-agent dispatch path).
|
|
6
|
+
# ================================================================
|
|
7
|
+
# PURPOSE:
|
|
8
|
+
# Issue #64022 documents a class where a plugin's
|
|
9
|
+
# `hooks/hooks.json` registrations multiply additively in
|
|
10
|
+
# multi-agent sessions (observed 1× → 122× per hook). At high
|
|
11
|
+
# multiples every hook fires N times per tool call and tool
|
|
12
|
+
# output is corrupted. The reporter's plugin had no additive
|
|
13
|
+
# writer; the only mechanism that fits is the harness re-running
|
|
14
|
+
# its plugin-hook load/merge and appending instead of replacing.
|
|
15
|
+
#
|
|
16
|
+
# The growth is silent until output corruption surfaces it. This
|
|
17
|
+
# hook scans every installed plugin's hooks.json at session
|
|
18
|
+
# start, counts duplicate command-string registrations within
|
|
19
|
+
# each file, and warns when a single command appears more than a
|
|
20
|
+
# threshold (default 5 times) — well below the 122× blowup but
|
|
21
|
+
# well above any legitimate "one event, one command, multiple
|
|
22
|
+
# matchers" registration shape.
|
|
23
|
+
#
|
|
24
|
+
# DETECTION MODEL:
|
|
25
|
+
# SessionStart fires once per session. We walk every
|
|
26
|
+
# `~/.claude/plugins/cache/**/hooks/hooks.json` (plus the canonical
|
|
27
|
+
# `~/.claude/plugins/marketplace/**/hooks/hooks.json` if it exists),
|
|
28
|
+
# parse each JSON, and within each file count how many times each
|
|
29
|
+
# distinct command string appears across all event types. If any
|
|
30
|
+
# command string appears more than CC_PLUGIN_HOOKS_BLOAT_THRESHOLD
|
|
31
|
+
# times in a single hooks.json, emit a warning identifying the
|
|
32
|
+
# plugin path, the command, and the duplicate count.
|
|
33
|
+
#
|
|
34
|
+
# We deliberately ignore the cross-plugin case (the same command
|
|
35
|
+
# appearing in two different plugins is legitimate) and the
|
|
36
|
+
# multi-event case (the same command registered for PreToolUse
|
|
37
|
+
# AND PostToolUse — count each event-bucket separately).
|
|
38
|
+
#
|
|
39
|
+
# CLUSTER:
|
|
40
|
+
# Candidate cluster #21 — Plugin lifecycle integrity gap
|
|
41
|
+
# Sub-axis 21A — additive hook-registration growth (#64022).
|
|
42
|
+
#
|
|
43
|
+
# TRIGGER: SessionStart MATCHER: ""
|
|
44
|
+
#
|
|
45
|
+
# ENV:
|
|
46
|
+
# CC_PLUGIN_HOOKS_BLOAT_THRESHOLD default 5 (warn when same command appears >5×)
|
|
47
|
+
# CC_PLUGIN_HOOKS_BLOAT_DISABLE non-empty → silent
|
|
48
|
+
# CC_PLUGIN_HOOKS_BLOAT_QUIET non-empty → silent
|
|
49
|
+
# CC_PLUGIN_HOOKS_BLOAT_ROOT default $HOME/.claude/plugins
|
|
50
|
+
# CC_PLUGIN_HOOKS_BLOAT_STATE_DIR default /tmp/cc-plugin-hooks-bloat
|
|
51
|
+
# ================================================================
|
|
52
|
+
|
|
53
|
+
set -u
|
|
54
|
+
|
|
55
|
+
# Disable / quiet
|
|
56
|
+
if [ -n "${CC_PLUGIN_HOOKS_BLOAT_DISABLE:-}" ] || [ -n "${CC_PLUGIN_HOOKS_BLOAT_QUIET:-}" ]; then
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
THRESHOLD="${CC_PLUGIN_HOOKS_BLOAT_THRESHOLD:-5}"
|
|
61
|
+
PLUGINS_ROOT="${CC_PLUGIN_HOOKS_BLOAT_ROOT:-$HOME/.claude/plugins}"
|
|
62
|
+
STATE_DIR="${CC_PLUGIN_HOOKS_BLOAT_STATE_DIR:-/tmp/cc-plugin-hooks-bloat}"
|
|
63
|
+
WARN_FILE="$STATE_DIR/last-warn"
|
|
64
|
+
|
|
65
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
66
|
+
|
|
67
|
+
# If plugin root doesn't exist, nothing to scan
|
|
68
|
+
[ -d "$PLUGINS_ROOT" ] || exit 0
|
|
69
|
+
|
|
70
|
+
# Need jq for JSON parsing; fail-soft if missing
|
|
71
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Read input (Claude Code passes session context on stdin; we don't use it for
|
|
76
|
+
# this detector, but consume it so the harness doesn't block).
|
|
77
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
78
|
+
|
|
79
|
+
# Track findings across all plugin hooks.json files
|
|
80
|
+
declare -a FINDINGS=()
|
|
81
|
+
|
|
82
|
+
# Walk every hooks.json under the plugins tree
|
|
83
|
+
while IFS= read -r -d '' HOOKS_FILE; do
|
|
84
|
+
# Skip if not a file (broken symlink etc.)
|
|
85
|
+
[ -f "$HOOKS_FILE" ] || continue
|
|
86
|
+
|
|
87
|
+
# Skip if the file is not valid JSON (fail-soft, do not warn on broken files
|
|
88
|
+
# — those are a separate problem)
|
|
89
|
+
if ! jq -e . "$HOOKS_FILE" >/dev/null 2>&1; then
|
|
90
|
+
continue
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Extract every hook command string, grouped per event-bucket so that the
|
|
94
|
+
# same command legitimately registered for PreToolUse AND PostToolUse
|
|
95
|
+
# doesn't trip the detector. Output format: "<event>\t<command>"
|
|
96
|
+
EVENT_CMDS=$(jq -r '
|
|
97
|
+
(.hooks // {}) | to_entries[] |
|
|
98
|
+
.key as $event |
|
|
99
|
+
(.value // []) | .[] |
|
|
100
|
+
((.hooks // []) | .[]) |
|
|
101
|
+
select(.command != null) |
|
|
102
|
+
($event + "\t" + (.command | tostring))
|
|
103
|
+
' "$HOOKS_FILE" 2>/dev/null) || continue
|
|
104
|
+
|
|
105
|
+
[ -z "$EVENT_CMDS" ] && continue
|
|
106
|
+
|
|
107
|
+
# Count duplicates per event+command pair
|
|
108
|
+
DUPES=$(printf '%s\n' "$EVENT_CMDS" | sort | uniq -c | awk -v t="$THRESHOLD" '$1 > t {print $0}')
|
|
109
|
+
|
|
110
|
+
if [ -n "$DUPES" ]; then
|
|
111
|
+
# Strip the canonical install root prefix for readability in the warning
|
|
112
|
+
DISPLAY_PATH="${HOOKS_FILE#$PLUGINS_ROOT/}"
|
|
113
|
+
FINDINGS+=("$DISPLAY_PATH")
|
|
114
|
+
FINDINGS+=("$DUPES")
|
|
115
|
+
FINDINGS+=("---")
|
|
116
|
+
fi
|
|
117
|
+
done < <(find "$PLUGINS_ROOT" -type f -name 'hooks.json' -path '*/hooks/*' -print0 2>/dev/null)
|
|
118
|
+
|
|
119
|
+
# No findings → silent exit
|
|
120
|
+
if [ "${#FINDINGS[@]}" -eq 0 ]; then
|
|
121
|
+
exit 0
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Debounce: only warn once per hour even if the session restarts repeatedly
|
|
125
|
+
NOW_S=$(date +%s)
|
|
126
|
+
LAST_WARN=0
|
|
127
|
+
if [ -f "$WARN_FILE" ]; then
|
|
128
|
+
LAST_WARN=$(cat "$WARN_FILE" 2>/dev/null || echo 0)
|
|
129
|
+
fi
|
|
130
|
+
HOUR_AGO=$((NOW_S - 3600))
|
|
131
|
+
if [ "$LAST_WARN" -gt "$HOUR_AGO" ] 2>/dev/null; then
|
|
132
|
+
exit 0
|
|
133
|
+
fi
|
|
134
|
+
printf '%s' "$NOW_S" > "$WARN_FILE" 2>/dev/null
|
|
135
|
+
|
|
136
|
+
# Emit advisory warning
|
|
137
|
+
cat >&2 <<EOF
|
|
138
|
+
|
|
139
|
+
⚠️ Plugin hooks.json bloat detected — duplicate hook registrations.
|
|
140
|
+
|
|
141
|
+
One or more installed plugins have a hooks.json file where the same command
|
|
142
|
+
string appears more than ${THRESHOLD} times within a single event bucket.
|
|
143
|
+
This is the fingerprint of the additive growth pattern documented in
|
|
144
|
+
anthropics/claude-code Issue #64022 — the harness's plugin-hook load/merge
|
|
145
|
+
path can re-run and append instead of replacing, causing each hook to fire
|
|
146
|
+
N times per tool call.
|
|
147
|
+
|
|
148
|
+
Findings:
|
|
149
|
+
EOF
|
|
150
|
+
|
|
151
|
+
for line in "${FINDINGS[@]}"; do
|
|
152
|
+
printf ' %s\n' "$line" >&2
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
cat >&2 <<EOF
|
|
156
|
+
|
|
157
|
+
What to do:
|
|
158
|
+
|
|
159
|
+
1. Restore canonical hooks.json from the plugin source (a fresh
|
|
160
|
+
reinstall of the plugin from its canonical marketplace usually works).
|
|
161
|
+
2. If the file regrows after restoration, file the recurrence against
|
|
162
|
+
anthropics/claude-code Issue #64022 with your version and a count.
|
|
163
|
+
3. Lower this hook's threshold if the false-positive rate is acceptable
|
|
164
|
+
for your environment (export CC_PLUGIN_HOOKS_BLOAT_THRESHOLD=3).
|
|
165
|
+
|
|
166
|
+
This warning is advisory. Set CC_PLUGIN_HOOKS_BLOAT_DISABLE=1 to silence.
|
|
167
|
+
EOF
|
|
168
|
+
|
|
169
|
+
exit 0
|
|
File without changes
|
|
@@ -21,6 +21,18 @@
|
|
|
21
21
|
# }
|
|
22
22
|
# }
|
|
23
23
|
|
|
24
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
25
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
26
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
27
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
28
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
29
|
+
_nojq_warned="/tmp/cc-nojq-warned-polyglot-rm-guard-$PPID"
|
|
30
|
+
[ -f "$_nojq_warned" ] || {
|
|
31
|
+
echo "WARNING [polyglot-rm-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
32
|
+
: > "$_nojq_warned"
|
|
33
|
+
}
|
|
34
|
+
fi
|
|
35
|
+
|
|
24
36
|
INPUT=$(cat)
|
|
25
37
|
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
26
38
|
[ -z "$CMD" ] && exit 0
|
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
#
|
|
28
28
|
# Config: CC_POST_COMPACT_GUARD=10 (block for first 10 calls after compact)
|
|
29
29
|
|
|
30
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
31
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
32
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
33
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
34
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
35
|
+
_nojq_warned="/tmp/cc-nojq-warned-post-compact-safety-$PPID"
|
|
36
|
+
[ -f "$_nojq_warned" ] || {
|
|
37
|
+
echo "WARNING [post-compact-safety]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
38
|
+
: > "$_nojq_warned"
|
|
39
|
+
}
|
|
40
|
+
fi
|
|
41
|
+
|
|
30
42
|
INPUT=$(cat)
|
|
31
43
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
32
44
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# post-edit-disk-verify.sh — Catch "Edit/Write reported success but didn't
|
|
3
|
+
# persist to disk" silent failures at the tool boundary.
|
|
4
|
+
#
|
|
5
|
+
# Solves: anthropics/claude-code#61303 — Windows MAX_PATH(260) + isolated
|
|
6
|
+
# worktree + deep nested path yielded an `Edit`/`Write` that reported success
|
|
7
|
+
# in-tool while the filesystem still showed the original content. The agent's
|
|
8
|
+
# `Read` reflected the "edited" state; the disk did not. A defensive
|
|
9
|
+
# verification step inside the dispatched subagent caught it, but the failure
|
|
10
|
+
# mode was invisible until that defensive step fired.
|
|
11
|
+
#
|
|
12
|
+
# The structural class is broader than the MAX_PATH trigger: any condition
|
|
13
|
+
# under which the harness reports a successful write but the on-disk content
|
|
14
|
+
# diverges from the claimed write should be caught at the tool boundary, not
|
|
15
|
+
# at the next session's read.
|
|
16
|
+
#
|
|
17
|
+
# Type: PostToolUse hook on Edit and Write.
|
|
18
|
+
#
|
|
19
|
+
# Decision rule:
|
|
20
|
+
#
|
|
21
|
+
# exit 0 — verification passed, or hook does not apply
|
|
22
|
+
# exit 2 — verification failed; stderr explains why and Claude sees it
|
|
23
|
+
#
|
|
24
|
+
# The hook is intentionally permissive on edge cases (Edit with no content
|
|
25
|
+
# field, ephemeral files, non-regular files) and intentionally strict on the
|
|
26
|
+
# specific divergence shape #61303 names.
|
|
27
|
+
#
|
|
28
|
+
# Configuration env vars:
|
|
29
|
+
#
|
|
30
|
+
# CC_POST_EDIT_VERIFY_DISABLE=1 — skip the hook entirely
|
|
31
|
+
# CC_POST_EDIT_VERIFY_QUIET=1 — exit 0 even on detected divergence,
|
|
32
|
+
# but still write the divergence to
|
|
33
|
+
# ~/.claude/receipts/post-edit-divergence.jsonl
|
|
34
|
+
# for audit (the "observe but don't gate"
|
|
35
|
+
# mode useful for first-week deployment)
|
|
36
|
+
|
|
37
|
+
set -u
|
|
38
|
+
|
|
39
|
+
# Read tool input from stdin (Claude Code passes a JSON envelope).
|
|
40
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
41
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
42
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
43
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
44
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
45
|
+
_nojq_warned="/tmp/cc-nojq-warned-post-edit-disk-verify-$PPID"
|
|
46
|
+
[ -f "$_nojq_warned" ] || {
|
|
47
|
+
echo "WARNING [post-edit-disk-verify]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
48
|
+
: > "$_nojq_warned"
|
|
49
|
+
}
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
INPUT=$(cat)
|
|
53
|
+
|
|
54
|
+
TOOL=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
55
|
+
[[ -z "$TOOL" ]] && exit 0
|
|
56
|
+
[[ "$TOOL" != "Edit" && "$TOOL" != "Write" ]] && exit 0
|
|
57
|
+
|
|
58
|
+
# Honor the global disable.
|
|
59
|
+
[[ "${CC_POST_EDIT_VERIFY_DISABLE:-0}" == "1" ]] && exit 0
|
|
60
|
+
|
|
61
|
+
FILE=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty' 2>/dev/null)
|
|
62
|
+
[[ -z "$FILE" ]] && exit 0
|
|
63
|
+
|
|
64
|
+
# Helper: append a divergence record to the receipt log.
|
|
65
|
+
# Defined before first use — the missing-after-write path below calls it.
|
|
66
|
+
_record_divergence() {
|
|
67
|
+
local file="$1"
|
|
68
|
+
local tool="$2"
|
|
69
|
+
local kind="$3"
|
|
70
|
+
local msg="$4"
|
|
71
|
+
local dir="${CC_POST_EDIT_VERIFY_RECEIPT_DIR:-$HOME/.claude/receipts}"
|
|
72
|
+
mkdir -p "$dir" 2>/dev/null || return 0
|
|
73
|
+
local ts
|
|
74
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
75
|
+
# The missing-after-write path calls this for a file that does not exist,
|
|
76
|
+
# so guard the redirection to avoid a leaked "No such file" shell error.
|
|
77
|
+
local file_size=0
|
|
78
|
+
[ -f "$file" ] && file_size=$(wc -c < "$file" 2>/dev/null || echo 0)
|
|
79
|
+
printf '{"ts":"%s","tool":"%s","file":"%s","kind":"%s","file_size":%s}\n' \
|
|
80
|
+
"$ts" "$tool" "$file" "$kind" "$file_size" \
|
|
81
|
+
>> "$dir/post-edit-divergence.jsonl" 2>/dev/null || true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# File must exist (Write may have created it; Edit always operates on existing).
|
|
85
|
+
[[ ! -e "$FILE" ]] && {
|
|
86
|
+
# If the tool reported success on a Write to a path that doesn't exist
|
|
87
|
+
# post-call, that is itself a divergence.
|
|
88
|
+
if [[ "$TOOL" == "Write" ]]; then
|
|
89
|
+
msg="post-edit-disk-verify: $TOOL claimed success on $FILE but file does not exist on disk (silent fail-to-persist; see anthropics/claude-code#61303)"
|
|
90
|
+
_record_divergence "$FILE" "$TOOL" "missing-after-write" "$msg"
|
|
91
|
+
if [[ "${CC_POST_EDIT_VERIFY_QUIET:-0}" != "1" ]]; then
|
|
92
|
+
echo "$msg" >&2
|
|
93
|
+
exit 2
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
96
|
+
exit 0
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Regular file only (skip symlinks, sockets, devices).
|
|
100
|
+
[[ ! -f "$FILE" ]] && exit 0
|
|
101
|
+
|
|
102
|
+
# --- Check 1: Write with claimed content vs actual on-disk size ---
|
|
103
|
+
# If a Write claimed N bytes but disk shows much less, that is the
|
|
104
|
+
# strongest single signal of silent fail-to-persist.
|
|
105
|
+
if [[ "$TOOL" == "Write" ]]; then
|
|
106
|
+
CLAIMED=$(printf '%s' "$INPUT" | jq -r '.tool_input.content // ""' 2>/dev/null)
|
|
107
|
+
CLAIMED_LEN=${#CLAIMED}
|
|
108
|
+
ACTUAL_LEN=$(wc -c < "$FILE" 2>/dev/null || echo 0)
|
|
109
|
+
|
|
110
|
+
# Only fire when claimed content is non-trivial (avoid empty-write false positives).
|
|
111
|
+
if [[ "$CLAIMED_LEN" -gt 100 ]]; then
|
|
112
|
+
# Allow up to 2x slack for CRLF / encoding / final newline differences,
|
|
113
|
+
# but a >50% shortfall is highly suggestive of fail-to-persist.
|
|
114
|
+
if [[ "$ACTUAL_LEN" -lt $((CLAIMED_LEN / 2)) ]]; then
|
|
115
|
+
msg="post-edit-disk-verify: Write to $FILE claimed $CLAIMED_LEN bytes but disk shows $ACTUAL_LEN bytes (>50% shortfall — likely silent fail-to-persist per anthropics/claude-code#61303). Check Windows MAX_PATH (260) on Windows, deep worktrees, or filesystem encoding."
|
|
116
|
+
_record_divergence "$FILE" "$TOOL" "size-shortfall" "$msg"
|
|
117
|
+
if [[ "${CC_POST_EDIT_VERIFY_QUIET:-0}" != "1" ]]; then
|
|
118
|
+
echo "$msg" >&2
|
|
119
|
+
exit 2
|
|
120
|
+
fi
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# --- Check 2: Edit with no diff in git ---
|
|
126
|
+
# If an Edit reported success on a git-tracked file and produces no diff,
|
|
127
|
+
# either the Edit was a no-op (legitimate) or the change failed to persist.
|
|
128
|
+
# The hook treats a "claimed-non-trivial Edit with no diff" as the latter.
|
|
129
|
+
if [[ "$TOOL" == "Edit" ]]; then
|
|
130
|
+
NEW=$(printf '%s' "$INPUT" | jq -r '.tool_input.new_string // ""' 2>/dev/null)
|
|
131
|
+
OLD=$(printf '%s' "$INPUT" | jq -r '.tool_input.old_string // ""' 2>/dev/null)
|
|
132
|
+
|
|
133
|
+
# Only check if old_string != new_string (a real claimed change).
|
|
134
|
+
if [[ -n "$NEW" && "$NEW" != "$OLD" ]]; then
|
|
135
|
+
# Find git root for the file's directory.
|
|
136
|
+
FILE_DIR=$(dirname "$FILE")
|
|
137
|
+
if git -C "$FILE_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
138
|
+
# File is in a git repo. Check whether the new_string appears in
|
|
139
|
+
# the on-disk content. If not, the Edit did not persist.
|
|
140
|
+
if ! grep -F -q -- "$NEW" "$FILE" 2>/dev/null; then
|
|
141
|
+
msg="post-edit-disk-verify: Edit on $FILE claimed to insert content that is not found in the on-disk file (silent fail-to-persist per anthropics/claude-code#61303). Either the Edit did not land, or in-tool Read is showing stale-cached content."
|
|
142
|
+
_record_divergence "$FILE" "$TOOL" "edit-not-in-file" "$msg"
|
|
143
|
+
if [[ "${CC_POST_EDIT_VERIFY_QUIET:-0}" != "1" ]]; then
|
|
144
|
+
echo "$msg" >&2
|
|
145
|
+
exit 2
|
|
146
|
+
fi
|
|
147
|
+
fi
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
exit 0
|