@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.
Files changed (832) hide show
  1. package/.claude-plugin/agents.manifest.json +476 -0
  2. package/.claude-plugin/plugin.json +42 -0
  3. package/README.md +44 -2
  4. package/agents/community/.gitkeep +0 -0
  5. package/agents/engineering/cto.md +87 -0
  6. package/agents/engineering/design/ddd-architect.md +95 -0
  7. package/agents/engineering/discovery/agent-finder.md +214 -0
  8. package/agents/engineering/discovery/functional-discovery.md +182 -0
  9. package/agents/engineering/infra/infra-security.md +151 -0
  10. package/agents/engineering/infra/platform-strategist.md +109 -0
  11. package/agents/engineering/infra/terraform-architect.md +171 -0
  12. package/agents/engineering/prompt-engineer.md +37 -0
  13. package/agents/engineering/research/best-practices-researcher.md +115 -0
  14. package/agents/engineering/research/framework-docs-researcher.md +93 -0
  15. package/agents/engineering/research/git-history-analyzer.md +53 -0
  16. package/agents/engineering/research/learnings-researcher.md +285 -0
  17. package/agents/engineering/research/repo-research-analyst.md +118 -0
  18. package/agents/engineering/review/agent-native-reviewer.md +279 -0
  19. package/agents/engineering/review/architecture-strategist.md +61 -0
  20. package/agents/engineering/review/code-quality-analyst.md +92 -0
  21. package/agents/engineering/review/code-simplicity-reviewer.md +109 -0
  22. package/agents/engineering/review/data-integrity-guardian.md +82 -0
  23. package/agents/engineering/review/data-migration-expert.md +98 -0
  24. package/agents/engineering/review/deployment-verification-agent.md +183 -0
  25. package/agents/engineering/review/dhh-rails-reviewer.md +46 -0
  26. package/agents/engineering/review/kieran-rails-reviewer.md +87 -0
  27. package/agents/engineering/review/legacy-code-expert.md +55 -0
  28. package/agents/engineering/review/observability-coverage-reviewer.md +147 -0
  29. package/agents/engineering/review/pattern-recognition-specialist.md +59 -0
  30. package/agents/engineering/review/performance-oracle.md +130 -0
  31. package/agents/engineering/review/security-sentinel.md +167 -0
  32. package/agents/engineering/review/semgrep-sast.md +36 -0
  33. package/agents/engineering/review/test-design-reviewer.md +150 -0
  34. package/agents/engineering/review/user-impact-reviewer.md +70 -0
  35. package/agents/engineering/workflow/pr-comment-resolver.md +69 -0
  36. package/agents/finance/budget-analyst.md +29 -0
  37. package/agents/finance/cfo.md +44 -0
  38. package/agents/finance/financial-reporter.md +30 -0
  39. package/agents/finance/revenue-analyst.md +30 -0
  40. package/agents/legal/clo.md +115 -0
  41. package/agents/legal/legal-compliance-auditor.md +110 -0
  42. package/agents/legal/legal-document-generator.md +134 -0
  43. package/agents/marketing/analytics-analyst.md +25 -0
  44. package/agents/marketing/brand-architect.md +181 -0
  45. package/agents/marketing/cmo.md +76 -0
  46. package/agents/marketing/conversion-optimizer.md +19 -0
  47. package/agents/marketing/copywriter.md +20 -0
  48. package/agents/marketing/fact-checker.md +70 -0
  49. package/agents/marketing/growth-strategist.md +145 -0
  50. package/agents/marketing/paid-media-strategist.md +28 -0
  51. package/agents/marketing/pricing-strategist.md +17 -0
  52. package/agents/marketing/programmatic-seo-specialist.md +25 -0
  53. package/agents/marketing/retention-strategist.md +23 -0
  54. package/agents/marketing/seo-aeo-analyst.md +164 -0
  55. package/agents/operations/coo.md +50 -0
  56. package/agents/operations/ops-advisor.md +78 -0
  57. package/agents/operations/ops-provisioner.md +101 -0
  58. package/agents/operations/ops-research.md +52 -0
  59. package/agents/operations/service-automator.md +278 -0
  60. package/agents/product/business-validator.md +206 -0
  61. package/agents/product/competitive-intelligence.md +89 -0
  62. package/agents/product/cpo.md +63 -0
  63. package/agents/product/design/ux-design-lead.md +209 -0
  64. package/agents/product/spec-flow-analyzer.md +122 -0
  65. package/agents/sales/cro.md +44 -0
  66. package/agents/sales/deal-architect.md +29 -0
  67. package/agents/sales/outbound-strategist.md +29 -0
  68. package/agents/sales/pipeline-analyst.md +29 -0
  69. package/agents/support/cco.md +48 -0
  70. package/agents/support/community-manager.md +570 -0
  71. package/agents/support/ticket-triage.md +70 -0
  72. package/bin/soleur-opencode.js +29 -0
  73. package/commands/go.md +660 -0
  74. package/commands/help.md +273 -0
  75. package/commands/sync.md +977 -0
  76. package/commands/version.md +103 -0
  77. package/hooks/antigravity-hooks.json +84 -0
  78. package/hooks/antigravity-session-start.sh +15 -0
  79. package/hooks/bare-root-cwd-guard.sh +131 -0
  80. package/hooks/browser-snapshot-credential-guard.sh +200 -0
  81. package/hooks/codex-session-start.sh +9 -0
  82. package/hooks/compaction-state.sh +525 -0
  83. package/hooks/destructive-command-guard.sh +1387 -0
  84. package/hooks/devin-session-start.sh +90 -0
  85. package/hooks/ext-filter-detect.sh +171 -0
  86. package/hooks/hooks.json +133 -0
  87. package/hooks/lib/hook-tool-kind.sh +24 -0
  88. package/hooks/lib/log-rotation.sh +176 -0
  89. package/hooks/lib/shell-argv.pl +576 -0
  90. package/hooks/memory-backstop.sh +1114 -0
  91. package/hooks/operator-stage-approval.sh +391 -0
  92. package/hooks/stop-hook.sh +367 -0
  93. package/hooks/unkept-promise-hook.sh +383 -0
  94. package/hooks/version-banner.sh +127 -0
  95. package/hooks/welcome-hook.sh +50 -0
  96. package/install.js +29 -0
  97. package/lib/agent-registry.ts +154 -0
  98. package/lib/c4-canonical-cli.mjs +34 -0
  99. package/lib/c4-canonical.mjs +46 -0
  100. package/lib/c4-from-components.ts +554 -0
  101. package/lib/go-routing.ts +81 -0
  102. package/lib/grok-inspect-contract.ts +311 -0
  103. package/lib/harness-model-map.ts +101 -0
  104. package/lib/harness-parity.ts +726 -0
  105. package/lib/harness-tool-map.ts +180 -0
  106. package/lib/harness.ts +716 -0
  107. package/lib/heartbeat-live-reconcile.ts +1153 -0
  108. package/lib/heartbeat-manifest.ts +361 -0
  109. package/lib/kb-coverage.ts +252 -0
  110. package/lib/pr-merge-poll.ts +103 -0
  111. package/lib/workflow-fidelity.ts +388 -0
  112. package/opencode/INSTRUCTIONS.md +171 -0
  113. package/opencode/agents/engineering/cto.md +10 -0
  114. package/opencode/agents/engineering/design/ddd-architect.md +10 -0
  115. package/opencode/agents/engineering/discovery/agent-finder.md +10 -0
  116. package/opencode/agents/engineering/discovery/functional-discovery.md +10 -0
  117. package/opencode/agents/engineering/infra/infra-security.md +10 -0
  118. package/opencode/agents/engineering/infra/platform-strategist.md +10 -0
  119. package/opencode/agents/engineering/infra/terraform-architect.md +10 -0
  120. package/opencode/agents/engineering/prompt-engineer.md +10 -0
  121. package/opencode/agents/engineering/research/best-practices-researcher.md +10 -0
  122. package/opencode/agents/engineering/research/framework-docs-researcher.md +10 -0
  123. package/opencode/agents/engineering/research/git-history-analyzer.md +10 -0
  124. package/opencode/agents/engineering/research/learnings-researcher.md +10 -0
  125. package/opencode/agents/engineering/research/repo-research-analyst.md +10 -0
  126. package/opencode/agents/engineering/review/agent-native-reviewer.md +10 -0
  127. package/opencode/agents/engineering/review/architecture-strategist.md +10 -0
  128. package/opencode/agents/engineering/review/code-quality-analyst.md +10 -0
  129. package/opencode/agents/engineering/review/code-simplicity-reviewer.md +10 -0
  130. package/opencode/agents/engineering/review/data-integrity-guardian.md +10 -0
  131. package/opencode/agents/engineering/review/data-migration-expert.md +10 -0
  132. package/opencode/agents/engineering/review/deployment-verification-agent.md +10 -0
  133. package/opencode/agents/engineering/review/dhh-rails-reviewer.md +10 -0
  134. package/opencode/agents/engineering/review/kieran-rails-reviewer.md +10 -0
  135. package/opencode/agents/engineering/review/legacy-code-expert.md +10 -0
  136. package/opencode/agents/engineering/review/observability-coverage-reviewer.md +10 -0
  137. package/opencode/agents/engineering/review/pattern-recognition-specialist.md +10 -0
  138. package/opencode/agents/engineering/review/performance-oracle.md +10 -0
  139. package/opencode/agents/engineering/review/security-sentinel.md +10 -0
  140. package/opencode/agents/engineering/review/semgrep-sast.md +10 -0
  141. package/opencode/agents/engineering/review/test-design-reviewer.md +10 -0
  142. package/opencode/agents/engineering/review/user-impact-reviewer.md +10 -0
  143. package/opencode/agents/engineering/workflow/pr-comment-resolver.md +10 -0
  144. package/opencode/agents/finance/budget-analyst.md +10 -0
  145. package/opencode/agents/finance/cfo.md +10 -0
  146. package/opencode/agents/finance/financial-reporter.md +10 -0
  147. package/opencode/agents/finance/revenue-analyst.md +10 -0
  148. package/opencode/agents/legal/clo.md +10 -0
  149. package/opencode/agents/legal/legal-compliance-auditor.md +10 -0
  150. package/opencode/agents/legal/legal-document-generator.md +10 -0
  151. package/opencode/agents/marketing/analytics-analyst.md +10 -0
  152. package/opencode/agents/marketing/brand-architect.md +10 -0
  153. package/opencode/agents/marketing/cmo.md +10 -0
  154. package/opencode/agents/marketing/conversion-optimizer.md +10 -0
  155. package/opencode/agents/marketing/copywriter.md +10 -0
  156. package/opencode/agents/marketing/fact-checker.md +10 -0
  157. package/opencode/agents/marketing/growth-strategist.md +10 -0
  158. package/opencode/agents/marketing/paid-media-strategist.md +10 -0
  159. package/opencode/agents/marketing/pricing-strategist.md +10 -0
  160. package/opencode/agents/marketing/programmatic-seo-specialist.md +10 -0
  161. package/opencode/agents/marketing/retention-strategist.md +10 -0
  162. package/opencode/agents/marketing/seo-aeo-analyst.md +10 -0
  163. package/opencode/agents/operations/coo.md +10 -0
  164. package/opencode/agents/operations/ops-advisor.md +10 -0
  165. package/opencode/agents/operations/ops-provisioner.md +10 -0
  166. package/opencode/agents/operations/ops-research.md +10 -0
  167. package/opencode/agents/operations/service-automator.md +10 -0
  168. package/opencode/agents/product/business-validator.md +10 -0
  169. package/opencode/agents/product/competitive-intelligence.md +10 -0
  170. package/opencode/agents/product/cpo.md +10 -0
  171. package/opencode/agents/product/design/ux-design-lead.md +10 -0
  172. package/opencode/agents/product/spec-flow-analyzer.md +10 -0
  173. package/opencode/agents/sales/cro.md +10 -0
  174. package/opencode/agents/sales/deal-architect.md +10 -0
  175. package/opencode/agents/sales/outbound-strategist.md +10 -0
  176. package/opencode/agents/sales/pipeline-analyst.md +10 -0
  177. package/opencode/agents/support/cco.md +10 -0
  178. package/opencode/agents/support/community-manager.md +10 -0
  179. package/opencode/agents/support/ticket-triage.md +10 -0
  180. package/opencode/commands/go.md +10 -0
  181. package/opencode/commands/help.md +10 -0
  182. package/opencode/commands/sync.md +10 -0
  183. package/opencode/commands/version.md +11 -0
  184. package/opencode/opencode.json +8 -0
  185. package/opencode/plugin.ts +818 -0
  186. package/package.json +36 -4
  187. package/scripts/admin-merge-ready.sh +545 -0
  188. package/scripts/admin-merge-ready.test.sh +753 -0
  189. package/scripts/affected-tests.sh +908 -0
  190. package/scripts/affected-tests.test.sh +1797 -0
  191. package/scripts/alpha-metrics.sh +78 -0
  192. package/scripts/alpha-metrics.test.sh +115 -0
  193. package/scripts/ancestor-signal-helpers.baseline.txt +16 -0
  194. package/scripts/audit-flag-flip.sh +107 -0
  195. package/scripts/check-red-on-main.sh +316 -0
  196. package/scripts/ci-head-verdict.sh +411 -0
  197. package/scripts/cloud-detect.sh +193 -0
  198. package/scripts/delegation-verify.sh +657 -0
  199. package/scripts/delegation-verify.test.sh +1424 -0
  200. package/scripts/deploy-arm.sh +475 -0
  201. package/scripts/domain-model-drift.sh +419 -0
  202. package/scripts/emit-decision.sh +144 -0
  203. package/scripts/emit-decision.test.sh +144 -0
  204. package/scripts/ext-filter-divergence-corpus.txt +15 -0
  205. package/scripts/ext-filter-divergence.sh +189 -0
  206. package/scripts/generate-c4-from-components.ts +442 -0
  207. package/scripts/grok-fidelity-gate.sh +68 -0
  208. package/scripts/grok-pre-push-gate.sh +232 -0
  209. package/scripts/harness-discovery-smoke.ts +906 -0
  210. package/scripts/harness-parity-census.ts +92 -0
  211. package/scripts/inngest-luks-alert-armed-probe.ts +29 -0
  212. package/scripts/install-opencode-adapter.ts +509 -0
  213. package/scripts/lib/affected-tests/common.sh +365 -0
  214. package/scripts/lib/affected-tests/go.sh +157 -0
  215. package/scripts/lib/affected-tests/js.sh +188 -0
  216. package/scripts/lib/affected-tests/nx-turbo.sh +98 -0
  217. package/scripts/lib/affected-tests/python.sh +185 -0
  218. package/scripts/lib/context-sanitize.sh +49 -0
  219. package/scripts/lib/domain-model-lib.sh +180 -0
  220. package/scripts/lib/ext-filter-grammar.tsv +34 -0
  221. package/scripts/lib/operator-script.sh +1236 -0
  222. package/scripts/lib/proc.sh +580 -0
  223. package/scripts/lib/session-state.sh +748 -0
  224. package/scripts/lib/tmp-classify.sh +843 -0
  225. package/scripts/lib/wrapper-boundary.sh +47 -0
  226. package/scripts/lint-ratchet.py +1547 -0
  227. package/scripts/monitor-pr-checks.sh +441 -0
  228. package/scripts/pipeline-tally.sh +756 -0
  229. package/scripts/pipeline-tally.test.sh +740 -0
  230. package/scripts/plugin-version.sh +528 -0
  231. package/scripts/precommit-guard.sh +115 -0
  232. package/scripts/precommit-guard.test.sh +254 -0
  233. package/scripts/reconcile-live-heartbeats.ts +705 -0
  234. package/scripts/render-c4-model.sh +217 -0
  235. package/scripts/resolve-git-root.sh +55 -0
  236. package/scripts/resolve-regenerable-conflicts.sh +363 -0
  237. package/scripts/resolve-regenerable-conflicts.test.sh +780 -0
  238. package/scripts/ruff-requirements.txt +22 -0
  239. package/scripts/run-in-pid-namespace.sh +98 -0
  240. package/scripts/run-in-pid-namespace.test.sh +290 -0
  241. package/scripts/scan-ancestor-signal-helpers.py +556 -0
  242. package/scripts/scan-ancestor-signal-helpers.test.sh +670 -0
  243. package/scripts/setup-ralph-loop.sh +238 -0
  244. package/scripts/sync-cursor-name-map.ts +316 -0
  245. package/scripts/sync-grok-agent-compat.ts +188 -0
  246. package/scripts/sync-npm-package.ts +165 -0
  247. package/scripts/sync-opencode-adapter.ts +498 -0
  248. package/scripts/sync-pr-behind.sh +647 -0
  249. package/scripts/sync-pr-behind.test.sh +252 -0
  250. package/scripts/taste-profile-update.sh +180 -0
  251. package/scripts/taste-profile-update.test.sh +167 -0
  252. package/scripts/write-budget-marker.sh +23 -0
  253. package/scripts/write-kb-coverage.ts +113 -0
  254. package/skills/admin-ip-refresh/SKILL.md +81 -0
  255. package/skills/admin-ip-refresh/references/admin-ip-refresh-procedure.md +201 -0
  256. package/skills/agent-browser/SKILL.md +698 -0
  257. package/skills/agent-browser/scripts/playwright-mcp-profile-slot.sh +304 -0
  258. package/skills/agent-browser/scripts/playwright-mcp-redact-proxy.py +964 -0
  259. package/skills/agent-browser/scripts/redact-a11y-snapshot.py +443 -0
  260. package/skills/agent-browser/test/fixtures/capture-playwright-mcp-fixtures.py +217 -0
  261. package/skills/agent-browser/test/fixtures/fake-passthrough-proxy.py +24 -0
  262. package/skills/agent-browser/test/fixtures/fake-playwright-mcp.py +131 -0
  263. package/skills/agent-browser/test/fixtures/make-proxy-mutant.py +48 -0
  264. package/skills/agent-browser/test/fixtures/odd-shapes/dialog-link-injection.json +10 -0
  265. package/skills/agent-browser/test/fixtures/odd-shapes/empty-content.json +5 -0
  266. package/skills/agent-browser/test/fixtures/odd-shapes/error-and-result.json +4 -0
  267. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-bool.json +6 -0
  268. package/skills/agent-browser/test/fixtures/odd-shapes/error-code-string.json +6 -0
  269. package/skills/agent-browser/test/fixtures/odd-shapes/error-message-tree.json +6 -0
  270. package/skills/agent-browser/test/fixtures/odd-shapes/error-no-data.json +6 -0
  271. package/skills/agent-browser/test/fixtures/odd-shapes/error-string.json +4 -0
  272. package/skills/agent-browser/test/fixtures/odd-shapes/error-with-data.json +9 -0
  273. package/skills/agent-browser/test/fixtures/odd-shapes/evaluate-escaped-object.json +10 -0
  274. package/skills/agent-browser/test/fixtures/odd-shapes/invalid-utf8.json +4 -0
  275. package/skills/agent-browser/test/fixtures/odd-shapes/link-result.json +10 -0
  276. package/skills/agent-browser/test/fixtures/odd-shapes/list-two-results.json +6 -0
  277. package/skills/agent-browser/test/fixtures/odd-shapes/meta-in-result.json +13 -0
  278. package/skills/agent-browser/test/fixtures/odd-shapes/no-content.json +5 -0
  279. package/skills/agent-browser/test/fixtures/odd-shapes/quoted-key.json +10 -0
  280. package/skills/agent-browser/test/fixtures/odd-shapes/resource-block.json +18 -0
  281. package/skills/agent-browser/test/fixtures/odd-shapes/result-and-method.json +11 -0
  282. package/skills/agent-browser/test/fixtures/odd-shapes/result-string.json +3 -0
  283. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped-one-row.json +10 -0
  284. package/skills/agent-browser/test/fixtures/odd-shapes/run-code-escaped.json +10 -0
  285. package/skills/agent-browser/test/fixtures/odd-shapes/structured-content.json +13 -0
  286. package/skills/agent-browser/test/fixtures/odd-shapes/tools-list-no-tools.json +5 -0
  287. package/skills/agent-browser/test/fixtures/odd-shapes/tree-no-credential.json +10 -0
  288. package/skills/agent-browser/test/fixtures/odd-shapes/two-text-blocks.json +14 -0
  289. package/skills/agent-browser/test/fixtures/odd-shapes/unparsable-line.json +3 -0
  290. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-brace.json +10 -0
  291. package/skills/agent-browser/test/fixtures/odd-shapes/value-contains-link-substring.json +10 -0
  292. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/close.json +12 -0
  293. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/evaluate.json +12 -0
  294. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/find.json +12 -0
  295. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/framing.json +6 -0
  296. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/initialize.json +14 -0
  297. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate-link.json +12 -0
  298. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/navigate.json +12 -0
  299. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/roots-list-request.json +5 -0
  300. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/screenshot.json +17 -0
  301. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-filename.json +12 -0
  302. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-json.json +12 -0
  303. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot-meta-raw.json +12 -0
  304. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/snapshot.json +12 -0
  305. package/skills/agent-browser/test/fixtures/playwright-mcp-0.0.78/tools-list.json +827 -0
  306. package/skills/agent-browser/test/fixtures/proxy-session-driver.py +138 -0
  307. package/skills/agent-browser/test/fixtures/session-facts.py +102 -0
  308. package/skills/agent-browser/test/playwright-mcp-lifetime.test.sh +1620 -0
  309. package/skills/agent-browser/test/playwright-mcp-redact-proxy.test.sh +1599 -0
  310. package/skills/agent-browser/test/redact-a11y-snapshot.test.sh +527 -0
  311. package/skills/agent-native-architecture/SKILL.md +479 -0
  312. package/skills/agent-native-architecture/references/action-parity-discipline.md +430 -0
  313. package/skills/agent-native-architecture/references/agent-execution-patterns.md +483 -0
  314. package/skills/agent-native-architecture/references/agent-native-testing.md +605 -0
  315. package/skills/agent-native-architecture/references/architecture-patterns.md +493 -0
  316. package/skills/agent-native-architecture/references/dynamic-context-injection.md +358 -0
  317. package/skills/agent-native-architecture/references/files-universal-interface.md +314 -0
  318. package/skills/agent-native-architecture/references/from-primitives-to-domain-tools.md +381 -0
  319. package/skills/agent-native-architecture/references/mcp-tool-design.md +524 -0
  320. package/skills/agent-native-architecture/references/mobile-patterns.md +897 -0
  321. package/skills/agent-native-architecture/references/product-implications.md +478 -0
  322. package/skills/agent-native-architecture/references/refactoring-to-prompt-native.md +342 -0
  323. package/skills/agent-native-architecture/references/self-modification.md +294 -0
  324. package/skills/agent-native-architecture/references/shared-workspace-architecture.md +700 -0
  325. package/skills/agent-native-architecture/references/system-prompt-design.md +263 -0
  326. package/skills/agent-native-audit/SKILL.md +300 -0
  327. package/skills/agent-native-audit/workflows/agent-native-audit.workflow.js +423 -0
  328. package/skills/andrew-kane-gem-writer/SKILL.md +189 -0
  329. package/skills/andrew-kane-gem-writer/references/database-adapters.md +231 -0
  330. package/skills/andrew-kane-gem-writer/references/module-organization.md +121 -0
  331. package/skills/andrew-kane-gem-writer/references/rails-integration.md +183 -0
  332. package/skills/andrew-kane-gem-writer/references/resources.md +126 -0
  333. package/skills/andrew-kane-gem-writer/references/testing-patterns.md +261 -0
  334. package/skills/architecture/SKILL.md +436 -0
  335. package/skills/architecture/references/adr-template.md +154 -0
  336. package/skills/architecture/references/likec4-reference.md +136 -0
  337. package/skills/architecture/references/nfr-reference.md +126 -0
  338. package/skills/archive-kb/SKILL.md +86 -0
  339. package/skills/archive-kb/scripts/archive-kb.sh +300 -0
  340. package/skills/archive-kb/test/archive-kb-partial-run.test.sh +276 -0
  341. package/skills/atdd-developer/SKILL.md +65 -0
  342. package/skills/brainstorm/SKILL.md +701 -0
  343. package/skills/brainstorm/references/brainstorm-brand-workshop.md +153 -0
  344. package/skills/brainstorm/references/brainstorm-domain-config.md +63 -0
  345. package/skills/brainstorm/references/brainstorm-validation-workshop.md +65 -0
  346. package/skills/brainstorm/references/ui-surface-terms.md +42 -0
  347. package/skills/brainstorm-techniques/SKILL.md +231 -0
  348. package/skills/brainstorm-techniques/references/decision-principles.md +150 -0
  349. package/skills/brainstorm-techniques/references/phase-boundaries.md +103 -0
  350. package/skills/brainstorm-techniques/references/standing-delegation.md +407 -0
  351. package/skills/brainstorm-techniques/references/technical-ruling-delegation.md +174 -0
  352. package/skills/campaign-calendar/SKILL.md +145 -0
  353. package/skills/cf-token-scope/SKILL.md +164 -0
  354. package/skills/cf-token-scope/references/widen-playbook.md +114 -0
  355. package/skills/cf-token-scope/scripts/cf-token-scope.sh +253 -0
  356. package/skills/changelog/SKILL.md +142 -0
  357. package/skills/code-to-prd/SKILL.md +66 -0
  358. package/skills/code-to-prd/references/banner-template.md +12 -0
  359. package/skills/code-to-prd/references/prd-template.md +41 -0
  360. package/skills/code-to-prd/scripts/code-to-prd.sh +634 -0
  361. package/skills/code-to-prd/test/code-to-prd.test.sh +447 -0
  362. package/skills/code-to-prd/test/fixture/.env.example +7 -0
  363. package/skills/code-to-prd/test/fixture/app/about/page.tsx +11 -0
  364. package/skills/code-to-prd/test/fixture/app/api/health/route.ts +10 -0
  365. package/skills/code-to-prd/test/fixture/app/page.tsx +14 -0
  366. package/skills/code-to-prd/test/fixture/next.config.mjs +3 -0
  367. package/skills/code-to-prd/test/fixture/package.json +6 -0
  368. package/skills/cohort-status/SKILL.md +62 -0
  369. package/skills/community/SKILL.md +210 -0
  370. package/skills/community/scripts/bsky-community.sh +644 -0
  371. package/skills/community/scripts/bsky-setup.sh +631 -0
  372. package/skills/community/scripts/community-router.sh +93 -0
  373. package/skills/community/scripts/discord-community.sh +487 -0
  374. package/skills/community/scripts/discord-setup.sh +784 -0
  375. package/skills/community/scripts/github-community.sh +706 -0
  376. package/skills/community/scripts/hn-community.sh +233 -0
  377. package/skills/community/scripts/lib/hmac-sha1-b64.sh +126 -0
  378. package/skills/community/scripts/linkedin-community.sh +750 -0
  379. package/skills/community/scripts/linkedin-setup.sh +758 -0
  380. package/skills/community/scripts/x-community.sh +890 -0
  381. package/skills/community/scripts/x-setup.sh +713 -0
  382. package/skills/community/test/community-argv.test.sh +2922 -0
  383. package/skills/community/test/github-community.test.sh +981 -0
  384. package/skills/competitive-analysis/SKILL.md +69 -0
  385. package/skills/competitive-analysis/references/peer-plugin-audit.md +218 -0
  386. package/skills/compound/SKILL.md +673 -0
  387. package/skills/compound/scripts/token-efficiency-report.sh +334 -0
  388. package/skills/compound/test/phase-16.test.sh +379 -0
  389. package/skills/compound-capture/SKILL.md +791 -0
  390. package/skills/compound-capture/assets/critical-pattern-template.md +37 -0
  391. package/skills/compound-capture/assets/resolution-template.md +116 -0
  392. package/skills/compound-capture/references/yaml-schema.md +67 -0
  393. package/skills/compound-capture/schema.yaml +181 -0
  394. package/skills/constraint-scaffold/SKILL.md +175 -0
  395. package/skills/constraint-scaffold/references/boundary-readme.template +35 -0
  396. package/skills/constraint-scaffold/references/constraint-gates-workflow.template +69 -0
  397. package/skills/constraint-scaffold/references/depcruise-config.template +230 -0
  398. package/skills/constraint-scaffold/references/fix-constraints-stage-a.template +240 -0
  399. package/skills/constraint-scaffold/references/fix-constraints-stage-b.template +313 -0
  400. package/skills/constraint-scaffold/references/shared-runner.template +135 -0
  401. package/skills/constraint-scaffold/scripts/constraint-scaffold.sh +589 -0
  402. package/skills/constraint-scaffold/test/bite-proof.test.sh +1338 -0
  403. package/skills/constraint-scaffold/test/boundary.test.sh +734 -0
  404. package/skills/constraint-scaffold/test/emit-fix-constraints.test.sh +193 -0
  405. package/skills/constraint-scaffold/test/generator.test.sh +93 -0
  406. package/skills/constraint-scaffold/test/parity.test.sh +285 -0
  407. package/skills/content-writer/SKILL.md +242 -0
  408. package/skills/content-writer/scripts/blog-jargon-scan.sh +42 -0
  409. package/skills/cron-delete/SKILL.md +56 -0
  410. package/skills/cron-list/SKILL.md +54 -0
  411. package/skills/deepen-plan/SKILL.md +937 -0
  412. package/skills/deepen-plan/workflows/deepen-plan.workflow.js +488 -0
  413. package/skills/deploy/SKILL.md +115 -0
  414. package/skills/deploy/references/hetzner-setup.md +67 -0
  415. package/skills/deploy/scripts/deploy.sh +37 -0
  416. package/skills/deploy-docs/SKILL.md +95 -0
  417. package/skills/dhh-rails-style/SKILL.md +203 -0
  418. package/skills/dhh-rails-style/references/architecture.md +717 -0
  419. package/skills/dhh-rails-style/references/controllers.md +323 -0
  420. package/skills/dhh-rails-style/references/frontend.md +556 -0
  421. package/skills/dhh-rails-style/references/gems.md +316 -0
  422. package/skills/dhh-rails-style/references/models.md +388 -0
  423. package/skills/dhh-rails-style/references/testing.md +354 -0
  424. package/skills/discord-content/SKILL.md +126 -0
  425. package/skills/docs-site/SKILL.md +214 -0
  426. package/skills/drain-labeled-backlog/SKILL.md +203 -0
  427. package/skills/drain-labeled-backlog/scripts/group-by-area.sh +208 -0
  428. package/skills/drain-labeled-backlog/workflows/drain-labeled-backlog.workflow.js +433 -0
  429. package/skills/drain-prs/SKILL.md +143 -0
  430. package/skills/drain-prs/scripts/triage-prs.sh +192 -0
  431. package/skills/drain-prs/test/argv-ceiling.test.sh +183 -0
  432. package/skills/dspy-ruby/SKILL.md +634 -0
  433. package/skills/dspy-ruby/assets/config-template.rb +359 -0
  434. package/skills/dspy-ruby/assets/module-template.rb +326 -0
  435. package/skills/dspy-ruby/assets/signature-template.rb +143 -0
  436. package/skills/dspy-ruby/references/core-concepts.md +268 -0
  437. package/skills/dspy-ruby/references/optimization.md +623 -0
  438. package/skills/dspy-ruby/references/providers.md +335 -0
  439. package/skills/eval-harness/README.md +194 -0
  440. package/skills/eval-harness/SKILL.md +157 -0
  441. package/skills/eval-harness/enums/go-routes.json +13 -0
  442. package/skills/eval-harness/enums/incident-threshold.json +5 -0
  443. package/skills/eval-harness/enums/lane.json +5 -0
  444. package/skills/eval-harness/enums/tool-selection.json +20 -0
  445. package/skills/eval-harness/enums/triage-levels.json +5 -0
  446. package/skills/eval-harness/gated-skills.json +34 -0
  447. package/skills/eval-harness/models.generated.json +5 -0
  448. package/skills/eval-harness/promptfooconfig-go-routing.yaml +35 -0
  449. package/skills/eval-harness/promptfooconfig-incident-threshold.yaml +32 -0
  450. package/skills/eval-harness/promptfooconfig-lane-inference.yaml +33 -0
  451. package/skills/eval-harness/promptfooconfig-ticket-triage.yaml +34 -0
  452. package/skills/eval-harness/promptfooconfig-tool-selection.yaml +33 -0
  453. package/skills/eval-harness/prompts/go-baseline.txt +6 -0
  454. package/skills/eval-harness/prompts/go-skill.txt +21 -0
  455. package/skills/eval-harness/prompts/incident-threshold-baseline.txt +6 -0
  456. package/skills/eval-harness/prompts/incident-threshold-skill.txt +12 -0
  457. package/skills/eval-harness/prompts/lane-inference-baseline.txt +6 -0
  458. package/skills/eval-harness/prompts/lane-inference-skill.txt +15 -0
  459. package/skills/eval-harness/prompts/tool-selection-baseline.txt +19 -0
  460. package/skills/eval-harness/prompts/tool-selection-skill.txt +22 -0
  461. package/skills/eval-harness/prompts/triage-baseline.txt +7 -0
  462. package/skills/eval-harness/prompts/triage-skill.txt +10 -0
  463. package/skills/eval-harness/scripts/eval-gate.cjs +318 -0
  464. package/skills/eval-harness/scripts/extract-block.cjs +87 -0
  465. package/skills/eval-harness/scripts/gate-classification.cjs +28 -0
  466. package/skills/eval-harness/scripts/gen-models.sh +41 -0
  467. package/skills/eval-harness/scripts/gen-skill-prompt.cjs +177 -0
  468. package/skills/eval-harness/scripts/measure-classification.cjs +30 -0
  469. package/skills/eval-harness/scripts/parse-label.cjs +93 -0
  470. package/skills/eval-harness/scripts/verdict.cjs +132 -0
  471. package/skills/eval-harness/tasks/go-routing.jsonl +8 -0
  472. package/skills/eval-harness/tasks/incident-threshold.jsonl +7 -0
  473. package/skills/eval-harness/tasks/lane-inference.jsonl +7 -0
  474. package/skills/eval-harness/tasks/ticket-triage.jsonl +6 -0
  475. package/skills/eval-harness/tasks/tool-selection.jsonl +15 -0
  476. package/skills/eval-harness/test/eval-gate.test.sh +132 -0
  477. package/skills/eval-harness/test/extract-block.test.sh +87 -0
  478. package/skills/eval-harness/test/gate-classification.test.sh +77 -0
  479. package/skills/eval-harness/test/gen-models.test.sh +75 -0
  480. package/skills/eval-harness/test/measure-classification.test.sh +74 -0
  481. package/skills/eval-harness/test/parse-label.test.sh +129 -0
  482. package/skills/eval-harness/test/registry-completeness.test.sh +109 -0
  483. package/skills/eval-harness/test/verdict.test.sh +123 -0
  484. package/skills/every-style-editor/SKILL.md +142 -0
  485. package/skills/every-style-editor/references/EVERY_WRITE_STYLE.md +529 -0
  486. package/skills/feature-tweet/SKILL.md +199 -0
  487. package/skills/feature-video/SKILL.md +412 -0
  488. package/skills/feature-video/scripts/check_deps.sh +281 -0
  489. package/skills/file-todos/SKILL.md +267 -0
  490. package/skills/file-todos/assets/todo-template.md +166 -0
  491. package/skills/fix-issue/SKILL.md +278 -0
  492. package/skills/fix-issue/references/agent-authored-exclusion.md +120 -0
  493. package/skills/fix-issue/references/exclude-label-jq-snippet.md +97 -0
  494. package/skills/flag-bootstrap/SETUP.md +142 -0
  495. package/skills/flag-create/SKILL.md +145 -0
  496. package/skills/flag-create/scripts/create.sh +273 -0
  497. package/skills/flag-delete/SKILL.md +167 -0
  498. package/skills/flag-delete/scripts/delete.sh +288 -0
  499. package/skills/flag-list/SKILL.md +99 -0
  500. package/skills/flag-list/scripts/list.sh +275 -0
  501. package/skills/flag-set-role/SKILL.md +229 -0
  502. package/skills/flag-set-role/scripts/flip.sh +774 -0
  503. package/skills/frontend-anti-slop/SKILL.md +106 -0
  504. package/skills/frontend-anti-slop/references/anti-patterns.md +199 -0
  505. package/skills/frontend-anti-slop/references/slop-rules.md +65 -0
  506. package/skills/frontend-anti-slop/scripts/tier1-scan.ts +525 -0
  507. package/skills/frontend-design/SKILL.md +77 -0
  508. package/skills/gdpr-gate/NOTICE +136 -0
  509. package/skills/gdpr-gate/SKILL.md +341 -0
  510. package/skills/gdpr-gate/references/fields.md +160 -0
  511. package/skills/gdpr-gate/references/layers/api-layer.md +355 -0
  512. package/skills/gdpr-gate/references/layers/auth-sessions.md +290 -0
  513. package/skills/gdpr-gate/references/layers/data-in-transit.md +331 -0
  514. package/skills/gdpr-gate/references/layers/data-lifecycle.md +341 -0
  515. package/skills/gdpr-gate/references/layers/frontend.md +249 -0
  516. package/skills/gdpr-gate/references/layers/testing-seeding.md +256 -0
  517. package/skills/gdpr-gate/references/leakage-vectors.md +248 -0
  518. package/skills/gdpr-gate/references/legacy/legal-consent-v1-prose.md +48 -0
  519. package/skills/gdpr-gate/references/legal-consent.md +140 -0
  520. package/skills/gdpr-gate/references/non-negotiables.md +60 -0
  521. package/skills/gdpr-gate/scripts/gdpr-gate.sh +271 -0
  522. package/skills/gdpr-gate/scripts/notice-frontmatter.sh +337 -0
  523. package/skills/gdpr-gate/scripts/path-denylist.txt +39 -0
  524. package/skills/gdpr-gate/scripts/repo-scan.sh +158 -0
  525. package/skills/gdpr-gate/scripts/vendor-drift-classify.sh +120 -0
  526. package/skills/gdpr-gate/scripts/vendor-pin-integrity.sh +237 -0
  527. package/skills/gemini-imagegen/SKILL.md +283 -0
  528. package/skills/gemini-imagegen/requirements.txt +5 -0
  529. package/skills/gemini-imagegen/scripts/_error_handling.py +146 -0
  530. package/skills/gemini-imagegen/scripts/compose_images.py +150 -0
  531. package/skills/gemini-imagegen/scripts/edit_image.py +137 -0
  532. package/skills/gemini-imagegen/scripts/gemini_images.py +256 -0
  533. package/skills/gemini-imagegen/scripts/generate_image.py +147 -0
  534. package/skills/gemini-imagegen/scripts/multi_turn_chat.py +223 -0
  535. package/skills/gemini-imagegen/scripts/test_error_handling.py +179 -0
  536. package/skills/git-worktree/SKILL.md +534 -0
  537. package/skills/git-worktree/scripts/git-repo-readiness-diag.sh +98 -0
  538. package/skills/git-worktree/scripts/worktree-manager.sh +4773 -0
  539. package/skills/git-worktree/test/create-from-origin-main.test.sh +116 -0
  540. package/skills/git-worktree/test/lease-protects-active.test.sh +1056 -0
  541. package/skills/git-worktree/test/no-repo-fail-loud.test.sh +88 -0
  542. package/skills/git-worktree/test/orphan-reaper-honest-count.test.sh +379 -0
  543. package/skills/git-worktree/test/reap-archive-persistence.test.sh +725 -0
  544. package/skills/git-worktree/test/stale-lock-sweep.test.sh +176 -0
  545. package/skills/go/SKILL.md +54 -0
  546. package/skills/growth/SKILL.md +164 -0
  547. package/skills/harvest-debt/SKILL.md +78 -0
  548. package/skills/harvest-debt/scripts/harvest-debt.sh +114 -0
  549. package/skills/heal-skill/SKILL.md +173 -0
  550. package/skills/help/SKILL.md +46 -0
  551. package/skills/incident/NOTICE +39 -0
  552. package/skills/incident/SKILL.md +395 -0
  553. package/skills/incident/scripts/dry-run.sh +448 -0
  554. package/skills/incident/scripts/redact-engine.py +412 -0
  555. package/skills/incident/scripts/redact-sentinel.sh +44 -0
  556. package/skills/incident/templates/pir.md +139 -0
  557. package/skills/incident/test/fixtures/dry-run-incident.json +26 -0
  558. package/skills/incident/test/fixtures/dry-run-secret-leak.json +26 -0
  559. package/skills/incident/test/fixtures/legacy-bash-scanner.sh +82 -0
  560. package/skills/incident/test/fixtures/positive-corpus.md +87 -0
  561. package/skills/incident/test/redact-sentinel.test.sh +1420 -0
  562. package/skills/invoice/SKILL.md +206 -0
  563. package/skills/kb-glossary/SKILL.md +71 -0
  564. package/skills/kb-glossary/references/glossary-format.md +111 -0
  565. package/skills/kb-glossary/references/rejected-request-register.md +115 -0
  566. package/skills/kb-search/SKILL.md +276 -0
  567. package/skills/kb-search/scripts/kb-search-cache.sh +123 -0
  568. package/skills/legal-audit/SKILL.md +161 -0
  569. package/skills/legal-generate/NOTICE +242 -0
  570. package/skills/legal-generate/SKILL.md +244 -0
  571. package/skills/legal-generate/references/templates/advisor-agreement/template.md +12 -0
  572. package/skills/legal-generate/references/templates/business-associate-agreement/template.md +112 -0
  573. package/skills/legal-generate/references/templates/cookie-notice/template.md +82 -0
  574. package/skills/legal-generate/references/templates/dpa-global/template.md +439 -0
  575. package/skills/legal-generate/references/templates/dpa-us/template.md +222 -0
  576. package/skills/legal-generate/references/templates/employee-offer-letter/template.md +75 -0
  577. package/skills/legal-generate/references/templates/master-services-agreement/template.md +252 -0
  578. package/skills/legal-generate/references/templates/mutual-nda/template.md +66 -0
  579. package/skills/legal-generate/references/templates/one-way-nda/template.md +38 -0
  580. package/skills/legal-generate/references/templates/privacy-policy-gdpr/template.md +427 -0
  581. package/skills/legal-generate/references/templates/privacy-policy-us/template.md +313 -0
  582. package/skills/legal-generate/references/templates/terms-of-use/template.md +75 -0
  583. package/skills/legal-generate/scripts/strip-vendor-credit.sh +96 -0
  584. package/skills/linear-fetch/SKILL.md +247 -0
  585. package/skills/linear-fetch/scripts/assert-no-linear-telemetry.sh +66 -0
  586. package/skills/linear-fetch/scripts/redact-linear-urls.sh +51 -0
  587. package/skills/linear-fetch/scripts/render-caller-template.sh +36 -0
  588. package/skills/linear-fetch/test/assert-no-linear-telemetry.test.sh +113 -0
  589. package/skills/linear-fetch/test/parity.test.sh +112 -0
  590. package/skills/linear-fetch/test/persist-safe-integration.test.sh +191 -0
  591. package/skills/linear-fetch/test/redact-linear-urls.test.sh +226 -0
  592. package/skills/merge-pr/SKILL.md +670 -0
  593. package/skills/model-launch-review/SKILL.md +255 -0
  594. package/skills/model-launch-review/scripts/audit-models.sh +501 -0
  595. package/skills/one-shot/SKILL.md +316 -0
  596. package/skills/one-shot/references/token-discipline.md +74 -0
  597. package/skills/operator-bootstrap/SKILL.md +412 -0
  598. package/skills/operator-bootstrap/template.sh +439 -0
  599. package/skills/operator-digest/SKILL.md +287 -0
  600. package/skills/operator-digest/assets/operator-digest.workflow.yml +175 -0
  601. package/skills/operator-digest/scripts/digest-scrub.sh +119 -0
  602. package/skills/operator-digest/scripts/provision-operator-digest-repo.sh +147 -0
  603. package/skills/operator-rephrase/SKILL.md +98 -0
  604. package/skills/pencil-setup/SKILL.md +201 -0
  605. package/skills/pencil-setup/scripts/check_deps.sh +556 -0
  606. package/skills/pencil-setup/scripts/copy_adapter.sh +80 -0
  607. package/skills/pencil-setup/scripts/package-lock.json +1172 -0
  608. package/skills/pencil-setup/scripts/package.json +14 -0
  609. package/skills/pencil-setup/scripts/pencil-error-enrichment.mjs +21 -0
  610. package/skills/pencil-setup/scripts/pencil-mcp-adapter.mjs +733 -0
  611. package/skills/pencil-setup/scripts/pencil-response-classify.mjs +38 -0
  612. package/skills/pencil-setup/scripts/pencil-save-gate.mjs +26 -0
  613. package/skills/pencil-setup/scripts/sanitize-filename.mjs +25 -0
  614. package/skills/plan/SKILL.md +1140 -0
  615. package/skills/plan/references/differential-migration-testing.md +185 -0
  616. package/skills/plan/references/plan-community-discovery.md +42 -0
  617. package/skills/plan/references/plan-founder-check.md +137 -0
  618. package/skills/plan/references/plan-functional-overlap.md +25 -0
  619. package/skills/plan/references/plan-host-fanout.md +51 -0
  620. package/skills/plan/references/plan-issue-templates.md +779 -0
  621. package/skills/plan/references/plan-network-outage-checklist.md +131 -0
  622. package/skills/plan/references/plan-scope-check.md +126 -0
  623. package/skills/plan/references/plan-sharp-edges.md +331 -0
  624. package/skills/plan/references/plan-signoff-lifecycle.md +12 -0
  625. package/skills/plan/references/webapp-cwv-observability.md +143 -0
  626. package/skills/plan-review/SKILL.md +91 -0
  627. package/skills/plan-review/lib/named-panel.mjs +58 -0
  628. package/skills/plan-review/workflows/plan-review.workflow.js +477 -0
  629. package/skills/postmerge/SKILL.md +642 -0
  630. package/skills/postmerge/references/deploy-status-debugging.md +141 -0
  631. package/skills/postmerge/references/graceful-degradation.md +20 -0
  632. package/skills/postmerge/references/sentry-error-count-delta.md +137 -0
  633. package/skills/preflight/SKILL.md +1553 -0
  634. package/skills/preflight/references/check-13-founder-check.md +286 -0
  635. package/skills/preflight/scripts/founder-check.py +1640 -0
  636. package/skills/preflight/scripts/parse-form-a.awk +107 -0
  637. package/skills/preflight/scripts/probe-verb-gate.sh +108 -0
  638. package/skills/product-roadmap/SKILL.md +357 -0
  639. package/skills/product-roadmap/scripts/roadmap-reconcile.sh +327 -0
  640. package/skills/provision-cloudflare/SKILL.md +67 -0
  641. package/skills/provision-cloudflare/scripts/provision-cloudflare.sh +271 -0
  642. package/skills/provision-doppler/SKILL.md +58 -0
  643. package/skills/provision-doppler/scripts/provision-doppler.sh +358 -0
  644. package/skills/provision-github/SKILL.md +59 -0
  645. package/skills/provision-github/scripts/provision-github.sh +300 -0
  646. package/skills/provision-hetzner/SKILL.md +76 -0
  647. package/skills/provision-hetzner/scripts/provision-hetzner.sh +262 -0
  648. package/skills/provision-hetzner/test/fixture/knowledge-base/legal/tenant-dpa-register.md +26 -0
  649. package/skills/provision-hetzner/test/fixture/provision-hetzner-dry-run.golden +34 -0
  650. package/skills/provision-hetzner/test/provision-hetzner-characterization.test.sh +227 -0
  651. package/skills/qa/SKILL.md +263 -0
  652. package/skills/qa/references/browser-preflight.md +22 -0
  653. package/skills/questionnaire-generate/SKILL.md +328 -0
  654. package/skills/questionnaire-generate/references/questionnaire.template +60 -0
  655. package/skills/rclone/SKILL.md +162 -0
  656. package/skills/rclone/scripts/check_setup.sh +63 -0
  657. package/skills/release-announce/SKILL.md +65 -0
  658. package/skills/release-docs/SKILL.md +92 -0
  659. package/skills/reproduce-bug/SKILL.md +358 -0
  660. package/skills/resolve-debt/SKILL.md +85 -0
  661. package/skills/resolve-debt/scripts/resolve-debt.py +584 -0
  662. package/skills/resolve-parallel/SKILL.md +45 -0
  663. package/skills/resolve-parallel/workflows/resolve-parallel.workflow.js +415 -0
  664. package/skills/resolve-pr-parallel/SKILL.md +68 -0
  665. package/skills/resolve-pr-parallel/workflows/resolve-pr-parallel.workflow.js +419 -0
  666. package/skills/resolve-todo-parallel/SKILL.md +57 -0
  667. package/skills/resolve-todo-parallel/workflows/resolve-todo-parallel.workflow.js +398 -0
  668. package/skills/review/SKILL.md +1620 -0
  669. package/skills/review/references/anti-slop-scanner-hook.md +40 -0
  670. package/skills/review/references/defect-classes-migrations.md +9 -0
  671. package/skills/review/references/generated-input-oracle-surfaces.md +15 -0
  672. package/skills/review/references/review-e2e-testing.md +116 -0
  673. package/skills/review/references/review-evidence-comment.md +36 -0
  674. package/skills/review/references/review-todo-structure.md +165 -0
  675. package/skills/review/references/risk-tier-and-fix-rounds.md +97 -0
  676. package/skills/review/references/semgrep-custom-rules.yaml +174 -0
  677. package/skills/review/references/ultrathink-phases.md +98 -0
  678. package/skills/review/references/wfs.md +6 -0
  679. package/skills/review/scripts/emit-review-trailer.sh +499 -0
  680. package/skills/review/scripts/ensure-semgrep.sh +99 -0
  681. package/skills/review/scripts/fix-round-seats.sh +197 -0
  682. package/skills/review/test/emit-review-trailer.test.sh +387 -0
  683. package/skills/review/test/ensure-semgrep.test.sh +111 -0
  684. package/skills/review/test/fix-round-seats.test.sh +237 -0
  685. package/skills/review/workflows/README.md +147 -0
  686. package/skills/review/workflows/review.workflow.js +667 -0
  687. package/skills/schedule/SKILL.md +796 -0
  688. package/skills/seo-aeo/SKILL.md +139 -0
  689. package/skills/seo-aeo/scripts/validate-csp.sh +233 -0
  690. package/skills/seo-aeo/scripts/validate-seo.sh +262 -0
  691. package/skills/ship/SKILL.md +3023 -0
  692. package/skills/ship/references/adr-ordinal-collision.md +47 -0
  693. package/skills/ship/references/affected-gate-contract.md +115 -0
  694. package/skills/ship/references/ci-run-diagnosis.md +29 -0
  695. package/skills/ship/references/ci-workflow-authoring.md +68 -0
  696. package/skills/ship/references/cleanup-merged-archival.md +39 -0
  697. package/skills/ship/references/counsel-review-clo-attestation.md +38 -0
  698. package/skills/ship/references/cto-ruling-armed-push.md +5 -0
  699. package/skills/ship/references/decision-challenges-render.md +71 -0
  700. package/skills/ship/references/delegated-act-authoring-form.md +7 -0
  701. package/skills/ship/references/detached-battery-verdict.md +13 -0
  702. package/skills/ship/references/epic-close-sweep.md +62 -0
  703. package/skills/ship/references/feature-tweet-draft.md +42 -0
  704. package/skills/ship/references/followthrough-issue-body-template.md +47 -0
  705. package/skills/ship/references/followthrough-stub-template.sh +92 -0
  706. package/skills/ship/references/merge-queue-dequeue.md +39 -0
  707. package/skills/ship/references/operator-holds.md +179 -0
  708. package/skills/ship/references/pipeline-tally-render.md +43 -0
  709. package/skills/ship/references/pr-overlap.md +153 -0
  710. package/skills/ship/references/queue-mode.md +7 -0
  711. package/skills/ship/references/ready-run-wait.md +36 -0
  712. package/skills/ship/references/red-on-main-quarantine.md +110 -0
  713. package/skills/ship/references/register-update-pr-pattern.md +88 -0
  714. package/skills/ship/references/settle-then-admin-merge.md +130 -0
  715. package/skills/ship/references/supabase-column-probe.md +13 -0
  716. package/skills/ship/scripts/auto-close-scan.sh +76 -0
  717. package/skills/ship/scripts/battery-owed.sh +403 -0
  718. package/skills/ship/scripts/hold-gate-eval.sh +410 -0
  719. package/skills/ship/scripts/net-issue-flow.sh +665 -0
  720. package/skills/ship/scripts/pr-overlap-preflight.sh +483 -0
  721. package/skills/ship/scripts/ship-pir-action-items-gate.sh +246 -0
  722. package/skills/ship/scripts/technical-ruling-gate.sh +444 -0
  723. package/skills/skill-creator/SKILL.md +299 -0
  724. package/skills/skill-creator/references/api-security.md +248 -0
  725. package/skills/skill-creator/references/authoring-levers.md +110 -0
  726. package/skills/skill-creator/references/be-clear-and-direct.md +587 -0
  727. package/skills/skill-creator/references/best-practices.md +431 -0
  728. package/skills/skill-creator/references/common-patterns.md +639 -0
  729. package/skills/skill-creator/references/core-principles.md +193 -0
  730. package/skills/skill-creator/references/executable-code.md +188 -0
  731. package/skills/skill-creator/references/iteration-and-testing.md +509 -0
  732. package/skills/skill-creator/references/official-spec.md +193 -0
  733. package/skills/skill-creator/references/recommended-structure.md +180 -0
  734. package/skills/skill-creator/references/skill-structure.md +396 -0
  735. package/skills/skill-creator/references/using-scripts.md +122 -0
  736. package/skills/skill-creator/references/using-templates.md +120 -0
  737. package/skills/skill-creator/references/workflows-and-validation.md +541 -0
  738. package/skills/skill-creator/scripts/init_skill.py +322 -0
  739. package/skills/skill-creator/scripts/package_skill.py +110 -0
  740. package/skills/skill-creator/scripts/quick_validate.py +64 -0
  741. package/skills/skill-creator/templates/router-skill.md +73 -0
  742. package/skills/skill-creator/templates/simple-skill.md +34 -0
  743. package/skills/skill-creator/workflows/add-reference.md +96 -0
  744. package/skills/skill-creator/workflows/add-script.md +104 -0
  745. package/skills/skill-creator/workflows/add-template.md +83 -0
  746. package/skills/skill-creator/workflows/add-workflow.md +128 -0
  747. package/skills/skill-creator/workflows/audit-skill.md +159 -0
  748. package/skills/skill-creator/workflows/create-domain-expertise-skill.md +623 -0
  749. package/skills/skill-creator/workflows/create-new-skill.md +207 -0
  750. package/skills/skill-creator/workflows/get-guidance.md +134 -0
  751. package/skills/skill-creator/workflows/upgrade-to-router.md +170 -0
  752. package/skills/skill-creator/workflows/verify-skill.md +226 -0
  753. package/skills/skill-security-scan/SKILL.md +145 -0
  754. package/skills/skill-security-scan/references/disclaimer.md +21 -0
  755. package/skills/skill-security-scan/references/first-party-allowlist.yaml +38 -0
  756. package/skills/skill-security-scan/references/override-artifact-schema.json +68 -0
  757. package/skills/skill-security-scan/references/override-mechanism.md +171 -0
  758. package/skills/skill-security-scan/references/redirect-domains.yaml +27 -0
  759. package/skills/skill-security-scan/references/regex-patterns.md +136 -0
  760. package/skills/skill-security-scan/references/rules/code-exec.yaml +70 -0
  761. package/skills/skill-security-scan/references/rules/filesystem-boundary.yaml +29 -0
  762. package/skills/skill-security-scan/references/rules/manifest.yaml +44 -0
  763. package/skills/skill-security-scan/references/rules/supply-chain.yaml +36 -0
  764. package/skills/skill-security-scan/references/scan-meta-schema.json +63 -0
  765. package/skills/skill-security-scan/references/test-fixtures/clean-soleur-style.skill.md +23 -0
  766. package/skills/skill-security-scan/references/test-fixtures/clean-third-party.skill.md +26 -0
  767. package/skills/skill-security-scan/references/test-fixtures/malicious-codeexec.skill.md +23 -0
  768. package/skills/skill-security-scan/references/test-fixtures/malicious-curl-pipe-bash.skill.md +69 -0
  769. package/skills/skill-security-scan/references/test-fixtures/malicious-prompt-injection.skill.md +17 -0
  770. package/skills/skill-security-scan/references/test-fixtures/malicious-telemetry-beacon.skill.md +23 -0
  771. package/skills/skill-security-scan/references/typosquat-targets.yaml +65 -0
  772. package/skills/skill-security-scan/scripts/check-codeexec.sh +41 -0
  773. package/skills/skill-security-scan/scripts/check-filesystem-boundary.sh +19 -0
  774. package/skills/skill-security-scan/scripts/check-prompt-injection.sh +95 -0
  775. package/skills/skill-security-scan/scripts/check-supply-chain.sh +219 -0
  776. package/skills/skill-security-scan/scripts/check-telemetry-surface.sh +126 -0
  777. package/skills/skill-security-scan/scripts/lib.sh +197 -0
  778. package/skills/skill-security-scan/scripts/parse-override.sh +231 -0
  779. package/skills/skill-security-scan/scripts/run-scan.sh +342 -0
  780. package/skills/skill-security-scan/scripts/run-self-test.sh +95 -0
  781. package/skills/skill-security-scan/test/argv-ceiling.test.sh +180 -0
  782. package/skills/skill-security-scan/test/meta-dir-reap.test.sh +411 -0
  783. package/skills/skill-security-scan/test/parse-override.test.sh +607 -0
  784. package/skills/skill-security-scan/test/redact-pii-ghs-shape.test.sh +251 -0
  785. package/skills/social-distribute/SKILL.md +485 -0
  786. package/skills/spec-templates/SKILL.md +274 -0
  787. package/skills/sync/SKILL.md +49 -0
  788. package/skills/test-browser/SKILL.md +464 -0
  789. package/skills/test-browser/references/feature-map.md +161 -0
  790. package/skills/test-fix-loop/SKILL.md +159 -0
  791. package/skills/test-fix-loop/references/determinism-checklist.md +154 -0
  792. package/skills/triage/SKILL.md +402 -0
  793. package/skills/trigger-cron/SKILL.md +136 -0
  794. package/skills/trigger-cron/scripts/trigger.sh +198 -0
  795. package/skills/user-set-role/SKILL.md +147 -0
  796. package/skills/user-set-role/scripts/set-role.sh +218 -0
  797. package/skills/user-story-writer/SKILL.md +77 -0
  798. package/skills/ux-audit/SKILL.md +251 -0
  799. package/skills/ux-audit/references/finding.schema.json +62 -0
  800. package/skills/ux-audit/references/route-list.yaml +95 -0
  801. package/skills/ux-audit/scripts/bot-fixture.ts +270 -0
  802. package/skills/ux-audit/scripts/bot-signin.ts +135 -0
  803. package/skills/ux-audit/scripts/dedup-hash.ts +46 -0
  804. package/skills/verification-scaffold/SKILL.md +73 -0
  805. package/skills/verification-scaffold/references/gitleaks.toml.template +13 -0
  806. package/skills/verification-scaffold/references/guardrail-audit.md +156 -0
  807. package/skills/verification-scaffold/references/guards/block-stash-hook.sh.template +72 -0
  808. package/skills/verification-scaffold/references/guards/commit-on-main-hook.sh.template +82 -0
  809. package/skills/verification-scaffold/references/guards/orphan-test-check.sh.template +102 -0
  810. package/skills/verification-scaffold/references/guards/precommit-guard.sh.template +115 -0
  811. package/skills/verification-scaffold/references/guards/secret-scan-hook.sh.template +176 -0
  812. package/skills/verification-scaffold/references/guards/verification-gates.yml.template +49 -0
  813. package/skills/verification-scaffold/references/guards/wrapper-boundary.sh.template +47 -0
  814. package/skills/verification-scaffold/references/guards.tsv +21 -0
  815. package/skills/verification-scaffold/references/verification-readme.template +55 -0
  816. package/skills/verification-scaffold/scripts/verification-scaffold.sh +785 -0
  817. package/skills/verification-scaffold/test/bite-proof.test.sh +159 -0
  818. package/skills/verification-scaffold/test/generator.test.sh +319 -0
  819. package/skills/verification-scaffold/test/manifest.test.sh +144 -0
  820. package/skills/work/SKILL.md +1480 -0
  821. package/skills/work/references/end-of-work-resume.md +7 -0
  822. package/skills/work/references/hook-test-main-cwd.md +24 -0
  823. package/skills/work/references/key-principles.md +83 -0
  824. package/skills/work/references/property-testing.md +122 -0
  825. package/skills/work/references/sql-security-definer-rpc-scaffold.sql +78 -0
  826. package/skills/work/references/work-agent-teams.md +97 -0
  827. package/skills/work/references/work-lifecycle-parallel.md +147 -0
  828. package/skills/work/references/work-lockfile-bumps.md +97 -0
  829. package/skills/work/references/work-scratch-sandboxes.md +212 -0
  830. package/skills/work/references/work-subagent-fanout.md +61 -0
  831. package/skills/work/references/work-test-harness-sharp-edges.md +73 -0
  832. 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