@soleur/opencode 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/agents.manifest.json +476 -0
- package/.claude-plugin/plugin.json +42 -0
- package/README.md +44 -2
- package/agents/community/.gitkeep +0 -0
- package/agents/engineering/cto.md +87 -0
- package/agents/engineering/design/ddd-architect.md +95 -0
- package/agents/engineering/discovery/agent-finder.md +214 -0
- package/agents/engineering/discovery/functional-discovery.md +182 -0
- package/agents/engineering/infra/infra-security.md +151 -0
- package/agents/engineering/infra/platform-strategist.md +109 -0
- package/agents/engineering/infra/terraform-architect.md +171 -0
- package/agents/engineering/prompt-engineer.md +37 -0
- package/agents/engineering/research/best-practices-researcher.md +115 -0
- package/agents/engineering/research/framework-docs-researcher.md +93 -0
- package/agents/engineering/research/git-history-analyzer.md +53 -0
- package/agents/engineering/research/learnings-researcher.md +285 -0
- package/agents/engineering/research/repo-research-analyst.md +118 -0
- package/agents/engineering/review/agent-native-reviewer.md +279 -0
- package/agents/engineering/review/architecture-strategist.md +61 -0
- package/agents/engineering/review/code-quality-analyst.md +92 -0
- package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
- package/agents/engineering/review/data-integrity-guardian.md +82 -0
- package/agents/engineering/review/data-migration-expert.md +98 -0
- package/agents/engineering/review/deployment-verification-agent.md +183 -0
- package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
- package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
- package/agents/engineering/review/legacy-code-expert.md +55 -0
- package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
- package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
- package/agents/engineering/review/performance-oracle.md +130 -0
- package/agents/engineering/review/security-sentinel.md +167 -0
- package/agents/engineering/review/semgrep-sast.md +36 -0
- package/agents/engineering/review/test-design-reviewer.md +150 -0
- package/agents/engineering/review/user-impact-reviewer.md +70 -0
- package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
- package/agents/finance/budget-analyst.md +29 -0
- package/agents/finance/cfo.md +44 -0
- package/agents/finance/financial-reporter.md +30 -0
- package/agents/finance/revenue-analyst.md +30 -0
- package/agents/legal/clo.md +115 -0
- package/agents/legal/legal-compliance-auditor.md +110 -0
- package/agents/legal/legal-document-generator.md +134 -0
- package/agents/marketing/analytics-analyst.md +25 -0
- package/agents/marketing/brand-architect.md +181 -0
- package/agents/marketing/cmo.md +76 -0
- package/agents/marketing/conversion-optimizer.md +19 -0
- package/agents/marketing/copywriter.md +20 -0
- package/agents/marketing/fact-checker.md +70 -0
- package/agents/marketing/growth-strategist.md +145 -0
- package/agents/marketing/paid-media-strategist.md +28 -0
- package/agents/marketing/pricing-strategist.md +17 -0
- package/agents/marketing/programmatic-seo-specialist.md +25 -0
- package/agents/marketing/retention-strategist.md +23 -0
- package/agents/marketing/seo-aeo-analyst.md +164 -0
- package/agents/operations/coo.md +50 -0
- package/agents/operations/ops-advisor.md +78 -0
- package/agents/operations/ops-provisioner.md +101 -0
- package/agents/operations/ops-research.md +52 -0
- package/agents/operations/service-automator.md +278 -0
- package/agents/product/business-validator.md +206 -0
- package/agents/product/competitive-intelligence.md +89 -0
- package/agents/product/cpo.md +63 -0
- package/agents/product/design/ux-design-lead.md +209 -0
- package/agents/product/spec-flow-analyzer.md +122 -0
- package/agents/sales/cro.md +44 -0
- package/agents/sales/deal-architect.md +29 -0
- package/agents/sales/outbound-strategist.md +29 -0
- package/agents/sales/pipeline-analyst.md +29 -0
- package/agents/support/cco.md +48 -0
- package/agents/support/community-manager.md +570 -0
- package/agents/support/ticket-triage.md +70 -0
- package/bin/soleur-opencode.js +29 -0
- package/commands/go.md +659 -0
- package/commands/help.md +273 -0
- package/commands/sync.md +977 -0
- package/commands/version.md +103 -0
- package/hooks/antigravity-hooks.json +84 -0
- package/hooks/antigravity-session-start.sh +15 -0
- package/hooks/bare-root-cwd-guard.sh +131 -0
- package/hooks/browser-snapshot-credential-guard.sh +200 -0
- package/hooks/codex-session-start.sh +9 -0
- package/hooks/compaction-state.sh +525 -0
- package/hooks/destructive-command-guard.sh +1387 -0
- package/hooks/devin-session-start.sh +90 -0
- package/hooks/ext-filter-detect.sh +171 -0
- package/hooks/hooks.json +133 -0
- package/hooks/lib/hook-tool-kind.sh +24 -0
- package/hooks/lib/log-rotation.sh +176 -0
- package/hooks/lib/shell-argv.pl +576 -0
- package/hooks/memory-backstop.sh +1114 -0
- package/hooks/operator-stage-approval.sh +391 -0
- package/hooks/stop-hook.sh +367 -0
- package/hooks/unkept-promise-hook.sh +383 -0
- package/hooks/version-banner.sh +127 -0
- package/hooks/welcome-hook.sh +50 -0
- package/install.js +108 -0
- package/lib/agent-registry.ts +154 -0
- package/lib/c4-canonical-cli.mjs +34 -0
- package/lib/c4-canonical.mjs +46 -0
- package/lib/c4-from-components.ts +554 -0
- package/lib/go-routing.ts +81 -0
- package/lib/grok-inspect-contract.ts +311 -0
- package/lib/harness-model-map.ts +101 -0
- package/lib/harness-parity.ts +726 -0
- package/lib/harness-tool-map.ts +180 -0
- package/lib/harness.ts +716 -0
- package/lib/heartbeat-live-reconcile.ts +1153 -0
- package/lib/heartbeat-manifest.ts +342 -0
- package/lib/kb-coverage.ts +252 -0
- package/lib/pr-merge-poll.ts +103 -0
- package/lib/workflow-fidelity.ts +388 -0
- package/opencode/INSTRUCTIONS.md +152 -0
- package/opencode/agents/engineering/cto.md +10 -0
- package/opencode/agents/engineering/design/ddd-architect.md +10 -0
- package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
- package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
- package/opencode/agents/engineering/infra/infra-security.md +10 -0
- package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
- package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
- package/opencode/agents/engineering/prompt-engineer.md +10 -0
- package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
- package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
- package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
- package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
- package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
- package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
- package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
- package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
- package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
- package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
- package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
- package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
- package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
- package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
- package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
- package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
- package/opencode/agents/engineering/review/performance-oracle.md +10 -0
- package/opencode/agents/engineering/review/security-sentinel.md +10 -0
- package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
- package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
- package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
- package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
- package/opencode/agents/finance/budget-analyst.md +10 -0
- package/opencode/agents/finance/cfo.md +10 -0
- package/opencode/agents/finance/financial-reporter.md +10 -0
- package/opencode/agents/finance/revenue-analyst.md +10 -0
- package/opencode/agents/legal/clo.md +10 -0
- package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
- package/opencode/agents/legal/legal-document-generator.md +10 -0
- package/opencode/agents/marketing/analytics-analyst.md +10 -0
- package/opencode/agents/marketing/brand-architect.md +10 -0
- package/opencode/agents/marketing/cmo.md +10 -0
- package/opencode/agents/marketing/conversion-optimizer.md +10 -0
- package/opencode/agents/marketing/copywriter.md +10 -0
- package/opencode/agents/marketing/fact-checker.md +10 -0
- package/opencode/agents/marketing/growth-strategist.md +10 -0
- package/opencode/agents/marketing/paid-media-strategist.md +10 -0
- package/opencode/agents/marketing/pricing-strategist.md +10 -0
- package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
- package/opencode/agents/marketing/retention-strategist.md +10 -0
- package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
- package/opencode/agents/operations/coo.md +10 -0
- package/opencode/agents/operations/ops-advisor.md +10 -0
- package/opencode/agents/operations/ops-provisioner.md +10 -0
- package/opencode/agents/operations/ops-research.md +10 -0
- package/opencode/agents/operations/service-automator.md +10 -0
- package/opencode/agents/product/business-validator.md +10 -0
- package/opencode/agents/product/competitive-intelligence.md +10 -0
- package/opencode/agents/product/cpo.md +10 -0
- package/opencode/agents/product/design/ux-design-lead.md +10 -0
- package/opencode/agents/product/spec-flow-analyzer.md +10 -0
- package/opencode/agents/sales/cro.md +10 -0
- package/opencode/agents/sales/deal-architect.md +10 -0
- package/opencode/agents/sales/outbound-strategist.md +10 -0
- package/opencode/agents/sales/pipeline-analyst.md +10 -0
- package/opencode/agents/support/cco.md +10 -0
- package/opencode/agents/support/community-manager.md +10 -0
- package/opencode/agents/support/ticket-triage.md +10 -0
- package/opencode/commands/go.md +10 -0
- package/opencode/commands/help.md +10 -0
- package/opencode/commands/sync.md +10 -0
- package/opencode/commands/version.md +11 -0
- package/opencode/opencode.json +8 -0
- package/opencode/plugin.ts +493 -0
- package/package.json +36 -4
- package/scripts/admin-merge-ready.sh +545 -0
- package/scripts/admin-merge-ready.test.sh +753 -0
- package/scripts/affected-tests.sh +908 -0
- package/scripts/affected-tests.test.sh +1797 -0
- package/scripts/alpha-metrics.sh +78 -0
- package/scripts/alpha-metrics.test.sh +115 -0
- package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
- package/scripts/audit-flag-flip.sh +107 -0
- package/scripts/check-red-on-main.sh +316 -0
- package/scripts/ci-head-verdict.sh +363 -0
- package/scripts/cloud-detect.sh +193 -0
- package/scripts/delegation-verify.sh +657 -0
- package/scripts/delegation-verify.test.sh +1424 -0
- package/scripts/deploy-arm.sh +475 -0
- package/scripts/domain-model-drift.sh +419 -0
- package/scripts/emit-decision.sh +144 -0
- package/scripts/emit-decision.test.sh +144 -0
- package/scripts/ext-filter-divergence-corpus.txt +15 -0
- package/scripts/ext-filter-divergence.sh +189 -0
- package/scripts/generate-c4-from-components.ts +442 -0
- package/scripts/grok-fidelity-gate.sh +68 -0
- package/scripts/grok-pre-push-gate.sh +232 -0
- package/scripts/harness-discovery-smoke.ts +906 -0
- package/scripts/harness-parity-census.ts +92 -0
- package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
- package/scripts/install-opencode-adapter.ts +520 -0
- package/scripts/lib/affected-tests/common.sh +365 -0
- package/scripts/lib/affected-tests/go.sh +157 -0
- package/scripts/lib/affected-tests/js.sh +188 -0
- package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
- package/scripts/lib/affected-tests/python.sh +185 -0
- package/scripts/lib/context-sanitize.sh +49 -0
- package/scripts/lib/domain-model-lib.sh +180 -0
- package/scripts/lib/ext-filter-grammar.tsv +34 -0
- package/scripts/lib/operator-script.sh +1236 -0
- package/scripts/lib/proc.sh +580 -0
- package/scripts/lib/session-state.sh +748 -0
- package/scripts/lib/tmp-classify.sh +843 -0
- package/scripts/lib/wrapper-boundary.sh +47 -0
- package/scripts/lint-ratchet.py +1547 -0
- package/scripts/monitor-pr-checks.sh +441 -0
- package/scripts/pipeline-tally.sh +756 -0
- package/scripts/pipeline-tally.test.sh +740 -0
- package/scripts/plugin-version.sh +528 -0
- package/scripts/precommit-guard.sh +113 -0
- package/scripts/precommit-guard.test.sh +254 -0
- package/scripts/reconcile-live-heartbeats.ts +705 -0
- package/scripts/render-c4-model.sh +217 -0
- package/scripts/resolve-git-root.sh +55 -0
- package/scripts/resolve-regenerable-conflicts.sh +363 -0
- package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
- package/scripts/ruff-requirements.txt +22 -0
- package/scripts/run-in-pid-namespace.sh +98 -0
- package/scripts/run-in-pid-namespace.test.sh +290 -0
- package/scripts/scan-ancestor-signal-helpers.py +556 -0
- package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
- package/scripts/setup-ralph-loop.sh +238 -0
- package/scripts/sync-cursor-name-map.ts +316 -0
- package/scripts/sync-grok-agent-compat.ts +188 -0
- package/scripts/sync-npm-package.ts +178 -0
- package/scripts/sync-opencode-adapter.ts +479 -0
- package/scripts/sync-pr-behind.sh +534 -0
- package/scripts/sync-pr-behind.test.sh +252 -0
- package/scripts/taste-profile-update.sh +180 -0
- package/scripts/taste-profile-update.test.sh +167 -0
- package/scripts/write-budget-marker.sh +23 -0
- package/scripts/write-kb-coverage.ts +113 -0
- package/skills/admin-ip-refresh/SKILL.md +81 -0
- package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
- package/skills/agent-browser/SKILL.md +698 -0
- package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
- package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
- package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
- package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
- package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
- package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
- package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
- package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
- package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
- package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
- package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
- package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
- package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
- package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
- package/skills/agent-native-architecture/SKILL.md +479 -0
- package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
- package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
- package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
- package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
- package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
- package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
- package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
- package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
- package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
- package/skills/agent-native-architecture/references/product-implications.md +478 -0
- package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
- package/skills/agent-native-architecture/references/self-modification.md +294 -0
- package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
- package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
- package/skills/agent-native-audit/SKILL.md +300 -0
- package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
- package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
- package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
- package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
- package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
- package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
- package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
- package/skills/architecture/SKILL.md +436 -0
- package/skills/architecture/references/adr-template.md +154 -0
- package/skills/architecture/references/likec4-reference.md +136 -0
- package/skills/architecture/references/nfr-reference.md +126 -0
- package/skills/archive-kb/SKILL.md +86 -0
- package/skills/archive-kb/scripts/archive-kb.sh +300 -0
- package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
- package/skills/atdd-developer/SKILL.md +65 -0
- package/skills/brainstorm/SKILL.md +701 -0
- package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
- package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
- package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
- package/skills/brainstorm/references/ui-surface-terms.md +42 -0
- package/skills/brainstorm-techniques/SKILL.md +231 -0
- package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
- package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
- package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
- package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
- package/skills/campaign-calendar/SKILL.md +145 -0
- package/skills/cf-token-scope/SKILL.md +164 -0
- package/skills/cf-token-scope/references/widen-playbook.md +114 -0
- package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
- package/skills/changelog/SKILL.md +142 -0
- package/skills/code-to-prd/SKILL.md +66 -0
- package/skills/code-to-prd/references/banner-template.md +12 -0
- package/skills/code-to-prd/references/prd-template.md +41 -0
- package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
- package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
- package/skills/code-to-prd/test/fixture/.env.example +7 -0
- package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
- package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
- package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
- package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
- package/skills/code-to-prd/test/fixture/package.json +6 -0
- package/skills/cohort-status/SKILL.md +62 -0
- package/skills/community/SKILL.md +210 -0
- package/skills/community/scripts/bsky-community.sh +644 -0
- package/skills/community/scripts/bsky-setup.sh +631 -0
- package/skills/community/scripts/community-router.sh +93 -0
- package/skills/community/scripts/discord-community.sh +487 -0
- package/skills/community/scripts/discord-setup.sh +784 -0
- package/skills/community/scripts/github-community.sh +706 -0
- package/skills/community/scripts/hn-community.sh +233 -0
- package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
- package/skills/community/scripts/linkedin-community.sh +750 -0
- package/skills/community/scripts/linkedin-setup.sh +758 -0
- package/skills/community/scripts/x-community.sh +890 -0
- package/skills/community/scripts/x-setup.sh +713 -0
- package/skills/community/test/community-argv.test.sh +2922 -0
- package/skills/community/test/github-community.test.sh +981 -0
- package/skills/competitive-analysis/SKILL.md +69 -0
- package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
- package/skills/compound/SKILL.md +673 -0
- package/skills/compound/scripts/token-efficiency-report.sh +334 -0
- package/skills/compound/test/phase-16.test.sh +379 -0
- package/skills/compound-capture/SKILL.md +791 -0
- package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
- package/skills/compound-capture/assets/resolution-template.md +116 -0
- package/skills/compound-capture/references/yaml-schema.md +67 -0
- package/skills/compound-capture/schema.yaml +181 -0
- package/skills/constraint-scaffold/SKILL.md +175 -0
- package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
- package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
- package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
- package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
- package/skills/constraint-scaffold/references/shared-runner.template +135 -0
- package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
- package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
- package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
- package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
- package/skills/constraint-scaffold/test/generator.test.sh +93 -0
- package/skills/constraint-scaffold/test/parity.test.sh +285 -0
- package/skills/content-writer/SKILL.md +242 -0
- package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
- package/skills/cron-delete/SKILL.md +56 -0
- package/skills/cron-list/SKILL.md +54 -0
- package/skills/deepen-plan/SKILL.md +937 -0
- package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
- package/skills/deploy/SKILL.md +115 -0
- package/skills/deploy/references/hetzner-setup.md +65 -0
- package/skills/deploy/scripts/deploy.sh +37 -0
- package/skills/deploy-docs/SKILL.md +95 -0
- package/skills/dhh-rails-style/SKILL.md +203 -0
- package/skills/dhh-rails-style/references/architecture.md +717 -0
- package/skills/dhh-rails-style/references/controllers.md +323 -0
- package/skills/dhh-rails-style/references/frontend.md +556 -0
- package/skills/dhh-rails-style/references/gems.md +316 -0
- package/skills/dhh-rails-style/references/models.md +388 -0
- package/skills/dhh-rails-style/references/testing.md +354 -0
- package/skills/discord-content/SKILL.md +126 -0
- package/skills/docs-site/SKILL.md +214 -0
- package/skills/drain-labeled-backlog/SKILL.md +203 -0
- package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
- package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
- package/skills/drain-prs/SKILL.md +142 -0
- package/skills/drain-prs/scripts/triage-prs.sh +192 -0
- package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
- package/skills/dspy-ruby/SKILL.md +634 -0
- package/skills/dspy-ruby/assets/config-template.rb +359 -0
- package/skills/dspy-ruby/assets/module-template.rb +326 -0
- package/skills/dspy-ruby/assets/signature-template.rb +143 -0
- package/skills/dspy-ruby/references/core-concepts.md +268 -0
- package/skills/dspy-ruby/references/optimization.md +623 -0
- package/skills/dspy-ruby/references/providers.md +335 -0
- package/skills/eval-harness/README.md +194 -0
- package/skills/eval-harness/SKILL.md +157 -0
- package/skills/eval-harness/enums/go-routes.json +13 -0
- package/skills/eval-harness/enums/incident-threshold.json +5 -0
- package/skills/eval-harness/enums/lane.json +5 -0
- package/skills/eval-harness/enums/tool-selection.json +20 -0
- package/skills/eval-harness/enums/triage-levels.json +5 -0
- package/skills/eval-harness/gated-skills.json +34 -0
- package/skills/eval-harness/models.generated.json +5 -0
- package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
- package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
- package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
- package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
- package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
- package/skills/eval-harness/prompts/go-baseline.txt +6 -0
- package/skills/eval-harness/prompts/go-skill.txt +21 -0
- package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
- package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
- package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
- package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
- package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
- package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
- package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
- package/skills/eval-harness/prompts/triage-skill.txt +10 -0
- package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
- package/skills/eval-harness/scripts/extract-block.cjs +87 -0
- package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
- package/skills/eval-harness/scripts/gen-models.sh +41 -0
- package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
- package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
- package/skills/eval-harness/scripts/parse-label.cjs +93 -0
- package/skills/eval-harness/scripts/verdict.cjs +132 -0
- package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
- package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
- package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
- package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
- package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
- package/skills/eval-harness/test/eval-gate.test.sh +132 -0
- package/skills/eval-harness/test/extract-block.test.sh +87 -0
- package/skills/eval-harness/test/gate-classification.test.sh +77 -0
- package/skills/eval-harness/test/gen-models.test.sh +75 -0
- package/skills/eval-harness/test/measure-classification.test.sh +74 -0
- package/skills/eval-harness/test/parse-label.test.sh +129 -0
- package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
- package/skills/eval-harness/test/verdict.test.sh +123 -0
- package/skills/every-style-editor/SKILL.md +142 -0
- package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
- package/skills/feature-tweet/SKILL.md +199 -0
- package/skills/feature-video/SKILL.md +412 -0
- package/skills/feature-video/scripts/check_deps.sh +281 -0
- package/skills/file-todos/SKILL.md +267 -0
- package/skills/file-todos/assets/todo-template.md +166 -0
- package/skills/fix-issue/SKILL.md +278 -0
- package/skills/fix-issue/references/agent-authored-exclusion.md +118 -0
- package/skills/fix-issue/references/exclude-label-jq-snippet.md +96 -0
- package/skills/flag-bootstrap/SETUP.md +142 -0
- package/skills/flag-create/SKILL.md +145 -0
- package/skills/flag-create/scripts/create.sh +273 -0
- package/skills/flag-delete/SKILL.md +167 -0
- package/skills/flag-delete/scripts/delete.sh +288 -0
- package/skills/flag-list/SKILL.md +99 -0
- package/skills/flag-list/scripts/list.sh +275 -0
- package/skills/flag-set-role/SKILL.md +229 -0
- package/skills/flag-set-role/scripts/flip.sh +774 -0
- package/skills/frontend-anti-slop/SKILL.md +106 -0
- package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
- package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
- package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
- package/skills/frontend-design/SKILL.md +77 -0
- package/skills/gdpr-gate/NOTICE +136 -0
- package/skills/gdpr-gate/SKILL.md +341 -0
- package/skills/gdpr-gate/references/fields.md +160 -0
- package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
- package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
- package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
- package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
- package/skills/gdpr-gate/references/layers/frontend.md +249 -0
- package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
- package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
- package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
- package/skills/gdpr-gate/references/legal-consent.md +140 -0
- package/skills/gdpr-gate/references/non-negotiables.md +60 -0
- package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
- package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
- package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
- package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
- package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
- package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
- package/skills/gemini-imagegen/SKILL.md +283 -0
- package/skills/gemini-imagegen/requirements.txt +5 -0
- package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
- package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
- package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
- package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
- package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
- package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
- package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
- package/skills/git-worktree/SKILL.md +534 -0
- package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
- package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
- package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
- package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
- package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
- package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
- package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
- package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
- package/skills/go/SKILL.md +54 -0
- package/skills/growth/SKILL.md +164 -0
- package/skills/harvest-debt/SKILL.md +78 -0
- package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
- package/skills/heal-skill/SKILL.md +173 -0
- package/skills/help/SKILL.md +46 -0
- package/skills/incident/NOTICE +39 -0
- package/skills/incident/SKILL.md +395 -0
- package/skills/incident/scripts/dry-run.sh +448 -0
- package/skills/incident/scripts/redact-engine.py +412 -0
- package/skills/incident/scripts/redact-sentinel.sh +44 -0
- package/skills/incident/templates/pir.md +139 -0
- package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
- package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
- package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
- package/skills/incident/test/fixtures/positive-corpus.md +87 -0
- package/skills/incident/test/redact-sentinel.test.sh +1420 -0
- package/skills/invoice/SKILL.md +206 -0
- package/skills/kb-glossary/SKILL.md +71 -0
- package/skills/kb-glossary/references/glossary-format.md +111 -0
- package/skills/kb-glossary/references/rejected-request-register.md +115 -0
- package/skills/kb-search/SKILL.md +276 -0
- package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
- package/skills/legal-audit/SKILL.md +161 -0
- package/skills/legal-generate/NOTICE +242 -0
- package/skills/legal-generate/SKILL.md +244 -0
- package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
- package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
- package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
- package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
- package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
- package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
- package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
- package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
- package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
- package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
- package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
- package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
- package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
- package/skills/linear-fetch/SKILL.md +247 -0
- package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
- package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
- package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
- package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
- package/skills/linear-fetch/test/parity.test.sh +112 -0
- package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
- package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
- package/skills/merge-pr/SKILL.md +668 -0
- package/skills/model-launch-review/SKILL.md +255 -0
- package/skills/model-launch-review/scripts/audit-models.sh +501 -0
- package/skills/one-shot/SKILL.md +316 -0
- package/skills/one-shot/references/token-discipline.md +74 -0
- package/skills/operator-bootstrap/SKILL.md +412 -0
- package/skills/operator-bootstrap/template.sh +439 -0
- package/skills/operator-digest/SKILL.md +287 -0
- package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
- package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
- package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
- package/skills/operator-rephrase/SKILL.md +98 -0
- package/skills/pencil-setup/SKILL.md +201 -0
- package/skills/pencil-setup/scripts/check_deps.sh +556 -0
- package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
- package/skills/pencil-setup/scripts/package-lock.json +1172 -0
- package/skills/pencil-setup/scripts/package.json +14 -0
- package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
- package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
- package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
- package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
- package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
- package/skills/plan/SKILL.md +1140 -0
- package/skills/plan/references/differential-migration-testing.md +185 -0
- package/skills/plan/references/plan-community-discovery.md +42 -0
- package/skills/plan/references/plan-founder-check.md +137 -0
- package/skills/plan/references/plan-functional-overlap.md +25 -0
- package/skills/plan/references/plan-host-fanout.md +51 -0
- package/skills/plan/references/plan-issue-templates.md +779 -0
- package/skills/plan/references/plan-network-outage-checklist.md +131 -0
- package/skills/plan/references/plan-scope-check.md +126 -0
- package/skills/plan/references/plan-sharp-edges.md +325 -0
- package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
- package/skills/plan/references/webapp-cwv-observability.md +143 -0
- package/skills/plan-review/SKILL.md +91 -0
- package/skills/plan-review/lib/named-panel.mjs +58 -0
- package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
- package/skills/postmerge/SKILL.md +642 -0
- package/skills/postmerge/references/deploy-status-debugging.md +138 -0
- package/skills/postmerge/references/graceful-degradation.md +20 -0
- package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
- package/skills/preflight/SKILL.md +1553 -0
- package/skills/preflight/references/check-13-founder-check.md +286 -0
- package/skills/preflight/scripts/founder-check.py +1640 -0
- package/skills/preflight/scripts/parse-form-a.awk +107 -0
- package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
- package/skills/product-roadmap/SKILL.md +357 -0
- package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
- package/skills/provision-cloudflare/SKILL.md +67 -0
- package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
- package/skills/provision-doppler/SKILL.md +58 -0
- package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
- package/skills/provision-github/SKILL.md +59 -0
- package/skills/provision-github/scripts/provision-github.sh +300 -0
- package/skills/provision-hetzner/SKILL.md +76 -0
- package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
- package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
- package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
- package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
- package/skills/qa/SKILL.md +263 -0
- package/skills/qa/references/browser-preflight.md +22 -0
- package/skills/questionnaire-generate/SKILL.md +328 -0
- package/skills/questionnaire-generate/references/questionnaire.template +60 -0
- package/skills/rclone/SKILL.md +162 -0
- package/skills/rclone/scripts/check_setup.sh +63 -0
- package/skills/release-announce/SKILL.md +65 -0
- package/skills/release-docs/SKILL.md +92 -0
- package/skills/reproduce-bug/SKILL.md +358 -0
- package/skills/resolve-debt/SKILL.md +85 -0
- package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
- package/skills/resolve-parallel/SKILL.md +45 -0
- package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
- package/skills/resolve-pr-parallel/SKILL.md +68 -0
- package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
- package/skills/resolve-todo-parallel/SKILL.md +57 -0
- package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
- package/skills/review/SKILL.md +1621 -0
- package/skills/review/references/anti-slop-scanner-hook.md +40 -0
- package/skills/review/references/defect-classes-migrations.md +9 -0
- package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
- package/skills/review/references/review-e2e-testing.md +116 -0
- package/skills/review/references/review-todo-structure.md +165 -0
- package/skills/review/references/risk-tier-and-fix-rounds.md +95 -0
- package/skills/review/references/semgrep-custom-rules.yaml +174 -0
- package/skills/review/references/ultrathink-phases.md +98 -0
- package/skills/review/references/wfs.md +6 -0
- package/skills/review/scripts/emit-review-trailer.sh +499 -0
- package/skills/review/scripts/ensure-semgrep.sh +99 -0
- package/skills/review/scripts/fix-round-seats.sh +197 -0
- package/skills/review/test/emit-review-trailer.test.sh +387 -0
- package/skills/review/test/ensure-semgrep.test.sh +111 -0
- package/skills/review/test/fix-round-seats.test.sh +237 -0
- package/skills/review/workflows/README.md +147 -0
- package/skills/review/workflows/review.workflow.js +667 -0
- package/skills/schedule/SKILL.md +796 -0
- package/skills/seo-aeo/SKILL.md +139 -0
- package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
- package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
- package/skills/ship/SKILL.md +3022 -0
- package/skills/ship/references/adr-ordinal-collision.md +47 -0
- package/skills/ship/references/affected-gate-contract.md +115 -0
- package/skills/ship/references/ci-run-diagnosis.md +29 -0
- package/skills/ship/references/ci-workflow-authoring.md +68 -0
- package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
- package/skills/ship/references/cto-ruling-armed-push.md +5 -0
- package/skills/ship/references/decision-challenges-render.md +71 -0
- package/skills/ship/references/detached-battery-verdict.md +13 -0
- package/skills/ship/references/feature-tweet-draft.md +42 -0
- package/skills/ship/references/followthrough-issue-body-template.md +47 -0
- package/skills/ship/references/followthrough-stub-template.sh +92 -0
- package/skills/ship/references/merge-queue-dequeue.md +39 -0
- package/skills/ship/references/operator-holds.md +149 -0
- package/skills/ship/references/pipeline-tally-render.md +43 -0
- package/skills/ship/references/pr-overlap.md +153 -0
- package/skills/ship/references/queue-mode.md +7 -0
- package/skills/ship/references/ready-run-wait.md +36 -0
- package/skills/ship/references/red-on-main-quarantine.md +110 -0
- package/skills/ship/references/register-update-pr-pattern.md +88 -0
- package/skills/ship/references/settle-then-admin-merge.md +130 -0
- package/skills/ship/references/supabase-column-probe.md +13 -0
- package/skills/ship/scripts/auto-close-scan.sh +76 -0
- package/skills/ship/scripts/battery-owed.sh +403 -0
- package/skills/ship/scripts/hold-gate-eval.sh +410 -0
- package/skills/ship/scripts/net-issue-flow.sh +665 -0
- package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
- package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
- package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
- package/skills/skill-creator/SKILL.md +299 -0
- package/skills/skill-creator/references/api-security.md +248 -0
- package/skills/skill-creator/references/authoring-levers.md +110 -0
- package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
- package/skills/skill-creator/references/best-practices.md +431 -0
- package/skills/skill-creator/references/common-patterns.md +639 -0
- package/skills/skill-creator/references/core-principles.md +193 -0
- package/skills/skill-creator/references/executable-code.md +188 -0
- package/skills/skill-creator/references/iteration-and-testing.md +509 -0
- package/skills/skill-creator/references/official-spec.md +193 -0
- package/skills/skill-creator/references/recommended-structure.md +180 -0
- package/skills/skill-creator/references/skill-structure.md +396 -0
- package/skills/skill-creator/references/using-scripts.md +122 -0
- package/skills/skill-creator/references/using-templates.md +120 -0
- package/skills/skill-creator/references/workflows-and-validation.md +541 -0
- package/skills/skill-creator/scripts/init_skill.py +322 -0
- package/skills/skill-creator/scripts/package_skill.py +110 -0
- package/skills/skill-creator/scripts/quick_validate.py +64 -0
- package/skills/skill-creator/templates/router-skill.md +73 -0
- package/skills/skill-creator/templates/simple-skill.md +34 -0
- package/skills/skill-creator/workflows/add-reference.md +96 -0
- package/skills/skill-creator/workflows/add-script.md +104 -0
- package/skills/skill-creator/workflows/add-template.md +83 -0
- package/skills/skill-creator/workflows/add-workflow.md +128 -0
- package/skills/skill-creator/workflows/audit-skill.md +159 -0
- package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
- package/skills/skill-creator/workflows/create-new-skill.md +207 -0
- package/skills/skill-creator/workflows/get-guidance.md +134 -0
- package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
- package/skills/skill-creator/workflows/verify-skill.md +226 -0
- package/skills/skill-security-scan/SKILL.md +145 -0
- package/skills/skill-security-scan/references/disclaimer.md +21 -0
- package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
- package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
- package/skills/skill-security-scan/references/override-mechanism.md +171 -0
- package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
- package/skills/skill-security-scan/references/regex-patterns.md +136 -0
- package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
- package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
- package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
- package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
- package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
- package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
- package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
- package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
- package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
- package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
- package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
- package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
- package/skills/skill-security-scan/scripts/lib.sh +197 -0
- package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
- package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
- package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
- package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
- package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
- package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
- package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
- package/skills/social-distribute/SKILL.md +485 -0
- package/skills/spec-templates/SKILL.md +274 -0
- package/skills/sync/SKILL.md +49 -0
- package/skills/test-browser/SKILL.md +464 -0
- package/skills/test-browser/references/feature-map.md +161 -0
- package/skills/test-fix-loop/SKILL.md +159 -0
- package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
- package/skills/triage/SKILL.md +402 -0
- package/skills/trigger-cron/SKILL.md +136 -0
- package/skills/trigger-cron/scripts/trigger.sh +198 -0
- package/skills/user-set-role/SKILL.md +147 -0
- package/skills/user-set-role/scripts/set-role.sh +218 -0
- package/skills/user-story-writer/SKILL.md +77 -0
- package/skills/ux-audit/SKILL.md +251 -0
- package/skills/ux-audit/references/finding.schema.json +62 -0
- package/skills/ux-audit/references/route-list.yaml +95 -0
- package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
- package/skills/ux-audit/scripts/bot-signin.ts +135 -0
- package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
- package/skills/work/SKILL.md +1479 -0
- package/skills/work/references/end-of-work-resume.md +7 -0
- package/skills/work/references/hook-test-main-cwd.md +24 -0
- package/skills/work/references/key-principles.md +83 -0
- package/skills/work/references/property-testing.md +122 -0
- package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
- package/skills/work/references/work-agent-teams.md +97 -0
- package/skills/work/references/work-lifecycle-parallel.md +147 -0
- package/skills/work/references/work-lockfile-bumps.md +97 -0
- package/skills/work/references/work-scratch-sandboxes.md +212 -0
- package/skills/work/references/work-subagent-fanout.md +61 -0
- package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
- package/skills/xcode-test/SKILL.md +360 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# roadmap-reconcile.sh — READ-ONLY roadmap↔GitHub reconcile module.
|
|
4
|
+
#
|
|
5
|
+
# Shared core behind `product-roadmap validate` (drift report) and `next`
|
|
6
|
+
# (advisory next-action). Part of feat-roadmap-program-layer's report-only
|
|
7
|
+
# design: this module NEVER writes to roadmap.md or any file. When drift is
|
|
8
|
+
# found, remediation routes through the existing cron-roadmap-review.ts (the
|
|
9
|
+
# sole writer, via reviewed fix PRs) — see ADR-033 / ADR-054.
|
|
10
|
+
#
|
|
11
|
+
# Verdict vocabulary mirrors cron-roadmap-review.ts's prompt:
|
|
12
|
+
# STALE_STATUS — roadmap count cell disagrees with the live milestone
|
|
13
|
+
# MISSING_ISSUE — a roadmap Phase row resolves to no GitHub milestone
|
|
14
|
+
# EMPTY_MILESTONE — a milestone has 0 open AND 0 closed issues
|
|
15
|
+
#
|
|
16
|
+
# Public functions (sourced by plugins/soleur/test/roadmap-reconcile.test.sh):
|
|
17
|
+
# extract_phase_counts stdin: roadmap md -> "N|open|closed" per Phase row
|
|
18
|
+
# reconcile_counts ROADMAP MS files: roadmap, milestones-json -> verdict lines
|
|
19
|
+
# pick_next_action ISSUES file: open-issues-json -> CODEABLE|OPERATOR|NONE line
|
|
20
|
+
# pick_phase MS file: milestones-json -> "N|title" of the live phase, or empty
|
|
21
|
+
# filter_frontier ISSUES file: open-issues-json -> {frontier,blocked,claimed}
|
|
22
|
+
#
|
|
23
|
+
# pick_phase depends on milestones being titled `Phase N: ...`. The frontier is a
|
|
24
|
+
# phase's open issues with no open blocker (GitHub-native "blocked by" edges) and
|
|
25
|
+
# no assignee; it needs `gh` >= 2.94.0, the first release exposing `blockedBy`.
|
|
26
|
+
#
|
|
27
|
+
# Milestone↔phase is NOT 1:1 (the Phase-N milestone also holds internal-tooling
|
|
28
|
+
# issues not on roadmap rows); reconcile keys strictly off the Current-State
|
|
29
|
+
# count cell, never feature-row tallies.
|
|
30
|
+
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
|
|
33
|
+
ROADMAP_FILE="${ROADMAP_FILE:-knowledge-base/product/roadmap.md}"
|
|
34
|
+
|
|
35
|
+
# Labels that mark an issue as codeable (an agent can build it via /soleur:go).
|
|
36
|
+
# Deliberately narrow: anything else (recruitment, interviews, research, marketing,
|
|
37
|
+
# ops, chores) classifies as an operator action. Under-classifying to OPERATOR is
|
|
38
|
+
# the safe failure for an advisory tool — it only ever NAMES the item, never wrongly
|
|
39
|
+
# tells the founder to /soleur:go a non-codeable task.
|
|
40
|
+
CODEABLE_LABELS='"domain/engineering","type/bug","type/feature","type/refactor"'
|
|
41
|
+
|
|
42
|
+
# A non-engineering domain-leader label means the work is operator-driven (marketing,
|
|
43
|
+
# legal, ops, sales, finance, support, product) — it OVERRIDES a codeable type/* label.
|
|
44
|
+
# Caught by dogfooding: #2603 ("Publish a case study") is type/feature + domain/marketing
|
|
45
|
+
# and must classify OPERATOR, not CODEABLE — never tell the founder to /soleur:go it.
|
|
46
|
+
OPERATOR_DOMAIN_LABELS='"domain/marketing","domain/legal","domain/operations","domain/sales","domain/finance","domain/support","domain/product"'
|
|
47
|
+
|
|
48
|
+
# extract_phase_counts: read roadmap markdown on stdin, emit "N|open|closed"
|
|
49
|
+
# for each `| Phase N (...) |` row in the `## Current State` table that carries
|
|
50
|
+
# an "X open, Y closed" count. Rows without counts (prose, Beta users) are skipped.
|
|
51
|
+
extract_phase_counts() {
|
|
52
|
+
awk '
|
|
53
|
+
/^## Current State/ { inblock = 1; next }
|
|
54
|
+
inblock && /^## / { inblock = 0 }
|
|
55
|
+
inblock { print }
|
|
56
|
+
' \
|
|
57
|
+
| grep -E '^\| Phase [0-9]+' \
|
|
58
|
+
| while IFS= read -r line; do
|
|
59
|
+
grep -qE '[0-9]+ open, [0-9]+ closed' <<<"$line" || continue
|
|
60
|
+
num="$(printf '%s\n' "$line" | sed -E 's/^\| Phase ([0-9]+).*/\1/')"
|
|
61
|
+
counts="$(printf '%s\n' "$line" | grep -oE '[0-9]+ open, [0-9]+ closed' | head -1)"
|
|
62
|
+
open="$(printf '%s\n' "$counts" | sed -E 's/^([0-9]+) open.*/\1/')"
|
|
63
|
+
closed="$(printf '%s\n' "$counts" | sed -E 's/^[0-9]+ open, ([0-9]+) closed/\1/')"
|
|
64
|
+
printf '%s|%s|%s\n' "$num" "$open" "$closed"
|
|
65
|
+
done
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# reconcile_counts ROADMAP_FILE MILESTONES_JSON_FILE: emit verdict lines.
|
|
69
|
+
reconcile_counts() {
|
|
70
|
+
local roadmap_file="$1" milestones_file="$2"
|
|
71
|
+
local rows num ropen rclosed found mopen mclosed ms_json
|
|
72
|
+
# Slurp milestones ONCE — the caller may pass a process-substitution FIFO,
|
|
73
|
+
# which drains on first read; re-reading it per loop iteration would yield
|
|
74
|
+
# empty and spuriously emit MISSING_ISSUE for every phase after the first.
|
|
75
|
+
ms_json="$(cat "$milestones_file")"
|
|
76
|
+
rows="$(extract_phase_counts < "$roadmap_file")"
|
|
77
|
+
[[ -z "$rows" ]] && return 0
|
|
78
|
+
while IFS='|' read -r num ropen rclosed; do
|
|
79
|
+
[[ -z "${num:-}" ]] && continue
|
|
80
|
+
found="$(jq -r --arg n "$num" '
|
|
81
|
+
[ .[] | select(.title | test("^Phase " + $n + "[:( ]")) ] | first
|
|
82
|
+
| if . == null then empty else "\(.open_issues)|\(.closed_issues)" end' \
|
|
83
|
+
<<< "$ms_json")"
|
|
84
|
+
if [[ -z "$found" ]]; then
|
|
85
|
+
printf 'MISSING_ISSUE|phase %s|roadmap=%so/%sc|milestone=none\n' "$num" "$ropen" "$rclosed"
|
|
86
|
+
continue
|
|
87
|
+
fi
|
|
88
|
+
mopen="${found%%|*}"
|
|
89
|
+
mclosed="${found##*|}"
|
|
90
|
+
if [[ "$mopen" -eq 0 && "$mclosed" -eq 0 ]]; then
|
|
91
|
+
printf 'EMPTY_MILESTONE|phase %s|milestone=0o/0c\n' "$num"
|
|
92
|
+
fi
|
|
93
|
+
if [[ "$mopen" != "$ropen" || "$mclosed" != "$rclosed" ]]; then
|
|
94
|
+
printf 'STALE_STATUS|phase %s|roadmap=%so/%sc|milestone=%so/%sc\n' \
|
|
95
|
+
"$num" "$ropen" "$rclosed" "$mopen" "$mclosed"
|
|
96
|
+
fi
|
|
97
|
+
done <<< "$rows"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# jq helpers shared by every line this module prints about an issue. `clean`
|
|
101
|
+
# makes a title safe to print as the last field of a `|`-separated line: issue
|
|
102
|
+
# titles are attacker-authorable on a public repo, and a newline in one could
|
|
103
|
+
# otherwise forge a whole extra `CODEABLE|#N|…` line. `classify` is the single
|
|
104
|
+
# CODEABLE-vs-OPERATOR rule, used by both `next` and `next --frontier`.
|
|
105
|
+
ISSUE_JQ_DEFS="
|
|
106
|
+
def clean: (.title // \"\") | gsub(\"[[:cntrl:]\\u2028\\u2029]\"; \" \") | gsub(\"[|]\"; \"/\");
|
|
107
|
+
def classify: if any(.labels[]?.name; IN($OPERATOR_DOMAIN_LABELS)) then \"OPERATOR\"
|
|
108
|
+
elif any(.labels[]?.name; IN($CODEABLE_LABELS)) then \"CODEABLE\"
|
|
109
|
+
else \"OPERATOR\" end;
|
|
110
|
+
"
|
|
111
|
+
|
|
112
|
+
# pick_next_action OPEN_ISSUES_JSON_FILE: lowest-numbered open issue first
|
|
113
|
+
# (deterministic tie-break), classified CODEABLE vs OPERATOR by label; explicit
|
|
114
|
+
# NONE when the set is empty (never silent). One jq pass.
|
|
115
|
+
pick_next_action() {
|
|
116
|
+
local line
|
|
117
|
+
line="$(jq -r "$ISSUE_JQ_DEFS"'
|
|
118
|
+
sort_by(.number) | (first // empty) | "\(classify)|#\(.number)|\(clean)"' "$1")" || return 2
|
|
119
|
+
if [[ -z "$line" ]]; then
|
|
120
|
+
echo "NONE|no actionable next item"
|
|
121
|
+
return 0
|
|
122
|
+
fi
|
|
123
|
+
printf '%s\n' "$line"
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# pick_phase MILESTONES_JSON_FILE: the lowest-numbered OPEN `Phase N` milestone
|
|
127
|
+
# that still has open issues, as "N|title"; empty when none. Read from live
|
|
128
|
+
# milestones, not the roadmap's Current State cells: a phase row may carry no
|
|
129
|
+
# frozen count, and skipping it picked the phase after it.
|
|
130
|
+
# Known edge: the REST open_issues count includes open pull requests, so a
|
|
131
|
+
# phase whose only open items are PRs is still picked (its frontier is empty).
|
|
132
|
+
pick_phase() {
|
|
133
|
+
jq -r '
|
|
134
|
+
[ .[] | select(.state == "open" and (.open_issues // 0) > 0)
|
|
135
|
+
| select(.title | test("^Phase [0-9]+[:( ]"))
|
|
136
|
+
| {n: (.title | capture("^Phase (?<n>[0-9]+)").n | tonumber), title} ]
|
|
137
|
+
| sort_by(.n) | (first // empty) | "\(.n)|\(.title)"' "$1"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# filter_frontier OPEN_ISSUES_JSON_FILE: split a phase's open issues into the
|
|
141
|
+
# frontier (no open blocker, no assignee; sorted by number) and the held-back
|
|
142
|
+
# sets. Fails closed: a blocker counts as resolved only when its node reads
|
|
143
|
+
# CLOSED. An issue with an OPEN blocker is `blocked`; one whose blockers could
|
|
144
|
+
# not all be read (count above the nodes returned — a blocker in a repo the
|
|
145
|
+
# token cannot see, or a truncated page — or a node whose state is neither OPEN
|
|
146
|
+
# nor CLOSED) is `unverified`, held back but reported separately so "could not
|
|
147
|
+
# check" never reads as "waiting". Blockers in any repository count. Returns 2,
|
|
148
|
+
# naming the field, when number is not a number, blockedBy not an object or
|
|
149
|
+
# assignees not an array (a missing or null field would otherwise read as
|
|
150
|
+
# unblocked and unclaimed, and a string number could carry a forged line).
|
|
151
|
+
# ONE jq pass: callers may pass a FIFO.
|
|
152
|
+
filter_frontier() {
|
|
153
|
+
local out
|
|
154
|
+
out="$(jq -c '
|
|
155
|
+
def nodes: (.blockedBy.nodes // []);
|
|
156
|
+
def blocked: any(nodes[]; .state == "OPEN");
|
|
157
|
+
def held: ((.blockedBy.totalCount // 0) > (nodes | length)) or any(nodes[]; .state != "CLOSED");
|
|
158
|
+
def claimed: ((.assignees // []) | length) > 0;
|
|
159
|
+
([ .[] | ((if (.number | type) == "number" then empty else "number" end),
|
|
160
|
+
(if (.blockedBy | type) == "object" then empty else "blockedBy" end),
|
|
161
|
+
(if (.assignees | type) == "array" then empty else "assignees" end)) ]
|
|
162
|
+
| unique) as $missing
|
|
163
|
+
| if ($missing | length) > 0 then {missing: $missing}
|
|
164
|
+
else { frontier: ([ .[] | select((held | not) and (claimed | not)) ] | sort_by(.number)),
|
|
165
|
+
blocked: ([ .[] | select(blocked) ] | sort_by(.number)),
|
|
166
|
+
unverified: ([ .[] | select(held and (blocked | not)) ] | sort_by(.number)),
|
|
167
|
+
claimed: ([ .[] | select((held | not) and claimed) ] | sort_by(.number)) }
|
|
168
|
+
end' "$1")" || return 2
|
|
169
|
+
if [[ "$(jq -r 'has("missing")' <<< "$out")" == "true" ]]; then
|
|
170
|
+
echo "roadmap-reconcile: ERROR — issue data lacks field(s): $(jq -r '.missing | join(", ")' <<< "$out") (needs gh >= 2.94.0)." >&2
|
|
171
|
+
return 2
|
|
172
|
+
fi
|
|
173
|
+
printf '%s\n' "$out"
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
# --- CLI entrypoint (only when executed directly, never when sourced) ---
|
|
177
|
+
_milestones_json() {
|
|
178
|
+
gh api 'repos/{owner}/{repo}/milestones?state=all&per_page=100' \
|
|
179
|
+
--jq '[ .[] | {title, state, open_issues, closed_issues} ]'
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
_usage() {
|
|
183
|
+
echo "usage: roadmap-reconcile.sh [validate|next [--frontier]]" >&2
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
# Held-back counts in the founder's words (DC-6), from filter_frontier output.
|
|
187
|
+
_held_text() {
|
|
188
|
+
jq -r '"\(.blocked | length) waiting on another issue"
|
|
189
|
+
+ (if (.unverified | length) > 0 then ", \(.unverified | length) whose blockers could not be read" else "" end)
|
|
190
|
+
+ ", \(.claimed | length) with someone on it"' <<< "$1"
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
main() {
|
|
194
|
+
local mode="${1:-validate}"
|
|
195
|
+
[[ $# -gt 0 ]] && shift
|
|
196
|
+
case "$mode" in
|
|
197
|
+
validate)
|
|
198
|
+
if [[ $# -gt 0 ]]; then
|
|
199
|
+
_usage
|
|
200
|
+
return 64
|
|
201
|
+
fi
|
|
202
|
+
local ms verdicts
|
|
203
|
+
if ! ms="$(_milestones_json 2>/dev/null)"; then
|
|
204
|
+
echo "roadmap-reconcile: ERROR — could not fetch GitHub milestones (gh auth?)." >&2
|
|
205
|
+
return 2
|
|
206
|
+
fi
|
|
207
|
+
verdicts="$(reconcile_counts "$ROADMAP_FILE" <(printf '%s' "$ms"))"
|
|
208
|
+
if [[ -z "$verdicts" ]]; then
|
|
209
|
+
echo "roadmap-validate: clean — Current State counts match GitHub milestones."
|
|
210
|
+
return 0
|
|
211
|
+
fi
|
|
212
|
+
echo "roadmap-validate: drift detected (read-only — no file was modified)"
|
|
213
|
+
echo "$verdicts"
|
|
214
|
+
echo ""
|
|
215
|
+
echo "To fix: trigger the roadmap-review cron, which opens a reviewed PR:"
|
|
216
|
+
echo " /soleur:trigger-cron cron/roadmap-review.manual-trigger"
|
|
217
|
+
return 1
|
|
218
|
+
;;
|
|
219
|
+
next)
|
|
220
|
+
# Advisory, read-only: the next action for the live phase, chosen from its
|
|
221
|
+
# frontier (open, no open blocker, no assignee). `--frontier` lists it all.
|
|
222
|
+
# Exit contract: 0 = answer printed; 2 = the data could not be trusted
|
|
223
|
+
# (fetch failure, old gh, unparseable data) — never "nothing to do";
|
|
224
|
+
# 64 = usage.
|
|
225
|
+
local frontier_mode=0 pfx=roadmap-next
|
|
226
|
+
if [[ $# -eq 1 && "$1" == "--frontier" ]]; then
|
|
227
|
+
frontier_mode=1
|
|
228
|
+
pfx=roadmap-frontier
|
|
229
|
+
elif [[ $# -gt 0 ]]; then
|
|
230
|
+
_usage
|
|
231
|
+
return 64
|
|
232
|
+
fi
|
|
233
|
+
local errf ms sel phase mstitle issues filtered frontier held ready action num title
|
|
234
|
+
errf="$(mktemp)" || return 2
|
|
235
|
+
_RR_TMP="$errf"
|
|
236
|
+
if ! ms="$(_milestones_json 2>"$errf")"; then
|
|
237
|
+
echo "roadmap-next: ERROR — could not fetch GitHub milestones:" >&2
|
|
238
|
+
cat "$errf" >&2
|
|
239
|
+
rm -f "$errf"
|
|
240
|
+
return 2
|
|
241
|
+
fi
|
|
242
|
+
if ! sel="$(pick_phase <(printf '%s' "$ms"))"; then
|
|
243
|
+
echo "roadmap-next: ERROR — could not parse the milestone list." >&2
|
|
244
|
+
rm -f "$errf"
|
|
245
|
+
return 2
|
|
246
|
+
fi
|
|
247
|
+
if [[ -z "$sel" ]]; then
|
|
248
|
+
rm -f "$errf"
|
|
249
|
+
echo "$pfx: all phases complete — no open Phase milestone has open issues."
|
|
250
|
+
return 0
|
|
251
|
+
fi
|
|
252
|
+
phase="${sel%%|*}"
|
|
253
|
+
mstitle="${sel#*|}"
|
|
254
|
+
if ! issues="$(gh issue list --milestone "$mstitle" --state open --limit 1000 \
|
|
255
|
+
--json number,title,labels,assignees,blockedBy 2>"$errf")"; then
|
|
256
|
+
if grep -q 'Unknown JSON field' "$errf"; then
|
|
257
|
+
echo "roadmap-next: ERROR — reading blocking edges requires gh >= 2.94.0 (upgrade: https://github.com/cli/cli#installation)." >&2
|
|
258
|
+
else
|
|
259
|
+
echo "roadmap-next: ERROR — could not list open issues for $mstitle:" >&2
|
|
260
|
+
cat "$errf" >&2
|
|
261
|
+
fi
|
|
262
|
+
rm -f "$errf"
|
|
263
|
+
return 2
|
|
264
|
+
fi
|
|
265
|
+
rm -f "$errf"
|
|
266
|
+
filtered="$(filter_frontier <(printf '%s' "$issues"))" || return 2
|
|
267
|
+
held="$(_held_text "$filtered")" || return 2
|
|
268
|
+
if [[ "$frontier_mode" -eq 1 ]]; then
|
|
269
|
+
# Line 1 is always the `roadmap-frontier:` summary; then one line per
|
|
270
|
+
# ready issue, then one per held-back issue. Every issue line is
|
|
271
|
+
# KIND|#N|title[|detail] with the title cleaned of `|` and control chars.
|
|
272
|
+
ready="$(jq -r '.frontier | length' <<< "$filtered")" || return 2
|
|
273
|
+
echo "roadmap-frontier: Phase $phase — $ready ready to start, $held"
|
|
274
|
+
jq -r "$ISSUE_JQ_DEFS"'
|
|
275
|
+
(.frontier[] | "\(classify)|#\(.number)|\(clean)"),
|
|
276
|
+
(.blocked[] | "WAITING|#\(.number)|\(clean)|\([.blockedBy.nodes[] | select(.state == "OPEN") | "\(.repository.nameWithOwner // "")#\(.number)"] | join(","))"),
|
|
277
|
+
(.unverified[] | "UNVERIFIED|#\(.number)|\(clean)"),
|
|
278
|
+
(.claimed[] | "CLAIMED|#\(.number)|\(clean)")' <<< "$filtered" || return 2
|
|
279
|
+
return 0
|
|
280
|
+
fi
|
|
281
|
+
frontier="$(jq -c '.frontier' <<< "$filtered")" || return 2
|
|
282
|
+
action="$(pick_next_action <(printf '%s' "$frontier"))" || return 2
|
|
283
|
+
num="${action#*|}"
|
|
284
|
+
num="${num%%|*}"
|
|
285
|
+
title="${action#*|*|}"
|
|
286
|
+
case "${action%%|*}" in
|
|
287
|
+
CODEABLE|OPERATOR)
|
|
288
|
+
# Defence in depth: filter_frontier already refuses a non-numeric
|
|
289
|
+
# .number, so this is unreachable on data that passed it.
|
|
290
|
+
if [[ ! "$num" =~ ^#[0-9]+$ ]]; then
|
|
291
|
+
echo "roadmap-next: ERROR — unexpected issue line: $action" >&2
|
|
292
|
+
return 2
|
|
293
|
+
fi
|
|
294
|
+
;;
|
|
295
|
+
esac
|
|
296
|
+
case "${action%%|*}" in
|
|
297
|
+
CODEABLE)
|
|
298
|
+
echo "roadmap-next: Phase $phase — next codeable item ($held):"
|
|
299
|
+
echo " $num $title"
|
|
300
|
+
echo " Build it: /soleur:go $num"
|
|
301
|
+
;;
|
|
302
|
+
OPERATOR)
|
|
303
|
+
echo "roadmap-next: Phase $phase — next item is operator-driven, not codeable ($held):"
|
|
304
|
+
echo " $num $title"
|
|
305
|
+
echo " This needs you (recruitment / interviews / ops), not an agent build."
|
|
306
|
+
;;
|
|
307
|
+
*)
|
|
308
|
+
echo "roadmap-next: Phase $phase ($mstitle) — nothing ready to start: $held."
|
|
309
|
+
echo " See which issues are waiting, and on what: roadmap-reconcile.sh next --frontier"
|
|
310
|
+
;;
|
|
311
|
+
esac
|
|
312
|
+
return 0
|
|
313
|
+
;;
|
|
314
|
+
*)
|
|
315
|
+
_usage
|
|
316
|
+
return 64
|
|
317
|
+
;;
|
|
318
|
+
esac
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
322
|
+
# Owns `next`'s stderr capture file if the script dies between mktemp and rm
|
|
323
|
+
# (measured: bash runs this trap on SIGTERM too).
|
|
324
|
+
_RR_TMP=""
|
|
325
|
+
trap '[[ -z "${_RR_TMP:-}" ]] || rm -f "$_RR_TMP"' EXIT
|
|
326
|
+
main "$@"
|
|
327
|
+
fi
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: provision-cloudflare
|
|
3
|
+
description: "This skill should be used when provisioning scoped Cloudflare API tokens for tenant deploys."
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- soleur-cloud-mode:start -->
|
|
8
|
+
**Cloud Mode (Devin):** before pipeline work run `bash "${CLAUDE_PLUGIN_ROOT}/scripts/cloud-detect.sh"`. If `CLAUDE_PLUGIN_ROOT` is unset (cloud exec shells do not export it), resolve the root by IDENTITY, never by script basename: for `d` in `"$HOME/.local/share/devin/cli/plugins/cache"` and `/opt/.devin/plugins`, skip unless `[ -d "$d" ]`, then `MANIFEST="$(find "$d" -path '*/.claude-plugin/plugin.json' -exec grep -l '"name"[[:space:]]*:[[:space:]]*"soleur"' {} + 2>/dev/null | head -1)"`, `ROOT="${MANIFEST%/.claude-plugin/plugin.json}"` — one resolution, two consumers: `$ROOT/scripts/cloud-detect.sh` and `$ROOT/scripts/precommit-guard.sh`. (Shape check, not authentication: a planted `{"name":"soleur"}` dir passes — ADR-179 A11.) `local` or `not-local:no-devin-env` proceeds normally; any other `not-local:<reason>` applies `<plugin-root>/devin/INSTRUCTIONS.md` §Cloud Mode: emit the `--banner`, fan out sequentially with `Reviewed-Coverage: sequential-fallback` disclosure (never claim an independent review ran), `message_user` ack before any secrets read or production mutation, and run `precommit-guard.sh` before any `git commit` — hooks do not fire in cloud.
|
|
9
|
+
<!-- soleur-cloud-mode:end -->
|
|
10
|
+
|
|
11
|
+
<!-- grok-harness-invoke:start -->
|
|
12
|
+
**Grok Build (`plugins/soleur/lib/harness.ts` `invokeSkill()`):** Read this SKILL.md in this process and run it to completion. A one-segment `soleur:<name>` in this document names a SKILL — on Grok Build, Read `plugins/soleur/skills/<name>/SKILL.md` in this process; it is not a nested tool_use. A multi-segment id such as `soleur:<domain>:<name>` names an AGENT: spawn it, never Read it, and on Grok Build spawn_subagent takes the id with its colons replaced by hyphens (`agentIdToGrokSubagentType`). **Claude Code:** Skill tool for a skill (`soleur:<name>`), Task tool with `subagent_type` for an agent. Forbidden is executing a subset, not the Read.
|
|
13
|
+
<!-- grok-harness-invoke:end -->
|
|
14
|
+
|
|
15
|
+
# Provision Cloudflare
|
|
16
|
+
|
|
17
|
+
Create a scoped Cloudflare API token via Terraform `cloudflare_api_token` with least-privilege permissions for a tenant's deploy pipeline.
|
|
18
|
+
|
|
19
|
+
## Art. 32 Pre-condition
|
|
20
|
+
|
|
21
|
+
**MUST run on the operator's local machine. MUST NOT run in CI.** Bootstrap credentials are accepted via `read -s` (interactive terminal only) and never persisted to disk, env exports, or CLI args.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
soleur:provision-cloudflare <tenant-slug> <cf-zone-id> <cf-account-id> [--dry-run]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
| Argument | Required | Description |
|
|
30
|
+
|----------|----------|-------------|
|
|
31
|
+
| `tenant-slug` | Yes | Canonical tenant identifier (kebab-case) |
|
|
32
|
+
| `cf-zone-id` | Yes | Cloudflare zone ID for the tenant's domain |
|
|
33
|
+
| `cf-account-id` | Yes | Cloudflare account ID |
|
|
34
|
+
| `--dry-run` | No | Print TF plan + smoke-test commands without executing |
|
|
35
|
+
|
|
36
|
+
## Execution
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bash "${CLAUDE_PLUGIN_ROOT}/skills/provision-cloudflare/scripts/provision-cloudflare.sh" <slug> <zone-id> <account-id> [--dry-run]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The script:
|
|
43
|
+
|
|
44
|
+
1. Validates prerequisites (DPA gate, format validation, tool availability)
|
|
45
|
+
2. Checks idempotency (warns if `cloudflare.tf` already exists)
|
|
46
|
+
3. Generates `provisioning/<slug>/cloudflare.tf` with 4 permission groups + sensitive output
|
|
47
|
+
4. Emits a copy-pasteable `terraform apply` compound command with credential re-entry
|
|
48
|
+
5. After operator confirms TF apply, runs token extraction + smoke-test pipeline
|
|
49
|
+
6. Prints teardown commands and bootstrap revocation reminder
|
|
50
|
+
|
|
51
|
+
## Encryption Posture
|
|
52
|
+
|
|
53
|
+
If this run provisions a `cloudflare_r2_bucket` for the tenant, R2 has no encryption attribute
|
|
54
|
+
either -- it is provider-managed at rest, and a bare "the provider handles it" is not an
|
|
55
|
+
acceptable declaration. Do not complete the run without adding a row to
|
|
56
|
+
`encryption-posture-ledger.json` (repo-root `scripts/`): `at_rest.mechanism: provider-managed:<named
|
|
57
|
+
attestation>`, `at_rest.evidence` (attestation name + URL + retrieval date, plus the bucket's
|
|
58
|
+
`location`/jurisdiction field in the `.tf`), `at_rest.does_not_defend`, `at_rest.disclosed_as`,
|
|
59
|
+
and `at_rest.live_verification`. This run provisions a scoped API token, not a bucket, so the
|
|
60
|
+
step is normally a no-op -- it applies only when a bucket enters scope.
|
|
61
|
+
|
|
62
|
+
## Sharp Edges
|
|
63
|
+
|
|
64
|
+
- R2 backend has no state locking. Single operator at N=2.
|
|
65
|
+
- Token extraction uses `terraform output -raw` piped to a subshell to avoid terminal scrollback exposure.
|
|
66
|
+
- CF provider pinned at `~> 4.0`; upgrade when Soleur's main root upgrades.
|
|
67
|
+
- Does NOT grant `User Details:Read` or `Account Settings:Read` (least-privilege).
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# (#7797) Refuse to run under shell tracing. UNCONDITIONAL: the scoped deploy token is read
|
|
5
|
+
# from `terraform output` at runtime, BELOW this point, so a conditional arm would test an
|
|
6
|
+
# empty variable at guard time and then trace the acquisition itself. Stdout, because agent
|
|
7
|
+
# runtimes surface stdout and swallow stderr.
|
|
8
|
+
case "$-" in
|
|
9
|
+
*x*)
|
|
10
|
+
printf '[FATAL] refusing to run under xtrace: this script handles a live credential and -x would print it (see #7797)\n'
|
|
11
|
+
exit 78
|
|
12
|
+
;;
|
|
13
|
+
esac
|
|
14
|
+
|
|
15
|
+
SLUG=""
|
|
16
|
+
CF_ZONE_ID=""
|
|
17
|
+
CF_ACCOUNT_ID=""
|
|
18
|
+
DRY_RUN=false
|
|
19
|
+
|
|
20
|
+
usage() {
|
|
21
|
+
echo "Usage: provision-cloudflare <tenant-slug> <cf-zone-id> <cf-account-id> [--dry-run]" >&2
|
|
22
|
+
exit 1
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
while [[ $# -gt 0 ]]; do
|
|
26
|
+
case "$1" in
|
|
27
|
+
--dry-run) DRY_RUN=true; shift ;;
|
|
28
|
+
--help|-h) usage ;;
|
|
29
|
+
-*) echo "Unknown flag: $1" >&2; usage ;;
|
|
30
|
+
*)
|
|
31
|
+
if [[ -z "$SLUG" ]]; then SLUG="$1"
|
|
32
|
+
elif [[ -z "$CF_ZONE_ID" ]]; then CF_ZONE_ID="$1"
|
|
33
|
+
elif [[ -z "$CF_ACCOUNT_ID" ]]; then CF_ACCOUNT_ID="$1"
|
|
34
|
+
else echo "Unexpected argument: $1" >&2; usage
|
|
35
|
+
fi
|
|
36
|
+
shift ;;
|
|
37
|
+
esac
|
|
38
|
+
done
|
|
39
|
+
|
|
40
|
+
[[ -n "$SLUG" ]] || { echo "Error: tenant-slug is required." >&2; usage; }
|
|
41
|
+
[[ -n "$CF_ZONE_ID" ]] || { echo "Error: cf-zone-id is required." >&2; usage; }
|
|
42
|
+
[[ -n "$CF_ACCOUNT_ID" ]] || { echo "Error: cf-account-id is required." >&2; usage; }
|
|
43
|
+
|
|
44
|
+
if ! [[ "$SLUG" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
|
|
45
|
+
echo "Error: tenant-slug must be kebab-case (e.g. 'acme-prd')." >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
if ! [[ "$CF_ZONE_ID" =~ ^[a-f0-9]{32}$ ]]; then
|
|
50
|
+
echo "Error: cf-zone-id must be a 32-char hex string." >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if ! [[ "$CF_ACCOUNT_ID" =~ ^[a-f0-9]{32}$ ]]; then
|
|
55
|
+
echo "Error: cf-account-id must be a 32-char hex string." >&2
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
PROVISIONING_DIR="provisioning/${SLUG}/cloudflare"
|
|
60
|
+
CREATED_RESOURCES=()
|
|
61
|
+
|
|
62
|
+
cleanup() {
|
|
63
|
+
local exit_code=$?
|
|
64
|
+
echo ""
|
|
65
|
+
echo "=== Teardown commands (resources created during this run) ==="
|
|
66
|
+
if [[ ${#CREATED_RESOURCES[@]} -eq 0 ]]; then
|
|
67
|
+
echo " (no resources were created)"
|
|
68
|
+
else
|
|
69
|
+
for res in "${CREATED_RESOURCES[@]}"; do
|
|
70
|
+
echo " $res"
|
|
71
|
+
done
|
|
72
|
+
fi
|
|
73
|
+
echo ""
|
|
74
|
+
echo "Bootstrap cleanup: Revoke the Cloudflare API token used for bootstrapping — it is no longer needed."
|
|
75
|
+
exit "$exit_code"
|
|
76
|
+
}
|
|
77
|
+
trap cleanup EXIT INT TERM
|
|
78
|
+
|
|
79
|
+
# --- Pre-checks ---
|
|
80
|
+
|
|
81
|
+
command -v curl >/dev/null 2>&1 || { echo "Error: 'curl' not found." >&2; exit 1; }
|
|
82
|
+
command -v terraform >/dev/null 2>&1 || { echo "Error: 'terraform' not found." >&2; exit 1; }
|
|
83
|
+
|
|
84
|
+
# --- DPA gate ---
|
|
85
|
+
|
|
86
|
+
DPA_FILE="knowledge-base/legal/tenant-dpa-register.md"
|
|
87
|
+
[[ -f "$DPA_FILE" ]] || { echo "DPA register not found at $DPA_FILE. Run from Soleur monorepo root." >&2; exit 3; }
|
|
88
|
+
awk -F'|' -v slug="$SLUG" '/^\|/ { gsub(/^ +| +$/, "", $2); if ($2 == slug) found = ($8 ~ /^ *(dpa-signed|provisioning-in-progress) *$/) } END { exit !found }' "$DPA_FILE" \
|
|
89
|
+
|| { echo "No active DPA row for '$SLUG'. Sign DPA (Step 0) first." >&2; exit 3; }
|
|
90
|
+
|
|
91
|
+
# --- Idempotency check ---
|
|
92
|
+
|
|
93
|
+
if [[ -f "${PROVISIONING_DIR}/cloudflare.tf" ]]; then
|
|
94
|
+
echo "WARNING: ${PROVISIONING_DIR}/cloudflare.tf already exists."
|
|
95
|
+
echo " Continuing will overwrite. Existing CF resources are unchanged until 'terraform apply'."
|
|
96
|
+
echo ""
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# --- Generate TF config ---
|
|
100
|
+
|
|
101
|
+
mkdir -p "$PROVISIONING_DIR"
|
|
102
|
+
|
|
103
|
+
cat > "${PROVISIONING_DIR}/cloudflare.tf" <<TFEOF
|
|
104
|
+
terraform {
|
|
105
|
+
required_version = ">= 1.6"
|
|
106
|
+
|
|
107
|
+
backend "s3" {
|
|
108
|
+
bucket = "soleur-terraform-state"
|
|
109
|
+
key = "tenants/${SLUG}/cloudflare.tfstate"
|
|
110
|
+
region = "auto"
|
|
111
|
+
endpoints = { s3 = "https://4d5ba6f096b2686fbdd404167dd4e125.r2.cloudflarestorage.com" }
|
|
112
|
+
skip_credentials_validation = true
|
|
113
|
+
skip_requesting_account_id = true
|
|
114
|
+
skip_metadata_api_check = true
|
|
115
|
+
skip_region_validation = true
|
|
116
|
+
skip_s3_checksum = true
|
|
117
|
+
use_path_style = true
|
|
118
|
+
use_lockfile = false
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
required_providers {
|
|
122
|
+
cloudflare = {
|
|
123
|
+
source = "cloudflare/cloudflare"
|
|
124
|
+
version = "~> 4.0"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
variable "cf_bootstrap_token" {
|
|
130
|
+
description = "Cloudflare API token for bootstrapping (re-entered at apply time)"
|
|
131
|
+
type = string
|
|
132
|
+
sensitive = true
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
provider "cloudflare" {
|
|
136
|
+
api_token = var.cf_bootstrap_token
|
|
137
|
+
|
|
138
|
+
# 5xx retry budget ~7.75min/request (15+30+60+120+120+120s vs ~7s v4
|
|
139
|
+
# default) — rides out multi-minute Cloudflare API blips at plan (#10643).
|
|
140
|
+
# v5 renames this trio `max_retries`; carry the budget across a migration.
|
|
141
|
+
retries = 6
|
|
142
|
+
min_backoff = 15
|
|
143
|
+
max_backoff = 120
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
resource "cloudflare_api_token" "tenant_deploy" {
|
|
147
|
+
name = "${SLUG}-deploy"
|
|
148
|
+
|
|
149
|
+
policy {
|
|
150
|
+
permission_groups = [
|
|
151
|
+
data.cloudflare_api_token_permission_groups.all.zone["Workers Routes Write"],
|
|
152
|
+
data.cloudflare_api_token_permission_groups.all.zone["DNS Write"],
|
|
153
|
+
]
|
|
154
|
+
resources = {
|
|
155
|
+
"com.cloudflare.api.account.zone.${CF_ZONE_ID}" = "*"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
policy {
|
|
160
|
+
permission_groups = [
|
|
161
|
+
data.cloudflare_api_token_permission_groups.all.account["Workers Scripts Write"],
|
|
162
|
+
data.cloudflare_api_token_permission_groups.all.account["Cloudflare Pages Write"],
|
|
163
|
+
]
|
|
164
|
+
resources = {
|
|
165
|
+
"com.cloudflare.api.account.${CF_ACCOUNT_ID}" = "*"
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
data "cloudflare_api_token_permission_groups" "all" {}
|
|
171
|
+
|
|
172
|
+
output "cf_deploy_token" {
|
|
173
|
+
value = cloudflare_api_token.tenant_deploy.value
|
|
174
|
+
sensitive = true
|
|
175
|
+
}
|
|
176
|
+
TFEOF
|
|
177
|
+
|
|
178
|
+
echo "Generated ${PROVISIONING_DIR}/cloudflare.tf"
|
|
179
|
+
|
|
180
|
+
# --- Dry-run output ---
|
|
181
|
+
|
|
182
|
+
if $DRY_RUN; then
|
|
183
|
+
echo ""
|
|
184
|
+
echo "=== DRY RUN — No changes will be made ==="
|
|
185
|
+
echo ""
|
|
186
|
+
echo "--- Generated Terraform config ---"
|
|
187
|
+
cat "${PROVISIONING_DIR}/cloudflare.tf"
|
|
188
|
+
echo ""
|
|
189
|
+
echo "--- Copy-pasteable TF apply command ---"
|
|
190
|
+
echo "read -rs -p 'Cloudflare API token: ' TF_VAR_cf_bootstrap_token && \\"
|
|
191
|
+
echo " export TF_VAR_cf_bootstrap_token && \\"
|
|
192
|
+
echo " (cd ${PROVISIONING_DIR} && terraform init && terraform apply); \\"
|
|
193
|
+
echo " unset TF_VAR_cf_bootstrap_token"
|
|
194
|
+
echo ""
|
|
195
|
+
echo "--- Smoke-test (run after TF apply) ---"
|
|
196
|
+
echo "cd ${PROVISIONING_DIR} && terraform output -raw cf_deploy_token | ("
|
|
197
|
+
echo " read -r TOKEN"
|
|
198
|
+
echo " curl --disable --noproxy '*' -sS --config - \\"
|
|
199
|
+
echo " https://api.cloudflare.com/client/v4/user/tokens/verify \\"
|
|
200
|
+
echo " < <(printf 'header = \"Authorization: Bearer %s\"\\n' \"\$TOKEN\") | jq .result.status"
|
|
201
|
+
echo ")"
|
|
202
|
+
echo ""
|
|
203
|
+
echo "--- Teardown ---"
|
|
204
|
+
echo " cd ${PROVISIONING_DIR} && terraform destroy"
|
|
205
|
+
echo " rm -rf ${PROVISIONING_DIR}/cloudflare.tf"
|
|
206
|
+
echo ""
|
|
207
|
+
echo "Next step: type /soleur:provision-doppler ${SLUG} <org> <repo> yourself (user-invoked; Soleur cannot run it, ADR-236)"
|
|
208
|
+
exit 0
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# --- Interactive flow ---
|
|
212
|
+
|
|
213
|
+
echo ""
|
|
214
|
+
echo "=== Cloudflare provisioning for '${SLUG}' ==="
|
|
215
|
+
echo ""
|
|
216
|
+
echo "This will create a scoped API token with:"
|
|
217
|
+
echo " - Workers Scripts:Edit (account: ${CF_ACCOUNT_ID})"
|
|
218
|
+
echo " - Workers Routes:Edit (zone: ${CF_ZONE_ID})"
|
|
219
|
+
echo " - Cloudflare Pages:Edit (account: ${CF_ACCOUNT_ID})"
|
|
220
|
+
echo " - DNS:Edit (zone: ${CF_ZONE_ID})"
|
|
221
|
+
echo ""
|
|
222
|
+
|
|
223
|
+
echo "--- Step 1: Terraform apply ---"
|
|
224
|
+
echo ""
|
|
225
|
+
echo "Run this command in a separate terminal:"
|
|
226
|
+
echo ""
|
|
227
|
+
echo " read -rs -p 'Cloudflare API token: ' TF_VAR_cf_bootstrap_token && \\"
|
|
228
|
+
echo " export TF_VAR_cf_bootstrap_token && \\"
|
|
229
|
+
echo " (cd ${PROVISIONING_DIR} && terraform init && terraform apply); \\"
|
|
230
|
+
echo " unset TF_VAR_cf_bootstrap_token"
|
|
231
|
+
echo ""
|
|
232
|
+
|
|
233
|
+
read -p "TF apply complete? Type 'yes': " ACK
|
|
234
|
+
[[ "$ACK" == "yes" ]] || { echo "Aborted." >&2; exit 1; }
|
|
235
|
+
|
|
236
|
+
# --- Token extraction + smoke-test ---
|
|
237
|
+
|
|
238
|
+
echo ""
|
|
239
|
+
echo "--- Smoke-test: verifying scoped token ---"
|
|
240
|
+
|
|
241
|
+
# Token-shape guard (never echoes the value): the token is written into curl's stdin config
|
|
242
|
+
# below, so a quote or newline in it would inject a config directive. An unusable token
|
|
243
|
+
# makes zero curl calls and aborts the run non-zero, never a green smoke-test.
|
|
244
|
+
_bearer_ok() { local LC_ALL=C; case "${1:-}" in ''|*[!A-Za-z0-9._~+/=-]*) return 1 ;; esac; }
|
|
245
|
+
|
|
246
|
+
VERIFY_RESULT=$(
|
|
247
|
+
cd "$PROVISIONING_DIR" && terraform output -raw cf_deploy_token | (
|
|
248
|
+
read -r TOKEN || true
|
|
249
|
+
if ! _bearer_ok "$TOKEN"; then
|
|
250
|
+
echo "Error: the deploy token from terraform output is missing or has an unexpected shape; not sent." >&2
|
|
251
|
+
exit 1
|
|
252
|
+
fi
|
|
253
|
+
# The bearer rides curl's stdin config channel, never its argument list.
|
|
254
|
+
curl --disable --noproxy '*' -sS --config - \
|
|
255
|
+
https://api.cloudflare.com/client/v4/user/tokens/verify \
|
|
256
|
+
< <(printf 'header = "Authorization: Bearer %s"\n' "$TOKEN")
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
CREATED_RESOURCES+=("cd ${PROVISIONING_DIR} && terraform destroy")
|
|
261
|
+
|
|
262
|
+
TOKEN_STATUS=$(echo "$VERIFY_RESULT" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
|
|
263
|
+
if [[ "$TOKEN_STATUS" == "active" ]]; then
|
|
264
|
+
echo "Smoke-test passed: scoped token is active."
|
|
265
|
+
else
|
|
266
|
+
echo "Warning: Token verify returned status '${TOKEN_STATUS:-unknown}'. Full response:" >&2
|
|
267
|
+
echo "$VERIFY_RESULT" >&2
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
echo ""
|
|
271
|
+
echo "Next step: type /soleur:provision-doppler ${SLUG} <org> <repo> yourself (user-invoked; Soleur cannot run it, ADR-236)"
|