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,232 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# public-artefact-socratic-narrowing.sh — Inject a Socratic-narrowing prompt
|
|
3
|
+
# at the public-artefact emission boundary, asking the agent to re-engage the
|
|
4
|
+
# gradient on decisions in the artefact before it ships.
|
|
5
|
+
#
|
|
6
|
+
# Solves: #60226 (the structural-parent frame) — recognition-without-arrest at
|
|
7
|
+
# the public-artefact emission boundary, as operationalized in @beq00000's
|
|
8
|
+
# clean-state worked example (#60226, 2026-05-19 comment).
|
|
9
|
+
#
|
|
10
|
+
# In that comment, seven instances of recognition-without-arrest surfaced in a
|
|
11
|
+
# single non-drifted session. Three of the seven were caught at the public-
|
|
12
|
+
# artefact emission boundary by the operator's Socratic-narrowing intervention:
|
|
13
|
+
#
|
|
14
|
+
# "The form: not 'is this wrong' (binary question, eliciting binary defence),
|
|
15
|
+
# but 'is this verifiable / already-documented / what-would-actually-need-
|
|
16
|
+
# attention look like' (gradient question, forcing the model to re-engage
|
|
17
|
+
# the rank ordering the original output had flattened). The first form gets
|
|
18
|
+
# defended; the second gets re-decided."
|
|
19
|
+
#
|
|
20
|
+
# The operator-language form is implementable as session discipline today, but
|
|
21
|
+
# the gate fires only when the operator is present and noticing. This hook is
|
|
22
|
+
# the tooling-side form: PreToolUse on the public-artefact emission tools
|
|
23
|
+
# injects a Socratic-narrowing reminder at the boundary so the agent re-engages
|
|
24
|
+
# the gradient regardless of whether the operator is watching this turn.
|
|
25
|
+
#
|
|
26
|
+
# The hook deliberately does not check what the artefact says. Recognition-
|
|
27
|
+
# without-arrest cannot be solved by content classification (that is the
|
|
28
|
+
# failure mode being addressed). The gate's only job is to force one more
|
|
29
|
+
# pass over the artefact with the gradient framing applied. The agent's
|
|
30
|
+
# re-emission is what does the work.
|
|
31
|
+
#
|
|
32
|
+
# Related Issues / Reports:
|
|
33
|
+
# #60226 (@suwayama, 2026-05-18) — recognition-without-arrest framework
|
|
34
|
+
# comment thread → @beq00000 2026-05-19 clean-state worked
|
|
35
|
+
# example with seven instances and the Socratic-narrowing
|
|
36
|
+
# mitigation
|
|
37
|
+
# #60188 (@suwayama) — binary-collapse subhypothesis; the
|
|
38
|
+
# Socratic form re-introduces the gradient
|
|
39
|
+
# #60506 (@zean89, 2026-05-19) — six-day drift across PR-body emissions
|
|
40
|
+
# that survived multiple operator passes
|
|
41
|
+
#
|
|
42
|
+
# TRIGGER: PreToolUse
|
|
43
|
+
# MATCHER: Bash|Write|Edit
|
|
44
|
+
#
|
|
45
|
+
# HOW IT WORKS:
|
|
46
|
+
# 1. Reads PreToolUse input via stdin.
|
|
47
|
+
# 2. For Bash, matches the command against public-artefact emission patterns
|
|
48
|
+
# (gh pr create/edit, gh issue create/comment, gh release create,
|
|
49
|
+
# git commit -m '<long>', git tag -a, etc.).
|
|
50
|
+
# 3. For Write/Edit, matches the target path against public-artefact paths
|
|
51
|
+
# (.github/, CHANGELOG.md, README*.md, docs/, sales-page*.md, etc.).
|
|
52
|
+
# 4. If the artefact body / file content is below a length threshold
|
|
53
|
+
# (default 200 chars), allows it through silently — short artefacts are
|
|
54
|
+
# not where the binary-collapse failure surfaces.
|
|
55
|
+
# 5. Computes a content hash of the artefact body. If the same hash was
|
|
56
|
+
# seen within the cache window (default 600s), allows through — the
|
|
57
|
+
# agent has already re-engaged the gradient on this content.
|
|
58
|
+
# 6. Otherwise emits a Socratic-narrowing system-reminder via stderr and
|
|
59
|
+
# exits 2, blocking the emission until the agent re-emits.
|
|
60
|
+
#
|
|
61
|
+
# The hash-based cache is what makes the gate non-infinite. After the agent
|
|
62
|
+
# re-emits with the gradient applied (different content → new hash → re-fired
|
|
63
|
+
# once), or after deliberately re-emitting the same content (operator-
|
|
64
|
+
# approved → hash matches → passes through), the artefact ships.
|
|
65
|
+
#
|
|
66
|
+
# CONFIGURATION (environment variables):
|
|
67
|
+
# CC_SOCRATIC_DISABLE set to "1" to disable the gate entirely
|
|
68
|
+
# CC_SOCRATIC_STATE_DIR default /tmp/cc-socratic-cache
|
|
69
|
+
# CC_SOCRATIC_BODY_MIN_CHARS default 200 — artefacts shorter than this
|
|
70
|
+
# are not gated
|
|
71
|
+
# CC_SOCRATIC_CACHE_TTL_SECONDS default 600 — how long a hash counts as
|
|
72
|
+
# "already re-engaged"
|
|
73
|
+
# CC_SOCRATIC_BASH_PATTERNS default built-in — regex of Bash commands
|
|
74
|
+
# CC_SOCRATIC_FILE_PATTERNS default built-in — regex of file paths
|
|
75
|
+
#
|
|
76
|
+
# USAGE (settings.json):
|
|
77
|
+
# {
|
|
78
|
+
# "hooks": {
|
|
79
|
+
# "PreToolUse": [{
|
|
80
|
+
# "matcher": "Bash|Write|Edit",
|
|
81
|
+
# "hooks": [{
|
|
82
|
+
# "type": "command",
|
|
83
|
+
# "command": "~/.claude/hooks/public-artefact-socratic-narrowing.sh"
|
|
84
|
+
# }]
|
|
85
|
+
# }]
|
|
86
|
+
# }
|
|
87
|
+
# }
|
|
88
|
+
|
|
89
|
+
set -uo pipefail
|
|
90
|
+
|
|
91
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
92
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
93
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
94
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
95
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
96
|
+
_nojq_warned="/tmp/cc-nojq-warned-public-artefact-socratic-narrowing-$PPID"
|
|
97
|
+
[ -f "$_nojq_warned" ] || {
|
|
98
|
+
echo "WARNING [public-artefact-socratic-narrowing]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
99
|
+
: > "$_nojq_warned"
|
|
100
|
+
}
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
[ "${CC_SOCRATIC_DISABLE:-0}" = "1" ] && exit 0
|
|
104
|
+
|
|
105
|
+
# OPT-IN: this gate blocks every public-artefact emission (commits, PRs, docs
|
|
106
|
+
# edits) on first pass, which is high friction as a default. It is therefore
|
|
107
|
+
# off unless explicitly enabled. Set CC_SOCRATIC_ENABLE=1 to turn it on.
|
|
108
|
+
[ "${CC_SOCRATIC_ENABLE:-0}" = "1" ] || exit 0
|
|
109
|
+
|
|
110
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
111
|
+
[ -z "$INPUT" ] && exit 0
|
|
112
|
+
|
|
113
|
+
STATE_DIR="${CC_SOCRATIC_STATE_DIR:-/tmp/cc-socratic-cache}"
|
|
114
|
+
BODY_MIN_CHARS="${CC_SOCRATIC_BODY_MIN_CHARS:-200}"
|
|
115
|
+
CACHE_TTL="${CC_SOCRATIC_CACHE_TTL_SECONDS:-600}"
|
|
116
|
+
|
|
117
|
+
DEFAULT_BASH_PATTERNS='gh[[:space:]]+pr[[:space:]]+(create|edit)|gh[[:space:]]+issue[[:space:]]+(create|comment)|gh[[:space:]]+release[[:space:]]+create|gh[[:space:]]+gist[[:space:]]+create|git[[:space:]]+commit[[:space:]]+.*-m|git[[:space:]]+tag[[:space:]]+-a|git[[:space:]]+notes[[:space:]]+add'
|
|
118
|
+
DEFAULT_FILE_PATTERNS='(^|/)\.github/|(^|/)CHANGELOG(\.[a-z]+)?|(^|/)README[^/]*$|(^|/)docs?/|(^|/)sales-page|(^|/)launch-|(^|/)RELEASE|(^|/)NOTICE|(^|/)CITATION'
|
|
119
|
+
|
|
120
|
+
BASH_PATTERNS="${CC_SOCRATIC_BASH_PATTERNS:-$DEFAULT_BASH_PATTERNS}"
|
|
121
|
+
FILE_PATTERNS="${CC_SOCRATIC_FILE_PATTERNS:-$DEFAULT_FILE_PATTERNS}"
|
|
122
|
+
|
|
123
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || true
|
|
124
|
+
|
|
125
|
+
# Extract tool name and input from the PreToolUse payload
|
|
126
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // .tool // empty' 2>/dev/null)
|
|
127
|
+
[ -z "$TOOL_NAME" ] && exit 0
|
|
128
|
+
|
|
129
|
+
ARTEFACT_BODY=""
|
|
130
|
+
ARTEFACT_KIND=""
|
|
131
|
+
|
|
132
|
+
case "$TOOL_NAME" in
|
|
133
|
+
Bash)
|
|
134
|
+
CMD=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
135
|
+
[ -z "$CMD" ] && exit 0
|
|
136
|
+
# Does the command match a public-artefact emission pattern?
|
|
137
|
+
printf '%s' "$CMD" | grep -Eiq "$BASH_PATTERNS" || exit 0
|
|
138
|
+
ARTEFACT_BODY="$CMD"
|
|
139
|
+
ARTEFACT_KIND="bash-command"
|
|
140
|
+
;;
|
|
141
|
+
Write)
|
|
142
|
+
FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
143
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
144
|
+
printf '%s' "$FILE_PATH" | grep -Eiq "$FILE_PATTERNS" || exit 0
|
|
145
|
+
ARTEFACT_BODY=$(printf '%s' "$INPUT" | jq -r '.tool_input.content // empty' 2>/dev/null)
|
|
146
|
+
ARTEFACT_KIND="file-write:$FILE_PATH"
|
|
147
|
+
;;
|
|
148
|
+
Edit)
|
|
149
|
+
FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
150
|
+
[ -z "$FILE_PATH" ] && exit 0
|
|
151
|
+
printf '%s' "$FILE_PATH" | grep -Eiq "$FILE_PATTERNS" || exit 0
|
|
152
|
+
ARTEFACT_BODY=$(printf '%s' "$INPUT" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
|
|
153
|
+
ARTEFACT_KIND="file-edit:$FILE_PATH"
|
|
154
|
+
;;
|
|
155
|
+
*)
|
|
156
|
+
exit 0
|
|
157
|
+
;;
|
|
158
|
+
esac
|
|
159
|
+
|
|
160
|
+
# Below threshold → not where the failure surfaces
|
|
161
|
+
BODY_LEN=${#ARTEFACT_BODY}
|
|
162
|
+
if [ "$BODY_LEN" -lt "$BODY_MIN_CHARS" ]; then
|
|
163
|
+
exit 0
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# Hash the artefact body. If we have seen this hash recently, the agent has
|
|
167
|
+
# already had one Socratic-narrowing pass on it — allow through.
|
|
168
|
+
HASH=$(printf '%s' "$ARTEFACT_BODY" | sha256sum 2>/dev/null | awk '{print $1}')
|
|
169
|
+
[ -z "$HASH" ] && exit 0
|
|
170
|
+
|
|
171
|
+
CACHE_FILE="$STATE_DIR/$HASH"
|
|
172
|
+
NOW=$(date +%s)
|
|
173
|
+
|
|
174
|
+
if [ -f "$CACHE_FILE" ]; then
|
|
175
|
+
CACHED_AT=$(cat "$CACHE_FILE" 2>/dev/null || echo 0)
|
|
176
|
+
AGE=$((NOW - CACHED_AT))
|
|
177
|
+
if [ "$AGE" -lt "$CACHE_TTL" ]; then
|
|
178
|
+
# Same content within window → agent has re-engaged → ship it
|
|
179
|
+
exit 0
|
|
180
|
+
fi
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
# Record the hash so the re-emission passes through
|
|
184
|
+
echo "$NOW" > "$CACHE_FILE"
|
|
185
|
+
|
|
186
|
+
# Best-effort cache eviction: drop entries older than 24h
|
|
187
|
+
find "$STATE_DIR" -type f -mmin +1440 -delete 2>/dev/null || true
|
|
188
|
+
|
|
189
|
+
# Emit the Socratic-narrowing reminder and block the emission once
|
|
190
|
+
cat >&2 <<EOF
|
|
191
|
+
<system-reminder>
|
|
192
|
+
PUBLIC-ARTEFACT EMISSION BOUNDARY — about to emit $ARTEFACT_KIND
|
|
193
|
+
($BODY_LEN chars). This is the boundary at which three of seven instances of
|
|
194
|
+
recognition-without-arrest surfaced in @beq00000's clean-state worked example
|
|
195
|
+
on #60226 (2026-05-19).
|
|
196
|
+
|
|
197
|
+
Before this artefact ships, re-engage the gradient on each decision in it.
|
|
198
|
+
The Socratic-narrowing form (per @beq00000) is the one that works:
|
|
199
|
+
|
|
200
|
+
Not "is any of this wrong?" — that question elicits binary defence and
|
|
201
|
+
the model defends the artefact as emitted.
|
|
202
|
+
|
|
203
|
+
Instead, ask of each list / each claim / each register choice in the
|
|
204
|
+
artefact:
|
|
205
|
+
(a) What is the gradient this decision sits on?
|
|
206
|
+
e.g. item-substantiveness, public-appropriateness, verifiable-vs-
|
|
207
|
+
speculative, novel-vs-already-documented, gradient-flag-quality.
|
|
208
|
+
(b) Which items in the artefact collapse into the substantive end of
|
|
209
|
+
the gradient on second-pass review? Which collapse into the trivial
|
|
210
|
+
end?
|
|
211
|
+
(c) Reproduce the artefact with the gradient applied — keep what
|
|
212
|
+
survives, drop or rephrase what does not.
|
|
213
|
+
|
|
214
|
+
Then re-emit. If the re-emitted artefact is structurally different from this
|
|
215
|
+
one, that is the gate working. If the re-emitted artefact is byte-identical
|
|
216
|
+
to this one and you have considered the gradient and stand by every decision,
|
|
217
|
+
re-running the same command within ${CACHE_TTL}s will ship it (the hash
|
|
218
|
+
matches and the gate passes through).
|
|
219
|
+
|
|
220
|
+
To disable this gate intentionally (for low-stakes commits, automated tooling,
|
|
221
|
+
non-public artefacts mis-classified as public), set CC_SOCRATIC_DISABLE=1 in
|
|
222
|
+
your environment, or refine CC_SOCRATIC_BASH_PATTERNS / CC_SOCRATIC_FILE_PATTERNS
|
|
223
|
+
to exclude the false-positive class.
|
|
224
|
+
|
|
225
|
+
Underlying mechanism (per @suwayama #60188): binary-collapse of decisions
|
|
226
|
+
that should sit on a gradient. The reminder above is the operator-language
|
|
227
|
+
intervention promoted to a tooling-side gate; the gradient framing is what
|
|
228
|
+
makes it work, not the blocking.
|
|
229
|
+
</system-reminder>
|
|
230
|
+
EOF
|
|
231
|
+
|
|
232
|
+
exit 2
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
|
|
18
18
|
set -uo pipefail
|
|
19
19
|
|
|
20
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
21
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
22
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
23
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
24
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
25
|
+
_nojq_warned="/tmp/cc-nojq-warned-public-repo-push-guard-$PPID"
|
|
26
|
+
[ -f "$_nojq_warned" ] || {
|
|
27
|
+
echo "WARNING [public-repo-push-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
28
|
+
: > "$_nojq_warned"
|
|
29
|
+
}
|
|
30
|
+
fi
|
|
31
|
+
|
|
20
32
|
INPUT=$(cat)
|
|
21
33
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
22
34
|
[ -z "$COMMAND" ] && exit 0
|
|
File without changes
|
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
#
|
|
28
28
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
29
29
|
|
|
30
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
31
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
32
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
33
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
34
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
35
|
+
_nojq_warned="/tmp/cc-nojq-warned-push-requires-test-pass-$PPID"
|
|
36
|
+
[ -f "$_nojq_warned" ] || {
|
|
37
|
+
echo "WARNING [push-requires-test-pass]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
38
|
+
: > "$_nojq_warned"
|
|
39
|
+
}
|
|
40
|
+
fi
|
|
41
|
+
|
|
30
42
|
INPUT=$(cat)
|
|
31
43
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
32
44
|
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# quota-anomaly-detector.sh — alert when token consumption rate diverges from your personal baseline
|
|
3
|
+
#
|
|
4
|
+
# Why: The Pro Max quota anomaly cluster (#16157 / #38335 / #45756 / #41788 / #29579
|
|
5
|
+
# / #19673 / cumulative ~1,600 reactions) reports the same operator-side symptom:
|
|
6
|
+
# the quota empties materially faster than the same workflow used to consume it,
|
|
7
|
+
# sometimes within minutes of the session starting. Four issues name a runtime
|
|
8
|
+
# version or date boundary (2026-03-23 / v2.1.89 / v2.1.100 / 2.1.1) so the
|
|
9
|
+
# shift is version-correlated.
|
|
10
|
+
#
|
|
11
|
+
# cache-creation-drift-detector.sh catches the *per-request* server-side
|
|
12
|
+
# inflation documented in #46917, but it cannot see the cross-request picture:
|
|
13
|
+
# a session that fires 40 small requests in 10 minutes burns the same quota as
|
|
14
|
+
# one large request, and only the rolling rate exposes it. This hook fills that
|
|
15
|
+
# gap by tracking total tokens-per-minute against a personal trailing baseline.
|
|
16
|
+
#
|
|
17
|
+
# Composes with cache-creation-drift-detector (per-request) and the existing
|
|
18
|
+
# session-quota-tracker.sh (raw tool-call count, no token weight).
|
|
19
|
+
#
|
|
20
|
+
# Event: PostToolUse MATCHER: "" (all tools)
|
|
21
|
+
# Action: Sum input_tokens + output_tokens + cache_read_input_tokens +
|
|
22
|
+
# cache_creation_input_tokens from the PostToolUse payload (or last
|
|
23
|
+
# assistant turn in the transcript as fallback). Append a timestamped
|
|
24
|
+
# sample to a rolling JSONL log. Compute the operator's tokens-per-minute
|
|
25
|
+
# over the trailing window. If the current window's rate exceeds the
|
|
26
|
+
# trailing baseline by a configurable multiplier, emit a one-line stderr
|
|
27
|
+
# warning. Advisory only (exit 0); does not block.
|
|
28
|
+
#
|
|
29
|
+
# Configuration (all optional):
|
|
30
|
+
# CC_QUOTA_ANOMALY_LOG Log path (default: ~/.cache/cc-safe-setup/quota-anomaly.jsonl)
|
|
31
|
+
# CC_QUOTA_ANOMALY_THRESHOLD Multiplier for alert (default: 1.5 = 50% above baseline rate)
|
|
32
|
+
# CC_QUOTA_ANOMALY_MIN_HISTORY Minimum samples before alerting (default: 30)
|
|
33
|
+
# CC_QUOTA_ANOMALY_WINDOW_MIN Current-rate window in minutes (default: 10)
|
|
34
|
+
# CC_QUOTA_ANOMALY_BASELINE_MIN Baseline window in minutes (default: 1440 = 24h)
|
|
35
|
+
# CC_QUOTA_ANOMALY_SILENT Set to "1" to suppress stderr (still logs)
|
|
36
|
+
#
|
|
37
|
+
# Inspect the log:
|
|
38
|
+
# tail -50 ~/.cache/cc-safe-setup/quota-anomaly.jsonl
|
|
39
|
+
# jq -s 'map(.total) | add' ~/.cache/cc-safe-setup/quota-anomaly.jsonl
|
|
40
|
+
#
|
|
41
|
+
# The registration was missing from this header. The installer reads TRIGGER
|
|
42
|
+
# and MATCHER from here and falls back to PreToolUse / Bash when both are
|
|
43
|
+
# absent, so this hook was being registered at a moment where the field it
|
|
44
|
+
# reads is always empty: it installed, it appeared in the settings, and it
|
|
45
|
+
# did nothing. Measured 2026-08-04 across examples/: 14 files were like this.
|
|
46
|
+
# TRIGGER: PostToolUse
|
|
47
|
+
# MATCHER: ""
|
|
48
|
+
|
|
49
|
+
set -u
|
|
50
|
+
|
|
51
|
+
LOG="${CC_QUOTA_ANOMALY_LOG:-${HOME}/.cache/cc-safe-setup/quota-anomaly.jsonl}"
|
|
52
|
+
THRESHOLD="${CC_QUOTA_ANOMALY_THRESHOLD:-1.5}"
|
|
53
|
+
MIN_HISTORY="${CC_QUOTA_ANOMALY_MIN_HISTORY:-30}"
|
|
54
|
+
WINDOW_MIN="${CC_QUOTA_ANOMALY_WINDOW_MIN:-10}"
|
|
55
|
+
BASELINE_MIN="${CC_QUOTA_ANOMALY_BASELINE_MIN:-1440}"
|
|
56
|
+
SILENT="${CC_QUOTA_ANOMALY_SILENT:-0}"
|
|
57
|
+
|
|
58
|
+
mkdir -p "$(dirname "$LOG")" 2>/dev/null
|
|
59
|
+
|
|
60
|
+
INPUT=$(cat)
|
|
61
|
+
|
|
62
|
+
extract_total() {
|
|
63
|
+
# $1 = jq path prefix to usage object
|
|
64
|
+
local prefix="$1"
|
|
65
|
+
printf '%s' "$INPUT" | jq -r --arg p "$prefix" '
|
|
66
|
+
def num(x): if (x | type) == "number" then x else 0 end;
|
|
67
|
+
($p | split(".") | map(select(length > 0))) as $path |
|
|
68
|
+
(getpath($path)) as $u |
|
|
69
|
+
if $u == null then empty
|
|
70
|
+
else
|
|
71
|
+
(num($u.input_tokens) + num($u.output_tokens) +
|
|
72
|
+
num($u.cache_read_input_tokens) + num($u.cache_creation_input_tokens))
|
|
73
|
+
end
|
|
74
|
+
' 2>/dev/null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Try PostToolUse payload first.
|
|
78
|
+
TOTAL=$(extract_total ".tool_response.usage")
|
|
79
|
+
|
|
80
|
+
# Fallback: read the last assistant turn's usage from the transcript.
|
|
81
|
+
if [ -z "$TOTAL" ] || [ "$TOTAL" = "0" ]; then
|
|
82
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
83
|
+
if [ -n "$TRANSCRIPT" ] && [ -r "$TRANSCRIPT" ]; then
|
|
84
|
+
LAST_USAGE_LINE=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"usage"' || true)
|
|
85
|
+
if [ -n "$LAST_USAGE_LINE" ]; then
|
|
86
|
+
TOTAL=$(printf '%s' "$LAST_USAGE_LINE" | jq -r '
|
|
87
|
+
def num(x): if (x | type) == "number" then x else 0 end;
|
|
88
|
+
(.message.usage // .usage // null) as $u |
|
|
89
|
+
if $u == null then empty
|
|
90
|
+
else
|
|
91
|
+
(num($u.input_tokens) + num($u.output_tokens) +
|
|
92
|
+
num($u.cache_read_input_tokens) + num($u.cache_creation_input_tokens))
|
|
93
|
+
end
|
|
94
|
+
' 2>/dev/null)
|
|
95
|
+
fi
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# No usable measurement.
|
|
100
|
+
if [ -z "$TOTAL" ] || [ "$TOTAL" = "0" ] || [ "$TOTAL" = "null" ]; then
|
|
101
|
+
exit 0
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Validate positive integer.
|
|
105
|
+
case "$TOTAL" in
|
|
106
|
+
''|*[!0-9]*) exit 0 ;;
|
|
107
|
+
esac
|
|
108
|
+
|
|
109
|
+
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
|
|
110
|
+
NOW_EPOCH=$(date -u +%s)
|
|
111
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
112
|
+
|
|
113
|
+
# Append sample.
|
|
114
|
+
printf '{"ts":"%s","epoch":%s,"session":"%s","total":%s}\n' \
|
|
115
|
+
"$TS" "$NOW_EPOCH" "$SESSION_ID" "$TOTAL" >> "$LOG"
|
|
116
|
+
|
|
117
|
+
# Need MIN_HISTORY samples before trusting the baseline.
|
|
118
|
+
SAMPLE_COUNT=$(wc -l < "$LOG" 2>/dev/null | tr -d ' ')
|
|
119
|
+
SAMPLE_COUNT="${SAMPLE_COUNT:-0}"
|
|
120
|
+
if [ "$SAMPLE_COUNT" -lt "$MIN_HISTORY" ]; then
|
|
121
|
+
exit 0
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Compute current window sum and baseline window sum.
|
|
125
|
+
WINDOW_CUTOFF=$((NOW_EPOCH - WINDOW_MIN * 60))
|
|
126
|
+
BASELINE_CUTOFF=$((NOW_EPOCH - BASELINE_MIN * 60))
|
|
127
|
+
|
|
128
|
+
# Read once, compute both sums and counts.
|
|
129
|
+
SUMS=$(awk -v wc="$WINDOW_CUTOFF" -v bc="$BASELINE_CUTOFF" '
|
|
130
|
+
/"epoch":/ {
|
|
131
|
+
# Extract epoch and total via simple field parse (matches our writer format).
|
|
132
|
+
match($0, /"epoch":[0-9]+/)
|
|
133
|
+
e = substr($0, RSTART+8, RLENGTH-8) + 0
|
|
134
|
+
match($0, /"total":[0-9]+/)
|
|
135
|
+
t = substr($0, RSTART+8, RLENGTH-8) + 0
|
|
136
|
+
if (e >= bc) {
|
|
137
|
+
bs += t; bn++
|
|
138
|
+
if (e >= wc) { ws += t; wn++ }
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
END { printf "%d %d %d %d", ws, wn, bs, bn }
|
|
142
|
+
' "$LOG" 2>/dev/null)
|
|
143
|
+
|
|
144
|
+
WINDOW_SUM=$(echo "$SUMS" | awk '{print $1}')
|
|
145
|
+
WINDOW_N=$(echo "$SUMS" | awk '{print $2}')
|
|
146
|
+
BASELINE_SUM=$(echo "$SUMS" | awk '{print $3}')
|
|
147
|
+
BASELINE_N=$(echo "$SUMS" | awk '{print $4}')
|
|
148
|
+
|
|
149
|
+
# Need enough activity in both windows.
|
|
150
|
+
if [ "${WINDOW_N:-0}" -lt 2 ] || [ "${BASELINE_N:-0}" -lt "$MIN_HISTORY" ]; then
|
|
151
|
+
exit 0
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# Compute rates: tokens per minute in each window.
|
|
155
|
+
RATIO=$(awk -v ws="$WINDOW_SUM" -v wm="$WINDOW_MIN" \
|
|
156
|
+
-v bs="$BASELINE_SUM" -v bm="$BASELINE_MIN" '
|
|
157
|
+
BEGIN {
|
|
158
|
+
wr = ws / wm
|
|
159
|
+
br = bs / bm
|
|
160
|
+
if (br > 0) printf "%.3f", wr / br; else print "0"
|
|
161
|
+
}')
|
|
162
|
+
EXCEEDS=$(awk -v r="$RATIO" -v t="$THRESHOLD" 'BEGIN { print (r > t) ? 1 : 0 }')
|
|
163
|
+
|
|
164
|
+
if [ "$EXCEEDS" = "1" ] && [ "$SILENT" != "1" ]; then
|
|
165
|
+
WIN_RATE=$(awk -v ws="$WINDOW_SUM" -v wm="$WINDOW_MIN" 'BEGIN { printf "%d", ws/wm }')
|
|
166
|
+
BASE_RATE=$(awk -v bs="$BASELINE_SUM" -v bm="$BASELINE_MIN" 'BEGIN { printf "%d", bs/bm }')
|
|
167
|
+
PCT=$(awk -v r="$RATIO" 'BEGIN { printf "%d", (r - 1) * 100 }')
|
|
168
|
+
echo "NOTICE: token consumption rate ~${WIN_RATE} tok/min over last ${WINDOW_MIN}min is ${PCT}% above your ${BASELINE_MIN}min baseline (~${BASE_RATE} tok/min)." >&2
|
|
169
|
+
echo " Pro Max quota anomaly cluster: anthropics/claude-code #16157 / #38335 / #45756." >&2
|
|
170
|
+
echo " Inspect ${LOG} or set CC_QUOTA_ANOMALY_SILENT=1 to suppress." >&2
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
exit 0
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# quota-reset-audit.sh — weekly quota reset cluster logger (Incident 9)
|
|
3
|
+
# Why: On 2026-04-23 users reported /usage showing quota available while
|
|
4
|
+
# sessions were being rate-limited. Client-side vs server-side
|
|
5
|
+
# timezone handling of the weekly reset diverged. The dashboard's
|
|
6
|
+
# resets_at value is the only ground truth available to users, and
|
|
7
|
+
# a log of resets_at at each session start is the only way to prove
|
|
8
|
+
# "the dashboard said X, the actual reset happened Y."
|
|
9
|
+
# Event: SessionStart
|
|
10
|
+
# Action: Capture /usage --json at session start. Log the timestamp,
|
|
11
|
+
# resets_at, and percent-used to ~/.claude/logs/usage-audit.log.
|
|
12
|
+
# If /usage is unavailable (pre-v2.1.118) log a placeholder so the
|
|
13
|
+
# session never fails because of the hook.
|
|
14
|
+
|
|
15
|
+
set -u
|
|
16
|
+
|
|
17
|
+
LOG_DIR="${HOME}/.claude/logs"
|
|
18
|
+
LOG_FILE="${LOG_DIR}/usage-audit.log"
|
|
19
|
+
mkdir -p "$LOG_DIR" 2>/dev/null
|
|
20
|
+
|
|
21
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
22
|
+
SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
|
|
23
|
+
|
|
24
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
25
|
+
|
|
26
|
+
fetch_usage() {
|
|
27
|
+
# Prefer the claude CLI subcommand when available (v2.1.118+ shipped
|
|
28
|
+
# /usage with --json output). Fall back to `claude usage --json` which
|
|
29
|
+
# some earlier builds exposed. If neither works, return empty.
|
|
30
|
+
local out=""
|
|
31
|
+
if command -v claude >/dev/null 2>&1; then
|
|
32
|
+
out=$(timeout 5 claude /usage --json 2>/dev/null || true)
|
|
33
|
+
if [ -z "$out" ] || ! printf '%s' "$out" | jq -e . >/dev/null 2>&1; then
|
|
34
|
+
out=$(timeout 5 claude usage --json 2>/dev/null || true)
|
|
35
|
+
fi
|
|
36
|
+
fi
|
|
37
|
+
printf '%s' "$out"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
USAGE_JSON=$(fetch_usage)
|
|
41
|
+
|
|
42
|
+
if [ -z "$USAGE_JSON" ] || ! printf '%s' "$USAGE_JSON" | jq -e . >/dev/null 2>&1; then
|
|
43
|
+
printf '%s\t%s\t%s\t%s\t%s\n' \
|
|
44
|
+
"$TS" "$SESSION_ID" "unavailable" "unavailable" "unavailable" \
|
|
45
|
+
>> "$LOG_FILE"
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Expected /usage fields vary by CC version. Pull common ones defensively.
|
|
50
|
+
RESETS_AT=$(printf '%s' "$USAGE_JSON" | jq -r '.weekly.resets_at // .resets_at // .weeklyResetsAt // "unknown"' 2>/dev/null)
|
|
51
|
+
PCT_USED=$(printf '%s' "$USAGE_JSON" | jq -r '.weekly.percent_used // .percent_used // .weeklyPercentUsed // "unknown"' 2>/dev/null)
|
|
52
|
+
TIER=$(printf '%s' "$USAGE_JSON" | jq -r '.tier // .plan // "unknown"' 2>/dev/null)
|
|
53
|
+
|
|
54
|
+
printf '%s\t%s\t%s\t%s\t%s\n' \
|
|
55
|
+
"$TS" "$SESSION_ID" "$TIER" "$RESETS_AT" "$PCT_USED" \
|
|
56
|
+
>> "$LOG_FILE"
|
|
57
|
+
|
|
58
|
+
exit 0
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
# trigger a confirmation prompt even when they match allowlist patterns.
|
|
11
11
|
#
|
|
12
12
|
# This PermissionRequest hook auto-approves these prompts when:
|
|
13
|
-
# 1.
|
|
13
|
+
# 1. Every command position is in a safe list
|
|
14
14
|
# 2. The only "issue" is quoted characters in flag values
|
|
15
15
|
#
|
|
16
16
|
# TRIGGER: PermissionRequest
|
|
@@ -25,6 +25,25 @@
|
|
|
25
25
|
# }]
|
|
26
26
|
# }
|
|
27
27
|
# }
|
|
28
|
+
#
|
|
29
|
+
# Fixed 2026-08-03. The safe list held bare command *words* — `git`, `curl`,
|
|
30
|
+
# `chmod`, `sed`, `node`, `python3`, `npx` — and a word says nothing about what
|
|
31
|
+
# the command does. `git commit -m "fix"` and `git push --force origin main`
|
|
32
|
+
# have the same first word.
|
|
33
|
+
#
|
|
34
|
+
# Measured against the shipped copy, over 20 destructive or credential-reading
|
|
35
|
+
# commands with no separator in them at all: **15 were approved**, among them
|
|
36
|
+
# `git push --force`, `git reset --hard`, `git clean -fdx`, `chmod -R 777 /`,
|
|
37
|
+
# `curl … | sh`, `node -e '…rmSync…'` and `cat ~/.aws/credentials`.
|
|
38
|
+
#
|
|
39
|
+
# This is a different defect from the first-command-position one repaired in
|
|
40
|
+
# #937/#940/#941/#942/#943/#947, and mixing the two would produce a number that
|
|
41
|
+
# looks right and is not: nothing here was hiding past a separator. The
|
|
42
|
+
# granularity of the list was the problem. (The first-position defect was here
|
|
43
|
+
# too, and is fixed in the same pass.)
|
|
44
|
+
#
|
|
45
|
+
# Known limit: quotes are not parsed when splitting, so a separator inside a
|
|
46
|
+
# quoted string ends a segment early. That errs toward fewer approvals.
|
|
28
47
|
|
|
29
48
|
INPUT=$(cat)
|
|
30
49
|
|
|
@@ -36,16 +55,86 @@ echo "$MESSAGE" | grep -qi "quoted characters in flag" || exit 0
|
|
|
36
55
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
37
56
|
[ -z "$COMMAND" ] && exit 0
|
|
38
57
|
|
|
39
|
-
#
|
|
40
|
-
|
|
58
|
+
# A substitution or backtick carries a command no string-level read can see.
|
|
59
|
+
# This hook is about quoted flag values, not substitution, so it refuses them.
|
|
60
|
+
case "$COMMAND" in
|
|
61
|
+
*'$('*|*'`'*) exit 0 ;;
|
|
62
|
+
esac
|
|
63
|
+
|
|
64
|
+
# Command words that carry no destructive form of their own. Anything that
|
|
65
|
+
# takes code as an argument (`node -e`, `python3 -c`, `npx`) or fetches and runs
|
|
66
|
+
# (`curl`, `wget`) is deliberately absent: for those the word says nothing.
|
|
67
|
+
cc_base_ok() {
|
|
68
|
+
case "$1" in
|
|
69
|
+
cat|head|tail|less|more|wc|file|stat|du|df|ls|tree|\
|
|
70
|
+
which|whereis|type|realpath|readlink|basename|dirname|\
|
|
71
|
+
grep|rg|ag|ack|sort|uniq|tr|cut|column|nl|rev|awk|\
|
|
72
|
+
echo|printf|true|false|pwd|date|uname|hostname|whoami|id|\
|
|
73
|
+
jq|yq|cd|\
|
|
74
|
+
tsc|eslint|prettier|jest|vitest|pytest)
|
|
75
|
+
return 0 ;;
|
|
76
|
+
esac
|
|
77
|
+
return 1
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Build tool subcommands that neither destroy history nor run fetched code.
|
|
81
|
+
# One line on purpose: inside single quotes a trailing backslash is a literal
|
|
82
|
+
# backslash-newline, not a continuation, and the pattern silently stops matching.
|
|
83
|
+
CC_SUBCMD_RE='^[[:space:]]*(git[[:space:]]+(status|log|diff|show|add|commit|branch|remote|describe|rev-parse|blame|shortlog|ls-files|ls-tree|fetch|stash[[:space:]]+(list|push|save))|npm[[:space:]]+(test|run|ci|ls|view|outdated)|yarn[[:space:]]+(test|run|info|why)|pnpm[[:space:]]+(test|run|list|why)|bun[[:space:]]+(test|run)|cargo[[:space:]]+(build|test|check|fmt|clippy|tree)|go[[:space:]]+(build|test|vet|fmt|list)|docker[[:space:]]+(ps|images|logs|inspect|version|info)|make[[:space:]]+[A-Za-z0-9_.-]+|pip[[:space:]]+(list|show|freeze)|python3[[:space:]]+-m[[:space:]]+(pytest|unittest|pip[[:space:]]+(list|show|freeze)))([[:space:]]|$)'
|
|
84
|
+
|
|
85
|
+
cc_subcommand_ok() {
|
|
86
|
+
printf '%s' "$1" | grep -qE "$CC_SUBCMD_RE"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
cc_segment_base() {
|
|
90
|
+
printf '%s' "$1" \
|
|
91
|
+
| sed -E 's/^[[:space:]]+//; s/^([A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*[[:space:]]+)*//' \
|
|
92
|
+
| awk '{print $1}' \
|
|
93
|
+
| sed 's|.*/||'
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# `git branch` reads; `git branch -D main` deletes one. Same first two words.
|
|
97
|
+
CC_GIT_DESTRUCTIVE_RE='^[[:space:]]*git[[:space:]]+(branch|tag)[[:space:]]+-([dDmM]|-delete|-move)([[:space:]]|$)'
|
|
98
|
+
|
|
99
|
+
cc_segment_ok() {
|
|
100
|
+
local seg="$1" base
|
|
101
|
+
base=$(cc_segment_base "$seg")
|
|
102
|
+
[ -z "$base" ] && return 1
|
|
103
|
+
|
|
104
|
+
if [ "$base" = "find" ]; then
|
|
105
|
+
printf '%s' "$seg" \
|
|
106
|
+
| grep -qE '(^|[[:space:]])-(delete|exec|execdir|ok|okdir|fprintf?|fls|fprint0)([[:space:]]|$)' \
|
|
107
|
+
&& return 1
|
|
108
|
+
return 0
|
|
109
|
+
fi
|
|
110
|
+
if [ "$base" = "sed" ]; then
|
|
111
|
+
printf '%s' "$seg" | grep -qE '(^|[[:space:]])-[a-zA-Z]*i' && return 1
|
|
112
|
+
return 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
cc_base_ok "$base" && return 0
|
|
116
|
+
printf '%s' "$seg" | grep -qE "$CC_GIT_DESTRUCTIVE_RE" && return 1
|
|
117
|
+
cc_subcommand_ok "$seg" && return 0
|
|
118
|
+
return 1
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# A redirection writes a file, whatever the command word says.
|
|
122
|
+
case "$COMMAND" in
|
|
123
|
+
*'>'*) exit 0 ;;
|
|
124
|
+
esac
|
|
41
125
|
|
|
42
|
-
|
|
43
|
-
|
|
126
|
+
IDX=0
|
|
127
|
+
while IFS= read -r SEG; do
|
|
128
|
+
SEG="${SEG#"${SEG%%[![:space:]]*}"}"
|
|
129
|
+
SEG="${SEG%"${SEG##*[![:space:]]}"}"
|
|
130
|
+
[ -z "$SEG" ] && continue
|
|
131
|
+
cc_segment_ok "$SEG" || exit 0
|
|
132
|
+
IDX=$((IDX + 1))
|
|
133
|
+
done <<EOF
|
|
134
|
+
$(printf '%s' "$COMMAND" | tr ';&|' '\n\n\n')
|
|
135
|
+
EOF
|
|
44
136
|
|
|
45
|
-
|
|
46
|
-
echo '{"permissionDecision":"allow"}'
|
|
47
|
-
exit 0
|
|
48
|
-
fi
|
|
137
|
+
[ "$IDX" -eq 0 ] && exit 0
|
|
49
138
|
|
|
50
|
-
|
|
139
|
+
echo '{"permissionDecision":"allow"}'
|
|
51
140
|
exit 0
|
|
@@ -19,6 +19,18 @@
|
|
|
19
19
|
#
|
|
20
20
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
21
21
|
|
|
22
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
23
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
24
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
25
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
26
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
27
|
+
_nojq_warned="/tmp/cc-nojq-warned-rails-migration-guard-$PPID"
|
|
28
|
+
[ -f "$_nojq_warned" ] || {
|
|
29
|
+
echo "WARNING [rails-migration-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
30
|
+
: > "$_nojq_warned"
|
|
31
|
+
}
|
|
32
|
+
fi
|
|
33
|
+
|
|
22
34
|
INPUT=$(cat)
|
|
23
35
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
24
36
|
|
|
File without changes
|
|
File without changes
|