cc-safe-setup 29.7.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-circuit-breaker.sh +72 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +89 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/thinking-stall-detector.sh +61 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-circuit-breaker.sh +134 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-exploration-budget-guard.sh +164 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-thinking-stall-detector.sh +151 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -18,6 +18,18 @@
|
|
|
18
18
|
|
|
19
19
|
set -euo pipefail
|
|
20
20
|
|
|
21
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
22
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
23
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
24
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
25
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
26
|
+
_nojq_warned="/tmp/cc-nojq-warned-role-tool-guard-$PPID"
|
|
27
|
+
[ -f "$_nojq_warned" ] || {
|
|
28
|
+
echo "WARNING [role-tool-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
29
|
+
: > "$_nojq_warned"
|
|
30
|
+
}
|
|
31
|
+
fi
|
|
32
|
+
|
|
21
33
|
INPUT=$(cat)
|
|
22
34
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
23
35
|
[ -z "$TOOL" ] && exit 0
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# route-handler-emptiness-gate.sh — Refuse Write/Edit when a route handler method
|
|
3
|
+
# body would ship with the surface form of a handler (auth + redirect + return)
|
|
4
|
+
# but with no data-mutation line (no save, update, create, insert, delete).
|
|
5
|
+
#
|
|
6
|
+
# Solves: anthropics/claude-code #61107 — "Opus 4.7 produces structurally
|
|
7
|
+
# correct code that silently discards user input." The four documented cases
|
|
8
|
+
# in that issue body share a shape: signature correct, auth check correct,
|
|
9
|
+
# redirect correct, the one line that materializes the side effect missing.
|
|
10
|
+
# A code review at a glance passes; the patient's reflection is silently
|
|
11
|
+
# discarded; the DELETE returns 200 with the row still present.
|
|
12
|
+
#
|
|
13
|
+
# RUSE Surface application: the operator's intent ("a route handler must
|
|
14
|
+
# materialize the request's effect on persistent state") is a wider semantic
|
|
15
|
+
# surface than any single deny rule or naming convention. The model honours
|
|
16
|
+
# the convention's named exemplars (handler signature, auth, redirect, route
|
|
17
|
+
# name) while skipping the rule's synonymous edge (the data-mutation line).
|
|
18
|
+
# This hook gates against the effect predicate (must contain a mutation),
|
|
19
|
+
# not against the surface convention (must look like a handler).
|
|
20
|
+
#
|
|
21
|
+
# TRIGGER: PreToolUse
|
|
22
|
+
# MATCHER: Write|Edit|MultiEdit
|
|
23
|
+
#
|
|
24
|
+
# SCOPE: PHP files only by default (the documented case is Laravel). Set
|
|
25
|
+
# CC_HANDLER_GATE_LANGUAGES to a comma-separated list to add languages
|
|
26
|
+
# (currently supported: php).
|
|
27
|
+
#
|
|
28
|
+
# MODE:
|
|
29
|
+
# advisory (default) — emits a system-reminder, allows the write
|
|
30
|
+
# strict — exits 2, refuses the write
|
|
31
|
+
#
|
|
32
|
+
# CONFIGURATION:
|
|
33
|
+
# CC_HANDLER_GATE_MODE advisory | strict (default: advisory)
|
|
34
|
+
# CC_HANDLER_GATE_LANGUAGES comma-separated list (default: php)
|
|
35
|
+
# CC_HANDLER_GATE_PATHS regex of paths to gate (default: /[Cc]ontrollers?/)
|
|
36
|
+
# CC_HANDLER_GATE_DISABLE set to "1" to disable (default: unset)
|
|
37
|
+
#
|
|
38
|
+
# DETECTION HEURISTIC (PHP / Laravel):
|
|
39
|
+
# A method body is flagged if ALL of:
|
|
40
|
+
# - The method body contains at least one of:
|
|
41
|
+
# auth(), Auth::, $request->user(), redirect(, return redirect(,
|
|
42
|
+
# response()->json(, return response()
|
|
43
|
+
# AND
|
|
44
|
+
# - The method body contains NONE of:
|
|
45
|
+
# ->save(, ::create(, ->update(, ::insert(, ->delete(, ::firstOrCreate(,
|
|
46
|
+
# ::updateOrCreate(, ->fill(, DB::table(, DB::insert, DB::update,
|
|
47
|
+
# DB::delete, Eloquent::, ->push(, ->associate(, ->detach(, ->sync(
|
|
48
|
+
# AND
|
|
49
|
+
# - The method body contains no PHP-side function call that names
|
|
50
|
+
# something like Service, Repository, Action (heuristic for service-
|
|
51
|
+
# layer pattern where the mutation is delegated)
|
|
52
|
+
#
|
|
53
|
+
# RELATED ISSUES:
|
|
54
|
+
# anthropics/claude-code #61107 (@nvst18, 2026-05-21) — direct motivation
|
|
55
|
+
# anthropics/claude-code #60226 (@suwayama, 2026-05-18) — structural parent
|
|
56
|
+
# anthropics/claude-code #60977 (@beq00000, 2026-05-20) — RUSE articulation
|
|
57
|
+
#
|
|
58
|
+
# USAGE (settings.json):
|
|
59
|
+
# {
|
|
60
|
+
# "hooks": {
|
|
61
|
+
# "PreToolUse": [
|
|
62
|
+
# {
|
|
63
|
+
# "matcher": "Write|Edit|MultiEdit",
|
|
64
|
+
# "hooks": [{"type":"command","command":"~/.claude/hooks/route-handler-emptiness-gate.sh"}]
|
|
65
|
+
# }
|
|
66
|
+
# ]
|
|
67
|
+
# }
|
|
68
|
+
# }
|
|
69
|
+
|
|
70
|
+
set -euo pipefail
|
|
71
|
+
|
|
72
|
+
# Bail if disabled
|
|
73
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
74
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
75
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
76
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
77
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
78
|
+
_nojq_warned="/tmp/cc-nojq-warned-route-handler-emptiness-gate-$PPID"
|
|
79
|
+
[ -f "$_nojq_warned" ] || {
|
|
80
|
+
echo "WARNING [route-handler-emptiness-gate]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
81
|
+
: > "$_nojq_warned"
|
|
82
|
+
}
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [ "${CC_HANDLER_GATE_DISABLE:-}" = "1" ]; then
|
|
86
|
+
exit 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
INPUT=$(cat)
|
|
90
|
+
|
|
91
|
+
MODE="${CC_HANDLER_GATE_MODE:-advisory}"
|
|
92
|
+
LANGUAGES="${CC_HANDLER_GATE_LANGUAGES:-php}"
|
|
93
|
+
PATH_REGEX="${CC_HANDLER_GATE_PATHS:-/[Cc]ontrollers?/}"
|
|
94
|
+
|
|
95
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
96
|
+
case "$TOOL" in
|
|
97
|
+
Write|Edit|MultiEdit) ;;
|
|
98
|
+
*) exit 0 ;;
|
|
99
|
+
esac
|
|
100
|
+
|
|
101
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
102
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
103
|
+
|
|
104
|
+
# Language and path gating
|
|
105
|
+
case "$FILE_PATH" in
|
|
106
|
+
*.php) ;;
|
|
107
|
+
*) exit 0 ;;
|
|
108
|
+
esac
|
|
109
|
+
|
|
110
|
+
# Only run if the path matches the configured controller-path regex
|
|
111
|
+
if ! echo "$FILE_PATH" | grep -qE "$PATH_REGEX"; then
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Extract the content the model is about to write
|
|
116
|
+
CONTENT=$(echo "$INPUT" | jq -r '
|
|
117
|
+
.tool_input.content //
|
|
118
|
+
.tool_input.new_string //
|
|
119
|
+
(if .tool_input.edits then (.tool_input.edits | map(.new_string) | join("\n")) else empty end) //
|
|
120
|
+
empty
|
|
121
|
+
' 2>/dev/null)
|
|
122
|
+
|
|
123
|
+
[ -z "$CONTENT" ] && exit 0
|
|
124
|
+
|
|
125
|
+
# Detection: look for PHP method bodies and check each one.
|
|
126
|
+
# This is a regex-based heuristic; a full PHP AST is out of scope for a bash hook.
|
|
127
|
+
# The trade is documented in the methodology note — heuristic-with-false-positive-surface,
|
|
128
|
+
# not strict parsing.
|
|
129
|
+
|
|
130
|
+
# Extract candidate method bodies using a Python helper for reliability
|
|
131
|
+
FLAGGED=$(python3 - "$CONTENT" <<'PYEOF'
|
|
132
|
+
import sys, re
|
|
133
|
+
|
|
134
|
+
content = sys.argv[1] if len(sys.argv) > 1 else sys.stdin.read()
|
|
135
|
+
|
|
136
|
+
# Find PHP method definitions: public/protected function name(...) { ... }
|
|
137
|
+
# We use a non-greedy match for the method body, but PHP can have nested braces,
|
|
138
|
+
# so we use a brace-counting approach.
|
|
139
|
+
|
|
140
|
+
method_re = re.compile(
|
|
141
|
+
r'(public|protected|private)\s+function\s+(\w+)\s*\([^)]*\)\s*(?::\s*[\w\\]+\s*)?\{',
|
|
142
|
+
re.MULTILINE
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Patterns that indicate "looks like a handler" (HTTP-shaped activity)
|
|
146
|
+
HANDLER_LIKE = [
|
|
147
|
+
r'auth\(\)',
|
|
148
|
+
r'Auth::',
|
|
149
|
+
r'\$request->user\(\)',
|
|
150
|
+
r'redirect\s*\(',
|
|
151
|
+
r'response\(\)',
|
|
152
|
+
r'return\s+view\(',
|
|
153
|
+
r'->json\(',
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
# Patterns that indicate "data mutation actually happens"
|
|
157
|
+
MUTATION = [
|
|
158
|
+
r'->save\(',
|
|
159
|
+
r'::create\(',
|
|
160
|
+
r'->update\(',
|
|
161
|
+
r'::insert\(',
|
|
162
|
+
r'->delete\(',
|
|
163
|
+
r'::firstOrCreate\(',
|
|
164
|
+
r'::updateOrCreate\(',
|
|
165
|
+
r'->fill\(',
|
|
166
|
+
r'DB::table\(',
|
|
167
|
+
r'DB::insert',
|
|
168
|
+
r'DB::update',
|
|
169
|
+
r'DB::delete',
|
|
170
|
+
r'->push\(',
|
|
171
|
+
r'->associate\(',
|
|
172
|
+
r'->detach\(',
|
|
173
|
+
r'->sync\(',
|
|
174
|
+
r'->touch\(',
|
|
175
|
+
r'->forceDelete\(',
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
# Service/Action/Repository delegation pattern (mutation may be delegated)
|
|
179
|
+
SERVICE_DELEGATION = [
|
|
180
|
+
r'\$\w*[Ss]ervice\b',
|
|
181
|
+
r'\$\w*[Rr]epository\b',
|
|
182
|
+
r'\$\w*[Aa]ction\b',
|
|
183
|
+
r'\$\w*[Hh]andler\b',
|
|
184
|
+
r'->dispatch\(',
|
|
185
|
+
r'::dispatch\(', # Job::dispatch() static call
|
|
186
|
+
r'->execute\(',
|
|
187
|
+
r'->perform\(',
|
|
188
|
+
r'->store\(\s*\$', # Service store with parameter
|
|
189
|
+
r'->handle\(\s*\$',
|
|
190
|
+
r'event\s*\(\s*new\s+', # event(new MyEvent()) dispatches listeners
|
|
191
|
+
r'->notify\(', # Notification::send() / $user->notify(...)
|
|
192
|
+
r'Notification::send\(',
|
|
193
|
+
r'broadcast\s*\(', # broadcast(new MyEvent())
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
# Exempt method names that legitimately don't mutate
|
|
197
|
+
READ_ONLY_NAMES = {
|
|
198
|
+
'index', 'show', 'view', 'create', 'edit', # standard CRUD read methods
|
|
199
|
+
'get', 'list', 'find', 'search', 'fetch',
|
|
200
|
+
'__construct', '__destruct', '__invoke', 'rules', 'authorize',
|
|
201
|
+
'middleware', 'register', 'boot',
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# Mutating method names where emptiness is suspicious
|
|
205
|
+
MUTATING_NAMES = {
|
|
206
|
+
'store', 'update', 'destroy', 'delete',
|
|
207
|
+
'patch', 'put', 'restore', 'archive',
|
|
208
|
+
'attach', 'detach', 'sync', 'associate',
|
|
209
|
+
'process', 'handle', 'execute', 'perform',
|
|
210
|
+
'save', 'submit', 'send', 'publish',
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
def has_pattern(body, patterns):
|
|
214
|
+
return any(re.search(p, body) for p in patterns)
|
|
215
|
+
|
|
216
|
+
def extract_body(text, start_pos):
|
|
217
|
+
"""Brace-match from text[start_pos] (which should be after the opening {)."""
|
|
218
|
+
depth = 1
|
|
219
|
+
i = start_pos
|
|
220
|
+
while i < len(text) and depth > 0:
|
|
221
|
+
# Skip strings naively
|
|
222
|
+
c = text[i]
|
|
223
|
+
if c == '"' or c == "'":
|
|
224
|
+
quote = c
|
|
225
|
+
i += 1
|
|
226
|
+
while i < len(text) and text[i] != quote:
|
|
227
|
+
if text[i] == '\\':
|
|
228
|
+
i += 2
|
|
229
|
+
else:
|
|
230
|
+
i += 1
|
|
231
|
+
i += 1
|
|
232
|
+
elif c == '/' and i + 1 < len(text) and text[i+1] == '/':
|
|
233
|
+
# line comment
|
|
234
|
+
while i < len(text) and text[i] != '\n':
|
|
235
|
+
i += 1
|
|
236
|
+
elif c == '/' and i + 1 < len(text) and text[i+1] == '*':
|
|
237
|
+
i += 2
|
|
238
|
+
while i + 1 < len(text) and not (text[i] == '*' and text[i+1] == '/'):
|
|
239
|
+
i += 1
|
|
240
|
+
i += 2
|
|
241
|
+
elif c == '{':
|
|
242
|
+
depth += 1
|
|
243
|
+
i += 1
|
|
244
|
+
elif c == '}':
|
|
245
|
+
depth -= 1
|
|
246
|
+
i += 1
|
|
247
|
+
else:
|
|
248
|
+
i += 1
|
|
249
|
+
return text[start_pos:i-1] if depth == 0 else text[start_pos:]
|
|
250
|
+
|
|
251
|
+
flags = []
|
|
252
|
+
for m in method_re.finditer(content):
|
|
253
|
+
visibility = m.group(1)
|
|
254
|
+
name = m.group(2)
|
|
255
|
+
body_start = m.end()
|
|
256
|
+
body = extract_body(content, body_start)
|
|
257
|
+
|
|
258
|
+
# Skip very short bodies (likely abstract/interface stubs) and empty constructors
|
|
259
|
+
if len(body.strip()) < 3:
|
|
260
|
+
continue
|
|
261
|
+
|
|
262
|
+
# Read-only method names are exempt
|
|
263
|
+
if name in READ_ONLY_NAMES:
|
|
264
|
+
continue
|
|
265
|
+
|
|
266
|
+
# Method names that should mutate get extra scrutiny: flag emptiness if no mutation
|
|
267
|
+
is_mutating_name = name in MUTATING_NAMES
|
|
268
|
+
|
|
269
|
+
looks_like_handler = has_pattern(body, HANDLER_LIKE)
|
|
270
|
+
has_mutation = has_pattern(body, MUTATION)
|
|
271
|
+
has_service = has_pattern(body, SERVICE_DELEGATION)
|
|
272
|
+
|
|
273
|
+
if is_mutating_name and not has_mutation and not has_service:
|
|
274
|
+
flags.append({
|
|
275
|
+
'method': name,
|
|
276
|
+
'visibility': visibility,
|
|
277
|
+
'reason': f'mutating-named method ({name!r}) has no data-mutation call and no service delegation'
|
|
278
|
+
})
|
|
279
|
+
elif looks_like_handler and not has_mutation and not has_service:
|
|
280
|
+
# Handler-shape body without mutation: flag with lower severity
|
|
281
|
+
flags.append({
|
|
282
|
+
'method': name,
|
|
283
|
+
'visibility': visibility,
|
|
284
|
+
'reason': f'handler-shape method ({name!r}) has no data-mutation call and no service delegation'
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
for f in flags:
|
|
288
|
+
print(f"{f['visibility']}|{f['method']}|{f['reason']}")
|
|
289
|
+
PYEOF
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
if [ -z "$FLAGGED" ]; then
|
|
293
|
+
exit 0
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
# Build the warning message
|
|
297
|
+
{
|
|
298
|
+
echo "⚠️ route-handler-emptiness-gate: detected $(echo "$FLAGGED" | wc -l) method(s) with handler shape but no data mutation:"
|
|
299
|
+
echo ""
|
|
300
|
+
echo "$FLAGGED" | while IFS='|' read -r vis name reason; do
|
|
301
|
+
echo " - $vis function $name(): $reason"
|
|
302
|
+
done
|
|
303
|
+
echo ""
|
|
304
|
+
echo "Reference: anthropics/claude-code#61107 — the four documented failure cases in"
|
|
305
|
+
echo "@nvst18's report share this shape (storeResearchReflection, destroy(),"
|
|
306
|
+
echo "validate-without-capture, dead conditionals)."
|
|
307
|
+
echo ""
|
|
308
|
+
echo "File: $FILE_PATH"
|
|
309
|
+
echo "Mode: $MODE"
|
|
310
|
+
echo ""
|
|
311
|
+
if [ "$MODE" = "strict" ]; then
|
|
312
|
+
echo "Refusing write. To override for this turn, set CC_HANDLER_GATE_MODE=advisory."
|
|
313
|
+
else
|
|
314
|
+
echo "Allowing write (advisory). Set CC_HANDLER_GATE_MODE=strict to block."
|
|
315
|
+
echo "If the method is intentionally a no-op (deprecated endpoint, soft-removal stub),"
|
|
316
|
+
echo "add a comment or a noop() marker the model is more likely to inspect on review."
|
|
317
|
+
fi
|
|
318
|
+
} >&2
|
|
319
|
+
|
|
320
|
+
if [ "$MODE" = "strict" ]; then
|
|
321
|
+
exit 2
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
exit 0
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# }
|
|
19
19
|
# ================================================================
|
|
20
20
|
#
|
|
21
|
-
# TRIGGER:
|
|
21
|
+
# TRIGGER: PostToolUse MATCHER: "Edit|Write"
|
|
22
22
|
|
|
23
23
|
INPUT=$(cat)
|
|
24
24
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# runtime-binary-change-detector.sh — Alert when the Claude Code binary changes between sessions.
|
|
3
|
+
#
|
|
4
|
+
# Solves: Operators who customize their workflow (hooks, slash commands, skills,
|
|
5
|
+
# system-prompt patches) can have behavior shift silently when the Claude
|
|
6
|
+
# Code binary is updated. Public discussion of this pattern includes
|
|
7
|
+
# matheusmoreira's Tell HN "Claude Code now allows Anthropic to remotely
|
|
8
|
+
# inject system prompts" — operators want a between-session signal that
|
|
9
|
+
# something changed, prompting a behavior re-verification before relying
|
|
10
|
+
# on prior workflow assumptions.
|
|
11
|
+
#
|
|
12
|
+
# How it works: On SessionStart, compute a fingerprint of the resolved `claude`
|
|
13
|
+
# binary (path + --version + size_mtime), compare against the fingerprint
|
|
14
|
+
# stored from the previous session, and print an advisory warning to stderr if
|
|
15
|
+
# they differ. State is stored at ~/.claude/runtime-binary-state.txt.
|
|
16
|
+
#
|
|
17
|
+
# This is an advisory hook (exit 0 in all cases); it never blocks. The signal
|
|
18
|
+
# tells the operator to verify hooks, slash commands, and skills still behave
|
|
19
|
+
# as expected after the binary changed.
|
|
20
|
+
#
|
|
21
|
+
# TRIGGER: SessionStart
|
|
22
|
+
# MATCHER: "" (all sessions)
|
|
23
|
+
#
|
|
24
|
+
# Env knobs:
|
|
25
|
+
# CC_BINARY_DETECTOR_SILENT=1 — suppress the alert (useful in CI / automation
|
|
26
|
+
# where the alert is logged elsewhere)
|
|
27
|
+
|
|
28
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
29
|
+
EVENT=$(echo "$INPUT" | jq -r '.event // .hook_event_name // empty' 2>/dev/null)
|
|
30
|
+
|
|
31
|
+
# Only run on session start; let other events pass.
|
|
32
|
+
case "$EVENT" in
|
|
33
|
+
session_start|SessionStart|"") ;;
|
|
34
|
+
*) exit 0 ;;
|
|
35
|
+
esac
|
|
36
|
+
|
|
37
|
+
STATE_FILE="${HOME}/.claude/runtime-binary-state.txt"
|
|
38
|
+
mkdir -p "$(dirname "$STATE_FILE")"
|
|
39
|
+
|
|
40
|
+
# Locate the claude binary. Bail silently if it's not on PATH — this hook
|
|
41
|
+
# shouldn't error in environments where Claude Code is invoked by absolute
|
|
42
|
+
# path or through a wrapper.
|
|
43
|
+
CLAUDE_BIN=$(command -v claude 2>/dev/null)
|
|
44
|
+
[ -z "$CLAUDE_BIN" ] && exit 0
|
|
45
|
+
|
|
46
|
+
# Resolve symlinks so version managers (asdf / volta / nvm) don't produce a
|
|
47
|
+
# spurious change every session from re-shimmed paths.
|
|
48
|
+
RESOLVED_BIN=$(readlink -f "$CLAUDE_BIN" 2>/dev/null || echo "$CLAUDE_BIN")
|
|
49
|
+
|
|
50
|
+
# Version string (best-effort; some wrappers reject --version).
|
|
51
|
+
VERSION=$("$RESOLVED_BIN" --version 2>/dev/null | head -1 | tr -d '\r' | head -c 200)
|
|
52
|
+
[ -z "$VERSION" ] && VERSION="version-unavailable"
|
|
53
|
+
|
|
54
|
+
# Size + mtime as a lightweight content fingerprint. Full sha256 would be more
|
|
55
|
+
# correct but is overkill at SessionStart latency; size+mtime catches every
|
|
56
|
+
# update path that swaps the binary (npm install, brew upgrade, manual replace).
|
|
57
|
+
if SIZE_MTIME=$(stat -c "%s_%Y" "$RESOLVED_BIN" 2>/dev/null); then
|
|
58
|
+
:
|
|
59
|
+
elif SIZE_MTIME=$(stat -f "%z_%m" "$RESOLVED_BIN" 2>/dev/null); then
|
|
60
|
+
:
|
|
61
|
+
else
|
|
62
|
+
SIZE_MTIME="stat-unavailable"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
CURRENT_STATE="${RESOLVED_BIN}|${VERSION}|${SIZE_MTIME}"
|
|
66
|
+
|
|
67
|
+
# First-session bootstrap: record state, no warning.
|
|
68
|
+
if [ ! -f "$STATE_FILE" ]; then
|
|
69
|
+
printf "%s\n" "$CURRENT_STATE" > "$STATE_FILE"
|
|
70
|
+
exit 0
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
PREV_STATE=$(head -1 "$STATE_FILE" 2>/dev/null)
|
|
74
|
+
|
|
75
|
+
if [ "$PREV_STATE" != "$CURRENT_STATE" ] && [ "${CC_BINARY_DETECTOR_SILENT:-}" != "1" ]; then
|
|
76
|
+
# Decompose for readability.
|
|
77
|
+
PREV_VER=$(printf "%s" "$PREV_STATE" | awk -F'|' '{print $2}')
|
|
78
|
+
CURR_VER=$(printf "%s" "$CURRENT_STATE" | awk -F'|' '{print $2}')
|
|
79
|
+
|
|
80
|
+
{
|
|
81
|
+
echo "⚠ Claude Code binary changed since the previous session."
|
|
82
|
+
if [ "$PREV_VER" != "$CURR_VER" ]; then
|
|
83
|
+
echo " ${PREV_VER} → ${CURR_VER}"
|
|
84
|
+
else
|
|
85
|
+
echo " Same --version string, but the binary's size or mtime moved."
|
|
86
|
+
echo " Path: ${RESOLVED_BIN}"
|
|
87
|
+
fi
|
|
88
|
+
echo " Release notes: https://github.com/anthropics/claude-code/releases"
|
|
89
|
+
echo " Verify before relying on prior behavior:"
|
|
90
|
+
echo " 1. Your custom hooks still fire on the expected events"
|
|
91
|
+
echo " 2. Slash commands return the same shape"
|
|
92
|
+
echo " 3. Skills load with the same precedence"
|
|
93
|
+
echo " 4. System-prompt patches (if any) survived the update"
|
|
94
|
+
echo " Silence with: export CC_BINARY_DETECTOR_SILENT=1"
|
|
95
|
+
} >&2
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# Always update state. Even on silent-mode the new fingerprint should be stored
|
|
99
|
+
# so the next non-silent session compares against the correct baseline.
|
|
100
|
+
printf "%s\n" "$CURRENT_STATE" > "$STATE_FILE"
|
|
101
|
+
|
|
102
|
+
exit 0
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# same-command-repeat-detector.sh — Block Opus 4.8 same-command repeat-execution
|
|
3
|
+
# (Cluster 25 candidate, axis 25F — non-no-op compensation repeat)
|
|
4
|
+
#
|
|
5
|
+
# Background:
|
|
6
|
+
# Sibling of axis 25B (echo-probe spam) with one operationally critical
|
|
7
|
+
# difference: this axis fires on REAL, non-no-op commands. Where 25B emits
|
|
8
|
+
# "echo s1, echo s2, ..." (cluttering screen but burning minimal CPU), 25F
|
|
9
|
+
# re-emits the same real build/test/lint/deploy command 5–10 times in a
|
|
10
|
+
# row — burning actual CPU, wall-clock, build artefact churn, and tokens.
|
|
11
|
+
#
|
|
12
|
+
# The root mechanic is the same as 25B: the model perceives non-receipt of
|
|
13
|
+
# the previous result and emits another invocation hoping it will land.
|
|
14
|
+
# The model cannot distinguish:
|
|
15
|
+
# - result-delivery-failed (call ran, output didn't reach model)
|
|
16
|
+
# - result-was-empty (call ran, output really was empty)
|
|
17
|
+
# - result-arrived-but-missed (call ran, output present, attention drift)
|
|
18
|
+
# All three produce the same retry burst, but the cost shape on 25F is
|
|
19
|
+
# 1–2 orders of magnitude worse than 25B because the repeated command
|
|
20
|
+
# is real work.
|
|
21
|
+
#
|
|
22
|
+
# Anchor case:
|
|
23
|
+
# #63887 (comment by @KamilDev, 2026-05-31 23:37 UTC) —
|
|
24
|
+
# "it decided to fire off a build command ten times in a row.
|
|
25
|
+
# This isn't just annoying to look at; it's wasting CPU and time."
|
|
26
|
+
# (Screenshots in the thread show 10 consecutive identical build calls.)
|
|
27
|
+
#
|
|
28
|
+
# Sibling axes (Cluster 25, all observed 2026-05-30 to 2026-06-01):
|
|
29
|
+
# 25A — late/empty tool-result delivery (substrate, no operator-side fix)
|
|
30
|
+
# 25B — echo-probe spam compensation (echo-probe-spam-detector.sh)
|
|
31
|
+
# 25C — 2>&1 fragmentation hang (redirect-fragment-warner.sh)
|
|
32
|
+
# 25D — compounding cost (downstream of 25B/25F/25C)
|
|
33
|
+
# 25E — empty-result triggered fabrication (Cluster 22 overlap)
|
|
34
|
+
# 25F — non-no-op repeat-execution (this hook)
|
|
35
|
+
#
|
|
36
|
+
# This hook is a PreToolUse hook on Bash that:
|
|
37
|
+
# - Captures the canonicalised form of each Bash command per session
|
|
38
|
+
# - Tracks consecutive identical commands
|
|
39
|
+
# - Warns on the 2nd consecutive identical command
|
|
40
|
+
# - Blocks (exit 2) on the N-th consecutive identical command (default 3)
|
|
41
|
+
#
|
|
42
|
+
# Canonicalisation rules (so trivial variations don't escape detection):
|
|
43
|
+
# - Strip leading/trailing whitespace
|
|
44
|
+
# - Collapse internal whitespace runs to single space
|
|
45
|
+
# - Lowercase nothing (case may carry meaning — `Make` vs `make`)
|
|
46
|
+
#
|
|
47
|
+
# What this hook does NOT cover:
|
|
48
|
+
# - Echo-probe shape (echo-probe-spam-detector.sh covers that)
|
|
49
|
+
# - Commands separated by long gaps (the streak counter resets when any
|
|
50
|
+
# different command runs in between, intentionally)
|
|
51
|
+
#
|
|
52
|
+
# When this hook does NOT block:
|
|
53
|
+
# - CC_SAME_CMD_REPEAT_DISABLE=1 — never warn or block
|
|
54
|
+
# - CC_SAME_CMD_REPEAT_QUIET=1 — silent (no stderr output)
|
|
55
|
+
# - CC_SAME_CMD_REPEAT_THRESHOLD=N — block at N consecutive (default 3)
|
|
56
|
+
# - the Bash command is shorter than 4 chars — exit 0 (avoid false-positive
|
|
57
|
+
# on `ls`, `pwd`, `cd`, etc.)
|
|
58
|
+
# - the operator includes "# RESET REPEAT" — exit 0 (manual reset)
|
|
59
|
+
#
|
|
60
|
+
# Hook config (settings.json):
|
|
61
|
+
# {
|
|
62
|
+
# "hooks": {
|
|
63
|
+
# "PreToolUse": [{
|
|
64
|
+
# "matcher": "Bash",
|
|
65
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/same-command-repeat-detector.sh" }]
|
|
66
|
+
# }]
|
|
67
|
+
# }
|
|
68
|
+
# }
|
|
69
|
+
#
|
|
70
|
+
# Env vars:
|
|
71
|
+
# CC_SAME_CMD_REPEAT_DISABLE=1 — never warn or block
|
|
72
|
+
# CC_SAME_CMD_REPEAT_QUIET=1 — silent (process but never write to stderr)
|
|
73
|
+
# CC_SAME_CMD_REPEAT_THRESHOLD=N — block at N consecutive same command (default 3)
|
|
74
|
+
|
|
75
|
+
set -u
|
|
76
|
+
|
|
77
|
+
if [ "${CC_SAME_CMD_REPEAT_DISABLE:-}" = "1" ]; then
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
THRESHOLD="${CC_SAME_CMD_REPEAT_THRESHOLD:-3}"
|
|
82
|
+
STATE_DIR="${TMPDIR:-/tmp}/cc-same-command-repeat-detector"
|
|
83
|
+
mkdir -p "$STATE_DIR"
|
|
84
|
+
SESSION_ID="${CLAUDE_SESSION_ID:-default}"
|
|
85
|
+
COUNTER_FILE="$STATE_DIR/${SESSION_ID}.counter"
|
|
86
|
+
LAST_CMD_FILE="$STATE_DIR/${SESSION_ID}.last"
|
|
87
|
+
|
|
88
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
89
|
+
CMD=""
|
|
90
|
+
if command -v jq >/dev/null 2>&1 && [ -n "$INPUT" ]; then
|
|
91
|
+
CMD=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || true)
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
if [ -z "$CMD" ]; then
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# Canonicalise: strip leading/trailing whitespace, collapse internal runs
|
|
99
|
+
CMD_CANON=$(printf '%s' "$CMD" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr -s '[:space:]' ' ')
|
|
100
|
+
|
|
101
|
+
# Skip very short commands (ls, pwd, cd, etc. — legitimate to repeat)
|
|
102
|
+
CMD_LEN=${#CMD_CANON}
|
|
103
|
+
if [ "$CMD_LEN" -lt 4 ]; then
|
|
104
|
+
rm -f "$COUNTER_FILE" "$LAST_CMD_FILE"
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Manual reset signal
|
|
109
|
+
if printf '%s\n' "$CMD_CANON" | grep -Eq '#[[:space:]]*RESET REPEAT'; then
|
|
110
|
+
rm -f "$COUNTER_FILE" "$LAST_CMD_FILE"
|
|
111
|
+
exit 0
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Compare against last command in this session
|
|
115
|
+
LAST_CMD=""
|
|
116
|
+
if [ -f "$LAST_CMD_FILE" ]; then
|
|
117
|
+
LAST_CMD=$(cat "$LAST_CMD_FILE" 2>/dev/null || true)
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [ "$CMD_CANON" != "$LAST_CMD" ]; then
|
|
121
|
+
# Different command — reset streak, record this one
|
|
122
|
+
printf '%s' "$CMD_CANON" > "$LAST_CMD_FILE"
|
|
123
|
+
printf '%d' 1 > "$COUNTER_FILE"
|
|
124
|
+
exit 0
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Same as previous: increment streak counter
|
|
128
|
+
CURRENT=0
|
|
129
|
+
if [ -f "$COUNTER_FILE" ]; then
|
|
130
|
+
CURRENT=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
|
|
131
|
+
case "$CURRENT" in
|
|
132
|
+
''|*[!0-9]*) CURRENT=0 ;;
|
|
133
|
+
esac
|
|
134
|
+
fi
|
|
135
|
+
CURRENT=$((CURRENT + 1))
|
|
136
|
+
printf '%d' "$CURRENT" > "$COUNTER_FILE"
|
|
137
|
+
|
|
138
|
+
if [ "${CC_SAME_CMD_REPEAT_QUIET:-}" = "1" ]; then
|
|
139
|
+
if [ "$CURRENT" -ge "$THRESHOLD" ]; then
|
|
140
|
+
exit 2
|
|
141
|
+
fi
|
|
142
|
+
exit 0
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
if [ "$CURRENT" -ge "$THRESHOLD" ]; then
|
|
146
|
+
# Truncate command for display (avoid floods on long commands)
|
|
147
|
+
DISPLAY_CMD="$CMD_CANON"
|
|
148
|
+
if [ "${#DISPLAY_CMD}" -gt 80 ]; then
|
|
149
|
+
DISPLAY_CMD="${CMD_CANON:0:77}..."
|
|
150
|
+
fi
|
|
151
|
+
cat >&2 <<EOF
|
|
152
|
+
|
|
153
|
+
BLOCKED: This is the ${CURRENT}th consecutive identical Bash command.
|
|
154
|
+
|
|
155
|
+
Repeated command: ${DISPLAY_CMD}
|
|
156
|
+
|
|
157
|
+
Pattern detected: Opus 4.8 re-emits the same real (non-no-op) command
|
|
158
|
+
5–10 times in a row, apparently to compensate for perceived non-receipt
|
|
159
|
+
of the previous result. This is Cluster 25 axis 25F — same-command
|
|
160
|
+
repeat-execution. Unlike axis 25B (echo-probe spam) which burns mostly
|
|
161
|
+
display clutter, 25F burns actual CPU + wall-clock + build artefact
|
|
162
|
+
churn each iteration.
|
|
163
|
+
|
|
164
|
+
What to do instead:
|
|
165
|
+
- If the previous result delivery failed: check the transcript for the
|
|
166
|
+
earlier tool_result block before re-running. Re-running won't unstick
|
|
167
|
+
the delivery layer.
|
|
168
|
+
- If the previous result was genuinely empty: verify via a side effect
|
|
169
|
+
that does not re-run the same command (git log, ls, status check).
|
|
170
|
+
- If the previous result simply hasn't been processed yet: wait, do not
|
|
171
|
+
re-emit.
|
|
172
|
+
|
|
173
|
+
Universal mitigation across Cluster 25 today: switch to Opus 4.7.
|
|
174
|
+
export ANTHROPIC_MODEL=claude-opus-4-7
|
|
175
|
+
|
|
176
|
+
Anchor case: github.com/anthropics/claude-code/issues/63887 (@KamilDev,
|
|
177
|
+
"it decided to fire off a build command ten times in a row")
|
|
178
|
+
|
|
179
|
+
To override this block once: include "# RESET REPEAT" in the next command.
|
|
180
|
+
To disable: export CC_SAME_CMD_REPEAT_DISABLE=1
|
|
181
|
+
To adjust threshold: export CC_SAME_CMD_REPEAT_THRESHOLD=N (default 3)
|
|
182
|
+
|
|
183
|
+
EOF
|
|
184
|
+
exit 2
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
cat >&2 <<EOF
|
|
188
|
+
|
|
189
|
+
NOTICE: Detected ${CURRENT}/${THRESHOLD} consecutive identical Bash commands.
|
|
190
|
+
This shape is the Cluster 25 axis 25F same-command repeat-execution
|
|
191
|
+
compensation routine. Will block at ${THRESHOLD} consecutive occurrences.
|
|
192
|
+
Anchor: github.com/anthropics/claude-code/issues/63887
|
|
193
|
+
|
|
194
|
+
EOF
|
|
195
|
+
|
|
196
|
+
exit 0
|