@openlife/cli 1.8.3 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/.catalog/agents/test-agent/AGENT.md +1 -1
  2. package/.catalog/mcps/test-mcp/mcp.json +1 -1
  3. package/.catalog/skills/sample-from-url/IMPORTED_REFERENCE.md +2 -2
  4. package/.catalog/skills/test-skill/REFERENCE.md +1 -1
  5. package/.catalog/squads/00-governance-advisory-board/workflows/wf-board-meeting.yaml +25 -0
  6. package/.catalog/squads/00-governance-advisory-board/workflows/wf-decision-framework.yaml +25 -0
  7. package/.catalog/squads/00-governance-c-level-squad/workflows/wf-board-presentation.yaml +25 -0
  8. package/.catalog/squads/00-governance-c-level-squad/workflows/wf-strategic-planning.yaml +25 -0
  9. package/.catalog/squads/00-governance-project-ops-squad/workflows/mission-to-project.yaml +25 -0
  10. package/.catalog/squads/00-governance-project-ops-squad/workflows/sprint-planning.yaml +25 -0
  11. package/.catalog/squads/00-governance-project-ops-squad/workflows/weekly-review.yaml +25 -0
  12. package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-analysis-flow.yaml +25 -0
  13. package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-execution-flow.yaml +25 -0
  14. package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-planning-flow.yaml +25 -0
  15. package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-resume-flow.yaml +25 -0
  16. package/.catalog/squads/02-product-growth-brand-squad/workflows/wf-brand-creation.yaml +25 -0
  17. package/.catalog/squads/02-product-growth-brand-squad/workflows/wf-rebrand.yaml +25 -0
  18. package/.catalog/squads/02-product-growth-copy-squad/workflows/wf-copy-review-cycle.yaml +25 -0
  19. package/.catalog/squads/02-product-growth-copy-squad/workflows/wf-full-copy-project.yaml +25 -0
  20. package/.catalog/squads/02-product-growth-design-squad/workflows/wf-design-system-creation.yaml +25 -0
  21. package/.catalog/squads/02-product-growth-design-squad/workflows/wf-feature-design.yaml +25 -0
  22. package/.catalog/squads/02-product-growth-hormozi-squad/workflows/wf-business-turnaround.yaml +25 -0
  23. package/.catalog/squads/02-product-growth-hormozi-squad/workflows/wf-offer-creation.yaml +25 -0
  24. package/.catalog/squads/02-product-growth-movement/workflows/wf-movement-launch.yaml +25 -0
  25. package/.catalog/squads/02-product-growth-saas-onboarding-activator/workflows/full-onboarding-activation-workflow.yaml +25 -0
  26. package/.catalog/squads/02-product-growth-saas-onboarding-activator/workflows/quick-engagement-boost-workflow.yaml +25 -0
  27. package/.catalog/squads/02-product-growth-sales-squad/workflows/followup-sequence.yaml +25 -0
  28. package/.catalog/squads/02-product-growth-sales-squad/workflows/full-sales-cycle.yaml +25 -0
  29. package/.catalog/squads/02-product-growth-sales-squad/workflows/proposal-flow.yaml +25 -0
  30. package/.catalog/squads/02-product-growth-storytelling/workflows/wf-brand-narrative.yaml +25 -0
  31. package/.catalog/squads/02-product-growth-storytelling/workflows/wf-story-development.yaml +25 -0
  32. package/.catalog/squads/02-product-growth-traffic-masters/workflows/wf-account-audit.yaml +25 -0
  33. package/.catalog/squads/02-product-growth-traffic-masters/workflows/wf-campaign-launch.yaml +25 -0
  34. package/.catalog/squads/03-engineering-quality-automated-code-review-squad/workflows/full-code-review-workflow.yaml +25 -0
  35. package/.catalog/squads/03-engineering-quality-automated-code-review-squad/workflows/quick-security-check-workflow.yaml +25 -0
  36. package/.catalog/squads/04-data-security-cybersecurity/workflows/wf-incident-response.yaml +25 -0
  37. package/.catalog/squads/04-data-security-cybersecurity/workflows/wf-pentest-engagement.yaml +25 -0
  38. package/.catalog/squads/04-data-security-data-quality-guardian/workflows/full-data-quality-audit-workflow.yaml +25 -0
  39. package/.catalog/squads/04-data-security-data-quality-guardian/workflows/quick-data-check-workflow.yaml +25 -0
  40. package/.catalog/squads/04-data-security-data-squad/workflows/wf-analytics-setup.yaml +25 -0
  41. package/.catalog/squads/04-data-security-data-squad/workflows/wf-growth-sprint.yaml +25 -0
  42. package/.catalog/squads/04-data-security-incident-response-squad/workflows/full-incident-response-workflow.yaml +25 -0
  43. package/.catalog/squads/04-data-security-incident-response-squad/workflows/rapid-triage-workflow.yaml +25 -0
  44. package/.catalog/squads/04-data-security-soc-alert-triage/workflows/full-alert-triage-workflow.yaml +25 -0
  45. package/.catalog/squads/04-data-security-soc-alert-triage/workflows/rapid-classification-workflow.yaml +25 -0
  46. package/.catalog/squads/05-domain-specialists-adaptive-tutor-k12/workflows/full-tutoring-cycle-workflow.yaml +25 -0
  47. package/.catalog/squads/05-domain-specialists-adaptive-tutor-k12/workflows/quick-practice-session-workflow.yaml +25 -0
  48. package/.catalog/squads/05-domain-specialists-ambient-clinical-scribe/workflows/full-documentation-workflow.yaml +25 -0
  49. package/.catalog/squads/05-domain-specialists-ambient-clinical-scribe/workflows/quick-note-workflow.yaml +25 -0
  50. package/.catalog/squads/05-domain-specialists-contract-review-squad/workflows/full-contract-review-workflow.yaml +25 -0
  51. package/.catalog/squads/05-domain-specialists-contract-review-squad/workflows/quick-risk-assessment-workflow.yaml +25 -0
  52. package/.catalog/squads/05-domain-specialists-crypto-token-forge/workflows/full-token-launch-workflow.yaml +25 -0
  53. package/.catalog/squads/05-domain-specialists-crypto-token-forge/workflows/memecoin-express-workflow.yaml +25 -0
  54. package/.catalog/squads/05-domain-specialists-crypto-token-forge/workflows/utility-token-launch-workflow.yaml +25 -0
  55. package/.catalog/squads/05-domain-specialists-resume-screener-squad/workflows/full-resume-screening-workflow.yaml +25 -0
  56. package/.catalog/squads/05-domain-specialists-resume-screener-squad/workflows/quick-skills-match-workflow.yaml +25 -0
  57. package/.catalog/squads/test-squad/SQUAD.md +1 -1
  58. package/.openlife/method/agents/atlas.md +102 -0
  59. package/.openlife/method/agents/builder.md +92 -0
  60. package/.openlife/method/agents/conductor.md +93 -0
  61. package/.openlife/method/agents/forge.md +96 -0
  62. package/.openlife/method/agents/genesis.md +115 -0
  63. package/.openlife/method/agents/lyra.md +85 -0
  64. package/.openlife/method/agents/maestro.md +92 -0
  65. package/.openlife/method/agents/mesh.md +101 -0
  66. package/.openlife/method/agents/prism.md +85 -0
  67. package/.openlife/method/agents/sentinel.md +115 -0
  68. package/.openlife/method/agents/steward.md +93 -0
  69. package/.openlife/method/agents/vortex.md +94 -0
  70. package/dist/cli/CommandFlowRunner.js +167 -0
  71. package/dist/cli/install/Phases.js +43 -0
  72. package/dist/index.js +118 -0
  73. package/dist/orchestrator/ProjectMetadata.js +183 -0
  74. package/dist/test_flow_run_cli.js +183 -0
  75. package/dist/test_host_uninstaller.js +12 -2
  76. package/dist/test_openlife_method_inventory.js +211 -0
  77. package/dist/test_workflow_e2e.js +10 -3
  78. package/dist-templates/claude-code/agents/openlife-atlas.md +12 -44
  79. package/dist-templates/claude-code/agents/openlife-builder.md +20 -0
  80. package/dist-templates/claude-code/agents/openlife-conductor.md +20 -0
  81. package/dist-templates/claude-code/agents/openlife-forge.md +12 -34
  82. package/dist-templates/claude-code/agents/openlife-genesis.md +12 -51
  83. package/dist-templates/claude-code/agents/openlife-lyra.md +12 -32
  84. package/dist-templates/claude-code/agents/openlife-maestro.md +27 -41
  85. package/dist-templates/claude-code/agents/openlife-mesh.md +20 -0
  86. package/dist-templates/claude-code/agents/openlife-prism.md +20 -0
  87. package/dist-templates/claude-code/agents/openlife-sentinel.md +20 -0
  88. package/dist-templates/claude-code/agents/openlife-steward.md +20 -0
  89. package/dist-templates/claude-code/agents/openlife-vortex.md +20 -0
  90. package/dist-templates/claude-code/commands/openlife/agents/atlas.md +28 -0
  91. package/dist-templates/claude-code/commands/openlife/agents/builder.md +28 -0
  92. package/dist-templates/claude-code/commands/openlife/agents/conductor.md +28 -0
  93. package/dist-templates/claude-code/commands/openlife/agents/forge.md +28 -0
  94. package/dist-templates/claude-code/commands/openlife/agents/genesis.md +28 -0
  95. package/dist-templates/claude-code/commands/openlife/agents/lyra.md +28 -0
  96. package/dist-templates/claude-code/commands/openlife/agents/maestro.md +28 -0
  97. package/dist-templates/claude-code/commands/openlife/agents/mesh.md +28 -0
  98. package/dist-templates/claude-code/commands/openlife/agents/prism.md +28 -0
  99. package/dist-templates/claude-code/commands/openlife/agents/sentinel.md +28 -0
  100. package/dist-templates/claude-code/commands/openlife/agents/steward.md +28 -0
  101. package/dist-templates/claude-code/commands/openlife/agents/vortex.md +28 -0
  102. package/dist-templates/claude-code/commands/openlife/ask.md +32 -9
  103. package/dist-templates/claude-code/commands/openlife/audit.md +43 -0
  104. package/dist-templates/claude-code/commands/openlife/doctor.md +9 -14
  105. package/dist-templates/claude-code/commands/openlife/dream.md +28 -13
  106. package/dist-templates/claude-code/commands/openlife/explore.md +32 -0
  107. package/dist-templates/claude-code/commands/openlife/flow/brownfield-discovery.md +38 -0
  108. package/dist-templates/claude-code/commands/openlife/flow/brownfield-fullstack.md +38 -0
  109. package/dist-templates/claude-code/commands/openlife/flow/brownfield-service.md +38 -0
  110. package/dist-templates/claude-code/commands/openlife/flow/brownfield-ui.md +38 -0
  111. package/dist-templates/claude-code/commands/openlife/flow/epic.md +38 -0
  112. package/dist-templates/claude-code/commands/openlife/flow/greenfield-fullstack.md +38 -0
  113. package/dist-templates/claude-code/commands/openlife/flow/greenfield-service.md +38 -0
  114. package/dist-templates/claude-code/commands/openlife/flow/greenfield-ui.md +38 -0
  115. package/dist-templates/claude-code/commands/openlife/flow/qa-loop.md +38 -0
  116. package/dist-templates/claude-code/commands/openlife/flow/release.md +38 -0
  117. package/dist-templates/claude-code/commands/openlife/flow/spec-pipeline.md +38 -0
  118. package/dist-templates/claude-code/commands/openlife/flow/story-cycle.md +38 -0
  119. package/dist-templates/claude-code/commands/openlife/health.md +37 -0
  120. package/dist-templates/claude-code/commands/openlife/plan.md +38 -0
  121. package/dist-templates/claude-code/commands/openlife/review.md +34 -0
  122. package/dist-templates/claude-code/commands/openlife/ship.md +35 -0
  123. package/dist-templates/claude-code/commands/openlife/start.md +38 -0
  124. package/dist-templates/claude-code/commands/openlife/status.md +8 -10
  125. package/dist-templates/claude-code/commands/openlife/story.md +34 -0
  126. package/dist-templates/codex/agents/openlife-atlas.md +12 -44
  127. package/dist-templates/codex/agents/openlife-builder.md +20 -0
  128. package/dist-templates/codex/agents/openlife-conductor.md +20 -0
  129. package/dist-templates/codex/agents/openlife-forge.md +12 -34
  130. package/dist-templates/codex/agents/openlife-genesis.md +12 -51
  131. package/dist-templates/codex/agents/openlife-lyra.md +12 -32
  132. package/dist-templates/codex/agents/openlife-maestro.md +27 -41
  133. package/dist-templates/codex/agents/openlife-mesh.md +20 -0
  134. package/dist-templates/codex/agents/openlife-prism.md +20 -0
  135. package/dist-templates/codex/agents/openlife-sentinel.md +20 -0
  136. package/dist-templates/codex/agents/openlife-steward.md +20 -0
  137. package/dist-templates/codex/agents/openlife-vortex.md +20 -0
  138. package/dist-templates/codex/commands/openlife/agents/atlas.md +28 -0
  139. package/dist-templates/codex/commands/openlife/agents/builder.md +28 -0
  140. package/dist-templates/codex/commands/openlife/agents/conductor.md +28 -0
  141. package/dist-templates/codex/commands/openlife/agents/forge.md +28 -0
  142. package/dist-templates/codex/commands/openlife/agents/genesis.md +28 -0
  143. package/dist-templates/codex/commands/openlife/agents/lyra.md +28 -0
  144. package/dist-templates/codex/commands/openlife/agents/maestro.md +28 -0
  145. package/dist-templates/codex/commands/openlife/agents/mesh.md +28 -0
  146. package/dist-templates/codex/commands/openlife/agents/prism.md +28 -0
  147. package/dist-templates/codex/commands/openlife/agents/sentinel.md +28 -0
  148. package/dist-templates/codex/commands/openlife/agents/steward.md +28 -0
  149. package/dist-templates/codex/commands/openlife/agents/vortex.md +28 -0
  150. package/dist-templates/codex/commands/openlife/ask.md +32 -9
  151. package/dist-templates/codex/commands/openlife/audit.md +43 -0
  152. package/dist-templates/codex/commands/openlife/doctor.md +9 -14
  153. package/dist-templates/codex/commands/openlife/dream.md +28 -13
  154. package/dist-templates/codex/commands/openlife/explore.md +32 -0
  155. package/dist-templates/codex/commands/openlife/flow/brownfield-discovery.md +38 -0
  156. package/dist-templates/codex/commands/openlife/flow/brownfield-fullstack.md +38 -0
  157. package/dist-templates/codex/commands/openlife/flow/brownfield-service.md +38 -0
  158. package/dist-templates/codex/commands/openlife/flow/brownfield-ui.md +38 -0
  159. package/dist-templates/codex/commands/openlife/flow/epic.md +38 -0
  160. package/dist-templates/codex/commands/openlife/flow/greenfield-fullstack.md +38 -0
  161. package/dist-templates/codex/commands/openlife/flow/greenfield-service.md +38 -0
  162. package/dist-templates/codex/commands/openlife/flow/greenfield-ui.md +38 -0
  163. package/dist-templates/codex/commands/openlife/flow/qa-loop.md +38 -0
  164. package/dist-templates/codex/commands/openlife/flow/release.md +38 -0
  165. package/dist-templates/codex/commands/openlife/flow/spec-pipeline.md +38 -0
  166. package/dist-templates/codex/commands/openlife/flow/story-cycle.md +38 -0
  167. package/dist-templates/codex/commands/openlife/health.md +37 -0
  168. package/dist-templates/codex/commands/openlife/plan.md +38 -0
  169. package/dist-templates/codex/commands/openlife/review.md +34 -0
  170. package/dist-templates/codex/commands/openlife/ship.md +35 -0
  171. package/dist-templates/codex/commands/openlife/start.md +38 -0
  172. package/dist-templates/codex/commands/openlife/status.md +8 -10
  173. package/dist-templates/codex/commands/openlife/story.md +34 -0
  174. package/dist-templates/gemini-cli/agents/openlife-atlas.md +12 -44
  175. package/dist-templates/gemini-cli/agents/openlife-builder.md +20 -0
  176. package/dist-templates/gemini-cli/agents/openlife-conductor.md +20 -0
  177. package/dist-templates/gemini-cli/agents/openlife-forge.md +12 -34
  178. package/dist-templates/gemini-cli/agents/openlife-genesis.md +12 -51
  179. package/dist-templates/gemini-cli/agents/openlife-lyra.md +12 -32
  180. package/dist-templates/gemini-cli/agents/openlife-maestro.md +27 -41
  181. package/dist-templates/gemini-cli/agents/openlife-mesh.md +20 -0
  182. package/dist-templates/gemini-cli/agents/openlife-prism.md +20 -0
  183. package/dist-templates/gemini-cli/agents/openlife-sentinel.md +20 -0
  184. package/dist-templates/gemini-cli/agents/openlife-steward.md +20 -0
  185. package/dist-templates/gemini-cli/agents/openlife-vortex.md +20 -0
  186. package/dist-templates/gemini-cli/commands/openlife/agents/atlas.md +28 -0
  187. package/dist-templates/gemini-cli/commands/openlife/agents/builder.md +28 -0
  188. package/dist-templates/gemini-cli/commands/openlife/agents/conductor.md +28 -0
  189. package/dist-templates/gemini-cli/commands/openlife/agents/forge.md +28 -0
  190. package/dist-templates/gemini-cli/commands/openlife/agents/genesis.md +28 -0
  191. package/dist-templates/gemini-cli/commands/openlife/agents/lyra.md +28 -0
  192. package/dist-templates/gemini-cli/commands/openlife/agents/maestro.md +28 -0
  193. package/dist-templates/gemini-cli/commands/openlife/agents/mesh.md +28 -0
  194. package/dist-templates/gemini-cli/commands/openlife/agents/prism.md +28 -0
  195. package/dist-templates/gemini-cli/commands/openlife/agents/sentinel.md +28 -0
  196. package/dist-templates/gemini-cli/commands/openlife/agents/steward.md +28 -0
  197. package/dist-templates/gemini-cli/commands/openlife/agents/vortex.md +28 -0
  198. package/dist-templates/gemini-cli/commands/openlife/ask.md +32 -9
  199. package/dist-templates/gemini-cli/commands/openlife/audit.md +43 -0
  200. package/dist-templates/gemini-cli/commands/openlife/doctor.md +9 -14
  201. package/dist-templates/gemini-cli/commands/openlife/dream.md +28 -13
  202. package/dist-templates/gemini-cli/commands/openlife/explore.md +32 -0
  203. package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-discovery.md +38 -0
  204. package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-fullstack.md +38 -0
  205. package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-service.md +38 -0
  206. package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-ui.md +38 -0
  207. package/dist-templates/gemini-cli/commands/openlife/flow/epic.md +38 -0
  208. package/dist-templates/gemini-cli/commands/openlife/flow/greenfield-fullstack.md +38 -0
  209. package/dist-templates/gemini-cli/commands/openlife/flow/greenfield-service.md +38 -0
  210. package/dist-templates/gemini-cli/commands/openlife/flow/greenfield-ui.md +38 -0
  211. package/dist-templates/gemini-cli/commands/openlife/flow/qa-loop.md +38 -0
  212. package/dist-templates/gemini-cli/commands/openlife/flow/release.md +38 -0
  213. package/dist-templates/gemini-cli/commands/openlife/flow/spec-pipeline.md +38 -0
  214. package/dist-templates/gemini-cli/commands/openlife/flow/story-cycle.md +38 -0
  215. package/dist-templates/gemini-cli/commands/openlife/health.md +37 -0
  216. package/dist-templates/gemini-cli/commands/openlife/plan.md +38 -0
  217. package/dist-templates/gemini-cli/commands/openlife/review.md +34 -0
  218. package/dist-templates/gemini-cli/commands/openlife/ship.md +35 -0
  219. package/dist-templates/gemini-cli/commands/openlife/start.md +38 -0
  220. package/dist-templates/gemini-cli/commands/openlife/status.md +8 -10
  221. package/dist-templates/gemini-cli/commands/openlife/story.md +34 -0
  222. package/dist-templates/workflows/brownfield-fullstack.yaml +131 -0
  223. package/dist-templates/workflows/brownfield-service.yaml +111 -0
  224. package/dist-templates/workflows/brownfield-ui.yaml +115 -0
  225. package/dist-templates/workflows/continuous-deployment.yaml +139 -0
  226. package/dist-templates/workflows/epic-orchestration.yaml +101 -0
  227. package/dist-templates/workflows/greenfield-service.yaml +154 -0
  228. package/dist-templates/workflows/greenfield-ui.yaml +140 -0
  229. package/dist-templates/workflows/spec-pipeline.yaml +135 -0
  230. package/package.json +5 -2
  231. package/scripts/generate-slash-commands.js +395 -0
  232. package/scripts/generate-squad-workflow-stubs.js +144 -0
@@ -0,0 +1,395 @@
1
+ #!/usr/bin/env node
2
+ // scripts/generate-slash-commands.js
3
+ //
4
+ // Host-Native generator (v1.10.0+).
5
+ // Produces files under dist-templates/<host>/commands/openlife/{,agents/,flow/}
6
+ // for hosts: claude-code, gemini-cli, codex.
7
+ //
8
+ // Architecture (v1.10.0):
9
+ // LLM-reasoning commands respond DIRECTLY using the host's LLM (Claude in
10
+ // Claude Code, Gemini in Gemini CLI, etc.) by reading the OpenLife method
11
+ // catalog at `.openlife/method/` for persona/workflow context. They do NOT
12
+ // shell out to `openlife <verb>` (which would route to an external Brain
13
+ // chain and require API keys).
14
+ //
15
+ // Runtime-state commands (doctor, status, project-mode get) still shell
16
+ // out — they query real local state, not LLM reasoning.
17
+ //
18
+ // External Brain mode is opt-in via the `--external` flag on the command
19
+ // or `OPENLIFE_USE_EXTERNAL_BRAIN=true` env var — useful for headless / CI
20
+ // contexts or when the user explicitly wants the configured model chain.
21
+ //
22
+ // Idempotent: re-running overwrites with the canonical content.
23
+
24
+ const fs = require('fs');
25
+ const path = require('path');
26
+
27
+ const HOSTS = ['claude-code', 'gemini-cli', 'codex'];
28
+ const REPO_ROOT = path.resolve(__dirname, '..');
29
+
30
+ // ─── Command catalog ────────────────────────────────────────────────────
31
+
32
+ const TOP_LEVEL = [
33
+ // ── LLM-reasoning: Claude responds directly, no shellout ──
34
+ {
35
+ name: 'ask',
36
+ mode: 'host-native',
37
+ persona: 'lyra',
38
+ description: 'Ask OpenLife — the host LLM answers directly using the OpenLife method context (no external API key required)',
39
+ argumentHint: '<question>',
40
+ instruction: `Answer the user's question directly using your own reasoning. You ARE the OpenLife Brain when invoked through a host CLI.
41
+
42
+ Optional context (read only when relevant to the question):
43
+ - \`.openlife/method/agents/lyra.md\` — research / synthesis persona to adopt when the question is research-shaped
44
+ - \`.openlife/project.json\` — current project mode (greenfield/brownfield)
45
+ - \`.catalog/\` — user's agents, squads, skills, capabilities
46
+ - \`dist-templates/workflows/\` — bundled method workflows
47
+
48
+ If the question is open-ended or asks for OpenLife status, prefer answering from this conversation's existing context rather than reading files speculatively. If the user explicitly wants the external model chain (e.g., for batch / cron / cost-tracking reasons), they can invoke \`openlife ask "..."\` directly in a terminal or pass \`--external\` to this command.`,
49
+ },
50
+ {
51
+ name: 'doctor',
52
+ mode: 'runtime',
53
+ description: 'Run OpenLife health checks (API keys, model chain, runtime catalogs, daemon state)',
54
+ instruction: 'Run `openlife system doctor` and walk the user through results.\n\nFor each failed check: quote the line, explain in 1 sentence what it verifies, suggest the concrete fix.',
55
+ },
56
+ {
57
+ name: 'status',
58
+ mode: 'runtime',
59
+ description: 'Show OpenLife system status — installed profile, host, catalog counts, daemon state',
60
+ instruction: 'Run `openlife status --json` and present a tight summary of: active profile, host CLIs installed, catalog counts (agents/squads/skills), daemon heartbeat freshness, telegram allowed user.',
61
+ },
62
+ {
63
+ name: 'dream',
64
+ mode: 'host-native',
65
+ persona: 'lyra',
66
+ description: 'Dream Organizer — surface ideas, pending stories, and prioritization from accumulated context (host LLM answers directly)',
67
+ instruction: `Run the OpenLife Dream Organizer using your own reasoning, not an external model.
68
+
69
+ 1. Read recent context from this conversation + any planning files the user has open
70
+ 2. Optionally read \`.catalog/\` for project-specific ideas already captured
71
+ 3. Surface unprioritized ideas, pending stories, and recommendations grouped by theme
72
+ 4. Be opinionated about priority order — don't return a flat list
73
+
74
+ If the user wants the external model chain for richer ideation: \`openlife dream "..."\` in a terminal.`,
75
+ },
76
+ {
77
+ name: 'start',
78
+ mode: 'host-native',
79
+ description: 'Bootstrap or resume work — reads .openlife/project.json mode and routes to greenfield or brownfield flow',
80
+ instruction: `Detect the project mode and route to the right workflow.
81
+
82
+ 1. Read \`.openlife/project.json\` if it exists. Use its \`mode\` field (\`greenfield\` / \`brownfield\` / \`not-applicable\`).
83
+ 2. If missing, ask the user via AskUserQuestion: "Is this a brand new project (greenfield) or existing codebase (brownfield)?"
84
+ 3. Based on the answer, decide and announce the recommended workflow:
85
+ - greenfield + fullstack → run \`/openlife:flow:greenfield-fullstack\`
86
+ - greenfield + service → run \`/openlife:flow:greenfield-service\`
87
+ - greenfield + ui → run \`/openlife:flow:greenfield-ui\`
88
+ - brownfield + first time → run \`/openlife:flow:brownfield-discovery\`
89
+ - brownfield + already discovered → ask sub-mode (fullstack/service/ui)
90
+ 4. If mode was just set, persist via \`openlife project-mode set <mode>\`.`,
91
+ },
92
+ {
93
+ name: 'plan',
94
+ mode: 'host-native',
95
+ persona: 'genesis',
96
+ description: 'Run the spec pipeline (gather → assess → research → write → critique → plan) — host LLM orchestrates the 6 phases',
97
+ instruction: `Orchestrate the spec-pipeline workflow YOURSELF, phase by phase. You play multiple personas inline.
98
+
99
+ 1. Read \`dist-templates/workflows/spec-pipeline.yaml\` to understand the phases
100
+ 2. Phase 1 — Gather: become @openlife-genesis (read \`.openlife/method/agents/genesis.md\`) and elicit requirements from the user via AskUserQuestion
101
+ 3. Phase 2 — Assess: become @openlife-atlas, score the 5 complexity dimensions
102
+ 4. Phase 3 — Research (skip if SIMPLE complexity): become @openlife-lyra, surface unknowns
103
+ 5. Phase 4 — Write: become @openlife-genesis again, draft spec.md
104
+ 6. Phase 5 — Critique: become @openlife-sentinel, return verdict (APPROVED / NEEDS_REVISION / BLOCKED)
105
+ 7. Phase 6 — Plan: become @openlife-atlas, generate implementation.yaml
106
+
107
+ Each phase ends with the user explicitly OK'ing before the next.`,
108
+ },
109
+ {
110
+ name: 'story',
111
+ mode: 'host-native',
112
+ description: 'Create the next story (Conductor) or validate a draft (Steward) — host LLM acts as the right persona',
113
+ instruction: `Determine intent from \`$ARGUMENTS\`:
114
+
115
+ - If the user wants to CREATE a story → read \`.openlife/method/agents/conductor.md\`, become Conductor, run \`*create-next-story\`. Apply the story template (frontmatter, title, description, AC, scope, deps, complexity, business value, risks, DoD).
116
+ - If the user wants to VALIDATE a draft → read \`.openlife/method/agents/steward.md\`, become Steward, run \`*validate-story\` with the 10-point checklist. Verdict: GO (≥7/10) or NO-GO (with required fixes).
117
+ - If unclear, ask via AskUserQuestion which action to take.
118
+
119
+ You play the persona directly — no shellout.`,
120
+ },
121
+ {
122
+ name: 'review',
123
+ mode: 'host-native',
124
+ persona: 'sentinel',
125
+ description: 'Run the QA gate on a story — host LLM acts as Sentinel and applies 7 quality checks',
126
+ instruction: `Read \`.openlife/method/agents/sentinel.md\`, become Sentinel, and run \`*qa-gate\` on the target (story id or file path from \`$ARGUMENTS\`).
127
+
128
+ Apply the 7 checks: code review, unit tests, AC coverage, no regressions, performance, security (OWASP-grade), documentation.
129
+
130
+ Return verdict: PASS / CONCERNS / FAIL / WAIVED with structured findings (severity + category + file:line + recommendation per finding).
131
+
132
+ If verdict is FAIL with HIGH/CRITICAL issues, suggest \`/openlife:agents:builder\` for the fix-loop iteration.`,
133
+ },
134
+ {
135
+ name: 'ship',
136
+ mode: 'host-native',
137
+ persona: 'vortex',
138
+ description: 'Run the continuous-deployment pipeline — host LLM orchestrates Vortex through PR → merge → tag → publish',
139
+ instruction: `Orchestrate the continuous-deployment workflow yourself.
140
+
141
+ 1. Read \`dist-templates/workflows/continuous-deployment.yaml\` to understand the phases
142
+ 2. Read \`.openlife/method/agents/vortex.md\` and become Vortex for steps that require the EXCLUSIVE git/PR/release authority
143
+ 3. Walk through: pre-release QA → open PR → wait CI → merge → version bump → tag → publish → release notes → log event
144
+ 4. EVERY destructive step (push, tag, publish) requires explicit user OK before proceeding — never auto-merge
145
+
146
+ Vortex is the only persona authorized to push, open/merge PRs, and run releases.`,
147
+ },
148
+ {
149
+ name: 'explore',
150
+ mode: 'host-native',
151
+ persona: 'lyra',
152
+ description: 'Exploratory ideation — host LLM acts as Lyra for divergent brainstorming then convergent narrative',
153
+ instruction: `Read \`.openlife/method/agents/lyra.md\`, become Lyra, and run \`*brainstorm "$ARGUMENTS"\`.
154
+
155
+ Surface options + tradeoffs. Mark confidence per claim (high / medium / low). Cite sources when claims are non-obvious.
156
+
157
+ Do NOT commit to a plan in this command — that's \`/openlife:plan\`. Explore is divergent; Plan is convergent.`,
158
+ },
159
+ {
160
+ name: 'audit',
161
+ mode: 'host-native',
162
+ persona: 'genesis',
163
+ description: 'Run brownfield-discovery — host LLM orchestrates the 10-phase audit of an existing codebase',
164
+ instruction: `Orchestrate the brownfield-discovery workflow yourself, playing multiple personas inline.
165
+
166
+ 1. Read \`dist-templates/workflows/brownfield-discovery.yaml\` to understand the 10 phases
167
+ 2. Walk through:
168
+ - Phase 1 (Atlas): system-architecture.md
169
+ - Phase 2 (Mesh, conditional): SCHEMA.md + DB-AUDIT.md
170
+ - Phase 3 (Prism, conditional): frontend-spec.md
171
+ - Phase 4 (Atlas): technical-debt-DRAFT.md
172
+ - Phase 5 (Mesh): db-specialist-review.md
173
+ - Phase 6 (Prism): ux-specialist-review.md
174
+ - Phase 7 (Sentinel): qa-review.md (gate: APPROVED / NEEDS WORK)
175
+ - Phase 8 (Atlas): technical-debt-assessment.md (final)
176
+ - Phase 9 (Lyra): TECHNICAL-DEBT-REPORT.md (executive)
177
+ - Phase 10 (Genesis): Epic + stories ready for backlog
178
+
179
+ Each phase ends with the user OK'ing before the next.`,
180
+ },
181
+ {
182
+ name: 'health',
183
+ mode: 'host-native',
184
+ description: 'Extended health check — combines `doctor` runtime check with Maestro\'s framework integrity review',
185
+ instruction: `Two-step health check:
186
+
187
+ 1. Run \`openlife system doctor\` (real shell command) to capture API keys, model chain, catalog state, daemon state
188
+ 2. Read \`.openlife/method/agents/maestro.md\`, become Maestro, and check cross-agent integrity:
189
+ - Catalog completeness (314 agents / 46 squads / 55 skills present?)
190
+ - Missing handoff artifacts in \`.openlife/handoffs/\`
191
+ - Draft components pending promotion in \`.catalog/{agents,squads,skills}/<id>/\` with \`status: draft\`
192
+ - Any contradictions between \`.openlife/project.json\` mode and active workflow
193
+
194
+ Present both diagnostics in one consolidated report.`,
195
+ },
196
+ ];
197
+
198
+ const AGENTS = [
199
+ { id: 'maestro', desc: 'Master Orchestrator — routes work, manages handoffs, arbitrates cross-agent decisions' },
200
+ { id: 'builder', desc: 'Full-Stack Developer — implements validated stories with self-review' },
201
+ { id: 'sentinel', desc: 'QA / Test Architect — 7-check gate + iterative QA Loop (max 5)' },
202
+ { id: 'steward', desc: 'Product Owner / Story Validator — owns the Draft → Ready gate' },
203
+ { id: 'conductor', desc: 'Scrum Master — drafts stories, manages sprint cadence, runs retros' },
204
+ { id: 'vortex', desc: 'DevOps — EXCLUSIVE authority over git push, gh PR, MCP, releases' },
205
+ { id: 'mesh', desc: 'Data Engineer — DDL, query optimization, RLS policies, migrations' },
206
+ { id: 'prism', desc: 'UX / UI Designer — wireframes, user research, design-system audits' },
207
+ { id: 'atlas', desc: 'System Architect — ADRs, technology selection, impact analysis' },
208
+ { id: 'lyra', desc: 'Analyst — deep research, synthesis, PRDs, ADRs, release notes' },
209
+ { id: 'forge', desc: 'Component Creator — agents, squads, skills, workflows, MCP configs, slash commands' },
210
+ { id: 'genesis', desc: 'Product Manager / Bootstrap — gather requirements, create epics, set project mode' },
211
+ ];
212
+
213
+ const FLOWS = [
214
+ { id: 'greenfield-fullstack', desc: 'Greenfield Full-Stack: end-to-end new app from concept to shippable stories' },
215
+ { id: 'greenfield-service', desc: 'Greenfield Service: backend-only / API-only / CLI / worker / MCP server' },
216
+ { id: 'greenfield-ui', desc: 'Greenfield UI: frontend-only / SPA / landing / admin panel / docs site' },
217
+ { id: 'brownfield-discovery', desc: 'Brownfield Discovery: 10-phase audit of an existing codebase' },
218
+ { id: 'brownfield-fullstack', desc: 'Brownfield Full-Stack: enhance an existing full-stack app' },
219
+ { id: 'brownfield-service', desc: 'Brownfield Service: modify an existing service / API' },
220
+ { id: 'brownfield-ui', desc: 'Brownfield UI: refactor or enhance an existing UI' },
221
+ { id: 'story-cycle', wfId: 'story-development-cycle', desc: 'Story Development Cycle: 4-phase Create → Validate → Implement → QA' },
222
+ { id: 'qa-loop', desc: 'QA Loop: iterative review-fix cycle (max 5 iterations) between Sentinel and Builder' },
223
+ { id: 'spec-pipeline', desc: 'Spec Pipeline: 6-phase gather → assess → research → write → critique → plan' },
224
+ { id: 'epic', wfId: 'epic-orchestration', desc: 'Epic Orchestration: coordinate multiple dependent stories within an epic' },
225
+ { id: 'release', wfId: 'continuous-deployment', desc: 'Continuous Deployment: release pipeline driven by Vortex (PR → merge → tag → publish)' },
226
+ ];
227
+
228
+ // ─── File renderers ─────────────────────────────────────────────────────
229
+
230
+ function renderTopLevel(cmd) {
231
+ const hintLine = cmd.argumentHint ? `argument-hint: "${cmd.argumentHint}"\n` : '';
232
+
233
+ // Runtime-state commands shell out (real diagnostics, not LLM reasoning).
234
+ if (cmd.mode === 'runtime') {
235
+ return `---
236
+ description: ${cmd.description}
237
+ ${hintLine}allowed-tools:
238
+ - Read
239
+ - Bash(openlife:*)
240
+ - Grep
241
+ - Glob
242
+ - Agent
243
+ - AskUserQuestion
244
+ ---
245
+
246
+ ${cmd.instruction}
247
+ `;
248
+ }
249
+
250
+ // Host-native LLM-reasoning commands respond directly using the host LLM.
251
+ return `---
252
+ description: ${cmd.description}
253
+ ${hintLine}allowed-tools:
254
+ - Read
255
+ - Write
256
+ - Edit
257
+ - Bash(openlife:*)
258
+ - Grep
259
+ - Glob
260
+ - Agent
261
+ - AskUserQuestion
262
+ ---
263
+
264
+ **Mode:** host-native (the host LLM running this conversation answers directly — no external API key required).
265
+
266
+ ${cmd.instruction}
267
+
268
+ ---
269
+
270
+ ### Want the external model chain instead?
271
+
272
+ If you specifically need the configured \`models.json\` chain (for cost-tracking, batch, or non-host contexts), run the command in a terminal:
273
+
274
+ \`\`\`bash
275
+ openlife ${cmd.name} "$ARGUMENTS"
276
+ \`\`\`
277
+
278
+ That path uses the Brain dispatcher and requires the appropriate API key in \`.env\`. The slash command (this one) intentionally bypasses external APIs to keep host-CLI usage zero-config.
279
+ `;
280
+ }
281
+
282
+ function renderAgent(agent) {
283
+ return `---
284
+ description: Activate ${capitalize(agent.id)} — ${agent.desc}
285
+ argument-hint: "[optional context]"
286
+ allowed-tools:
287
+ - Read
288
+ - Write
289
+ - Edit
290
+ - Bash(openlife:*)
291
+ - Grep
292
+ - Glob
293
+ - Agent
294
+ - AskUserQuestion
295
+ ---
296
+
297
+ **Mode:** host-native — you (the host LLM) become **${capitalize(agent.id)}** for this conversation.
298
+
299
+ Activation:
300
+
301
+ 1. Read \`.openlife/method/agents/${agent.id}.md\` in full.
302
+ 2. Adopt the persona and execute the activation flow defined there:
303
+ - Display the persona greeting (icon + 1-line role)
304
+ - Show the top 5 commands
305
+ - HALT and await \`*command\` from the user
306
+ 3. If \`$ARGUMENTS\` is non-empty, treat it as an initial task or context for the persona.
307
+
308
+ After the user's first \`*command\`, follow the persona's hand-off rules to suggest the next persona when appropriate.
309
+
310
+ This activation does NOT use any external model — you ARE the agent. The OpenLife Brain (external model chain) is reserved for headless / CI usage via \`openlife ask\` in a terminal.
311
+ `;
312
+ }
313
+
314
+ function renderFlow(flow) {
315
+ const wfId = flow.wfId || flow.id;
316
+ return `---
317
+ description: ${flow.desc}
318
+ argument-hint: "[--dry-run] [--vars key=value]"
319
+ allowed-tools:
320
+ - Read
321
+ - Bash(openlife:*)
322
+ - Grep
323
+ - Glob
324
+ - Agent
325
+ - AskUserQuestion
326
+ ---
327
+
328
+ **Mode:** host-native — you (the host LLM) orchestrate the \`${wfId}\` workflow yourself, playing the personas as needed.
329
+
330
+ ### Step 1 — Load the workflow definition
331
+
332
+ Read \`dist-templates/workflows/${wfId}.yaml\` (project local override at \`.openlife/method/workflows/${wfId}.yaml\` or \`.catalog/workflows/${wfId}.yaml\` takes precedence if present).
333
+
334
+ If \`$ARGUMENTS\` contains \`--dry-run\`, ALSO shell out to \`openlife flow run ${wfId} --dry-run\` to print the phase plan, then STOP.
335
+
336
+ ### Step 2 — Walk the phases
337
+
338
+ For each phase in the workflow's \`sequence\`:
339
+
340
+ 1. Announce which phase you're entering and which persona owns this phase (the \`agent:\` field on the step)
341
+ 2. Read \`.openlife/method/agents/<persona-id>.md\` for the active persona — adopt that persona for this phase
342
+ 3. Execute the step's \`action\` using the persona's discipline (commands, hand-off rules, anti-patterns)
343
+ 4. Produce the artifacts listed in \`creates:\` — write them to the paths declared in the YAML
344
+ 5. If \`elicit: true\`, ask the user via AskUserQuestion before proceeding
345
+ 6. Hand off to the next phase's persona; announce the handoff
346
+
347
+ ### Step 3 — Surface failures explicitly
348
+
349
+ On any step failure: identify the failing step, the active persona, and offer to escalate to \`@openlife-maestro\` (read \`.openlife/method/agents/maestro.md\`).
350
+
351
+ ### Why host-native, not shell?
352
+
353
+ Running the workflow this way uses your reasoning (the host LLM) instead of the external Brain chain. Zero API key needed for orchestration. If the user wants the external Brain to drive (headless / batch / cron), they can run \`openlife flow run ${wfId} "$ARGUMENTS"\` in a terminal.
354
+ `;
355
+ }
356
+
357
+ function capitalize(s) {
358
+ return s[0].toUpperCase() + s.slice(1);
359
+ }
360
+
361
+ // ─── Emit ───────────────────────────────────────────────────────────────
362
+
363
+ let total = 0;
364
+ let hostNative = 0;
365
+ let runtime = 0;
366
+
367
+ for (const host of HOSTS) {
368
+ const baseDir = path.join(REPO_ROOT, 'dist-templates', host, 'commands', 'openlife');
369
+ fs.mkdirSync(path.join(baseDir, 'agents'), { recursive: true });
370
+ fs.mkdirSync(path.join(baseDir, 'flow'), { recursive: true });
371
+
372
+ for (const cmd of TOP_LEVEL) {
373
+ const fp = path.join(baseDir, `${cmd.name}.md`);
374
+ fs.writeFileSync(fp, renderTopLevel(cmd));
375
+ total++;
376
+ if (cmd.mode === 'host-native') hostNative++;
377
+ else if (cmd.mode === 'runtime') runtime++;
378
+ }
379
+ for (const agent of AGENTS) {
380
+ const fp = path.join(baseDir, 'agents', `${agent.id}.md`);
381
+ fs.writeFileSync(fp, renderAgent(agent));
382
+ total++;
383
+ hostNative++;
384
+ }
385
+ for (const flow of FLOWS) {
386
+ const fp = path.join(baseDir, 'flow', `${flow.id}.md`);
387
+ fs.writeFileSync(fp, renderFlow(flow));
388
+ total++;
389
+ hostNative++;
390
+ }
391
+ }
392
+
393
+ console.log(`[generate-slash-commands] wrote ${total} files across ${HOSTS.length} hosts.`);
394
+ console.log(`Breakdown per host: ${TOP_LEVEL.length} top-level + ${AGENTS.length} agents + ${FLOWS.length} flows = ${TOP_LEVEL.length + AGENTS.length + FLOWS.length}`);
395
+ console.log(`Mode split: ${hostNative} host-native + ${runtime} runtime-state (× ${HOSTS.length} hosts)`);
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env node
2
+ // scripts/generate-squad-workflow-stubs.js
3
+ //
4
+ // Walks `.catalog/squads/*/SQUAD.md`, extracts the workflows declared in
5
+ // each squad's embedded yaml block (the `workflows:` list under
6
+ // `components:`), and creates parse-clean stub `.yaml` files at
7
+ // `.catalog/squads/<squad-id>/workflows/<ref>` for any reference that
8
+ // lacks a corresponding file on disk.
9
+ //
10
+ // Stubs are marked `status: draft` so the framework treats them as
11
+ // pending fleshing-out (via aiobuilder evolve or manual editing).
12
+ //
13
+ // Idempotent: re-running only creates missing files, never overwrites.
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const REPO_ROOT = path.resolve(__dirname, '..');
19
+ const SQUADS_DIR = path.join(REPO_ROOT, '.catalog', 'squads');
20
+
21
+ if (!fs.existsSync(SQUADS_DIR)) {
22
+ console.error(`SQUADS_DIR_MISSING: ${SQUADS_DIR}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ function humanize(ref) {
27
+ return ref
28
+ .replace(/\.ya?ml$/, '')
29
+ .replace(/^wf-/, '')
30
+ .replace(/-/g, ' ')
31
+ .replace(/\b\w/g, (c) => c.toUpperCase());
32
+ }
33
+
34
+ function extractWorkflowRefs(squadMd) {
35
+ // Matches:
36
+ // workflows:
37
+ // - wf-foo.yaml
38
+ // - wf-bar.yaml
39
+ // (possibly nested with extra indentation; we just match the list items)
40
+ const refs = new Set();
41
+ const lines = squadMd.split('\n');
42
+ let inWorkflowBlock = false;
43
+ let workflowIndent = -1;
44
+
45
+ for (const raw of lines) {
46
+ const trimmed = raw.trimStart();
47
+ const indent = raw.length - trimmed.length;
48
+
49
+ if (/^workflows:\s*$/.test(trimmed)) {
50
+ inWorkflowBlock = true;
51
+ workflowIndent = indent;
52
+ continue;
53
+ }
54
+
55
+ if (inWorkflowBlock) {
56
+ // Exit block on the first non-list-item line at or below the parent indent
57
+ if (trimmed === '' || (indent <= workflowIndent && !trimmed.startsWith('-'))) {
58
+ inWorkflowBlock = false;
59
+ continue;
60
+ }
61
+ // List item: `- wf-foo.yaml` or `- "wf-foo.yaml"`
62
+ const m = trimmed.match(/^-\s+["']?([^"'\s]+\.ya?ml)["']?\s*$/);
63
+ if (m) refs.add(m[1]);
64
+ }
65
+ }
66
+
67
+ return Array.from(refs);
68
+ }
69
+
70
+ function renderStub(ref, squadId) {
71
+ const id = ref.replace(/\.ya?ml$/, '');
72
+ const name = humanize(ref);
73
+ // Stub is a parse-clean Workflow YAML. status:draft signals not-yet-fleshed.
74
+ return `workflow:
75
+ id: ${squadId}/${id}
76
+ name: "${name} (${squadId})"
77
+ description: >-
78
+ Stub workflow scaffolded for squad ${squadId}. Declared in SQUAD.md but
79
+ not yet fleshed out. Run \`openlife aiobuilder evolve\` or edit manually
80
+ to define phases, sequence, and success criteria.
81
+ type: custom
82
+ version: "0.1"
83
+ status: draft
84
+ framework: openlife-method
85
+
86
+ sequence:
87
+ - phase: 1
88
+ name: "TODO"
89
+ - id: todo-step
90
+ agent: openlife-forge
91
+ action: define_workflow
92
+ notes: |
93
+ Define the squad-internal workflow logic here.
94
+ Replace this stub with real phases and steps. When complete, change
95
+ status from "draft" to "active".
96
+
97
+ handoff_prompts:
98
+ initial: "This is a stub — define the workflow before running it."
99
+ `;
100
+ }
101
+
102
+ // ─── Main ───────────────────────────────────────────────────────────────
103
+
104
+ let squadsTotal = 0;
105
+ let squadsWithRefs = 0;
106
+ let stubsCreated = 0;
107
+ let stubsSkipped = 0;
108
+ const missingDetails = [];
109
+
110
+ for (const squadId of fs.readdirSync(SQUADS_DIR).sort()) {
111
+ const squadDir = path.join(SQUADS_DIR, squadId);
112
+ if (!fs.statSync(squadDir).isDirectory()) continue;
113
+ if (squadId.startsWith('test-')) continue; // test pollution
114
+
115
+ squadsTotal++;
116
+ const squadMdPath = path.join(squadDir, 'SQUAD.md');
117
+ if (!fs.existsSync(squadMdPath)) continue;
118
+
119
+ const content = fs.readFileSync(squadMdPath, 'utf-8');
120
+ const refs = extractWorkflowRefs(content);
121
+ if (refs.length === 0) continue;
122
+
123
+ squadsWithRefs++;
124
+ const workflowsDir = path.join(squadDir, 'workflows');
125
+ fs.mkdirSync(workflowsDir, { recursive: true });
126
+
127
+ for (const ref of refs) {
128
+ const target = path.join(workflowsDir, ref);
129
+ if (fs.existsSync(target)) {
130
+ stubsSkipped++;
131
+ continue;
132
+ }
133
+ fs.writeFileSync(target, renderStub(ref, squadId));
134
+ stubsCreated++;
135
+ missingDetails.push(`${squadId}/${ref}`);
136
+ }
137
+ }
138
+
139
+ console.log(`[squad-workflow-stubs] scanned ${squadsTotal} squads (${squadsWithRefs} with workflow refs)`);
140
+ console.log(`[squad-workflow-stubs] stubs: ${stubsCreated} created, ${stubsSkipped} already existed`);
141
+ if (stubsCreated > 0 && process.env.VERBOSE) {
142
+ console.log('Created:');
143
+ for (const d of missingDetails) console.log(' +', d);
144
+ }