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,139 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# extended-thinking-loop-guard.sh — Hard-block a Cluster 13A resume when the
|
|
3
|
+
# session is running under an autonomous-loop / headless-resume harness.
|
|
4
|
+
#
|
|
5
|
+
# Solves: the LMS927369 amplification reported in #63147 on 2026-05-29. The
|
|
6
|
+
# well-known 13A wedge (transcript persists thinking blocks with
|
|
7
|
+
# `thinking: ""` + retained `signature`, then resume re-sends them and the
|
|
8
|
+
# API returns 400) is normally a one-time failure under interactive use.
|
|
9
|
+
# Under `/loop`-style autonomous resume, the failure is instead an
|
|
10
|
+
# *unrecoverable infinite loop*: the loop queues another continuation,
|
|
11
|
+
# the latest assistant message is unchanged on disk, the next request
|
|
12
|
+
# hits the same 400, and the loop never bails because the wedged turn
|
|
13
|
+
# never gets past the API.
|
|
14
|
+
#
|
|
15
|
+
# Why a second hook (in addition to PR #445's advisory): the existing
|
|
16
|
+
# extended-thinking-resume-warning.sh always exits 0 — it surfaces the
|
|
17
|
+
# precursor to the operator's terminal but does not block the session
|
|
18
|
+
# start. Under `/loop`, nobody is watching stderr in the moment, so a
|
|
19
|
+
# non-blocking advisory does not break the loop. This hook is the
|
|
20
|
+
# opt-in BLOCKING complement: when the operator declares "I am running
|
|
21
|
+
# under an autonomous resume harness" via CC_LOOP_GUARD_ENABLED=1, the
|
|
22
|
+
# hook scans the transcript on the disk and exits 2 with a decision
|
|
23
|
+
# block if the 13A precursor is present. The blocking exit propagates
|
|
24
|
+
# into the loop layer and breaks the retry cycle.
|
|
25
|
+
#
|
|
26
|
+
# Issue addressed: #63147 (central case), amplification reported by
|
|
27
|
+
# LMS927369 (https://github.com/anthropics/claude-code/issues/63147#issuecomment-4571317923).
|
|
28
|
+
# Field guide: https://gist.github.com/yurukusa/8c6be069f602399238356a9c9b719a45
|
|
29
|
+
#
|
|
30
|
+
# Default behavior: SILENT NO-OP. The hook exits 0 immediately unless
|
|
31
|
+
# CC_LOOP_GUARD_ENABLED=1 is explicitly set. This makes it safe to drop
|
|
32
|
+
# into a settings.json template that gets applied broadly — interactive
|
|
33
|
+
# operators who do not set the env var see no change in behavior. Only
|
|
34
|
+
# harnesses that opt in get the blocking semantics.
|
|
35
|
+
#
|
|
36
|
+
# Environment variables:
|
|
37
|
+
# CC_LOOP_GUARD_ENABLED=1 — REQUIRED to arm the guard
|
|
38
|
+
# CC_LOOP_GUARD_DISABLE=1 — kill switch (wins over enable)
|
|
39
|
+
# CC_LOOP_GUARD_TRANSCRIPT=<path> — override transcript path (test)
|
|
40
|
+
# CC_LOOP_GUARD_FORCE=1 — fire regardless of source (test)
|
|
41
|
+
# CC_LOOP_GUARD_THRESHOLD=<N> — minimum precursor blocks to
|
|
42
|
+
# trigger (default 1)
|
|
43
|
+
#
|
|
44
|
+
# TRIGGER: SessionStart
|
|
45
|
+
# MATCHER: "" (filters event internally)
|
|
46
|
+
#
|
|
47
|
+
# Exit codes:
|
|
48
|
+
# 0 — safe to proceed (env disabled, no precursor, or non-resume source)
|
|
49
|
+
# 2 — BLOCK (precursor detected under armed guard); decision JSON on stderr
|
|
50
|
+
|
|
51
|
+
set -uo pipefail
|
|
52
|
+
|
|
53
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
54
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
55
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
56
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
57
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
58
|
+
_nojq_warned="/tmp/cc-nojq-warned-extended-thinking-loop-guard-$PPID"
|
|
59
|
+
[ -f "$_nojq_warned" ] || {
|
|
60
|
+
echo "WARNING [extended-thinking-loop-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
61
|
+
: > "$_nojq_warned"
|
|
62
|
+
}
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
INPUT=$(cat)
|
|
66
|
+
|
|
67
|
+
# Kill switch wins.
|
|
68
|
+
[ "${CC_LOOP_GUARD_DISABLE:-0}" = "1" ] && exit 0
|
|
69
|
+
|
|
70
|
+
# Default behavior: not armed → silent no-op. This is the key safety
|
|
71
|
+
# property: dropping the hook into settings.json without setting the env
|
|
72
|
+
# var must not change behavior for interactive operators.
|
|
73
|
+
[ "${CC_LOOP_GUARD_ENABLED:-0}" = "1" ] || exit 0
|
|
74
|
+
|
|
75
|
+
EVENT=$(printf '%s' "$INPUT" | jq -r '.event // .hook_event_name // empty' 2>/dev/null)
|
|
76
|
+
case "$EVENT" in
|
|
77
|
+
session_start|SessionStart|sessionstart) ;;
|
|
78
|
+
*) exit 0 ;;
|
|
79
|
+
esac
|
|
80
|
+
|
|
81
|
+
# Only fire on resume/continue. A fresh `startup` cannot carry a stale
|
|
82
|
+
# precursor (no transcript yet). Unknown source defaults to scanning so
|
|
83
|
+
# new client versions that introduce new source labels stay covered.
|
|
84
|
+
SOURCE=$(printf '%s' "$INPUT" | jq -r '.source // empty' 2>/dev/null)
|
|
85
|
+
if [ "${CC_LOOP_GUARD_FORCE:-0}" != "1" ]; then
|
|
86
|
+
case "$SOURCE" in
|
|
87
|
+
resume|continue|"") ;;
|
|
88
|
+
startup|fresh|new) exit 0 ;;
|
|
89
|
+
*) ;;
|
|
90
|
+
esac
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Locate the transcript file. Same heuristic as PR #445 — recompute the
|
|
94
|
+
# Claude Code project slug from CC_PROJECT_DIR or PWD; if it doesn't
|
|
95
|
+
# resolve, fail open rather than blocking blindly.
|
|
96
|
+
LATEST="${CC_LOOP_GUARD_TRANSCRIPT:-}"
|
|
97
|
+
if [ -z "$LATEST" ]; then
|
|
98
|
+
PROJ_DIR="${CC_PROJECT_DIR:-$PWD}"
|
|
99
|
+
SLUG=$(printf '%s' "$PROJ_DIR" | sed 's|/|-|g')
|
|
100
|
+
TRANSCRIPT_DIR="${HOME}/.claude/projects/${SLUG}"
|
|
101
|
+
[ -d "$TRANSCRIPT_DIR" ] || exit 0
|
|
102
|
+
LATEST=$(ls -t "$TRANSCRIPT_DIR"/*.jsonl 2>/dev/null | head -1)
|
|
103
|
+
fi
|
|
104
|
+
[ -n "$LATEST" ] || exit 0
|
|
105
|
+
[ -r "$LATEST" ] || exit 0
|
|
106
|
+
|
|
107
|
+
# Scan for empty-thinking + non-empty-signature blocks. Same shape as the
|
|
108
|
+
# PR #445 detector; the difference is what we do with the result.
|
|
109
|
+
SCAN=$(jq -rR 'fromjson? | select(.type == "assistant") | .message.content[]? | select(.type == "thinking" and ((.thinking // "") | length) == 0 and ((.signature // "") | length) > 0) | (.signature | length)' "$LATEST" 2>/dev/null || true)
|
|
110
|
+
|
|
111
|
+
if [ -z "$SCAN" ]; then
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
COUNT=$(printf '%s\n' "$SCAN" | grep -c .)
|
|
116
|
+
THRESHOLD="${CC_LOOP_GUARD_THRESHOLD:-1}"
|
|
117
|
+
|
|
118
|
+
if [ "$COUNT" -lt "$THRESHOLD" ]; then
|
|
119
|
+
exit 0
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Block. Emit decision JSON on stderr and exit 2. The decision payload is
|
|
123
|
+
# what Claude Code surfaces to the operator (and what an enclosing harness
|
|
124
|
+
# can grep for to identify the bail reason).
|
|
125
|
+
REASON="Cluster 13A precursor detected on disk (${COUNT} empty-text-signed thinking block(s) in ${LATEST}). Under autonomous loop, resuming this transcript would re-send the corrupted blocks, hit API 400 (\`thinking\` blocks cannot be modified), and the loop would replay indefinitely. Stopping the resume to break the loop. Recover by: (1) backing up the .jsonl, (2) stripping thinking/redacted_thinking blocks from assistant content arrays in-place (leave uuid/parentUuid chains intact), (3) clearing CC_LOOP_GUARD_ENABLED or setting CC_LOOP_GUARD_DISABLE=1 for the recovery session, then resuming. Reference: https://github.com/anthropics/claude-code/issues/63147 — Field guide: https://gist.github.com/yurukusa/8c6be069f602399238356a9c9b719a45"
|
|
126
|
+
|
|
127
|
+
# JSON-escape the reason field for the decision payload. Use jq for the
|
|
128
|
+
# escape so embedded backticks, quotes, slashes, etc. don't break the JSON.
|
|
129
|
+
DECISION=$(jq -nc --arg r "$REASON" '{decision:"block", reason:$r}' 2>/dev/null)
|
|
130
|
+
|
|
131
|
+
if [ -n "$DECISION" ]; then
|
|
132
|
+
printf '%s\n' "$DECISION" >&2
|
|
133
|
+
else
|
|
134
|
+
# jq unavailable for the escape — fall back to a plain-text reason.
|
|
135
|
+
# Operators get the message; harness grep on "decision" may miss it.
|
|
136
|
+
printf '[extended-thinking-loop-guard] BLOCK: %s\n' "$REASON" >&2
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
exit 2
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# extended-thinking-resume-warning.sh — Warn before resuming a session whose
|
|
3
|
+
# transcript carries the 13A precursor.
|
|
4
|
+
#
|
|
5
|
+
# Solves: Cluster 13 Axis A — the resume serialization corruption that wedges
|
|
6
|
+
# extended-thinking sessions on a permanent API 400. Claude Code
|
|
7
|
+
# persists thinking blocks to the session transcript with the
|
|
8
|
+
# `thinking` field emptied to "" but the `signature` field retained
|
|
9
|
+
# from the original response. When the session is resumed, the client
|
|
10
|
+
# sends `{"thinking": "", "signature": "<original>"}` to the API; the
|
|
11
|
+
# signature was computed over the original non-empty thinking text,
|
|
12
|
+
# so validation fails and the session is permanently wedged.
|
|
13
|
+
#
|
|
14
|
+
# Issue addressed: #63147 (central case, 33 reactions). Field guide:
|
|
15
|
+
# https://gist.github.com/yurukusa/8c6be069f602399238356a9c9b719a45
|
|
16
|
+
#
|
|
17
|
+
# How it works: SessionStart hook. When the session source indicates a resume
|
|
18
|
+
# or continue, finds the transcript directory for the current project
|
|
19
|
+
# (~/.claude/projects/<slug>/) and reads the most recent .jsonl file. Scans
|
|
20
|
+
# the file for assistant thinking blocks where `thinking` is empty but
|
|
21
|
+
# `signature` is non-empty — the on-disk shape that becomes the 13A wedge
|
|
22
|
+
# on the next API request.
|
|
23
|
+
#
|
|
24
|
+
# If the pattern is present, the hook emits a stderr advisory naming
|
|
25
|
+
# sub-pattern 13A, pointing at the field guide, and listing the recommended
|
|
26
|
+
# actions (save state, start fresh). The hook NEVER blocks — exit 0 always.
|
|
27
|
+
#
|
|
28
|
+
# Heuristic notes:
|
|
29
|
+
# - Claude Code's project slug is the absolute project dir with leading
|
|
30
|
+
# slash stripped and remaining `/` replaced with `-` (e.g.
|
|
31
|
+
# `/home/u/proj` → `home-u-proj`). The hook recomputes this from
|
|
32
|
+
# CC_PROJECT_DIR or PWD; if the layout differs in a future client
|
|
33
|
+
# version the hook fails open rather than emitting a stale warning.
|
|
34
|
+
# - Trailing thinking blocks in healthy sessions are *also* frequently
|
|
35
|
+
# stored empty-but-signed (per #63147 evidence), so the hook fires on
|
|
36
|
+
# a SHAPE that is common, not a SHAPE that is uniquely broken. The
|
|
37
|
+
# advisory is calibrated to match: it warns the operator that resume
|
|
38
|
+
# may hit the 400, not that it definitely will.
|
|
39
|
+
#
|
|
40
|
+
# Environment variables:
|
|
41
|
+
# CC_EXTENDED_THINKING_RESUME_DISABLE=1 — disable advisory entirely
|
|
42
|
+
# CC_EXTENDED_THINKING_RESUME_VERBOSE=1 — include per-block sizes
|
|
43
|
+
# CC_EXTENDED_THINKING_RESUME_TRANSCRIPT — override transcript path (test)
|
|
44
|
+
# CC_EXTENDED_THINKING_RESUME_FORCE=1 — fire regardless of source (test)
|
|
45
|
+
#
|
|
46
|
+
# TRIGGER: SessionStart
|
|
47
|
+
# MATCHER: "" (filters event internally)
|
|
48
|
+
|
|
49
|
+
set -uo pipefail
|
|
50
|
+
|
|
51
|
+
INPUT=$(cat)
|
|
52
|
+
[ "${CC_EXTENDED_THINKING_RESUME_DISABLE:-0}" = "1" ] && exit 0
|
|
53
|
+
|
|
54
|
+
EVENT=$(printf '%s' "$INPUT" | jq -r '.event // .hook_event_name // empty' 2>/dev/null)
|
|
55
|
+
case "$EVENT" in
|
|
56
|
+
session_start|SessionStart|sessionstart) ;;
|
|
57
|
+
*) exit 0 ;;
|
|
58
|
+
esac
|
|
59
|
+
|
|
60
|
+
# Only fire on resume/continue. Some clients send `source: "resume"`,
|
|
61
|
+
# others `source: "continue"`, others omit it. Fail-open: when the source
|
|
62
|
+
# field is missing or unknown, default to scanning (the cost is one
|
|
63
|
+
# advisory if the transcript happens to carry the precursor shape).
|
|
64
|
+
SOURCE=$(printf '%s' "$INPUT" | jq -r '.source // empty' 2>/dev/null)
|
|
65
|
+
if [ "${CC_EXTENDED_THINKING_RESUME_FORCE:-0}" != "1" ]; then
|
|
66
|
+
case "$SOURCE" in
|
|
67
|
+
resume|continue|"") ;;
|
|
68
|
+
startup|fresh|new) exit 0 ;;
|
|
69
|
+
*) ;; # unknown source — scan anyway
|
|
70
|
+
esac
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Locate the transcript file.
|
|
74
|
+
LATEST="${CC_EXTENDED_THINKING_RESUME_TRANSCRIPT:-}"
|
|
75
|
+
if [ -z "$LATEST" ]; then
|
|
76
|
+
PROJ_DIR="${CC_PROJECT_DIR:-$PWD}"
|
|
77
|
+
SLUG=$(printf '%s' "$PROJ_DIR" | sed 's|/|-|g')
|
|
78
|
+
TRANSCRIPT_DIR="${HOME}/.claude/projects/${SLUG}"
|
|
79
|
+
[ -d "$TRANSCRIPT_DIR" ] || exit 0
|
|
80
|
+
LATEST=$(ls -t "$TRANSCRIPT_DIR"/*.jsonl 2>/dev/null | head -1)
|
|
81
|
+
fi
|
|
82
|
+
[ -n "$LATEST" ] || exit 0
|
|
83
|
+
[ -r "$LATEST" ] || exit 0
|
|
84
|
+
|
|
85
|
+
# Scan for empty-thinking + non-empty-signature blocks. Read each line as
|
|
86
|
+
# raw text and use fromjson? so malformed lines are silently skipped rather
|
|
87
|
+
# than aborting the scan.
|
|
88
|
+
SCAN=$(jq -rR 'fromjson? | select(.type == "assistant") | .message.content[]? | select(.type == "thinking" and ((.thinking // "") | length) == 0 and ((.signature // "") | length) > 0) | (.signature | length)' "$LATEST" 2>/dev/null || true)
|
|
89
|
+
[ -z "$SCAN" ] && exit 0
|
|
90
|
+
|
|
91
|
+
COUNT=$(printf '%s\n' "$SCAN" | grep -c .)
|
|
92
|
+
SIG_LENGTHS=$(printf '%s' "$SCAN" | tr '\n' ' ')
|
|
93
|
+
|
|
94
|
+
{
|
|
95
|
+
echo "[extended-thinking-resume-warning] Cluster 13A precursor detected."
|
|
96
|
+
echo ""
|
|
97
|
+
echo " Transcript: $LATEST"
|
|
98
|
+
echo " Empty-text signed thinking block(s): ${COUNT}"
|
|
99
|
+
echo ""
|
|
100
|
+
echo "Resuming this session may hit the persistent API 400:"
|
|
101
|
+
echo " \`thinking\` blocks in the latest assistant message cannot be modified."
|
|
102
|
+
echo ""
|
|
103
|
+
echo "Once it fires, the wedge persists for the life of the transcript —"
|
|
104
|
+
echo "every subsequent turn re-sends the same corrupted message and re-fails."
|
|
105
|
+
echo ""
|
|
106
|
+
echo "Recommended actions:"
|
|
107
|
+
echo " - If resume is critical, save state from the running process now."
|
|
108
|
+
echo " - Otherwise start a fresh session; the wedge cannot be cleared in-session."
|
|
109
|
+
echo " - Disable extended thinking via /model if your next task allows."
|
|
110
|
+
echo ""
|
|
111
|
+
echo "Reference: https://github.com/anthropics/claude-code/issues/63147"
|
|
112
|
+
echo "Field guide: https://gist.github.com/yurukusa/8c6be069f602399238356a9c9b719a45"
|
|
113
|
+
if [ "${CC_EXTENDED_THINKING_RESUME_VERBOSE:-0}" = "1" ]; then
|
|
114
|
+
echo ""
|
|
115
|
+
echo "(per-block signature lengths: ${SIG_LENGTHS})"
|
|
116
|
+
fi
|
|
117
|
+
} >&2
|
|
118
|
+
|
|
119
|
+
exit 0
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# extended-thinking-tool-use-mismatch-detector.sh — Warn when the
|
|
4
|
+
# structural 12B pattern is detected in the trailing transcript:
|
|
5
|
+
# assistant turns with stop_reason="tool_use" but no parseable
|
|
6
|
+
# tool_use block in content (only thinking and/or text blocks).
|
|
7
|
+
# ================================================================
|
|
8
|
+
# PURPOSE:
|
|
9
|
+
# Issue #62467 documents that when Opus 4.7's extended thinking
|
|
10
|
+
# is active, the assistant turn can carry stop_reason="tool_use"
|
|
11
|
+
# yet emit only a thinking block — no tool_use block reaches the
|
|
12
|
+
# harness parser. The harness then surfaces a "malformed and
|
|
13
|
+
# could not be parsed" notice and retries; in the reporter's
|
|
14
|
+
# sessions ~20 retry prompts accumulated across 6 sessions with
|
|
15
|
+
# no recovery. Output size and special characters are ruled out;
|
|
16
|
+
# the common factor is Opus 4.7 + extended thinking.
|
|
17
|
+
#
|
|
18
|
+
# The companion sub-pattern 12A
|
|
19
|
+
# (long-session-malformed-tool-call-detector.sh, PR #406) keys
|
|
20
|
+
# off the literal "malformed and could not be parsed" string in
|
|
21
|
+
# the transcript text. That text marker fires for any cause of
|
|
22
|
+
# the same surface symptom. The 12B detector here keys off the
|
|
23
|
+
# structural mismatch directly — stop_reason vs. content-block
|
|
24
|
+
# absence — so the operator gets sub-pattern-specific naming
|
|
25
|
+
# even when 12A's text marker has not appeared yet (the harness
|
|
26
|
+
# may suppress the parser notice in some configurations) or when
|
|
27
|
+
# it fires together with 12A's marker (both advisories then name
|
|
28
|
+
# the cluster, with 12B specifically calling out the
|
|
29
|
+
# extended-thinking factor and pointing to the workaround at the
|
|
30
|
+
# model layer rather than at the session layer).
|
|
31
|
+
#
|
|
32
|
+
# TRIGGER: PostToolUse MATCHER: ""
|
|
33
|
+
# CLUSTER: 12 (Tool Call Parsing failures in Opus 4.7)
|
|
34
|
+
# SUB-PATTERN: 12B (extended-thinking serialization defect)
|
|
35
|
+
#
|
|
36
|
+
# BEHAVIOR:
|
|
37
|
+
# - Read transcript_path from PostToolUse hook input.
|
|
38
|
+
# - Scan the trailing LOOKBACK lines for assistant turns.
|
|
39
|
+
# - For each assistant turn, check if .stop_reason == "tool_use"
|
|
40
|
+
# and the .content array contains no element with
|
|
41
|
+
# .type == "tool_use". Count each such mismatch.
|
|
42
|
+
# - If at or above the threshold, emit a one-screen stderr
|
|
43
|
+
# advisory naming sub-pattern 12B and pointing to the
|
|
44
|
+
# model-layer workaround (switch to a variant without
|
|
45
|
+
# extended thinking).
|
|
46
|
+
# - Rate-limit advisory emission per session via a counter
|
|
47
|
+
# file so the warning does not repeat on every PostToolUse
|
|
48
|
+
# after the first detection.
|
|
49
|
+
# - Always exits 0 (advisory only; never blocks tool execution).
|
|
50
|
+
#
|
|
51
|
+
# CONFIGURATION (env vars):
|
|
52
|
+
# CC_THINKING_MISMATCH_DISABLE Set to "1" to silence.
|
|
53
|
+
# CC_THINKING_MISMATCH_LOOKBACK How many recent transcript
|
|
54
|
+
# lines to scan. Default 150.
|
|
55
|
+
# CC_THINKING_MISMATCH_THRESHOLD Minimum mismatches in
|
|
56
|
+
# LOOKBACK to fire. Default 2.
|
|
57
|
+
# (Single mismatches are rare
|
|
58
|
+
# but can occur from unrelated
|
|
59
|
+
# serialization edge cases;
|
|
60
|
+
# requiring 2 keys off the
|
|
61
|
+
# repeated-failure shape
|
|
62
|
+
# #62467 actually documents.)
|
|
63
|
+
# CC_THINKING_MISMATCH_COOLDOWN Minimum tool calls between
|
|
64
|
+
# repeat advisories per
|
|
65
|
+
# session. Default 30.
|
|
66
|
+
# CC_THINKING_MISMATCH_TRANSCRIPT Override transcript path
|
|
67
|
+
# (used by tests).
|
|
68
|
+
# CC_THINKING_MISMATCH_STATE_DIR Override state directory
|
|
69
|
+
# (used by tests). Default
|
|
70
|
+
# /tmp/cc-thinking-mismatch.
|
|
71
|
+
#
|
|
72
|
+
# UPSTREAM REFERENCES:
|
|
73
|
+
# #62467 (central case: stop_reason="tool_use" with only a
|
|
74
|
+
# thinking block, ~20 retry prompts across 6 sessions,
|
|
75
|
+
# Opus 4.7 + extended thinking)
|
|
76
|
+
# #62123 (broader "retry also failed" central case, 21 reactions)
|
|
77
|
+
# #62344 (in-context few-shot poisoning, sub-pattern 12A)
|
|
78
|
+
# #62700 (spurious malformed notice, sub-pattern 12C)
|
|
79
|
+
#
|
|
80
|
+
# RECOVERY ON A HIT:
|
|
81
|
+
# The advisory does not recover the session. The known
|
|
82
|
+
# workaround for sub-pattern 12B is at the model layer:
|
|
83
|
+
# - Switch to a Claude Sonnet variant for the task at hand.
|
|
84
|
+
# - Disable extended thinking via the /model command when
|
|
85
|
+
# Opus's standard mode is sufficient.
|
|
86
|
+
# /clear (the 12A recovery) does not fix 12B because the
|
|
87
|
+
# serialization defect re-fires on the next extended-thinking
|
|
88
|
+
# turn even in a fresh session. The advisory's value is in
|
|
89
|
+
# pointing the operator at the correct workaround layer.
|
|
90
|
+
# ================================================================
|
|
91
|
+
|
|
92
|
+
set -u
|
|
93
|
+
|
|
94
|
+
if [ "${CC_THINKING_MISMATCH_DISABLE:-0}" = "1" ]; then
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
LOOKBACK="${CC_THINKING_MISMATCH_LOOKBACK:-150}"
|
|
99
|
+
THRESHOLD="${CC_THINKING_MISMATCH_THRESHOLD:-2}"
|
|
100
|
+
COOLDOWN="${CC_THINKING_MISMATCH_COOLDOWN:-30}"
|
|
101
|
+
STATE_DIR="${CC_THINKING_MISMATCH_STATE_DIR:-/tmp/cc-thinking-mismatch}"
|
|
102
|
+
|
|
103
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
104
|
+
|
|
105
|
+
TRANSCRIPT_PATH="${CC_THINKING_MISMATCH_TRANSCRIPT:-}"
|
|
106
|
+
if [ -z "$TRANSCRIPT_PATH" ]; then
|
|
107
|
+
TRANSCRIPT_PATH=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
if [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ]; then
|
|
111
|
+
exit 0
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "default"' 2>/dev/null)
|
|
115
|
+
[ -z "$SESSION_ID" ] && SESSION_ID="default"
|
|
116
|
+
|
|
117
|
+
SAFE_SESSION=$(printf '%s' "$SESSION_ID" | tr -c 'A-Za-z0-9._-' '_' | head -c 80)
|
|
118
|
+
[ -z "$SAFE_SESSION" ] && SAFE_SESSION="default"
|
|
119
|
+
|
|
120
|
+
mkdir -p "$STATE_DIR" 2>/dev/null
|
|
121
|
+
|
|
122
|
+
COUNTER_FILE="$STATE_DIR/${SAFE_SESSION}.count"
|
|
123
|
+
LASTFIRED_FILE="$STATE_DIR/${SAFE_SESSION}.lastfired"
|
|
124
|
+
|
|
125
|
+
COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
|
|
126
|
+
COUNT=$((COUNT + 1))
|
|
127
|
+
echo "$COUNT" > "$COUNTER_FILE"
|
|
128
|
+
|
|
129
|
+
# Count structural 12B mismatches in the trailing window.
|
|
130
|
+
# A mismatch is an assistant turn line where:
|
|
131
|
+
# - stop_reason equals "tool_use" (checked at .stop_reason and
|
|
132
|
+
# .message.stop_reason to handle both common transcript shapes)
|
|
133
|
+
# - the matching content array contains no element with
|
|
134
|
+
# type == "tool_use"
|
|
135
|
+
# Each line is parsed independently; lines that fail to parse as
|
|
136
|
+
# JSON are silently skipped.
|
|
137
|
+
MISMATCHES=$(tail -n "$LOOKBACK" "$TRANSCRIPT_PATH" 2>/dev/null | jq -R -r '
|
|
138
|
+
try (fromjson) catch null | select(. != null) | . as $obj |
|
|
139
|
+
(
|
|
140
|
+
(($obj.stop_reason // $obj.message.stop_reason) == "tool_use")
|
|
141
|
+
and
|
|
142
|
+
(
|
|
143
|
+
(($obj.content // $obj.message.content // []) | type) == "array"
|
|
144
|
+
)
|
|
145
|
+
and
|
|
146
|
+
(
|
|
147
|
+
(($obj.content // $obj.message.content // []) | map(select(.type == "tool_use")) | length) == 0
|
|
148
|
+
)
|
|
149
|
+
) | select(. == true) | "1"
|
|
150
|
+
' 2>/dev/null | wc -l | tr -d ' ')
|
|
151
|
+
|
|
152
|
+
MISMATCHES="${MISMATCHES:-0}"
|
|
153
|
+
|
|
154
|
+
if [ "$MISMATCHES" -lt "$THRESHOLD" ]; then
|
|
155
|
+
exit 0
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
LASTFIRED=$(cat "$LASTFIRED_FILE" 2>/dev/null || echo 0)
|
|
159
|
+
SINCE=$((COUNT - LASTFIRED))
|
|
160
|
+
|
|
161
|
+
if [ "$LASTFIRED" -gt 0 ] && [ "$SINCE" -lt "$COOLDOWN" ]; then
|
|
162
|
+
exit 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
echo "$COUNT" > "$LASTFIRED_FILE"
|
|
166
|
+
|
|
167
|
+
cat >&2 <<EOF
|
|
168
|
+
|
|
169
|
+
⚠️ Detected ${MISMATCHES} assistant turn(s) with stop_reason="tool_use"
|
|
170
|
+
but no parseable tool_use block in content, in the trailing
|
|
171
|
+
${LOOKBACK} transcript lines.
|
|
172
|
+
|
|
173
|
+
This is the structural signal for sub-pattern 12B
|
|
174
|
+
(extended-thinking serialization defect), the case filed in #62467.
|
|
175
|
+
When Opus 4.7's extended thinking is active, the assistant turn can
|
|
176
|
+
carry stop_reason="tool_use" yet emit only a thinking block — the
|
|
177
|
+
tool_use block never reaches the harness parser. The reporter
|
|
178
|
+
observed ~20 retry prompts accumulated across 6 sessions before
|
|
179
|
+
giving up; output size and special characters were ruled out, and
|
|
180
|
+
the common factor was Opus 4.7 + extended thinking.
|
|
181
|
+
|
|
182
|
+
Sub-pattern 12B is distinct from 12A (in-context few-shot
|
|
183
|
+
poisoning, #62344, recovered by \`/clear\`). 12B is at the model
|
|
184
|
+
serialization layer, so a fresh session does not recover — the
|
|
185
|
+
defect re-fires on the next extended-thinking turn.
|
|
186
|
+
|
|
187
|
+
Known workarounds (operator-side, at the model layer):
|
|
188
|
+
- Switch to a Claude Sonnet variant for the affected task.
|
|
189
|
+
- Disable extended thinking via the \`/model\` command when
|
|
190
|
+
Opus's standard mode is sufficient for the work.
|
|
191
|
+
- Break the work into smaller sub-tasks that complete without
|
|
192
|
+
the model entering extended thinking.
|
|
193
|
+
|
|
194
|
+
If a single mismatch in the window is informational, sub-pattern
|
|
195
|
+
12B's actual signal is the repeated-failure shape #62467 documents
|
|
196
|
+
(the default threshold of 2 keys off that). If you are seeing
|
|
197
|
+
mismatches reliably above the threshold, the model layer is in the
|
|
198
|
+
state #62467 describes and operator-side hooks cannot recover.
|
|
199
|
+
|
|
200
|
+
References: #62467 (the extended-thinking-serialization central
|
|
201
|
+
case), #62123 (the broader "retry also failed" case, 21 reactions),
|
|
202
|
+
Cluster 12 in the cc-safe-setup tracker:
|
|
203
|
+
https://yurukusa.github.io/cc-safe-setup/cluster-tracker.html#cluster-tool-call-parsing
|
|
204
|
+
|
|
205
|
+
Silence: set CC_THINKING_MISMATCH_DISABLE=1.
|
|
206
|
+
Tune sensitivity: CC_THINKING_MISMATCH_THRESHOLD (default 2),
|
|
207
|
+
CC_THINKING_MISMATCH_LOOKBACK (default 150 lines),
|
|
208
|
+
CC_THINKING_MISMATCH_COOLDOWN (default 30 tool calls).
|
|
209
|
+
|
|
210
|
+
EOF
|
|
211
|
+
|
|
212
|
+
exit 0
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# fabricated-command-detector.sh — Detect command-shaped tokens in the final
|
|
3
|
+
# assistant response that were never invoked as Bash tool calls in the session.
|
|
4
|
+
#
|
|
5
|
+
# Solves: substitution-by-default at the response layer (issue #60340).
|
|
6
|
+
# In #60340, a security-research reproduction shipped with `./exploit` as
|
|
7
|
+
# the command in the assistant's writeup, while the operator's actual
|
|
8
|
+
# reproduction command (`./chage_pwn root`) was established through dozens
|
|
9
|
+
# of Bash tool calls. The model never invoked `./exploit` — it generated
|
|
10
|
+
# a plausible-looking parallel command and substituted it into the response.
|
|
11
|
+
#
|
|
12
|
+
# How it works: Stop hook that reads the latest assistant turn from the
|
|
13
|
+
# session transcript, extracts command-shaped tokens (./xxx, git xxx,
|
|
14
|
+
# bash xxx, etc.) from inline code spans, and cross-references each one
|
|
15
|
+
# against the Bash tool calls that actually occurred in the session.
|
|
16
|
+
# Tokens that look like commands but were never invoked are flagged as
|
|
17
|
+
# possible fabrication.
|
|
18
|
+
#
|
|
19
|
+
# This hook is advisory by default — it warns to stderr and exits 0.
|
|
20
|
+
# It does not block the response. Set CC_FABRICATED_CMD_BLOCK=1 to make
|
|
21
|
+
# unverified tokens cause a non-zero exit (use for high-stakes contexts
|
|
22
|
+
# like security reproductions).
|
|
23
|
+
#
|
|
24
|
+
# TRIGGER: Stop
|
|
25
|
+
# MATCHER: ""
|
|
26
|
+
#
|
|
27
|
+
# Configuration:
|
|
28
|
+
# CC_FABRICATED_CMD_DISABLE=1 Disable the hook completely.
|
|
29
|
+
# CC_FABRICATED_CMD_BLOCK=1 Exit non-zero (exit 2) when fabricated
|
|
30
|
+
# tokens are detected. Default: advisory.
|
|
31
|
+
# CC_FABRICATED_CMD_ALLOW=regex Pattern of tokens to ignore (e.g. for
|
|
32
|
+
# hypothetical example commands). Matched
|
|
33
|
+
# with `grep -E` against the token text.
|
|
34
|
+
# CC_FABRICATED_CMD_MAX=20 Maximum tokens to scan per response.
|
|
35
|
+
# Default 20. Cap protects performance on
|
|
36
|
+
# very long responses.
|
|
37
|
+
|
|
38
|
+
set -u
|
|
39
|
+
|
|
40
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
41
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
42
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
43
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
44
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
45
|
+
_nojq_warned="/tmp/cc-nojq-warned-fabricated-command-detector-$PPID"
|
|
46
|
+
[ -f "$_nojq_warned" ] || {
|
|
47
|
+
echo "WARNING [fabricated-command-detector]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
48
|
+
: > "$_nojq_warned"
|
|
49
|
+
}
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
[ "${CC_FABRICATED_CMD_DISABLE:-0}" = "1" ] && exit 0
|
|
53
|
+
|
|
54
|
+
INPUT=$(cat)
|
|
55
|
+
|
|
56
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
57
|
+
[ -z "$TRANSCRIPT" ] && exit 0
|
|
58
|
+
[ ! -r "$TRANSCRIPT" ] && exit 0
|
|
59
|
+
|
|
60
|
+
# Extract the LAST assistant message text content from the transcript.
|
|
61
|
+
# Transcript is jsonl: one event per line. Look for the last assistant
|
|
62
|
+
# message and concatenate its text content blocks.
|
|
63
|
+
LAST_ASSISTANT=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"role":"assistant"' || true)
|
|
64
|
+
[ -z "$LAST_ASSISTANT" ] && exit 0
|
|
65
|
+
|
|
66
|
+
# Try a few schemas for the assistant text. Newer transcripts wrap content
|
|
67
|
+
# as an array of typed blocks; older ones may use a flat text field.
|
|
68
|
+
RESPONSE_TEXT=$(printf '%s' "$LAST_ASSISTANT" | jq -r '
|
|
69
|
+
if .message.content then
|
|
70
|
+
(.message.content | if type == "array" then map(select(.type == "text") | .text) | join("\n") else . end)
|
|
71
|
+
elif .content then
|
|
72
|
+
(.content | if type == "array" then map(select(.type == "text") | .text) | join("\n") else . end)
|
|
73
|
+
else
|
|
74
|
+
empty
|
|
75
|
+
end
|
|
76
|
+
' 2>/dev/null)
|
|
77
|
+
|
|
78
|
+
[ -z "$RESPONSE_TEXT" ] && exit 0
|
|
79
|
+
|
|
80
|
+
# Extract command-shaped tokens from backtick inline code in the response.
|
|
81
|
+
# Patterns that look like operator commands the response is asserting were
|
|
82
|
+
# (or are to be) run:
|
|
83
|
+
# - ./xxx and ./xxx_yyy and ./bin/xxx (relative executables)
|
|
84
|
+
# - git <subcommand> ... (git invocations)
|
|
85
|
+
# - bash <script>, sh <script> (shell-script invocations)
|
|
86
|
+
# - npm/pnpm/yarn run <task>
|
|
87
|
+
# - python <script>, node <script>
|
|
88
|
+
MAX_TOKENS="${CC_FABRICATED_CMD_MAX:-20}"
|
|
89
|
+
ALLOW_PATTERN="${CC_FABRICATED_CMD_ALLOW:-}"
|
|
90
|
+
|
|
91
|
+
# Extract inline code spans (backtick-fenced single-line content)
|
|
92
|
+
TOKENS=$(printf '%s\n' "$RESPONSE_TEXT" \
|
|
93
|
+
| grep -oE '`[^`]+`' 2>/dev/null \
|
|
94
|
+
| sed -e 's/^`//' -e 's/`$//' \
|
|
95
|
+
| grep -E '^(\./|git[[:space:]]+[a-z]+|bash[[:space:]]+[^[:space:]]|sh[[:space:]]+[^[:space:]]|npm[[:space:]]+run|pnpm[[:space:]]+run|yarn[[:space:]]+run|python[[:space:]]+[^[:space:]]+\.py|node[[:space:]]+[^[:space:]]+\.[mc]?js)' 2>/dev/null \
|
|
96
|
+
| sort -u \
|
|
97
|
+
| head -n "$MAX_TOKENS")
|
|
98
|
+
|
|
99
|
+
[ -z "$TOKENS" ] && exit 0
|
|
100
|
+
|
|
101
|
+
# Apply ALLOW filter if set
|
|
102
|
+
if [ -n "$ALLOW_PATTERN" ]; then
|
|
103
|
+
TOKENS=$(printf '%s\n' "$TOKENS" | grep -Ev "$ALLOW_PATTERN" 2>/dev/null || true)
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
[ -z "$TOKENS" ] && exit 0
|
|
107
|
+
|
|
108
|
+
# Extract all Bash tool-call commands from the entire transcript.
|
|
109
|
+
# Look at tool_use events with name=Bash and pull their command input.
|
|
110
|
+
INVOKED_COMMANDS=$(grep -h '"name":"Bash"' "$TRANSCRIPT" 2>/dev/null \
|
|
111
|
+
| jq -r '
|
|
112
|
+
if .message.content then
|
|
113
|
+
(.message.content[]? | select(.type == "tool_use" and .name == "Bash") | .input.command // empty)
|
|
114
|
+
elif .content then
|
|
115
|
+
(.content[]? | select(.type == "tool_use" and .name == "Bash") | .input.command // empty)
|
|
116
|
+
else empty end
|
|
117
|
+
' 2>/dev/null)
|
|
118
|
+
|
|
119
|
+
# Compare each candidate token against the invoked commands.
|
|
120
|
+
# A token is "verified" if its command-shaped form appears as a substring
|
|
121
|
+
# of any invoked command (matches the literal sequence the operator ran).
|
|
122
|
+
UNVERIFIED=""
|
|
123
|
+
while IFS= read -r token; do
|
|
124
|
+
[ -z "$token" ] && continue
|
|
125
|
+
# Escape token for fixed-string match
|
|
126
|
+
if ! printf '%s' "$INVOKED_COMMANDS" | grep -Fq -- "$token" 2>/dev/null; then
|
|
127
|
+
UNVERIFIED="${UNVERIFIED}${UNVERIFIED:+$'\n'}${token}"
|
|
128
|
+
fi
|
|
129
|
+
done <<< "$TOKENS"
|
|
130
|
+
|
|
131
|
+
[ -z "$UNVERIFIED" ] && exit 0
|
|
132
|
+
|
|
133
|
+
# Emit advisory listing unverified tokens.
|
|
134
|
+
echo "⚠ fabricated-command-detector: command-shaped tokens in the response were not invoked as Bash tool calls in this session:" >&2
|
|
135
|
+
printf '%s\n' "$UNVERIFIED" | while IFS= read -r line; do
|
|
136
|
+
[ -n "$line" ] && echo " - $line" >&2
|
|
137
|
+
done
|
|
138
|
+
echo " Verify each token before relying on the response as an operational record." >&2
|
|
139
|
+
echo " See issue #60340 for the failure shape (substitution-by-default at the response layer)." >&2
|
|
140
|
+
|
|
141
|
+
if [ "${CC_FABRICATED_CMD_BLOCK:-0}" = "1" ]; then
|
|
142
|
+
exit 2
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
exit 0
|