cc-safe-setup 29.8.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-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 +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-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,246 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for forbidden-response-phrase-detector.sh
|
|
3
|
+
# Run: bash tests/test-forbidden-response-phrase-detector.sh
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
|
|
6
|
+
HOOK="$(dirname "$0")/../examples/forbidden-response-phrase-detector.sh"
|
|
7
|
+
PASS=0 FAIL=0
|
|
8
|
+
|
|
9
|
+
# Helper: build a temp transcript with one assistant response, run the hook with
|
|
10
|
+
# an explicit CLAUDE.md path, assert the exit code.
|
|
11
|
+
run_test() {
|
|
12
|
+
local desc="$1" expected_exit="$2" response="$3" claudemd_content="$4" envvars="${5:-}"
|
|
13
|
+
local tmpdir transcript claudemd actual_exit input
|
|
14
|
+
tmpdir=$(mktemp -d)
|
|
15
|
+
transcript="${tmpdir}/transcript.jsonl"
|
|
16
|
+
claudemd="${tmpdir}/CLAUDE.md"
|
|
17
|
+
printf '%s' "$claudemd_content" > "$claudemd"
|
|
18
|
+
|
|
19
|
+
jq -nc --arg text "$response" '{
|
|
20
|
+
"role": "assistant",
|
|
21
|
+
"message": {"role": "assistant", "content": [{"type": "text", "text": $text}]}
|
|
22
|
+
}' > "$transcript"
|
|
23
|
+
|
|
24
|
+
input=$(jq -nc --arg t "$transcript" '{"transcript_path": $t}')
|
|
25
|
+
|
|
26
|
+
if [ -n "$envvars" ]; then
|
|
27
|
+
actual_exit=$(echo "$input" | env CC_CLAUDEMD_PATH="$claudemd" $envvars bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
|
|
28
|
+
else
|
|
29
|
+
echo "$input" | CC_CLAUDEMD_PATH="$claudemd" bash "$HOOK" >/dev/null 2>/dev/null
|
|
30
|
+
actual_exit=$?
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
rm -rf "$tmpdir"
|
|
34
|
+
|
|
35
|
+
if [ "$actual_exit" -eq "$expected_exit" ]; then
|
|
36
|
+
echo " PASS: $desc"
|
|
37
|
+
PASS=$((PASS + 1))
|
|
38
|
+
else
|
|
39
|
+
echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
|
|
40
|
+
FAIL=$((FAIL + 1))
|
|
41
|
+
fi
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
expect_stderr_contains() {
|
|
45
|
+
local desc="$1" response="$2" claudemd_content="$3" expect="$4" envvars="${5:-}"
|
|
46
|
+
local tmpdir transcript claudemd stderr_out input
|
|
47
|
+
tmpdir=$(mktemp -d)
|
|
48
|
+
transcript="${tmpdir}/transcript.jsonl"
|
|
49
|
+
claudemd="${tmpdir}/CLAUDE.md"
|
|
50
|
+
printf '%s' "$claudemd_content" > "$claudemd"
|
|
51
|
+
|
|
52
|
+
jq -nc --arg text "$response" '{
|
|
53
|
+
"role": "assistant",
|
|
54
|
+
"message": {"role": "assistant", "content": [{"type": "text", "text": $text}]}
|
|
55
|
+
}' > "$transcript"
|
|
56
|
+
|
|
57
|
+
input=$(jq -nc --arg t "$transcript" '{"transcript_path": $t}')
|
|
58
|
+
|
|
59
|
+
if [ -n "$envvars" ]; then
|
|
60
|
+
stderr_out=$(echo "$input" | env CC_CLAUDEMD_PATH="$claudemd" $envvars bash "$HOOK" 2>&1 >/dev/null)
|
|
61
|
+
else
|
|
62
|
+
stderr_out=$(echo "$input" | CC_CLAUDEMD_PATH="$claudemd" bash "$HOOK" 2>&1 >/dev/null)
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
rm -rf "$tmpdir"
|
|
66
|
+
|
|
67
|
+
if echo "$stderr_out" | grep -q -- "$expect"; then
|
|
68
|
+
echo " PASS: $desc"
|
|
69
|
+
PASS=$((PASS + 1))
|
|
70
|
+
else
|
|
71
|
+
echo " FAIL: $desc (stderr missing '$expect')"
|
|
72
|
+
echo " got: $stderr_out"
|
|
73
|
+
FAIL=$((FAIL + 1))
|
|
74
|
+
fi
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
echo "Testing forbidden-response-phrase-detector.sh"
|
|
78
|
+
echo "============================================="
|
|
79
|
+
|
|
80
|
+
# --- BASELINE ---
|
|
81
|
+
run_test "no CLAUDE.md → exit 0" 0 "Some response" ""
|
|
82
|
+
run_test "CLAUDE.md without prohibitions → exit 0" 0 "You're right that the issue is..." "# project notes\nuse anything"
|
|
83
|
+
|
|
84
|
+
# --- PROSE PROHIBITIONS ---
|
|
85
|
+
run_test "Do NOT open with You're right blocks" \
|
|
86
|
+
0 "You're right that the issue is here." \
|
|
87
|
+
"Do NOT open replies with \`You're right\`."
|
|
88
|
+
|
|
89
|
+
run_test "never say I apologize warns" \
|
|
90
|
+
0 "I apologize for the confusion." \
|
|
91
|
+
"never say \`I apologize\` in responses."
|
|
92
|
+
|
|
93
|
+
run_test "do not use Great point blocks" \
|
|
94
|
+
0 "Great point about that." \
|
|
95
|
+
"Do not use \`Great point\` as an opener."
|
|
96
|
+
|
|
97
|
+
# --- BLOCK MODE ---
|
|
98
|
+
run_test "BLOCK=1 with violation exits 2" \
|
|
99
|
+
2 "You're right that..." \
|
|
100
|
+
"Do NOT open with \`You're right\`." \
|
|
101
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
102
|
+
|
|
103
|
+
run_test "BLOCK=1 with clean response exits 0" \
|
|
104
|
+
0 "Looking at the code, I see the issue is..." \
|
|
105
|
+
"Do NOT open with \`You're right\`." \
|
|
106
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
107
|
+
|
|
108
|
+
# --- DISABLE ---
|
|
109
|
+
run_test "DISABLE=1 short-circuits" \
|
|
110
|
+
0 "You're right" \
|
|
111
|
+
"Do NOT use \`You're right\`." \
|
|
112
|
+
"CC_FORBIDDEN_PHRASE_DISABLE=1"
|
|
113
|
+
|
|
114
|
+
# --- OPEN_ONLY ---
|
|
115
|
+
# Response is 250+ chars; "Great point" appears at char ~210, JUST past the 200-char window
|
|
116
|
+
LONG_RESPONSE_OPEN_ONLY="Here is a thorough analysis of the existing implementation that covers all the edge cases we have observed in production over the past several weeks of operation since the deployment of the most recent revision. Great point about backwards compatibility."
|
|
117
|
+
run_test "OPEN_ONLY=1 limits scope to first 200 chars (violation outside window)" \
|
|
118
|
+
0 "$LONG_RESPONSE_OPEN_ONLY" \
|
|
119
|
+
"Do NOT say \`Great point\` in opening." \
|
|
120
|
+
"CC_FORBIDDEN_PHRASE_OPEN_ONLY=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
121
|
+
|
|
122
|
+
run_test "OPEN_ONLY=1 catches violation in first 200 chars" \
|
|
123
|
+
2 "Great point about that. Let me look at the code." \
|
|
124
|
+
"Do NOT say \`Great point\` in opening." \
|
|
125
|
+
"CC_FORBIDDEN_PHRASE_OPEN_ONLY=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
126
|
+
|
|
127
|
+
# --- CASE SENSITIVITY ---
|
|
128
|
+
run_test "case-insensitive (default) matches mixed-case violation" \
|
|
129
|
+
2 "you're right that we need to fix this." \
|
|
130
|
+
"Do NOT open with \`You're right\`." \
|
|
131
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
132
|
+
|
|
133
|
+
run_test "CASE_SENSITIVE=1 does not match lowercase" \
|
|
134
|
+
0 "you're right that we need to fix this." \
|
|
135
|
+
"Do NOT open with \`You're right\`." \
|
|
136
|
+
"CC_FORBIDDEN_PHRASE_CASE_SENSITIVE=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
137
|
+
|
|
138
|
+
run_test "CASE_SENSITIVE=1 matches exact case" \
|
|
139
|
+
2 "You're right that we need to fix this." \
|
|
140
|
+
"Do NOT open with \`You're right\`." \
|
|
141
|
+
"CC_FORBIDDEN_PHRASE_CASE_SENSITIVE=1 CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
142
|
+
|
|
143
|
+
# --- HEADER LIST FORMAT ---
|
|
144
|
+
run_test "Forbidden Response Phrases header list blocks violation" \
|
|
145
|
+
2 "You're right that this needs work." \
|
|
146
|
+
"## Forbidden Response Phrases
|
|
147
|
+
|
|
148
|
+
- \`You're right\`
|
|
149
|
+
- \`Great point\`
|
|
150
|
+
- \`I apologize\`" \
|
|
151
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
152
|
+
|
|
153
|
+
run_test "Filler Phrases header list blocks violation" \
|
|
154
|
+
2 "Great point — let me investigate." \
|
|
155
|
+
"## Filler Phrases
|
|
156
|
+
|
|
157
|
+
- \`Great point\`
|
|
158
|
+
- \`Exactly\`" \
|
|
159
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
160
|
+
|
|
161
|
+
# --- JAPANESE ---
|
|
162
|
+
run_test "Japanese: 了解しました prohibition blocks" \
|
|
163
|
+
2 "了解しました。 修正を行います。" \
|
|
164
|
+
"\`了解しました\` を返信の冒頭で使うな。" \
|
|
165
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
166
|
+
|
|
167
|
+
run_test "Japanese: header 禁止する応答 list blocks" \
|
|
168
|
+
2 "はい、その通りです。" \
|
|
169
|
+
"## 禁止する応答
|
|
170
|
+
|
|
171
|
+
- \`はい、その通りです\`
|
|
172
|
+
- \`了解しました\`" \
|
|
173
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
174
|
+
|
|
175
|
+
# --- NEGATIVE CASES ---
|
|
176
|
+
run_test "Phrase not in response → exit 0" \
|
|
177
|
+
0 "Let me look at the code and analyse the issue." \
|
|
178
|
+
"Do NOT use \`You're right\`."
|
|
179
|
+
|
|
180
|
+
run_test "Different phrase in prohibition does not match different phrase in response" \
|
|
181
|
+
0 "Great point about that." \
|
|
182
|
+
"Do NOT use \`You're absolutely correct\`."
|
|
183
|
+
|
|
184
|
+
# --- STDERR ---
|
|
185
|
+
expect_stderr_contains \
|
|
186
|
+
"stderr names the violated phrase" \
|
|
187
|
+
"You're right that..." \
|
|
188
|
+
"Do NOT open with \`You're right\`." \
|
|
189
|
+
"You're right"
|
|
190
|
+
|
|
191
|
+
expect_stderr_contains \
|
|
192
|
+
"stderr cites issue #60339" \
|
|
193
|
+
"You're right" \
|
|
194
|
+
"Do NOT open with \`You're right\`." \
|
|
195
|
+
"#60339"
|
|
196
|
+
|
|
197
|
+
expect_stderr_contains \
|
|
198
|
+
"stderr says detector header" \
|
|
199
|
+
"You're right" \
|
|
200
|
+
"Do NOT open with \`You're right\`." \
|
|
201
|
+
"forbidden-response-phrase-detector"
|
|
202
|
+
|
|
203
|
+
# --- COMBINED FORMATS ---
|
|
204
|
+
run_test "combined prose + header list works" \
|
|
205
|
+
2 "You're absolutely correct here." \
|
|
206
|
+
"## Forbidden Response Phrases
|
|
207
|
+
- \`I apologize\`
|
|
208
|
+
|
|
209
|
+
Also do NOT say \`You're absolutely correct\`." \
|
|
210
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
211
|
+
|
|
212
|
+
# --- EDGE CASES ---
|
|
213
|
+
run_test "phrase requires backticks; bare mention does not parse" \
|
|
214
|
+
0 "You're right" \
|
|
215
|
+
"Do NOT say You're right (no backticks here)."
|
|
216
|
+
|
|
217
|
+
run_test "empty response → exit 0" \
|
|
218
|
+
0 "" \
|
|
219
|
+
"Do NOT use \`You're right\`."
|
|
220
|
+
|
|
221
|
+
run_test "phrase appearing in code block (legitimate code, not natural-language)" \
|
|
222
|
+
2 "Here is some code: \`You're right\` — but this is just text matching." \
|
|
223
|
+
"Do NOT use \`You're right\`." \
|
|
224
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
225
|
+
|
|
226
|
+
# Note: the hook intentionally does not try to distinguish code blocks from
|
|
227
|
+
# narrative text. The operator's CLAUDE.md should be specific enough that
|
|
228
|
+
# inadvertent matches are rare. If false positives become an issue, the
|
|
229
|
+
# operator can refine the phrase list or use CASE_SENSITIVE mode.
|
|
230
|
+
|
|
231
|
+
# --- #60339 REPRODUCTION ---
|
|
232
|
+
RESPONSE_FROM_60339="You are right that the issue with hook execution is..."
|
|
233
|
+
CLAUDEMD_60339="## Response style rules
|
|
234
|
+
|
|
235
|
+
Do NOT open replies with filler phrases like \`You are right\`, \`Great point\`, or \`I apologize\`."
|
|
236
|
+
|
|
237
|
+
run_test "#60339 reproduction: forbidden opener blocks" \
|
|
238
|
+
2 "$RESPONSE_FROM_60339" "$CLAUDEMD_60339" \
|
|
239
|
+
"CC_FORBIDDEN_PHRASE_BLOCK=1"
|
|
240
|
+
|
|
241
|
+
run_test "#60339 reproduction with clean response passes" \
|
|
242
|
+
0 "Looking at the hook configuration, the issue is..." "$CLAUDEMD_60339"
|
|
243
|
+
|
|
244
|
+
echo ""
|
|
245
|
+
echo "Result: $PASS passed, $FAIL failed"
|
|
246
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -59,6 +59,59 @@ test_hook '{"tool_input":{"command":"printf git push"}}' 0 "printf git push not
|
|
|
59
59
|
test_hook '{"tool_input":{"command":""}}' 0 "empty command passes"
|
|
60
60
|
test_hook '{}' 0 "empty input passes"
|
|
61
61
|
|
|
62
|
+
|
|
63
|
+
# --- git's own global options between `git` and the verb (#1117) ---
|
|
64
|
+
# git -C <dir> push does exactly what git push does. Matching the two as
|
|
65
|
+
# adjacent words missed every shape below; all of them ran a real push.
|
|
66
|
+
test_hook '{"tool_input":{"command":"git -C /tmp/repo push --force origin main"}}' 2 "git -C <dir> push blocked"
|
|
67
|
+
test_hook '{"tool_input":{"command":"git --git-dir=/tmp/r/repo.d push origin main"}}' 2 "git --git-dir=<path> push blocked"
|
|
68
|
+
test_hook '{"tool_input":{"command":"git --git-dir /tmp/r/repo.d push origin main"}}' 2 "git --git-dir <path> (separate value) push blocked"
|
|
69
|
+
test_hook '{"tool_input":{"command":"git --work-tree=/tmp/w --git-dir=/tmp/r/repo.d push origin main"}}' 2 "two global options before push blocked"
|
|
70
|
+
test_hook '{"tool_input":{"command":"git -c user.name=x commit -m x"}}' 2 "git -c <k=v> commit blocked"
|
|
71
|
+
test_hook '{"tool_input":{"command":"git -C /tmp/r checkout -b feature"}}' 2 "git -C <dir> checkout -b blocked"
|
|
72
|
+
test_hook '{"tool_input":{"command":"git -C /tmp/r switch -c feature"}}' 2 "git -C <dir> switch -c blocked"
|
|
73
|
+
test_hook '{"tool_input":{"command":"git -C /tmp/r branch feature"}}' 2 "git -C <dir> branch <name> blocked"
|
|
74
|
+
test_hook '{"tool_input":{"command":"git -C /tmp/r branch -a"}}' 0 "git -C <dir> branch -a still a listing"
|
|
75
|
+
test_hook '{"tool_input":{"command":"git --no-pager push origin main"}}' 2 "git --no-pager push blocked"
|
|
76
|
+
test_hook '{"tool_input":{"command":"/usr/bin/git push origin main"}}' 2 "git invoked by absolute path blocked"
|
|
77
|
+
|
|
78
|
+
# --- the plumbing form of push ---
|
|
79
|
+
test_hook '{"tool_input":{"command":"git send-pack origin main"}}' 2 "git send-pack blocked"
|
|
80
|
+
test_hook '{"tool_input":{"command":"git -C /tmp/r send-pack origin main"}}' 2 "git -C <dir> send-pack blocked"
|
|
81
|
+
|
|
82
|
+
# --- the read-only exemption must cover its own segment only ---
|
|
83
|
+
# `^\s*(echo|printf)\s` used to exempt the WHOLE command, so everything after
|
|
84
|
+
# a harmless first segment ran unguarded.
|
|
85
|
+
test_hook '{"tool_input":{"command":"echo hi && git push origin main"}}' 2 "echo first segment does not exempt a later push"
|
|
86
|
+
test_hook '{"tool_input":{"command":"echo start; git push origin main"}}' 2 "echo before ; does not exempt a later push"
|
|
87
|
+
test_hook '{"tool_input":{"command":"printf x && git commit -m x"}}' 2 "printf first segment does not exempt a later commit"
|
|
88
|
+
test_hook '{"tool_input":{"command":"grep -r \"git push\" ./docs"}}' 0 "grep for the words is not an invocation"
|
|
89
|
+
|
|
90
|
+
# --- a single pipe is a separator too (2026-09-15) ---
|
|
91
|
+
# The splitter knew && ; and || but not `|`, so a read-only command piped into
|
|
92
|
+
# a git write arrived as ONE segment whose first word was the reader.
|
|
93
|
+
# READ_ONLY_RE exempted the whole segment and the write on the right of the
|
|
94
|
+
# pipe was never examined. Measured on the published file: these four exited 0.
|
|
95
|
+
test_hook '{"tool_input":{"command":"echo x | git push origin main"}}' 2 "echo piped into push blocked"
|
|
96
|
+
test_hook '{"tool_input":{"command":"cat f | git commit -m x"}}' 2 "cat piped into commit blocked"
|
|
97
|
+
test_hook '{"tool_input":{"command":"grep q f | git push origin main"}}' 2 "grep piped into push blocked"
|
|
98
|
+
test_hook '{"tool_input":{"command":"head -1 f | git checkout -b feature"}}' 2 "head piped into checkout -b blocked"
|
|
99
|
+
|
|
100
|
+
# The same change must not start blocking ordinary pipes. A tightening fix
|
|
101
|
+
# looks green on the blocking table while quietly breaking normal work, so the
|
|
102
|
+
# passing side is listed here on purpose. `git branch | grep main` is here
|
|
103
|
+
# because the pre-fix file refused it: unsplit, it read as `git branch <name>`.
|
|
104
|
+
test_hook '{"tool_input":{"command":"git log | head -20"}}' 0 "git log piped to head still passes"
|
|
105
|
+
test_hook '{"tool_input":{"command":"git diff | grep push"}}' 0 "git diff piped to grep still passes"
|
|
106
|
+
test_hook '{"tool_input":{"command":"git branch | grep main"}}' 0 "git branch listing piped still passes"
|
|
107
|
+
test_hook '{"tool_input":{"command":"echo \"a|b\""}}' 0 "a pipe inside quotes is not a separator"
|
|
108
|
+
|
|
109
|
+
# --- the .git path coincidence ---
|
|
110
|
+
# `git --git-dir=/tmp/r/.git push` used to match only because the PATH ended in
|
|
111
|
+
# `.git`; the same command with any other git-dir name went through.
|
|
112
|
+
test_hook '{"tool_input":{"command":"git --git-dir=/tmp/r/.git push origin main"}}' 2 "git-dir named .git blocked"
|
|
113
|
+
test_hook '{"tool_input":{"command":"ls /tmp/r/.git"}}' 0 "a path containing .git is not a push"
|
|
114
|
+
|
|
62
115
|
echo ""
|
|
63
116
|
echo "Results: $PASS passed, $FAIL failed"
|
|
64
117
|
[ "$FAIL" -gt 0 ] && exit 1
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for git-push-blast-radius-guard.sh
|
|
3
|
+
HOOK="examples/git-push-blast-radius-guard.sh"
|
|
4
|
+
# Allow running from /tmp during development: fall back to an absolute path.
|
|
5
|
+
[ -f "$HOOK" ] || HOOK="/tmp/ccps/git-push-blast-radius-guard.sh"
|
|
6
|
+
PASS=0 FAIL=0
|
|
7
|
+
|
|
8
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3' in output)"; fi; }
|
|
9
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
|
|
10
|
+
|
|
11
|
+
DIR="/tmp/cc-push-blast-test-$$"
|
|
12
|
+
export CC_PUSH_BLAST_DIR="$DIR"
|
|
13
|
+
export CC_PUSH_BLAST_WARN=3
|
|
14
|
+
export CC_PUSH_BLAST_BLOCK=6
|
|
15
|
+
export CC_PUSH_BLAST_WINDOW=3600
|
|
16
|
+
|
|
17
|
+
fresh() { rm -rf "$DIR"; }
|
|
18
|
+
# Build a Bash PreToolUse payload pushing to a named branch.
|
|
19
|
+
push() { printf '{"tool_name":"Bash","session_id":"%s","tool_input":{"command":"git push origin %s"}}' "$1" "$2"; }
|
|
20
|
+
# Record a push by actually running it through the hook (output discarded).
|
|
21
|
+
rec() { push "$1" "$2" | bash "$HOOK" >/dev/null 2>&1; }
|
|
22
|
+
|
|
23
|
+
# Test 1: non-Bash tool passes through silently
|
|
24
|
+
fresh
|
|
25
|
+
OUT=$(echo '{"tool_name":"WebFetch","tool_input":{"url":"https://x"}}' | bash "$HOOK" 2>&1)
|
|
26
|
+
assert_not_contains "non-Bash passthrough" "$OUT" "git-push-blast-radius-guard"
|
|
27
|
+
assert_not_contains "non-Bash no block" "$OUT" "decision"
|
|
28
|
+
|
|
29
|
+
# Test 2: a Bash command that is not a push passes through
|
|
30
|
+
fresh
|
|
31
|
+
OUT=$(echo '{"tool_name":"Bash","session_id":"s1","tool_input":{"command":"git status"}}' | bash "$HOOK" 2>&1)
|
|
32
|
+
assert_not_contains "non-push passthrough" "$OUT" "git-push-blast-radius-guard"
|
|
33
|
+
|
|
34
|
+
# Test 3: first two distinct branches are silent (below WARN)
|
|
35
|
+
fresh
|
|
36
|
+
for b in b1 b2; do
|
|
37
|
+
OUT=$(push s1 "$b" | bash "$HOOK" 2>&1)
|
|
38
|
+
assert_not_contains "push $b silent" "$OUT" "git-push-blast-radius-guard"
|
|
39
|
+
done
|
|
40
|
+
|
|
41
|
+
# Test 4: at WARN (3rd distinct branch) -> stderr warning, no block
|
|
42
|
+
OUT=$(push s1 b3 | bash "$HOOK" 2>&1)
|
|
43
|
+
assert_contains "3rd distinct warns" "$OUT" "git-push-blast-radius-guard"
|
|
44
|
+
STDOUT=$(push s1 b4 | bash "$HOOK" 2>/dev/null)
|
|
45
|
+
assert_not_contains "4th no block on stdout" "$STDOUT" "decision"
|
|
46
|
+
|
|
47
|
+
# Test 5: at BLOCK (6th distinct) -> block decision JSON on stdout, exit 0
|
|
48
|
+
rec s1 b5
|
|
49
|
+
STDOUT=$(push s1 b6 | bash "$HOOK" 2>/dev/null)
|
|
50
|
+
RC=$?
|
|
51
|
+
assert_contains "6th distinct blocks" "$STDOUT" '"decision": "block"'
|
|
52
|
+
assert_contains "block reason references issue" "$STDOUT" "65944"
|
|
53
|
+
[ "$RC" -eq 0 ] && PASS=$((PASS+1)) || { FAIL=$((FAIL+1)); echo "FAIL: block exits 0 (got $RC)"; }
|
|
54
|
+
|
|
55
|
+
# Test 6: re-pushing the SAME branch many times never trips (distinct stays 1)
|
|
56
|
+
fresh
|
|
57
|
+
for i in 1 2 3 4 5 6 7 8 9 10; do
|
|
58
|
+
STDOUT=$(push s2 feature | bash "$HOOK" 2>/dev/null)
|
|
59
|
+
assert_not_contains "re-push same branch #$i no block" "$STDOUT" "decision"
|
|
60
|
+
done
|
|
61
|
+
|
|
62
|
+
# Test 7: git push --all is an immediate trip (whole-repo fan-out)
|
|
63
|
+
fresh
|
|
64
|
+
STDOUT=$(echo '{"tool_name":"Bash","session_id":"s3","tool_input":{"command":"git push --all origin"}}' | bash "$HOOK" 2>/dev/null)
|
|
65
|
+
assert_contains "--all blocks immediately" "$STDOUT" '"decision": "block"'
|
|
66
|
+
|
|
67
|
+
# Test 8: off mode passes through even over the limit
|
|
68
|
+
fresh
|
|
69
|
+
for b in c1 c2 c3 c4 c5 c6; do rec s4 "$b"; done
|
|
70
|
+
OUT=$(push s4 c7 | CC_PUSH_BLAST_GUARD=off bash "$HOOK" 2>&1)
|
|
71
|
+
assert_not_contains "off mode no block" "$OUT" "decision"
|
|
72
|
+
|
|
73
|
+
# Test 9: warn mode never emits a block decision, only stderr
|
|
74
|
+
fresh
|
|
75
|
+
for b in d1 d2 d3 d4 d5; do rec s5 "$b"; done
|
|
76
|
+
OUT=$(push s5 d6 | CC_PUSH_BLAST_GUARD=warn bash "$HOOK" 2>&1)
|
|
77
|
+
assert_not_contains "warn mode no block decision" "$OUT" '"decision"'
|
|
78
|
+
assert_contains "warn mode warns" "$OUT" "git-push-blast-radius-guard"
|
|
79
|
+
|
|
80
|
+
# Test 10: window expiry prunes old branches -> count resets below warn
|
|
81
|
+
fresh
|
|
82
|
+
mkdir -p "$DIR"
|
|
83
|
+
OLD=$(( $(date +%s) - 7200 ))
|
|
84
|
+
for i in 1 2 3 4 5; do printf '%s\told%s\n' "$OLD" "$i" >> "$DIR/s6"; done
|
|
85
|
+
OUT=$(push s6 newbranch | bash "$HOOK" 2>&1)
|
|
86
|
+
assert_not_contains "expired window resets, no warn" "$OUT" "git-push-blast-radius-guard"
|
|
87
|
+
|
|
88
|
+
# Test 11: per-session isolation -- another session has its own counter
|
|
89
|
+
fresh
|
|
90
|
+
for b in e1 e2 e3 e4 e5 e6; do rec s7 "$b"; done # s7 now blocking
|
|
91
|
+
STDOUT=$(push s8 e1 | bash "$HOOK" 2>/dev/null)
|
|
92
|
+
assert_not_contains "separate session not blocked" "$STDOUT" "decision"
|
|
93
|
+
|
|
94
|
+
# Test 12: malformed input fails open (no crash, no block)
|
|
95
|
+
fresh
|
|
96
|
+
OUT=$(echo 'not json' | bash "$HOOK" 2>&1)
|
|
97
|
+
assert_not_contains "malformed input fails open" "$OUT" "decision"
|
|
98
|
+
|
|
99
|
+
# Test 13: HEAD:branch refspec counts the destination branch
|
|
100
|
+
fresh
|
|
101
|
+
for i in 1 2 3 4 5; do rec s9 "f$i"; done
|
|
102
|
+
STDOUT=$(echo '{"tool_name":"Bash","session_id":"s9","tool_input":{"command":"git push origin HEAD:f6"}}' | bash "$HOOK" 2>/dev/null)
|
|
103
|
+
assert_contains "HEAD:dst counts destination -> blocks at 6th" "$STDOUT" '"decision": "block"'
|
|
104
|
+
|
|
105
|
+
# Test 14: pushing two branches in one command counts both
|
|
106
|
+
fresh
|
|
107
|
+
rec s10 g1
|
|
108
|
+
rec s10 g2
|
|
109
|
+
rec s10 g3
|
|
110
|
+
STDOUT=$(echo '{"tool_name":"Bash","session_id":"s10","tool_input":{"command":"git push origin g4 g5 g6"}}' | bash "$HOOK" 2>/dev/null)
|
|
111
|
+
assert_contains "multi-branch single push counts all -> blocks" "$STDOUT" '"decision": "block"'
|
|
112
|
+
|
|
113
|
+
rm -rf "$DIR"
|
|
114
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
115
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for goal-iteration-limit-warner.sh
|
|
3
|
+
|
|
4
|
+
HOOK="$(dirname "$0")/../examples/goal-iteration-limit-warner.sh"
|
|
5
|
+
PASS=0 FAIL=0
|
|
6
|
+
|
|
7
|
+
TMPROOT="$(mktemp -d -t cc-goal-warn-test.XXXXXX)"
|
|
8
|
+
trap 'rm -rf "$TMPROOT"' EXIT
|
|
9
|
+
|
|
10
|
+
run_test() {
|
|
11
|
+
local desc="$1" expected_exit="$2" prompt="$3" extra_env="$4"
|
|
12
|
+
local logfile="$TMPROOT/log-$RANDOM"
|
|
13
|
+
local actual_exit
|
|
14
|
+
local payload
|
|
15
|
+
payload=$(jq -nc --arg p "$prompt" '{prompt:$p}')
|
|
16
|
+
if [ -n "$extra_env" ]; then
|
|
17
|
+
actual_exit=$(printf '%s' "$payload" | env CC_GOAL_WARN_LOG="$logfile" $extra_env bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
|
|
18
|
+
else
|
|
19
|
+
actual_exit=$(printf '%s' "$payload" | env CC_GOAL_WARN_LOG="$logfile" bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
|
|
20
|
+
fi
|
|
21
|
+
if [ "$actual_exit" -eq "$expected_exit" ]; then
|
|
22
|
+
echo " PASS: $desc"
|
|
23
|
+
PASS=$((PASS+1))
|
|
24
|
+
else
|
|
25
|
+
echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
|
|
26
|
+
FAIL=$((FAIL+1))
|
|
27
|
+
fi
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
echo "Testing goal-iteration-limit-warner.sh"
|
|
31
|
+
echo "======================================"
|
|
32
|
+
|
|
33
|
+
# 1. Empty prompt → pass
|
|
34
|
+
PAYLOAD='{"prompt":""}'
|
|
35
|
+
EXIT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
|
|
36
|
+
[ "$EXIT" -eq 0 ] && { echo " PASS: empty prompt passes"; PASS=$((PASS+1)); } || { echo " FAIL: empty prompt"; FAIL=$((FAIL+1)); }
|
|
37
|
+
|
|
38
|
+
# 2. Non-/goal prompt → pass
|
|
39
|
+
run_test "regular prompt passes" 0 "please write a poem about cats"
|
|
40
|
+
|
|
41
|
+
# 3. /goal with no termination clause → warn (exit 0)
|
|
42
|
+
run_test "/goal without limit warns (default)" 0 "/goal find the death certificate for John Smith"
|
|
43
|
+
|
|
44
|
+
# 4. /goal with no termination clause in block mode → exit 2
|
|
45
|
+
run_test "/goal without limit blocks when action=block" 2 "/goal find the death certificate for John Smith" "CC_GOAL_WARN_ACTION=block"
|
|
46
|
+
|
|
47
|
+
# 5. /goal clear → pass silently
|
|
48
|
+
run_test "/goal clear passes silently" 0 "/goal clear"
|
|
49
|
+
|
|
50
|
+
# 6. /goal status → pass silently
|
|
51
|
+
run_test "/goal status passes silently" 0 "/goal status"
|
|
52
|
+
|
|
53
|
+
# 7. /goal evaluate-once → pass silently
|
|
54
|
+
run_test "/goal evaluate-once passes silently" 0 "/goal evaluate-once"
|
|
55
|
+
|
|
56
|
+
# 8. /goal with 'or stop after 20 turns' → pass
|
|
57
|
+
run_test "/goal with 'or stop after N turns' passes" 0 "/goal find the death certificate or stop after 20 turns"
|
|
58
|
+
|
|
59
|
+
# 9. /goal with 'max 15 iterations' → pass
|
|
60
|
+
run_test "/goal with 'max N iterations' passes" 0 "/goal find the source, max 15 iterations"
|
|
61
|
+
|
|
62
|
+
# 10. /goal with 'within 10 turns' → pass
|
|
63
|
+
run_test "/goal with 'within N turns' passes" 0 "/goal find it within 10 turns"
|
|
64
|
+
|
|
65
|
+
# 11. /goal with 'after 5 attempts' → pass
|
|
66
|
+
run_test "/goal with 'after N attempts' passes" 0 "/goal find it, give up after 5 attempts"
|
|
67
|
+
|
|
68
|
+
# 12. Bare /goal (just the command) → pass (informational)
|
|
69
|
+
run_test "/goal alone passes (informational)" 0 "/goal"
|
|
70
|
+
|
|
71
|
+
# 13. /goal help → pass
|
|
72
|
+
run_test "/goal help passes silently" 0 "/goal help"
|
|
73
|
+
|
|
74
|
+
# 14. /goal with embedded newlines → still detected
|
|
75
|
+
PAYLOAD=$(jq -nc '{prompt:"some context\n/goal find rare manuscript\nmore context"}')
|
|
76
|
+
EXIT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" >/dev/null 2>/dev/null; echo $?)
|
|
77
|
+
[ "$EXIT" -eq 0 ] && { echo " PASS: /goal on a line within multi-line prompt detected"; PASS=$((PASS+1)); } || { echo " FAIL: multi-line /goal"; FAIL=$((FAIL+1)); }
|
|
78
|
+
|
|
79
|
+
# 15. Disabled via env var → pass silently
|
|
80
|
+
run_test "CC_GOAL_WARN_DISABLE=1 disables hook" 0 "/goal find anything" "CC_GOAL_WARN_DISABLE=1"
|
|
81
|
+
|
|
82
|
+
# 16. Warning to stderr, stdout empty
|
|
83
|
+
PAYLOAD=$(jq -nc '{prompt:"/goal find a rare book"}')
|
|
84
|
+
STDOUT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" 2>/dev/null)
|
|
85
|
+
STDERR=$(printf '%s' "$PAYLOAD" | bash "$HOOK" 2>&1 >/dev/null)
|
|
86
|
+
if [ -z "$STDOUT" ] && echo "$STDERR" | grep -q "without a termination clause"; then
|
|
87
|
+
echo " PASS: stdout empty, stderr has warning"
|
|
88
|
+
PASS=$((PASS+1))
|
|
89
|
+
else
|
|
90
|
+
echo " FAIL: stdout/stderr separation"
|
|
91
|
+
FAIL=$((FAIL+1))
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# 17. Log file is created
|
|
95
|
+
LOG="$TMPROOT/goal.log"
|
|
96
|
+
PAYLOAD=$(jq -nc '{prompt:"/goal find something obscure"}')
|
|
97
|
+
printf '%s' "$PAYLOAD" | env CC_GOAL_WARN_LOG="$LOG" bash "$HOOK" >/dev/null 2>/dev/null
|
|
98
|
+
if [ -f "$LOG" ] && grep -q "goal_without_limit" "$LOG"; then
|
|
99
|
+
echo " PASS: log file written"
|
|
100
|
+
PASS=$((PASS+1))
|
|
101
|
+
else
|
|
102
|
+
echo " FAIL: log file missing"
|
|
103
|
+
FAIL=$((FAIL+1))
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# 18. CC_GOAL_WARN_MAX_TURNS reflected in message
|
|
107
|
+
PAYLOAD=$(jq -nc '{prompt:"/goal find something"}')
|
|
108
|
+
STDERR=$(printf '%s' "$PAYLOAD" | env CC_GOAL_WARN_MAX_TURNS=42 bash "$HOOK" 2>&1 >/dev/null)
|
|
109
|
+
if echo "$STDERR" | grep -q "stop after 42 turns"; then
|
|
110
|
+
echo " PASS: custom max turns reflected in suggestion"
|
|
111
|
+
PASS=$((PASS+1))
|
|
112
|
+
else
|
|
113
|
+
echo " FAIL: max turns env not reflected"
|
|
114
|
+
FAIL=$((FAIL+1))
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# 19. /goal with uppercase 'STOP AFTER' → still recognized (case-insensitive)
|
|
118
|
+
run_test "/goal with 'STOP AFTER' (uppercase) passes" 0 "/goal find it OR STOP AFTER 10 TURNS"
|
|
119
|
+
|
|
120
|
+
# 20. /goal with extra spacing → still detected
|
|
121
|
+
run_test "/goal with multiple spaces detected" 0 "/goal find rare information"
|
|
122
|
+
|
|
123
|
+
# 21. Prompt without /goal anywhere → pass
|
|
124
|
+
run_test "prompt containing 'goal' as a word passes" 0 "my goal here is to write good code"
|
|
125
|
+
|
|
126
|
+
echo "======================================"
|
|
127
|
+
echo "Result: PASS=$PASS FAIL=$FAIL"
|
|
128
|
+
[ "$FAIL" -eq 0 ]
|