@soleur/opencode 0.0.0-stage → 3.354.2
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/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +660 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +29 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +361 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +171 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +818 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +411 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +509 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +115 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +165 -0
- package/scripts/sync-opencode-adapter.ts +498 -0
- package/scripts/sync-pr-behind.sh +647 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +67 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +143 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +120 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +670 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +331 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +141 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1620 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-evidence-comment.md +36 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3023 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/cleanup-merged-archival.md +39 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/delegated-act-authoring-form.md +7 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/epic-close-sweep.md +62 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +179 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/verification-scaffold/SKILL.md +73 -0
- package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
- package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
- package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
- package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
- package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
- package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
- package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
- package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
- package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
- package/skills/verification-scaffold/references/guards.tsv +21 -0
- package/skills/verification-scaffold/references/verification-readme.template +55 -0
- package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
- package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
- package/skills/verification-scaffold/test/generator.test.sh +319 -0
- package/skills/verification-scaffold/test/manifest.test.sh +144 -0
- package/skills/work/SKILL.md +1480 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Self-tests for the accessibility-snapshot credential redactor (#7947).
|
|
3
|
+
#
|
|
4
|
+
# Runs in the scripts shard — scripts/test-all.sh globs
|
|
5
|
+
# plugins/soleur/skills/*/test/*.test.sh, so this file carries NO run_suite line.
|
|
6
|
+
#
|
|
7
|
+
# Every fixture is synthesized. The sentinel ZZQP-SENTINEL-7947 is invented and
|
|
8
|
+
# is never a real credential (cq-test-fixtures-synthesized-only).
|
|
9
|
+
#
|
|
10
|
+
# The case list is derived from the Phase 0.1 measurement recorded at
|
|
11
|
+
# knowledge-base/project/specs/feat-one-shot-7946-7947-sentry-org-token-and-snapshot-redaction/phase-0-measurement.md
|
|
12
|
+
# and NOT from the plan's original structural assumption. Measured: neither
|
|
13
|
+
# agent-browser 0.22.3 nor the Playwright MCP serializes `type=`, so a
|
|
14
|
+
# structural "is this a password input" predicate is unimplementable and the
|
|
15
|
+
# accessible-name limb does all the work.
|
|
16
|
+
set -uo pipefail
|
|
17
|
+
|
|
18
|
+
REPO_ROOT="$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse --show-toplevel)"
|
|
19
|
+
FILTER="$REPO_ROOT/plugins/soleur/skills/agent-browser/scripts/redact-a11y-snapshot.py"
|
|
20
|
+
SENTINEL='ZZQP-SENTINEL-7947'
|
|
21
|
+
|
|
22
|
+
pass=0
|
|
23
|
+
fail=0
|
|
24
|
+
# Case counter. It is incremented inside assert_redacted/assert_preserved, NOT
|
|
25
|
+
# at the call sites -- an earlier comment here claimed otherwise and was wrong.
|
|
26
|
+
# That coupling means a stubbed or misrouted assert helper keeps the count
|
|
27
|
+
# reconciling while asserting nothing, which the floor cannot see. The helper
|
|
28
|
+
# control below is what closes that, by proving each verdict-owning helper can
|
|
29
|
+
# still REJECT.
|
|
30
|
+
cases=0
|
|
31
|
+
|
|
32
|
+
# Floor derived as a lower bound, not a snapshot of today's total:
|
|
33
|
+
# 6 redaction rows + 5 must-PASS rows + 3 shape rows + 3 failure-mode rows
|
|
34
|
+
# + 13 review rows (round 1) + 12 review rows (round 2) = 42.
|
|
35
|
+
# The two instrument self-test rows are excluded: they run before the counters
|
|
36
|
+
# are zeroed, so they are a precondition on the harness, not coverage of the SUT.
|
|
37
|
+
# MIN_ASSERTIONS is bound ADJACENT to the floor block at the bottom of this
|
|
38
|
+
# file, not here: scripts/guard-vacuity-floor.test.sh builds its mutant by
|
|
39
|
+
# slicing the floor block and widening BACKWARD over contiguous simple
|
|
40
|
+
# assignments only. A threshold declared up here is unbound in that slice, so
|
|
41
|
+
# the mutant dies on `set -u` BEFORE reaching the floor and the floor is scored
|
|
42
|
+
# unconstructible -- which is indistinguishable from a floor that does not fire.
|
|
43
|
+
|
|
44
|
+
ok() { printf 'ok - %s\n' "$1"; pass=$((pass + 1)); }
|
|
45
|
+
bad() { printf 'FAIL - %s\n' "$1"; fail=$((fail + 1)); }
|
|
46
|
+
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
# Instrument self-test (runs BEFORE any real row).
|
|
49
|
+
# Drives both verdict helpers once each and refuses to continue unless both
|
|
50
|
+
# counters moved. A suite whose helpers are stubbed exits 0 having asserted
|
|
51
|
+
# nothing; this is the only row that can see that.
|
|
52
|
+
# ---------------------------------------------------------------------------
|
|
53
|
+
_p0=$pass; _f0=$fail
|
|
54
|
+
ok "instrument self-test: ok() increments"
|
|
55
|
+
bad "instrument self-test: bad() increments (EXPECTED, not a real failure)"
|
|
56
|
+
if [[ $pass -ne $((_p0 + 1)) || $fail -ne $((_f0 + 1)) ]]; then
|
|
57
|
+
printf 'INSTRUMENT BROKEN: ok()/bad() did not both move (pass %d->%d, fail %d->%d)\n' \
|
|
58
|
+
"$_p0" "$pass" "$_f0" "$fail" >&2
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
# Zero all three counters rather than retiring just the deliberate failure.
|
|
62
|
+
# Half-retiring it (dropping the fail but keeping its `cases` increment) breaks
|
|
63
|
+
# the pass+fail==cases reconciliation below — which is exactly what that
|
|
64
|
+
# reconciliation is for, and it caught this on the first run.
|
|
65
|
+
pass=0; fail=0; cases=0
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# Helper control. The instrument self-test above proves ok()/bad() move their
|
|
69
|
+
# counters; it cannot see a helper that OWNS a verdict taking the wrong branch
|
|
70
|
+
# and then calling the correct-looking helper, nor one stubbed to always pass.
|
|
71
|
+
# Both survived a mutation battery until this was added.
|
|
72
|
+
#
|
|
73
|
+
# Each verdict-owning helper is driven once with an input it MUST reject, with
|
|
74
|
+
# the filter swapped for a passthrough so rejection is forced. Counters are
|
|
75
|
+
# unwound afterwards.
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
_helper_control() {
|
|
78
|
+
local _saved; _saved="$(declare -f run_filter)"
|
|
79
|
+
run_filter() { printf '%s' "$1"; } # passthrough: leaks by construction
|
|
80
|
+
local _p=$pass _f=$fail _c=$cases
|
|
81
|
+
assert_redacted 'helper control: assert_redacted must REJECT a leak (EXPECTED)' \
|
|
82
|
+
"- textbox \"Token\" [ref=e1]: $SENTINEL"
|
|
83
|
+
assert_preserved 'helper control: assert_preserved must REJECT a loss (EXPECTED)' \
|
|
84
|
+
'- textbox "x" [ref=e1]: y' 'THIS_NEEDLE_IS_NEVER_PRESENT'
|
|
85
|
+
eval "$_saved"
|
|
86
|
+
if [[ $fail -ne $((_f + 2)) ]]; then
|
|
87
|
+
printf 'HELPER CONTROL BROKEN: assert_redacted/assert_preserved did not both reject (fail %d->%d)\n' \
|
|
88
|
+
"$_f" "$fail" >&2
|
|
89
|
+
exit 1
|
|
90
|
+
fi
|
|
91
|
+
pass=$_p; fail=$_f; cases=$_c
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if [[ ! -x "$FILTER" ]]; then
|
|
95
|
+
printf 'FAIL - redactor missing or not executable at %s\n' "$FILTER"
|
|
96
|
+
printf '\nRED: the filter does not exist yet. This is the expected pre-implementation state.\n'
|
|
97
|
+
exit 1
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
run_filter() { printf '%s' "$1" | python3 "$FILTER" 2>/dev/null; }
|
|
101
|
+
|
|
102
|
+
# assert_redacted <label> <input>
|
|
103
|
+
# The value must be gone from stdout AND the marker present. Asserting the
|
|
104
|
+
# NEGATIVE (the sentinel must never appear) is the load-bearing half: a
|
|
105
|
+
# positive "is <redacted> present" is satisfied by any arm that also leaks.
|
|
106
|
+
assert_redacted() {
|
|
107
|
+
local label="$1" input="$2" out
|
|
108
|
+
cases=$((cases + 1))
|
|
109
|
+
out="$(run_filter "$input")"
|
|
110
|
+
if [[ "$out" == *"$SENTINEL"* ]]; then
|
|
111
|
+
bad "$label — sentinel survived in stdout"
|
|
112
|
+
elif [[ "$out" != *"<redacted>"* ]]; then
|
|
113
|
+
bad "$label — value removed but no <redacted> marker emitted"
|
|
114
|
+
else
|
|
115
|
+
ok "$label"
|
|
116
|
+
fi
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# assert_preserved <label> <input> <needle>
|
|
120
|
+
# The must-PASS side. A filter that redacts everything is as broken as one that
|
|
121
|
+
# redacts nothing, so every credential row above is paired against one of these.
|
|
122
|
+
assert_preserved() {
|
|
123
|
+
local label="$1" input="$2" needle="$3" out
|
|
124
|
+
cases=$((cases + 1))
|
|
125
|
+
out="$(run_filter "$input")"
|
|
126
|
+
if [[ "$out" == *"$needle"* ]]; then
|
|
127
|
+
ok "$label"
|
|
128
|
+
else
|
|
129
|
+
bad "$label — benign value was redacted (over-aggressive filter)"
|
|
130
|
+
fi
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
_helper_control
|
|
134
|
+
|
|
135
|
+
# ---------------------------------------------------------------------------
|
|
136
|
+
# Redaction rows — one per credential-shaped accessible name.
|
|
137
|
+
# "Token" is not decoration: it is the ONLY node agent-browser 0.22.3 leaks
|
|
138
|
+
# (it masks type=password as bullets), and it is the class with a recorded
|
|
139
|
+
# in-repo incident (2026-05-19-sentry-token-scope-probe-divergence.md).
|
|
140
|
+
# ---------------------------------------------------------------------------
|
|
141
|
+
assert_redacted 'agent-browser -i shape: textbox "Token"' \
|
|
142
|
+
"- textbox \"Token\" [ref=e5]: $SENTINEL"
|
|
143
|
+
|
|
144
|
+
assert_redacted 'playwright-mcp shape: textbox "Enter your password"' \
|
|
145
|
+
"- textbox \"Enter your password\" [ref=e3]: $SENTINEL"
|
|
146
|
+
|
|
147
|
+
assert_redacted 'credential name: "API key"' \
|
|
148
|
+
"- textbox \"API key\" [ref=e2]: $SENTINEL"
|
|
149
|
+
|
|
150
|
+
assert_redacted 'credential name: "Client secret"' \
|
|
151
|
+
"- textbox \"Client secret\" [ref=e2]: $SENTINEL"
|
|
152
|
+
|
|
153
|
+
assert_redacted 'credential name: "Passphrase"' \
|
|
154
|
+
"- textbox \"Passphrase\" [ref=e2]: $SENTINEL"
|
|
155
|
+
|
|
156
|
+
# Indented node — the tree is nested in real output, so an anchor on ^- only
|
|
157
|
+
# would miss every node below the root.
|
|
158
|
+
assert_redacted 'indented node is still redacted' \
|
|
159
|
+
"- generic [ref=e1]:
|
|
160
|
+
- textbox \"Token\" [ref=e5]: $SENTINEL"
|
|
161
|
+
|
|
162
|
+
# ---------------------------------------------------------------------------
|
|
163
|
+
# must-PASS rows.
|
|
164
|
+
# ---------------------------------------------------------------------------
|
|
165
|
+
assert_preserved 'must-PASS: "Email address" value survives' \
|
|
166
|
+
'- textbox "Email address" [ref=e6]: probe-user@example.invalid' \
|
|
167
|
+
'probe-user@example.invalid'
|
|
168
|
+
|
|
169
|
+
assert_preserved 'must-PASS: "Search" value survives' \
|
|
170
|
+
'- searchbox "Search" [ref=e2]: quarterly report' \
|
|
171
|
+
'quarterly report'
|
|
172
|
+
|
|
173
|
+
assert_preserved 'must-PASS: "Username" is not a secret' \
|
|
174
|
+
'- textbox "Username" [ref=e2]: alice' \
|
|
175
|
+
'alice'
|
|
176
|
+
|
|
177
|
+
assert_preserved 'must-PASS: heading text is untouched' \
|
|
178
|
+
'- heading "Reset your password" [level=1, ref=e1]' \
|
|
179
|
+
'Reset your password'
|
|
180
|
+
|
|
181
|
+
assert_preserved 'must-PASS: non-credential node name containing "key" as a substring' \
|
|
182
|
+
'- textbox "Keyboard shortcut" [ref=e2]: ctrl+k' \
|
|
183
|
+
'ctrl+k'
|
|
184
|
+
|
|
185
|
+
# ---------------------------------------------------------------------------
|
|
186
|
+
# Shape rows — the serializations measured in Phase 0.1.
|
|
187
|
+
# ---------------------------------------------------------------------------
|
|
188
|
+
|
|
189
|
+
# The no-flag / -d N shape emits the value TWICE: once as the ": value" tail and
|
|
190
|
+
# again as a nested StaticText child. A tail-only filter is half a fix and this
|
|
191
|
+
# row is what proves it.
|
|
192
|
+
assert_redacted 'nested StaticText duplicate is redacted too' \
|
|
193
|
+
"- textbox \"Token\" [ref=e5]: $SENTINEL
|
|
194
|
+
- StaticText \"$SENTINEL\""
|
|
195
|
+
|
|
196
|
+
# --json wraps the same text in data.snapshot as an escaped string.
|
|
197
|
+
assert_redacted '--json shape: data.snapshot is redacted' \
|
|
198
|
+
"{\"success\":true,\"data\":{\"snapshot\":\"- textbox \\\"Token\\\" [ref=e5]: $SENTINEL\"},\"error\":null}"
|
|
199
|
+
|
|
200
|
+
# A heading carries [level=1, ref=e1] — two attrs in one bracket. Confirm the
|
|
201
|
+
# attribute-bracket parse does not depend on a single-attr shape.
|
|
202
|
+
assert_redacted 'multi-attribute bracket parses' \
|
|
203
|
+
"- textbox \"Token\" [level=2, ref=e5]: $SENTINEL"
|
|
204
|
+
|
|
205
|
+
# ---------------------------------------------------------------------------
|
|
206
|
+
# Review rows (round 1). Every one of these reproduced a live leak or a live
|
|
207
|
+
# over-redaction in the first shipped revision; they exist so the fixes are
|
|
208
|
+
# pinned rather than merely applied.
|
|
209
|
+
# ---------------------------------------------------------------------------
|
|
210
|
+
|
|
211
|
+
# Playwright appends [checked] [disabled] [expanded] [active] [invalid]
|
|
212
|
+
# [level=N] [pressed] [selected] before [ref=eN]. The first revision accepted
|
|
213
|
+
# exactly ONE bracket, so a node with any state attribute matched nothing at
|
|
214
|
+
# all. `[disabled]` is the standard shape of a "copy your new token" panel and
|
|
215
|
+
# `[active]` is the focused password field -- both leaked in clear.
|
|
216
|
+
assert_redacted 'multi-bracket: [active] before [ref]' \
|
|
217
|
+
"- textbox \"Token\" [active] [ref=e5]: $SENTINEL"
|
|
218
|
+
assert_redacted 'multi-bracket: [disabled] (the credential-panel shape)' \
|
|
219
|
+
"- textbox \"API key\" [disabled] [ref=e7]: $SENTINEL"
|
|
220
|
+
|
|
221
|
+
# English plurals and camelCase. "API Keys" and "Tokens" are the literal labels
|
|
222
|
+
# on the Cloudflare and Sentry token pages this filter was written for, and
|
|
223
|
+
# "Token" is the class with the recorded in-repo incident -- all three leaked on
|
|
224
|
+
# their own plural.
|
|
225
|
+
assert_redacted 'plural: "API Keys"' "- textbox \"API Keys\" [ref=e1]: $SENTINEL"
|
|
226
|
+
assert_redacted 'plural: "Tokens"' "- textbox \"Tokens\" [ref=e1]: $SENTINEL"
|
|
227
|
+
assert_redacted 'camelCase: "apiKey"' "- textbox \"apiKey\" [ref=e1]: $SENTINEL"
|
|
228
|
+
|
|
229
|
+
# The one-time-code family and the carriers that embed a password.
|
|
230
|
+
assert_redacted 'one-time-code family: "Verification code"' \
|
|
231
|
+
"- textbox \"Verification code\" [ref=e1]: $SENTINEL"
|
|
232
|
+
assert_redacted 'carrier: "Connection string"' \
|
|
233
|
+
"- textbox \"Connection string\" [ref=e1]: $SENTINEL"
|
|
234
|
+
|
|
235
|
+
# `agent-browser diff snapshot` emits additions with a `+` bullet. The first
|
|
236
|
+
# revision anchored on the list-dash, so the ADDED line -- the new value --
|
|
237
|
+
# passed through in clear while only the removed one was redacted.
|
|
238
|
+
assert_redacted 'diff addition line (+ bullet)' \
|
|
239
|
+
"+ textbox \"Token\" [ref=e5]: $SENTINEL"
|
|
240
|
+
|
|
241
|
+
# The approved form is `... 2>&1 | python3 <this>`, so any agent-browser
|
|
242
|
+
# diagnostic lands AHEAD of the JSON. The first revision detected JSON with a
|
|
243
|
+
# whole-stream startswith(), so one stderr line defeated detection and the
|
|
244
|
+
# payload was emitted verbatim at exit 0 -- on the exact shape the guard
|
|
245
|
+
# prescribes.
|
|
246
|
+
assert_redacted 'stderr line ahead of --json still redacts' \
|
|
247
|
+
"warn: daemon retry
|
|
248
|
+
{\"data\":{\"snapshot\":\"- textbox \\\"Token\\\" [ref=e5]: $SENTINEL\"}}"
|
|
249
|
+
|
|
250
|
+
# An unlabeled readonly box is the commonest shape of a credential panel and
|
|
251
|
+
# matched nothing at all before. Redacted on the fail-safe side.
|
|
252
|
+
assert_redacted 'unnamed text-input carrying a value' \
|
|
253
|
+
"- textbox [ref=e5]: $SENTINEL"
|
|
254
|
+
|
|
255
|
+
cases=$((cases + 1))
|
|
256
|
+
nested="$(run_filter "- textbox \"Token\" [ref=e5]: $SENTINEL
|
|
257
|
+
- textbox \"Confirm\" [ref=e6]: $SENTINEL")"
|
|
258
|
+
if [[ "$nested" == *"$SENTINEL"* ]]; then
|
|
259
|
+
bad 'nested credential node: value must be redacted'
|
|
260
|
+
elif [[ "$nested" != *'"Confirm"'* ]]; then
|
|
261
|
+
bad 'nested credential node: the NAME must survive (the first revision redacted the name and kept the value -- the exact inversion)'
|
|
262
|
+
else
|
|
263
|
+
ok 'nested credential node: value redacted, name preserved'
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
cases=$((cases + 1))
|
|
267
|
+
labels="$(run_filter '- combobox "Primary key" [ref=e2]: users_pkey
|
|
268
|
+
- option "id" [ref=e3]
|
|
269
|
+
- option "email" [ref=e4]')"
|
|
270
|
+
if [[ "$labels" == *'"id"'* && "$labels" == *'"email"'* ]]; then
|
|
271
|
+
ok 'option LABELS survive under a redacted parent'
|
|
272
|
+
else
|
|
273
|
+
bad 'option labels were destroyed — the agent can no longer pick an option, and no credential was protected'
|
|
274
|
+
fi
|
|
275
|
+
|
|
276
|
+
assert_preserved 'must-PASS: an unnamed STRUCTURAL node is untouched' \
|
|
277
|
+
'- generic [ref=e1]:' '- generic [ref=e1]:'
|
|
278
|
+
|
|
279
|
+
# ---------------------------------------------------------------------------
|
|
280
|
+
# Review rows (round 2) — axes the round-1 battery never edited.
|
|
281
|
+
# ---------------------------------------------------------------------------
|
|
282
|
+
|
|
283
|
+
# ROLE-SET CARDINALITY. `textbox` carried every redaction row, so truncating
|
|
284
|
+
# TEXT_INPUT_ROLES to it alone was invisible -- and a member (`textarea`) had
|
|
285
|
+
# already silently left the set during round 1 and was leaking.
|
|
286
|
+
assert_redacted 'role: combobox' "- combobox \"Token\" [ref=e2]: $SENTINEL"
|
|
287
|
+
assert_redacted 'role: spinbutton' "- spinbutton \"PIN\" [ref=e2]: $SENTINEL"
|
|
288
|
+
assert_redacted 'role: textarea' "- textarea \"Token\" [ref=e2]: $SENTINEL"
|
|
289
|
+
|
|
290
|
+
# NAME-LIST CARDINALITY. These alternatives had no fixture, so truncating the
|
|
291
|
+
# regex to the covered subset survived.
|
|
292
|
+
assert_redacted 'name: "Bearer"' "- textbox \"Bearer\" [ref=e1]: $SENTINEL"
|
|
293
|
+
assert_redacted 'name: "OTP"' "- textbox \"OTP\" [ref=e1]: $SENTINEL"
|
|
294
|
+
assert_redacted 'name: "Mnemonic"' "- textbox \"Mnemonic\" [ref=e1]: $SENTINEL"
|
|
295
|
+
assert_redacted 'name: "Seed phrase"' "- textbox \"Seed phrase\" [ref=e1]: $SENTINEL"
|
|
296
|
+
assert_redacted 'name: "Credential"' "- textbox \"Credential\" [ref=e1]: $SENTINEL"
|
|
297
|
+
|
|
298
|
+
# JSON must-PASS. Every preserved-row fed the TEXT shape, so the JSON arm was
|
|
299
|
+
# pinned in one direction only: an arm that emitted just `<redacted>` and
|
|
300
|
+
# destroyed the whole envelope satisfied every assertion.
|
|
301
|
+
cases=$((cases + 1))
|
|
302
|
+
json_out="$(run_filter "{\"success\":true,\"data\":{\"snapshot\":\"- textbox \\\"Token\\\" [ref=e5]: $SENTINEL\"},\"error\":null}")"
|
|
303
|
+
if [[ "$json_out" == *"$SENTINEL"* ]]; then
|
|
304
|
+
bad 'JSON must-PASS: sentinel survived'
|
|
305
|
+
elif ! printf '%s' "$json_out" | python3 -c 'import json,sys; json.load(sys.stdin)' 2>/dev/null; then
|
|
306
|
+
bad 'JSON must-PASS: output is no longer valid JSON'
|
|
307
|
+
elif [[ "$json_out" != *'"success"'* || "$json_out" != *'"error"'* ]]; then
|
|
308
|
+
bad 'JSON must-PASS: benign sibling fields were destroyed'
|
|
309
|
+
else
|
|
310
|
+
ok 'JSON arm redacts the snapshot and preserves the rest of the envelope'
|
|
311
|
+
fi
|
|
312
|
+
|
|
313
|
+
# A snapshot nested inside an ARRAY -- the list branch of the JSON walker had
|
|
314
|
+
# no fixture, so returning the node unchanged survived.
|
|
315
|
+
assert_redacted 'JSON: snapshot nested in an array' \
|
|
316
|
+
"{\"data\":{\"results\":[{\"snapshot\":\"- textbox \\\"Token\\\" [ref=e5]: $SENTINEL\"}]}}"
|
|
317
|
+
|
|
318
|
+
# The fail-closed contract declares three refusal reasons; the UTF-8 one had no
|
|
319
|
+
# fixture, so deleting it (decode with errors="replace") survived and leaked.
|
|
320
|
+
cases=$((cases + 1))
|
|
321
|
+
u_out="$(printf '\xff\xfe- textbox "Token" [ref=e5]: %s' "$SENTINEL" | python3 "$FILTER" 2>/dev/null)"; u_rc=$?
|
|
322
|
+
if [[ $u_rc -eq 2 && -z "$u_out" ]]; then
|
|
323
|
+
ok 'non-UTF-8 input: exit 2, stdout empty'
|
|
324
|
+
else
|
|
325
|
+
bad "non-UTF-8 input must refuse (rc=$u_rc, out='${u_out:0:30}')"
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
# A JSON envelope truncated BEFORE the "snapshot" key. The round-1 fix keyed on
|
|
329
|
+
# that literal being present, so a partial envelope -- exactly what a killed
|
|
330
|
+
# agent-browser produces -- fell through to the text path and was emitted
|
|
331
|
+
# verbatim at exit 0.
|
|
332
|
+
cases=$((cases + 1))
|
|
333
|
+
t_out="$(printf 'agent-browser: reconnecting\n{"success":true,"data":{"snapsho":"- textbox \\"Token\\" [ref=e5]: %s' "$SENTINEL" | python3 "$FILTER" 2>/dev/null)"; t_rc=$?
|
|
334
|
+
if [[ $t_rc -eq 2 && -z "$t_out" ]]; then
|
|
335
|
+
ok 'truncated envelope before the snapshot key: exit 2, stdout empty'
|
|
336
|
+
elif [[ "$t_out" == *"$SENTINEL"* ]]; then
|
|
337
|
+
bad 'truncated envelope leaked the sentinel (fail-open)'
|
|
338
|
+
else
|
|
339
|
+
bad "truncated envelope must refuse (rc=$t_rc)"
|
|
340
|
+
fi
|
|
341
|
+
|
|
342
|
+
# ---------------------------------------------------------------------------
|
|
343
|
+
# Failure-mode rows — the fail-closed contract (ADR-095 shape).
|
|
344
|
+
# On refusal: exit 2, stdout EMPTY, stderr non-empty and sentinel-free. The
|
|
345
|
+
# third clause is the one that matters: a filter that echoes the offending
|
|
346
|
+
# input into its own error message re-opens the leak it exists to close.
|
|
347
|
+
# ---------------------------------------------------------------------------
|
|
348
|
+
cases=$((cases + 1))
|
|
349
|
+
over_cap="$(python3 -c "print('- textbox \"Token\" [ref=e1]: $SENTINEL' * 400000)")"
|
|
350
|
+
oc_out="$(printf '%s' "$over_cap" | python3 "$FILTER" 2>/tmp/rd_err.$$)"; oc_rc=$?
|
|
351
|
+
oc_err="$(cat /tmp/rd_err.$$ 2>/dev/null)"; rm -f /tmp/rd_err.$$
|
|
352
|
+
if [[ $oc_rc -ne 2 ]]; then
|
|
353
|
+
bad "over-cap input must exit 2 (got $oc_rc)"
|
|
354
|
+
elif [[ -n "$oc_out" ]]; then
|
|
355
|
+
bad "over-cap input must leave stdout empty"
|
|
356
|
+
elif [[ -z "$oc_err" ]]; then
|
|
357
|
+
bad "over-cap input must write a reason to stderr"
|
|
358
|
+
elif [[ "$oc_err" == *"$SENTINEL"* ]]; then
|
|
359
|
+
bad "over-cap stderr leaked the sentinel"
|
|
360
|
+
else
|
|
361
|
+
ok "over-cap input: exit 2, stdout empty, stderr non-empty and sentinel-free"
|
|
362
|
+
fi
|
|
363
|
+
|
|
364
|
+
cases=$((cases + 1))
|
|
365
|
+
mal_out="$(printf '%s' "{\"data\":{\"snapshot\": " | python3 "$FILTER" 2>/tmp/rd_err2.$$)"; mal_rc=$?
|
|
366
|
+
mal_err="$(cat /tmp/rd_err2.$$ 2>/dev/null)"; rm -f /tmp/rd_err2.$$
|
|
367
|
+
if [[ $mal_rc -ne 2 ]]; then
|
|
368
|
+
bad "truncated JSON must exit 2 (got $mal_rc)"
|
|
369
|
+
elif [[ -n "$mal_out" ]]; then
|
|
370
|
+
bad "truncated JSON must leave stdout empty"
|
|
371
|
+
elif [[ -z "$mal_err" ]]; then
|
|
372
|
+
bad "truncated JSON must write a reason to stderr"
|
|
373
|
+
else
|
|
374
|
+
ok "truncated JSON: exit 2, stdout empty, stderr non-empty"
|
|
375
|
+
fi
|
|
376
|
+
|
|
377
|
+
cases=$((cases + 1))
|
|
378
|
+
empty_out="$(printf '' | python3 "$FILTER" 2>/dev/null)"; empty_rc=$?
|
|
379
|
+
if [[ $empty_rc -eq 0 && -z "$empty_out" ]]; then
|
|
380
|
+
ok "empty input is a clean no-op (exit 0, empty stdout)"
|
|
381
|
+
else
|
|
382
|
+
bad "empty input should be a clean no-op (rc=$empty_rc, out='${empty_out:0:40}')"
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
# ---------------------------------------------------------------------------
|
|
386
|
+
# Rows added after the ship-gate consult measured six leaks against the REAL
|
|
387
|
+
# agent-browser 0.22.3, every one of which this suite was green against. The
|
|
388
|
+
# common cause is that each row above was written from the shape I expected the
|
|
389
|
+
# CLI to emit rather than from the shape it does emit.
|
|
390
|
+
# ---------------------------------------------------------------------------
|
|
391
|
+
|
|
392
|
+
# F3 -- env-var-style labels. `_` is a \w character, so `\btoken\b` never fired
|
|
393
|
+
# inside SENTRY_AUTH_TOKEN. This casing is the standard shape of a secrets
|
|
394
|
+
# editor (Doppler, Vercel, Supabase), i.e. the exact panel class this exists for.
|
|
395
|
+
assert_redacted 'env-var casing: SENTRY_AUTH_TOKEN' \
|
|
396
|
+
"- textbox \"SENTRY_AUTH_TOKEN\" [ref=e1]: $SENTINEL"
|
|
397
|
+
assert_redacted 'env-var casing: API_KEY' \
|
|
398
|
+
"- textbox \"API_KEY\" [ref=e1]: $SENTINEL"
|
|
399
|
+
assert_redacted 'env-var casing: DB_PASSWORD' \
|
|
400
|
+
"- textbox \"DB_PASSWORD\" [ref=e1]: $SENTINEL"
|
|
401
|
+
|
|
402
|
+
# F3 -- the 2FA family. `2FA` additionally regressed once during the fix: the
|
|
403
|
+
# camelCase splitter turned it into `2 FA`, un-matching the alternative.
|
|
404
|
+
assert_redacted '2fa family: "Authenticator code"' \
|
|
405
|
+
"- textbox \"Authenticator code\" [ref=e1]: $SENTINEL"
|
|
406
|
+
assert_redacted '2fa family: "TOTP"' \
|
|
407
|
+
"- textbox \"TOTP\" [ref=e1]: $SENTINEL"
|
|
408
|
+
assert_redacted '2fa family: "2FA code" (acronym must not be camel-split)' \
|
|
409
|
+
"- textbox \"2FA code\" [ref=e1]: $SENTINEL"
|
|
410
|
+
assert_redacted '2fa family: "Two-factor code"' \
|
|
411
|
+
"- textbox \"Two-factor code\" [ref=e1]: $SENTINEL"
|
|
412
|
+
assert_redacted '2fa family: "MFA code"' \
|
|
413
|
+
"- textbox \"MFA code\" [ref=e1]: $SENTINEL"
|
|
414
|
+
|
|
415
|
+
# F5 -- the over-redaction side. Bare `session`/`cookie`/`signature` ate all
|
|
416
|
+
# four of these. A filter that eats ordinary fields gets switched off.
|
|
417
|
+
assert_preserved 'must-PASS: "Session name" is not a credential' \
|
|
418
|
+
'- textbox "Session name" [ref=e1]: my-session' 'my-session'
|
|
419
|
+
assert_preserved 'must-PASS: "Email signature" is not a credential' \
|
|
420
|
+
'- textbox "Email signature" [ref=e1]: Best regards' 'Best regards'
|
|
421
|
+
assert_preserved 'must-PASS: "Cookie name" is not a credential' \
|
|
422
|
+
'- textbox "Cookie name" [ref=e1]: sid' 'sid'
|
|
423
|
+
assert_preserved 'must-PASS: "Search sessions" is not a credential' \
|
|
424
|
+
'- searchbox "Search sessions" [ref=e1]: my-query' 'my-query'
|
|
425
|
+
|
|
426
|
+
# F5b -- but the bare word IS the credential when it is the whole name. Pairing
|
|
427
|
+
# these with the four above is what keeps the narrowing honest in both
|
|
428
|
+
# directions: neither row alone would catch a one-sided over-correction.
|
|
429
|
+
assert_redacted 'whole-name credential: "Session"' \
|
|
430
|
+
"- textbox \"Session\" [ref=e1]: $SENTINEL"
|
|
431
|
+
assert_redacted 'whole-name credential: "Cookie"' \
|
|
432
|
+
"- textbox \"Cookie\" [ref=e1]: $SENTINEL"
|
|
433
|
+
|
|
434
|
+
# F1 -- a multi-line value. A textarea holding a PEM block emits its 2nd..Nth
|
|
435
|
+
# lines raw at COLUMN 0, which ended indent-keyed suppression on line 2 and
|
|
436
|
+
# printed the rest of the key in clear, together with every StaticText
|
|
437
|
+
# duplicate below it. Measured on all four output shapes.
|
|
438
|
+
assert_redacted 'multi-line textarea value does not escape suppression' \
|
|
439
|
+
"$(printf -- '- textbox "Private key" [ref=e1]: -----BEGIN\n%s\n-----END\n - generic\n - StaticText "%s"\n- button "Save"' "$SENTINEL" "$SENTINEL")"
|
|
440
|
+
|
|
441
|
+
# F2a -- the REAL `agent-browser diff snapshot` bullet shapes. The pre-existing
|
|
442
|
+
# `+ textbox` row below pins a shape the CLI never emits; these are the ones it
|
|
443
|
+
# does, including the SGR colouring that sits outside the bullet.
|
|
444
|
+
assert_redacted 'diff shape: "+- textbox" (no space after the marker)' \
|
|
445
|
+
"+- textbox \"Token\" [ref=e1]: $SENTINEL"
|
|
446
|
+
assert_redacted 'diff shape: "+ - textbox" (marker, then indent)' \
|
|
447
|
+
"+ - textbox \"API_KEY\" [ref=e1]: $SENTINEL"
|
|
448
|
+
assert_redacted 'diff shape: ANSI SGR wrapping the whole line' \
|
|
449
|
+
"$(printf -- '\033[32m+ - textbox "Password" [ref=e1]: %s\033[0m' "$SENTINEL")"
|
|
450
|
+
|
|
451
|
+
# F2b -- `diff snapshot --json` puts the tree under data.diff, not
|
|
452
|
+
# data.snapshot. The envelope parsed, matched no key, and every value was
|
|
453
|
+
# emitted verbatim at exit 0 -- on a command the interceptor ALLOWS.
|
|
454
|
+
assert_redacted 'json shape: tree under data.diff, not data.snapshot' \
|
|
455
|
+
"$(printf -- '{"ok":true,"data":{"diff":"+- textbox \\"Token\\" [ref=e1]: %s"}}' "$SENTINEL")"
|
|
456
|
+
|
|
457
|
+
# ---------------------------------------------------------------------------
|
|
458
|
+
# YAML single-quoted keys (#7980 review). Playwright wraps the WHOLE key in single
|
|
459
|
+
# quotes when the accessible name contains ` #`, `: `, `{`, `}`, a backtick or a
|
|
460
|
+
# control character; the key strings below were rendered by 0.0.78's own
|
|
461
|
+
# yamlEscapeKeyIfNeeded. Measured live: "API Key #1" leaked in clear through the
|
|
462
|
+
# proxy before this arm existed.
|
|
463
|
+
# ---------------------------------------------------------------------------
|
|
464
|
+
assert_redacted 'quoted key: "API Key #1" (space-hash)' \
|
|
465
|
+
"$(printf -- "- 'textbox \"API Key #1\" [ref=e2]': %s" "$SENTINEL")"
|
|
466
|
+
assert_redacted 'quoted key: "Token: production" (colon-space)' \
|
|
467
|
+
"$(printf -- "- 'textbox \"Token: production\" [ref=e3]': %s" "$SENTINEL")"
|
|
468
|
+
assert_redacted 'quoted key: "Secret {prod}" (braces)' \
|
|
469
|
+
"$(printf -- "- 'textbox \"Secret {prod}\" [ref=e4]': %s" "$SENTINEL")"
|
|
470
|
+
assert_redacted 'quoted key: "Deploy `key`" (backtick)' \
|
|
471
|
+
"$(printf -- "- 'textbox \"Deploy \`key\`\" [ref=e5]': %s" "$SENTINEL")"
|
|
472
|
+
assert_redacted "quoted key: doubled apostrophe (Owner''s token #2), indented" \
|
|
473
|
+
"$(printf -- "- generic [ref=e1]:\n - 'textbox \"Owner''s token #2\" [ref=e6]': %s" "$SENTINEL")"
|
|
474
|
+
assert_preserved 'must-PASS: quoted key "Notes #3" keeps its value' \
|
|
475
|
+
"- 'textbox \"Notes #3\" [ref=e7]': ZZQP-BENIGN-A11Y" 'ZZQP-BENIGN-A11Y'
|
|
476
|
+
assert_preserved 'must-PASS: a redacted quoted key keeps its quoting' \
|
|
477
|
+
"$(printf -- "- 'textbox \"API Key #1\" [ref=e2]': %s" "$SENTINEL")" "- 'textbox \"API Key #1\" [ref=e2]': <redacted>"
|
|
478
|
+
|
|
479
|
+
# ---------------------------------------------------------------------------
|
|
480
|
+
# Provider contract (#7980). playwright-mcp-redact-proxy.py loads this file by
|
|
481
|
+
# path and binds exactly these four names at startup. The contract is tested
|
|
482
|
+
# where it is provided: a rename of any of them must red THIS suite, not only
|
|
483
|
+
# the proxy's refuse-to-start arm. The row increments `cases` itself because it
|
|
484
|
+
# uses neither assert helper.
|
|
485
|
+
# ---------------------------------------------------------------------------
|
|
486
|
+
cases=$((cases + 1))
|
|
487
|
+
_contract_out=$(python3 - "$FILTER" <<'PY' 2>&1 || true
|
|
488
|
+
import importlib.util, sys
|
|
489
|
+
spec = importlib.util.spec_from_file_location("redact_a11y_snapshot", sys.argv[1])
|
|
490
|
+
mod = importlib.util.module_from_spec(spec)
|
|
491
|
+
spec.loader.exec_module(mod)
|
|
492
|
+
names = ["redact_text", "looks_like_a11y_tree", "MAX_INPUT_BYTES", "REDACTED"]
|
|
493
|
+
missing = [n for n in names if not hasattr(mod, n)]
|
|
494
|
+
if missing or mod.__all__ != names:
|
|
495
|
+
print("CONTRACT-BROKEN missing=%s __all__=%s" % (missing, getattr(mod, "__all__", None)))
|
|
496
|
+
elif not mod.looks_like_a11y_tree('- textbox "Token" [ref=e1]: x') or mod.looks_like_a11y_tree("### Page\n- Page URL: x"):
|
|
497
|
+
print("CONTRACT-BROKEN looks_like_a11y_tree verdicts")
|
|
498
|
+
elif not mod.looks_like_a11y_tree("- 'textbox \"API Key #1\" [ref=e2]': x"):
|
|
499
|
+
print("CONTRACT-BROKEN looks_like_a11y_tree on a quoted key")
|
|
500
|
+
else:
|
|
501
|
+
print("CONTRACT-OK")
|
|
502
|
+
PY
|
|
503
|
+
)
|
|
504
|
+
if [[ "$_contract_out" == "CONTRACT-OK" ]]; then
|
|
505
|
+
ok "provider contract: the four consumer names are exported, __all__ pins them, quoted keys are tree-shaped"
|
|
506
|
+
else
|
|
507
|
+
bad "provider contract: $_contract_out"
|
|
508
|
+
fi
|
|
509
|
+
|
|
510
|
+
# ---------------------------------------------------------------------------
|
|
511
|
+
# Verdict. Reported with printf + exit, never through ok()/bad() — the floor
|
|
512
|
+
# must not be dispatched through the helpers it backstops (ADR-193).
|
|
513
|
+
# ---------------------------------------------------------------------------
|
|
514
|
+
printf '\n%d passed, %d failed, %d cases\n' "$pass" "$fail" "$cases"
|
|
515
|
+
|
|
516
|
+
if [[ $((pass + fail)) -ne $cases ]]; then
|
|
517
|
+
printf '[FATAL] vacuity accounting: pass+fail (%d) != cases (%d) — a row did not report\n' \
|
|
518
|
+
"$((pass + fail))" "$cases" >&2
|
|
519
|
+
exit 1
|
|
520
|
+
fi
|
|
521
|
+
MIN_ASSERTIONS=69
|
|
522
|
+
if [[ $cases -lt $MIN_ASSERTIONS ]]; then
|
|
523
|
+
printf '[FATAL] vacuity floor: only %d cases executed, expected at least %d\n' "$cases" "$MIN_ASSERTIONS" >&2
|
|
524
|
+
exit 1
|
|
525
|
+
fi
|
|
526
|
+
[[ $fail -eq 0 ]] || exit 1
|
|
527
|
+
exit 0
|