@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,92 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Harness-parity census over the plugin doc population (ADR-226, #8299).
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* bun plugins/soleur/scripts/harness-parity-census.ts --report # print every non-canonical site; exit 1 if any
|
|
7
|
+
* bun plugins/soleur/scripts/harness-parity-census.ts --fix # rewrite the mechanical shapes in place (idempotent)
|
|
8
|
+
*
|
|
9
|
+
* The gate is `plugins/soleur/test/harness-parity-tree.test.ts`; this CLI is the author's
|
|
10
|
+
* inner loop and the remediation tool. `--fix` inverts only `/soleur:x`, `$soleur:x`,
|
|
11
|
+
* `@agent-soleur:x` and grok `/x` for a known skill; bare agent leaves, `@agent-<leaf>`
|
|
12
|
+
* mentions and grok stems in prose are hand edits (the sentence around them changes).
|
|
13
|
+
*
|
|
14
|
+
* `--fix` REWRITES TRACKED FILES IN PLACE and is the remedy the gate's own failure message
|
|
15
|
+
* prescribes, so it refuses to run against a dirty working tree unless `--force` is passed.
|
|
16
|
+
* That is not ceremony: a grok slash and a root-relative path are lexically identical after a
|
|
17
|
+
* boundary character (`run /plan` vs `POST /invoice`), so a rewrite CAN consume a real byte,
|
|
18
|
+
* and the result then classifies CANONICAL — meaning the census reports clean and the loss is
|
|
19
|
+
* invisible to the gate. Requiring a clean tree makes every rewrite reviewable with `git diff`
|
|
20
|
+
* and revertible with `git checkout`, which is the only guard that covers the whole class
|
|
21
|
+
* rather than one spelling of it.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { execFileSync } from "child_process";
|
|
25
|
+
import { writeFileSync } from "fs";
|
|
26
|
+
import { resolve } from "path";
|
|
27
|
+
import { REPO_ROOT, census, classifyDoc, fixDoc, formatReport, readIndex, readPopulation } from "../lib/harness-parity";
|
|
28
|
+
|
|
29
|
+
const args = new Set(process.argv.slice(2));
|
|
30
|
+
const mode = args.has("--fix") ? "fix" : args.has("--report") ? "report" : undefined;
|
|
31
|
+
if (mode === undefined) {
|
|
32
|
+
console.error("usage: harness-parity-census.ts --report | --fix [--force]");
|
|
33
|
+
process.exit(2);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (mode === "fix" && !args.has("--force")) {
|
|
37
|
+
const dirty = execFileSync("git", ["status", "--porcelain", "--", "plugins/soleur"], {
|
|
38
|
+
cwd: REPO_ROOT,
|
|
39
|
+
encoding: "utf-8",
|
|
40
|
+
}).trim();
|
|
41
|
+
if (dirty.length > 0) {
|
|
42
|
+
console.error(
|
|
43
|
+
[
|
|
44
|
+
"harness-parity --fix: refusing to rewrite a dirty tree — it edits tracked files in place,",
|
|
45
|
+
"and an uncommitted change would be indistinguishable from its own rewrites in `git diff`.",
|
|
46
|
+
"Commit or discard the changes below, then re-run; pass --force to override.",
|
|
47
|
+
"",
|
|
48
|
+
dirty,
|
|
49
|
+
].join("\n"),
|
|
50
|
+
);
|
|
51
|
+
process.exit(2);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const index = readIndex();
|
|
56
|
+
const docs = readPopulation();
|
|
57
|
+
|
|
58
|
+
if (mode === "fix") {
|
|
59
|
+
let changed = 0;
|
|
60
|
+
let skipped = 0;
|
|
61
|
+
for (const doc of docs) {
|
|
62
|
+
// A malformed marker leaves the region state unreliable, and `fixDoc` mirrors that state to
|
|
63
|
+
// decide what is exempt — so rewriting such a doc can edit inside a region the author meant
|
|
64
|
+
// to protect. Report it and leave it; the marker is RED in the gate either way.
|
|
65
|
+
const pre = classifyDoc(doc.text, index, doc.regionPolicy, doc.path);
|
|
66
|
+
if (pre.errors.length > 0) {
|
|
67
|
+
console.log(`skipped ${doc.path} — malformed marker, fix the marker first:`);
|
|
68
|
+
for (const e of pre.errors) console.log(` ${e}`);
|
|
69
|
+
skipped += 1;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const fixed = fixDoc(doc.text, index, doc.regionPolicy);
|
|
73
|
+
if (fixed !== doc.text) {
|
|
74
|
+
writeFileSync(resolve(REPO_ROOT, doc.path), fixed);
|
|
75
|
+
changed += 1;
|
|
76
|
+
console.log(`fixed ${doc.path}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const after = census(readPopulation(), index);
|
|
80
|
+
console.log(`harness-parity --fix: ${changed} docs rewritten, ${skipped} skipped for malformed markers; ${after.noncanonical.length} non-canonical sites remain (hand edits)`);
|
|
81
|
+
process.exit(0);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = census(docs, index);
|
|
85
|
+
console.log(formatReport(result));
|
|
86
|
+
if (result.noncanonical.length > 0 || result.errors.length > 0) {
|
|
87
|
+
console.log(
|
|
88
|
+
`\nRED: ${result.noncanonical.length} non-canonical sites, ${result.errors.length} marker errors. ` +
|
|
89
|
+
"Run `bun plugins/soleur/scripts/harness-parity-census.ts --fix` for the mechanical shapes (it requires a clean tree, so its rewrites stay reviewable with `git diff`); the rest are hand edits.",
|
|
90
|
+
);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// Discoverability probe for #8296 PR-1: does the SOURCE declare the Inngest wrong-volume
|
|
3
|
+
// Better Stack alert ARMED? Resolves `paused = !var.inngest_luks_cutover_complete` against the
|
|
4
|
+
// variable's declared default through the same code path the drift reconciler uses
|
|
5
|
+
// (../lib/heartbeat-live-reconcile.ts via discoverLogsAlertsFromInfra), so a regression in either
|
|
6
|
+
// the declaration or the resolver prints EXEMPT here before it silences the twice-daily report.
|
|
7
|
+
//
|
|
8
|
+
// Credential-free and sub-second: it reads apps/web-platform/infra/*.tf only. It says nothing
|
|
9
|
+
// about the LIVE alert (a Doppler TF_VAR override, or a vendor-side pause) — that half is the
|
|
10
|
+
// reconciler's job on scheduled-terraform-drift.yml, and PR-2's followthrough probe covers the
|
|
11
|
+
// device the store is actually on.
|
|
12
|
+
//
|
|
13
|
+
// This is a standalone file, not a `bun -e` one-liner, because preflight Check 10 (ADR-175)
|
|
14
|
+
// runs the plan's discoverability command inside a sandbox behind a shell-active-token reject:
|
|
15
|
+
// an arrow function's `=>` and a statement `;` both trip it, by design.
|
|
16
|
+
//
|
|
17
|
+
// Exit 0 + "ARMED" when the declaration resolves to paused=false; exit 1 + "EXEMPT" otherwise
|
|
18
|
+
// (unresolvable variable, non-boolean default, or the alert missing from the root entirely).
|
|
19
|
+
import { discoverLogsAlertsFromInfra } from "./reconcile-live-heartbeats.ts";
|
|
20
|
+
|
|
21
|
+
// argv[2] is a TEST seam only (a synthesized root with the default flipped); the plan's
|
|
22
|
+
// discoverability command passes nothing and reads the real root.
|
|
23
|
+
const INFRA_DIR = process.argv[2] ?? "apps/web-platform/infra";
|
|
24
|
+
const RESOURCE = "inngest_luks_wrong_volume";
|
|
25
|
+
|
|
26
|
+
const alert = discoverLogsAlertsFromInfra(INFRA_DIR).find((a) => a.resourceName === RESOURCE);
|
|
27
|
+
const armed = alert?.pausedResolvesFalse === true;
|
|
28
|
+
console.log(armed ? "ARMED" : "EXEMPT");
|
|
29
|
+
process.exit(armed ? 0 : 1);
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Install the generated OpenCode front door into an OpenCode config directory.
|
|
4
|
+
*
|
|
5
|
+
* bun plugins/soleur/scripts/install-opencode-adapter.ts # ~/.config/opencode
|
|
6
|
+
* bun plugins/soleur/scripts/install-opencode-adapter.ts --target DIR # e.g. a project .opencode
|
|
7
|
+
* bun plugins/soleur/scripts/install-opencode-adapter.ts --check --target DIR
|
|
8
|
+
*
|
|
9
|
+
* Why this exists: the generated tree commits its paths as `__SOLEUR_PLUGIN_ROOT__` rather
|
|
10
|
+
* than absolute ones, because the tree is shared across machines and an absolute path would
|
|
11
|
+
* make `sync-opencode-adapter.ts --check` machine-dependent. OpenCode's `skills` and
|
|
12
|
+
* `instructions` keys take plain paths with no env expansion, and the config schema has no
|
|
13
|
+
* `import` key (measurement §7.1), so something must resolve the token once, on the
|
|
14
|
+
* operator's machine. That is this script.
|
|
15
|
+
*
|
|
16
|
+
* Shapes here are each forced by a measurement:
|
|
17
|
+
*
|
|
18
|
+
* - `agents/` and `commands/` are copied straight into the config dir, because those are
|
|
19
|
+
* the roots OpenCode discovers (§3.0, §4.0). Skills are **not** copied on a checkout
|
|
20
|
+
* install — they register from the canonical tree through the `skills` key (§2.0), so the
|
|
21
|
+
* config points at the checkout and a second skill tree that could drift is never created.
|
|
22
|
+
* - On an npm install (`--vendor-payload`), the canonical payload is mirrored into
|
|
23
|
+
* `<configdir>/soleur/` so every installed reference points at a durable directory that
|
|
24
|
+
* survives `npx` / `bunx` cache eviction.
|
|
25
|
+
* - The config fragment is merged rather than written, so an operator's existing
|
|
26
|
+
* `skills` / `instructions` entries and every other key survive — for a config this script
|
|
27
|
+
* can READ. A config it cannot parse (JSONC comments, a syntax error, a torn write) is
|
|
28
|
+
* **refused**, not replaced: silently substituting `{}` would discard every key the operator
|
|
29
|
+
* ever set, and report success. `--force` replaces it after writing a `.bak-<ts>` beside it.
|
|
30
|
+
* - Writes are temp-file + rename, so an interrupted install cannot leave a half-written
|
|
31
|
+
* `opencode.json` whose next read takes the unparseable path.
|
|
32
|
+
* - The hook module (`opencode/plugin.ts`, source rather than a generated stub) is copied
|
|
33
|
+
* into `<configdir>/plugins/`, OpenCode's plugin discovery directory (measurement §6.6),
|
|
34
|
+
* with the plugin-root token resolved so the installed copy still reaches the guard scripts.
|
|
35
|
+
*
|
|
36
|
+
* `--check` writes nothing: it compares the target against `expectedInstalled` and exits 1
|
|
37
|
+
* on a difference.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import {
|
|
41
|
+
chmodSync,
|
|
42
|
+
copyFileSync,
|
|
43
|
+
existsSync,
|
|
44
|
+
mkdirSync,
|
|
45
|
+
readFileSync,
|
|
46
|
+
readdirSync,
|
|
47
|
+
renameSync,
|
|
48
|
+
rmSync,
|
|
49
|
+
statSync,
|
|
50
|
+
writeFileSync,
|
|
51
|
+
} from "fs";
|
|
52
|
+
import { dirname, join, relative, resolve } from "path";
|
|
53
|
+
import {
|
|
54
|
+
ADAPTER_DIR,
|
|
55
|
+
ADAPTER_SOURCE_FILES,
|
|
56
|
+
PLUGIN_ROOT_TOKEN,
|
|
57
|
+
configFragmentValues,
|
|
58
|
+
expectedOpenCodeAdapter,
|
|
59
|
+
} from "./sync-opencode-adapter";
|
|
60
|
+
|
|
61
|
+
const PLUGIN_ROOT = resolve(dirname(import.meta.filename), "..");
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Where a vendored payload lives, target-relative.
|
|
65
|
+
*
|
|
66
|
+
* `<configdir>/soleur/` is already Soleur's exclusive namespace in a config dir (the installed
|
|
67
|
+
* `INSTRUCTIONS.md` lives there and `installedExtras` treats everything under it as ours by
|
|
68
|
+
* name), so the payload joins it rather than opening a second namespace. One directory is also
|
|
69
|
+
* one thing to remove on uninstall.
|
|
70
|
+
*/
|
|
71
|
+
export const VENDOR_DIR = "soleur";
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The plugin-root subtrees a vendored payload carries.
|
|
75
|
+
*
|
|
76
|
+
* Each entry is load-bearing: `skills` is what the `skills` key registers, `agents`/`commands`
|
|
77
|
+
* are what the generated stubs name, `hooks` is what the installed hook module spawns its guards
|
|
78
|
+
* from, `scripts` is what the canonical prose calls as `<root>/scripts/<name>.sh` (404 call
|
|
79
|
+
* sites), `lib` is what those scripts import, `opencode` is the generated tree the installer
|
|
80
|
+
* itself reads, and `.claude-plugin` is the identity marker `plugin-version.sh` and
|
|
81
|
+
* `resolve-regenerable-conflicts.sh` resolve the root by.
|
|
82
|
+
*/
|
|
83
|
+
export const PAYLOAD_DIRS = [
|
|
84
|
+
"skills",
|
|
85
|
+
"agents",
|
|
86
|
+
"commands",
|
|
87
|
+
"hooks",
|
|
88
|
+
"scripts",
|
|
89
|
+
"lib",
|
|
90
|
+
ADAPTER_DIR,
|
|
91
|
+
".claude-plugin",
|
|
92
|
+
] as const;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Marker that tells a plugin root apart as a **vendored payload** rather than a checkout.
|
|
96
|
+
*
|
|
97
|
+
* It is what lets the copy's own `scripts/install-opencode-adapter.ts --check` pass: run from
|
|
98
|
+
* `<configdir>/soleur/`, the payload is inside the target, so the extras sweep would otherwise
|
|
99
|
+
* report every one of the ~800 payload files as EXTRA and exit 1 — a correct install graded as
|
|
100
|
+
* broken.
|
|
101
|
+
*/
|
|
102
|
+
export const VENDOR_MARKER = ".soleur-vendored.json";
|
|
103
|
+
|
|
104
|
+
/** True when `root` is a payload the installer vendored, not a checkout. */
|
|
105
|
+
export function isVendoredRoot(root: string): boolean {
|
|
106
|
+
return existsSync(join(root, VENDOR_MARKER));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function vendorMarkerContent(): string {
|
|
110
|
+
return `${JSON.stringify({ format: 1, kind: "soleur-opencode-payload", owns: [...PAYLOAD_DIRS] }, null, 2)}\n`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface PayloadEntry {
|
|
114
|
+
content: string;
|
|
115
|
+
executable: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Every regular file under `<root>/<dir>`, keyed `<dir>/<relative path>`, in sorted order.
|
|
120
|
+
* Symlinks are refused so a stray symlink in the source tree can never be dereferenced into
|
|
121
|
+
* the published npm tarball or vendored config directory.
|
|
122
|
+
*/
|
|
123
|
+
export function walkPayloadFiles(root: string, dir: string): Array<[string, PayloadEntry]> {
|
|
124
|
+
const found: Array<[string, PayloadEntry]> = [];
|
|
125
|
+
const visit = (relativeDir: string): void => {
|
|
126
|
+
let entries;
|
|
127
|
+
try {
|
|
128
|
+
entries = readdirSync(join(root, relativeDir), { withFileTypes: true });
|
|
129
|
+
} catch {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
133
|
+
const path = `${currentPath(relativeDir, entry.name)}`;
|
|
134
|
+
if (entry.isSymbolicLink()) {
|
|
135
|
+
throw new Error(`Refusing symbolic link in payload tree: ${join(root, path)}`);
|
|
136
|
+
}
|
|
137
|
+
if (entry.isDirectory()) {
|
|
138
|
+
visit(path);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (!entry.isFile()) continue;
|
|
142
|
+
const full = join(root, path);
|
|
143
|
+
const executable = (statSync(full).mode & 0o111) !== 0;
|
|
144
|
+
found.push([path, { content: readFileSync(full, "utf-8"), executable }]);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
visit(dir);
|
|
148
|
+
return found;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function currentPath(dir: string, name: string): string {
|
|
152
|
+
return `${dir}/${name}`;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Full payload map for `root`, shared with `sync-npm-package.ts`. */
|
|
156
|
+
export function expectedPayloadEntries(root: string): Map<string, PayloadEntry> {
|
|
157
|
+
const expected = new Map<string, PayloadEntry>();
|
|
158
|
+
for (const dir of PAYLOAD_DIRS) {
|
|
159
|
+
for (const [path, entry] of walkPayloadFiles(root, dir)) {
|
|
160
|
+
expected.set(path, entry);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return expected;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface InstallOptions {
|
|
167
|
+
force?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Mirror the canonical payload into `<target>/soleur/` and point every installed file at that
|
|
170
|
+
* copy instead of at `pluginRoot`. Used by the npm distribution, which has no checkout.
|
|
171
|
+
*/
|
|
172
|
+
vendorPayload?: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function resolveEffectiveRoot(targetDir: string, pluginRoot: string, options: InstallOptions): string {
|
|
176
|
+
return options.vendorPayload === true ? join(targetDir, VENDOR_DIR) : pluginRoot;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** `__SOLEUR_PLUGIN_ROOT__` → the resolved root. The only substitution in the whole install. */
|
|
180
|
+
function resolveToken(content: string, pluginRoot: string): string {
|
|
181
|
+
return content.split(PLUGIN_ROOT_TOKEN).join(pluginRoot);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Union a fragment's path arrays into an existing config, preserving every other key. */
|
|
185
|
+
export function mergeFragment(
|
|
186
|
+
existing: Record<string, unknown>,
|
|
187
|
+
fragment: { skills: string[]; instructions: string[] },
|
|
188
|
+
): Record<string, unknown> {
|
|
189
|
+
const merged: Record<string, unknown> = { ...existing };
|
|
190
|
+
for (const key of ["skills", "instructions"] as const) {
|
|
191
|
+
const present = Array.isArray(existing[key]) ? (existing[key] as unknown[]) : [];
|
|
192
|
+
merged[key] = [...present, ...fragment[key]].filter((value, index, all) => all.indexOf(value) === index);
|
|
193
|
+
}
|
|
194
|
+
return merged;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export class UnparseableConfigError extends Error {
|
|
198
|
+
constructor(
|
|
199
|
+
readonly path: string,
|
|
200
|
+
readonly detail: string,
|
|
201
|
+
) {
|
|
202
|
+
super(
|
|
203
|
+
`${path} exists but is not a JSON object (${detail}). Refusing to overwrite it — that would replace every key you set with the Soleur fragment alone. Fix the file, move it aside, or re-run with --force (which writes a timestamped backup first).`,
|
|
204
|
+
);
|
|
205
|
+
this.name = "UnparseableConfigError";
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function expectedInstalled(
|
|
210
|
+
targetDir: string,
|
|
211
|
+
pluginRoot = PLUGIN_ROOT,
|
|
212
|
+
config?: Record<string, unknown>,
|
|
213
|
+
options: InstallOptions = {},
|
|
214
|
+
): Map<string, string> {
|
|
215
|
+
const expected = new Map<string, string>();
|
|
216
|
+
const effectiveRoot = resolveEffectiveRoot(targetDir, pluginRoot, options);
|
|
217
|
+
for (const [path, content] of expectedOpenCodeAdapter(pluginRoot)) {
|
|
218
|
+
if (path === `${ADAPTER_DIR}/opencode.json`) continue;
|
|
219
|
+
const installed =
|
|
220
|
+
path === `${ADAPTER_DIR}/INSTRUCTIONS.md` ? `soleur/${relative(ADAPTER_DIR, path)}` : relative(ADAPTER_DIR, path);
|
|
221
|
+
expected.set(installed, resolveToken(content, effectiveRoot));
|
|
222
|
+
}
|
|
223
|
+
for (const source of ADAPTER_SOURCE_FILES) {
|
|
224
|
+
if (!source.startsWith(`${ADAPTER_DIR}/`)) continue;
|
|
225
|
+
const installed = `plugins/soleur-${source.slice(ADAPTER_DIR.length + 1)}`;
|
|
226
|
+
expected.set(installed, resolveToken(readFileSync(join(pluginRoot, source), "utf-8"), effectiveRoot));
|
|
227
|
+
}
|
|
228
|
+
for (const [path, entry] of payloadExpected(targetDir, pluginRoot, effectiveRoot, options)) {
|
|
229
|
+
expected.set(path, entry.content);
|
|
230
|
+
}
|
|
231
|
+
const fragment = configFragmentValues(effectiveRoot);
|
|
232
|
+
const merged = mergeFragment(config ?? readConfig(join(targetDir, "opencode.json")), {
|
|
233
|
+
skills: fragment.skills,
|
|
234
|
+
instructions: [join(targetDir, "soleur", "INSTRUCTIONS.md")],
|
|
235
|
+
});
|
|
236
|
+
expected.set("opencode.json", `${JSON.stringify(merged, null, 2)}\n`);
|
|
237
|
+
return expected;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function payloadExpected(
|
|
241
|
+
targetDir: string,
|
|
242
|
+
sourceRoot: string,
|
|
243
|
+
effectiveRoot: string,
|
|
244
|
+
options: InstallOptions,
|
|
245
|
+
): Map<string, PayloadEntry> {
|
|
246
|
+
const owned = options.vendorPayload === true || isVendoredRoot(sourceRoot);
|
|
247
|
+
const result = new Map<string, PayloadEntry>();
|
|
248
|
+
if (!owned) return result;
|
|
249
|
+
const prefix = relative(targetDir, effectiveRoot).split("\\").join("/");
|
|
250
|
+
if (prefix === "" || prefix.startsWith("..")) return result;
|
|
251
|
+
for (const [path, entry] of expectedPayloadEntries(sourceRoot)) {
|
|
252
|
+
result.set(`${prefix}/${path}`, entry);
|
|
253
|
+
}
|
|
254
|
+
result.set(`${prefix}/${VENDOR_MARKER}`, { content: vendorMarkerContent(), executable: false });
|
|
255
|
+
return result;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function readConfig(path: string): Record<string, unknown> {
|
|
259
|
+
let raw: string;
|
|
260
|
+
try {
|
|
261
|
+
raw = readFileSync(path, "utf-8");
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return {};
|
|
264
|
+
throw new UnparseableConfigError(path, `could not be read: ${String(error)}`);
|
|
265
|
+
}
|
|
266
|
+
let parsed: unknown;
|
|
267
|
+
try {
|
|
268
|
+
parsed = JSON.parse(raw);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
throw new UnparseableConfigError(path, String(error));
|
|
271
|
+
}
|
|
272
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
273
|
+
throw new UnparseableConfigError(
|
|
274
|
+
path,
|
|
275
|
+
`top level is ${Array.isArray(parsed) ? "an array" : parsed === null ? "null" : typeof parsed}`,
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
return parsed as Record<string, unknown>;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/** Target-relative paths of every regular file under `dir` (skips symlinks; empty when absent). */
|
|
282
|
+
function walkFiles(targetDir: string, dir: string): string[] {
|
|
283
|
+
const found: string[] = [];
|
|
284
|
+
const visit = (relativeDir: string): void => {
|
|
285
|
+
let entries;
|
|
286
|
+
try {
|
|
287
|
+
entries = readdirSync(join(targetDir, relativeDir), { withFileTypes: true });
|
|
288
|
+
} catch {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
for (const entry of entries) {
|
|
292
|
+
if (entry.isSymbolicLink()) continue;
|
|
293
|
+
const path = `${relativeDir}/${entry.name}`;
|
|
294
|
+
if (entry.isDirectory()) visit(path);
|
|
295
|
+
else if (entry.isFile()) found.push(path);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
visit(dir);
|
|
299
|
+
return found.sort();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const STUB_SIGNATURES = ["Stub for the canonical agent `", "Run the canonical `"] as const;
|
|
303
|
+
|
|
304
|
+
function isGeneratedStub(content: string, pluginRoot: string): boolean {
|
|
305
|
+
return content.includes(pluginRoot) && STUB_SIGNATURES.some((signature) => content.includes(signature));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export function installedExtras(
|
|
309
|
+
targetDir: string,
|
|
310
|
+
expected: Map<string, string>,
|
|
311
|
+
root = PLUGIN_ROOT,
|
|
312
|
+
): string[] {
|
|
313
|
+
const extras: string[] = [];
|
|
314
|
+
for (const path of walkFiles(targetDir, "soleur")) if (!expected.has(path)) extras.push(path);
|
|
315
|
+
for (const path of walkFiles(targetDir, "plugins")) {
|
|
316
|
+
if (path.startsWith("plugins/soleur-") && !expected.has(path)) extras.push(path);
|
|
317
|
+
}
|
|
318
|
+
for (const root_ of ["agents", "commands"]) {
|
|
319
|
+
for (const path of walkFiles(targetDir, root_)) {
|
|
320
|
+
if (expected.has(path)) continue;
|
|
321
|
+
let content: string;
|
|
322
|
+
try {
|
|
323
|
+
content = readFileSync(join(targetDir, path), "utf-8");
|
|
324
|
+
} catch {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (isGeneratedStub(content, root)) extras.push(path);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return extras.sort();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Write through a sibling temp file and rename, preserving executable mode when needed. */
|
|
334
|
+
function writeAtomic(full: string, content: string, executable = false): void {
|
|
335
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
336
|
+
const temp = `${full}.soleur-tmp-${process.pid}`;
|
|
337
|
+
writeFileSync(temp, content);
|
|
338
|
+
if (executable) chmodSync(temp, 0o755);
|
|
339
|
+
renameSync(temp, full);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface InstallResult {
|
|
343
|
+
written: string[];
|
|
344
|
+
unchanged: string[];
|
|
345
|
+
removed: string[];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export function installOpenCodeAdapter(
|
|
349
|
+
targetDir: string,
|
|
350
|
+
pluginRoot = PLUGIN_ROOT,
|
|
351
|
+
options: InstallOptions = {},
|
|
352
|
+
): InstallResult {
|
|
353
|
+
const result: InstallResult = { written: [], unchanged: [], removed: [] };
|
|
354
|
+
const configPath = join(targetDir, "opencode.json");
|
|
355
|
+
let config: Record<string, unknown> | undefined;
|
|
356
|
+
try {
|
|
357
|
+
config = readConfig(configPath);
|
|
358
|
+
} catch (error) {
|
|
359
|
+
if (!(error instanceof UnparseableConfigError)) throw error;
|
|
360
|
+
if (options.force !== true) throw error;
|
|
361
|
+
const backup = `${configPath}.bak-${Date.now()}`;
|
|
362
|
+
copyFileSync(configPath, backup);
|
|
363
|
+
console.error(`[soleur] --force: replaced ${configPath}; the previous bytes are at ${backup}`);
|
|
364
|
+
config = {};
|
|
365
|
+
}
|
|
366
|
+
const effectiveRoot = resolveEffectiveRoot(targetDir, pluginRoot, options);
|
|
367
|
+
const payload = payloadExpected(targetDir, pluginRoot, effectiveRoot, options);
|
|
368
|
+
const expected = expectedInstalled(targetDir, pluginRoot, config, options);
|
|
369
|
+
for (const [path, content] of expected) {
|
|
370
|
+
const full = join(targetDir, path);
|
|
371
|
+
const wantExec = payload.get(path)?.executable === true;
|
|
372
|
+
let current: string | undefined;
|
|
373
|
+
let currentExec = false;
|
|
374
|
+
try {
|
|
375
|
+
current = readFileSync(full, "utf-8");
|
|
376
|
+
currentExec = (statSync(full).mode & 0o111) !== 0;
|
|
377
|
+
} catch {
|
|
378
|
+
current = undefined;
|
|
379
|
+
}
|
|
380
|
+
if (current === content && (!wantExec || currentExec)) {
|
|
381
|
+
result.unchanged.push(path);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
writeAtomic(full, content, wantExec);
|
|
385
|
+
result.written.push(path);
|
|
386
|
+
}
|
|
387
|
+
for (const path of installedExtras(targetDir, expected, effectiveRoot)) {
|
|
388
|
+
rmSync(join(targetDir, path), { force: true });
|
|
389
|
+
result.removed.push(path);
|
|
390
|
+
}
|
|
391
|
+
result.written.sort();
|
|
392
|
+
result.unchanged.sort();
|
|
393
|
+
result.removed.sort();
|
|
394
|
+
return result;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export function installProblems(targetDir: string, pluginRoot = PLUGIN_ROOT, options: InstallOptions = {}): string[] {
|
|
398
|
+
const problems: string[] = [];
|
|
399
|
+
const effectiveRoot = resolveEffectiveRoot(targetDir, pluginRoot, options);
|
|
400
|
+
const payload = payloadExpected(targetDir, pluginRoot, effectiveRoot, options);
|
|
401
|
+
const expected = expectedInstalled(targetDir, pluginRoot, undefined, options);
|
|
402
|
+
for (const [path, content] of expected) {
|
|
403
|
+
const full = join(targetDir, path);
|
|
404
|
+
const wantExec = payload.get(path)?.executable === true;
|
|
405
|
+
let current: string | undefined;
|
|
406
|
+
let currentExec = false;
|
|
407
|
+
try {
|
|
408
|
+
current = readFileSync(full, "utf-8");
|
|
409
|
+
currentExec = (statSync(full).mode & 0o111) !== 0;
|
|
410
|
+
} catch {
|
|
411
|
+
current = undefined;
|
|
412
|
+
}
|
|
413
|
+
if (current === undefined) problems.push(`MISSING: ${path}`);
|
|
414
|
+
else if (current !== content || (wantExec && !currentExec)) problems.push(`STALE: ${path}`);
|
|
415
|
+
}
|
|
416
|
+
for (const path of installedExtras(targetDir, expected, effectiveRoot)) {
|
|
417
|
+
problems.push(`EXTRA: ${path}`);
|
|
418
|
+
}
|
|
419
|
+
return problems.sort();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function parseArg(argv: readonly string[], flag: string): string | undefined {
|
|
423
|
+
const index = argv.indexOf(flag);
|
|
424
|
+
if (index === -1) return undefined;
|
|
425
|
+
return argv[index + 1];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const USAGE = [
|
|
429
|
+
"Usage: bun plugins/soleur/scripts/install-opencode-adapter.ts [install] [--target DIR] [--plugin-root DIR] [--vendor-payload] [--check] [--force] [--help]",
|
|
430
|
+
"",
|
|
431
|
+
" --target DIR config dir to install into (default: $HOME/.config/opencode)",
|
|
432
|
+
" --plugin-root DIR checkout (or package) the installed files should point at (default: this checkout)",
|
|
433
|
+
" --vendor-payload copy the payload into <target>/soleur/ and point the installed files at that",
|
|
434
|
+
" copy; required when there is no checkout to point at (the npm distribution)",
|
|
435
|
+
" --check write nothing; report MISSING / STALE / EXTRA",
|
|
436
|
+
" --force replace an existing opencode.json that cannot be parsed (backup first)",
|
|
437
|
+
" --help, -h print this text and exit 0 without writing",
|
|
438
|
+
].join("\n");
|
|
439
|
+
|
|
440
|
+
function validateArgs(argv: readonly string[], usage = USAGE): void {
|
|
441
|
+
const withValue = new Set(["--target", "--plugin-root"]);
|
|
442
|
+
const known = new Set([...withValue, "--vendor-payload", "--check", "--force", "--help", "-h"]);
|
|
443
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
444
|
+
const arg = argv[i];
|
|
445
|
+
if (arg === "--help" || arg === "-h") {
|
|
446
|
+
console.log(usage);
|
|
447
|
+
process.exit(0);
|
|
448
|
+
}
|
|
449
|
+
if (!known.has(arg)) {
|
|
450
|
+
console.error(`unknown argument: ${arg}\n${usage}`);
|
|
451
|
+
process.exit(2);
|
|
452
|
+
}
|
|
453
|
+
if (withValue.has(arg)) {
|
|
454
|
+
const next = argv[i + 1];
|
|
455
|
+
if (next === undefined || next.startsWith("-")) {
|
|
456
|
+
console.error(`${arg} requires a directory\n${usage}`);
|
|
457
|
+
process.exit(2);
|
|
458
|
+
}
|
|
459
|
+
i += 1;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export function runCli(
|
|
465
|
+
rawArgv: readonly string[],
|
|
466
|
+
defaultPluginRoot = PLUGIN_ROOT,
|
|
467
|
+
defaultVendorPayload = false,
|
|
468
|
+
usage = USAGE,
|
|
469
|
+
): void {
|
|
470
|
+
const argv = rawArgv[0] === "install" ? rawArgv.slice(1) : rawArgv;
|
|
471
|
+
validateArgs(argv, usage);
|
|
472
|
+
const explicitTarget = parseArg(argv, "--target");
|
|
473
|
+
const home = process.env["HOME"];
|
|
474
|
+
if (explicitTarget === undefined && (home === undefined || home === "")) {
|
|
475
|
+
console.error(
|
|
476
|
+
"HOME is not set and --target was not given: refusing to install into a cwd-relative `.config/opencode`. Pass --target DIR.",
|
|
477
|
+
);
|
|
478
|
+
process.exit(2);
|
|
479
|
+
}
|
|
480
|
+
const targetDir = resolve(explicitTarget ?? join(home as string, ".config", "opencode"));
|
|
481
|
+
const pluginRoot = resolve(parseArg(argv, "--plugin-root") ?? defaultPluginRoot);
|
|
482
|
+
const options: InstallOptions = {
|
|
483
|
+
force: argv.includes("--force"),
|
|
484
|
+
vendorPayload: defaultVendorPayload || argv.includes("--vendor-payload"),
|
|
485
|
+
};
|
|
486
|
+
try {
|
|
487
|
+
if (argv.includes("--check")) {
|
|
488
|
+
const problems = installProblems(targetDir, pluginRoot, options);
|
|
489
|
+
if (problems.length > 0) {
|
|
490
|
+
for (const problem of problems) console.error(problem);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
console.log("opencode-install ok");
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const result = installOpenCodeAdapter(targetDir, pluginRoot, options);
|
|
497
|
+
console.log(
|
|
498
|
+
`opencode-adapter installed into ${targetDir} (${result.written.length} written, ${result.unchanged.length} unchanged, ${result.removed.length} removed)`,
|
|
499
|
+
);
|
|
500
|
+
} catch (error) {
|
|
501
|
+
if (error instanceof UnparseableConfigError) {
|
|
502
|
+
console.error(error.message);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
throw error;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (import.meta.main) runCli(process.argv.slice(2));
|