cc-safe-setup 29.8.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-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 +12 -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/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-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-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-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,90 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# tokenizer-ratio-alert-corpus.sh — 個人 corpus の input_tokens/character_count 比率 drift を検知 (PostToolUse rolling baseline 方式)
|
|
3
|
+
# 関連: examples/tokenizer-ratio-alert.sh は同名異設計の PreToolUse + Anthropic API count_tokens 経由版 (Postmortems Incident 5)
|
|
4
|
+
# Why: Anthropic がトークナイザーを silent に変更 (#46829 関連、Opus 4.7 で 1.35-1.46× インフレ実測 Simon Willison 2026-04-20)。
|
|
5
|
+
# 個人の corpus に対し input_tokens / character_count を 7日 rolling baseline と比較、
|
|
6
|
+
# 1.25× threshold を 3 連続 session で超えたら alert。
|
|
7
|
+
# Migration Playbook Chapter 4 (Path A Stay-and-Fortify) Hook 6 specification 実装。
|
|
8
|
+
# Event: PostToolUse MATCHER: ""
|
|
9
|
+
# Action: 各 turn の input_tokens を log、baseline drift 検知時に stderr alert (non-blocking)
|
|
10
|
+
#
|
|
11
|
+
# The registration was missing from this header. The installer reads TRIGGER
|
|
12
|
+
# and MATCHER from here and falls back to PreToolUse / Bash when both are
|
|
13
|
+
# absent, so this hook was being registered at a moment where the field it
|
|
14
|
+
# reads is always empty: it installed, it appeared in the settings, and it
|
|
15
|
+
# did nothing. Measured 2026-08-04 across examples/: 14 files were like this.
|
|
16
|
+
# TRIGGER: PostToolUse
|
|
17
|
+
# MATCHER: ""
|
|
18
|
+
|
|
19
|
+
HISTORY="/tmp/cc-tokenizer-ratio-history"
|
|
20
|
+
SESSION_FLAG="/tmp/cc-tokenizer-ratio-session"
|
|
21
|
+
TODAY=$(date +%Y-%m-%d)
|
|
22
|
+
|
|
23
|
+
# stdin から JSON を取得 (Claude Code PostToolUse hook input)
|
|
24
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
25
|
+
|
|
26
|
+
# tool_input から approximate character count を計算 (text-like fields の長さ合計)
|
|
27
|
+
CHARS=$(echo "$INPUT" | jq -r '
|
|
28
|
+
.tool_input // {} |
|
|
29
|
+
[.. | strings] |
|
|
30
|
+
map(length) |
|
|
31
|
+
add // 0
|
|
32
|
+
' 2>/dev/null)
|
|
33
|
+
|
|
34
|
+
# tool_response から input_tokens を取得 (利用可能な場合)
|
|
35
|
+
TOKENS=$(echo "$INPUT" | jq -r '
|
|
36
|
+
.tool_response // {} |
|
|
37
|
+
.usage.input_tokens //
|
|
38
|
+
.input_tokens //
|
|
39
|
+
0
|
|
40
|
+
' 2>/dev/null)
|
|
41
|
+
|
|
42
|
+
# どちらかが 0 なら処理中断 (signal 不足、log 汚染防止)
|
|
43
|
+
[ -z "$CHARS" ] || [ "$CHARS" = "0" ] && exit 0
|
|
44
|
+
[ -z "$TOKENS" ] || [ "$TOKENS" = "0" ] && exit 0
|
|
45
|
+
|
|
46
|
+
# 比率計算 (tokens / chars)
|
|
47
|
+
RATIO=$(awk "BEGIN { printf \"%.4f\", $TOKENS / $CHARS }")
|
|
48
|
+
|
|
49
|
+
# log: timestamp|date|tokens|chars|ratio
|
|
50
|
+
echo "$(date +%s)|$TODAY|$TOKENS|$CHARS|$RATIO" >> "$HISTORY"
|
|
51
|
+
|
|
52
|
+
# 7日 rolling baseline 計算 (8日以上前は除外、POSIX awk safe で mean 採用)
|
|
53
|
+
SEVEN_DAYS_AGO=$(date -d "7 days ago" +%s 2>/dev/null || date -v-7d +%s 2>/dev/null)
|
|
54
|
+
[ -z "$SEVEN_DAYS_AGO" ] && exit 0
|
|
55
|
+
|
|
56
|
+
BASELINE=$(awk -F'|' -v cutoff="$SEVEN_DAYS_AGO" '
|
|
57
|
+
$1 >= cutoff { sum += $5; n++ }
|
|
58
|
+
END {
|
|
59
|
+
if (n < 50) exit 1 # baseline 未確立 (50 turn 未満)
|
|
60
|
+
print sum / n
|
|
61
|
+
}
|
|
62
|
+
' "$HISTORY" 2>/dev/null)
|
|
63
|
+
|
|
64
|
+
# baseline 未確立時は exit (50 turn 蓄積待ち、blocking なし)
|
|
65
|
+
[ -z "$BASELINE" ] && exit 0
|
|
66
|
+
|
|
67
|
+
# 1.25× threshold チェック
|
|
68
|
+
THRESHOLD=$(awk "BEGIN { printf \"%.4f\", $BASELINE * 1.25 }")
|
|
69
|
+
EXCEEDS=$(awk "BEGIN { print ($RATIO > $THRESHOLD) ? 1 : 0 }")
|
|
70
|
+
|
|
71
|
+
# 3 連続 session 超過判定
|
|
72
|
+
SESSION_ID="${CLAUDE_SESSION_ID:-default}"
|
|
73
|
+
LAST_SESSION=$(head -1 "$SESSION_FLAG" 2>/dev/null | cut -d'|' -f1)
|
|
74
|
+
EXCEED_COUNT=$(head -1 "$SESSION_FLAG" 2>/dev/null | cut -d'|' -f2)
|
|
75
|
+
EXCEED_COUNT=${EXCEED_COUNT:-0}
|
|
76
|
+
|
|
77
|
+
if [ "$EXCEEDS" = "1" ]; then
|
|
78
|
+
if [ "$LAST_SESSION" != "$SESSION_ID" ]; then
|
|
79
|
+
EXCEED_COUNT=$((EXCEED_COUNT + 1))
|
|
80
|
+
echo "$SESSION_ID|$EXCEED_COUNT" > "$SESSION_FLAG"
|
|
81
|
+
fi
|
|
82
|
+
if [ "$EXCEED_COUNT" -ge 3 ]; then
|
|
83
|
+
echo "[tokenizer-ratio-alert-corpus] tokens/chars ratio ${RATIO} exceeds 1.25x baseline (${BASELINE}) for ${EXCEED_COUNT} consecutive sessions. Tokenizer may have shifted (Issue #46829 / Opus 4.7 inflation pattern). Review your /usage --json output." >&2
|
|
84
|
+
fi
|
|
85
|
+
else
|
|
86
|
+
# 比率正常 = 連続カウンタ reset
|
|
87
|
+
echo "$SESSION_ID|0" > "$SESSION_FLAG"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
exit 0
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# tokenizer-ratio-alert.sh — Opus 4.7 tokenizer inflation monitor (Incident 5)
|
|
3
|
+
# Why: Opus 4.7 encodes the same prompt 1.35-1.46x larger than Opus 4.6
|
|
4
|
+
# (Anthropic stated ceiling 1.35, Simon Willison independent verification
|
|
5
|
+
# 1.46 for system prompts). If you have pinned 4.6 but want to verify
|
|
6
|
+
# token accounting is actually on 4.6, this hook measures the ratio by
|
|
7
|
+
# calling the count_tokens endpoint against both models and alerts when
|
|
8
|
+
# the observed ratio exceeds a threshold.
|
|
9
|
+
# Event: PreToolUse MATCHER: "*" (filter inside for model-bound turns)
|
|
10
|
+
# Action: When the incoming tool call is a large enough user turn,
|
|
11
|
+
# compute count_tokens(4.6) and count_tokens(4.7) via the Anthropic
|
|
12
|
+
# API and emit a stderr alert if ratio > TOKENIZER_RATIO_THRESHOLD.
|
|
13
|
+
#
|
|
14
|
+
# Runtime cost: two network calls per eligible turn (tens to hundreds of ms).
|
|
15
|
+
# This is the most expensive hook in the catalog. Enable only while actively
|
|
16
|
+
# investigating an incident, then disable.
|
|
17
|
+
#
|
|
18
|
+
# Environment:
|
|
19
|
+
# ANTHROPIC_API_KEY required for real count_tokens calls
|
|
20
|
+
# TOKENIZER_RATIO_THRESHOLD ratio above which to alert (default 1.40)
|
|
21
|
+
# TOKENIZER_MIN_PROMPT_TOKENS skip measurement for prompts below this
|
|
22
|
+
# many characters / 4 ≈ tokens (default 500)
|
|
23
|
+
# TOKENIZER_RATIO_ENDPOINT override API base URL (for tests)
|
|
24
|
+
# TOKENIZER_RATIO_MODEL_OLD (default claude-opus-4-6)
|
|
25
|
+
# TOKENIZER_RATIO_MODEL_NEW (default claude-opus-4-7)
|
|
26
|
+
#
|
|
27
|
+
# The registration was missing from this header. The installer reads TRIGGER
|
|
28
|
+
# and MATCHER from here and falls back to PreToolUse / Bash when both are
|
|
29
|
+
# absent, so this hook was being registered at a moment where the field it
|
|
30
|
+
# reads is always empty: it installed, it appeared in the settings, and it
|
|
31
|
+
# did nothing. Measured 2026-08-04 across examples/: 14 files were like this.
|
|
32
|
+
# TRIGGER: UserPromptSubmit
|
|
33
|
+
# MATCHER: ""
|
|
34
|
+
|
|
35
|
+
set -u
|
|
36
|
+
|
|
37
|
+
THRESHOLD="${TOKENIZER_RATIO_THRESHOLD:-1.40}"
|
|
38
|
+
MIN_CHARS="${TOKENIZER_MIN_PROMPT_TOKENS:-500}" # used as char cutoff, not true tokens
|
|
39
|
+
MIN_CHARS=$((MIN_CHARS * 4)) # 1 token ≈ 4 chars for quick filter
|
|
40
|
+
ENDPOINT="${TOKENIZER_RATIO_ENDPOINT:-https://api.anthropic.com}"
|
|
41
|
+
MODEL_OLD="${TOKENIZER_RATIO_MODEL_OLD:-claude-opus-4-6}"
|
|
42
|
+
MODEL_NEW="${TOKENIZER_RATIO_MODEL_NEW:-claude-opus-4-7}"
|
|
43
|
+
|
|
44
|
+
INPUT=$(cat)
|
|
45
|
+
|
|
46
|
+
# Extract prompt text. For a conversation-bound tool invocation, the most
|
|
47
|
+
# recent user turn's text is a reasonable proxy for "what the model just
|
|
48
|
+
# paid to encode."
|
|
49
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
50
|
+
PROMPT=""
|
|
51
|
+
if [ -n "$TRANSCRIPT" ] && [ -r "$TRANSCRIPT" ]; then
|
|
52
|
+
PROMPT=$(tac "$TRANSCRIPT" 2>/dev/null \
|
|
53
|
+
| grep -m1 '"role":"user"' \
|
|
54
|
+
| jq -r '.message.content[0].text // .message.content // .content // empty' 2>/dev/null)
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Fallback to direct prompt-like field on the payload (for tests and
|
|
58
|
+
# unusual tools that carry the turn text inline).
|
|
59
|
+
if [ -z "$PROMPT" ]; then
|
|
60
|
+
PROMPT=$(printf '%s' "$INPUT" | jq -r '.tool_input.prompt // .tool_input.text // empty' 2>/dev/null)
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
[ -z "$PROMPT" ] && exit 0
|
|
64
|
+
|
|
65
|
+
LEN=${#PROMPT}
|
|
66
|
+
if [ "$LEN" -lt "$MIN_CHARS" ]; then
|
|
67
|
+
exit 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [ -z "${ANTHROPIC_API_KEY:-}" ]; then
|
|
71
|
+
echo "tokenizer-ratio-alert: ANTHROPIC_API_KEY not set, skipping (hook is a no-op)" >&2
|
|
72
|
+
exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
count_tokens() {
|
|
76
|
+
local model="$1"
|
|
77
|
+
local body
|
|
78
|
+
body=$(jq -n --arg model "$model" --arg text "$PROMPT" \
|
|
79
|
+
'{model: $model, messages: [{role: "user", content: $text}]}')
|
|
80
|
+
curl -s --max-time 10 -X POST "$ENDPOINT/v1/messages/count_tokens" \
|
|
81
|
+
-H "x-api-key: $ANTHROPIC_API_KEY" \
|
|
82
|
+
-H "anthropic-version: 2023-06-01" \
|
|
83
|
+
-H "content-type: application/json" \
|
|
84
|
+
-d "$body" 2>/dev/null \
|
|
85
|
+
| jq -r '.input_tokens // empty' 2>/dev/null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
OLD=$(count_tokens "$MODEL_OLD")
|
|
89
|
+
NEW=$(count_tokens "$MODEL_NEW")
|
|
90
|
+
|
|
91
|
+
if [ -z "$OLD" ] || [ -z "$NEW" ] || [ "$OLD" -eq 0 ] 2>/dev/null; then
|
|
92
|
+
exit 0
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
# Compute ratio as floating-point via awk (no bc dependency).
|
|
96
|
+
RATIO=$(awk -v n="$NEW" -v o="$OLD" 'BEGIN { if (o > 0) printf "%.4f", n/o; else print "0" }')
|
|
97
|
+
EXCEEDS=$(awk -v r="$RATIO" -v t="$THRESHOLD" 'BEGIN { print (r > t) ? 1 : 0 }')
|
|
98
|
+
|
|
99
|
+
if [ "$EXCEEDS" = "1" ]; then
|
|
100
|
+
echo "⚠ tokenizer-ratio-alert: $MODEL_NEW=$NEW tokens vs $MODEL_OLD=$OLD tokens (ratio ${RATIO}, threshold ${THRESHOLD})" >&2
|
|
101
|
+
echo " Opus 4.7 tokenizer encodes this prompt larger than 4.6 by more than the expected 1.35x ceiling." >&2
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
exit 0
|
|
File without changes
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# tool-result-correlation-checker.sh — Detect tool-result misattribution
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# When Claude Code dispatches parallel tool calls in a single
|
|
7
|
+
# assistant turn, the harness must correlate each `tool_use_id`
|
|
8
|
+
# to exactly one `tool_result` block with the same id. Issue
|
|
9
|
+
# #64095 documents a failure mode where this correlation breaks:
|
|
10
|
+
#
|
|
11
|
+
# - A `Skill(...)` call returned, as its results, the outputs
|
|
12
|
+
# of unrelated calls from earlier turns (multiple `Read`s,
|
|
13
|
+
# four `TaskCreate`s, and an `Agent` dispatch).
|
|
14
|
+
#
|
|
15
|
+
# This is qualitatively different from cluster 20's cancellation
|
|
16
|
+
# cascade (#64047 / #64052 / #64059) — those produce cancelled
|
|
17
|
+
# batches, this produces *misrouted* results that the model
|
|
18
|
+
# reasons against as if they were the genuine output of the call
|
|
19
|
+
# it actually issued. The model then composes downstream replies
|
|
20
|
+
# from invented observations.
|
|
21
|
+
#
|
|
22
|
+
# This hook scans the recent transcript for `tool_use_id` ↔
|
|
23
|
+
# `tool_result` pairing mismatches and surfaces them on stderr.
|
|
24
|
+
# It does NOT prevent misrouting (the routing happens upstream
|
|
25
|
+
# in the harness) — it surfaces the symptom so operators can
|
|
26
|
+
# recognize when the model's tool-output claims may be reasoning
|
|
27
|
+
# against misrouted data.
|
|
28
|
+
#
|
|
29
|
+
# CLUSTER:
|
|
30
|
+
# Candidate cluster #22 axis 22B (parallel-batch fabrication
|
|
31
|
+
# compounding) — Opus 4.8 pre-execution tool-output fabrication
|
|
32
|
+
# surfaces 6+ filings in 48 hours (#64048 / #64055 / #64065 /
|
|
33
|
+
# #64076 / #64095 / #64103 / #64118), with #64095 specifically
|
|
34
|
+
# documenting envelope leak + out-of-order misattribution.
|
|
35
|
+
#
|
|
36
|
+
# Also addresses cluster 20 axis 20B (cancellation message
|
|
37
|
+
# indistinguishability) when a cancelled call's slot is filled
|
|
38
|
+
# by a routed-elsewhere result from another batch.
|
|
39
|
+
#
|
|
40
|
+
# TRIGGER: PostToolUse MATCHER: ""
|
|
41
|
+
#
|
|
42
|
+
# ENV:
|
|
43
|
+
# CC_TOOL_CORRELATION_THRESHOLD default 1 (warn on first mismatch)
|
|
44
|
+
# CC_TOOL_CORRELATION_WINDOW_SEC default 60 (per-batch window)
|
|
45
|
+
# CC_TOOL_CORRELATION_DISABLE non-empty → silent
|
|
46
|
+
# CC_TOOL_CORRELATION_QUIET non-empty → silent
|
|
47
|
+
# CC_TOOL_CORRELATION_STATE_DIR default /tmp/cc-tool-correlation
|
|
48
|
+
# CC_TOOL_CORRELATION_TRANSCRIPT override transcript path (test-only)
|
|
49
|
+
# ================================================================
|
|
50
|
+
|
|
51
|
+
set -u
|
|
52
|
+
|
|
53
|
+
# Disable / quiet
|
|
54
|
+
if [ -n "${CC_TOOL_CORRELATION_DISABLE:-}" ] || [ -n "${CC_TOOL_CORRELATION_QUIET:-}" ]; then
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
THRESHOLD="${CC_TOOL_CORRELATION_THRESHOLD:-1}"
|
|
59
|
+
WINDOW_SEC="${CC_TOOL_CORRELATION_WINDOW_SEC:-60}"
|
|
60
|
+
STATE_DIR="${CC_TOOL_CORRELATION_STATE_DIR:-/tmp/cc-tool-correlation}"
|
|
61
|
+
LOG_FILE="$STATE_DIR/events.log"
|
|
62
|
+
|
|
63
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
64
|
+
|
|
65
|
+
INPUT=$(cat)
|
|
66
|
+
|
|
67
|
+
# Locate transcript: prefer env override (for tests), else parse from input
|
|
68
|
+
TRANSCRIPT="${CC_TOOL_CORRELATION_TRANSCRIPT:-}"
|
|
69
|
+
if [ -z "$TRANSCRIPT" ]; then
|
|
70
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# If no transcript, nothing to check
|
|
74
|
+
[ -z "$TRANSCRIPT" ] && exit 0
|
|
75
|
+
[ ! -r "$TRANSCRIPT" ] && exit 0
|
|
76
|
+
|
|
77
|
+
# Extract the most recent assistant turn's tool_use blocks and the
|
|
78
|
+
# corresponding user turn's tool_result blocks. We check the last
|
|
79
|
+
# ~30 lines of transcript (enough for one assistant→user round-trip
|
|
80
|
+
# even with large parallel batches).
|
|
81
|
+
RECENT_LINES=$(tail -n 30 "$TRANSCRIPT" 2>/dev/null)
|
|
82
|
+
[ -z "$RECENT_LINES" ] && exit 0
|
|
83
|
+
|
|
84
|
+
# Collect tool_use_ids from the most recent assistant turn (newest first)
|
|
85
|
+
# and tool_result tool_use_ids from the user turn that should answer them.
|
|
86
|
+
# Format: one id per line.
|
|
87
|
+
USE_IDS=$(printf '%s\n' "$RECENT_LINES" | jq -rR '
|
|
88
|
+
fromjson? |
|
|
89
|
+
select(.type == "assistant") |
|
|
90
|
+
.message.content[]? |
|
|
91
|
+
select(.type == "tool_use") |
|
|
92
|
+
.id
|
|
93
|
+
' 2>/dev/null)
|
|
94
|
+
|
|
95
|
+
RESULT_IDS=$(printf '%s\n' "$RECENT_LINES" | jq -rR '
|
|
96
|
+
fromjson? |
|
|
97
|
+
select(.type == "user") |
|
|
98
|
+
.message.content[]? |
|
|
99
|
+
select(.type == "tool_result") |
|
|
100
|
+
.tool_use_id
|
|
101
|
+
' 2>/dev/null)
|
|
102
|
+
|
|
103
|
+
# If either list is empty, no batch to correlate
|
|
104
|
+
[ -z "$USE_IDS" ] && exit 0
|
|
105
|
+
[ -z "$RESULT_IDS" ] && exit 0
|
|
106
|
+
|
|
107
|
+
# Count tool_use ids and tool_result ids; mismatch indicates either:
|
|
108
|
+
# (a) duplicate result for one id (envelope leak)
|
|
109
|
+
# (b) result for an id never used (misrouting from earlier turn)
|
|
110
|
+
# (c) missing result for a used id (lost result)
|
|
111
|
+
USE_COUNT=$(printf '%s\n' "$USE_IDS" | grep -c . || true)
|
|
112
|
+
RESULT_COUNT=$(printf '%s\n' "$RESULT_IDS" | grep -c . || true)
|
|
113
|
+
|
|
114
|
+
# Check for results without matching uses (misrouting signal)
|
|
115
|
+
ORPHAN_RESULTS=$(comm -13 <(printf '%s\n' "$USE_IDS" | sort -u) <(printf '%s\n' "$RESULT_IDS" | sort -u) | grep -c . || true)
|
|
116
|
+
|
|
117
|
+
# Check for duplicate result ids (envelope leak signal)
|
|
118
|
+
DUP_RESULTS=$(printf '%s\n' "$RESULT_IDS" | sort | uniq -d | grep -c . || true)
|
|
119
|
+
|
|
120
|
+
# Mismatch detected if either:
|
|
121
|
+
# - there are orphan results (results without matching uses), OR
|
|
122
|
+
# - there are duplicate result ids
|
|
123
|
+
MISMATCH=0
|
|
124
|
+
if [ "${ORPHAN_RESULTS:-0}" -gt 0 ] || [ "${DUP_RESULTS:-0}" -gt 0 ]; then
|
|
125
|
+
MISMATCH=1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
# Record event and check rolling-window count
|
|
129
|
+
if [ "$MISMATCH" -eq 1 ]; then
|
|
130
|
+
NOW=$(date +%s)
|
|
131
|
+
printf '%s\n' "$NOW" >> "$LOG_FILE"
|
|
132
|
+
|
|
133
|
+
# Prune old events and count
|
|
134
|
+
CUTOFF=$((NOW - WINDOW_SEC))
|
|
135
|
+
COUNT=0
|
|
136
|
+
TMP_LOG=$(mktemp)
|
|
137
|
+
while IFS= read -r ts; do
|
|
138
|
+
if [ "${ts:-0}" -ge "$CUTOFF" ]; then
|
|
139
|
+
printf '%s\n' "$ts" >> "$TMP_LOG"
|
|
140
|
+
COUNT=$((COUNT + 1))
|
|
141
|
+
fi
|
|
142
|
+
done < "$LOG_FILE"
|
|
143
|
+
mv "$TMP_LOG" "$LOG_FILE"
|
|
144
|
+
|
|
145
|
+
# Warn if threshold crossed
|
|
146
|
+
if [ "$COUNT" -ge "$THRESHOLD" ]; then
|
|
147
|
+
cat >&2 <<EOF
|
|
148
|
+
⚠️ tool-result correlation mismatch detected ($COUNT in last ${WINDOW_SEC}s)
|
|
149
|
+
Recent batch: $USE_COUNT tool_use, $RESULT_COUNT tool_result
|
|
150
|
+
Orphan results (no matching use): $ORPHAN_RESULTS
|
|
151
|
+
Duplicate result ids (envelope leak): $DUP_RESULTS
|
|
152
|
+
|
|
153
|
+
This is the symptom shape of cluster #22 axis 22B
|
|
154
|
+
(Opus 4.8 misrouted tool-result envelopes) per Issue #64095.
|
|
155
|
+
|
|
156
|
+
Operator action: do NOT trust the model's "I executed X" claims
|
|
157
|
+
from this turn — re-verify any tool-output values manually.
|
|
158
|
+
Consider switching to /model claude-opus-4-7 and dropping to
|
|
159
|
+
single sequential tool calls for the next critical step.
|
|
160
|
+
|
|
161
|
+
See: https://github.com/yurukusa/cc-safe-setup/blob/main/docs/cluster-tracker.html#cluster-22
|
|
162
|
+
Silence: export CC_TOOL_CORRELATION_QUIET=1
|
|
163
|
+
EOF
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
exit 0
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# tool-result-size-guard.sh — Block or warn on Bash commands likely to produce oversized output
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Many Bash patterns produce unbounded or very large output even on small
|
|
7
|
+
# inputs: `find /` (root scan), `ls -R` (recursive ls), `tail -f`
|
|
8
|
+
# (streaming, never returns), `dmesg`, `journalctl` without -n,
|
|
9
|
+
# `git log` without -n / --oneline, `npm ls -a` / `pip list` without
|
|
10
|
+
# filter, `docker logs` without --tail. These burn Claude Code quota
|
|
11
|
+
# fast — a single such call can consume several percent of the monthly
|
|
12
|
+
# allowance on the Max $200 plan.
|
|
13
|
+
#
|
|
14
|
+
# This hook detects such patterns BEFORE the command runs (PreToolUse)
|
|
15
|
+
# and warns with a specific safer alternative. Set CC_TOOL_RESULT_BLOCK=1
|
|
16
|
+
# to upgrade warning to a hard block.
|
|
17
|
+
#
|
|
18
|
+
# Companion to large-read-guard.sh (which checks specific file sizes)
|
|
19
|
+
# and output-explosion-detector.sh (which warns AFTER the burn happened).
|
|
20
|
+
# This hook prevents the burn upfront.
|
|
21
|
+
#
|
|
22
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
23
|
+
#
|
|
24
|
+
# CONFIG:
|
|
25
|
+
# CC_TOOL_RESULT_BLOCK=0 (default: warn only; set 1 to block)
|
|
26
|
+
# CC_TOOL_RESULT_GUARD_SKIP= (comma-separated patterns to skip, e.g. "find,ls")
|
|
27
|
+
# ================================================================
|
|
28
|
+
|
|
29
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
30
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
31
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
32
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
33
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
34
|
+
_nojq_warned="/tmp/cc-nojq-warned-tool-result-size-guard-$PPID"
|
|
35
|
+
[ -f "$_nojq_warned" ] || {
|
|
36
|
+
echo "WARNING [tool-result-size-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
37
|
+
: > "$_nojq_warned"
|
|
38
|
+
}
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
INPUT=$(cat)
|
|
42
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
43
|
+
[ -z "$COMMAND" ] && exit 0
|
|
44
|
+
|
|
45
|
+
BLOCK_MODE="${CC_TOOL_RESULT_BLOCK:-0}"
|
|
46
|
+
SKIP_PATTERNS="${CC_TOOL_RESULT_GUARD_SKIP:-}"
|
|
47
|
+
|
|
48
|
+
# Helper: emit warning or block based on mode
|
|
49
|
+
# Args: <id> <description> <suggested-alternative>
|
|
50
|
+
emit() {
|
|
51
|
+
local id="$1" pattern="$2" suggest="$3"
|
|
52
|
+
# Skip if user explicitly opted out of this id (comma-separated)
|
|
53
|
+
if [ -n "$SKIP_PATTERNS" ] && echo "$SKIP_PATTERNS" | tr ',' '\n' | grep -qx "$id"; then
|
|
54
|
+
return 0
|
|
55
|
+
fi
|
|
56
|
+
if [ "$BLOCK_MODE" = "1" ]; then
|
|
57
|
+
echo "BLOCKED by tool-result-size-guard: $pattern is likely to produce oversized output." >&2
|
|
58
|
+
echo "Safer alternative: $suggest" >&2
|
|
59
|
+
echo "To override for this session: unset CC_TOOL_RESULT_BLOCK or set CC_TOOL_RESULT_GUARD_SKIP=$id" >&2
|
|
60
|
+
exit 2
|
|
61
|
+
fi
|
|
62
|
+
echo "WARNING (tool-result-size-guard): $pattern is likely to produce large output." >&2
|
|
63
|
+
echo "Safer alternative: $suggest" >&2
|
|
64
|
+
echo "Set CC_TOOL_RESULT_BLOCK=1 to block, or CC_TOOL_RESULT_GUARD_SKIP=$id to suppress." >&2
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Pattern 1: find / or find ~ (root/home scans without -maxdepth or limit)
|
|
68
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\|\| | && |\| )\s*find\s+(/|~)([^a-zA-Z0-9_/-]|$)'; then
|
|
69
|
+
if ! echo "$COMMAND" | grep -qE '\-maxdepth|\-quit|\| head|\| wc'; then
|
|
70
|
+
emit "find" "find / or find ~ without -maxdepth or head/wc piping" \
|
|
71
|
+
"find / -maxdepth 3 -name '<pattern>' | head -50"
|
|
72
|
+
fi
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Pattern 2: ls -R (recursive without limit)
|
|
76
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*ls\s+(-[a-zA-Z]*R[a-zA-Z]*)\b'; then
|
|
77
|
+
if ! echo "$COMMAND" | grep -qE '\| head|\| tail|\| wc'; then
|
|
78
|
+
emit "ls-r" "ls -R (recursive listing without limit)" \
|
|
79
|
+
"ls -R <dir> | head -100 OR find <dir> -maxdepth 2 -type f"
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Pattern 3: tail -f (streaming, never returns in a Claude Code session)
|
|
84
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*tail\s+(-[a-zA-Z]*f[a-zA-Z]*)\b'; then
|
|
85
|
+
emit "tail-f" "tail -f (streaming follow — does not return)" \
|
|
86
|
+
"tail -n 100 <file> (one-shot read of last 100 lines)"
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Pattern 4: dmesg (system log, often >1MB)
|
|
90
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*(sudo\s+)?dmesg\b'; then
|
|
91
|
+
if ! echo "$COMMAND" | grep -qE '\| head|\| tail|\| wc|-T\s'; then
|
|
92
|
+
emit "dmesg" "dmesg without head/tail" \
|
|
93
|
+
"dmesg | tail -100 OR dmesg --time-format=iso | grep <pattern>"
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Pattern 5: journalctl without -n
|
|
98
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*(sudo\s+)?journalctl\b'; then
|
|
99
|
+
if ! echo "$COMMAND" | grep -qE '\-n\s+[0-9]|\-\-lines|\| head|\| tail|\| wc'; then
|
|
100
|
+
emit "journalctl" "journalctl without -n or pipe to head/tail" \
|
|
101
|
+
"journalctl -n 100 OR journalctl --since '1 hour ago' | tail -200"
|
|
102
|
+
fi
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# Pattern 6: git log without -n or --oneline
|
|
106
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*git\s+log\b'; then
|
|
107
|
+
if ! echo "$COMMAND" | grep -qE '\-n\s*[0-9]|\-\-max-count|\-[0-9]+|\-\-oneline|\| head|\| tail'; then
|
|
108
|
+
emit "git-log" "git log without -n / -<N> / --oneline limit" \
|
|
109
|
+
"git log -20 --oneline OR git log -20"
|
|
110
|
+
fi
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Pattern 7: npm ls -a (full dependency tree) or pip list (without filter)
|
|
114
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*npm\s+(ls|list)\s+(-a|--all)\b'; then
|
|
115
|
+
emit "npm-ls" "npm ls -a / npm ls --all (full recursive deps tree)" \
|
|
116
|
+
"npm ls --depth=0 OR npm ls <package>"
|
|
117
|
+
fi
|
|
118
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*pip\s+list\b' && \
|
|
119
|
+
! echo "$COMMAND" | grep -qE '\| grep|\| head|\| wc|\-\-format'; then
|
|
120
|
+
emit "pip-list" "pip list without filter" \
|
|
121
|
+
"pip list | grep <pattern> OR pip show <package>"
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Pattern 8: docker logs without --tail
|
|
125
|
+
if echo "$COMMAND" | grep -qE '(^|;|&&|\| )\s*docker\s+logs\b'; then
|
|
126
|
+
if ! echo "$COMMAND" | grep -qE '\-\-tail|\-n\s+[0-9]|\| head|\| tail'; then
|
|
127
|
+
emit "docker-logs" "docker logs without --tail" \
|
|
128
|
+
"docker logs --tail 200 <container>"
|
|
129
|
+
fi
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
exit 0
|
|
@@ -9,6 +9,18 @@
|
|
|
9
9
|
#
|
|
10
10
|
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
11
11
|
|
|
12
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
13
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
14
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
15
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
16
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
17
|
+
_nojq_warned="/tmp/cc-nojq-warned-tool-retry-budget-guard-$PPID"
|
|
18
|
+
[ -f "$_nojq_warned" ] || {
|
|
19
|
+
echo "WARNING [tool-retry-budget-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
20
|
+
: > "$_nojq_warned"
|
|
21
|
+
}
|
|
22
|
+
fi
|
|
23
|
+
|
|
12
24
|
INPUT=$(cat)
|
|
13
25
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
14
26
|
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# transcript-contamination-detector.sh — Detect synthetic entries injected
|
|
3
|
+
# into session transcript .jsonl files by the /resume contamination bug.
|
|
4
|
+
#
|
|
5
|
+
# Solves: #60802 — "/resume renders an unselected session's transcript and
|
|
6
|
+
# injects synthetic messages into its .jsonl (v2.1.139, Windows PowerShell)"
|
|
7
|
+
#
|
|
8
|
+
# In that case, /resume on Windows v2.1.139 contaminated *unselected* session
|
|
9
|
+
# .jsonl logs with two synthetic entries:
|
|
10
|
+
#
|
|
11
|
+
# - user message: { isMeta: true, content: "Continue from where you left off." }
|
|
12
|
+
# - assistant message: { model: "<synthetic>", content: "No response requested." }
|
|
13
|
+
#
|
|
14
|
+
# These entries appear in the .jsonl file of a session the user did NOT
|
|
15
|
+
# resume. The contaminated session's log no longer faithfully records what
|
|
16
|
+
# happened — a later audit would see message exchanges that never occurred.
|
|
17
|
+
#
|
|
18
|
+
# Related: #46603 (parentUuid chain breakage after compaction; different
|
|
19
|
+
# mechanism but same structural family — transcript log losing fidelity to
|
|
20
|
+
# the actual conversation).
|
|
21
|
+
#
|
|
22
|
+
# This hook runs on SessionStart and scans the user's per-project .jsonl
|
|
23
|
+
# logs for the synthetic markers. If any are found, it surfaces the count
|
|
24
|
+
# and file paths so the operator can decide whether to restore from backup
|
|
25
|
+
# or annotate the log.
|
|
26
|
+
#
|
|
27
|
+
# The hook does NOT block session start (exit 0 even when contamination is
|
|
28
|
+
# detected) because session-start blocking is too disruptive for a
|
|
29
|
+
# detection-only signal. It does emit a system-reminder for Claude to see.
|
|
30
|
+
#
|
|
31
|
+
# TRIGGER: SessionStart
|
|
32
|
+
# MATCHER: ""
|
|
33
|
+
#
|
|
34
|
+
# CONFIGURATION (environment variables):
|
|
35
|
+
# CC_PROJECTS_DIR default ~/.claude/projects
|
|
36
|
+
# CC_TRANSCRIPT_DETECTOR_DISABLE set to "1" to skip
|
|
37
|
+
# CC_TRANSCRIPT_DETECTOR_MAX max .jsonl files to scan (default 200)
|
|
38
|
+
#
|
|
39
|
+
# USAGE (settings.json):
|
|
40
|
+
# {
|
|
41
|
+
# "hooks": {
|
|
42
|
+
# "SessionStart": [{
|
|
43
|
+
# "matcher": "",
|
|
44
|
+
# "hooks": [{
|
|
45
|
+
# "type": "command",
|
|
46
|
+
# "command": "~/.claude/hooks/transcript-contamination-detector.sh"
|
|
47
|
+
# }]
|
|
48
|
+
# }]
|
|
49
|
+
# }
|
|
50
|
+
# }
|
|
51
|
+
|
|
52
|
+
set -uo pipefail
|
|
53
|
+
|
|
54
|
+
[ "${CC_TRANSCRIPT_DETECTOR_DISABLE:-0}" = "1" ] && exit 0
|
|
55
|
+
|
|
56
|
+
PROJECTS_DIR="${CC_PROJECTS_DIR:-$HOME/.claude/projects}"
|
|
57
|
+
MAX_FILES="${CC_TRANSCRIPT_DETECTOR_MAX:-200}"
|
|
58
|
+
|
|
59
|
+
# If no projects directory, nothing to scan.
|
|
60
|
+
[ ! -d "$PROJECTS_DIR" ] && exit 0
|
|
61
|
+
|
|
62
|
+
# The two synthetic markers from #60802. Match conservatively — require both
|
|
63
|
+
# the isMeta:true + the specific synthetic-model marker patterns.
|
|
64
|
+
USER_MARKER='"isMeta"[[:space:]]*:[[:space:]]*true.*Continue from where you left off'
|
|
65
|
+
ASSISTANT_MARKER='"model"[[:space:]]*:[[:space:]]*"<synthetic>".*No response requested'
|
|
66
|
+
|
|
67
|
+
# Collect .jsonl files, capped at MAX_FILES, most-recently-modified first.
|
|
68
|
+
mapfile -t FILES < <(
|
|
69
|
+
find "$PROJECTS_DIR" -maxdepth 3 -type f -name '*.jsonl' \
|
|
70
|
+
-printf '%T@ %p\n' 2>/dev/null \
|
|
71
|
+
| sort -rn \
|
|
72
|
+
| head -n "$MAX_FILES" \
|
|
73
|
+
| awk '{ $1=""; sub(/^ /, ""); print }'
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
[ "${#FILES[@]}" -eq 0 ] && exit 0
|
|
77
|
+
|
|
78
|
+
CONTAMINATED=()
|
|
79
|
+
for f in "${FILES[@]}"; do
|
|
80
|
+
# Both markers must be present on at least one line each (they don't
|
|
81
|
+
# need to be on the same line — they're separate messages).
|
|
82
|
+
if grep -Eq "$USER_MARKER" "$f" 2>/dev/null && grep -Eq "$ASSISTANT_MARKER" "$f" 2>/dev/null; then
|
|
83
|
+
CONTAMINATED+=("$f")
|
|
84
|
+
fi
|
|
85
|
+
done
|
|
86
|
+
|
|
87
|
+
[ "${#CONTAMINATED[@]}" -eq 0 ] && exit 0
|
|
88
|
+
|
|
89
|
+
# Contamination found. Build a feedback message for Claude.
|
|
90
|
+
# Limit output to first 5 paths to avoid wall-of-text.
|
|
91
|
+
SHOWN=()
|
|
92
|
+
for ((i = 0; i < ${#CONTAMINATED[@]} && i < 5; i++)); do
|
|
93
|
+
SHOWN+=("${CONTAMINATED[$i]}")
|
|
94
|
+
done
|
|
95
|
+
EXTRA=$(( ${#CONTAMINATED[@]} - ${#SHOWN[@]} ))
|
|
96
|
+
|
|
97
|
+
cat >&2 <<EOF
|
|
98
|
+
<system-reminder>
|
|
99
|
+
TRANSCRIPT CONTAMINATION DETECTED — ${#CONTAMINATED[@]} session .jsonl file(s)
|
|
100
|
+
contain the synthetic-entry markers introduced by the /resume bug
|
|
101
|
+
documented in anthropics/claude-code#60802 (v2.1.139, originally Windows
|
|
102
|
+
PowerShell — may affect other platforms / versions).
|
|
103
|
+
|
|
104
|
+
Markers found (both must be present in a single .jsonl for it to be flagged):
|
|
105
|
+
- user message with "isMeta": true + content "Continue from where you left off."
|
|
106
|
+
- assistant message with "model": "<synthetic>" + content "No response requested."
|
|
107
|
+
|
|
108
|
+
These entries are NOT real conversation. They were injected when /resume was
|
|
109
|
+
invoked on a *different* session. The log of the affected file no longer
|
|
110
|
+
faithfully records what actually happened in that session.
|
|
111
|
+
|
|
112
|
+
Affected files (first 5):
|
|
113
|
+
EOF
|
|
114
|
+
for f in "${SHOWN[@]}"; do
|
|
115
|
+
echo " $f" >&2
|
|
116
|
+
done
|
|
117
|
+
if [ "$EXTRA" -gt 0 ]; then
|
|
118
|
+
echo " ... and $EXTRA more" >&2
|
|
119
|
+
fi
|
|
120
|
+
cat >&2 <<EOF
|
|
121
|
+
|
|
122
|
+
Recommended next actions for the operator (NOT for the model to perform
|
|
123
|
+
automatically):
|
|
124
|
+
1. If an offline backup of the session .jsonl exists from before the
|
|
125
|
+
/resume incident, restore the affected file from backup.
|
|
126
|
+
2. Otherwise, append an editorial note to the affected session
|
|
127
|
+
documenting that the synthetic entries were injected by the harness,
|
|
128
|
+
not authored by the operator or the model.
|
|
129
|
+
3. Avoid using /resume on multi-session projects on the affected version
|
|
130
|
+
until the upstream fix lands. Workaround: open the desired session
|
|
131
|
+
directly via the .jsonl path argument rather than the picker.
|
|
132
|
+
|
|
133
|
+
To disable this detector, set CC_TRANSCRIPT_DETECTOR_DISABLE=1.
|
|
134
|
+
</system-reminder>
|
|
135
|
+
EOF
|
|
136
|
+
|
|
137
|
+
# Exit 0 — detection-only, don't block session start.
|
|
138
|
+
exit 0
|