@soleur/opencode 0.0.0-stage → 3.354.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +660 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +29 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +361 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +171 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +818 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +411 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +509 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +115 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +165 -0
- package/scripts/sync-opencode-adapter.ts +498 -0
- package/scripts/sync-pr-behind.sh +647 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +67 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +143 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +120 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +670 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +331 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +141 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1620 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-evidence-comment.md +36 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3023 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/cleanup-merged-archival.md +39 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/delegated-act-authoring-form.md +7 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/epic-close-sweep.md +62 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +179 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/verification-scaffold/SKILL.md +73 -0
- package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
- package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
- package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
- package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
- package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
- package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
- package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
- package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
- package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
- package/skills/verification-scaffold/references/guards.tsv +21 -0
- package/skills/verification-scaffold/references/verification-readme.template +55 -0
- package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
- package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
- package/skills/verification-scaffold/test/generator.test.sh +319 -0
- package/skills/verification-scaffold/test/manifest.test.sh +144 -0
- package/skills/work/SKILL.md +1480 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// eval-gate.cjs — thin orchestrator for the validation-gated classifier-skill-edit loop.
|
|
3
|
+
//
|
|
4
|
+
// The verdict MATH lives in verdict.cjs (pure); this file only does I/O: resolve the
|
|
5
|
+
// gated-skills registry, extract current+candidate blocks, project them into skill-arm
|
|
6
|
+
// prompts, shell promptfoo SKILL-ARM ONLY (current vs candidate — the baseline control
|
|
7
|
+
// arm is irrelevant to a regression gate), normalize promptfoo JSON into the shape
|
|
8
|
+
// verdict.cjs expects, and print the verdict. FAIL-CLOSED: any error => non-zero exit +
|
|
9
|
+
// stderr and the verdict defaults to NOT accept.
|
|
10
|
+
//
|
|
11
|
+
// Flags:
|
|
12
|
+
// --check <file> Lookup-only: print {gated, target, block_id} for whether
|
|
13
|
+
// <file> is a gated source. Exit 0. NO API.
|
|
14
|
+
// --target <id> Gated target id (go-routing | ticket-triage).
|
|
15
|
+
// --candidate-file <path> The edited source file holding the candidate block.
|
|
16
|
+
// --target-task <json|path> The synthesized row whose candidate samples must pass.
|
|
17
|
+
// --repeat N Samples per cell (default 5).
|
|
18
|
+
// --append-on-accept On accept, append the (synthesized-only) target task to
|
|
19
|
+
// tasks/<target>.jsonl.
|
|
20
|
+
// --dry-run Print the skill-arm-only API-call estimate; exit. NO API.
|
|
21
|
+
"use strict";
|
|
22
|
+
|
|
23
|
+
const fs = require("node:fs");
|
|
24
|
+
const os = require("node:os");
|
|
25
|
+
const path = require("node:path");
|
|
26
|
+
const { execFileSync } = require("node:child_process");
|
|
27
|
+
const { extractBlock } = require("./extract-block.cjs");
|
|
28
|
+
const { renderSkillPrompt, tokensFor } = require("./gen-skill-prompt.cjs");
|
|
29
|
+
const { computeVerdict } = require("./verdict.cjs");
|
|
30
|
+
|
|
31
|
+
const SKILL_DIR = path.resolve(__dirname, "..");
|
|
32
|
+
const REPO_ROOT = path.resolve(SKILL_DIR, "..", "..", "..", "..");
|
|
33
|
+
const REGISTRY = path.join(SKILL_DIR, "gated-skills.json");
|
|
34
|
+
const MODELS_FILE = path.join(SKILL_DIR, "models.generated.json");
|
|
35
|
+
|
|
36
|
+
// Per-target promptfoo resources (enum SSOT does NOT follow the target id, so it is
|
|
37
|
+
// listed explicitly). Corpus tasks file follows tasks/<target>.jsonl by convention.
|
|
38
|
+
const TARGET_RESOURCES = {
|
|
39
|
+
"go-routing": { tasks: "tasks/go-routing.jsonl", enumPath: "enums/go-routes.json" },
|
|
40
|
+
"ticket-triage": { tasks: "tasks/ticket-triage.jsonl", enumPath: "enums/triage-levels.json" },
|
|
41
|
+
"lane-inference": { tasks: "tasks/lane-inference.jsonl", enumPath: "enums/lane.json" },
|
|
42
|
+
"incident-threshold": { tasks: "tasks/incident-threshold.jsonl", enumPath: "enums/incident-threshold.json" },
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function die(message, payload) {
|
|
46
|
+
process.stderr.write(`eval-gate: ${message}\n`);
|
|
47
|
+
// Fail-closed: surface a NOT-accept verdict to any JSON consumer.
|
|
48
|
+
process.stdout.write(JSON.stringify(Object.assign({ accept: false, error: message }, payload || {})) + "\n");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function loadRegistry() {
|
|
53
|
+
return JSON.parse(fs.readFileSync(REGISTRY, "utf8"));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parseArgs(argv) {
|
|
57
|
+
const args = { repeat: 5, appendOnAccept: false, dryRun: false };
|
|
58
|
+
for (let i = 0; i < argv.length; i++) {
|
|
59
|
+
const a = argv[i];
|
|
60
|
+
switch (a) {
|
|
61
|
+
case "--check": args.check = argv[++i]; break;
|
|
62
|
+
case "--target": args.target = argv[++i]; break;
|
|
63
|
+
case "--candidate-file": args.candidateFile = argv[++i]; break;
|
|
64
|
+
case "--target-task": args.targetTask = argv[++i]; break;
|
|
65
|
+
case "--repeat": args.repeat = parseInt(argv[++i], 10); break;
|
|
66
|
+
case "--append-on-accept": args.appendOnAccept = true; break;
|
|
67
|
+
case "--dry-run": args.dryRun = true; break;
|
|
68
|
+
default:
|
|
69
|
+
process.stderr.write(`eval-gate: unknown flag ${a}\n`);
|
|
70
|
+
process.exit(2);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Fix 5: a non-positive / non-integer --repeat would make the dry-run estimate
|
|
74
|
+
// dishonest and send String(NaN) to promptfoo. Fail-closed.
|
|
75
|
+
if (!(Number.isInteger(args.repeat) && args.repeat >= 1)) {
|
|
76
|
+
die("--repeat must be a positive integer");
|
|
77
|
+
}
|
|
78
|
+
return args;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// findBySourceFile(file): the registry entry whose source_file resolves to the same
|
|
82
|
+
// absolute path as `file` (resolved against CWD), or null.
|
|
83
|
+
function findBySourceFile(file) {
|
|
84
|
+
const wanted = path.resolve(process.cwd(), file);
|
|
85
|
+
const wantedRepoRel = path.resolve(REPO_ROOT, file);
|
|
86
|
+
return (
|
|
87
|
+
loadRegistry().find((e) => {
|
|
88
|
+
const abs = path.resolve(REPO_ROOT, e.source_file);
|
|
89
|
+
return abs === wanted || abs === wantedRepoRel;
|
|
90
|
+
}) || null
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function entryForTarget(target) {
|
|
95
|
+
const entry = loadRegistry().find((e) => e.target === target);
|
|
96
|
+
if (!entry) die(`unknown target ${JSON.stringify(target)}`);
|
|
97
|
+
return entry;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function countTasks(target) {
|
|
101
|
+
const res = TARGET_RESOURCES[target];
|
|
102
|
+
if (!res) die(`no promptfoo resources for target ${JSON.stringify(target)}`);
|
|
103
|
+
const text = fs.readFileSync(path.join(SKILL_DIR, res.tasks), "utf8");
|
|
104
|
+
return text.split(/\r?\n/).filter((l) => l.trim() !== "").length;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// --- synthesized-only guard (TR2 / cq-test-fixtures-synthesized-only) ----------
|
|
108
|
+
// Reject inputs that look like real user data / PII. Heuristic, fail-closed.
|
|
109
|
+
function synthesizedCheck(input) {
|
|
110
|
+
const s = String(input);
|
|
111
|
+
const realEmail = /\b[\w.+-]+@(?!example\.|test\.|acme\.)[\w-]+\.[\w.-]+\b/i;
|
|
112
|
+
const cardOrPhone = /\b\d[\d -]{10,}\d\b/;
|
|
113
|
+
const ssn = /\b\d{3}-\d{2}-\d{4}\b/;
|
|
114
|
+
if (realEmail.test(s)) return { ok: false, reason: "input contains a real-looking email address" };
|
|
115
|
+
if (ssn.test(s)) return { ok: false, reason: "input contains an SSN-shaped sequence" };
|
|
116
|
+
if (cardOrPhone.test(s)) return { ok: false, reason: "input contains a card/phone-shaped digit sequence" };
|
|
117
|
+
return { ok: true };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// parsePromptfooOutput(json): normalize promptfoo --output JSON into the verdict shape.
|
|
121
|
+
// task_id = vars.input (the unique per-task key); correct is read from the MEASUREMENT
|
|
122
|
+
// assert (measure-classification.cjs), identified by its "classification-correct" /
|
|
123
|
+
// "classification-incorrect" reason prefix — robust to assert ordering. Fail-closed: a
|
|
124
|
+
// row with no measurement component throws.
|
|
125
|
+
function parsePromptfooOutput(json) {
|
|
126
|
+
const rows = (json && json.results && Array.isArray(json.results.results))
|
|
127
|
+
? json.results.results
|
|
128
|
+
: (Array.isArray(json && json.results) ? json.results : null);
|
|
129
|
+
if (!rows) throw new Error("promptfoo output has no results array");
|
|
130
|
+
return rows.map((r) => {
|
|
131
|
+
const vars = r.vars || (r.testCase && r.testCase.vars) || {};
|
|
132
|
+
const task_id = vars.input;
|
|
133
|
+
if (typeof task_id !== "string") throw new Error("promptfoo result missing vars.input");
|
|
134
|
+
const comps = (r.gradingResult && Array.isArray(r.gradingResult.componentResults))
|
|
135
|
+
? r.gradingResult.componentResults
|
|
136
|
+
: [];
|
|
137
|
+
const measure = comps.find((c) => typeof c.reason === "string" && /^classification-(in)?correct/.test(c.reason));
|
|
138
|
+
if (!measure) throw new Error(`no measurement component for task ${JSON.stringify(task_id)}`);
|
|
139
|
+
return { task_id, correct: /^classification-correct/.test(measure.reason) };
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// runPromptfoo(promptText, target, combinedTasksFile, repeat): SKILL-ARM ONLY run of a
|
|
144
|
+
// single prompt; returns the normalized results array. Thin shell-out.
|
|
145
|
+
function runPromptfoo(promptText, target, combinedTasksFile, repeat) {
|
|
146
|
+
const res = TARGET_RESOURCES[target];
|
|
147
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "eval-gate-"));
|
|
148
|
+
const promptFile = path.join(tmpDir, "skill.txt");
|
|
149
|
+
const configFile = path.join(tmpDir, "config.json");
|
|
150
|
+
const outFile = path.join(tmpDir, "results.json");
|
|
151
|
+
fs.writeFileSync(promptFile, promptText);
|
|
152
|
+
const config = {
|
|
153
|
+
description: `eval-gate skill-arm-only (${target})`,
|
|
154
|
+
providers: `file://${MODELS_FILE}`,
|
|
155
|
+
prompts: [`file://${promptFile}`],
|
|
156
|
+
defaultTest: {
|
|
157
|
+
vars: { enum: `file://${path.join(SKILL_DIR, res.enumPath)}` },
|
|
158
|
+
assert: [
|
|
159
|
+
{ type: "javascript", value: `file://${path.join(SKILL_DIR, "scripts", "measure-classification.cjs")}` },
|
|
160
|
+
{ type: "javascript", value: `file://${path.join(SKILL_DIR, "scripts", "gate-classification.cjs")}` },
|
|
161
|
+
],
|
|
162
|
+
},
|
|
163
|
+
tests: `file://${combinedTasksFile}`,
|
|
164
|
+
};
|
|
165
|
+
fs.writeFileSync(configFile, JSON.stringify(config));
|
|
166
|
+
execFileSync("npx", ["promptfoo", "eval", "-c", configFile, "--repeat", String(repeat), "--output", outFile], {
|
|
167
|
+
cwd: SKILL_DIR,
|
|
168
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
169
|
+
});
|
|
170
|
+
return parsePromptfooOutput(JSON.parse(fs.readFileSync(outFile, "utf8")));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function main() {
|
|
174
|
+
const args = parseArgs(process.argv.slice(2));
|
|
175
|
+
|
|
176
|
+
// --check: lookup-only, NO API.
|
|
177
|
+
if (args.check) {
|
|
178
|
+
const entry = findBySourceFile(args.check);
|
|
179
|
+
process.stdout.write(JSON.stringify({
|
|
180
|
+
gated: Boolean(entry),
|
|
181
|
+
target: entry ? entry.target : null,
|
|
182
|
+
block_id: entry ? entry.block_id : null,
|
|
183
|
+
}) + "\n");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!args.target) die("--target is required (or use --check)");
|
|
188
|
+
|
|
189
|
+
// --dry-run: API-cost disclosure (skill-arm-only), NO API.
|
|
190
|
+
if (args.dryRun) {
|
|
191
|
+
const models = JSON.parse(fs.readFileSync(MODELS_FILE, "utf8")).length;
|
|
192
|
+
const corpus = countTasks(args.target);
|
|
193
|
+
const tasks = corpus + 1; // corpus + the target task
|
|
194
|
+
// Two skill-arm runs (current vs candidate); the baseline control arm is skipped.
|
|
195
|
+
const estimate = 2 * models * tasks * args.repeat;
|
|
196
|
+
process.stdout.write(JSON.stringify({
|
|
197
|
+
dry_run: true,
|
|
198
|
+
target: args.target,
|
|
199
|
+
arms: "skill-only (current vs candidate; baseline control arm skipped)",
|
|
200
|
+
models,
|
|
201
|
+
corpus_tasks: corpus,
|
|
202
|
+
target_tasks: 1,
|
|
203
|
+
repeat: args.repeat,
|
|
204
|
+
estimated_api_calls: estimate,
|
|
205
|
+
formula: "2 (current+candidate) x models x (corpus_tasks + 1) x repeat",
|
|
206
|
+
note: "estimate only — no API call made",
|
|
207
|
+
}) + "\n");
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Real run.
|
|
212
|
+
if (!args.candidateFile) die("--candidate-file is required for a real run");
|
|
213
|
+
|
|
214
|
+
const entry = entryForTarget(args.target);
|
|
215
|
+
let currentBlock, candidateBlock;
|
|
216
|
+
try {
|
|
217
|
+
const currentSource = fs.readFileSync(path.join(REPO_ROOT, entry.source_file), "utf8");
|
|
218
|
+
const candidateSource = fs.readFileSync(args.candidateFile, "utf8");
|
|
219
|
+
currentBlock = extractBlock(currentSource, entry.block_start_marker, entry.block_end_marker);
|
|
220
|
+
candidateBlock = extractBlock(candidateSource, entry.block_start_marker, entry.block_end_marker);
|
|
221
|
+
} catch (err) {
|
|
222
|
+
die(err.message);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Fix 4: an in-place-edited source would make currentBlock === candidateBlock
|
|
226
|
+
// (the candidate IS the live file), masquerading as "no gated-block change". Refuse
|
|
227
|
+
// before the short-circuit — the proposed edit must live at a distinct temp path.
|
|
228
|
+
if (path.resolve(args.candidateFile) === path.resolve(REPO_ROOT, entry.source_file)) {
|
|
229
|
+
die("candidate-file must differ from the live source file (write the proposed edit to a temp path)");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Ungateable no-op: the edit did not change the gated block. Short-circuit BEFORE
|
|
233
|
+
// requiring a target task or spending any API — there is nothing to gate.
|
|
234
|
+
if (currentBlock === candidateBlock) {
|
|
235
|
+
process.stdout.write(JSON.stringify({ accept: true, reason: "no gated-block change" }) + "\n");
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (!args.targetTask) die("--target-task is required for a real run with a changed block");
|
|
240
|
+
|
|
241
|
+
// Parse the target task (inline JSON or a path).
|
|
242
|
+
let targetTaskObj;
|
|
243
|
+
try {
|
|
244
|
+
const raw = fs.existsSync(args.targetTask)
|
|
245
|
+
? fs.readFileSync(args.targetTask, "utf8")
|
|
246
|
+
: args.targetTask;
|
|
247
|
+
targetTaskObj = JSON.parse(raw);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
die(`cannot parse --target-task: ${err.message}`);
|
|
250
|
+
}
|
|
251
|
+
const targetInput = targetTaskObj && targetTaskObj.vars && targetTaskObj.vars.input;
|
|
252
|
+
const targetGolden = targetTaskObj && targetTaskObj.vars && targetTaskObj.vars.golden_label;
|
|
253
|
+
if (typeof targetInput !== "string" || typeof targetGolden !== "string") {
|
|
254
|
+
die("--target-task must be {\"vars\":{\"input\":\"...\",\"golden_label\":\"...\"}}");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Fix 2: synthesized/PII guard runs on the target-task input IMMEDIATELY after parse,
|
|
258
|
+
// BEFORE the combined tasks file is built or any API call is made — a real-data-shaped
|
|
259
|
+
// target task must never reach the LLM providers (fail-closed, before any API spend).
|
|
260
|
+
const synth = synthesizedCheck(targetInput);
|
|
261
|
+
if (!synth.ok) die(`target task is not synthesized: ${synth.reason}`);
|
|
262
|
+
|
|
263
|
+
// Build the combined tasks file: corpus + the target task row.
|
|
264
|
+
const res = TARGET_RESOURCES[args.target];
|
|
265
|
+
const corpusText = fs.readFileSync(path.join(SKILL_DIR, res.tasks), "utf8").replace(/\s*$/, "");
|
|
266
|
+
const combinedDir = fs.mkdtempSync(path.join(os.tmpdir(), "eval-gate-tasks-"));
|
|
267
|
+
const combinedFile = path.join(combinedDir, "combined.jsonl");
|
|
268
|
+
fs.writeFileSync(combinedFile, corpusText + "\n" + JSON.stringify(targetTaskObj) + "\n");
|
|
269
|
+
|
|
270
|
+
const tokens = tokensFor(args.target);
|
|
271
|
+
const currentPrompt = renderSkillPrompt(args.target, currentBlock, tokens);
|
|
272
|
+
const candidatePrompt = renderSkillPrompt(args.target, candidateBlock, tokens);
|
|
273
|
+
|
|
274
|
+
let verdict;
|
|
275
|
+
try {
|
|
276
|
+
const currentResults = runPromptfoo(currentPrompt, args.target, combinedFile, args.repeat);
|
|
277
|
+
const candidateResults = runPromptfoo(candidatePrompt, args.target, combinedFile, args.repeat);
|
|
278
|
+
verdict = computeVerdict(currentResults, candidateResults, { task_id: targetInput }, {});
|
|
279
|
+
} catch (err) {
|
|
280
|
+
die(`gate run failed: ${err.message}`);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// --append-on-accept: on accept, append the synthesized target task to the corpus.
|
|
284
|
+
// Fix 3: the input was already gated as synthesized before the run (Fix 2), so this
|
|
285
|
+
// defensive re-check should never fail. If it ever did, a skipped corpus-write is NOT
|
|
286
|
+
// a gate failure — keep the real verdict (accept reflects the GATE decision) and record
|
|
287
|
+
// append_skipped rather than flipping top-level accept to false.
|
|
288
|
+
if (args.appendOnAccept && verdict.accept) {
|
|
289
|
+
const guard = synthesizedCheck(targetInput);
|
|
290
|
+
if (!guard.ok) {
|
|
291
|
+
verdict.append_skipped = true;
|
|
292
|
+
verdict.append_skipped_reason = guard.reason;
|
|
293
|
+
} else {
|
|
294
|
+
const corpusPath = path.join(SKILL_DIR, res.tasks);
|
|
295
|
+
const existing = fs.readFileSync(corpusPath, "utf8").replace(/\s*$/, "");
|
|
296
|
+
fs.writeFileSync(corpusPath, existing + "\n" + JSON.stringify(targetTaskObj) + "\n");
|
|
297
|
+
verdict.appended_to = res.tasks;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
process.stdout.write(JSON.stringify(verdict) + "\n");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Export the per-target resource map so the registry-coverage consistency test can
|
|
305
|
+
// assert every gated target is wired here (a missing entry ships the gate DORMANT —
|
|
306
|
+
// --check reports gated:true but --target/--dry-run die fail-closed). Requiring this
|
|
307
|
+
// module must NOT run the CLI, hence the require.main guard below.
|
|
308
|
+
module.exports = { TARGET_RESOURCES };
|
|
309
|
+
|
|
310
|
+
// Fix 1: any uncaught throw (registry parse, missing corpus file, mkdtemp, render)
|
|
311
|
+
// must still emit the {accept:false} stdout contract via die(), not just exit non-zero.
|
|
312
|
+
if (require.main === module) {
|
|
313
|
+
try {
|
|
314
|
+
main();
|
|
315
|
+
} catch (e) {
|
|
316
|
+
die(e && e.message ? e.message : String(e));
|
|
317
|
+
}
|
|
318
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// extract-block.cjs — deterministic projection of a gated classifier block.
|
|
3
|
+
//
|
|
4
|
+
// A "gated block" is the span of a source file (e.g. the /go routing table, the
|
|
5
|
+
// ticket-triage P-level rubric) wrapped in HTML-comment sentinels:
|
|
6
|
+
//
|
|
7
|
+
// <!-- eval-gate:block:<block-id>:start -->
|
|
8
|
+
// ...the classifier rules (the SSOT)...
|
|
9
|
+
// <!-- eval-gate:block:<block-id>:end -->
|
|
10
|
+
//
|
|
11
|
+
// This is the mechanical link that makes the eval-harness skill-arm prompt a
|
|
12
|
+
// projection of the production source (NOT a hand-copied paraphrase). It is used
|
|
13
|
+
// (a) to build the skill-arm prompt and (b) to detect whether an edit changed the
|
|
14
|
+
// block at all.
|
|
15
|
+
//
|
|
16
|
+
// Pure / deterministic: extractBlock() takes text in, returns text out, no I/O.
|
|
17
|
+
//
|
|
18
|
+
// CLI: node extract-block.cjs <source-file> <block-id>
|
|
19
|
+
// Prints the text strictly between the markers (exclusive of the marker lines),
|
|
20
|
+
// trimmed. Exits non-zero with a clear stderr message if either marker is missing.
|
|
21
|
+
"use strict";
|
|
22
|
+
|
|
23
|
+
const fs = require("node:fs");
|
|
24
|
+
|
|
25
|
+
// markersFor(blockId): the canonical start/end sentinels for a block id.
|
|
26
|
+
function markersFor(blockId) {
|
|
27
|
+
return {
|
|
28
|
+
start: `<!-- eval-gate:block:${blockId}:start -->`,
|
|
29
|
+
end: `<!-- eval-gate:block:${blockId}:end -->`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// extractBlock(sourceText, startMarker, endMarker): the text strictly between the
|
|
34
|
+
// two markers, trimmed. Throws (fail-closed) if either marker is absent or the end
|
|
35
|
+
// precedes the start.
|
|
36
|
+
function extractBlock(sourceText, startMarker, endMarker) {
|
|
37
|
+
if (typeof sourceText !== "string") {
|
|
38
|
+
throw new TypeError("extractBlock: sourceText must be a string");
|
|
39
|
+
}
|
|
40
|
+
const startIdx = sourceText.indexOf(startMarker);
|
|
41
|
+
if (startIdx === -1) {
|
|
42
|
+
throw new Error(`extract-block: start marker not found: ${startMarker}`);
|
|
43
|
+
}
|
|
44
|
+
const endIdx = sourceText.indexOf(endMarker);
|
|
45
|
+
if (endIdx === -1) {
|
|
46
|
+
throw new Error(`extract-block: end marker not found: ${endMarker}`);
|
|
47
|
+
}
|
|
48
|
+
if (endIdx < startIdx) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`extract-block: end marker ${endMarker} precedes start marker ${startMarker}`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const between = sourceText.slice(startIdx + startMarker.length, endIdx);
|
|
54
|
+
return between.trim();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// extractBlockById(sourceText, blockId): convenience wrapper using the canonical
|
|
58
|
+
// marker convention for a block id.
|
|
59
|
+
function extractBlockById(sourceText, blockId) {
|
|
60
|
+
const { start, end } = markersFor(blockId);
|
|
61
|
+
return extractBlock(sourceText, start, end);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = { extractBlock, extractBlockById, markersFor };
|
|
65
|
+
|
|
66
|
+
if (require.main === module) {
|
|
67
|
+
const [sourceFile, blockId] = process.argv.slice(2);
|
|
68
|
+
if (!sourceFile || !blockId) {
|
|
69
|
+
process.stderr.write(
|
|
70
|
+
"usage: node extract-block.cjs <source-file> <block-id>\n",
|
|
71
|
+
);
|
|
72
|
+
process.exit(2);
|
|
73
|
+
}
|
|
74
|
+
let text;
|
|
75
|
+
try {
|
|
76
|
+
text = fs.readFileSync(sourceFile, "utf8");
|
|
77
|
+
} catch (err) {
|
|
78
|
+
process.stderr.write(`extract-block: cannot read ${sourceFile}: ${err.message}\n`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
process.stdout.write(extractBlockById(text, blockId) + "\n");
|
|
83
|
+
} catch (err) {
|
|
84
|
+
process.stderr.write(`${err.message}\n`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// GATE assert (the ponytail `correctness.js` analog).
|
|
2
|
+
//
|
|
3
|
+
// promptfoo custom JavaScript assert. FAILS when the model's emitted label is NOT
|
|
4
|
+
// a member of the target's closed enum — a malformed or hallucinated label breaks
|
|
5
|
+
// the skill's contract regardless of whether it would have been the "right" answer.
|
|
6
|
+
// This is the deterministic contract check: the output must be a well-formed label.
|
|
7
|
+
//
|
|
8
|
+
// Signature: module.exports = (output, context) => GradingResult
|
|
9
|
+
// context.vars.enum : the closed set of allowed labels — a direct array or a
|
|
10
|
+
// `file://`/relative path to the enum SSOT (promptfoo passes the `file://` ref
|
|
11
|
+
// verbatim, so loadEnum() reads the file itself).
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
const { extractLabel, loadEnum } = require("./parse-label.cjs");
|
|
15
|
+
|
|
16
|
+
module.exports = (output, context) => {
|
|
17
|
+
const vars = (context && context.vars) || {};
|
|
18
|
+
const allowed = loadEnum(vars);
|
|
19
|
+
const got = extractLabel(output, allowed);
|
|
20
|
+
const inEnum = allowed.includes(got);
|
|
21
|
+
return {
|
|
22
|
+
pass: inEnum,
|
|
23
|
+
score: inEnum ? 1.0 : 0.0,
|
|
24
|
+
reason: inEnum
|
|
25
|
+
? `in-enum label: ${got}`
|
|
26
|
+
: `out-of-enum label ${JSON.stringify(got)} — not one of [${allowed.join(", ")}]`,
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Single-source the three current Claude model IDs into models.generated.json.
|
|
3
|
+
#
|
|
4
|
+
# The model IDs live in ONE place — the TypeScript registry under
|
|
5
|
+
# apps/web-platform/server/inngest/. promptfoo YAML cannot import TS, so this
|
|
6
|
+
# generator reads the IDs VERBATIM from the registry and emits a provider list
|
|
7
|
+
# the promptfooconfig-*.yaml files reference via `providers: file://models.generated.json`.
|
|
8
|
+
# No model literal is ever hardcoded in a config-class file, which also keeps the
|
|
9
|
+
# model-launch-review auto-fixer from rewriting a stale literal here.
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
ROOT="$(git -C "$HERE" rev-parse --show-toplevel)"
|
|
14
|
+
CONST="$ROOT/apps/web-platform/server/inngest/leader-prompts/constants.ts"
|
|
15
|
+
TIERS="$ROOT/apps/web-platform/server/inngest/model-tiers.ts"
|
|
16
|
+
OUT="$HERE/../models.generated.json"
|
|
17
|
+
|
|
18
|
+
extract() { # file, exported-const-name -> the claude-* literal
|
|
19
|
+
grep -E "^export const $2" "$1" | grep -oE '"claude-[^"]+"' | tr -d '"' | head -1
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
SONNET="$(extract "$CONST" "SONNET_MODEL")"
|
|
23
|
+
HAIKU="$(extract "$CONST" "HAIKU_MODEL")"
|
|
24
|
+
OPUS="$(extract "$TIERS" "AUDIT_MODEL")"
|
|
25
|
+
|
|
26
|
+
for pair in "SONNET_MODEL:$SONNET" "HAIKU_MODEL:$HAIKU" "AUDIT_MODEL:$OPUS"; do
|
|
27
|
+
if [[ -z "${pair#*:}" ]]; then
|
|
28
|
+
echo "gen-models: failed to read ${pair%%:*} from the registry" >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
done
|
|
32
|
+
|
|
33
|
+
cat > "$OUT" <<EOF
|
|
34
|
+
[
|
|
35
|
+
"anthropic:messages:$OPUS",
|
|
36
|
+
"anthropic:messages:$SONNET",
|
|
37
|
+
"anthropic:messages:$HAIKU"
|
|
38
|
+
]
|
|
39
|
+
EOF
|
|
40
|
+
|
|
41
|
+
echo "gen-models: wrote $OUT"
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// gen-skill-prompt.cjs — project a gated classifier block into a promptfoo
|
|
3
|
+
// skill-arm prompt.
|
|
4
|
+
//
|
|
5
|
+
// The skill-arm prompt is a MECHANICAL PROJECTION of the source block (extracted
|
|
6
|
+
// by extract-block.cjs), not a hand-copied paraphrase. This file owns the fixed
|
|
7
|
+
// wrapper (instruction header + the block + the {{input}} trailer) per target.
|
|
8
|
+
// Regenerate the committed prompts/<target>-skill.txt whenever the source block
|
|
9
|
+
// changes; the AC4 round-trip test asserts generated == committed byte-for-byte.
|
|
10
|
+
//
|
|
11
|
+
// renderSkillPrompt(target, block, tokens) is PURE (text in, text out). The CLI
|
|
12
|
+
// reads the source file on disk via gated-skills.json, extracts the block, reads
|
|
13
|
+
// the target's enum for the token list, renders, and writes the projection.
|
|
14
|
+
//
|
|
15
|
+
// CLI:
|
|
16
|
+
// node gen-skill-prompt.cjs <target> # write prompts/<target>-skill.txt
|
|
17
|
+
// node gen-skill-prompt.cjs --all # regenerate every gated target
|
|
18
|
+
// node gen-skill-prompt.cjs <target> --stdout # print, do not write
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
const fs = require("node:fs");
|
|
22
|
+
const path = require("node:path");
|
|
23
|
+
const { extractBlock } = require("./extract-block.cjs");
|
|
24
|
+
|
|
25
|
+
const SKILL_DIR = path.resolve(__dirname, "..");
|
|
26
|
+
const REPO_ROOT = path.resolve(SKILL_DIR, "..", "..", "..", "..");
|
|
27
|
+
const REGISTRY = path.join(SKILL_DIR, "gated-skills.json");
|
|
28
|
+
|
|
29
|
+
// Per-target wrapper. `enumPath` is relative to the skill dir; `render` is pure.
|
|
30
|
+
const TARGET_CONFIG = {
|
|
31
|
+
"go-routing": {
|
|
32
|
+
enumPath: "enums/go-routes.json",
|
|
33
|
+
render(block, tokens) {
|
|
34
|
+
return [
|
|
35
|
+
"You are the Soleur /go router. Classify the user's request into EXACTLY ONE route token using this routing table.",
|
|
36
|
+
"",
|
|
37
|
+
"Routing table:",
|
|
38
|
+
block,
|
|
39
|
+
"",
|
|
40
|
+
`Respond with ONLY the single route token (one of: ${tokens.join(", ")}). No explanation, no punctuation, no extra words.`,
|
|
41
|
+
"",
|
|
42
|
+
"User request: {{input}}",
|
|
43
|
+
"Route:",
|
|
44
|
+
"",
|
|
45
|
+
].join("\n");
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
"ticket-triage": {
|
|
49
|
+
enumPath: "enums/triage-levels.json",
|
|
50
|
+
render(block, tokens) {
|
|
51
|
+
return [
|
|
52
|
+
"You are the Soleur ticket-triage classifier. Assign a priority level to the GitHub issue using this rubric.",
|
|
53
|
+
"",
|
|
54
|
+
"Priority rubric:",
|
|
55
|
+
block,
|
|
56
|
+
"",
|
|
57
|
+
`Respond with ONLY the single priority token (one of: ${tokens.join(", ")}). No explanation, no extra words.`,
|
|
58
|
+
"",
|
|
59
|
+
"Issue:",
|
|
60
|
+
"{{input}}",
|
|
61
|
+
"Priority:",
|
|
62
|
+
"",
|
|
63
|
+
].join("\n");
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
"lane-inference": {
|
|
67
|
+
enumPath: "enums/lane.json",
|
|
68
|
+
render(block, tokens) {
|
|
69
|
+
return [
|
|
70
|
+
"You are the Soleur brainstorm lane classifier. Classify the feature description into EXACTLY ONE lane using this rule.",
|
|
71
|
+
"",
|
|
72
|
+
"Lane inference rule:",
|
|
73
|
+
block,
|
|
74
|
+
"",
|
|
75
|
+
`Respond with ONLY the single lane token (one of: ${tokens.join(", ")}). No explanation, no punctuation, no extra words.`,
|
|
76
|
+
"",
|
|
77
|
+
"Feature description: {{input}}",
|
|
78
|
+
"Lane:",
|
|
79
|
+
"",
|
|
80
|
+
].join("\n");
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
"incident-threshold": {
|
|
84
|
+
enumPath: "enums/incident-threshold.json",
|
|
85
|
+
render(block, tokens) {
|
|
86
|
+
return [
|
|
87
|
+
"You are the Soleur incident brand-survival classifier. Assign a threshold to the incident description using this rubric.",
|
|
88
|
+
"",
|
|
89
|
+
"Classification rubric:",
|
|
90
|
+
block,
|
|
91
|
+
"",
|
|
92
|
+
`Respond with ONLY the single threshold value (exactly one of: ${tokens.join(", ")}). No explanation, no extra words.`,
|
|
93
|
+
"",
|
|
94
|
+
"Incident:",
|
|
95
|
+
"{{input}}",
|
|
96
|
+
"Threshold:",
|
|
97
|
+
"",
|
|
98
|
+
].join("\n");
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// renderSkillPrompt(target, block, tokens): PURE projection of a block into the
|
|
104
|
+
// target's skill-arm prompt. Throws on an unknown target (fail-closed).
|
|
105
|
+
function renderSkillPrompt(target, block, tokens) {
|
|
106
|
+
const cfg = TARGET_CONFIG[target];
|
|
107
|
+
if (!cfg) {
|
|
108
|
+
throw new Error(`gen-skill-prompt: unknown target ${JSON.stringify(target)}`);
|
|
109
|
+
}
|
|
110
|
+
return cfg.render(block, tokens);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function loadRegistry() {
|
|
114
|
+
return JSON.parse(fs.readFileSync(REGISTRY, "utf8"));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function entryFor(target) {
|
|
118
|
+
const entry = loadRegistry().find((e) => e.target === target);
|
|
119
|
+
if (!entry) {
|
|
120
|
+
throw new Error(`gen-skill-prompt: target ${JSON.stringify(target)} not in gated-skills.json`);
|
|
121
|
+
}
|
|
122
|
+
return entry;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function tokensFor(target) {
|
|
126
|
+
const cfg = TARGET_CONFIG[target];
|
|
127
|
+
const enumAbs = path.join(SKILL_DIR, cfg.enumPath);
|
|
128
|
+
const arr = JSON.parse(fs.readFileSync(enumAbs, "utf8"));
|
|
129
|
+
if (!Array.isArray(arr)) {
|
|
130
|
+
throw new Error(`gen-skill-prompt: enum ${cfg.enumPath} is not an array`);
|
|
131
|
+
}
|
|
132
|
+
return arr;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// generateFromDisk(target): read source_file, extract the block, render. Returns
|
|
136
|
+
// { prompt, projectedPromptPath }.
|
|
137
|
+
function generateFromDisk(target) {
|
|
138
|
+
const entry = entryFor(target);
|
|
139
|
+
const sourceAbs = path.join(REPO_ROOT, entry.source_file);
|
|
140
|
+
const sourceText = fs.readFileSync(sourceAbs, "utf8");
|
|
141
|
+
const block = extractBlock(sourceText, entry.block_start_marker, entry.block_end_marker);
|
|
142
|
+
const prompt = renderSkillPrompt(target, block, tokensFor(target));
|
|
143
|
+
return { prompt, projectedPromptPath: path.join(REPO_ROOT, entry.projected_prompt_path) };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = { renderSkillPrompt, generateFromDisk, TARGET_CONFIG, tokensFor };
|
|
147
|
+
|
|
148
|
+
if (require.main === module) {
|
|
149
|
+
const args = process.argv.slice(2);
|
|
150
|
+
const toStdout = args.includes("--stdout");
|
|
151
|
+
const all = args.includes("--all");
|
|
152
|
+
const targets = all
|
|
153
|
+
? loadRegistry().map((e) => e.target)
|
|
154
|
+
: args.filter((a) => !a.startsWith("--"));
|
|
155
|
+
|
|
156
|
+
if (targets.length === 0) {
|
|
157
|
+
process.stderr.write(
|
|
158
|
+
"usage: node gen-skill-prompt.cjs <target> [--stdout] | --all\n",
|
|
159
|
+
);
|
|
160
|
+
process.exit(2);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
for (const target of targets) {
|
|
165
|
+
const { prompt, projectedPromptPath } = generateFromDisk(target);
|
|
166
|
+
if (toStdout) {
|
|
167
|
+
process.stdout.write(prompt);
|
|
168
|
+
} else {
|
|
169
|
+
fs.writeFileSync(projectedPromptPath, prompt);
|
|
170
|
+
process.stderr.write(`gen-skill-prompt: wrote ${projectedPromptPath}\n`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} catch (err) {
|
|
174
|
+
process.stderr.write(`${err.message}\n`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// MEASUREMENT assert (the ponytail `loc.js` analog).
|
|
2
|
+
//
|
|
3
|
+
// promptfoo custom JavaScript assert. Records the classification-correct rate as
|
|
4
|
+
// a score and ALWAYS passes — it measures, it never gates. The recorded number is
|
|
5
|
+
// the metric under test: 1.0 when the model's emitted label matches the golden
|
|
6
|
+
// label, 0.0 otherwise. Aggregated across runs (repeat: N) and across the skill
|
|
7
|
+
// vs baseline arms, the mean of this score IS the baseline-vs-skill delta.
|
|
8
|
+
//
|
|
9
|
+
// Signature: module.exports = (output, context) => GradingResult
|
|
10
|
+
// context.vars.golden_label : the expected label (route or P-level)
|
|
11
|
+
// context.vars.enum : the closed set of allowed labels — array or a
|
|
12
|
+
// `file://`/relative path to the SSOT (resolved by loadEnum()).
|
|
13
|
+
"use strict";
|
|
14
|
+
|
|
15
|
+
const { extractLabel, loadEnum } = require("./parse-label.cjs");
|
|
16
|
+
|
|
17
|
+
module.exports = (output, context) => {
|
|
18
|
+
const vars = (context && context.vars) || {};
|
|
19
|
+
const golden = vars.golden_label;
|
|
20
|
+
const allowed = loadEnum(vars);
|
|
21
|
+
const got = extractLabel(output, allowed);
|
|
22
|
+
const correct = got === golden;
|
|
23
|
+
return {
|
|
24
|
+
pass: true, // measurement only — never gates
|
|
25
|
+
score: correct ? 1.0 : 0.0,
|
|
26
|
+
reason: correct
|
|
27
|
+
? `classification-correct: ${got}`
|
|
28
|
+
: `classification-incorrect: got ${JSON.stringify(got)}, expected ${JSON.stringify(golden)}`,
|
|
29
|
+
};
|
|
30
|
+
};
|