cc-safe-setup 29.8.0 → 30.0.5
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 +421 -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 +1718 -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,143 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# opus48-thinking-wedge-advisor.sh — Warn when a mid-conversation model swap
|
|
3
|
+
# from Opus 4.7 to Opus 4.8 is about to hit
|
|
4
|
+
# the Cluster 13 Axis G hard 400.
|
|
5
|
+
#
|
|
6
|
+
# Solves: Cluster 13 Axis G — Opus 4.7 → Opus 4.8 mid-conversation model swap
|
|
7
|
+
# produces a hard 400 ("thinking blocks must remain as original
|
|
8
|
+
# response") that strip-on-retry does not recover from. The signature
|
|
9
|
+
# of a thinking block generated by 4.7 is computed against the 4.7
|
|
10
|
+
# reasoning state; 4.8's resume path applies a stricter validation
|
|
11
|
+
# that rejects the 4.7-signed block even when the text is preserved
|
|
12
|
+
# verbatim. Unlike Cluster 13A (signature/text mismatch, soft 400),
|
|
13
|
+
# 13G is structural: the only known full fix is staying on 4.7.
|
|
14
|
+
#
|
|
15
|
+
# Issues addressed: #63607 (Opus 4.8 incompatibility, "must remain as
|
|
16
|
+
# original response" phrasing), #63606, #63612, #63412 (Opus 4.8
|
|
17
|
+
# on long tool-heavy chats; 4.7 unaffected). Field guide on the
|
|
18
|
+
# seven-pattern split: https://github.com/anthropics/claude-code/issues/63147#issuecomment-4580358273
|
|
19
|
+
#
|
|
20
|
+
# How it works: Notification hook. Reads the model name from the event body
|
|
21
|
+
# (falling back to $CLAUDE_MODEL). Compares to the model recorded on the
|
|
22
|
+
# previous Notification. When the transition matches "Opus 4.7 → Opus 4.8"
|
|
23
|
+
# AND the current session transcript carries the empty-text + signed
|
|
24
|
+
# thinking block shape (the precondition for the 4.8 strict validation to
|
|
25
|
+
# trip), emits a stderr advisory naming sub-pattern 13G, the four central
|
|
26
|
+
# issues, and the only known full-fix path (stay on 4.7 + 2.1.152).
|
|
27
|
+
#
|
|
28
|
+
# The hook NEVER blocks — exit 0 always. The advisory is calibrated to a
|
|
29
|
+
# transition shape that the operator can act on before the next API call.
|
|
30
|
+
#
|
|
31
|
+
# Differentiation from model-version-change-alert.sh:
|
|
32
|
+
# The general alert fires on any model change. This hook fires only on the
|
|
33
|
+
# 13G transition shape (4.7 → 4.8 + signed thinking blocks in transcript)
|
|
34
|
+
# and articulates the specific failure mode and workaround. The two hooks
|
|
35
|
+
# are complementary; running both gives general visibility plus 13G-specific
|
|
36
|
+
# guidance.
|
|
37
|
+
#
|
|
38
|
+
# Environment variables:
|
|
39
|
+
# CC_CLUSTER_13G_DISABLE=1 — disable advisory entirely
|
|
40
|
+
# CC_CLUSTER_13G_VERBOSE=1 — include sample signature lengths
|
|
41
|
+
# CC_CLUSTER_13G_TRANSCRIPT — override transcript path (test)
|
|
42
|
+
# CC_CLUSTER_13G_HISTORY_FILE — override model history file (test)
|
|
43
|
+
# CC_CLUSTER_13G_FORCE=1 — fire regardless of source (test)
|
|
44
|
+
#
|
|
45
|
+
# TRIGGER: Notification
|
|
46
|
+
# MATCHER: "" (filters event internally)
|
|
47
|
+
|
|
48
|
+
set -uo pipefail
|
|
49
|
+
|
|
50
|
+
INPUT=$(cat)
|
|
51
|
+
[ "${CC_CLUSTER_13G_DISABLE:-0}" = "1" ] && exit 0
|
|
52
|
+
|
|
53
|
+
# Resolve current model from event body or environment.
|
|
54
|
+
BODY_MODEL=$(printf '%s' "$INPUT" | jq -r '.model // empty' 2>/dev/null)
|
|
55
|
+
CURRENT_MODEL="${BODY_MODEL:-${CLAUDE_MODEL:-}}"
|
|
56
|
+
[ -z "$CURRENT_MODEL" ] && exit 0
|
|
57
|
+
|
|
58
|
+
# History file persists the last observed model across hook invocations.
|
|
59
|
+
HISTORY_FILE="${CC_CLUSTER_13G_HISTORY_FILE:-/tmp/cc-cluster-13g-model-history}"
|
|
60
|
+
PREV_MODEL=$(cat "$HISTORY_FILE" 2>/dev/null || true)
|
|
61
|
+
|
|
62
|
+
# Always record current model on exit (fail-open if we cannot write).
|
|
63
|
+
record_current_model() {
|
|
64
|
+
printf '%s' "$CURRENT_MODEL" > "$HISTORY_FILE" 2>/dev/null || true
|
|
65
|
+
}
|
|
66
|
+
trap record_current_model EXIT
|
|
67
|
+
|
|
68
|
+
# Require a previous observation to detect a transition.
|
|
69
|
+
[ -z "$PREV_MODEL" ] && exit 0
|
|
70
|
+
|
|
71
|
+
# Same model — no transition.
|
|
72
|
+
[ "$PREV_MODEL" = "$CURRENT_MODEL" ] && exit 0
|
|
73
|
+
|
|
74
|
+
# Identify the 13G transition: Opus 4.7 series → Opus 4.8 series.
|
|
75
|
+
# Accept any string containing "opus-4-7" / "opus-4-8" (case-insensitive)
|
|
76
|
+
# to match both API model IDs and Claude Code's internal naming.
|
|
77
|
+
is_opus_47() {
|
|
78
|
+
printf '%s' "$1" | grep -qiE 'opus[-_. ]*4[-_. ]*7'
|
|
79
|
+
}
|
|
80
|
+
is_opus_48() {
|
|
81
|
+
printf '%s' "$1" | grep -qiE 'opus[-_. ]*4[-_. ]*8'
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if [ "${CC_CLUSTER_13G_FORCE:-0}" != "1" ]; then
|
|
85
|
+
is_opus_47 "$PREV_MODEL" || exit 0
|
|
86
|
+
is_opus_48 "$CURRENT_MODEL" || exit 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Precondition for 13G to fire on the next API call: the transcript carries
|
|
90
|
+
# signed thinking blocks emitted by the prior model. If there are no signed
|
|
91
|
+
# thinking blocks, the swap may complete cleanly and the advisory is noise.
|
|
92
|
+
LATEST="${CC_CLUSTER_13G_TRANSCRIPT:-}"
|
|
93
|
+
if [ -z "$LATEST" ]; then
|
|
94
|
+
PROJ_DIR="${CC_PROJECT_DIR:-$PWD}"
|
|
95
|
+
SLUG=$(printf '%s' "$PROJ_DIR" | sed 's|/|-|g')
|
|
96
|
+
TRANSCRIPT_DIR="${HOME}/.claude/projects/${SLUG}"
|
|
97
|
+
[ -d "$TRANSCRIPT_DIR" ] || exit 0
|
|
98
|
+
LATEST=$(ls -t "$TRANSCRIPT_DIR"/*.jsonl 2>/dev/null | head -1)
|
|
99
|
+
fi
|
|
100
|
+
[ -n "$LATEST" ] || exit 0
|
|
101
|
+
[ -r "$LATEST" ] || exit 0
|
|
102
|
+
|
|
103
|
+
# Scan for any signed thinking block (text empty or non-empty — the 13G
|
|
104
|
+
# trigger is the 4.7-computed signature itself, independent of whether the
|
|
105
|
+
# text was emptied to "" as in 13A).
|
|
106
|
+
SCAN=$(jq -rR 'fromjson? | select(.type == "assistant") | .message.content[]? | select(.type == "thinking" and ((.signature // "") | length) > 0) | (.signature | length)' "$LATEST" 2>/dev/null || true)
|
|
107
|
+
[ -z "$SCAN" ] && exit 0
|
|
108
|
+
|
|
109
|
+
COUNT=$(printf '%s\n' "$SCAN" | grep -c .)
|
|
110
|
+
SIG_SAMPLE=$(printf '%s' "$SCAN" | head -3 | tr '\n' ' ')
|
|
111
|
+
|
|
112
|
+
{
|
|
113
|
+
echo "[opus48-thinking-wedge-advisor] Cluster 13G transition detected."
|
|
114
|
+
echo ""
|
|
115
|
+
echo " Previous model: $PREV_MODEL"
|
|
116
|
+
echo " Current model: $CURRENT_MODEL"
|
|
117
|
+
echo " Transcript: $LATEST"
|
|
118
|
+
echo " Signed thinking block(s) carried from prior model: ${COUNT}"
|
|
119
|
+
echo ""
|
|
120
|
+
echo "The next API call may hit the hard 400:"
|
|
121
|
+
echo " \`thinking\` or \`redacted_thinking\` blocks in the latest assistant"
|
|
122
|
+
echo " message must remain as they were in the original response."
|
|
123
|
+
echo ""
|
|
124
|
+
echo "This 400 differs from the Cluster 13A wedge: strip-on-retry does NOT"
|
|
125
|
+
echo "recover, because the 4.7-computed signature is structurally rejected"
|
|
126
|
+
echo "by the 4.8 validation path. The session cannot continue on 4.8 once"
|
|
127
|
+
echo "this fires."
|
|
128
|
+
echo ""
|
|
129
|
+
echo "Recommended actions:"
|
|
130
|
+
echo " - Switch back to Opus 4.7 with /model and continue on this session."
|
|
131
|
+
echo " - For 4.8 work, start a fresh session without prior 4.7-signed blocks."
|
|
132
|
+
echo " - Pinning Claude Code to 2.1.152 avoids the related Cluster 13F"
|
|
133
|
+
echo " context-ops failure that 13G frequently compounds with."
|
|
134
|
+
echo ""
|
|
135
|
+
echo "Reference: https://github.com/anthropics/claude-code/issues/63607"
|
|
136
|
+
echo "Related: https://github.com/anthropics/claude-code/issues/63147#issuecomment-4580358273"
|
|
137
|
+
if [ "${CC_CLUSTER_13G_VERBOSE:-0}" = "1" ]; then
|
|
138
|
+
echo ""
|
|
139
|
+
echo "(first 3 signature lengths: ${SIG_SAMPLE})"
|
|
140
|
+
fi
|
|
141
|
+
} >&2
|
|
142
|
+
|
|
143
|
+
exit 0
|
|
@@ -17,7 +17,7 @@ STDOUT=$(echo "$INPUT" | jq -r '.tool_result.stdout // empty' 2>/dev/null)
|
|
|
17
17
|
[ -z "$STDOUT" ] && exit 0
|
|
18
18
|
|
|
19
19
|
# Check for common credential patterns in output
|
|
20
|
-
if echo "$STDOUT" | grep -qiE '(sk-[
|
|
20
|
+
if echo "$STDOUT" | grep -qiE '((^|[^A-Za-z0-9])sk-[A-Za-z0-9_-]{20,}|ghp_[a-zA-Z0-9]{36}|AKIA[A-Z0-9]{16}|xox[bpsa]-[a-zA-Z0-9-]+|eyJ[a-zA-Z0-9_-]+\.eyJ)'; then
|
|
21
21
|
echo "⚠ Possible credential detected in command output!" >&2
|
|
22
22
|
echo " This output may contain API keys, tokens, or secrets." >&2
|
|
23
23
|
echo " Avoid sharing this output or committing it to version control." >&2
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# output-secret-mask.sh —
|
|
2
|
+
# output-secret-mask.sh — Warn when tool output looks like it contained a secret
|
|
3
3
|
#
|
|
4
4
|
# Solves: Commands like `env`, `printenv`, `cat .env` expose secrets in tool output.
|
|
5
5
|
# Claude then has secrets in its context window, increasing leak risk.
|
|
6
|
-
# This hook masks secret values in PostToolUse output.
|
|
7
6
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
7
|
+
# CORRECTION 2026-08-13 — read this before relying on the name.
|
|
8
|
+
# This file used to claim it "masks secret values" and that "the masked output
|
|
9
|
+
# is what Claude sees in its context". It never did that. `[MASKED]` appeared
|
|
10
|
+
# only in this comment; there is no substitution anywhere in the body, and
|
|
11
|
+
# running it against a real key produces one line on stderr and nothing else.
|
|
12
|
+
# The name promised a control that did not exist, which is worse than no hook:
|
|
13
|
+
# someone reads "output-secret-mask", installs it, and believes secrets are
|
|
14
|
+
# being stripped out of the context window. They are not.
|
|
11
15
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
16
|
+
# The premise is also not implementable at this event. PostToolUse fires
|
|
17
|
+
# *after* the tool result exists; it validates output, it does not rewrite what
|
|
18
|
+
# the model already received (see SETTINGS_REFERENCE.md, PostToolUse row).
|
|
19
|
+
# So this hook has been corrected to describe what it does, rather than
|
|
20
|
+
# implementing a promise the event cannot keep.
|
|
21
|
+
#
|
|
22
|
+
# What it actually does: scans the tool result for secret-shaped strings and
|
|
23
|
+
# writes one warning to stderr. Detection only. The secret is already in the
|
|
24
|
+
# context by the time this runs.
|
|
25
|
+
#
|
|
26
|
+
# What to use instead, if you need the secret to never reach the context:
|
|
27
|
+
# block the command before it runs (a PreToolUse guard on `env` / `printenv` /
|
|
28
|
+
# `cat .env`), or keep secrets out of files the agent reads at all.
|
|
14
29
|
#
|
|
15
30
|
# Usage: Add to settings.json as a PostToolUse hook
|
|
16
31
|
#
|
|
@@ -37,8 +52,15 @@ NEEDS_MASK=false
|
|
|
37
52
|
echo "$OUTPUT" | grep -qE 'AKIA[0-9A-Z]{16}' && NEEDS_MASK=true
|
|
38
53
|
# GitHub tokens
|
|
39
54
|
echo "$OUTPUT" | grep -qE '(ghp_|gho_|ghs_|ghr_)[A-Za-z0-9_]{20,}' && NEEDS_MASK=true
|
|
40
|
-
# OpenAI/Anthropic keys
|
|
41
|
-
|
|
55
|
+
# OpenAI/Anthropic keys.
|
|
56
|
+
# The prefix has to START a token. Without the left boundary this also fired on
|
|
57
|
+
# ordinary English words that end in "sk" before a separator — task-, ask-,
|
|
58
|
+
# risk-, disk-, desk- — so any path built from one of those, followed by twenty
|
|
59
|
+
# more word characters, was reported as a leaked key. The same defect was fixed
|
|
60
|
+
# in write-secret-guard.sh on 2026-08-13. A warning that cries on ordinary
|
|
61
|
+
# output is a warning people learn to ignore, so precision matters here as much
|
|
62
|
+
# as coverage.
|
|
63
|
+
echo "$OUTPUT" | grep -qE '(^|[^A-Za-z0-9_-])sk-[A-Za-z0-9_-]{20,}' && NEEDS_MASK=true
|
|
42
64
|
# Slack tokens
|
|
43
65
|
echo "$OUTPUT" | grep -qE '(xoxb-|xoxp-)[0-9A-Za-z-]{20,}' && NEEDS_MASK=true
|
|
44
66
|
# Generic secrets in env output (KEY=value pattern with high-entropy value)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# output-token-spike-detector.sh — alert when per-request output_tokens spikes above baseline
|
|
3
|
+
#
|
|
4
|
+
# Why: Cluster 23 candidate (Opus 4.8 effort-budget regression) documents that
|
|
5
|
+
# Opus 4.8 under effort=medium can spend 40-50k output tokens on hidden
|
|
6
|
+
# thinking for a routine coding turn — Issue #64153 anchor (46,433 output
|
|
7
|
+
# tokens / 22m 43s of thinking on a small rename-impact scan, transcript
|
|
8
|
+
# stop_reason=end_turn so this completed normally, not a retry / not an
|
|
9
|
+
# API 400). The reporter explicitly compares: Opus 4.6 / Opus 4.7 do NOT
|
|
10
|
+
# show this magnitude for comparable routine work. Five independent filings
|
|
11
|
+
# so far (#64153 / #64152 / #64143 / #64102 / #63455).
|
|
12
|
+
#
|
|
13
|
+
# This is structurally distinct from Cluster 4 (Pro Max quota) which is
|
|
14
|
+
# server-side cache_creation_input_tokens inflation — Cluster 23 candidate
|
|
15
|
+
# is output_tokens magnitude. #64153's transcript shows cache_creation
|
|
16
|
+
# 4,054 vs output 46,433, the opposite ratio of Cluster 4's signature.
|
|
17
|
+
# So Cluster 4's hooks (cache-creation-drift-detector etc.) do not catch
|
|
18
|
+
# Cluster 23 candidate directly.
|
|
19
|
+
#
|
|
20
|
+
# Routine coding turns should sit at 1-5k output tokens; 10× above that is
|
|
21
|
+
# the operator-side signal that the model is burning hidden-thinking budget
|
|
22
|
+
# out of proportion to the visible work. This hook emits a one-line stderr
|
|
23
|
+
# warning when the current request's output_tokens exceeds the trailing-
|
|
24
|
+
# window mean by a configurable multiplier (default 3.0, higher than the
|
|
25
|
+
# cache-creation drift threshold because output_tokens naturally varies
|
|
26
|
+
# more across turns).
|
|
27
|
+
#
|
|
28
|
+
# Event: PostToolUse MATCHER: "" (all tools)
|
|
29
|
+
# Action: Read output_tokens from the PostToolUse payload (or the last assistant
|
|
30
|
+
# turn in the transcript as fallback). Append to a rolling JSONL log.
|
|
31
|
+
# Compute the mean of the last N nonzero samples. If the current value
|
|
32
|
+
# exceeds threshold * mean, emit a warning to stderr with the Opus 4.7
|
|
33
|
+
# fallback path. Advisory only (exit 0); does not block.
|
|
34
|
+
#
|
|
35
|
+
# Configuration (all optional):
|
|
36
|
+
# CC_OUTPUT_SPIKE_LOG Log path (default: ~/.cache/cc-safe-setup/output-token-spike.jsonl)
|
|
37
|
+
# CC_OUTPUT_SPIKE_THRESHOLD Multiplier for alert (default: 3.0 = 3× above mean)
|
|
38
|
+
# CC_OUTPUT_SPIKE_MIN_HISTORY Minimum samples before alerting (default: 20)
|
|
39
|
+
# CC_OUTPUT_SPIKE_WINDOW Trailing window size for mean (default: 200 samples)
|
|
40
|
+
# CC_OUTPUT_SPIKE_FLOOR Absolute minimum (default: 10000) — never alert below this
|
|
41
|
+
# even at threshold ratio, to suppress noise on small turns
|
|
42
|
+
# CC_OUTPUT_SPIKE_SILENT Set to "1" to suppress stderr (still logs)
|
|
43
|
+
#
|
|
44
|
+
# Inspect the log:
|
|
45
|
+
# tail -50 ~/.cache/cc-safe-setup/output-token-spike.jsonl
|
|
46
|
+
# jq -s 'map(.out_tokens) | add / length' ~/.cache/cc-safe-setup/output-token-spike.jsonl
|
|
47
|
+
#
|
|
48
|
+
# The registration was missing from this header. The installer reads TRIGGER
|
|
49
|
+
# and MATCHER from here and falls back to PreToolUse / Bash when both are
|
|
50
|
+
# absent, so this hook was being registered at a moment where the field it
|
|
51
|
+
# reads is always empty: it installed, it appeared in the settings, and it
|
|
52
|
+
# did nothing. Measured 2026-08-04 across examples/: 14 files were like this.
|
|
53
|
+
# TRIGGER: PostToolUse
|
|
54
|
+
# MATCHER: ""
|
|
55
|
+
|
|
56
|
+
set -u
|
|
57
|
+
|
|
58
|
+
LOG="${CC_OUTPUT_SPIKE_LOG:-${HOME}/.cache/cc-safe-setup/output-token-spike.jsonl}"
|
|
59
|
+
THRESHOLD="${CC_OUTPUT_SPIKE_THRESHOLD:-3.0}"
|
|
60
|
+
MIN_HISTORY="${CC_OUTPUT_SPIKE_MIN_HISTORY:-20}"
|
|
61
|
+
WINDOW="${CC_OUTPUT_SPIKE_WINDOW:-200}"
|
|
62
|
+
FLOOR="${CC_OUTPUT_SPIKE_FLOOR:-10000}"
|
|
63
|
+
SILENT="${CC_OUTPUT_SPIKE_SILENT:-0}"
|
|
64
|
+
|
|
65
|
+
mkdir -p "$(dirname "$LOG")" 2>/dev/null
|
|
66
|
+
|
|
67
|
+
INPUT=$(cat)
|
|
68
|
+
|
|
69
|
+
# Extract output_tokens from the PostToolUse payload (path varies by tool).
|
|
70
|
+
OUT_TOKENS=$(printf '%s' "$INPUT" | jq -r '.tool_response.usage.output_tokens // empty' 2>/dev/null)
|
|
71
|
+
|
|
72
|
+
# Fallback: read the last assistant turn's usage from the transcript.
|
|
73
|
+
if [ -z "$OUT_TOKENS" ]; then
|
|
74
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
75
|
+
if [ -n "$TRANSCRIPT" ] && [ -r "$TRANSCRIPT" ]; then
|
|
76
|
+
LAST_USAGE=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"usage"' || true)
|
|
77
|
+
if [ -n "$LAST_USAGE" ]; then
|
|
78
|
+
OUT_TOKENS=$(printf '%s' "$LAST_USAGE" | \
|
|
79
|
+
jq -r '.message.usage.output_tokens // .usage.output_tokens // empty' 2>/dev/null)
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# No usable measurement — exit quietly (this is the common case for many tools).
|
|
85
|
+
if [ -z "$OUT_TOKENS" ] || [ "$OUT_TOKENS" = "0" ] || [ "$OUT_TOKENS" = "null" ]; then
|
|
86
|
+
exit 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Validate the value is a positive integer.
|
|
90
|
+
case "$OUT_TOKENS" in
|
|
91
|
+
''|*[!0-9]*) exit 0 ;;
|
|
92
|
+
esac
|
|
93
|
+
|
|
94
|
+
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
|
|
95
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
96
|
+
|
|
97
|
+
# Try to capture the model name too — useful for distinguishing Opus 4.7 vs 4.8 in logs.
|
|
98
|
+
MODEL=$(printf '%s' "$INPUT" | jq -r '.tool_response.model // .model // empty' 2>/dev/null)
|
|
99
|
+
if [ -z "$MODEL" ] && [ -n "${TRANSCRIPT:-}" ] && [ -r "${TRANSCRIPT:-}" ]; then
|
|
100
|
+
MODEL=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"model"' | jq -r '.message.model // .model // empty' 2>/dev/null || true)
|
|
101
|
+
fi
|
|
102
|
+
MODEL="${MODEL:-unknown}"
|
|
103
|
+
|
|
104
|
+
# Append this sample to the rolling log as a JSONL line.
|
|
105
|
+
printf '{"ts":"%s","session":"%s","model":"%s","out_tokens":%s}\n' "$TS" "$SESSION_ID" "$MODEL" "$OUT_TOKENS" >> "$LOG"
|
|
106
|
+
|
|
107
|
+
# How many historical samples do we have so far? (Includes the line we just appended.)
|
|
108
|
+
SAMPLE_COUNT=$(wc -l < "$LOG" 2>/dev/null | tr -d ' ')
|
|
109
|
+
SAMPLE_COUNT="${SAMPLE_COUNT:-0}"
|
|
110
|
+
|
|
111
|
+
# Need at least MIN_HISTORY samples before we trust the baseline.
|
|
112
|
+
if [ "$SAMPLE_COUNT" -lt "$MIN_HISTORY" ]; then
|
|
113
|
+
exit 0
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# Compute the mean of the trailing window (excluding the just-written sample).
|
|
117
|
+
# We exclude the current sample so the alert compares "this" against "the past".
|
|
118
|
+
TAIL_LINES=$((WINDOW + 1))
|
|
119
|
+
MEAN=$(tail -n "$TAIL_LINES" "$LOG" 2>/dev/null | head -n -1 | \
|
|
120
|
+
jq -s 'if length > 0 then (map(.out_tokens) | add / length) else 0 end' 2>/dev/null)
|
|
121
|
+
|
|
122
|
+
# If the baseline mean is invalid or zero, skip (defensive).
|
|
123
|
+
if [ -z "$MEAN" ] || [ "$MEAN" = "0" ] || [ "$MEAN" = "null" ]; then
|
|
124
|
+
exit 0
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Compute ratio = OUT_TOKENS / MEAN. Use awk because bash lacks float arithmetic.
|
|
128
|
+
RATIO=$(awk -v c="$OUT_TOKENS" -v m="$MEAN" 'BEGIN { if (m > 0) printf "%.3f", c/m; else print "0" }')
|
|
129
|
+
EXCEEDS=$(awk -v r="$RATIO" -v t="$THRESHOLD" 'BEGIN { print (r > t) ? 1 : 0 }')
|
|
130
|
+
|
|
131
|
+
# Suppress noise: even at threshold ratio, do not alert below the absolute floor.
|
|
132
|
+
# A 3× spike from 1k → 3k is normal variance; a 3× spike from 5k → 15k matters.
|
|
133
|
+
ABOVE_FLOOR=$(awk -v c="$OUT_TOKENS" -v f="$FLOOR" 'BEGIN { print (c > f) ? 1 : 0 }')
|
|
134
|
+
|
|
135
|
+
if [ "$EXCEEDS" = "1" ] && [ "$ABOVE_FLOOR" = "1" ] && [ "$SILENT" != "1" ]; then
|
|
136
|
+
# Format the baseline mean as an integer for the human-readable output.
|
|
137
|
+
MEAN_INT=$(awk -v m="$MEAN" 'BEGIN { printf "%d", m }')
|
|
138
|
+
PCT=$(awk -v r="$RATIO" 'BEGIN { printf "%d", (r - 1) * 100 }')
|
|
139
|
+
echo "NOTICE: output_tokens=${OUT_TOKENS} (model=${MODEL}) is ${PCT}% above your trailing-${WINDOW}-sample baseline (~${MEAN_INT})." >&2
|
|
140
|
+
echo " Possible Cluster 23 candidate signal (Opus 4.8 effort-budget regression, see #64153 / #64152 / #64143)." >&2
|
|
141
|
+
echo " Mitigations: switch via '/model claude-opus-4-7', set effort=low for routine turns, or audit with:" >&2
|
|
142
|
+
echo " jq -s 'map(.out_tokens) | sort | .[length/2]' ${LOG}" >&2
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
exit 0
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
#
|
|
3
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-package-json-guard-$PPID"
|
|
10
|
+
[ -f "$_nojq_warned" ] || {
|
|
11
|
+
echo "WARNING [package-json-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
|
+
|
|
4
16
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
5
17
|
[ -z "$COMMAND" ] && exit 0
|
|
6
18
|
if echo "$COMMAND" | grep -qE '\brm\b.*package\.json'; then
|
|
@@ -9,6 +9,18 @@
|
|
|
9
9
|
# TRIGGER: PreToolUse
|
|
10
10
|
# 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-package-lock-frozen-$PPID"
|
|
18
|
+
[ -f "$_nojq_warned" ] || {
|
|
19
|
+
echo "WARNING [package-lock-frozen]: 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
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.filePath // empty' 2>/dev/null)
|
|
14
26
|
[ -z "$FILE" ] && exit 0
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# parallel-batch-size-limiter.sh — Surface large parallel batches
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# The companion to parallel-cascade-detector.sh (which fires
|
|
7
|
+
# POST-cascade). This PRE-batch hook detects when a single
|
|
8
|
+
# assistant turn is firing many tool calls in quick succession
|
|
9
|
+
# (within a configurable batch window) and warns the operator
|
|
10
|
+
# BEFORE the batch can cascade.
|
|
11
|
+
#
|
|
12
|
+
# Why: a single failed tool call in a parallel batch cancels every
|
|
13
|
+
# sibling call (Issue #64059 / #64052 / #64047). Larger batches
|
|
14
|
+
# have larger cascade blast-radius. Capping batch size from the
|
|
15
|
+
# operator side keeps cascade radius small while the upstream
|
|
16
|
+
# "fan-out, continue on partial failure" semantic is still pending.
|
|
17
|
+
#
|
|
18
|
+
# DETECTION MODEL:
|
|
19
|
+
# PreToolUse fires per tool call. Same-batch parallel calls fire in
|
|
20
|
+
# quick succession (default within 500ms). This hook records each
|
|
21
|
+
# call's timestamp; on each new fire, it counts calls in the rolling
|
|
22
|
+
# batch window and warns when the count crosses a configurable
|
|
23
|
+
# threshold.
|
|
24
|
+
#
|
|
25
|
+
# CLUSTER:
|
|
26
|
+
# Candidate cluster #20 — parallel tool batch cancellation cascade
|
|
27
|
+
# Same cluster as parallel-cascade-detector.sh (PostToolUse companion).
|
|
28
|
+
#
|
|
29
|
+
# TRIGGER: PreToolUse MATCHER: ""
|
|
30
|
+
#
|
|
31
|
+
# ENV:
|
|
32
|
+
# CC_PARALLEL_BATCH_LIMITER_THRESHOLD default 6 (warn at 6+ siblings)
|
|
33
|
+
# CC_PARALLEL_BATCH_LIMITER_WINDOW_MS default 500
|
|
34
|
+
# CC_PARALLEL_BATCH_LIMITER_DISABLE non-empty → silent
|
|
35
|
+
# CC_PARALLEL_BATCH_LIMITER_QUIET non-empty → silent
|
|
36
|
+
# CC_PARALLEL_BATCH_LIMITER_STATE_DIR default /tmp/cc-parallel-batch
|
|
37
|
+
# ================================================================
|
|
38
|
+
|
|
39
|
+
set -u
|
|
40
|
+
|
|
41
|
+
# Disable / quiet
|
|
42
|
+
if [ -n "${CC_PARALLEL_BATCH_LIMITER_DISABLE:-}" ] || [ -n "${CC_PARALLEL_BATCH_LIMITER_QUIET:-}" ]; then
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
THRESHOLD="${CC_PARALLEL_BATCH_LIMITER_THRESHOLD:-6}"
|
|
47
|
+
WINDOW_MS="${CC_PARALLEL_BATCH_LIMITER_WINDOW_MS:-500}"
|
|
48
|
+
STATE_DIR="${CC_PARALLEL_BATCH_LIMITER_STATE_DIR:-/tmp/cc-parallel-batch}"
|
|
49
|
+
LOG_FILE="$STATE_DIR/batch.log"
|
|
50
|
+
WARN_FILE="$STATE_DIR/last-warn"
|
|
51
|
+
|
|
52
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
53
|
+
|
|
54
|
+
# Read input (don't fail if jq missing — just exit silently)
|
|
55
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
56
|
+
[ -z "$INPUT" ] && exit 0
|
|
57
|
+
|
|
58
|
+
# Current time in milliseconds (portable across GNU and BSD date)
|
|
59
|
+
NOW_MS=$(date +%s%3N 2>/dev/null)
|
|
60
|
+
if [ -z "$NOW_MS" ] || [ "${#NOW_MS}" -lt 13 ]; then
|
|
61
|
+
# macOS / BSD date doesn't support %N — fall back to seconds * 1000
|
|
62
|
+
NOW_S=$(date +%s)
|
|
63
|
+
NOW_MS=$((NOW_S * 1000))
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Record this fire
|
|
67
|
+
printf '%s\n' "$NOW_MS" >> "$LOG_FILE"
|
|
68
|
+
|
|
69
|
+
# Compute cutoff (NOW - WINDOW_MS)
|
|
70
|
+
CUTOFF=$((NOW_MS - WINDOW_MS))
|
|
71
|
+
|
|
72
|
+
# Count events in window and prune old entries
|
|
73
|
+
COUNT=0
|
|
74
|
+
TMP_LOG=$(mktemp)
|
|
75
|
+
while IFS= read -r ts; do
|
|
76
|
+
# Skip malformed entries
|
|
77
|
+
case "$ts" in
|
|
78
|
+
''|*[!0-9]*) continue ;;
|
|
79
|
+
esac
|
|
80
|
+
if [ "$ts" -ge "$CUTOFF" ] 2>/dev/null; then
|
|
81
|
+
printf '%s\n' "$ts" >> "$TMP_LOG"
|
|
82
|
+
COUNT=$((COUNT + 1))
|
|
83
|
+
fi
|
|
84
|
+
done < "$LOG_FILE"
|
|
85
|
+
mv "$TMP_LOG" "$LOG_FILE" 2>/dev/null
|
|
86
|
+
|
|
87
|
+
# Warn only when threshold is freshly crossed (debounce repeat warnings within
|
|
88
|
+
# the same batch — checking last-warn timestamp).
|
|
89
|
+
if [ "$COUNT" -ge "$THRESHOLD" ]; then
|
|
90
|
+
LAST_WARN=0
|
|
91
|
+
if [ -f "$WARN_FILE" ]; then
|
|
92
|
+
LAST_WARN=$(cat "$WARN_FILE" 2>/dev/null || echo 0)
|
|
93
|
+
fi
|
|
94
|
+
# Only warn if last warning was outside the current batch window
|
|
95
|
+
if [ "$LAST_WARN" -lt "$CUTOFF" ] 2>/dev/null; then
|
|
96
|
+
printf '%s' "$NOW_MS" > "$WARN_FILE"
|
|
97
|
+
cat >&2 <<EOF
|
|
98
|
+
|
|
99
|
+
⚠️ Large parallel batch detected: $COUNT tool calls in the last ${WINDOW_MS}ms.
|
|
100
|
+
|
|
101
|
+
What this means:
|
|
102
|
+
A single failed tool call in this batch will cancel every sibling
|
|
103
|
+
call with "Cancelled: parallel tool call X errored" (Issue #64059
|
|
104
|
+
/ #64052 / #64047). Larger batches have larger cascade radius.
|
|
105
|
+
The model may then misattribute the cascade to a user interrupt
|
|
106
|
+
and fabricate user statements that never happened.
|
|
107
|
+
|
|
108
|
+
Recommended:
|
|
109
|
+
Cap parallel batches at N=3-5 in CLAUDE.md guidance.
|
|
110
|
+
Common non-fatal triggers to keep OUT of parallel batches:
|
|
111
|
+
- git with potentially-invalid revisions (exit 128)
|
|
112
|
+
- curl probes expected to return 404
|
|
113
|
+
- pkill with nothing matching (exit 144)
|
|
114
|
+
|
|
115
|
+
Tracking: cc-safe-setup candidate cluster #20.
|
|
116
|
+
Defense companion: parallel-cascade-detector.sh (PostToolUse).
|
|
117
|
+
EOF
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
exit 0
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# parallel-cascade-detector.sh — Detect parallel-batch cascade
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# When Claude Code sends parallel tool calls in a single assistant
|
|
7
|
+
# turn and one of them errors, all sibling calls are cancelled with
|
|
8
|
+
# "Cancelled: parallel tool call X errored" — even when the failure
|
|
9
|
+
# is non-fatal (exit 144 from pkill, expected 404 from curl,
|
|
10
|
+
# invalid git revision, etc.).
|
|
11
|
+
#
|
|
12
|
+
# Two problems:
|
|
13
|
+
# 1. The whole batch's compute is wasted (40-100K tokens / cascade).
|
|
14
|
+
# 2. The cancellation message is indistinguishable from a user
|
|
15
|
+
# interrupt, so the model itself can misattribute the cascade
|
|
16
|
+
# to user action and fabricate user statements ("You're right
|
|
17
|
+
# to stop me…") — see Issue #64047.
|
|
18
|
+
#
|
|
19
|
+
# This hook counts cascade events in a rolling time window and
|
|
20
|
+
# warns when the count crosses a configurable threshold. It does
|
|
21
|
+
# NOT prevent cascades (the policy is upstream) — it surfaces them
|
|
22
|
+
# so operators can recognize the pattern and restructure batches.
|
|
23
|
+
#
|
|
24
|
+
# CLUSTER:
|
|
25
|
+
# Candidate cluster #20 — parallel tool batch cancellation cascade
|
|
26
|
+
# 3 independent reports on 2026-05-30:
|
|
27
|
+
# - #64059 (enrico2468) - confirmed behavior across long sessions
|
|
28
|
+
# - #64052 (omar16100) - minimal reproduction on v2.1.158
|
|
29
|
+
# - #64047 (snichols) - the indistinguishability + fabrication
|
|
30
|
+
#
|
|
31
|
+
# TRIGGER: PostToolUse MATCHER: ""
|
|
32
|
+
#
|
|
33
|
+
# ENV:
|
|
34
|
+
# CC_PARALLEL_CASCADE_THRESHOLD default 5
|
|
35
|
+
# CC_PARALLEL_CASCADE_WINDOW_SEC default 60
|
|
36
|
+
# CC_PARALLEL_CASCADE_DISABLE non-empty → silent
|
|
37
|
+
# CC_PARALLEL_CASCADE_QUIET non-empty → silent
|
|
38
|
+
# CC_PARALLEL_CASCADE_STATE_DIR default /tmp/cc-parallel-cascade
|
|
39
|
+
# ================================================================
|
|
40
|
+
|
|
41
|
+
set -u
|
|
42
|
+
|
|
43
|
+
# Disable / quiet
|
|
44
|
+
if [ -n "${CC_PARALLEL_CASCADE_DISABLE:-}" ] || [ -n "${CC_PARALLEL_CASCADE_QUIET:-}" ]; then
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
THRESHOLD="${CC_PARALLEL_CASCADE_THRESHOLD:-5}"
|
|
49
|
+
WINDOW_SEC="${CC_PARALLEL_CASCADE_WINDOW_SEC:-60}"
|
|
50
|
+
STATE_DIR="${CC_PARALLEL_CASCADE_STATE_DIR:-/tmp/cc-parallel-cascade}"
|
|
51
|
+
LOG_FILE="$STATE_DIR/events.log"
|
|
52
|
+
|
|
53
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
54
|
+
|
|
55
|
+
INPUT=$(cat)
|
|
56
|
+
|
|
57
|
+
# Extract tool_response (cancellation message lives here)
|
|
58
|
+
RESPONSE=$(printf '%s' "$INPUT" | jq -r '.tool_response // .tool_result // empty' 2>/dev/null)
|
|
59
|
+
|
|
60
|
+
# Some Claude Code versions wrap tool_response as an object; try common nested fields
|
|
61
|
+
if [ -z "$RESPONSE" ]; then
|
|
62
|
+
RESPONSE=$(printf '%s' "$INPUT" | jq -r '.tool_response.output // .tool_response.error // .tool_response.text // empty' 2>/dev/null)
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# If no response at all, nothing to count
|
|
66
|
+
[ -z "$RESPONSE" ] && exit 0
|
|
67
|
+
|
|
68
|
+
# Detect the cascade signature
|
|
69
|
+
# Pattern: "Cancelled: parallel tool call X errored" (case-insensitive on cancelled)
|
|
70
|
+
if printf '%s' "$RESPONSE" | grep -qiE 'Cancelled:[[:space:]]+parallel tool call[[:space:]]+.*errored'; then
|
|
71
|
+
NOW=$(date +%s)
|
|
72
|
+
# Append event timestamp
|
|
73
|
+
printf '%s\n' "$NOW" >> "$LOG_FILE"
|
|
74
|
+
|
|
75
|
+
# Compute cutoff
|
|
76
|
+
CUTOFF=$((NOW - WINDOW_SEC))
|
|
77
|
+
|
|
78
|
+
# Count events within window and rewrite log to prune old entries
|
|
79
|
+
COUNT=0
|
|
80
|
+
TMP_LOG=$(mktemp)
|
|
81
|
+
while IFS= read -r ts; do
|
|
82
|
+
if [ "$ts" -ge "$CUTOFF" ] 2>/dev/null; then
|
|
83
|
+
printf '%s\n' "$ts" >> "$TMP_LOG"
|
|
84
|
+
COUNT=$((COUNT + 1))
|
|
85
|
+
fi
|
|
86
|
+
done < "$LOG_FILE"
|
|
87
|
+
mv "$TMP_LOG" "$LOG_FILE" 2>/dev/null
|
|
88
|
+
|
|
89
|
+
# Warn at threshold
|
|
90
|
+
if [ "$COUNT" -ge "$THRESHOLD" ]; then
|
|
91
|
+
cat >&2 <<EOF
|
|
92
|
+
|
|
93
|
+
⚠️ Parallel-batch cascade detected: $COUNT cancellation events in the last ${WINDOW_SEC}s.
|
|
94
|
+
|
|
95
|
+
What this means:
|
|
96
|
+
A single failed tool call in a parallel batch cancels every sibling
|
|
97
|
+
call with "Cancelled: parallel tool call X errored". The model can
|
|
98
|
+
misattribute these cancellations to a user interrupt and may
|
|
99
|
+
fabricate user statements that never happened. See Issue #64047
|
|
100
|
+
for a worked example (25-call cascade → 2-hour fabricated user
|
|
101
|
+
state, zero actual user input).
|
|
102
|
+
|
|
103
|
+
Operator-side mitigation today:
|
|
104
|
+
1. Reduce parallel batch size to N=3-5 via CLAUDE.md guidance.
|
|
105
|
+
2. Audit transcripts:
|
|
106
|
+
grep -c "parallel tool call.*errored" ~/.claude/projects/*/recent.jsonl
|
|
107
|
+
3. Avoid git / curl / pkill in parallel batches when the
|
|
108
|
+
failure-on-empty case is common — they are the 3 most-cited
|
|
109
|
+
cascade triggers in the cluster reports (#64059 / #64052 / #64047).
|
|
110
|
+
|
|
111
|
+
Tracking: cc-safe-setup candidate cluster #20.
|
|
112
|
+
EOF
|
|
113
|
+
fi
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
exit 0
|