@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,197 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fix-round-seats.sh — the single path→seat map for review fix-commit targeted
|
|
3
|
+
# rounds AND the `none`-tier panel trigger-gating (ADR-267). One map, two
|
|
4
|
+
# consumers, so no second prose predicate table can drift from it.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# fix-round-seats.sh --files <newline-or-comma file list> [--finding-seats <seat,...>]
|
|
8
|
+
#
|
|
9
|
+
# stdout: one seat leaf-name per line, deduped, deterministic order (the
|
|
10
|
+
# never-shed safety floor seats emit first).
|
|
11
|
+
#
|
|
12
|
+
# LEAF→SPAWNABLE-ID MAPPING IS NOT UNIFORM: most review seats resolve to
|
|
13
|
+
# `soleur:engineering:review:<leaf>`, but `git-history-analyzer` lives under
|
|
14
|
+
# `soleur:engineering:research:` and `shellcheck`/`anti-slop`/`gdpr-gate`/
|
|
15
|
+
# `structural-enumeration` are deterministic or SKILL-level seats with no
|
|
16
|
+
# spawnable agent id at all — never mechanically prefix the output.
|
|
17
|
+
#
|
|
18
|
+
# Exit codes:
|
|
19
|
+
# 0 seats emitted (or legitimately none: empty --files, or non-source paths
|
|
20
|
+
# that map to no seat)
|
|
21
|
+
# 2 usage error
|
|
22
|
+
#
|
|
23
|
+
# --finding-seats carries the seats that reported the findings being fixed
|
|
24
|
+
# (from the dedup ledger — see references/risk-tier-and-fix-rounds.md). Every
|
|
25
|
+
# token is validated against the canonical seat registry below; unknown tokens
|
|
26
|
+
# are dropped with an `unknown-seat:` stderr warning and NEVER echoed raw —
|
|
27
|
+
# the input is model-emitted text, and a forged token carrying whitespace or
|
|
28
|
+
# metacharacters must not smuggle an extra output line.
|
|
29
|
+
#
|
|
30
|
+
# Portability: POSIX/bash only — no timeout, sed -i, readlink -f, stat -c,
|
|
31
|
+
# date -d (operator hosts include stock macOS).
|
|
32
|
+
set -uo pipefail
|
|
33
|
+
|
|
34
|
+
usage() {
|
|
35
|
+
cat <<'EOF'
|
|
36
|
+
Usage: fix-round-seats.sh --files <newline-or-comma file list> [--finding-seats <seat,...>]
|
|
37
|
+
|
|
38
|
+
Prints the review seats a fix-commit diff should re-spawn, one per line:
|
|
39
|
+
{path-mapped seats} ∪ {--finding-seats} ∪ {conditional seats}. A source-touching
|
|
40
|
+
fix never resolves empty — unmatched source files emit the code-quality-analyst
|
|
41
|
+
floor. An empty --files list emits nothing plus a `note: empty fix diff` stderr
|
|
42
|
+
line (a zero-change round legitimately spawns zero seats).
|
|
43
|
+
|
|
44
|
+
Exit 0 on valid input; exit 2 on usage error.
|
|
45
|
+
EOF
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Canonical seat registry (leaf names). Registry order IS the emission order —
|
|
49
|
+
# the never-shed floor seats come first. The parity guard
|
|
50
|
+
# plugins/soleur/test/review-tier-parity.test.ts pins this set against
|
|
51
|
+
# review.workflow.js DIMENSIONS/agentType — extend both, never one.
|
|
52
|
+
SEAT_REGISTRY='security-sentinel code-quality-analyst git-history-analyzer pattern-recognition-specialist architecture-strategist performance-oracle data-integrity-guardian agent-native-reviewer user-impact-reviewer data-migration-expert deployment-verification-agent code-simplicity-reviewer kieran-rails-reviewer dhh-rails-reviewer test-design-reviewer structural-enumeration semgrep-sast shellcheck anti-slop gdpr-gate'
|
|
53
|
+
|
|
54
|
+
# --finding-seats vocabulary: callers may report seats by workflow DIMENSION
|
|
55
|
+
# key or canonical agent id; both normalize to the leaf name here.
|
|
56
|
+
dim_to_leaf() {
|
|
57
|
+
case "$1" in
|
|
58
|
+
security) echo security-sentinel ;;
|
|
59
|
+
git-history) echo git-history-analyzer ;;
|
|
60
|
+
pattern) echo pattern-recognition-specialist ;;
|
|
61
|
+
architecture) echo architecture-strategist ;;
|
|
62
|
+
performance) echo performance-oracle ;;
|
|
63
|
+
data-integrity) echo data-integrity-guardian ;;
|
|
64
|
+
agent-native) echo agent-native-reviewer ;;
|
|
65
|
+
code-quality) echo code-quality-analyst ;;
|
|
66
|
+
user-impact) echo user-impact-reviewer ;;
|
|
67
|
+
data-migration) echo data-migration-expert ;;
|
|
68
|
+
deploy-verify) echo deployment-verification-agent ;;
|
|
69
|
+
code-simplicity) echo code-simplicity-reviewer ;;
|
|
70
|
+
rails-kieran) echo kieran-rails-reviewer ;;
|
|
71
|
+
rails-dhh) echo dhh-rails-reviewer ;;
|
|
72
|
+
test-design) echo test-design-reviewer ;;
|
|
73
|
+
semgrep) echo semgrep-sast ;;
|
|
74
|
+
gdpr) echo gdpr-gate ;;
|
|
75
|
+
*) echo "$1" ;;
|
|
76
|
+
esac
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Byte-identical mirror of preflight Check 6 Step 6.1's SENSITIVE_PATH_RE (the
|
|
80
|
+
# canonical literal lives in plugins/soleur/skills/preflight/SKILL.md). The
|
|
81
|
+
# parity test pins this copy against the canonical one — edit together or not
|
|
82
|
+
# at all.
|
|
83
|
+
SENSITIVE_PATH_RE='^(apps/web-platform/(server|supabase|app/api|middleware\.ts$)|apps/web-platform/lib/(stripe|auth|byok|security-headers|csp|log-sanitize|safe-session|safe-return-to|supabase)|apps/web-platform/lib/(legal|auth)/|apps/[^/]+/infra/|.+/doppler[^/]*\.(yml|yaml|sh)$|\.github/workflows/.*(doppler|secret|token|deploy|release|version-bump|web-platform|infra-validation|cla|cf-token|linkedin-token).*\.ya?ml$)'
|
|
84
|
+
|
|
85
|
+
# Byte-identical mirror of the gdpr-gate canonical path regex (source of truth:
|
|
86
|
+
# plugins/soleur/skills/gdpr-gate/SKILL.md `## Path globs (canonical)`).
|
|
87
|
+
GDPR_PATH_RE='^(apps/web-platform/supabase/migrations/|apps/web-platform/lib/auth/|apps/web-platform/server/.*auth.*\.(ts|tsx|js)|apps/web-platform/app/api/.*\.(ts|tsx)$|.*\.sql$)'
|
|
88
|
+
|
|
89
|
+
SOURCE_RE='\.(ts|tsx|js|jsx|rb|py|go|rs|swift|kt|java|c|cpp|cs|php|sh|bash|zsh|mjs|cjs)$'
|
|
90
|
+
MIGRATION_RE='(/migrations/|/migrate/|\.sql$)'
|
|
91
|
+
PERSIST_RE='(apps/web-platform/(server|supabase|lib)/)'
|
|
92
|
+
PERF_RE='(apps/web-platform/(server|supabase)/|inngest|cron|queue|worker|bench|perf)'
|
|
93
|
+
AGENT_SURFACE_RE='(apps/web-platform/(app|components)/|plugins/soleur/(agents|skills|commands|docs)/)'
|
|
94
|
+
TEST_RE='(\.test\.|\.spec\.|_test\.|_spec\.|(^|/)test_[^/]*\.py$|__tests__/|(^|/)tests?/|(^|/)spec/|Tests\.swift$|\.e2e\.[jt]sx?$|(^|/)e2e/|\.cy\.)'
|
|
95
|
+
SHELL_RE='\.(sh|bash|zsh)$'
|
|
96
|
+
ANTISLOP_RE='(apps/web-platform/(app|components)/.*\.(tsx|jsx|css)$|apps/web-platform/server/.*\.(ts|tsx)$|plugins/soleur/docs/.*\.(njk|css)$)'
|
|
97
|
+
|
|
98
|
+
FILES_SEEN=""
|
|
99
|
+
FILES_GIVEN=0
|
|
100
|
+
FINDING_SEATS=""
|
|
101
|
+
while [[ $# -gt 0 ]]; do
|
|
102
|
+
case "$1" in
|
|
103
|
+
--files)
|
|
104
|
+
[[ $# -ge 2 ]] || { echo "fix-round-seats: --files needs a value" >&2; exit 2; }
|
|
105
|
+
FILES_SEEN="$2"; FILES_GIVEN=1; shift 2 ;;
|
|
106
|
+
--finding-seats)
|
|
107
|
+
[[ $# -ge 2 ]] || { echo "fix-round-seats: --finding-seats needs a value" >&2; exit 2; }
|
|
108
|
+
FINDING_SEATS="$2"; shift 2 ;;
|
|
109
|
+
-h|--help) usage; exit 0 ;;
|
|
110
|
+
*) echo "fix-round-seats: unknown argument '$1'" >&2; exit 2 ;;
|
|
111
|
+
esac
|
|
112
|
+
done
|
|
113
|
+
[[ "$FILES_GIVEN" -eq 1 ]] || { usage >&2; exit 2; }
|
|
114
|
+
|
|
115
|
+
if [[ -z "$FILES_SEEN" ]]; then
|
|
116
|
+
echo "note: empty fix diff" >&2
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
# Emit at most once per seat: newline-ANCHORED membership, never substring —
|
|
120
|
+
# a future seat name that is a substring of another must not dedup-fail.
|
|
121
|
+
SEATS=$'\n'
|
|
122
|
+
add() { case "$SEATS" in *$'\n'"$1"$'\n'*) ;; *) SEATS="${SEATS}${1}"$'\n' ;; esac; }
|
|
123
|
+
has() { case "$SEATS" in *$'\n'"$1"$'\n'*) return 0 ;; *) return 1 ;; esac; }
|
|
124
|
+
|
|
125
|
+
floor_needed=0
|
|
126
|
+
UNMAPPED=""
|
|
127
|
+
# Split on newlines AND commas. The while loop is heredoc-fed (not piped) so it
|
|
128
|
+
# does NOT run in a subshell — SEATS/floor_needed/UNMAPPED survive it.
|
|
129
|
+
while IFS= read -r f; do
|
|
130
|
+
f="${f%$'\r'}"
|
|
131
|
+
f="${f#"${f%%[![:space:]]*}"}" # leading whitespace
|
|
132
|
+
f="${f%"${f##*[![:space:]]}"}" # trailing whitespace
|
|
133
|
+
f="${f#\"}"; f="${f%\"}" # quote-path wrapping (spaces/non-ASCII in git --name-only)
|
|
134
|
+
[[ -n "$f" ]] || continue
|
|
135
|
+
area=0
|
|
136
|
+
if grep -qE "$MIGRATION_RE" <<<"$f"; then
|
|
137
|
+
add data-integrity-guardian; add data-migration-expert; add deployment-verification-agent
|
|
138
|
+
area=1
|
|
139
|
+
fi
|
|
140
|
+
if grep -qE "$PERSIST_RE" <<<"$f"; then add data-integrity-guardian; area=1; fi
|
|
141
|
+
if grep -qE "$SENSITIVE_PATH_RE" <<<"$f"; then add security-sentinel; area=1; fi
|
|
142
|
+
if grep -qE "$GDPR_PATH_RE" <<<"$f"; then add gdpr-gate; area=1; fi
|
|
143
|
+
if grep -qE "$ANTISLOP_RE" <<<"$f"; then add anti-slop; area=1; fi
|
|
144
|
+
if grep -qE "$AGENT_SURFACE_RE" <<<"$f"; then add agent-native-reviewer; area=1; fi
|
|
145
|
+
if grep -qE "$PERF_RE" <<<"$f"; then add performance-oracle; area=1; fi
|
|
146
|
+
if grep -qE "$TEST_RE" <<<"$f"; then add test-design-reviewer; area=1; fi
|
|
147
|
+
if grep -qE "$SHELL_RE" <<<"$f"; then
|
|
148
|
+
add shellcheck
|
|
149
|
+
elif grep -qE "$SOURCE_RE" <<<"$f"; then
|
|
150
|
+
add semgrep-sast
|
|
151
|
+
fi
|
|
152
|
+
if grep -qE "$SOURCE_RE" <<<"$f"; then
|
|
153
|
+
# The floor guards "a source fix with no judgment seat". Deterministic
|
|
154
|
+
# seats (semgrep/shellcheck) do NOT satisfy it — they are scanners, not
|
|
155
|
+
# reviewers; only an area arm (a judgment seat) exempts the floor.
|
|
156
|
+
[[ "$area" -eq 1 ]] || { floor_needed=1; UNMAPPED="${UNMAPPED}${UNMAPPED:+,}${f}"; }
|
|
157
|
+
fi
|
|
158
|
+
done <<EOF_FILES
|
|
159
|
+
$(printf '%s\n' "$FILES_SEEN" | tr ',' '\n')
|
|
160
|
+
EOF_FILES
|
|
161
|
+
|
|
162
|
+
if [[ "$floor_needed" -eq 1 ]]; then
|
|
163
|
+
add code-quality-analyst
|
|
164
|
+
printf 'unmapped-paths: %s\n' "$UNMAPPED" >&2
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# --finding-seats: normalized (canonical `soleur:…:leaf` ids and workflow
|
|
168
|
+
# dimension keys both reduce to leaf names), then validated against the
|
|
169
|
+
# registry; unknown tokens are dropped with a sanitized stderr warning and
|
|
170
|
+
# never echoed raw to stdout. `set -f` kills pathname expansion, so a forged
|
|
171
|
+
# `*`/`?`/glob token cannot expand into cwd filenames mid-validation.
|
|
172
|
+
_ctx_lib="$(cd "${BASH_SOURCE[0]%/*}/../../../scripts/lib" 2>/dev/null && pwd -P)/context-sanitize.sh"
|
|
173
|
+
_ctx_lib="${_ctx_lib:-/nonexistent/context-sanitize.sh}"
|
|
174
|
+
# shellcheck source=/dev/null
|
|
175
|
+
[[ -r "$_ctx_lib" ]] && . "$_ctx_lib" || true
|
|
176
|
+
# Ambient-locale [:cntrl:] on purpose — mirrors technical-ruling-gate.sh: a C-pinned
|
|
177
|
+
# fallback could strip less than the pre-change site under UTF-8 locales (C1 range).
|
|
178
|
+
declare -F soleur_ctx_sanitize >/dev/null 2>&1 \
|
|
179
|
+
|| soleur_ctx_sanitize() { tr -d '[:cntrl:]'; }
|
|
180
|
+
if [[ -n "$FINDING_SEATS" ]]; then
|
|
181
|
+
set -f
|
|
182
|
+
for tok in $(printf '%s' "$FINDING_SEATS" | tr ',' ' '); do
|
|
183
|
+
tok="$(dim_to_leaf "${tok##*:}")"
|
|
184
|
+
for s in $SEAT_REGISTRY; do
|
|
185
|
+
if [[ "$tok" == "$s" ]]; then add "$tok"; continue 2; fi
|
|
186
|
+
done
|
|
187
|
+
printf 'unknown-seat: %s\n' "$(printf '%s' "$tok" | soleur_ctx_sanitize)" >&2
|
|
188
|
+
done
|
|
189
|
+
set +f
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
# Emit in registry order (floor seats first), deduped.
|
|
193
|
+
for s in $SEAT_REGISTRY; do
|
|
194
|
+
if has "$s"; then printf '%s\n' "$s"; fi
|
|
195
|
+
done
|
|
196
|
+
exit 0
|
|
197
|
+
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Tests for emit-review-trailer.sh's coverage field (#7066 follow-up).
|
|
4
|
+
#
|
|
5
|
+
# WHY THIS SUITE EXISTS. The script's whole value is that a downstream consumer can tell a
|
|
6
|
+
# full review from a degraded one. Every way that can silently stop being true looks like
|
|
7
|
+
# success: a value that does not parse as a trailer is invisible to `git log
|
|
8
|
+
# --format='%(trailers:...)'` while reading fine to a human; an absent measurement defaulting
|
|
9
|
+
# to the strongest value makes the field decorative; and a caller-supplied `--mode full`
|
|
10
|
+
# alongside 2-of-10 counts overclaims in the one direction that matters.
|
|
11
|
+
#
|
|
12
|
+
# EVERY ARM RUNS AGAINST A THROWAWAY REPO, never the real one — the script COMMITS, so a
|
|
13
|
+
# suite that ran in-tree would leave empty commits on whatever branch invoked it.
|
|
14
|
+
set -uo pipefail
|
|
15
|
+
export TMPDIR="${TMPDIR:-/var/tmp}"
|
|
16
|
+
|
|
17
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
18
|
+
# ../scripts/ — this suite deliberately lives in skills/review/test/ and not beside the SUT
|
|
19
|
+
# in skills/review/scripts/, because scripts/test-all.sh discovers
|
|
20
|
+
# `plugins/soleur/skills/*/test/*.test.sh` and NOT `skills/*/scripts/*.test.sh`. Placed next
|
|
21
|
+
# to the SUT it would be silent AND green: never run, never red (#3366).
|
|
22
|
+
SUT="$(cd "${DIR}/../scripts" && pwd)/emit-review-trailer.sh"
|
|
23
|
+
|
|
24
|
+
# assert_fixture_dir — the operand guard for the fixture repos below
|
|
25
|
+
# (fixture-dir-operand-assert.test.sh scans this file).
|
|
26
|
+
# shellcheck source=../../../test/test-helpers.sh
|
|
27
|
+
source "${DIR}/../../../test/test-helpers.sh" || { echo "FATAL: test-helpers.sh" >&2; exit 2; }
|
|
28
|
+
set +e # the helper sets -e; restore this suite's verdict-counting contract
|
|
29
|
+
|
|
30
|
+
TMP="$(mktemp -d -t emitrt.XXXXXXXX)" || { echo "mktemp failed" >&2; exit 2; }
|
|
31
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
32
|
+
|
|
33
|
+
passes=0
|
|
34
|
+
fails=0
|
|
35
|
+
# The INDEPENDENT case counter (ADR-193 #2). It moves in assert() — the ASSERTION helper —
|
|
36
|
+
# and NEVER in pass()/fail(), the VERDICT helpers. That split is the whole point: a counter
|
|
37
|
+
# incremented inside the verdict helpers moves WITH the verdict, so stubbing fail() drops the
|
|
38
|
+
# row and its count together and the conservation identity below holds under the exact fault
|
|
39
|
+
# it exists to catch. Never increment this inside `$( )`; a subshell discards it.
|
|
40
|
+
CASES=0
|
|
41
|
+
|
|
42
|
+
# VERDICT helpers — they own passes/fails and nothing else.
|
|
43
|
+
pass() { passes=$((passes + 1)); printf ' ok %s\n' "$1"; }
|
|
44
|
+
fail() {
|
|
45
|
+
fails=$((fails + 1))
|
|
46
|
+
printf ' FAIL %s\n' "$1"
|
|
47
|
+
[[ -n "${2:-}" ]] && printf ' %s\n' "$2"
|
|
48
|
+
return 0
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# ASSERTION helper — owns CASES. $1 = description, $2 = condition (eval'd), $3 = failure detail.
|
|
52
|
+
assert() {
|
|
53
|
+
CASES=$((CASES + 1))
|
|
54
|
+
if eval "$2"; then
|
|
55
|
+
pass "$1"
|
|
56
|
+
else
|
|
57
|
+
fail "$1" "${3:-$2}"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
printf '\n=== emit-review-trailer coverage field ===\n\n'
|
|
62
|
+
|
|
63
|
+
# Reported DIRECTLY, not through fail(): with the SUT absent there is nothing to assert, so a
|
|
64
|
+
# verdict-helper report here would be a row in a suite that never ran.
|
|
65
|
+
[[ -f "$SUT" ]] || {
|
|
66
|
+
printf '\n[FATAL] SUT missing at %s — nothing to test.\n' "$SUT" >&2
|
|
67
|
+
exit 1
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# A fresh repo on a feature branch with a `main` to scope against. The script refuses to run
|
|
71
|
+
# on main/master, and its idempotence check scopes to `origin/main..HEAD`-equivalent, so both
|
|
72
|
+
# refs have to exist for the arms below to exercise the real paths.
|
|
73
|
+
new_repo() {
|
|
74
|
+
local d="$TMP/$1"; mkdir -p "$d"
|
|
75
|
+
git -C "$d" init -q -b main
|
|
76
|
+
# LOCAL config, not `-c` on our own commits. The SUT runs its OWN `git commit`, so an
|
|
77
|
+
# identity supplied only via `-c` on the fixture's setup commits does not reach it — it
|
|
78
|
+
# inherits whatever the ambient environment has. On a developer laptop that is the global
|
|
79
|
+
# config and every arm passes; on a bare CI runner there is none and the SUT dies with
|
|
80
|
+
# "Please tell me who you are", which surfaces as `git commit failed` and 8 of 12 arms red.
|
|
81
|
+
# Measured: this suite was 12/12 locally and 4/8 in CI on its first run (#7070).
|
|
82
|
+
git -C "$d" config user.email soleur-test@example.invalid
|
|
83
|
+
git -C "$d" config user.name "Soleur Test"
|
|
84
|
+
# Some runners set commit.gpgsign globally; a throwaway repo has no key.
|
|
85
|
+
git -C "$d" config commit.gpgsign false
|
|
86
|
+
git -C "$d" commit -q --allow-empty -m "base"
|
|
87
|
+
git -C "$d" checkout -q -b feat-x
|
|
88
|
+
printf '%s' "$d"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
coverage_of() { # $1 = repo dir -> the parsed Reviewed-Coverage trailer value
|
|
92
|
+
git -C "$1" log -1 --format='%(trailers:key=Reviewed-Coverage,valueonly)' | tr -d '\n'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# ── ARM 1: full coverage ──────────────────────────────────────────────────────────
|
|
96
|
+
d="$(new_repo full)"
|
|
97
|
+
out="$(cd "$d" && bash "$SUT" --findings 0 --agents-ran 9 --agents-expected 9 2>&1)"; rc=$?
|
|
98
|
+
assert "full coverage exits 0" '[[ "$rc" -eq 0 ]]' "rc=$rc out=$out"
|
|
99
|
+
cov="$(coverage_of "$d")"
|
|
100
|
+
assert "records 'full 9/9 agents'" '[[ "$cov" == *"full 9/9 agents"* ]]' "got: '$cov'"
|
|
101
|
+
|
|
102
|
+
# ── ARM 2: degraded coverage, with the missing agents NAMED ───────────────────────
|
|
103
|
+
#
|
|
104
|
+
# This is the shape measured on PR #7066 (7 of 9 died on 529s). The named list is the part a
|
|
105
|
+
# reader needs: "2/9" says how much ran, not WHICH lens is absent, and the agents that die
|
|
106
|
+
# are not the ones you needed least.
|
|
107
|
+
d="$(new_repo degraded)"
|
|
108
|
+
out="$(cd "$d" && bash "$SUT" --findings 3 --agents-ran 2 --agents-expected 9 \
|
|
109
|
+
--agents-missing security-sentinel,test-design-reviewer 2>&1)"; rc=$?
|
|
110
|
+
cov="$(coverage_of "$d")"
|
|
111
|
+
assert "records 'degraded 2/9 agents'" \
|
|
112
|
+
'[[ "$rc" -eq 0 && "$cov" == *"degraded 2/9 agents"* ]]' "rc=$rc got: '$cov'"
|
|
113
|
+
assert "names the missing agents in the trailer value" \
|
|
114
|
+
'[[ "$cov" == *"security-sentinel"* && "$cov" == *"test-design-reviewer"* ]]' "got: '$cov'"
|
|
115
|
+
|
|
116
|
+
# ── ARM 3: zero agents => inline-fallback ─────────────────────────────────────────
|
|
117
|
+
d="$(new_repo zero)"
|
|
118
|
+
(cd "$d" && bash "$SUT" --findings 1 --agents-ran 0 --agents-expected 8 >/dev/null 2>&1)
|
|
119
|
+
cov="$(coverage_of "$d")"
|
|
120
|
+
assert "zero agents records 'inline-fallback'" \
|
|
121
|
+
'[[ "$cov" == *"inline-fallback 0/8 agents"* ]]' "got: '$cov'"
|
|
122
|
+
|
|
123
|
+
# ── ARM 4: THE COUNTS OVERRIDE A CALLER'S LABEL ───────────────────────────────────
|
|
124
|
+
#
|
|
125
|
+
# A caller passing `--mode full` with 2-of-10 counts is either confused or overclaiming.
|
|
126
|
+
# Deriving the mode from the counts is what makes the field non-forgeable by accident.
|
|
127
|
+
d="$(new_repo overclaim)"
|
|
128
|
+
(cd "$d" && bash "$SUT" --agents-ran 2 --agents-expected 10 --mode full >/dev/null 2>&1)
|
|
129
|
+
cov="$(coverage_of "$d")"
|
|
130
|
+
assert "counts override an overclaiming --mode full" \
|
|
131
|
+
'[[ "$cov" == *degraded* && "$cov" != *full* ]]' "got: '$cov'"
|
|
132
|
+
|
|
133
|
+
# ── ARM 5: ABSENT measurement is 'unknown', NOT 'full' ────────────────────────────
|
|
134
|
+
#
|
|
135
|
+
# The load-bearing default. Every legacy call site omits the flags, so defaulting an absent
|
|
136
|
+
# measurement to the strongest value would make the field decorative on exactly the calls
|
|
137
|
+
# that predate it — and would read as a full review having run.
|
|
138
|
+
d="$(new_repo legacy)"
|
|
139
|
+
(cd "$d" && bash "$SUT" --findings 0 >/dev/null 2>&1)
|
|
140
|
+
cov="$(coverage_of "$d")"
|
|
141
|
+
assert "absent measurement records 'unknown', not 'full'" '[[ "$cov" == "unknown" ]]' "got: '$cov'"
|
|
142
|
+
|
|
143
|
+
# ── ARM 6: the coverage trailer PARSES (it is last, so it splits first) ───────────
|
|
144
|
+
#
|
|
145
|
+
# git needs the whole final paragraph to be `Key: value` lines. Reviewed-Coverage sits LAST,
|
|
146
|
+
# so it is the first casualty of a split — and a value that does not parse is invisible to
|
|
147
|
+
# every consumer while looking like evidence in `git log`.
|
|
148
|
+
d="$(new_repo parse)"
|
|
149
|
+
(cd "$d" && bash "$SUT" --agents-ran 4 --agents-expected 4 >/dev/null 2>&1)
|
|
150
|
+
cov="$(coverage_of "$d")"
|
|
151
|
+
# shellcheck disable=SC2034 # consumed via `eval "$condition"` in assert()
|
|
152
|
+
by="$(git -C "$d" log -1 --format='%(trailers:key=Reviewed-By-Soleur,valueonly)' | tr -d '[:space:]')"
|
|
153
|
+
assert "both Reviewed-By-Soleur and Reviewed-Coverage parse as trailers" \
|
|
154
|
+
'[[ -n "$cov" && -n "$by" ]]' "$(git -C "$d" log -1 --format=%B)"
|
|
155
|
+
|
|
156
|
+
# ── ARM 7: malformed input is REFUSED before any commit ───────────────────────────
|
|
157
|
+
#
|
|
158
|
+
# A bad count must not land in main's permanent history as an unparseable coverage claim.
|
|
159
|
+
# Asserting "no commit was created" is the load-bearing half: exiting 2 while having already
|
|
160
|
+
# committed would be strictly worse than accepting the value.
|
|
161
|
+
for bad in "--agents-ran abc --agents-expected 5" \
|
|
162
|
+
"--agents-ran 5 --agents-expected 2" \
|
|
163
|
+
"--mode enthusiastic"; do
|
|
164
|
+
d="$(new_repo "bad$(echo "$bad" | tr -cd 'a-z0-9')")"
|
|
165
|
+
: "${d:?fixture dir is empty; git -C <empty> would retarget this write}"
|
|
166
|
+
before="$(git -C "$d" rev-parse HEAD)"
|
|
167
|
+
# shellcheck disable=SC2086
|
|
168
|
+
out="$(cd "$d" && bash "$SUT" $bad 2>&1)"; rc=$?
|
|
169
|
+
after="$(git -C "$d" rev-parse HEAD)"
|
|
170
|
+
# CASES moves here, once per loop iteration, because assert() is called once per iteration —
|
|
171
|
+
# the counter has to track the arms that actually run, not the arms written in the source.
|
|
172
|
+
assert "refuses '$bad' with no commit" '[[ "$rc" -eq 2 && "$before" == "$after" ]]' \
|
|
173
|
+
"rc=$rc committed=$([[ "$before" != "$after" ]] && echo yes || echo no) out=$out"
|
|
174
|
+
done
|
|
175
|
+
|
|
176
|
+
# ── ARM 9: sequential-fallback SURVIVES the count derivation ────────────────────
|
|
177
|
+
#
|
|
178
|
+
# sequential-fallback is not a count axis — it attests the plugin subagent
|
|
179
|
+
# surface was absent (Devin Cloud) and the roles ran sequentially inline. A
|
|
180
|
+
# cloud review that ran all N roles sequentially passes N/N; letting the
|
|
181
|
+
# derivation "upgrade" that to `full` would emit a trailer claiming
|
|
182
|
+
# independent-agent coverage that never ran, and the /ship gate (which keys on
|
|
183
|
+
# the sequential-fallback PREFIX) would never fire. The explicit mode must win.
|
|
184
|
+
d="$(new_repo seqfallback)"
|
|
185
|
+
out="$(cd "$d" && bash "$SUT" --agents-ran 9 --agents-expected 9 \
|
|
186
|
+
--mode sequential-fallback 2>&1)"; rc=$?
|
|
187
|
+
cov="$(coverage_of "$d")"
|
|
188
|
+
assert "explicit sequential-fallback + N/N counts is NOT upgraded to full" \
|
|
189
|
+
'[[ "$rc" -eq 0 && "$cov" == sequential-fallback* && "$cov" == *"9/9 agents"* ]]' \
|
|
190
|
+
"rc=$rc got: '$cov'"
|
|
191
|
+
assert "ship-gate prefix still matches (starts-with sequential-fallback)" \
|
|
192
|
+
'[[ "$cov" == sequential-fallback* ]]' "got: '$cov'"
|
|
193
|
+
|
|
194
|
+
d="$(new_repo seqfallback_partial)"
|
|
195
|
+
out="$(cd "$d" && bash "$SUT" --agents-ran 5 --agents-expected 9 \
|
|
196
|
+
--mode sequential-fallback 2>&1)"; rc=$?
|
|
197
|
+
cov="$(coverage_of "$d")"
|
|
198
|
+
assert "explicit sequential-fallback + partial counts is NOT rewritten to degraded" \
|
|
199
|
+
'[[ "$rc" -eq 0 && "$cov" == sequential-fallback* && "$cov" == *"5/9 agents"* ]]' \
|
|
200
|
+
"rc=$rc got: '$cov'"
|
|
201
|
+
|
|
202
|
+
# ── ARM 8: still refuses to run on main ──────────────────────────────────────────
|
|
203
|
+
# Guards against the coverage plumbing having disturbed the pre-existing branch guard.
|
|
204
|
+
d="$(new_repo onmain)"
|
|
205
|
+
: "${d:?fixture dir is empty; git -C <empty> would retarget this write}"
|
|
206
|
+
git -C "$d" checkout -q main
|
|
207
|
+
out="$(cd "$d" && bash "$SUT" --agents-ran 1 --agents-expected 1 2>&1)"; rc=$?
|
|
208
|
+
assert "still skips on main (pre-existing guard intact)" \
|
|
209
|
+
'[[ "$rc" -eq 0 && "$out" == *"nothing to mark, skipping"* ]]' "rc=$rc out=$out"
|
|
210
|
+
|
|
211
|
+
# ── Guard 2 (ADR-267): --risk-tier emits Reviewed-Risk-Tier from the resolved enum only ──
|
|
212
|
+
tier_of() { # $1 = repo dir -> the parsed Reviewed-Risk-Tier trailer value
|
|
213
|
+
git -C "$1" log -1 --format='%(trailers:key=Reviewed-Risk-Tier,valueonly)' | tr -d '\n'
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# Every resolved-tier value produces a trailer that PARSES — a value that does not parse is
|
|
217
|
+
# invisible to `git log --format=%(trailers:...)` while looking like evidence to a human.
|
|
218
|
+
for tier in "none" "single-user incident" "aggregate pattern"; do
|
|
219
|
+
d="$(new_repo "tier$(printf '%s' "$tier" | tr -cd 'a-z0-9')")"
|
|
220
|
+
: "${d:?fixture dir is empty; git -C <empty> would retarget this write}"
|
|
221
|
+
out="$(cd "$d" && bash "$SUT" --risk-tier "$tier" 2>&1)"; rc=$?
|
|
222
|
+
t="$(tier_of "$d")"
|
|
223
|
+
assert "--risk-tier '$tier' emits a parseable trailer" \
|
|
224
|
+
'[[ "$rc" -eq 0 && "$t" == "$tier" ]]' "rc=$rc parsed='$t' out=$out"
|
|
225
|
+
done
|
|
226
|
+
|
|
227
|
+
# `undeclared` is a classifier parse state, never a resolved tier — rejected like any other
|
|
228
|
+
# invalid value, BEFORE any commit exists to carry it.
|
|
229
|
+
for bad in "bogus" "undeclared" "Full"; do
|
|
230
|
+
d="$(new_repo "badtier$(printf '%s' "$bad" | tr -cd 'a-z0-9')")"
|
|
231
|
+
: "${d:?fixture dir is empty; git -C <empty> would retarget this write}"
|
|
232
|
+
before="$(git -C "$d" rev-parse HEAD)"
|
|
233
|
+
out="$(cd "$d" && bash "$SUT" --risk-tier "$bad" 2>&1)"; rc=$?
|
|
234
|
+
after="$(git -C "$d" rev-parse HEAD)"
|
|
235
|
+
assert "--risk-tier '$bad' refused, no commit" \
|
|
236
|
+
'[[ "$rc" -eq 2 && "$before" == "$after" ]]' \
|
|
237
|
+
"rc=$rc committed=$([[ "$before" != "$after" ]] && echo yes || echo no) out=$out"
|
|
238
|
+
done
|
|
239
|
+
|
|
240
|
+
# Absent flag → absent field. A fabricated `unknown` literal would be a claim the caller
|
|
241
|
+
# never measured (same honesty rule as Reviewed-Coverage's 'unknown').
|
|
242
|
+
d="$(new_repo notier)"
|
|
243
|
+
(cd "$d" && bash "$SUT" --findings 0 >/dev/null 2>&1)
|
|
244
|
+
t="$(tier_of "$d")"
|
|
245
|
+
assert "no --risk-tier → field absent, not 'unknown'" '[[ -z "$t" ]]' "parsed='$t'"
|
|
246
|
+
|
|
247
|
+
# Coverage must remain the LAST trailer line — it is the first casualty of a
|
|
248
|
+
# split trailers paragraph, and RISK_TIER_LINE now interpolates above it.
|
|
249
|
+
d="$(new_repo lastline)"
|
|
250
|
+
(cd "$d" && bash "$SUT" --risk-tier none --agents-ran 3 --agents-expected 3 >/dev/null 2>&1)
|
|
251
|
+
last="$(git -C "$d" log -1 --format=%B | git interpret-trailers --parse | tail -1)"
|
|
252
|
+
assert "Reviewed-Coverage stays the last trailer line" \
|
|
253
|
+
'[[ "$last" == "Reviewed-Coverage:"* ]]' "last='$last'"
|
|
254
|
+
|
|
255
|
+
# ── Guard 3 (ADR-267): --fix-round emits fix-scoped keys, never Reviewed-Coverage ──
|
|
256
|
+
#
|
|
257
|
+
# The whole point of the separate keys: a targeted round covering `full` over the
|
|
258
|
+
# fix range would misread as branch-level coverage on ship's gate, and the main
|
|
259
|
+
# trailer's idempotence skip would swallow the emission anyway.
|
|
260
|
+
|
|
261
|
+
# --fix-round requires --since; --since requires --fix-round — an orphaned flag is a
|
|
262
|
+
# scope error, not a default to the whole branch.
|
|
263
|
+
for bad in "--fix-round" "--since HEAD"; do
|
|
264
|
+
d="$(new_repo "frbad$(printf '%s' "$bad" | tr -cd 'a-z0-9')")"
|
|
265
|
+
: "${d:?fixture dir is empty; git -C <empty> would retarget this write}"
|
|
266
|
+
before="$(git -C "$d" rev-parse HEAD)"
|
|
267
|
+
out="$(cd "$d" && bash "$SUT" $bad 2>&1)"; rc=$?
|
|
268
|
+
after="$(git -C "$d" rev-parse HEAD)"
|
|
269
|
+
assert "refuses '$bad' with no commit" \
|
|
270
|
+
'[[ "$rc" -eq 2 && "$before" == "$after" ]]' \
|
|
271
|
+
"rc=$rc committed=$([[ "$before" != "$after" ]] && echo yes || echo no) out=$out"
|
|
272
|
+
done
|
|
273
|
+
|
|
274
|
+
# --since must resolve to a commit — an unresolvable sha cannot land in a range trailer.
|
|
275
|
+
d="$(new_repo frbadsha)"
|
|
276
|
+
before="$(git -C "$d" rev-parse HEAD)"
|
|
277
|
+
out="$(cd "$d" && bash "$SUT" --fix-round --since 'not-a-sha' 2>&1)"; rc=$?
|
|
278
|
+
after="$(git -C "$d" rev-parse HEAD)"
|
|
279
|
+
assert "--fix-round --since <unresolvable> refused, no commit" \
|
|
280
|
+
'[[ "$rc" -eq 2 && "$before" == "$after" ]]' "rc=$rc out=$out"
|
|
281
|
+
|
|
282
|
+
# A resolvable-but-not-ancestor --since (stale post-rebase sha) must refuse —
|
|
283
|
+
# otherwise the recorded range spans unrelated history.
|
|
284
|
+
d="$(new_repo frnonancestor)"
|
|
285
|
+
assert_fixture_dir "$d"
|
|
286
|
+
git -C "$d" checkout -qb sideline main
|
|
287
|
+
git -C "$d" commit -q --allow-empty -m "work not on this branch"
|
|
288
|
+
stale="$(git -C "$d" rev-parse HEAD)"
|
|
289
|
+
git -C "$d" checkout -q feat-x
|
|
290
|
+
before="$(git -C "$d" rev-parse HEAD)"
|
|
291
|
+
out="$(cd "$d" && bash "$SUT" --fix-round --since "$stale" 2>&1)"; rc=$?
|
|
292
|
+
after="$(git -C "$d" rev-parse HEAD)"
|
|
293
|
+
assert "--fix-round --since <non-ancestor> refused, no commit" \
|
|
294
|
+
'[[ "$rc" -eq 2 && "$out" == *"not an ancestor"* && "$before" == "$after" ]]' "rc=$rc out=$out"
|
|
295
|
+
|
|
296
|
+
# The load-bearing arm: branch already carries the MAIN trailer (the normal
|
|
297
|
+
# post-panel state) — a fix round must still emit, with the fix keys, WITHOUT a
|
|
298
|
+
# second Reviewed-Coverage claim.
|
|
299
|
+
d="$(new_repo frhappy)"
|
|
300
|
+
base="$(git -C "$d" rev-parse HEAD)"
|
|
301
|
+
(cd "$d" && bash "$SUT" --agents-ran 7 --agents-expected 7 >/dev/null 2>&1) # main-panel trailer
|
|
302
|
+
out="$(cd "$d" && bash "$SUT" --fix-round --since "$base" --agents-ran 3 --agents-expected 3 \
|
|
303
|
+
--risk-tier none 2>&1)"; rc=$?
|
|
304
|
+
fr="$(git -C "$d" log -1 --format='%(trailers:key=Reviewed-Fix-Round,valueonly)' | tr -d '\n')"
|
|
305
|
+
rng="$(git -C "$d" log -1 --format='%(trailers:key=Reviewed-Fix-Range,valueonly)' | tr -d '\n')"
|
|
306
|
+
cov2="$(coverage_of "$d")"
|
|
307
|
+
by2="$(git -C "$d" log -1 --format='%(trailers:key=Reviewed-By-Soleur,valueonly)' | tr -d '\n')"
|
|
308
|
+
t2="$(tier_of "$d")"
|
|
309
|
+
assert "fix round emits after main trailer (not swallowed by idempotence)" \
|
|
310
|
+
'[[ "$rc" -eq 0 && "$fr" == *"3/3"* ]]' "rc=$rc fr='$fr' out=$out"
|
|
311
|
+
assert "fix round records the range and carries NO Reviewed-Coverage" \
|
|
312
|
+
'[[ "$rng" == "$base"..* && -z "$cov2" ]]' "rng='$rng' cov='$cov2'"
|
|
313
|
+
assert "fix round does not re-emit Reviewed-By-Soleur" \
|
|
314
|
+
'[[ -z "$by2" ]]' "by='$by2'"
|
|
315
|
+
assert "fix round still records the risk tier" \
|
|
316
|
+
'[[ "$t2" == "none" ]]' "t='$t2'"
|
|
317
|
+
|
|
318
|
+
# Same range twice → idempotent skip (the range is the dedup key, not the branch).
|
|
319
|
+
out="$(cd "$d" && bash "$SUT" --fix-round --since "$base" --agents-ran 3 --agents-expected 3 2>&1)"; rc=$?
|
|
320
|
+
n_commits="$(git -C "$d" rev-list --count main..feat-x)"
|
|
321
|
+
assert "repeat fix round over the same range skips" \
|
|
322
|
+
'[[ "$rc" -eq 0 && "$out" == *"already exists"* && "$n_commits" -eq 2 ]]' \
|
|
323
|
+
"rc=$rc commits=$n_commits out=$out"
|
|
324
|
+
|
|
325
|
+
# A SECOND round after more fix commits is a different range — the left edge
|
|
326
|
+
# alone must not suppress it (idempotence keys on the full since..head).
|
|
327
|
+
assert_fixture_dir "$d"
|
|
328
|
+
git -C "$d" commit -q --allow-empty -m "fix: second round commit"
|
|
329
|
+
out="$(cd "$d" && bash "$SUT" --fix-round --since "$base" --agents-ran 1 --agents-expected 1 2>&1)"; rc=$?
|
|
330
|
+
fr2="$(git -C "$d" log -1 --format='%(trailers:key=Reviewed-Fix-Range,valueonly)' | tr -d '\n')"
|
|
331
|
+
assert "second round over an extended range still emits" \
|
|
332
|
+
'[[ "$rc" -eq 0 && "$fr2" == "$base"..* ]]' "rc=$rc range='$fr2' out=$out"
|
|
333
|
+
|
|
334
|
+
# A `review:`-subjected FIX commit is a real fix (SKILL.md's own convention),
|
|
335
|
+
# not an attestation — it must extend the effective range, not be excluded.
|
|
336
|
+
assert_fixture_dir "$d"
|
|
337
|
+
git -C "$d" commit -q --allow-empty -m "review: fix finding (P2)"
|
|
338
|
+
out="$(cd "$d" && bash "$SUT" --fix-round --since "$base" --agents-ran 2 --agents-expected 2 2>&1)"; rc=$?
|
|
339
|
+
fr3="$(git -C "$d" log -1 --format='%(trailers:key=Reviewed-Fix-Range,valueonly)' | tr -d '\n')"
|
|
340
|
+
fixsha="$(git -C "$d" rev-parse 'HEAD^')"
|
|
341
|
+
assert "a review:-subjected fix commit extends the range (not excluded)" \
|
|
342
|
+
'[[ "$rc" -eq 0 && "$fr3" == "$base".."$fixsha" ]]' "rc=$rc range='$fr3' want-end=$fixsha out=$out"
|
|
343
|
+
|
|
344
|
+
# ── Accounting conservation (ADR-193 #3) ─────────────────────────────────────────
|
|
345
|
+
# Ordered BEFORE the floor per ADR-193 #4: a neutered fail() deflates the verdict counts, so
|
|
346
|
+
# a floor reading them would ALSO trip and would report the misleading "arms were deleted".
|
|
347
|
+
# This says "a verdict was discarded" instead. Reported with printf >&2 + exit 1 DIRECTLY,
|
|
348
|
+
# never through pass()/fail(): a check that reports by calling a verdict helper increments the
|
|
349
|
+
# very counter the exit status reads, so neutering the helper silences the rows AND the check
|
|
350
|
+
# meant to notice the silence. The literal `[FATAL] accounting` is load-bearing —
|
|
351
|
+
# guard-vacuity-floor's ARM 10 builds its conservation population by grepping that string.
|
|
352
|
+
if [[ $((passes + fails)) -ne "$CASES" ]]; then
|
|
353
|
+
printf '\n[FATAL] accounting: passes+fails (%d) != CASES (%d).\n' \
|
|
354
|
+
"$((passes + fails))" "$CASES" >&2
|
|
355
|
+
if [[ $((passes + fails)) -lt "$CASES" ]]; then
|
|
356
|
+
printf ' An assertion was counted but its verdict was discarded — that is what a neutered pass()/fail() looks like.\n' >&2
|
|
357
|
+
else
|
|
358
|
+
printf ' A verdict was recorded at a call site with no `CASES=$((CASES + 1))` before it. This is a harness bug, not a product failure: add the increment at that call site.\n' >&2
|
|
359
|
+
fi
|
|
360
|
+
printf '\n=== emit-review-trailer coverage: %d passed, %d failed (%d assertions) ===\n\n' \
|
|
361
|
+
"$passes" "$fails" "$CASES"
|
|
362
|
+
exit 1
|
|
363
|
+
fi
|
|
364
|
+
|
|
365
|
+
# ── Anti-vacuity floor (ADR-193 #1) ──────────────────────────────────────────────
|
|
366
|
+
# Reads the INDEPENDENT case counter, and reports with printf >&2 + exit 1 DIRECTLY. It
|
|
367
|
+
# previously read `passes + fails` and reported via `fails=$((fails + 1))` — a tautology on
|
|
368
|
+
# both counts: the operand moved WITH the verdict, and the report went into a counter that a
|
|
369
|
+
# neutered fail() had already stopped feeding. Stub the assertion machinery and the suite
|
|
370
|
+
# printed a clean total and exited 0.
|
|
371
|
+
#
|
|
372
|
+
# A floor, not equality: developer-incremented, so `-eq` would redden the suite on every added
|
|
373
|
+
# arm. Ratchet when adding arms; read a floor failure on an otherwise-green run as "you added
|
|
374
|
+
# assertions, update this number".
|
|
375
|
+
TRAILER_MIN_ASSERTIONS=34
|
|
376
|
+
if (( CASES < TRAILER_MIN_ASSERTIONS )); then
|
|
377
|
+
printf '\n[FATAL] anti-vacuity floor: only %d assertion(s) ran, expected >= %d.\n' \
|
|
378
|
+
"$CASES" "$TRAILER_MIN_ASSERTIONS" >&2
|
|
379
|
+
printf ' Arms were deleted or skipped; a green run here would be a coverage loss.\n' >&2
|
|
380
|
+
printf '\n=== emit-review-trailer coverage: %d passed, %d failed (%d assertions) ===\n\n' \
|
|
381
|
+
"$passes" "$fails" "$CASES"
|
|
382
|
+
exit 1
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
printf '\n=== emit-review-trailer coverage: %d passed, %d failed (%d assertions) ===\n\n' \
|
|
386
|
+
"$passes" "$fails" "$CASES"
|
|
387
|
+
[[ "$fails" -eq 0 ]]
|