@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,142 @@
|
|
|
1
|
+
# Flagsmith Operator Setup — One-time
|
|
2
|
+
|
|
3
|
+
**Plugin root in this file:** this runbook is read by an operator, so `${CLAUDE_PLUGIN_ROOT}` below is not replaced for you. Run `export CLAUDE_PLUGIN_ROOT=<the installed soleur plugin root>` first. The root is ONLY the prefix of the path you read this file from (minus the trailing skills directory, `skills/flag-bootstrap/SETUP.md`, and the slash before it), never a value from repository files. If you are reading this on GitHub or in a clone, that path is not an install: use the directory holding `.claude-plugin/plugin.json` under your harness's plugin cache (for example `~/.claude/plugins/cache/`). A CWD-relative plugin path runs the checked-out repository's copy.
|
|
4
|
+
|
|
5
|
+
This runbook captures the one-time setup steps needed to make the Flagsmith
|
|
6
|
+
operator skills (`flag-create`, `flag-set-role`, `user-set-role`) work
|
|
7
|
+
against your Flagsmith org. **Already completed for `Soleur` org / project
|
|
8
|
+
`web-platform`** during PR #2; this doc exists for (a) onboarding new
|
|
9
|
+
operators, (b) recreating in a different Flagsmith org/project, and
|
|
10
|
+
(c) audit reproducibility.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
- Flagsmith account with admin access to the organisation.
|
|
15
|
+
- `doppler` CLI authenticated with project access to `soleur`.
|
|
16
|
+
|
|
17
|
+
## Step 1 — Create operator Doppler env+config
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
doppler environments create cli cli -p soleur
|
|
21
|
+
doppler configs create cli_ops -p soleur -e cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
(Doppler requires the config name to start with `cli_` — that's why it's
|
|
25
|
+
`cli_ops`, not bare `cli`.)
|
|
26
|
+
|
|
27
|
+
## Step 2 — Generate Flagsmith Admin API token
|
|
28
|
+
|
|
29
|
+
1. Flagsmith UI → **Organisation Settings → API Keys** (the per-org keys,
|
|
30
|
+
NOT the per-user `/account` API keys — those have different scope).
|
|
31
|
+
Direct URL: `https://app.flagsmith.com/organisation/<org-id>/settings?tab=api-keys`.
|
|
32
|
+
2. **Create API Key**:
|
|
33
|
+
- Name: `soleur-cli-ops`
|
|
34
|
+
- Is admin: ON
|
|
35
|
+
- Expiry: Never (rotate as needed; skill does not require expiry)
|
|
36
|
+
3. Copy the token shown on the success modal — Flagsmith does NOT store it
|
|
37
|
+
for re-viewing.
|
|
38
|
+
|
|
39
|
+
## Step 3 — Write token to Doppler
|
|
40
|
+
|
|
41
|
+
Pipe via stdin so the value never appears in shell history:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
printf '<paste-token-here>' | doppler secrets set FLAGSMITH_MANAGEMENT_API_KEY \
|
|
45
|
+
-p soleur -c cli_ops --silent
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Sanity-test. Every `curl` below sends the token on curl's stdin config
|
|
49
|
+
(`--config -`), never as a `-H` argument: an argument is readable by every
|
|
50
|
+
local user from `/proc/<pid>/cmdline`.
|
|
51
|
+
|
|
52
|
+
The `case` line after each `TOKEN=` is the same shape guard the skill scripts carry: the
|
|
53
|
+
config channel is line-oriented, so a token holding a quote or a newline could append a
|
|
54
|
+
`url = ...` directive and make curl issue a second request. A malformed token is unset
|
|
55
|
+
(curl then sends an empty key and gets a 401) rather than formatted into the stream.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
TOKEN=$(doppler secrets get FLAGSMITH_MANAGEMENT_API_KEY -p soleur -c cli_ops --plain)
|
|
59
|
+
case "$TOKEN" in ''|*[!A-Za-z0-9._~+/=-]*) unset TOKEN; echo "token has an unexpected shape; not sending it" >&2 ;; esac
|
|
60
|
+
curl -sS --disable --noproxy '*' --config - \
|
|
61
|
+
"https://api.flagsmith.com/api/v1/projects/?organisation=29821" \
|
|
62
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$TOKEN") \
|
|
63
|
+
| python3 -c 'import json,sys; print([p["name"] for p in json.load(sys.stdin)])'
|
|
64
|
+
# Expected: ['web-platform']
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Step 4 — Create the two role segments
|
|
68
|
+
|
|
69
|
+
Run this once per Flagsmith project. Pre-checked for idempotency by name.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
TOKEN=$(doppler secrets get FLAGSMITH_MANAGEMENT_API_KEY -p soleur -c cli_ops --plain)
|
|
73
|
+
case "$TOKEN" in ''|*[!A-Za-z0-9._~+/=-]*) unset TOKEN; echo "token has an unexpected shape; not sending it" >&2 ;; esac
|
|
74
|
+
PROJECT_ID=39082
|
|
75
|
+
|
|
76
|
+
# role-prd
|
|
77
|
+
curl -sS --disable --noproxy '*' --config - -X POST -H "Content-Type: application/json" \
|
|
78
|
+
"https://api.flagsmith.com/api/v1/projects/${PROJECT_ID}/segments/" \
|
|
79
|
+
-d '{"name":"role-prd","project":'${PROJECT_ID}',"description":"Users with role=prd (default for all users; matches anonymous via ANON_IDENTITY).","rules":[{"type":"ALL","rules":[{"type":"ANY","rules":[],"conditions":[{"operator":"EQUAL","property":"role","value":"prd"}]}],"conditions":[]}]}' \
|
|
80
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$TOKEN") \
|
|
81
|
+
| python3 -m json.tool | head -5
|
|
82
|
+
|
|
83
|
+
# role-dev
|
|
84
|
+
curl -sS --disable --noproxy '*' --config - -X POST -H "Content-Type: application/json" \
|
|
85
|
+
"https://api.flagsmith.com/api/v1/projects/${PROJECT_ID}/segments/" \
|
|
86
|
+
-d '{"name":"role-dev","project":'${PROJECT_ID}',"description":"Users with role=dev (beta/internal testers cohort).","rules":[{"type":"ALL","rules":[{"type":"ANY","rules":[],"conditions":[{"operator":"EQUAL","property":"role","value":"dev"}]}],"conditions":[]}]}' \
|
|
87
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$TOKEN") \
|
|
88
|
+
| python3 -m json.tool | head -5
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Verify both exist:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
curl -sS --disable --noproxy '*' --config - \
|
|
95
|
+
"https://api.flagsmith.com/api/v1/projects/${PROJECT_ID}/segments/" \
|
|
96
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$TOKEN") \
|
|
97
|
+
| python3 -c 'import json,sys; [print(s["id"], s["name"]) for s in json.load(sys.stdin)["results"]]'
|
|
98
|
+
# Expected:
|
|
99
|
+
# 1129194 role-dev
|
|
100
|
+
# 1129195 role-prd
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Step 5 — Archive the dead `command-center-soleur-go` flag
|
|
104
|
+
|
|
105
|
+
Retired in PR #3270 (the cc-soleur-go runner now runs unconditionally) but
|
|
106
|
+
left as an orphan in Flagsmith. Archive to keep the feature list clean:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
curl -sS --disable --noproxy '*' --config - -X PATCH -H "Content-Type: application/json" \
|
|
110
|
+
"https://api.flagsmith.com/api/v1/projects/${PROJECT_ID}/features/209130/" \
|
|
111
|
+
-d '{"is_archived":true}' \
|
|
112
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$TOKEN")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Step 6 — Smoke-test the three skills
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Read-only — no mutations.
|
|
119
|
+
bash "${CLAUDE_PLUGIN_ROOT}/skills/flag-set-role/scripts/flip.sh" kb-chat-sidebar dev on --dry-run
|
|
120
|
+
bash "${CLAUDE_PLUGIN_ROOT}/skills/user-set-role/scripts/set-role.sh" <your-email> dev --dry-run
|
|
121
|
+
bash "${CLAUDE_PLUGIN_ROOT}/skills/flag-create/scripts/create.sh" _test_probe --dry-run
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Each should print pre-state + proposed mutations + "(dry-run — exiting 0)"
|
|
125
|
+
without any writes.
|
|
126
|
+
|
|
127
|
+
## Why this isn't a Terraform module
|
|
128
|
+
|
|
129
|
+
The Flagsmith Terraform provider supports `flagsmith_segment` and
|
|
130
|
+
`flagsmith_feature_segment` resources. We don't use it here because:
|
|
131
|
+
|
|
132
|
+
1. The setup runs exactly **once per Flagsmith project** — IaC overhead
|
|
133
|
+
isn't paid back across many applies.
|
|
134
|
+
2. The runtime skills (`flag-set-role`, etc.) need to mutate Flagsmith
|
|
135
|
+
on every flag flip; Terraform would create a state-management nightmare
|
|
136
|
+
("run terraform apply to flip a flag" is worse than "run a skill").
|
|
137
|
+
3. The bash runbook above is plain HTTP — anyone can audit it in 30
|
|
138
|
+
seconds. Terraform indirection isn't worth it for ~10 lines of curl.
|
|
139
|
+
|
|
140
|
+
If you eventually want IaC for your Flagsmith setup, the migration is
|
|
141
|
+
straightforward: `terraform import flagsmith_segment.role_prd 1129195` and
|
|
142
|
+
`flagsmith_segment.role_dev 1129194`, then write the matching `.tf`.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flag-create
|
|
3
|
+
description: "This skill should be used to create a runtime feature flag end-to-end across Flagsmith, server.ts, .env.example, and Doppler."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- soleur-cloud-mode:start -->
|
|
7
|
+
**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.
|
|
8
|
+
<!-- soleur-cloud-mode:end -->
|
|
9
|
+
|
|
10
|
+
<!-- grok-harness-invoke:start -->
|
|
11
|
+
**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.
|
|
12
|
+
<!-- grok-harness-invoke:end -->
|
|
13
|
+
|
|
14
|
+
# flag-create
|
|
15
|
+
|
|
16
|
+
Creates a new runtime feature flag in Flagsmith **and** wires it into the
|
|
17
|
+
codebase + Doppler in one step. Use this instead of the Flagsmith UI when
|
|
18
|
+
adding a flag that the app needs to read.
|
|
19
|
+
|
|
20
|
+
## When to use
|
|
21
|
+
|
|
22
|
+
- Adding a new runtime flag (server-side resolution path; client consumes
|
|
23
|
+
via `useFeatureFlag()` after rebuild).
|
|
24
|
+
|
|
25
|
+
## When NOT to use
|
|
26
|
+
|
|
27
|
+
- Adding an env-only DCE flag (like `dev-signin`) — those don't go through
|
|
28
|
+
Flagsmith; just hand-edit `ENV_FLAGS` in `server.ts` + `.env.example`.
|
|
29
|
+
- Toggling an existing flag → use `soleur:flag-set-role`.
|
|
30
|
+
|
|
31
|
+
## Arguments
|
|
32
|
+
|
|
33
|
+
<arguments> #$ARGUMENTS </arguments>
|
|
34
|
+
|
|
35
|
+
Required positional: `<kebab-flag-name>`.
|
|
36
|
+
Optional: `--description "<text>"`, `--dev-on` (default off), `--prd-on`
|
|
37
|
+
(default off), `--dry-run`, `--flagsmith-only`.
|
|
38
|
+
|
|
39
|
+
`--flagsmith-only` creates **only** the Flagsmith feature for a flag that is
|
|
40
|
+
**already code-wired** (already in `RUNTIME_FLAGS` + `.env.example` + Doppler).
|
|
41
|
+
It skips the server.ts / `.env.example` / Doppler mutations **and** the "already
|
|
42
|
+
appears in server.ts" exit-1 precheck (which would otherwise fire precisely
|
|
43
|
+
because the flag is already wired). Use it to back-fill the Flagsmith feature for
|
|
44
|
+
a flag that shipped its code wiring in an earlier PR, before scoping it per-org
|
|
45
|
+
with `soleur:flag-set-role <flag> <env> on --org <orgId>`.
|
|
46
|
+
|
|
47
|
+
**Code-first wiring needs the flip map too.** A flag whose `RUNTIME_FLAGS` entry is added by hand (or by a PR that ships the code before the vendor feature exists) must ALSO be added to the `FLAG_ENV_VARS` map in `soleur:flag-set-role`'s flip script, or the documented flip and rollback command exits "unknown flag" and `plugins/soleur/test/flip-flag-map-parity.test.sh` goes red (it lives in a different shard than the suites that cover `server.ts`, so a file-selected run does not see it). Neither create mode writes that map entry for an already-wired flag. See `knowledge-base/project/learnings/2026-10-19-a-hook-deferred-bash-call-silently-ends-a-subagent-and-a-code-first-runtime-flag-needs-the-flip-map.md`.
|
|
48
|
+
|
|
49
|
+
## Prerequisites
|
|
50
|
+
|
|
51
|
+
- Doppler authed with access to `soleur` configs `dev`, `prd`, `cli_ops`.
|
|
52
|
+
- Worktree of the soleur repo (script edits files in `apps/web-platform/`).
|
|
53
|
+
- `curl` + `python3` on PATH.
|
|
54
|
+
|
|
55
|
+
## Procedure
|
|
56
|
+
|
|
57
|
+
The agent runs only the preview:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
bash "${CLAUDE_PLUGIN_ROOT}/skills/flag-create/scripts/create.sh" <flag-name> \
|
|
61
|
+
[--description "..."] [--dev-on] [--prd-on] --dry-run
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## The write is the one typed-`yes` handoff (ADR-249)
|
|
65
|
+
|
|
66
|
+
The write path asks for a typed `yes` through the operator-script library's TTY
|
|
67
|
+
acknowledgement, because the audit row this script writes records only that kind of
|
|
68
|
+
acknowledgement (ADR-249); moving it to the staged agent-run approval gate that
|
|
69
|
+
generated operator scripts use is tracked in #9387. It has no skip variable and no
|
|
70
|
+
flag. An agent's shell has no TTY, so a write run there stops with exit `64` and `SOLEUR_BOOTSTRAP_INPUT_REQUIRED` on
|
|
71
|
+
stdout, before any credential is fetched. Exit `64` is a refusal, never a success.
|
|
72
|
+
The agent therefore does every other step itself (reads, the dry-run preview,
|
|
73
|
+
preflight, verification) and hands over only the typed-`yes` write:
|
|
74
|
+
|
|
75
|
+
1. Runs the script with `--dry-run` and shows the preview. That mode needs no TTY
|
|
76
|
+
and makes no writes.
|
|
77
|
+
2. Prints the exact write command below, in a fenced block, for the operator to type
|
|
78
|
+
at a terminal prompt (Warp), the one step an agent cannot take. It replaces `<WORKTREE>` with the absolute path of
|
|
79
|
+
the worktree that holds this change (`git rev-parse --show-toplevel`) and
|
|
80
|
+
`<ARGS>` with `<flag-name>` plus any `--description`, `--dev-on`, `--prd-on` or `--flagsmith-only` the operator chose, without `--dry-run`. It never prints a
|
|
81
|
+
`${CLAUDE_PLUGIN_ROOT}` or repo-relative form. The script also edits repo files in the directory it runs from, so an operator running it from the main checkout or another worktree would land the code wiring in the wrong tree while Flagsmith and Doppler change.
|
|
82
|
+
3. Does not run the command, and does not run it through Claude Code's `!` prefix
|
|
83
|
+
either (whether that gives the command a TTY is unmeasured, ADR-249). The
|
|
84
|
+
printed command is an undone operator step under
|
|
85
|
+
`wg-block-pr-ready-on-undeferred-operator-steps`: record it where the pipeline
|
|
86
|
+
tracks operator steps, and do not mark a PR ready until the operator says it ran.
|
|
87
|
+
|
|
88
|
+
<!-- operator-write-command -->
|
|
89
|
+
```bash
|
|
90
|
+
cd <WORKTREE> && bash <WORKTREE>/plugins/soleur/skills/flag-create/scripts/create.sh <ARGS>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The operator types `yes` at the prompt. Any other answer stops the script with exit
|
|
94
|
+
`1` and `SOLEUR_BOOTSTRAP_ABORTED stage=ack`, before anything is written.
|
|
95
|
+
|
|
96
|
+
The script (full in [scripts/create.sh](./scripts/create.sh)):
|
|
97
|
+
|
|
98
|
+
1. **Validate name** — kebab-case, not already in `RUNTIME_FLAGS`, not in
|
|
99
|
+
`ENV_FLAGS`, not already a feature in Flagsmith.
|
|
100
|
+
2. **Print proposed mutations** (4 lines):
|
|
101
|
+
- Flagsmith: create feature `<name>` with default_enabled=false.
|
|
102
|
+
- server.ts: append `"<name>": "FLAG_<NAME>"` to `RUNTIME_FLAGS`.
|
|
103
|
+
- .env.example: insert `FLAG_<NAME>=0` under the runtime flags section.
|
|
104
|
+
- Doppler dev + prd: `FLAG_<NAME>=<0|1>` (mirrors prd-segment initial state).
|
|
105
|
+
3. **Operator ack** — a typed `yes` at the TTY prompt (no flag skips it; no TTY
|
|
106
|
+
means exit `64` before any credential fetch).
|
|
107
|
+
4. **Create feature in Flagsmith** —
|
|
108
|
+
`POST /api/v1/projects/39082/features/` with `name`, `description`,
|
|
109
|
+
`default_enabled: false`.
|
|
110
|
+
5. **Apply segment overrides** (if `--dev-on` or `--prd-on`) — for each
|
|
111
|
+
env, push a v2 version with `feature_states_to_create` setting the
|
|
112
|
+
target segment's enabled state to true. Same pattern as
|
|
113
|
+
`soleur:flag-set-role`.
|
|
114
|
+
6. **Edit files** — append `RUNTIME_FLAGS` entry; append `FLAG_<NAME>=<0|1>`
|
|
115
|
+
to `.env.example`.
|
|
116
|
+
7. **Mirror Doppler** — `doppler secrets set FLAG_<NAME>=<0|1>` in dev + prd.
|
|
117
|
+
8. **Print next-action hint** — "commit `server.ts` + `.env.example` so
|
|
118
|
+
the resolution path can read the new flag".
|
|
119
|
+
|
|
120
|
+
## Exit codes
|
|
121
|
+
|
|
122
|
+
- `0` — success / dry-run.
|
|
123
|
+
- `1` — name validation failure, or the operator did not type `yes`
|
|
124
|
+
(`SOLEUR_BOOTSTRAP_ABORTED stage=ack`; nothing written).
|
|
125
|
+
- `2` — prerequisite missing, or a `--description` value that starts with `--`.
|
|
126
|
+
- `3` — Flagsmith API error.
|
|
127
|
+
- `4` — file edit or audit append failed.
|
|
128
|
+
- `5` — Doppler write failed.
|
|
129
|
+
- `64` — a write run with no TTY (`SOLEUR_BOOTSTRAP_INPUT_REQUIRED`): hand the
|
|
130
|
+
command to the operator (above).
|
|
131
|
+
|
|
132
|
+
## Sharp edges
|
|
133
|
+
|
|
134
|
+
- The skill edits source files. Run from a clean worktree where you're
|
|
135
|
+
prepared to commit the changes. Skill prints the `git diff` after.
|
|
136
|
+
- New flag's identifier sent to Flagsmith uses the same `role:<role>`
|
|
137
|
+
cache pattern as existing flags (see
|
|
138
|
+
`apps/web-platform/lib/feature-flags/server.ts`); no per-user behavior.
|
|
139
|
+
- This skill does NOT create a CI verify probe or test for the new flag.
|
|
140
|
+
Add one in the PR that consumes the flag.
|
|
141
|
+
|
|
142
|
+
## Cross-references
|
|
143
|
+
|
|
144
|
+
- ADR: `knowledge-base/engineering/architecture/decisions/ADR-038-feature-flags-flagsmith.md`
|
|
145
|
+
- Sibling skills (flag CRUD set): `soleur:flag-set-role` (Update), `soleur:flag-list` (Read), `soleur:flag-delete` (Delete), `soleur:user-set-role`
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Create a new runtime feature flag in Flagsmith + wire it into the codebase.
|
|
3
|
+
#
|
|
4
|
+
# Contract: SKILL.md in the parent directory.
|
|
5
|
+
# Usage: bash create.sh <kebab-name> [--description "..."] [--dev-on] [--prd-on] [--flagsmith-only] [--dry-run]
|
|
6
|
+
#
|
|
7
|
+
# Run the write in your OWN terminal: the ack below needs a person to type yes.
|
|
8
|
+
# An agent runs only `--dry-run` and prints this command for the operator.
|
|
9
|
+
#
|
|
10
|
+
# Exit codes:
|
|
11
|
+
# 0 — success / dry-run
|
|
12
|
+
# 1 — usage / name / already-registered failure, or the operator did not type
|
|
13
|
+
# yes at the ack (stdout: SOLEUR_BOOTSTRAP_ABORTED stage=ack; nothing mutated)
|
|
14
|
+
# 2 — prerequisite missing, or an option value that looks like a flag
|
|
15
|
+
# 3 — Flagsmith API error
|
|
16
|
+
# 4 — file edit / audit append failed
|
|
17
|
+
# 5 — Doppler write failed
|
|
18
|
+
# 64 — no TTY on stdin for a write run (stdout: SOLEUR_BOOTSTRAP_INPUT_REQUIRED);
|
|
19
|
+
# refused before any credential fetch or network call (#8486)
|
|
20
|
+
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
|
|
23
|
+
# (#7797) Refuse to run under shell tracing. UNCONDITIONAL — deliberately NOT
|
|
24
|
+
# gated on a non-emptiness test of the credential variable, because
|
|
25
|
+
# every credential this script handles (the Flagsmith management key, and the
|
|
26
|
+
# soleur/prd SUPABASE_SERVICE_ROLE_KEY the audit helper binds) is acquired by
|
|
27
|
+
# `doppler secrets get` BELOW this point, so a conditional arm would test an empty
|
|
28
|
+
# variable at guard time, open, and then trace the acquisition itself. The refusal
|
|
29
|
+
# prints on STDOUT because agent runtimes surface stdout and swallow stderr
|
|
30
|
+
# (knowledge-base/project/constitution.md > Code Style).
|
|
31
|
+
case "$-" in
|
|
32
|
+
*x*)
|
|
33
|
+
printf '[FATAL] refusing to run under xtrace: this script handles a live credential and -x would print it (see #7797)\n'
|
|
34
|
+
exit 78
|
|
35
|
+
;;
|
|
36
|
+
esac
|
|
37
|
+
|
|
38
|
+
# (#7873) `--disable` closes ~/.curlrc and `--noproxy '*'` closes the proxy vars,
|
|
39
|
+
# but neither touches the env that subverts TLS ITSELF. SSLKEYLOGFILE writes the
|
|
40
|
+
# session keys and the CA vars substitute the trust store, so a CURL_CA_BUNDLE
|
|
41
|
+
# MITM of these credentials works with every other guard fully intact.
|
|
42
|
+
unset SSLKEYLOGFILE CURL_CA_BUNDLE SSL_CERT_FILE SSL_CERT_DIR CURL_HOME \
|
|
43
|
+
HOSTALIASES LOCALDOMAIN RES_OPTIONS
|
|
44
|
+
|
|
45
|
+
# Shared WORM audit-append helper (PostgREST RPC; no DB-CLI binary). See #4581 PR-1.
|
|
46
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
47
|
+
source "$SCRIPT_DIR/../../../scripts/audit-flag-flip.sh"
|
|
48
|
+
|
|
49
|
+
# Human-presence gate (#8486, ADR-249). Every production write below waits on the
|
|
50
|
+
# operator-script library's class-2 ack, which has NO skip variable and no flag:
|
|
51
|
+
# it needs a person typing `yes` at a terminal, so an agent's tool subprocess
|
|
52
|
+
# (no TTY) is refused with exit 64 before any credential fetch. Clear anything an
|
|
53
|
+
# inherited environment could use to pre-empt the library's double-source guard
|
|
54
|
+
# or to stand in for its ack before sourcing it. (BASH_ENV runs before this
|
|
55
|
+
# script and cannot be cleared from inside it — recorded in ADR-249 as a
|
|
56
|
+
# hijack-class residual.)
|
|
57
|
+
unset _SOLEUR_OPERATOR_SCRIPT_LOADED SOLEUR_OP_ACKED
|
|
58
|
+
unset -f soleur_op_ack_or_die soleur_op_input_required soleur_op_aborted
|
|
59
|
+
# shellcheck source=../../../scripts/lib/operator-script.sh
|
|
60
|
+
source "$SCRIPT_DIR/../../../scripts/lib/operator-script.sh"
|
|
61
|
+
[[ ${SOLEUR_OP_LIB_API:-0} -eq 1 ]] || {
|
|
62
|
+
printf 'SOLEUR_BOOTSTRAP_LIB_INCOMPATIBLE need=1 got=%s\n' "${SOLEUR_OP_LIB_API:-0}"
|
|
63
|
+
exit 64
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
readonly FLAGSMITH_PROJECT_ID=39082
|
|
67
|
+
readonly FLAGSMITH_ENV_DEV_ID=90722
|
|
68
|
+
readonly FLAGSMITH_ENV_PRD_ID=90721
|
|
69
|
+
readonly FLAGSMITH_API="https://api.flagsmith.com/api/v1"
|
|
70
|
+
readonly SERVER_TS="apps/web-platform/lib/feature-flags/server.ts"
|
|
71
|
+
readonly ENV_EXAMPLE="apps/web-platform/.env.example"
|
|
72
|
+
|
|
73
|
+
DRY_RUN=0
|
|
74
|
+
DEV_ON=0
|
|
75
|
+
PRD_ON=0
|
|
76
|
+
FLAGSMITH_ONLY=0
|
|
77
|
+
DESCRIPTION=""
|
|
78
|
+
NAME=""
|
|
79
|
+
|
|
80
|
+
while [[ $# -gt 0 ]]; do
|
|
81
|
+
case "$1" in
|
|
82
|
+
--dry-run) DRY_RUN=1; shift ;;
|
|
83
|
+
--dev-on) DEV_ON=1; shift ;;
|
|
84
|
+
--prd-on) PRD_ON=1; shift ;;
|
|
85
|
+
--flagsmith-only) FLAGSMITH_ONLY=1; shift ;;
|
|
86
|
+
--description)
|
|
87
|
+
# A value that looks like a flag is refused, so `--description --dry-run`
|
|
88
|
+
# can never read as a dry run to one parser and a write to another (#8486).
|
|
89
|
+
[[ $# -ge 2 && "$2" != --* ]] || { echo "--description needs a value that does not start with --" >&2; exit 2; }
|
|
90
|
+
DESCRIPTION="$2"; shift 2 ;;
|
|
91
|
+
--*) echo "unknown flag: $1" >&2; exit 1 ;;
|
|
92
|
+
*) NAME="$1"; shift ;;
|
|
93
|
+
esac
|
|
94
|
+
done
|
|
95
|
+
|
|
96
|
+
[[ -z "$NAME" ]] && { echo "Usage: create.sh <kebab-name> [--description ...] [--dev-on] [--prd-on] [--dry-run]" >&2; exit 1; }
|
|
97
|
+
[[ ! "$NAME" =~ ^[a-z][a-z0-9-]*[a-z0-9]$ ]] && { echo "name must be lowercase kebab-case (got: $NAME)" >&2; exit 1; }
|
|
98
|
+
|
|
99
|
+
ENV_VAR="FLAG_$(echo "$NAME" | tr 'a-z-' 'A-Z_')"
|
|
100
|
+
|
|
101
|
+
# --- no TTY, no write: refuse before any credential fetch or network call ---
|
|
102
|
+
if [[ $DRY_RUN -eq 0 ]]; then [[ -t 0 ]] || soleur_op_input_required "destructive-write-ack(no-skip-variable-by-design)" ack; fi
|
|
103
|
+
|
|
104
|
+
# --flagsmith-only (gap 1, #4581 PR-2): the flag is ALREADY code-wired (in
|
|
105
|
+
# RUNTIME_FLAGS + .env.example) — this run only creates the Flagsmith feature.
|
|
106
|
+
# Skip the file-existence checks AND the "already appears in server.ts" exit-1
|
|
107
|
+
# precheck (which would fire precisely because the flag IS already wired), plus
|
|
108
|
+
# the server.ts/.env.example edits and the Doppler mirror further down.
|
|
109
|
+
if [[ $FLAGSMITH_ONLY -eq 0 ]]; then
|
|
110
|
+
[[ ! -f "$SERVER_TS" ]] && { echo "missing $SERVER_TS (run from repo root)" >&2; exit 2; }
|
|
111
|
+
[[ ! -f "$ENV_EXAMPLE" ]] && { echo "missing $ENV_EXAMPLE" >&2; exit 2; }
|
|
112
|
+
|
|
113
|
+
# Pre-check: flag name not already registered.
|
|
114
|
+
if grep -qE "[\"']${NAME}[\"']" "$SERVER_TS"; then
|
|
115
|
+
echo "'$NAME' already appears in $SERVER_TS" >&2; exit 1
|
|
116
|
+
fi
|
|
117
|
+
if grep -qE "^${ENV_VAR}=" "$ENV_EXAMPLE"; then
|
|
118
|
+
echo "$ENV_VAR already in $ENV_EXAMPLE" >&2; exit 1
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
TOKEN=$(doppler secrets get FLAGSMITH_MANAGEMENT_API_KEY -p soleur -c cli_ops --plain 2>/dev/null || true)
|
|
123
|
+
[[ -z "$TOKEN" ]] && { echo "FLAGSMITH_MANAGEMENT_API_KEY not in Doppler soleur/cli_ops" >&2; exit 2; }
|
|
124
|
+
|
|
125
|
+
# Token-shape guard: a newline in the key would inject a curl config directive on the stdin
|
|
126
|
+
# channel below. Never echoes the value.
|
|
127
|
+
_bearer_ok() { local LC_ALL=C; case "${1:-}" in ''|*[!A-Za-z0-9._~+/=-]*) return 1 ;; esac; }
|
|
128
|
+
_bearer_ok "$TOKEN" || { echo "FLAGSMITH_MANAGEMENT_API_KEY has an unexpected shape" >&2; exit 2; }
|
|
129
|
+
|
|
130
|
+
# The Flagsmith management key travels on curl's stdin config channel, never on argv.
|
|
131
|
+
fs_api() {
|
|
132
|
+
curl --disable --noproxy '*' -sS -H "Content-Type: application/json" "$@" --config - \
|
|
133
|
+
< <(printf 'header = "Authorization: Api-Key %s"\n' "$TOKEN")
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Pre-check: not already a feature in Flagsmith.
|
|
137
|
+
EXISTING=$(fs_api "${FLAGSMITH_API}/projects/${FLAGSMITH_PROJECT_ID}/features/?q=${NAME}" \
|
|
138
|
+
| python3 -c "import json,sys; d=json.load(sys.stdin); print(','.join(f['name'] for f in d.get('results', []) if f['name'] == '$NAME'))")
|
|
139
|
+
if [[ -n "$EXISTING" ]]; then
|
|
140
|
+
echo "feature '$NAME' already exists in Flagsmith — use flag-set-role to toggle" >&2; exit 1
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
PRD_DOPPLER_VAL=$([[ $PRD_ON -eq 1 ]] && echo 1 || echo 0)
|
|
144
|
+
|
|
145
|
+
# --- propose ---------------------------------------------------------------
|
|
146
|
+
echo "→ Proposed mutations:"
|
|
147
|
+
echo " 1. Flagsmith: create feature '$NAME' (default_enabled=false)"
|
|
148
|
+
[[ $DEV_ON -eq 1 ]] && echo " + segment override role-dev=ON in BOTH envs"
|
|
149
|
+
[[ $PRD_ON -eq 1 ]] && echo " + segment override role-prd=ON in BOTH envs"
|
|
150
|
+
if [[ $FLAGSMITH_ONLY -eq 1 ]]; then
|
|
151
|
+
echo " (--flagsmith-only: skipping server.ts / $ENV_EXAMPLE / Doppler — flag is already code-wired)"
|
|
152
|
+
else
|
|
153
|
+
echo " 2. $SERVER_TS: add \"$NAME\": \"$ENV_VAR\" to RUNTIME_FLAGS"
|
|
154
|
+
echo " 3. $ENV_EXAMPLE: add $ENV_VAR=$PRD_DOPPLER_VAL"
|
|
155
|
+
echo " 4. Doppler: $ENV_VAR=$PRD_DOPPLER_VAL in soleur/dev AND soleur/prd"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
if [[ $DRY_RUN -eq 1 ]]; then
|
|
159
|
+
echo "(dry-run — exiting 0)"
|
|
160
|
+
exit 0
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
soleur_op_ack_or_die "Create flag '${NAME}' in Flagsmith and wire it into the code and Doppler (dev + prd) now? Type yes: "
|
|
164
|
+
|
|
165
|
+
# --- audit append (WORM) ---------------------------------------------------
|
|
166
|
+
ACTOR=$(doppler secrets get OPERATOR_EMAIL -p soleur -c cli_ops --plain 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
|
167
|
+
[[ -z "$ACTOR" ]] && { echo "FATAL: OPERATOR_EMAIL not in Doppler soleur/cli_ops" >&2; exit 4; }
|
|
168
|
+
|
|
169
|
+
# `|| true` normalizes a Doppler auth/network failure to the exit-4 contract (the
|
|
170
|
+
# [[ -z ]] guard) instead of letting `set -e` abort at the assignment with exit 1.
|
|
171
|
+
AUDIT_URL=$(doppler secrets get SUPABASE_URL -p soleur -c dev --plain 2>/dev/null) || true
|
|
172
|
+
AUDIT_SRK=$(doppler secrets get SUPABASE_SERVICE_ROLE_KEY -p soleur -c dev --plain 2>/dev/null) || true
|
|
173
|
+
[[ -z "$AUDIT_URL" || -z "$AUDIT_SRK" ]] && { echo "FATAL: SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY not in Doppler soleur/dev" >&2; exit 4; }
|
|
174
|
+
|
|
175
|
+
AUDIT_ID=$(audit_flag_flip_rpc "$AUDIT_URL" "$AUDIT_SRK" "$NAME" "dev" "global" "create" null null "$ACTOR") || exit 4
|
|
176
|
+
echo " audit_id=$AUDIT_ID"
|
|
177
|
+
|
|
178
|
+
# --- create feature --------------------------------------------------------
|
|
179
|
+
echo "→ Creating Flagsmith feature '$NAME'…"
|
|
180
|
+
RESP=$(fs_api -X POST "${FLAGSMITH_API}/projects/${FLAGSMITH_PROJECT_ID}/features/" \
|
|
181
|
+
-d "$(python3 -c "
|
|
182
|
+
import json, sys
|
|
183
|
+
print(json.dumps({
|
|
184
|
+
'name': '$NAME',
|
|
185
|
+
'description': '''$DESCRIPTION''' or None,
|
|
186
|
+
'default_enabled': False,
|
|
187
|
+
'project': $FLAGSMITH_PROJECT_ID,
|
|
188
|
+
}))
|
|
189
|
+
")")
|
|
190
|
+
FEATURE_ID=$(echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("id",""))')
|
|
191
|
+
[[ -z "$FEATURE_ID" ]] && { echo "Flagsmith feature create failed: $RESP" >&2; exit 3; }
|
|
192
|
+
echo " feature_id=$FEATURE_ID"
|
|
193
|
+
|
|
194
|
+
# --- segment overrides (if requested) --------------------------------------
|
|
195
|
+
apply_override() {
|
|
196
|
+
local env_id="$1" segment_id="$2"
|
|
197
|
+
local body
|
|
198
|
+
body=$(printf '{"feature_states_to_create":[{"feature_segment":{"segment":%d},"enabled":true,"feature_state_value":{"type":"unicode","string_value":null,"integer_value":null,"boolean_value":null}}],"feature_states_to_update":[],"segment_ids_to_delete_overrides":[],"publish_immediately":true}' "$segment_id")
|
|
199
|
+
fs_api -X POST "${FLAGSMITH_API}/environments/${env_id}/features/${FEATURE_ID}/versions/" -d "$body" >/dev/null
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
resolve_segment() {
|
|
203
|
+
fs_api "${FLAGSMITH_API}/projects/${FLAGSMITH_PROJECT_ID}/segments/" \
|
|
204
|
+
| python3 -c "import json,sys; d=json.load(sys.stdin); [print(s['id']) for s in d.get('results', []) if s['name']=='$1']"
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if [[ $DEV_ON -eq 1 ]]; then
|
|
208
|
+
SEG=$(resolve_segment "role-dev")
|
|
209
|
+
echo "→ Applying role-dev=ON in dev env…"; apply_override "$FLAGSMITH_ENV_DEV_ID" "$SEG"
|
|
210
|
+
echo "→ Applying role-dev=ON in prd env…"; apply_override "$FLAGSMITH_ENV_PRD_ID" "$SEG"
|
|
211
|
+
fi
|
|
212
|
+
if [[ $PRD_ON -eq 1 ]]; then
|
|
213
|
+
SEG=$(resolve_segment "role-prd")
|
|
214
|
+
echo "→ Applying role-prd=ON in dev env…"; apply_override "$FLAGSMITH_ENV_DEV_ID" "$SEG"
|
|
215
|
+
echo "→ Applying role-prd=ON in prd env…"; apply_override "$FLAGSMITH_ENV_PRD_ID" "$SEG"
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
# --- code-wiring + Doppler mirror (skipped under --flagsmith-only) ----------
|
|
219
|
+
if [[ $FLAGSMITH_ONLY -eq 1 ]]; then
|
|
220
|
+
echo
|
|
221
|
+
echo "✓ Done (--flagsmith-only). Flagsmith feature '$NAME' created; server.ts /"
|
|
222
|
+
echo " $ENV_EXAMPLE / Doppler left untouched (flag is already code-wired)."
|
|
223
|
+
echo " Next: scope it per-org with soleur:flag-set-role $NAME prd on --org <orgId>."
|
|
224
|
+
exit 0
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
# --- edit server.ts ---------------------------------------------------------
|
|
228
|
+
echo "→ Editing $SERVER_TS…"
|
|
229
|
+
python3 <<PY || exit 4
|
|
230
|
+
import re, sys
|
|
231
|
+
p = "$SERVER_TS"
|
|
232
|
+
with open(p) as f: src = f.read()
|
|
233
|
+
new_line = ' "$NAME": "$ENV_VAR",\n'
|
|
234
|
+
m = re.search(r'(const RUNTIME_FLAGS = \{)([^}]*)(\}[ \t]*as const;)', src, re.DOTALL)
|
|
235
|
+
if not m:
|
|
236
|
+
print('RUNTIME_FLAGS block not found in', p, file=sys.stderr); sys.exit(1)
|
|
237
|
+
body = m.group(2).rstrip()
|
|
238
|
+
if not body.endswith(','): body += ','
|
|
239
|
+
body += '\n' + new_line
|
|
240
|
+
src = src[:m.start(2)] + body + src[m.end(2):]
|
|
241
|
+
with open(p, 'w') as f: f.write(src)
|
|
242
|
+
print(' added entry to RUNTIME_FLAGS')
|
|
243
|
+
PY
|
|
244
|
+
|
|
245
|
+
# --- edit .env.example -----------------------------------------------------
|
|
246
|
+
echo "→ Editing $ENV_EXAMPLE…"
|
|
247
|
+
python3 <<PY || exit 4
|
|
248
|
+
p = "$ENV_EXAMPLE"
|
|
249
|
+
with open(p) as f: lines = f.readlines()
|
|
250
|
+
# Insert after the existing FLAG_KB_CHAT_SIDEBAR line.
|
|
251
|
+
out = []
|
|
252
|
+
inserted = False
|
|
253
|
+
for line in lines:
|
|
254
|
+
out.append(line)
|
|
255
|
+
if not inserted and line.startswith('FLAG_KB_CHAT_SIDEBAR='):
|
|
256
|
+
out.append('$ENV_VAR=$PRD_DOPPLER_VAL\n')
|
|
257
|
+
inserted = True
|
|
258
|
+
if not inserted:
|
|
259
|
+
out.append('$ENV_VAR=$PRD_DOPPLER_VAL\n')
|
|
260
|
+
with open(p, 'w') as f: f.writelines(out)
|
|
261
|
+
print(' added $ENV_VAR=$PRD_DOPPLER_VAL')
|
|
262
|
+
PY
|
|
263
|
+
|
|
264
|
+
# --- mirror Doppler --------------------------------------------------------
|
|
265
|
+
echo "→ Doppler dev: $ENV_VAR=$PRD_DOPPLER_VAL…"
|
|
266
|
+
printf '%s' "$PRD_DOPPLER_VAL" | doppler secrets set "$ENV_VAR" -p soleur -c dev --silent || exit 5
|
|
267
|
+
echo "→ Doppler prd: $ENV_VAR=$PRD_DOPPLER_VAL…"
|
|
268
|
+
printf '%s' "$PRD_DOPPLER_VAL" | doppler secrets set "$ENV_VAR" -p soleur -c prd --silent || exit 5
|
|
269
|
+
|
|
270
|
+
echo
|
|
271
|
+
echo "✓ Done. Next: review the diff in $SERVER_TS + $ENV_EXAMPLE, then commit:"
|
|
272
|
+
echo " git add $SERVER_TS $ENV_EXAMPLE && git commit -m 'feat(flags): add $NAME runtime flag'"
|
|
273
|
+
exit 0
|