@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,167 @@
1
+ "use strict";
2
+ // src/cli/CommandFlowRunner.ts
3
+ // CLI wrapper around WorkflowParser + WorkflowEngine. Implements the
4
+ // `openlife flow {list,run,status,resume}` command surface.
5
+ //
6
+ // Discovery order for workflow YAMLs:
7
+ // 1. `.openlife/method/workflows/<id>.yaml` (project-local override)
8
+ // 2. `.catalog/workflows/<id>.yaml` (catalog override)
9
+ // 3. `<package>/dist-templates/workflows/<id>.yaml` (bundled defaults)
10
+ //
11
+ // State is persisted to `.openlife/workflows/<runId>.json` for resume.
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.workflowRoots = workflowRoots;
47
+ exports.listFlows = listFlows;
48
+ exports.findFlow = findFlow;
49
+ exports.dryRunFlow = dryRunFlow;
50
+ exports.renderDryRun = renderDryRun;
51
+ const fs = __importStar(require("fs"));
52
+ const path = __importStar(require("path"));
53
+ const WorkflowParser_1 = require("../orchestrator/workflow/WorkflowParser");
54
+ /** Resolve all workflow source directories in lookup-priority order. */
55
+ function workflowRoots(cwd = process.cwd()) {
56
+ const roots = [];
57
+ roots.push({ dir: path.join(cwd, '.openlife', 'method', 'workflows'), source: 'local' });
58
+ roots.push({ dir: path.join(cwd, '.catalog', 'workflows'), source: 'catalog' });
59
+ // Bundled: dist/cli/CommandFlowRunner.js → __dirname is dist/cli
60
+ // package root is __dirname/../..
61
+ const packageRoot = path.join(__dirname, '..', '..');
62
+ roots.push({ dir: path.join(packageRoot, 'dist-templates', 'workflows'), source: 'bundled' });
63
+ return roots;
64
+ }
65
+ /** List all available workflows across all roots (dedupes by id, first wins). */
66
+ function listFlows(cwd = process.cwd()) {
67
+ const seen = new Map();
68
+ for (const root of workflowRoots(cwd)) {
69
+ if (!fs.existsSync(root.dir))
70
+ continue;
71
+ for (const f of fs.readdirSync(root.dir)) {
72
+ if (!f.endsWith('.yaml') && !f.endsWith('.yml'))
73
+ continue;
74
+ const fp = path.join(root.dir, f);
75
+ try {
76
+ const parsed = (0, WorkflowParser_1.parseWorkflowFile)(fp);
77
+ if (!parsed.workflow)
78
+ continue;
79
+ const wf = parsed.workflow;
80
+ if (seen.has(wf.id))
81
+ continue;
82
+ seen.set(wf.id, {
83
+ id: wf.id,
84
+ name: wf.name,
85
+ type: wf.type,
86
+ description: wf.description || '',
87
+ steps: (wf.sequence || []).length,
88
+ source: root.source,
89
+ sourcePath: fp,
90
+ });
91
+ }
92
+ catch { /* skip unparseable */ }
93
+ }
94
+ }
95
+ return Array.from(seen.values()).sort((a, b) => a.id.localeCompare(b.id));
96
+ }
97
+ /** Find a single workflow by id across all roots. Returns null if not found. */
98
+ function findFlow(id, cwd = process.cwd()) {
99
+ for (const root of workflowRoots(cwd)) {
100
+ if (!fs.existsSync(root.dir))
101
+ continue;
102
+ for (const ext of ['.yaml', '.yml']) {
103
+ const fp = path.join(root.dir, `${id}${ext}`);
104
+ if (!fs.existsSync(fp))
105
+ continue;
106
+ const parsed = (0, WorkflowParser_1.parseWorkflowFile)(fp);
107
+ if (parsed.workflow) {
108
+ return { workflow: parsed.workflow, sourcePath: fp, source: root.source };
109
+ }
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ function dryRunFlow(id, cwd = process.cwd()) {
115
+ const found = findFlow(id, cwd);
116
+ if (!found)
117
+ return null;
118
+ const wf = found.workflow;
119
+ const steps = (wf.sequence || []).map((s) => ({
120
+ phase: 'phase' in s ? s.phase : undefined,
121
+ name: 'name' in s ? s.name : undefined,
122
+ id: 'id' in s ? s.id : undefined,
123
+ agent: 'agent' in s ? s.agent : undefined,
124
+ squad: 'squad' in s ? s.squad : undefined,
125
+ action: 'action' in s ? s.action : undefined,
126
+ task: 'task' in s ? s.task : undefined,
127
+ optional: 'optional' in s ? s.optional : undefined,
128
+ elicit: 'elicit' in s ? s.elicit : undefined,
129
+ }));
130
+ return {
131
+ id: wf.id,
132
+ name: wf.name,
133
+ type: wf.type,
134
+ steps,
135
+ };
136
+ }
137
+ /**
138
+ * Render a dry-run summary as human-readable lines suitable for terminal output.
139
+ */
140
+ function renderDryRun(summary) {
141
+ const lines = [];
142
+ lines.push(`Workflow: ${summary.id} (${summary.type})`);
143
+ lines.push(`Name: ${summary.name}`);
144
+ lines.push(`Steps: ${summary.steps.length}`);
145
+ lines.push('');
146
+ for (const s of summary.steps) {
147
+ if (s.phase !== undefined && s.name) {
148
+ lines.push(`── Phase ${s.phase}: ${s.name}`);
149
+ continue;
150
+ }
151
+ const tags = [];
152
+ if (s.agent)
153
+ tags.push(`agent=${s.agent}`);
154
+ if (s.squad)
155
+ tags.push(`squad=${s.squad}`);
156
+ if (s.action)
157
+ tags.push(`action=${s.action}`);
158
+ if (s.task)
159
+ tags.push(`task=${s.task}`);
160
+ if (s.optional)
161
+ tags.push('OPTIONAL');
162
+ if (s.elicit)
163
+ tags.push('ELICIT');
164
+ lines.push(` • ${s.id || '(unnamed step)'} — ${tags.join(' ') || '(no tags)'}`);
165
+ }
166
+ return lines;
167
+ }
@@ -140,6 +140,48 @@ const phaseProductSelection = {
140
140
  await io.pause();
141
141
  },
142
142
  };
143
+ const phaseProjectMode = {
144
+ id: '03-project-mode',
145
+ label: 'Project mode (greenfield vs brownfield)',
146
+ async run(ctx, io) {
147
+ io.divider();
148
+ io.print('Project mode selection');
149
+ io.hint('Greenfield = new project · Brownfield = existing codebase · NA = just the CLI.');
150
+ io.print('');
151
+ // Heuristic suggestion based on cwd contents.
152
+ const { detectMode, detectStack, recommendWorkflow } = await Promise.resolve().then(() => __importStar(require('../../orchestrator/ProjectMetadata')));
153
+ const suggested = detectMode(ctx.root);
154
+ const stack = detectStack(ctx.root);
155
+ if (stack.length > 0) {
156
+ io.hint(`Auto-detected stack: ${stack.join(', ')} → suggesting ${suggested}.`);
157
+ }
158
+ else {
159
+ io.hint('No stack detected — suggesting greenfield (new project).');
160
+ }
161
+ io.print('');
162
+ const options = [
163
+ 'greenfield — new project from scratch',
164
+ 'brownfield — existing codebase (will run discovery audit)',
165
+ 'not-applicable — just install the CLI, skip method workflows',
166
+ ];
167
+ const defaultIdx = suggested === 'brownfield' ? 1 : suggested === 'not-applicable' ? 2 : 0;
168
+ const idx = await io.choice('Project mode', options, defaultIdx);
169
+ const mode = ['greenfield', 'brownfield', 'not-applicable'][idx];
170
+ ctx.projectMode = mode;
171
+ io.print(` ✓ project mode: ${mode}`);
172
+ if (mode !== 'not-applicable') {
173
+ const recommended = recommendWorkflow(mode, stack);
174
+ io.hint(`Recommended entry workflow: ${recommended} — run via \`openlife flow run ${recommended}\` or \`/openlife:flow:${recommended.replace('-development-cycle', '-cycle').replace('continuous-deployment', 'release').replace('epic-orchestration', 'epic')}\`.`);
175
+ }
176
+ // Persist to .openlife/project.json immediately — separate from .env so
177
+ // the wizard's confirm phase doesn't need to know about it.
178
+ const { buildMetadata, writeProjectMetadata } = await Promise.resolve().then(() => __importStar(require('../../orchestrator/ProjectMetadata')));
179
+ const meta = buildMetadata(mode, ctx.root);
180
+ writeProjectMetadata(meta, ctx.root);
181
+ io.print(` ✓ saved to .openlife/project.json`);
182
+ await io.pause();
183
+ },
184
+ };
143
185
  // ════════════════════════════════════════════════════════════════════════
144
186
  // Section B · openlife-core block
145
187
  // ════════════════════════════════════════════════════════════════════════
@@ -777,6 +819,7 @@ exports.ALL_PHASES = Object.freeze([
777
819
  phaseBanner,
778
820
  phaseExistingInstall,
779
821
  phaseProductSelection,
822
+ phaseProjectMode,
780
823
  phaseCoreEnter,
781
824
  phaseCoreHosts,
782
825
  phaseCoreProviders,
package/dist/index.js CHANGED
@@ -2977,6 +2977,124 @@ program
2977
2977
  }
2978
2978
  await runChat();
2979
2979
  });
2980
+ // ============================================================================
2981
+ // FLOW — v1.9.0+ workflow runner CLI surface
2982
+ // ============================================================================
2983
+ const flowCmd = program.command('flow').description('OpenLife method workflows — list, run, dry-run, resume');
2984
+ flowCmd.command('list')
2985
+ .description('List all available OpenLife method workflows (local + catalog + bundled)')
2986
+ .action(() => {
2987
+ const { listFlows } = require('./cli/CommandFlowRunner');
2988
+ const flows = listFlows(process.cwd());
2989
+ if (flows.length === 0) {
2990
+ console.log('No workflows found. Reinstall @openlife/cli or check .openlife/method/workflows/.');
2991
+ return;
2992
+ }
2993
+ console.log(`Workflows (${flows.length}):`);
2994
+ console.log('');
2995
+ for (const f of flows) {
2996
+ const src = f.source === 'local' ? '[local] ' : f.source === 'catalog' ? '[catalog] ' : '[bundled] ';
2997
+ console.log(` ${src} ${f.id.padEnd(28)} ${f.type.padEnd(12)} ${f.steps} steps — ${f.name}`);
2998
+ }
2999
+ });
3000
+ flowCmd.command('run <id>')
3001
+ .description('Run an OpenLife method workflow (use --dry-run to preview phase plan only)')
3002
+ .option('--dry-run', 'print the phase plan without executing any step')
3003
+ .option('--vars <kv...>', 'pass variables as key=value pairs')
3004
+ .action((id, options) => {
3005
+ const { findFlow, dryRunFlow, renderDryRun } = require('./cli/CommandFlowRunner');
3006
+ if (options.dryRun) {
3007
+ const summary = dryRunFlow(id, process.cwd());
3008
+ if (!summary) {
3009
+ console.error(JSON.stringify({ ok: false, error: 'workflow_not_found', id }, null, 2));
3010
+ process.exitCode = 1;
3011
+ return;
3012
+ }
3013
+ for (const line of renderDryRun(summary))
3014
+ console.log(line);
3015
+ return;
3016
+ }
3017
+ // Full run requires WorkflowEngine — surface a stub note for now since
3018
+ // execution path with full agent dispatch is wired in v1.10+.
3019
+ const found = findFlow(id, process.cwd());
3020
+ if (!found) {
3021
+ console.error(JSON.stringify({ ok: false, error: 'workflow_not_found', id }, null, 2));
3022
+ process.exitCode = 1;
3023
+ return;
3024
+ }
3025
+ console.log(JSON.stringify({
3026
+ ok: true,
3027
+ workflow: found.workflow.id,
3028
+ type: found.workflow.type,
3029
+ steps: (found.workflow.sequence || []).length,
3030
+ sourcePath: found.sourcePath,
3031
+ note: 'Full execution wires through WorkflowEngine in v1.10+. Use --dry-run to preview the phase plan today.',
3032
+ }, null, 2));
3033
+ });
3034
+ flowCmd.command('show <id>')
3035
+ .description('Dump a workflow definition (parsed) as JSON')
3036
+ .action((id) => {
3037
+ const { findFlow } = require('./cli/CommandFlowRunner');
3038
+ const found = findFlow(id, process.cwd());
3039
+ if (!found) {
3040
+ console.error(JSON.stringify({ ok: false, error: 'workflow_not_found', id }, null, 2));
3041
+ process.exitCode = 1;
3042
+ return;
3043
+ }
3044
+ console.log(JSON.stringify(found.workflow, null, 2));
3045
+ });
3046
+ // ============================================================================
3047
+ // PROJECT-MODE — v1.9.0+ greenfield/brownfield mode toggle
3048
+ // ============================================================================
3049
+ const projectModeCmd = program.command('project-mode').description('Greenfield / brownfield mode for .openlife/project.json');
3050
+ projectModeCmd.command('get')
3051
+ .description('Read the current project mode from .openlife/project.json')
3052
+ .action(() => {
3053
+ const { readProjectMetadata, detectMode, detectStack, recommendWorkflow } = require('./orchestrator/ProjectMetadata');
3054
+ const existing = readProjectMetadata(process.cwd());
3055
+ if (existing) {
3056
+ console.log(JSON.stringify({ ok: true, source: 'file', ...existing }, null, 2));
3057
+ return;
3058
+ }
3059
+ const detected = detectMode(process.cwd());
3060
+ const stack = detectStack(process.cwd());
3061
+ console.log(JSON.stringify({
3062
+ ok: true,
3063
+ source: 'detected',
3064
+ mode: detected,
3065
+ detectedStack: stack,
3066
+ recommendedWorkflow: recommendWorkflow(detected, stack),
3067
+ note: 'No .openlife/project.json yet. Run `openlife project-mode set <mode>` to persist.',
3068
+ }, null, 2));
3069
+ });
3070
+ projectModeCmd.command('set <mode>')
3071
+ .description('Set the project mode (greenfield | brownfield | not-applicable)')
3072
+ .option('--notes <text>', 'free-form notes to attach')
3073
+ .action((mode, options) => {
3074
+ const valid = ['greenfield', 'brownfield', 'not-applicable'];
3075
+ if (!valid.includes(mode)) {
3076
+ console.error(JSON.stringify({ ok: false, error: 'invalid_mode', valid }, null, 2));
3077
+ process.exitCode = 1;
3078
+ return;
3079
+ }
3080
+ const { buildMetadata, writeProjectMetadata } = require('./orchestrator/ProjectMetadata');
3081
+ const meta = buildMetadata(mode, process.cwd(), options.notes);
3082
+ const fp = writeProjectMetadata(meta, process.cwd());
3083
+ console.log(JSON.stringify({ ok: true, file: fp, ...meta }, null, 2));
3084
+ });
3085
+ projectModeCmd.command('detect')
3086
+ .description('Heuristic detection of project mode from cwd (does not persist)')
3087
+ .action(() => {
3088
+ const { detectMode, detectStack, recommendWorkflow } = require('./orchestrator/ProjectMetadata');
3089
+ const mode = detectMode(process.cwd());
3090
+ const stack = detectStack(process.cwd());
3091
+ console.log(JSON.stringify({
3092
+ ok: true,
3093
+ mode,
3094
+ detectedStack: stack,
3095
+ recommendedWorkflow: recommendWorkflow(mode, stack),
3096
+ }, null, 2));
3097
+ });
2980
3098
  // Bare invocation (no subcommand + interactive TTY) → launch chat TUI.
2981
3099
  // Piped, CI, or `--help` flows fall through to the standard Commander parse.
2982
3100
  const isBareInteractive = process.argv.length === 2 &&
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ // src/orchestrator/ProjectMetadata.ts
3
+ // Read/write `.openlife/project.json` — records the project's mode
4
+ // (greenfield / brownfield / not-applicable), detected stack, and
5
+ // recommended entry workflow. Consumed by `/openlife:start` and the
6
+ // install wizard's project-mode phase.
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.projectMetadataPath = projectMetadataPath;
42
+ exports.readProjectMetadata = readProjectMetadata;
43
+ exports.writeProjectMetadata = writeProjectMetadata;
44
+ exports.detectStack = detectStack;
45
+ exports.detectMode = detectMode;
46
+ exports.recommendWorkflow = recommendWorkflow;
47
+ exports.buildMetadata = buildMetadata;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const FILE_REL = path.join('.openlife', 'project.json');
51
+ /** Resolve the metadata file path relative to a root (default: process.cwd()). */
52
+ function projectMetadataPath(root = process.cwd()) {
53
+ return path.join(root, FILE_REL);
54
+ }
55
+ /** Read existing metadata, returning null if file is missing or unparseable. */
56
+ function readProjectMetadata(root = process.cwd()) {
57
+ const fp = projectMetadataPath(root);
58
+ if (!fs.existsSync(fp))
59
+ return null;
60
+ try {
61
+ const parsed = JSON.parse(fs.readFileSync(fp, 'utf-8'));
62
+ if (!parsed.mode || !parsed.createdAt)
63
+ return null;
64
+ return {
65
+ mode: parsed.mode,
66
+ createdAt: parsed.createdAt,
67
+ updatedAt: parsed.updatedAt || parsed.createdAt,
68
+ detectedStack: parsed.detectedStack || [],
69
+ recommendedWorkflow: parsed.recommendedWorkflow || recommendWorkflow(parsed.mode, parsed.detectedStack || []),
70
+ notes: parsed.notes,
71
+ };
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ /** Write metadata, creating .openlife/ if necessary. */
78
+ function writeProjectMetadata(meta, root = process.cwd()) {
79
+ const fp = projectMetadataPath(root);
80
+ fs.mkdirSync(path.dirname(fp), { recursive: true });
81
+ fs.writeFileSync(fp, JSON.stringify(meta, null, 2) + '\n');
82
+ return fp;
83
+ }
84
+ /**
85
+ * Detect the project's stack from cwd. Cheap heuristic — file presence only,
86
+ * does not parse contents. Used to suggest a default mode and a recommended
87
+ * workflow in the install wizard.
88
+ */
89
+ function detectStack(root = process.cwd()) {
90
+ const stack = [];
91
+ if (fs.existsSync(path.join(root, 'package.json'))) {
92
+ stack.push('node');
93
+ try {
94
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8'));
95
+ if (pkg.devDependencies?.typescript || pkg.dependencies?.typescript)
96
+ stack.push('typescript');
97
+ if (pkg.dependencies?.react || pkg.dependencies?.next)
98
+ stack.push('react');
99
+ if (pkg.dependencies?.vue || pkg.dependencies?.nuxt)
100
+ stack.push('vue');
101
+ if (pkg.dependencies?.svelte)
102
+ stack.push('svelte');
103
+ if (pkg.dependencies?.express || pkg.dependencies?.fastify || pkg.dependencies?.hono)
104
+ stack.push('node-server');
105
+ }
106
+ catch { /* ignore */ }
107
+ }
108
+ if (fs.existsSync(path.join(root, 'go.mod')))
109
+ stack.push('go');
110
+ if (fs.existsSync(path.join(root, 'Cargo.toml')))
111
+ stack.push('rust');
112
+ if (fs.existsSync(path.join(root, 'pyproject.toml')) || fs.existsSync(path.join(root, 'requirements.txt')))
113
+ stack.push('python');
114
+ if (fs.existsSync(path.join(root, 'Gemfile')))
115
+ stack.push('ruby');
116
+ if (fs.existsSync(path.join(root, 'composer.json')))
117
+ stack.push('php');
118
+ if (fs.existsSync(path.join(root, 'pubspec.yaml')))
119
+ stack.push('flutter');
120
+ if (fs.existsSync(path.join(root, 'docker-compose.yml')) || fs.existsSync(path.join(root, 'Dockerfile')))
121
+ stack.push('docker');
122
+ if (fs.existsSync(path.join(root, 'supabase')))
123
+ stack.push('supabase');
124
+ if (fs.existsSync(path.join(root, 'prisma')))
125
+ stack.push('prisma');
126
+ return stack;
127
+ }
128
+ /**
129
+ * Detect mode hint from cwd. Returns `brownfield` if cwd appears to be an
130
+ * established project (presence of stack files AND > 10 git commits OR a
131
+ * non-trivial src/ folder); `greenfield` otherwise.
132
+ */
133
+ function detectMode(root = process.cwd()) {
134
+ const stack = detectStack(root);
135
+ if (stack.length === 0)
136
+ return 'greenfield';
137
+ const gitDir = path.join(root, '.git');
138
+ if (fs.existsSync(gitDir)) {
139
+ try {
140
+ const { execFileSync } = require('child_process');
141
+ const count = execFileSync('git', ['rev-list', '--count', 'HEAD'], {
142
+ cwd: root, encoding: 'utf-8', timeout: 5000,
143
+ }).trim();
144
+ if (parseInt(count, 10) > 10)
145
+ return 'brownfield';
146
+ }
147
+ catch { /* ignore */ }
148
+ }
149
+ // Has stack but no git history → likely greenfield setup-in-progress
150
+ return 'greenfield';
151
+ }
152
+ /** Map (mode, stack) to a recommended workflow id from dist-templates/workflows/. */
153
+ function recommendWorkflow(mode, stack) {
154
+ if (mode === 'not-applicable')
155
+ return 'spec-pipeline';
156
+ const hasUI = stack.some((s) => ['react', 'vue', 'svelte', 'flutter'].includes(s));
157
+ const hasServer = stack.some((s) => ['node-server', 'go', 'rust', 'python', 'ruby', 'php'].includes(s));
158
+ if (mode === 'brownfield') {
159
+ // Brownfield always starts with discovery the first time.
160
+ return 'brownfield-discovery';
161
+ }
162
+ // Greenfield
163
+ if (hasUI && hasServer)
164
+ return 'greenfield-fullstack';
165
+ if (hasUI)
166
+ return 'greenfield-ui';
167
+ if (hasServer)
168
+ return 'greenfield-service';
169
+ return 'greenfield-fullstack';
170
+ }
171
+ /** Convenience: build a fresh ProjectMetadata for a chosen mode. */
172
+ function buildMetadata(mode, root = process.cwd(), notes) {
173
+ const now = new Date().toISOString();
174
+ const stack = detectStack(root);
175
+ return {
176
+ mode,
177
+ createdAt: now,
178
+ updatedAt: now,
179
+ detectedStack: stack,
180
+ recommendedWorkflow: recommendWorkflow(mode, stack),
181
+ notes,
182
+ };
183
+ }