@soleur/opencode 0.0.0-stage → 1.0.0
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 +659 -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 +108 -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 +342 -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 +152 -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 +493 -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 +363 -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 +520 -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 +113 -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 +178 -0
- package/scripts/sync-opencode-adapter.ts +479 -0
- package/scripts/sync-pr-behind.sh +534 -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 +65 -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 +142 -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 +118 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -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 +668 -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 +325 -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 +138 -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 +1621 -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-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +95 -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 +3022 -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/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/detached-battery-verdict.md +13 -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 +149 -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/work/SKILL.md +1479 -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,342 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# run-scan.sh — orchestrate the five category checks, aggregate verdict,
|
|
3
|
+
# emit markdown findings + mandatory disclaimer footer, write .scan-meta.json
|
|
4
|
+
# (with PII redaction).
|
|
5
|
+
#
|
|
6
|
+
# Stdin: SKILL.md content. Or: positional file path.
|
|
7
|
+
# Stdout: markdown findings table + disclaimer footer.
|
|
8
|
+
# Exit code: NOT guaranteed 0. This header claimed "0 always (advisory)" and
|
|
9
|
+
# that was false the moment `set -euo pipefail` below was added: any internal
|
|
10
|
+
# command failure, unset variable, or failing pipeline aborts this script with a
|
|
11
|
+
# non-zero status. Callers MUST check it. The claim was load-bearing in the
|
|
12
|
+
# wrong direction -- the skill-security-scan workflows relied on it to justify
|
|
13
|
+
# `2>/dev/null | head -1 | grep ... || echo UNKNOWN`, which converted a crashed
|
|
14
|
+
# scanner into a verdict the gate then accepted (#7629).
|
|
15
|
+
#
|
|
16
|
+
# The VERDICT is advisory; the EXIT STATUS is not. A non-zero exit means no
|
|
17
|
+
# verdict was produced, which is not the same as a clean skill.
|
|
18
|
+
|
|
19
|
+
set -euo pipefail
|
|
20
|
+
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
23
|
+
SCANNER_VERSION="0.1.0"
|
|
24
|
+
|
|
25
|
+
# Resolve input file
|
|
26
|
+
if [ "$#" -ge 1 ] && [ -f "$1" ]; then
|
|
27
|
+
INPUT="$1"
|
|
28
|
+
CLEANUP=""
|
|
29
|
+
else
|
|
30
|
+
INPUT="$(mktemp -t skill-scan-input-XXXXXX)"
|
|
31
|
+
CLEANUP="$INPUT"
|
|
32
|
+
cat > "$INPUT"
|
|
33
|
+
fi
|
|
34
|
+
trap '[ -n "$CLEANUP" ] && rm -f "$CLEANUP"' EXIT
|
|
35
|
+
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
# Self-defense: rule-pack SHA validation (per Phase 5)
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
|
+
manifest="$SKILL_DIR/references/rules/manifest.yaml"
|
|
40
|
+
rule_pack_sha="unknown"
|
|
41
|
+
rule_pack_version="unknown"
|
|
42
|
+
if [ -f "$manifest" ]; then
|
|
43
|
+
rule_pack_version="$(awk '/^version:/ { gsub(/^version:[[:space:]]*"?|"?$/, ""); print; exit }' "$manifest")"
|
|
44
|
+
# Compute current manifest SHA over the manifest file itself for traceability.
|
|
45
|
+
rule_pack_sha="$(sha256sum "$manifest" | cut -d' ' -f1)"
|
|
46
|
+
# Validate per-file SHAs declared in manifest. Tampered file → flag and
|
|
47
|
+
# short-circuit to REVIEW. Manifest format: list of `- path:`/`sha256:`
|
|
48
|
+
# tuples relative to the rules/ directory.
|
|
49
|
+
tampered=""
|
|
50
|
+
while IFS= read -r line; do
|
|
51
|
+
case "$line" in
|
|
52
|
+
*path:*)
|
|
53
|
+
cur_path="${line#*path:}"
|
|
54
|
+
cur_path="${cur_path// /}"
|
|
55
|
+
cur_path="${cur_path//\"/}"
|
|
56
|
+
cur_path="${cur_path//\'/}"
|
|
57
|
+
;;
|
|
58
|
+
*sha256:*)
|
|
59
|
+
cur_sha="${line#*sha256:}"
|
|
60
|
+
cur_sha="${cur_sha// /}"
|
|
61
|
+
cur_sha="${cur_sha//\"/}"
|
|
62
|
+
cur_sha="${cur_sha//\'/}"
|
|
63
|
+
actual="$(sha256sum "$SKILL_DIR/references/$cur_path" 2>/dev/null | cut -d' ' -f1 || echo "")"
|
|
64
|
+
if [ -n "$actual" ] && [ "$actual" != "$cur_sha" ]; then
|
|
65
|
+
tampered+="$cur_path "
|
|
66
|
+
fi
|
|
67
|
+
cur_path=""
|
|
68
|
+
;;
|
|
69
|
+
esac
|
|
70
|
+
done < "$manifest"
|
|
71
|
+
if [ -n "$tampered" ]; then
|
|
72
|
+
# Tamper short-circuits to HIGH-RISK (deny-by-default), not REVIEW.
|
|
73
|
+
# Rationale: REVIEW maps to `ask` in the PreToolUse hook, which an operator
|
|
74
|
+
# can confirm-through; an attacker with rule-pack write access could then
|
|
75
|
+
# downgrade a real HIGH-RISK skill to REVIEW and have the operator accept.
|
|
76
|
+
# HIGH-RISK on tamper forces an override-artifact path and audit trail.
|
|
77
|
+
cat <<EOF
|
|
78
|
+
# skill-security-scan verdict: HIGH-RISK
|
|
79
|
+
|
|
80
|
+
**Self-defense:** rule pack tampered. Files with SHA mismatch:
|
|
81
|
+
|
|
82
|
+
$(echo "$tampered" | tr ' ' '\n' | grep -v '^$' | sed 's/^/ - /')
|
|
83
|
+
|
|
84
|
+
Re-run with \`scripts/run-self-test.sh --regenerate-manifest\` (dev) or fix
|
|
85
|
+
the rule pack before scanning. Override requires a structured artifact under
|
|
86
|
+
\`knowledge-base/engineering/security/skill-overrides/\`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
Advisory static analysis only. LOW-RISK does not constitute a security audit,
|
|
90
|
+
certification, or warranty of safety. The skill executes in your environment
|
|
91
|
+
under your account; you remain responsible for review.
|
|
92
|
+
|
|
93
|
+
Scanner version: $SCANNER_VERSION Rule pack: ${rule_pack_sha:0:12} Scanned: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
94
|
+
EOF
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
# Run the five category checks. Each consumes stdin (the SKILL.md content)
|
|
101
|
+
# and emits a JSON document on stdout. We collect into a temp dir.
|
|
102
|
+
# ---------------------------------------------------------------------------
|
|
103
|
+
results_dir="$(mktemp -dt skill-scan-results-XXXXXX)"
|
|
104
|
+
trap '[ -n "$CLEANUP" ] && rm -f "$CLEANUP"; rm -rf "$results_dir"' EXIT
|
|
105
|
+
|
|
106
|
+
run_category() {
|
|
107
|
+
local script="$1" out="$2"
|
|
108
|
+
bash "$SCRIPT_DIR/$script" < "$INPUT" > "$out" 2>/dev/null || \
|
|
109
|
+
echo '{"verdict":"REVIEW","category":"unknown","findings":[{"rule_id":"check-failed","severity":"REVIEW","line":0,"snippet":"category script error"}]}' > "$out"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
run_category check-codeexec.sh "$results_dir/code-execution.json" &
|
|
113
|
+
run_category check-prompt-injection.sh "$results_dir/prompt-injection.json" &
|
|
114
|
+
run_category check-supply-chain.sh "$results_dir/supply-chain.json" &
|
|
115
|
+
run_category check-filesystem-boundary.sh "$results_dir/filesystem-boundary.json" &
|
|
116
|
+
run_category check-telemetry-surface.sh "$results_dir/telemetry-surface.json" &
|
|
117
|
+
wait
|
|
118
|
+
|
|
119
|
+
# Aggregate verdict (max-severity wins).
|
|
120
|
+
agg_verdict="LOW-RISK"
|
|
121
|
+
for f in "$results_dir"/*.json; do
|
|
122
|
+
v="$(jq -r '.verdict' "$f" 2>/dev/null || echo "REVIEW")"
|
|
123
|
+
case "$v" in
|
|
124
|
+
HIGH-RISK) agg_verdict="HIGH-RISK"; break ;;
|
|
125
|
+
REVIEW) [ "$agg_verdict" = "LOW-RISK" ] && agg_verdict="REVIEW" ;;
|
|
126
|
+
esac
|
|
127
|
+
done
|
|
128
|
+
|
|
129
|
+
# Build findings_summary JSON (with PII + secret redaction).
|
|
130
|
+
# Per GDPR-DataMin-1 (PII) and security review P2-4 (high-entropy secrets):
|
|
131
|
+
# redact email/IPv4/IBAN PLUS JWT, Anthropic/OpenAI keys, GitHub PAT/OAuth,
|
|
132
|
+
# Doppler tokens, GitLab PAT, Slack tokens, AWS access keys.
|
|
133
|
+
redact_pii() {
|
|
134
|
+
sed -E '
|
|
135
|
+
s/\bghp_[A-Za-z0-9._~+/=-]{20,}/<github-pat>/g;
|
|
136
|
+
s/\bgho_[A-Za-z0-9._~+/=-]{20,}/<github-oauth>/g;
|
|
137
|
+
s/\bghs_[A-Za-z0-9._~+/=-]{20,}/<github-server>/g;
|
|
138
|
+
s/\bghr_[A-Za-z0-9._~+/=-]{20,}/<github-refresh>/g;
|
|
139
|
+
s/\bghu_[A-Za-z0-9._~+/=-]{20,}/<github-user>/g;
|
|
140
|
+
s/\bgithub_pat_[A-Za-z0-9._~+/=-]{40,}/<github-pat>/g;
|
|
141
|
+
s/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/<email>/g;
|
|
142
|
+
s/\b([0-9]{1,3}\.){3}[0-9]{1,3}\b/<ip>/g;
|
|
143
|
+
s/\b[A-Z]{2}[0-9]{2}[A-Z0-9]{4,}\b/<iban>/g;
|
|
144
|
+
s/eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/<jwt>/g;
|
|
145
|
+
s/sk-ant-[A-Za-z0-9_-]{8,}/<anthropic-key>/g;
|
|
146
|
+
s/sk-[A-Za-z0-9]{20,}/<openai-key>/g;
|
|
147
|
+
s/\bglpat-[A-Za-z0-9_-]{8,}/<gitlab-pat>/g;
|
|
148
|
+
s/dp\.ct\.[A-Za-z0-9_-]{20,}/<doppler-token>/g;
|
|
149
|
+
s/dp\.pt\.[A-Za-z0-9_-]{20,}/<doppler-token>/g;
|
|
150
|
+
s/dp\.st\.[A-Za-z0-9_-]{20,}/<doppler-token>/g;
|
|
151
|
+
s/xox[bopas]-[A-Za-z0-9-]{10,}/<slack-token>/g;
|
|
152
|
+
s/\bAKIA[A-Z0-9]{16}\b/<aws-access-key>/g
|
|
153
|
+
'
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# ARGV CEILING (#6736). Both the per-category body and the accumulated summary are
|
|
157
|
+
# kept in FILES and bound with `--rawfile … | fromjson`, never `--argjson`. A shell
|
|
158
|
+
# variable bound via --argjson is ONE argv argument, and the kernel caps a SINGLE argv
|
|
159
|
+
# argument at MAX_ARG_STRLEN = 131,072 B — verified by bisect on this host: 131,071 B
|
|
160
|
+
# passes, 131,072 B fails E2BIG. This is NOT `getconf ARG_MAX` (2,097,152 B, the
|
|
161
|
+
# argv+envp total); a payload at 6% of ARG_MAX still dies.
|
|
162
|
+
#
|
|
163
|
+
# Nothing bounds this: snippets are capped at 200 chars by apply_yaml_rules, but the
|
|
164
|
+
# FINDING COUNT is uncapped (one grep hit per matching line), and $findings_summary is
|
|
165
|
+
# the sum over all five categories — so it crosses the ceiling before any single
|
|
166
|
+
# category does. Pre-fix this died with `Argument list too long` mid-scan, after the
|
|
167
|
+
# per-category checks had already succeeded.
|
|
168
|
+
#
|
|
169
|
+
# The scratch files live in "$results_dir/.agg" rather than "$results_dir" itself:
|
|
170
|
+
# the markdown-table loop below re-globs "$results_dir"/*.json, and a summary file
|
|
171
|
+
# sitting there would be read back as a sixth bogus category row. A dot-prefixed
|
|
172
|
+
# subdirectory is invisible to that glob and is still cleaned by the existing
|
|
173
|
+
# `rm -rf "$results_dir"` EXIT trap, so this adds no new cleanup obligation.
|
|
174
|
+
agg_dir="$results_dir/.agg"
|
|
175
|
+
mkdir -p "$agg_dir"
|
|
176
|
+
summary_file="$agg_dir/findings-summary.json"
|
|
177
|
+
body_file="$agg_dir/body-redacted.json"
|
|
178
|
+
echo '{}' > "$summary_file"
|
|
179
|
+
for f in "$results_dir"/*.json; do
|
|
180
|
+
cat="$(jq -r '.category' "$f")"
|
|
181
|
+
jq '{verdict, findings}' "$f" | redact_pii > "$body_file"
|
|
182
|
+
jq --arg c "$cat" --rawfile b "$body_file" '. + {($c): ($b | fromjson)}' \
|
|
183
|
+
"$summary_file" > "$summary_file.next"
|
|
184
|
+
mv "$summary_file.next" "$summary_file"
|
|
185
|
+
done
|
|
186
|
+
|
|
187
|
+
# Write .scan-meta.json under meta_base (XDG_RUNTIME_DIR, else /tmp).
|
|
188
|
+
# umask 077 ensures persisted findings are not world-readable on shared hosts.
|
|
189
|
+
ts="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
|
|
190
|
+
meta_base="${SKILL_SCAN_META_BASE:-${XDG_RUNTIME_DIR:-/tmp}}"
|
|
191
|
+
|
|
192
|
+
# Bound the per-invocation meta_dir leak (#6789). Each run creates
|
|
193
|
+
# skill-security-scan-<pid>/ and NOTHING removes it: measured 12,889 leaked
|
|
194
|
+
# dirs. The fix is a STARTUP age-reap of OLDER siblings — deliberately NOT a
|
|
195
|
+
# `trap 'rm -rf "$meta_dir"' EXIT`. `.scan-meta.json` is GDPR Art. 32 evidence:
|
|
196
|
+
# override-mechanism.md instructs the operator to reference this path in an
|
|
197
|
+
# override artifact AFTER the scan exits (see the "written to:" line below), so
|
|
198
|
+
# a naive EXIT trap would delete the very artifact the override flow needs (R1).
|
|
199
|
+
# The current process's own dir is created after this reap and is never a
|
|
200
|
+
# candidate here, so the artifact this run writes always survives this run.
|
|
201
|
+
# Age-only is the correct sole dimension: these dirs are per-pid and single-use,
|
|
202
|
+
# so an OLD one is definitionally abandoned (name-scoped age is safe here —
|
|
203
|
+
# unlike a generic /tmp reaper, which cannot distinguish producer families).
|
|
204
|
+
#
|
|
205
|
+
# The floor defaults to 7 DAYS, not 24h: .scan-meta.json is Art. 32 evidence an
|
|
206
|
+
# operator may reference when building an override artifact, and that can happen
|
|
207
|
+
# a day or more after the scan. A generous floor keeps a still-referenceable
|
|
208
|
+
# evidence dir alive across a realistic operator gap while still bounding the
|
|
209
|
+
# leak — these dirs are tiny (one JSON file) and live in the runtime tmpfs,
|
|
210
|
+
# which is near-empty, so the leak's cost is inode COUNT, not bytes, and a 7-day
|
|
211
|
+
# window caps that at a manageable steady state. A longer-lived reference is the
|
|
212
|
+
# same pre-existing fragility the override mechanism already carries
|
|
213
|
+
# ($XDG_RUNTIME_DIR is cleared on logout regardless), out of scope here.
|
|
214
|
+
# SKILL_SCAN_META_REAP_MIN overrides the floor (minutes). Non-numeric values
|
|
215
|
+
# fall back to the default rather than silently disabling BOTH reaps below;
|
|
216
|
+
# `10#` normalizes leading zeros — unnormalized, the expansion error on
|
|
217
|
+
# `08`/`09` silently strands the literal string (the `||` fallback and the
|
|
218
|
+
# clamp both skip on arithmetic error), so find reads an octal-legal floor
|
|
219
|
+
# BELOW the 60-minute minimum.
|
|
220
|
+
_reap_min="${SKILL_SCAN_META_REAP_MIN:-10080}"
|
|
221
|
+
[[ "$_reap_min" =~ ^[0-9]{1,9}$ ]] && _reap_min=$((10#${_reap_min})) || _reap_min=10080
|
|
222
|
+
# Both sweeps clamp to >=60 minutes: `-mmin "+0"` matches ANY past mtime,
|
|
223
|
+
# so a pathological or test-seam floor below an hour reaps a CONCURRENT
|
|
224
|
+
# scan's live scratch and meta dir — the exclusions below cover only this
|
|
225
|
+
# run's own entries. 60 bounds a plausible scan lifetime; the operator's
|
|
226
|
+
# floor above it is verbatim.
|
|
227
|
+
_reap_min=$(( _reap_min < 60 ? 60 : _reap_min ))
|
|
228
|
+
meta_root="$(cd -P "$meta_base" 2>/dev/null && pwd -P || true)"
|
|
229
|
+
if [ -n "$meta_root" ]; then
|
|
230
|
+
# -maxdepth 1 -type d, older than the floor, own the current uid. `-mmin` on
|
|
231
|
+
# each dir is safe here: the dir is written once at creation and never touched
|
|
232
|
+
# again, so its own mtime IS the run's age. cd -P canonicalizes the base —
|
|
233
|
+
# find under default -P does not descend a symlinked startpoint, so a
|
|
234
|
+
# symlinked meta_base would silently no-op the whole reap. rm failures (a
|
|
235
|
+
# sibling reaping the same dir) are tolerated; a non-zero find exit warns
|
|
236
|
+
# instead of silently disabling the reap.
|
|
237
|
+
find "$meta_root" -mindepth 1 -maxdepth 1 -type d \
|
|
238
|
+
-name 'skill-security-scan-*' -user "$(id -u)" -mmin "+${_reap_min}" \
|
|
239
|
+
-exec rm -rf {} + 2>/dev/null \
|
|
240
|
+
|| echo "run-scan: meta_dir reap failed; orphans retained" >&2
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
# #6760: age-floor sweep for the scratch families under ${TMPDIR:-/tmp} —
|
|
244
|
+
# orphans the meta-base reap cannot reach. Three classes: the `skill-scan-*`
|
|
245
|
+
# scratch producers (skill-scan-input-*, skill-scan-results-*,
|
|
246
|
+
# skill-scan-XXXXXX + .code/.fm/.body/.req/.resp siblings — created by
|
|
247
|
+
# `mktemp -t` under TMPDIR and EXIT-trap-cleaned only on a clean exit);
|
|
248
|
+
# `skill-security-scan-*` meta dirs stranded under /tmp by the
|
|
249
|
+
# XDG_RUNTIME_DIR env flip (when ${TMPDIR:-/tmp} resolves to that base —
|
|
250
|
+
# with a custom TMPDIR the pre-flip orphans sit on a root this sweep does
|
|
251
|
+
# not scan); and `sss-write.*.err` captures from the skill's own write-hook.
|
|
252
|
+
# Top-level `-mmin` is the sole age test because every producer write creates
|
|
253
|
+
# a new entry (dir mtime tracks its last child) — a write-once invariant
|
|
254
|
+
# matching the meta reap's, so an OLD entry is definitionally orphaned.
|
|
255
|
+
#
|
|
256
|
+
# The `! -samefile` exclusions are load-bearing and asymmetric with the meta
|
|
257
|
+
# reap: INPUT and results_dir are created BEFORE this reap (meta_dir is
|
|
258
|
+
# created after), so this run's own live scratch is otherwise a candidate —
|
|
259
|
+
# a positional INPUT can carry an mtime far older than any floor (a stale
|
|
260
|
+
# file is a legitimate scan target); results_dir's mtime is refreshed by
|
|
261
|
+
# aggregation writes right before this reap, so its exclusion covers only
|
|
262
|
+
# stalls/suspension between creation and this point — belt-and-suspenders
|
|
263
|
+
# for the same self-reap class. `-samefile` (inode compare), never `-path`
|
|
264
|
+
# (literal/fnmatch string compare): a relative or glob-shaped INPUT spelling
|
|
265
|
+
# defeats string equality and could rm -rf the very file the operator asked
|
|
266
|
+
# to scan. The `[ -e ]` gates skip an exclusion whose referent died or
|
|
267
|
+
# became unstatable mid-scan — a dead -samefile operand would error the
|
|
268
|
+
# whole find (now a warn, not a silent no-op).
|
|
269
|
+
#
|
|
270
|
+
# Residual surfaces, accepted: a PEER's live input named like a family
|
|
271
|
+
# member under TMPDIR is indistinguishable from an orphan by age (do not
|
|
272
|
+
# name scan targets skill-scan-*/sss-write.* inside TMPDIR); a same-uid
|
|
273
|
+
# bind/FUSE mount inside a family-named dir is descended by rm -rf (same-uid
|
|
274
|
+
# blast radius — find's -mount is a no-op at maxdepth 1 and cannot reach
|
|
275
|
+
# rm's own recursion); a family-named symlink entry loses the link, never
|
|
276
|
+
# its target; a find build without -samefile/-mmin (a stripped BusyBox
|
|
277
|
+
# config — both are default-on features upstream — or heirloom) warns and
|
|
278
|
+
# skips rather than sweeping; an unreachable base canonicalizes to empty
|
|
279
|
+
# and skips silently (nothing reapable there anyway).
|
|
280
|
+
_excl=()
|
|
281
|
+
[ -e "$INPUT" ] && _excl+=("!" -samefile "$INPUT")
|
|
282
|
+
[ -e "$results_dir" ] && _excl+=("!" -samefile "$results_dir")
|
|
283
|
+
tmp_root="$(cd -P "${TMPDIR:-/tmp}" 2>/dev/null && pwd -P || true)"
|
|
284
|
+
if [ -n "$tmp_root" ]; then
|
|
285
|
+
# cd -P resolves a symlinked base (macOS /tmp -> private/tmp) — find under
|
|
286
|
+
# default -P does not descend a symlinked startpoint, so without
|
|
287
|
+
# canonicalization the sweep silently no-ops there.
|
|
288
|
+
find "$tmp_root" -mindepth 1 -maxdepth 1 -user "$(id -u)" \
|
|
289
|
+
-mmin "+${_reap_min}" \
|
|
290
|
+
\( -name 'skill-security-scan-*' -o -name 'skill-scan-*' -o -name 'sss-write.*.err' \) \
|
|
291
|
+
${_excl[@]+"${_excl[@]}"} \
|
|
292
|
+
-exec rm -rf {} + 2>/dev/null \
|
|
293
|
+
|| echo "run-scan: scratch reap failed; orphans retained" >&2
|
|
294
|
+
fi
|
|
295
|
+
|
|
296
|
+
(umask 077; mkdir -p "$meta_base/skill-security-scan-$$")
|
|
297
|
+
meta_dir="$meta_base/skill-security-scan-$$"
|
|
298
|
+
meta_path="$meta_dir/.scan-meta.json"
|
|
299
|
+
jq -n \
|
|
300
|
+
--arg sv "$SCANNER_VERSION" \
|
|
301
|
+
--arg rpv "$rule_pack_version" \
|
|
302
|
+
--arg sha "$rule_pack_sha" \
|
|
303
|
+
--arg v "$agg_verdict" \
|
|
304
|
+
--arg ts "$ts" \
|
|
305
|
+
--rawfile fs "$summary_file" \
|
|
306
|
+
'{scanner_version: $sv, rule_pack_version: $rpv, rule_pack_sha256: $sha, verdict: $v, timestamp: $ts, findings_summary: ($fs | fromjson)}' \
|
|
307
|
+
> "$meta_path"
|
|
308
|
+
|
|
309
|
+
# Emit markdown findings table + mandatory disclaimer.
|
|
310
|
+
echo "# skill-security-scan verdict: $agg_verdict"
|
|
311
|
+
echo ""
|
|
312
|
+
echo "| Category | Verdict | Findings |"
|
|
313
|
+
echo "|---|---|---|"
|
|
314
|
+
for f in "$results_dir"/*.json; do
|
|
315
|
+
cat="$(jq -r '.category' "$f")"
|
|
316
|
+
v="$(jq -r '.verdict' "$f")"
|
|
317
|
+
n="$(jq -r '.findings | length' "$f")"
|
|
318
|
+
echo "| $cat | $v | $n |"
|
|
319
|
+
done
|
|
320
|
+
echo ""
|
|
321
|
+
echo "Per-finding details (operator-facing, unredacted):"
|
|
322
|
+
echo ""
|
|
323
|
+
for f in "$results_dir"/*.json; do
|
|
324
|
+
v="$(jq -r '.verdict' "$f")"
|
|
325
|
+
if [ "$v" != "LOW-RISK" ]; then
|
|
326
|
+
cat="$(jq -r '.category' "$f")"
|
|
327
|
+
echo "## $cat ($v)"
|
|
328
|
+
echo ""
|
|
329
|
+
jq -r '.findings[] | "- **\(.rule_id)** (\(.severity)) line \(.line): `\(.snippet)`"' "$f"
|
|
330
|
+
echo ""
|
|
331
|
+
fi
|
|
332
|
+
done
|
|
333
|
+
echo ".scan-meta.json written to: $meta_path"
|
|
334
|
+
echo ""
|
|
335
|
+
cat <<EOF
|
|
336
|
+
---
|
|
337
|
+
Advisory static analysis only. LOW-RISK does not constitute a security audit,
|
|
338
|
+
certification, or warranty of safety. The skill executes in your environment
|
|
339
|
+
under your account; you remain responsible for review.
|
|
340
|
+
|
|
341
|
+
Scanner version: $SCANNER_VERSION Rule pack: ${rule_pack_sha:0:12} Scanned: $ts
|
|
342
|
+
EOF
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Fail-loud self-test for skill-security-scan.
|
|
3
|
+
#
|
|
4
|
+
# Iterates references/test-fixtures/{malicious-*,clean-*}.skill.md and asserts
|
|
5
|
+
# deterministic verdicts:
|
|
6
|
+
# - malicious-*.skill.md → HIGH-RISK
|
|
7
|
+
# - clean-*.skill.md → LOW-RISK
|
|
8
|
+
#
|
|
9
|
+
# Exits 1 with diagnostic if any false-negative or false-positive is observed.
|
|
10
|
+
# Wired into CI per .github/workflows/skill-security-scan-corpus.yml.
|
|
11
|
+
#
|
|
12
|
+
# Flags:
|
|
13
|
+
# --regenerate-manifest recompute manifest SHAs from current rule-file
|
|
14
|
+
# contents BEFORE running fixtures. Used during
|
|
15
|
+
# rule-pack development. CI rejects this flag when
|
|
16
|
+
# env CI=true (per plan SpecFlow Gap 4).
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
22
|
+
FIXTURES="$SKILL_DIR/references/test-fixtures"
|
|
23
|
+
MANIFEST="$SKILL_DIR/references/rules/manifest.yaml"
|
|
24
|
+
|
|
25
|
+
REGENERATE=0
|
|
26
|
+
if [ "${1:-}" = "--regenerate-manifest" ]; then
|
|
27
|
+
if [ "${CI:-false}" = "true" ]; then
|
|
28
|
+
echo "ERROR: --regenerate-manifest is rejected in CI (CI=true). See SpecFlow Gap 4." >&2
|
|
29
|
+
exit 2
|
|
30
|
+
fi
|
|
31
|
+
REGENERATE=1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [ "$REGENERATE" = "1" ]; then
|
|
35
|
+
echo "regenerating manifest SHAs..." >&2
|
|
36
|
+
tmp_manifest="$(mktemp)"
|
|
37
|
+
# Owning trap (ADR-129): mv consumes the file on success (rm -f then no-ops);
|
|
38
|
+
# the trap covers the awk/mv failure window.
|
|
39
|
+
trap 'rm -f "$tmp_manifest"' EXIT
|
|
40
|
+
awk -v skill_dir="$SKILL_DIR/references" '
|
|
41
|
+
/^[[:space:]]*-[[:space:]]*path:/ {
|
|
42
|
+
path = $0
|
|
43
|
+
sub(/^[[:space:]]*-[[:space:]]*path:[[:space:]]*/, "", path)
|
|
44
|
+
gsub(/[[:space:]]*$/, "", path)
|
|
45
|
+
print
|
|
46
|
+
cmd = "sha256sum \"" skill_dir "/" path "\" | cut -d\" \" -f1"
|
|
47
|
+
cmd | getline sha
|
|
48
|
+
close(cmd)
|
|
49
|
+
print " sha256: " sha
|
|
50
|
+
next
|
|
51
|
+
}
|
|
52
|
+
/^[[:space:]]+sha256:/ { next }
|
|
53
|
+
{ print }
|
|
54
|
+
' "$MANIFEST" > "$tmp_manifest"
|
|
55
|
+
mv "$tmp_manifest" "$MANIFEST"
|
|
56
|
+
echo "manifest updated. commit it alongside the rule-pack edits." >&2
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
failures=0
|
|
60
|
+
|
|
61
|
+
# Test malicious fixtures: must be HIGH-RISK.
|
|
62
|
+
for fx in "$FIXTURES"/malicious-*.skill.md; do
|
|
63
|
+
[ -f "$fx" ] || continue
|
|
64
|
+
fx_name="$(basename "$fx")"
|
|
65
|
+
out="$(bash "$SCRIPT_DIR/run-scan.sh" < "$fx" 2>/dev/null || echo "")"
|
|
66
|
+
verdict="$(echo "$out" | head -1 | grep -oE 'HIGH-RISK|REVIEW|LOW-RISK' || echo "UNKNOWN")"
|
|
67
|
+
if [ "$verdict" != "HIGH-RISK" ]; then
|
|
68
|
+
echo "FAIL: $fx_name expected HIGH-RISK, got $verdict" >&2
|
|
69
|
+
failures=$((failures + 1))
|
|
70
|
+
else
|
|
71
|
+
echo "ok: $fx_name → HIGH-RISK" >&2
|
|
72
|
+
fi
|
|
73
|
+
done
|
|
74
|
+
|
|
75
|
+
# Test clean fixtures: must be LOW-RISK.
|
|
76
|
+
for fx in "$FIXTURES"/clean-*.skill.md; do
|
|
77
|
+
[ -f "$fx" ] || continue
|
|
78
|
+
fx_name="$(basename "$fx")"
|
|
79
|
+
out="$(SKILL_SECURITY_SCAN_OFFLINE=1 bash "$SCRIPT_DIR/run-scan.sh" < "$fx" 2>/dev/null || echo "")"
|
|
80
|
+
verdict="$(echo "$out" | head -1 | grep -oE 'HIGH-RISK|REVIEW|LOW-RISK' || echo "UNKNOWN")"
|
|
81
|
+
if [ "$verdict" != "LOW-RISK" ]; then
|
|
82
|
+
echo "FAIL: $fx_name expected LOW-RISK, got $verdict" >&2
|
|
83
|
+
failures=$((failures + 1))
|
|
84
|
+
else
|
|
85
|
+
echo "ok: $fx_name → LOW-RISK" >&2
|
|
86
|
+
fi
|
|
87
|
+
done
|
|
88
|
+
|
|
89
|
+
if [ "$failures" -gt 0 ]; then
|
|
90
|
+
echo "self-test FAILED: $failures fixture(s) returned wrong verdict" >&2
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
echo "self-test PASSED: all fixtures returned expected verdicts" >&2
|
|
95
|
+
exit 0
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Argv-ceiling regression for skill-security-scan (#6736).
|
|
3
|
+
#
|
|
4
|
+
# WHAT THIS GUARDS. Two sites used to bind an unbounded payload as ONE argv argument:
|
|
5
|
+
# - scripts/lib.sh emit_result() `--argjson f "$findings_json"` (per category)
|
|
6
|
+
# - scripts/run-scan.sh `--argjson fs "$findings_summary"` (all five)
|
|
7
|
+
# The kernel caps a SINGLE argv argument at MAX_ARG_STRLEN = 131,072 B -- bisected on this
|
|
8
|
+
# host: 131,071 B passes, 131,072 B fails E2BIG. That is NOT `getconf ARG_MAX` (2,097,152 B
|
|
9
|
+
# here); a payload at 6% of ARG_MAX still dies. Both now use stdin / `--rawfile`, which is
|
|
10
|
+
# file-or-pipe I/O and has no per-argument limit.
|
|
11
|
+
#
|
|
12
|
+
# WHY THIS IS THE UNBOUNDED ONE. apply_yaml_rules caps each snippet at 200 chars, so it
|
|
13
|
+
# LOOKS bounded -- but nothing caps the FINDING COUNT: one grep hit per matching line, over
|
|
14
|
+
# a SKILL.md of any length. At ~265 B/finding the ceiling lands near 490 findings, and this
|
|
15
|
+
# repo already ships a 220,523 B SKILL.md.
|
|
16
|
+
#
|
|
17
|
+
# THE FAILURE WAS SILENT, which is why the behavioural assertions below check CONTENT and
|
|
18
|
+
# not just the exit code. run-scan.sh invokes each category as
|
|
19
|
+
# `bash check-*.sh … || echo '{"…check-failed…"}'`, so an E2BIG inside a category script is
|
|
20
|
+
# swallowed into a "category script error" placeholder: the scan exits 0 and reports a
|
|
21
|
+
# REVIEW verdict with ZERO real findings instead of the hundreds it actually found. An
|
|
22
|
+
# exit-code-only test passes straight through that.
|
|
23
|
+
#
|
|
24
|
+
# FIXTURE ADEQUACY. The fixture is SYNTHESIZED (cq-test-fixtures-synthesized-only) -- it is
|
|
25
|
+
# generated here, never copied from a real skill. It is also PRODUCTION-SHAPED: each line is
|
|
26
|
+
# long enough to fill the 200-char snippet window, because BYTES PER FINDING is the
|
|
27
|
+
# load-bearing parameter, not finding count. Short matching lines would yield ~70 B findings,
|
|
28
|
+
# so even thousands of them would stay under the ceiling and PASS ON UNMODIFIED CODE.
|
|
29
|
+
|
|
30
|
+
set -uo pipefail
|
|
31
|
+
|
|
32
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
|
+
SCRIPTS="$SCRIPT_DIR/../scripts"
|
|
34
|
+
CHECK_FS="$SCRIPTS/check-filesystem-boundary.sh"
|
|
35
|
+
RUN_SCAN="$SCRIPTS/run-scan.sh"
|
|
36
|
+
|
|
37
|
+
# Named at every use, never bare.
|
|
38
|
+
MAX_ARG_STRLEN=131072
|
|
39
|
+
|
|
40
|
+
PASS=0
|
|
41
|
+
FAIL=0
|
|
42
|
+
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
|
|
43
|
+
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
|
|
44
|
+
|
|
45
|
+
command -v jq >/dev/null 2>&1 || { echo "SKIP: jq missing"; exit 0; }
|
|
46
|
+
[[ -f "$CHECK_FS" ]] || { echo "ERROR: not found: $CHECK_FS" >&2; exit 1; }
|
|
47
|
+
|
|
48
|
+
WORK="$(mktemp -d)"
|
|
49
|
+
trap 'rm -rf "$WORK"' EXIT
|
|
50
|
+
export SKILL_SECURITY_SCAN_OFFLINE=1
|
|
51
|
+
|
|
52
|
+
echo "TEST: skill-security-scan argv ceiling (#6736)"
|
|
53
|
+
|
|
54
|
+
# --- Synthesized, production-shaped fixture ---------------------------------------------
|
|
55
|
+
# Each line trips filesystem-boundary's `path-traversal-absolute` rule (a quote followed by
|
|
56
|
+
# /etc/) and is padded past 200 chars so the captured snippet fills its cap. Nothing here is
|
|
57
|
+
# copied from a real SKILL.md.
|
|
58
|
+
FIXTURE="$WORK/synth.skill.md"
|
|
59
|
+
ROWS=900
|
|
60
|
+
{
|
|
61
|
+
printf '# Synthesized fixture skill\n\n'
|
|
62
|
+
for i in $(seq 1 "$ROWS"); do
|
|
63
|
+
printf 'Line %04d config path "/etc/synthesized-fixture-%04d/a-deliberately-long-configuration-path-segment-that-fills-the-two-hundred-character-snippet-window-so-that-bytes-per-finding-not-finding-count-is-what-drives-this-fixture-over-the-ceiling"\n' "$i" "$i"
|
|
64
|
+
done
|
|
65
|
+
} > "$FIXTURE"
|
|
66
|
+
|
|
67
|
+
# --- Generator cardinality --------------------------------------------------------------
|
|
68
|
+
gen_rows="$(grep -c '^Line [0-9]' "$FIXTURE")"
|
|
69
|
+
if [[ "$gen_rows" -eq "$ROWS" ]]; then
|
|
70
|
+
pass "fixture generator emitted $gen_rows matching lines (want $ROWS)"
|
|
71
|
+
else
|
|
72
|
+
fail "fixture generator emitted $gen_rows lines (want $ROWS) -- asserts below would be vacuous"
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# --- Category level: emit_result must survive a >ceiling findings array ------------------
|
|
76
|
+
cat_out="$(bash "$CHECK_FS" < "$FIXTURE" 2>"$WORK/cat_err.txt")"
|
|
77
|
+
cat_rc=$?
|
|
78
|
+
if [[ "$cat_rc" -eq 0 ]]; then
|
|
79
|
+
pass "check-filesystem-boundary exits 0 on a >ceiling finding set"
|
|
80
|
+
else
|
|
81
|
+
fail "check-filesystem-boundary exit=$cat_rc -- stderr: $(head -c 200 "$WORK/cat_err.txt")"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# FIXTURE ADEQUACY, asserted IN-SUITE so this cannot silently degrade to vacuous as the
|
|
85
|
+
# rule pack, the snippet cap, or jq's encoding changes.
|
|
86
|
+
findings_bytes="$(printf '%s' "$cat_out" | jq -c '.findings' | wc -c)"
|
|
87
|
+
if [[ "$findings_bytes" -gt "$MAX_ARG_STRLEN" ]]; then
|
|
88
|
+
pass "findings payload is ${findings_bytes} B > MAX_ARG_STRLEN (${MAX_ARG_STRLEN})"
|
|
89
|
+
else
|
|
90
|
+
fail "findings payload is only ${findings_bytes} B -- below MAX_ARG_STRLEN (${MAX_ARG_STRLEN}), this test proves nothing"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Count asserted RELATIONALLY against the source line count, not a literal pin.
|
|
94
|
+
findings_n="$(printf '%s' "$cat_out" | jq '.findings | length')"
|
|
95
|
+
if [[ "$findings_n" -eq "$gen_rows" ]]; then
|
|
96
|
+
pass "findings|length=$findings_n == $gen_rows source lines (no truncation)"
|
|
97
|
+
else
|
|
98
|
+
fail "findings|length=$findings_n != $gen_rows source lines (undercount / truncation)"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# The findings must really carry their rule_id and snippet -- not empty shells.
|
|
102
|
+
real_findings="$(printf '%s' "$cat_out" | jq '[.findings[] | select(.rule_id == "path-traversal-absolute" and (.snippet | length) > 100)] | length')"
|
|
103
|
+
if [[ "$real_findings" -eq "$gen_rows" ]]; then
|
|
104
|
+
pass "all $real_findings findings carry rule_id + a full snippet at >ceiling size"
|
|
105
|
+
else
|
|
106
|
+
fail "only $real_findings of $gen_rows findings carry rule_id + full snippet"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# --- Aggregator level: run-scan must not degrade to the check-failed placeholder ---------
|
|
110
|
+
scan_out="$(bash "$RUN_SCAN" "$FIXTURE" 2>"$WORK/scan_err.txt")"
|
|
111
|
+
scan_rc=$?
|
|
112
|
+
if [[ "$scan_rc" -eq 0 ]]; then
|
|
113
|
+
pass "run-scan.sh exits 0 on a >ceiling finding set"
|
|
114
|
+
else
|
|
115
|
+
fail "run-scan.sh exit=$scan_rc -- stderr: $(head -c 200 "$WORK/scan_err.txt")"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# THE ANTI-SILENT-DEGRADATION ASSERTION. Pre-fix, the E2BIG inside check-filesystem-boundary
|
|
119
|
+
# is swallowed by run-scan's `|| echo '{"…check-failed…"}'` fallback, so the run still exits
|
|
120
|
+
# 0 -- but the filesystem-boundary row is replaced by an "unknown" category carrying a single
|
|
121
|
+
# `check-failed` finding. Asserting on the REAL row is what makes that visible.
|
|
122
|
+
#
|
|
123
|
+
# `grep -c` on a herestring, never `producer | grep -q`: under `set -o pipefail` an early
|
|
124
|
+
# match closes the pipe, the producer takes SIGPIPE (141), and the pipeline reports failure
|
|
125
|
+
# even though grep MATCHED.
|
|
126
|
+
fs_row="$(grep -cE '^\| filesystem-boundary \| (REVIEW|HIGH-RISK) \| [0-9]+ \|' <<<"$scan_out")"
|
|
127
|
+
if [[ "$fs_row" -ge 1 ]]; then
|
|
128
|
+
pass "filesystem-boundary reported as a real category row"
|
|
129
|
+
else
|
|
130
|
+
fail "no real filesystem-boundary row -- the category silently degraded to check-failed"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
reported_n="$(sed -nE 's/^\| filesystem-boundary \| [A-Z-]+ \| ([0-9]+) \|.*/\1/p' <<<"$scan_out" | head -1)"
|
|
134
|
+
if [[ "${reported_n:-0}" -eq "$gen_rows" ]]; then
|
|
135
|
+
pass "run-scan reports all $reported_n findings (== $gen_rows source lines)"
|
|
136
|
+
else
|
|
137
|
+
fail "run-scan reports ${reported_n:-<none>} findings but fixture had $gen_rows -- silent loss"
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
checkfailed="$(grep -c 'check-failed' <<<"$scan_out")"
|
|
141
|
+
if [[ "$checkfailed" -eq 0 ]]; then
|
|
142
|
+
pass "no check-failed placeholder in the report"
|
|
143
|
+
else
|
|
144
|
+
fail "report contains $checkfailed check-failed placeholder(s) -- a category died and was swallowed"
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
if grep -qiE 'argument list too long' "$WORK/cat_err.txt" "$WORK/scan_err.txt"; then
|
|
148
|
+
fail "an E2BIG diagnostic reached stderr -- argv ceiling was hit"
|
|
149
|
+
else
|
|
150
|
+
pass "no 'Argument list too long' diagnostic on stderr"
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# --- Structural: neither site may rebind an unbounded payload onto argv ------------------
|
|
154
|
+
# Anchored on syntax a COMMENT cannot produce. Both files now carry prose mentioning
|
|
155
|
+
# `--argjson`, so a bare-token grep would false-pass on this fix's own documentation
|
|
156
|
+
# (cq-assert-anchor-not-bare-token). `-cE` with a leading `^[^#]*` restricts to code lines.
|
|
157
|
+
lib_argjson="$(grep -cE '^[^#]*--argjson[[:space:]]+f[[:space:]]+"\$findings_json"' "$SCRIPTS/lib.sh")"
|
|
158
|
+
if [[ "$lib_argjson" -eq 0 ]]; then
|
|
159
|
+
pass "lib.sh does not bind \$findings_json via --argjson"
|
|
160
|
+
else
|
|
161
|
+
fail "lib.sh rebinds \$findings_json via --argjson on $lib_argjson code line(s)"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
scan_argjson="$(grep -cE '^[^#]*--argjson[[:space:]]+(fs|b)[[:space:]]+"\$(findings_summary|body_redacted)"' "$RUN_SCAN")"
|
|
165
|
+
if [[ "$scan_argjson" -eq 0 ]]; then
|
|
166
|
+
pass "run-scan.sh does not bind the summary/body via --argjson"
|
|
167
|
+
else
|
|
168
|
+
fail "run-scan.sh rebinds an unbounded payload via --argjson on $scan_argjson code line(s)"
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
# Positive form: the --rawfile binding must actually be present. `--rawfile\s+\w+` is
|
|
172
|
+
# syntax a comment cannot produce in the code position asserted here.
|
|
173
|
+
if grep -qE '^[^#]*--rawfile[[:space:]]+fs[[:space:]]+"\$summary_file"' "$RUN_SCAN"; then
|
|
174
|
+
pass "run-scan.sh binds the summary with --rawfile"
|
|
175
|
+
else
|
|
176
|
+
fail "run-scan.sh no longer binds the summary with --rawfile"
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
echo "=== Results: $PASS passed, $FAIL failed ==="
|
|
180
|
+
[[ "$FAIL" -eq 0 ]]
|