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,182 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# stop-hook-sigterm-wrapper.sh — Wrap the claude CLI so an
|
|
4
|
+
# external supervisor can distinguish "completed" from "killed
|
|
5
|
+
# mid-work" when SIGTERM (e.g. `timeout` exit code 124) bypasses
|
|
6
|
+
# the configured Stop hook.
|
|
7
|
+
# ================================================================
|
|
8
|
+
# PURPOSE:
|
|
9
|
+
# Issue #64017 documents a class where SIGTERM termination of
|
|
10
|
+
# the claude process (typically by a wrapper enforcing an
|
|
11
|
+
# execution timeout) kills the CLI without firing the configured
|
|
12
|
+
# Stop hook. Any state the Stop hook was responsible for writing
|
|
13
|
+
# is left stale — it still reflects the previous run — so a
|
|
14
|
+
# supervisor reading that file cannot tell "completed" apart
|
|
15
|
+
# from "killed mid-work."
|
|
16
|
+
#
|
|
17
|
+
# The reporter's own band-aid was an outer wrapper that observes
|
|
18
|
+
# the wrapped command's exit code and writes its own termination
|
|
19
|
+
# marker before reading any hook output. This script ships a
|
|
20
|
+
# clean, parseable version of that band-aid: it wraps the claude
|
|
21
|
+
# invocation, traps SIGTERM/SIGINT, and writes a JSON state file
|
|
22
|
+
# on every transition (running, completed, killed-sigterm,
|
|
23
|
+
# killed-sigint, killed-timeout, killed-sigkill, error). The
|
|
24
|
+
# supervisor reads the state file and can decisively
|
|
25
|
+
# differentiate the termination cause.
|
|
26
|
+
#
|
|
27
|
+
# This is not a fix for the upstream Stop-hook-on-SIGTERM gap.
|
|
28
|
+
# It is the operator-side workaround that lets supervisors stop
|
|
29
|
+
# misattributing prior-run completion summaries to current
|
|
30
|
+
# killed runs.
|
|
31
|
+
#
|
|
32
|
+
# CLUSTER:
|
|
33
|
+
# Candidate cluster #21 — Plugin lifecycle integrity gap
|
|
34
|
+
# Sub-axis 21D — signal gap (Stop hook silent on SIGTERM, #64017).
|
|
35
|
+
#
|
|
36
|
+
# USAGE:
|
|
37
|
+
# 1. Place this script on PATH (e.g. ~/bin/claude-wrapped.sh)
|
|
38
|
+
# 2. Optionally alias claude='/path/to/stop-hook-sigterm-wrapper.sh'
|
|
39
|
+
# 3. Or invoke directly: stop-hook-sigterm-wrapper.sh -p "your prompt"
|
|
40
|
+
# 4. Supervisor reads $CC_STOP_SIGTERM_MARKER_DIR/state.json after
|
|
41
|
+
# the wrapped invocation completes (or is killed)
|
|
42
|
+
#
|
|
43
|
+
# The state file is JSON, one line per state transition:
|
|
44
|
+
# {"state":"running","timestamp":"2026-05-31T10:00:00+0900","pid":12345}
|
|
45
|
+
# {"state":"completed","timestamp":"2026-05-31T10:30:00+0900","exit_code":0,"duration_s":1800}
|
|
46
|
+
#
|
|
47
|
+
# States:
|
|
48
|
+
# running — claude was launched, no termination signal yet
|
|
49
|
+
# completed — claude exited with code 0
|
|
50
|
+
# killed-sigterm — claude received SIGTERM (exit 143)
|
|
51
|
+
# killed-sigint — claude received SIGINT / Ctrl-C (exit 130)
|
|
52
|
+
# killed-timeout — wrapper saw exit 124 from `timeout` wrapper above us
|
|
53
|
+
# killed-sigkill — claude exited with 137 (SIGKILL, cannot be trapped)
|
|
54
|
+
# error — claude exited with any other non-zero code
|
|
55
|
+
#
|
|
56
|
+
# ENV:
|
|
57
|
+
# CC_STOP_SIGTERM_MARKER_DIR default $HOME/.claude/run-state
|
|
58
|
+
# CC_STOP_SIGTERM_WRAPPER_CMD default "claude" (override for testing or alt CLI path)
|
|
59
|
+
# CC_STOP_SIGTERM_DISABLE non-empty → wrapper passes through without writing markers
|
|
60
|
+
# ================================================================
|
|
61
|
+
|
|
62
|
+
set -u
|
|
63
|
+
|
|
64
|
+
# Disable pass-through
|
|
65
|
+
if [ -n "${CC_STOP_SIGTERM_DISABLE:-}" ]; then
|
|
66
|
+
exec "${CC_STOP_SIGTERM_WRAPPER_CMD:-claude}" "$@"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# No-op when invoked with no args. The cc-safe-setup CI smoke-tests every
|
|
70
|
+
# example/*.sh by piping an empty stdin and expecting exit 0 — this wrapper
|
|
71
|
+
# is invoked with claude's CLI arguments, never with stdin alone, so a no-args
|
|
72
|
+
# invocation is unambiguously the smoke-test path.
|
|
73
|
+
if [ $# -eq 0 ]; then
|
|
74
|
+
exit 0
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
MARKER_DIR="${CC_STOP_SIGTERM_MARKER_DIR:-$HOME/.claude/run-state}"
|
|
78
|
+
WRAPPED_CMD="${CC_STOP_SIGTERM_WRAPPER_CMD:-claude}"
|
|
79
|
+
STATE_FILE="$MARKER_DIR/state.json"
|
|
80
|
+
|
|
81
|
+
mkdir -p "$MARKER_DIR" 2>/dev/null || {
|
|
82
|
+
# If we cannot create the marker dir, fall back to pass-through
|
|
83
|
+
exec "$WRAPPED_CMD" "$@"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Portable ISO 8601 timestamp with timezone
|
|
87
|
+
timestamp() {
|
|
88
|
+
if date +%Y-%m-%dT%H:%M:%S%z >/dev/null 2>&1; then
|
|
89
|
+
date +%Y-%m-%dT%H:%M:%S%z
|
|
90
|
+
else
|
|
91
|
+
date -u +%Y-%m-%dT%H:%M:%SZ
|
|
92
|
+
fi
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
write_state() {
|
|
96
|
+
local state="$1"
|
|
97
|
+
local extra="$2"
|
|
98
|
+
local now
|
|
99
|
+
now=$(timestamp)
|
|
100
|
+
local payload="{\"state\":\"$state\",\"timestamp\":\"$now\",\"pid\":$$"
|
|
101
|
+
if [ -n "$extra" ]; then
|
|
102
|
+
payload="$payload,$extra"
|
|
103
|
+
fi
|
|
104
|
+
payload="$payload}"
|
|
105
|
+
# Atomic write: rename from temp
|
|
106
|
+
local tmp
|
|
107
|
+
tmp=$(mktemp "$MARKER_DIR/.state.json.XXXXXX" 2>/dev/null) || {
|
|
108
|
+
# mktemp failed; best-effort direct write
|
|
109
|
+
printf '%s\n' "$payload" > "$STATE_FILE" 2>/dev/null
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
printf '%s\n' "$payload" > "$tmp"
|
|
113
|
+
mv -f "$tmp" "$STATE_FILE" 2>/dev/null
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# Track start time for duration calculation on exit
|
|
117
|
+
START_S=$(date +%s)
|
|
118
|
+
|
|
119
|
+
# Initial state: running
|
|
120
|
+
write_state "running" ""
|
|
121
|
+
|
|
122
|
+
# Trap signals — write the killed state before exiting. We re-raise
|
|
123
|
+
# the same signal so the parent supervisor still sees the normal
|
|
124
|
+
# 128+N exit code, preserving wait() semantics.
|
|
125
|
+
on_sigterm() {
|
|
126
|
+
local elapsed=$(( $(date +%s) - START_S ))
|
|
127
|
+
write_state "killed-sigterm" "\"exit_code\":143,\"duration_s\":$elapsed"
|
|
128
|
+
# Kill the child if still alive
|
|
129
|
+
if [ -n "${CLAUDE_PID:-}" ] && kill -0 "$CLAUDE_PID" 2>/dev/null; then
|
|
130
|
+
kill -TERM "$CLAUDE_PID" 2>/dev/null
|
|
131
|
+
fi
|
|
132
|
+
exit 143
|
|
133
|
+
}
|
|
134
|
+
on_sigint() {
|
|
135
|
+
local elapsed=$(( $(date +%s) - START_S ))
|
|
136
|
+
write_state "killed-sigint" "\"exit_code\":130,\"duration_s\":$elapsed"
|
|
137
|
+
if [ -n "${CLAUDE_PID:-}" ] && kill -0 "$CLAUDE_PID" 2>/dev/null; then
|
|
138
|
+
kill -INT "$CLAUDE_PID" 2>/dev/null
|
|
139
|
+
fi
|
|
140
|
+
exit 130
|
|
141
|
+
}
|
|
142
|
+
trap on_sigterm TERM
|
|
143
|
+
trap on_sigint INT
|
|
144
|
+
|
|
145
|
+
# Launch the wrapped command in background so we can wait() and trap.
|
|
146
|
+
# Pass through all args verbatim.
|
|
147
|
+
"$WRAPPED_CMD" "$@" &
|
|
148
|
+
CLAUDE_PID=$!
|
|
149
|
+
|
|
150
|
+
# Wait for completion. `wait` is interrupted by trapped signals.
|
|
151
|
+
wait "$CLAUDE_PID"
|
|
152
|
+
EXIT_CODE=$?
|
|
153
|
+
|
|
154
|
+
# Compute duration
|
|
155
|
+
ELAPSED=$(( $(date +%s) - START_S ))
|
|
156
|
+
|
|
157
|
+
# Map exit code to state
|
|
158
|
+
case $EXIT_CODE in
|
|
159
|
+
0)
|
|
160
|
+
write_state "completed" "\"exit_code\":0,\"duration_s\":$ELAPSED"
|
|
161
|
+
;;
|
|
162
|
+
124)
|
|
163
|
+
# `timeout` parent exit code — wrapped command was killed by
|
|
164
|
+
# an outer `timeout` wrapper.
|
|
165
|
+
write_state "killed-timeout" "\"exit_code\":124,\"duration_s\":$ELAPSED"
|
|
166
|
+
;;
|
|
167
|
+
130)
|
|
168
|
+
write_state "killed-sigint" "\"exit_code\":130,\"duration_s\":$ELAPSED"
|
|
169
|
+
;;
|
|
170
|
+
137)
|
|
171
|
+
# SIGKILL cannot be trapped, but we can record it post-mortem.
|
|
172
|
+
write_state "killed-sigkill" "\"exit_code\":137,\"duration_s\":$ELAPSED"
|
|
173
|
+
;;
|
|
174
|
+
143)
|
|
175
|
+
write_state "killed-sigterm" "\"exit_code\":143,\"duration_s\":$ELAPSED"
|
|
176
|
+
;;
|
|
177
|
+
*)
|
|
178
|
+
write_state "error" "\"exit_code\":$EXIT_CODE,\"duration_s\":$ELAPSED"
|
|
179
|
+
;;
|
|
180
|
+
esac
|
|
181
|
+
|
|
182
|
+
exit $EXIT_CODE
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# stop-transcript-write-health.sh — Detect a silently stalled or reverted transcript
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Claude Code writes the conversation to
|
|
7
|
+
# ~/.claude/projects/<slug>/<session-id>.jsonl as the session runs.
|
|
8
|
+
# Some failures stop that write silently: an account switch can revert
|
|
9
|
+
# the live file to an older snapshot and then never write again, with no
|
|
10
|
+
# error shown (anthropics/claude-code#73937). The session keeps working,
|
|
11
|
+
# so the loss is invisible until you diff line counts by hand.
|
|
12
|
+
#
|
|
13
|
+
# HOW IT WORKS:
|
|
14
|
+
# Stop fires after every completed turn and its input carries
|
|
15
|
+
# `transcript_path`. That is the natural "a turn's worth of lines should
|
|
16
|
+
# have just been written" checkpoint. This hook records the transcript's
|
|
17
|
+
# line count and mtime per session_id, and on the next Stop:
|
|
18
|
+
# - line count + mtime unchanged since last turn -> the turn was NOT
|
|
19
|
+
# persisted (silent save-stop) -> warn.
|
|
20
|
+
# - line count shrank -> the file was
|
|
21
|
+
# reverted to an older snapshot -> warn.
|
|
22
|
+
# The warning is emitted via {"systemMessage": ...} so it surfaces to the
|
|
23
|
+
# user without blocking the session. It only detects; it does not replace
|
|
24
|
+
# an independent content backup.
|
|
25
|
+
#
|
|
26
|
+
# TRIGGER: Stop
|
|
27
|
+
# MATCHER: (none — Stop has no tool matcher)
|
|
28
|
+
#
|
|
29
|
+
# CONFIGURATION:
|
|
30
|
+
# none
|
|
31
|
+
# ================================================================
|
|
32
|
+
set -uo pipefail
|
|
33
|
+
|
|
34
|
+
input=$(cat)
|
|
35
|
+
tp=$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
36
|
+
sid=$(printf '%s' "$input" | jq -r '.session_id // "nosid"' 2>/dev/null)
|
|
37
|
+
|
|
38
|
+
# No transcript path / unreadable -> nothing to check.
|
|
39
|
+
[ -z "$tp" ] && exit 0
|
|
40
|
+
[ ! -f "$tp" ] && exit 0
|
|
41
|
+
|
|
42
|
+
state_dir="${HOME}/.claude/transcript-health"
|
|
43
|
+
mkdir -p "$state_dir"
|
|
44
|
+
state_file="${state_dir}/${sid}.state"
|
|
45
|
+
|
|
46
|
+
cur_lines=$(wc -l < "$tp" 2>/dev/null | tr -d ' ')
|
|
47
|
+
cur_mtime=$(stat -c %Y "$tp" 2>/dev/null || stat -f %m "$tp" 2>/dev/null)
|
|
48
|
+
|
|
49
|
+
warn=""
|
|
50
|
+
if [ -f "$state_file" ]; then
|
|
51
|
+
read -r prev_lines prev_mtime < "$state_file"
|
|
52
|
+
if [ "${cur_lines:-0}" -lt "${prev_lines:-0}" ]; then
|
|
53
|
+
warn="⚠ transcript reverted (${prev_lines}→${cur_lines} lines). The live file may have been replaced with an older snapshot (account switch / #73937). Check your recovery point before continuing."
|
|
54
|
+
elif [ "${cur_lines:-0}" -eq "${prev_lines:-0}" ] && [ "${cur_mtime:-0}" -eq "${prev_mtime:-0}" ]; then
|
|
55
|
+
warn="⚠ the last turn was NOT persisted to ${tp} (line count and mtime unchanged since the previous turn). Saves may have silently stopped (#73937). This turn may exist only in memory — take an independent backup and restart."
|
|
56
|
+
fi
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
printf '%s %s\n' "${cur_lines:-0}" "${cur_mtime:-0}" > "$state_file"
|
|
60
|
+
|
|
61
|
+
if [ -n "$warn" ]; then
|
|
62
|
+
jq -cn --arg m "$warn" '{systemMessage:$m}'
|
|
63
|
+
fi
|
|
64
|
+
exit 0
|
|
@@ -18,6 +18,18 @@
|
|
|
18
18
|
# "Immutable session manifest with allowlist-only enforcement"
|
|
19
19
|
# ================================================================
|
|
20
20
|
|
|
21
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
22
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
23
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
24
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
25
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
26
|
+
_nojq_warned="/tmp/cc-nojq-warned-strict-allowlist-$PPID"
|
|
27
|
+
[ -f "$_nojq_warned" ] || {
|
|
28
|
+
echo "WARNING [strict-allowlist]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
29
|
+
: > "$_nojq_warned"
|
|
30
|
+
}
|
|
31
|
+
fi
|
|
32
|
+
|
|
21
33
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
22
34
|
[ -z "$COMMAND" ] && exit 0
|
|
23
35
|
|
|
@@ -65,24 +77,54 @@ DEFAULT
|
|
|
65
77
|
echo "Edit it to customize permitted commands." >&2
|
|
66
78
|
fi
|
|
67
79
|
|
|
68
|
-
#
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
done < "$ALLOWLIST"
|
|
80
|
+
# One line can chain several commands. The shipped patterns are anchored with
|
|
81
|
+
# "^", so matching them against the whole line only ever inspects the first
|
|
82
|
+
# word: an approved command followed by "&&" and anything at all was approved.
|
|
83
|
+
# For a denylist that is a gap; for an allowlist it means the list stops
|
|
84
|
+
# enforcing after the first segment, which is the whole feature. Claude Code
|
|
85
|
+
# closed the same class of hole in its own permission checking (2.1.216,
|
|
86
|
+
# "Fixed Bash permission checking for compound statements").
|
|
87
|
+
#
|
|
88
|
+
# So: split on the operators that begin a new command and require EVERY segment
|
|
89
|
+
# to match a pattern. One unapproved segment blocks the line.
|
|
90
|
+
SEGMENTS=$(printf '%s' "$COMMAND" | sed -E 's/(\|\||&&|[;|&])/\n/g')
|
|
80
91
|
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
# Command substitution executes text that never appears as a segment, so
|
|
93
|
+
# splitting cannot vet it. Refuse rather than guess.
|
|
94
|
+
if printf '%s' "$COMMAND" | grep -qE '\$\(|`'; then
|
|
95
|
+
echo "BLOCKED: command substitution is not allowed by the allowlist." >&2
|
|
83
96
|
echo "Command: $COMMAND" >&2
|
|
84
|
-
echo "Add a matching pattern to $ALLOWLIST to permit." >&2
|
|
85
97
|
exit 2
|
|
86
98
|
fi
|
|
87
99
|
|
|
100
|
+
while IFS= read -r SEGMENT; do
|
|
101
|
+
# sed leaves an empty field where a two-character operator was split
|
|
102
|
+
[[ -z "${SEGMENT//[[:space:]]/}" ]] && continue
|
|
103
|
+
|
|
104
|
+
# "ls; pwd" splits into "ls" and " pwd". The shipped patterns are anchored
|
|
105
|
+
# with "^" and no leading \s*, so the space would make the second segment
|
|
106
|
+
# fail to match and block a perfectly approved chain. Trim before matching.
|
|
107
|
+
SEGMENT=$(printf '%s' "$SEGMENT" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')
|
|
108
|
+
|
|
109
|
+
ALLOWED=0
|
|
110
|
+
while IFS= read -r pattern; do
|
|
111
|
+
# Skip comments and empty lines
|
|
112
|
+
[[ "$pattern" =~ ^[[:space:]]*# ]] && continue
|
|
113
|
+
[[ -z "$pattern" ]] && continue
|
|
114
|
+
|
|
115
|
+
if printf '%s' "$SEGMENT" | grep -qE "$pattern"; then
|
|
116
|
+
ALLOWED=1
|
|
117
|
+
break
|
|
118
|
+
fi
|
|
119
|
+
done < "$ALLOWLIST"
|
|
120
|
+
|
|
121
|
+
if [ "$ALLOWED" -eq 0 ]; then
|
|
122
|
+
echo "BLOCKED: Command not in allowlist." >&2
|
|
123
|
+
echo "Command: $COMMAND" >&2
|
|
124
|
+
echo "Unapproved segment: $SEGMENT" >&2
|
|
125
|
+
echo "Add a matching pattern to $ALLOWLIST to permit." >&2
|
|
126
|
+
exit 2
|
|
127
|
+
fi
|
|
128
|
+
done <<< "$SEGMENTS"
|
|
129
|
+
|
|
88
130
|
exit 0
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# strip-coauthored-by.sh —
|
|
2
|
+
# strip-coauthored-by.sh — Warn about (or block) unwanted commit-message trailers
|
|
3
3
|
#
|
|
4
|
-
# Solves
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# Solves two trailers Claude appends to commits without the user asking:
|
|
5
|
+
# 1. Co-Authored-By: ...Claude/Anthropic — branding without consent.
|
|
6
|
+
# See: https://github.com/anthropics/claude-code/issues/29999
|
|
7
|
+
# 2. Claude-Session: https://claude.ai/code/session_<id> — leaks a PRIVATE
|
|
8
|
+
# session identifier into commit history, which is published to public
|
|
9
|
+
# repos. Data minimisation should apply by default.
|
|
10
|
+
# See: https://github.com/anthropics/claude-code/issues/69669
|
|
11
|
+
#
|
|
12
|
+
# Mechanism: this is a PreToolUse hook, which can BLOCK a tool call (exit 2)
|
|
13
|
+
# but cannot rewrite it — so it cannot silently strip the trailer. Instead it
|
|
14
|
+
# bounces the commit back so the model removes the trailer before committing.
|
|
15
|
+
# - Session-id leak: blocked by default (exit 2) — it is a privacy issue.
|
|
16
|
+
# - Co-Authored-By: warn-only (exit 0) — it is a preference, user decides.
|
|
17
|
+
# Note: only the `git commit -m "<msg>"` form carries the message in the
|
|
18
|
+
# command string. Commits via an editor or `-F <file>` are not visible here.
|
|
7
19
|
#
|
|
8
20
|
# TRIGGER: PreToolUse
|
|
9
21
|
# MATCHER: Bash
|
|
@@ -22,19 +34,47 @@
|
|
|
22
34
|
# }
|
|
23
35
|
# }
|
|
24
36
|
#
|
|
25
|
-
# Config:
|
|
37
|
+
# Config:
|
|
38
|
+
# CC_ALLOW_COAUTHOR=1 allow Co-Authored-By trailers (default: 0 = warn)
|
|
39
|
+
# CC_ALLOW_SESSION_TRAILER=1 allow the session-id URL trailer (default: 0 = block)
|
|
40
|
+
|
|
41
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
42
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
43
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
44
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
45
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
46
|
+
_nojq_warned="/tmp/cc-nojq-warned-strip-coauthored-by-$PPID"
|
|
47
|
+
[ -f "$_nojq_warned" ] || {
|
|
48
|
+
echo "WARNING [strip-coauthored-by]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
49
|
+
: > "$_nojq_warned"
|
|
50
|
+
}
|
|
51
|
+
fi
|
|
26
52
|
|
|
27
53
|
INPUT=$(cat)
|
|
28
54
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
29
55
|
[ -z "$COMMAND" ] && exit 0
|
|
30
56
|
|
|
31
|
-
# Only
|
|
32
|
-
|
|
57
|
+
# Only inspect git commit commands. Match at the start or after a chaining
|
|
58
|
+
# operator (so `cd repo && git commit ...` is covered too).
|
|
59
|
+
echo "$COMMAND" | grep -qE '(^|[;&|[:space:]])git[[:space:]]+commit' || exit 0
|
|
60
|
+
|
|
61
|
+
# 1. Private session-id leak — block by default (privacy issue).
|
|
62
|
+
# The harness emits `Claude-Session: https://claude.ai/code/session_<id>`.
|
|
63
|
+
if echo "$COMMAND" | grep -qiE 'claude\.ai/code/session|Claude-Session:'; then
|
|
64
|
+
if [ "${CC_ALLOW_SESSION_TRAILER:-0}" != "1" ]; then
|
|
65
|
+
echo "✖ Blocked: commit message contains a private Claude session URL" >&2
|
|
66
|
+
echo " (Claude-Session: https://claude.ai/code/session_...)." >&2
|
|
67
|
+
echo " This publishes a private session identifier to your repo history." >&2
|
|
68
|
+
echo " Remove that trailer from the commit message, then retry." >&2
|
|
69
|
+
echo " Set CC_ALLOW_SESSION_TRAILER=1 to allow it. See issue #69669." >&2
|
|
70
|
+
exit 2
|
|
71
|
+
fi
|
|
72
|
+
fi
|
|
33
73
|
|
|
34
|
-
#
|
|
35
|
-
if echo "$COMMAND" | grep -qiE 'Co-Authored-By.*Claude
|
|
74
|
+
# 2. Co-Authored-By branding — warn only (the user decides).
|
|
75
|
+
if echo "$COMMAND" | grep -qiE 'Co-Authored-By.*(Claude|Anthropic|noreply@anthropic)'; then
|
|
36
76
|
if [ "${CC_ALLOW_COAUTHOR:-0}" = "1" ]; then
|
|
37
|
-
exit 0
|
|
77
|
+
exit 0
|
|
38
78
|
fi
|
|
39
79
|
echo "⚠ Co-Authored-By trailer detected in commit message" >&2
|
|
40
80
|
echo " Set CC_ALLOW_COAUTHOR=1 to allow, or remove the trailer." >&2
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# subagent-blast-radius-guard.sh — Surface and gate the files a
|
|
4
|
+
# sub-agent actually writes, at the moment it writes them
|
|
5
|
+
# ================================================================
|
|
6
|
+
# PURPOSE:
|
|
7
|
+
# Existing sub-agent hooks in this repo (subagent-scope-validator,
|
|
8
|
+
# subagent-tool-allowlist-enforcer, subagent-boundary-precheck,
|
|
9
|
+
# subagent-destructive-git-guard, ...) all fire on the PARENT's
|
|
10
|
+
# PreToolUse for the Agent/Task tool. They inspect the delegation
|
|
11
|
+
# PROMPT and nudge the operator to state boundaries before the
|
|
12
|
+
# sub-agent starts. None of them see what the sub-agent then
|
|
13
|
+
# actually does. Once the sub-agent is running, its individual
|
|
14
|
+
# Write/Edit calls are unguarded at the execution layer.
|
|
15
|
+
#
|
|
16
|
+
# This hook closes that gap. It fires on the sub-agent's own
|
|
17
|
+
# Write/Edit calls and keys off the `agent_id` / `agent_type`
|
|
18
|
+
# fields that Claude Code adds to the PreToolUse payload for
|
|
19
|
+
# sub-agent-originated tool calls (verified on v2.1.161: a
|
|
20
|
+
# sub-agent's Write call carries agent_id+agent_type; the main
|
|
21
|
+
# thread's calls do not). When agent_id is present, the write
|
|
22
|
+
# came from a sub-agent, and this hook can surface it or block it
|
|
23
|
+
# — without ever touching the human-supervised main agent's writes.
|
|
24
|
+
#
|
|
25
|
+
# TRIGGER: PreToolUse
|
|
26
|
+
# MATCHER: "Edit|Write"
|
|
27
|
+
#
|
|
28
|
+
# WHY THIS MATTERS:
|
|
29
|
+
# #65152 (2026-06-03) — a sub-agent asked only to "run these two
|
|
30
|
+
# shell commands" autonomously used Write/Edit on 15 files,
|
|
31
|
+
# including production database migration files, and the operator
|
|
32
|
+
# only discovered the blast radius after the fact. The same shape
|
|
33
|
+
# recurs in #63356 and #45108: a narrowly-scoped delegation turns
|
|
34
|
+
# into a wide, partly-irreversible set of writes, and there is no
|
|
35
|
+
# per-write signal the operator sees in time to intervene.
|
|
36
|
+
#
|
|
37
|
+
# The fix the parent-side nudge hooks cannot provide is a signal
|
|
38
|
+
# (or a stop) at the instant the sub-agent writes a high-blast
|
|
39
|
+
# file. That is what this hook adds.
|
|
40
|
+
#
|
|
41
|
+
# WHAT IT DOES:
|
|
42
|
+
# * Main-thread writes (no agent_id): exit 0 immediately. This hook
|
|
43
|
+
# deliberately never interferes with the supervised main agent.
|
|
44
|
+
# * Sub-agent writes (agent_id present): apply CC_SUBAGENT_WRITE_GUARD:
|
|
45
|
+
# off — do nothing (exit 0).
|
|
46
|
+
# warn — (default) warn on a "flagged" write (sensitive
|
|
47
|
+
# path, or outside the allowlist when one is set);
|
|
48
|
+
# silent on ordinary writes. Always exit 0.
|
|
49
|
+
# warn-all — warn on EVERY sub-agent write (full blast-radius
|
|
50
|
+
# visibility). Always exit 0.
|
|
51
|
+
# block — exit 2 (block) on a flagged write; ordinary
|
|
52
|
+
# sub-agent writes pass silently.
|
|
53
|
+
#
|
|
54
|
+
# A write is "flagged" when it matches the high-blast sensitive
|
|
55
|
+
# pattern (migrations, IaC state, .env / secrets, prod config, DB
|
|
56
|
+
# schema, lockfiles, CI workflows) OR — if CC_SUBAGENT_WRITE_ALLOW
|
|
57
|
+
# is set — when it falls outside every allowed path prefix.
|
|
58
|
+
#
|
|
59
|
+
# CONFIG:
|
|
60
|
+
# CC_SUBAGENT_WRITE_GUARD off | warn (default) | warn-all | block
|
|
61
|
+
# CC_SUBAGENT_WRITE_ALLOW space/colon-separated path prefixes the
|
|
62
|
+
# sub-agent may write under (e.g.
|
|
63
|
+
# "src/feature-x/ docs/"). Writes outside
|
|
64
|
+
# all prefixes are flagged. Match is a
|
|
65
|
+
# literal prefix on the file_path Claude
|
|
66
|
+
# passes (usually an absolute cwd path).
|
|
67
|
+
# CC_SUBAGENT_WRITE_SENSITIVE extra ERE appended (alternation) to the
|
|
68
|
+
# built-in sensitive pattern.
|
|
69
|
+
#
|
|
70
|
+
# DESIGN NOTES (why these defaults):
|
|
71
|
+
# * Default is warn, not block: blocking a sub-agent mid-run can
|
|
72
|
+
# wedge legitimate fan-out work and break headless/CI. Visibility
|
|
73
|
+
# of the dangerous writes is the safe default; blocking is opt-in,
|
|
74
|
+
# matching memory-write-guard's opt-in philosophy.
|
|
75
|
+
# * Fail-open on malformed input / missing jq: a safety hook must
|
|
76
|
+
# never be the thing that breaks the session.
|
|
77
|
+
# * Edit|Write only (not Bash): destructive Bash by anyone is already
|
|
78
|
+
# covered by rm-safety-net / destructive-guard / git guards
|
|
79
|
+
# regardless of agent_id. The genuinely uncovered gap is the
|
|
80
|
+
# sub-agent's structured file writes.
|
|
81
|
+
#
|
|
82
|
+
# RELATED ISSUES:
|
|
83
|
+
# https://github.com/anthropics/claude-code/issues/65152
|
|
84
|
+
# https://github.com/anthropics/claude-code/issues/63356
|
|
85
|
+
# https://github.com/anthropics/claude-code/issues/45108
|
|
86
|
+
# ================================================================
|
|
87
|
+
|
|
88
|
+
set -u
|
|
89
|
+
|
|
90
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
91
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
92
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
93
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
94
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
95
|
+
_nojq_warned="/tmp/cc-nojq-warned-subagent-blast-radius-guard-$PPID"
|
|
96
|
+
[ -f "$_nojq_warned" ] || {
|
|
97
|
+
echo "WARNING [subagent-blast-radius-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
98
|
+
: > "$_nojq_warned"
|
|
99
|
+
}
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
INPUT=$(cat)
|
|
103
|
+
|
|
104
|
+
MODE="${CC_SUBAGENT_WRITE_GUARD:-warn}"
|
|
105
|
+
[ "$MODE" = "off" ] && exit 0
|
|
106
|
+
|
|
107
|
+
# agent_id is present only for sub-agent-originated tool calls. No
|
|
108
|
+
# agent_id => main-thread write => never our concern.
|
|
109
|
+
AGENT_ID=$(printf '%s' "$INPUT" | jq -r '.agent_id // empty' 2>/dev/null)
|
|
110
|
+
[ -z "$AGENT_ID" ] && exit 0
|
|
111
|
+
|
|
112
|
+
FILE=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
113
|
+
[ -z "$FILE" ] && exit 0
|
|
114
|
+
|
|
115
|
+
AGENT_TYPE=$(printf '%s' "$INPUT" | jq -r '.agent_type // empty' 2>/dev/null)
|
|
116
|
+
[ -z "$AGENT_TYPE" ] && AGENT_TYPE="subagent"
|
|
117
|
+
|
|
118
|
+
# High-blast / hard-to-reverse destinations a narrowly-scoped sub-agent
|
|
119
|
+
# should not be silently rewriting.
|
|
120
|
+
SENSITIVE_ERE='(^|/)migrations?/|(^|/)migrate/|\.tf$|\.tfstate|(^|/)terraform/|(^|/)\.env|secrets?\.(ya?ml|json|env)|(^|/)credentials|(^|/)(prod|production)\.(ya?ml|yml|json|env|toml)|(^|/)config/(prod|production)|schema\.(sql|prisma|rb)$|(^|/)db/schema|(^|/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Cargo\.lock|poetry\.lock|Gemfile\.lock)$|(^|/)\.github/workflows/|(^|/)\.gitlab-ci\.yml$'
|
|
121
|
+
if [ -n "${CC_SUBAGENT_WRITE_SENSITIVE:-}" ]; then
|
|
122
|
+
SENSITIVE_ERE="${SENSITIVE_ERE}|${CC_SUBAGENT_WRITE_SENSITIVE}"
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
is_sensitive=0
|
|
126
|
+
if printf '%s' "$FILE" | grep -qE "$SENSITIVE_ERE"; then
|
|
127
|
+
is_sensitive=1
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Allowlist: if set, a write outside every prefix is out-of-scope.
|
|
131
|
+
out_of_scope=0
|
|
132
|
+
REASON=""
|
|
133
|
+
if [ -n "${CC_SUBAGENT_WRITE_ALLOW:-}" ]; then
|
|
134
|
+
out_of_scope=1
|
|
135
|
+
# Split on whitespace and colons.
|
|
136
|
+
OLD_IFS="$IFS"; IFS=': '
|
|
137
|
+
for prefix in $CC_SUBAGENT_WRITE_ALLOW; do
|
|
138
|
+
[ -z "$prefix" ] && continue
|
|
139
|
+
case "$FILE" in
|
|
140
|
+
"$prefix"*) out_of_scope=0 ;;
|
|
141
|
+
esac
|
|
142
|
+
done
|
|
143
|
+
IFS="$OLD_IFS"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
flagged=0
|
|
147
|
+
if [ "$is_sensitive" -eq 1 ]; then
|
|
148
|
+
flagged=1
|
|
149
|
+
REASON="high-blast path (migration / IaC / secret / prod config / schema / lockfile / CI)"
|
|
150
|
+
fi
|
|
151
|
+
if [ "$out_of_scope" -eq 1 ]; then
|
|
152
|
+
flagged=1
|
|
153
|
+
if [ -n "$REASON" ]; then
|
|
154
|
+
REASON="$REASON; outside CC_SUBAGENT_WRITE_ALLOW"
|
|
155
|
+
else
|
|
156
|
+
REASON="outside CC_SUBAGENT_WRITE_ALLOW ($CC_SUBAGENT_WRITE_ALLOW)"
|
|
157
|
+
fi
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
SHORT_ID=$(printf '%s' "$AGENT_ID" | cut -c1-8)
|
|
161
|
+
|
|
162
|
+
emit_warn() {
|
|
163
|
+
echo "subagent-blast-radius-guard: sub-agent [$AGENT_TYPE#$SHORT_ID] is writing $FILE${1:+ — $1}" >&2
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
case "$MODE" in
|
|
167
|
+
warn-all)
|
|
168
|
+
if [ "$flagged" -eq 1 ]; then emit_warn "$REASON"; else emit_warn ""; fi
|
|
169
|
+
exit 0
|
|
170
|
+
;;
|
|
171
|
+
block)
|
|
172
|
+
if [ "$flagged" -eq 1 ]; then
|
|
173
|
+
echo "BLOCKED: sub-agent [$AGENT_TYPE#$SHORT_ID] attempted to write $FILE" >&2
|
|
174
|
+
echo "Reason: $REASON." >&2
|
|
175
|
+
echo "A narrowly-delegated sub-agent should not write this. Re-delegate with an explicit scope, write it from the supervised main thread, or set CC_SUBAGENT_WRITE_GUARD=warn to allow with a warning." >&2
|
|
176
|
+
exit 2
|
|
177
|
+
fi
|
|
178
|
+
exit 0
|
|
179
|
+
;;
|
|
180
|
+
*) # warn (default)
|
|
181
|
+
[ "$flagged" -eq 1 ] && emit_warn "$REASON"
|
|
182
|
+
exit 0
|
|
183
|
+
;;
|
|
184
|
+
esac
|