@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.
- package/.catalog/agents/test-agent/AGENT.md +1 -1
- package/.catalog/mcps/test-mcp/mcp.json +1 -1
- package/.catalog/skills/sample-from-url/IMPORTED_REFERENCE.md +2 -2
- package/.catalog/skills/test-skill/REFERENCE.md +1 -1
- package/.catalog/squads/00-governance-advisory-board/workflows/wf-board-meeting.yaml +25 -0
- package/.catalog/squads/00-governance-advisory-board/workflows/wf-decision-framework.yaml +25 -0
- package/.catalog/squads/00-governance-c-level-squad/workflows/wf-board-presentation.yaml +25 -0
- package/.catalog/squads/00-governance-c-level-squad/workflows/wf-strategic-planning.yaml +25 -0
- package/.catalog/squads/00-governance-project-ops-squad/workflows/mission-to-project.yaml +25 -0
- package/.catalog/squads/00-governance-project-ops-squad/workflows/sprint-planning.yaml +25 -0
- package/.catalog/squads/00-governance-project-ops-squad/workflows/weekly-review.yaml +25 -0
- package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-analysis-flow.yaml +25 -0
- package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-execution-flow.yaml +25 -0
- package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-planning-flow.yaml +25 -0
- package/.catalog/squads/01-meta-framework-swarm-tree-orchestration/workflows/tree-resume-flow.yaml +25 -0
- package/.catalog/squads/02-product-growth-brand-squad/workflows/wf-brand-creation.yaml +25 -0
- package/.catalog/squads/02-product-growth-brand-squad/workflows/wf-rebrand.yaml +25 -0
- package/.catalog/squads/02-product-growth-copy-squad/workflows/wf-copy-review-cycle.yaml +25 -0
- package/.catalog/squads/02-product-growth-copy-squad/workflows/wf-full-copy-project.yaml +25 -0
- package/.catalog/squads/02-product-growth-design-squad/workflows/wf-design-system-creation.yaml +25 -0
- package/.catalog/squads/02-product-growth-design-squad/workflows/wf-feature-design.yaml +25 -0
- package/.catalog/squads/02-product-growth-hormozi-squad/workflows/wf-business-turnaround.yaml +25 -0
- package/.catalog/squads/02-product-growth-hormozi-squad/workflows/wf-offer-creation.yaml +25 -0
- package/.catalog/squads/02-product-growth-movement/workflows/wf-movement-launch.yaml +25 -0
- package/.catalog/squads/02-product-growth-saas-onboarding-activator/workflows/full-onboarding-activation-workflow.yaml +25 -0
- package/.catalog/squads/02-product-growth-saas-onboarding-activator/workflows/quick-engagement-boost-workflow.yaml +25 -0
- package/.catalog/squads/02-product-growth-sales-squad/workflows/followup-sequence.yaml +25 -0
- package/.catalog/squads/02-product-growth-sales-squad/workflows/full-sales-cycle.yaml +25 -0
- package/.catalog/squads/02-product-growth-sales-squad/workflows/proposal-flow.yaml +25 -0
- package/.catalog/squads/02-product-growth-storytelling/workflows/wf-brand-narrative.yaml +25 -0
- package/.catalog/squads/02-product-growth-storytelling/workflows/wf-story-development.yaml +25 -0
- package/.catalog/squads/02-product-growth-traffic-masters/workflows/wf-account-audit.yaml +25 -0
- package/.catalog/squads/02-product-growth-traffic-masters/workflows/wf-campaign-launch.yaml +25 -0
- package/.catalog/squads/03-engineering-quality-automated-code-review-squad/workflows/full-code-review-workflow.yaml +25 -0
- package/.catalog/squads/03-engineering-quality-automated-code-review-squad/workflows/quick-security-check-workflow.yaml +25 -0
- package/.catalog/squads/04-data-security-cybersecurity/workflows/wf-incident-response.yaml +25 -0
- package/.catalog/squads/04-data-security-cybersecurity/workflows/wf-pentest-engagement.yaml +25 -0
- package/.catalog/squads/04-data-security-data-quality-guardian/workflows/full-data-quality-audit-workflow.yaml +25 -0
- package/.catalog/squads/04-data-security-data-quality-guardian/workflows/quick-data-check-workflow.yaml +25 -0
- package/.catalog/squads/04-data-security-data-squad/workflows/wf-analytics-setup.yaml +25 -0
- package/.catalog/squads/04-data-security-data-squad/workflows/wf-growth-sprint.yaml +25 -0
- package/.catalog/squads/04-data-security-incident-response-squad/workflows/full-incident-response-workflow.yaml +25 -0
- package/.catalog/squads/04-data-security-incident-response-squad/workflows/rapid-triage-workflow.yaml +25 -0
- package/.catalog/squads/04-data-security-soc-alert-triage/workflows/full-alert-triage-workflow.yaml +25 -0
- package/.catalog/squads/04-data-security-soc-alert-triage/workflows/rapid-classification-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-adaptive-tutor-k12/workflows/full-tutoring-cycle-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-adaptive-tutor-k12/workflows/quick-practice-session-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-ambient-clinical-scribe/workflows/full-documentation-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-ambient-clinical-scribe/workflows/quick-note-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-contract-review-squad/workflows/full-contract-review-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-contract-review-squad/workflows/quick-risk-assessment-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-crypto-token-forge/workflows/full-token-launch-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-crypto-token-forge/workflows/memecoin-express-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-crypto-token-forge/workflows/utility-token-launch-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-resume-screener-squad/workflows/full-resume-screening-workflow.yaml +25 -0
- package/.catalog/squads/05-domain-specialists-resume-screener-squad/workflows/quick-skills-match-workflow.yaml +25 -0
- package/.catalog/squads/test-squad/SQUAD.md +1 -1
- package/.openlife/method/agents/atlas.md +102 -0
- package/.openlife/method/agents/builder.md +92 -0
- package/.openlife/method/agents/conductor.md +93 -0
- package/.openlife/method/agents/forge.md +96 -0
- package/.openlife/method/agents/genesis.md +115 -0
- package/.openlife/method/agents/lyra.md +85 -0
- package/.openlife/method/agents/maestro.md +92 -0
- package/.openlife/method/agents/mesh.md +101 -0
- package/.openlife/method/agents/prism.md +85 -0
- package/.openlife/method/agents/sentinel.md +115 -0
- package/.openlife/method/agents/steward.md +93 -0
- package/.openlife/method/agents/vortex.md +94 -0
- package/dist/cli/CommandFlowRunner.js +167 -0
- package/dist/cli/install/Phases.js +43 -0
- package/dist/index.js +118 -0
- package/dist/orchestrator/ProjectMetadata.js +183 -0
- package/dist/test_flow_run_cli.js +183 -0
- package/dist/test_host_uninstaller.js +12 -2
- package/dist/test_openlife_method_inventory.js +211 -0
- package/dist/test_workflow_e2e.js +10 -3
- package/dist-templates/claude-code/agents/openlife-atlas.md +12 -44
- package/dist-templates/claude-code/agents/openlife-builder.md +20 -0
- package/dist-templates/claude-code/agents/openlife-conductor.md +20 -0
- package/dist-templates/claude-code/agents/openlife-forge.md +12 -34
- package/dist-templates/claude-code/agents/openlife-genesis.md +12 -51
- package/dist-templates/claude-code/agents/openlife-lyra.md +12 -32
- package/dist-templates/claude-code/agents/openlife-maestro.md +27 -41
- package/dist-templates/claude-code/agents/openlife-mesh.md +20 -0
- package/dist-templates/claude-code/agents/openlife-prism.md +20 -0
- package/dist-templates/claude-code/agents/openlife-sentinel.md +20 -0
- package/dist-templates/claude-code/agents/openlife-steward.md +20 -0
- package/dist-templates/claude-code/agents/openlife-vortex.md +20 -0
- package/dist-templates/claude-code/commands/openlife/agents/atlas.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/builder.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/conductor.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/forge.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/genesis.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/lyra.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/maestro.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/mesh.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/prism.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/sentinel.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/steward.md +28 -0
- package/dist-templates/claude-code/commands/openlife/agents/vortex.md +28 -0
- package/dist-templates/claude-code/commands/openlife/ask.md +32 -9
- package/dist-templates/claude-code/commands/openlife/audit.md +43 -0
- package/dist-templates/claude-code/commands/openlife/doctor.md +9 -14
- package/dist-templates/claude-code/commands/openlife/dream.md +28 -13
- package/dist-templates/claude-code/commands/openlife/explore.md +32 -0
- package/dist-templates/claude-code/commands/openlife/flow/brownfield-discovery.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/brownfield-fullstack.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/brownfield-service.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/brownfield-ui.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/epic.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/greenfield-fullstack.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/greenfield-service.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/greenfield-ui.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/qa-loop.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/release.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/spec-pipeline.md +38 -0
- package/dist-templates/claude-code/commands/openlife/flow/story-cycle.md +38 -0
- package/dist-templates/claude-code/commands/openlife/health.md +37 -0
- package/dist-templates/claude-code/commands/openlife/plan.md +38 -0
- package/dist-templates/claude-code/commands/openlife/review.md +34 -0
- package/dist-templates/claude-code/commands/openlife/ship.md +35 -0
- package/dist-templates/claude-code/commands/openlife/start.md +38 -0
- package/dist-templates/claude-code/commands/openlife/status.md +8 -10
- package/dist-templates/claude-code/commands/openlife/story.md +34 -0
- package/dist-templates/codex/agents/openlife-atlas.md +12 -44
- package/dist-templates/codex/agents/openlife-builder.md +20 -0
- package/dist-templates/codex/agents/openlife-conductor.md +20 -0
- package/dist-templates/codex/agents/openlife-forge.md +12 -34
- package/dist-templates/codex/agents/openlife-genesis.md +12 -51
- package/dist-templates/codex/agents/openlife-lyra.md +12 -32
- package/dist-templates/codex/agents/openlife-maestro.md +27 -41
- package/dist-templates/codex/agents/openlife-mesh.md +20 -0
- package/dist-templates/codex/agents/openlife-prism.md +20 -0
- package/dist-templates/codex/agents/openlife-sentinel.md +20 -0
- package/dist-templates/codex/agents/openlife-steward.md +20 -0
- package/dist-templates/codex/agents/openlife-vortex.md +20 -0
- package/dist-templates/codex/commands/openlife/agents/atlas.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/builder.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/conductor.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/forge.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/genesis.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/lyra.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/maestro.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/mesh.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/prism.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/sentinel.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/steward.md +28 -0
- package/dist-templates/codex/commands/openlife/agents/vortex.md +28 -0
- package/dist-templates/codex/commands/openlife/ask.md +32 -9
- package/dist-templates/codex/commands/openlife/audit.md +43 -0
- package/dist-templates/codex/commands/openlife/doctor.md +9 -14
- package/dist-templates/codex/commands/openlife/dream.md +28 -13
- package/dist-templates/codex/commands/openlife/explore.md +32 -0
- package/dist-templates/codex/commands/openlife/flow/brownfield-discovery.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/brownfield-fullstack.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/brownfield-service.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/brownfield-ui.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/epic.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/greenfield-fullstack.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/greenfield-service.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/greenfield-ui.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/qa-loop.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/release.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/spec-pipeline.md +38 -0
- package/dist-templates/codex/commands/openlife/flow/story-cycle.md +38 -0
- package/dist-templates/codex/commands/openlife/health.md +37 -0
- package/dist-templates/codex/commands/openlife/plan.md +38 -0
- package/dist-templates/codex/commands/openlife/review.md +34 -0
- package/dist-templates/codex/commands/openlife/ship.md +35 -0
- package/dist-templates/codex/commands/openlife/start.md +38 -0
- package/dist-templates/codex/commands/openlife/status.md +8 -10
- package/dist-templates/codex/commands/openlife/story.md +34 -0
- package/dist-templates/gemini-cli/agents/openlife-atlas.md +12 -44
- package/dist-templates/gemini-cli/agents/openlife-builder.md +20 -0
- package/dist-templates/gemini-cli/agents/openlife-conductor.md +20 -0
- package/dist-templates/gemini-cli/agents/openlife-forge.md +12 -34
- package/dist-templates/gemini-cli/agents/openlife-genesis.md +12 -51
- package/dist-templates/gemini-cli/agents/openlife-lyra.md +12 -32
- package/dist-templates/gemini-cli/agents/openlife-maestro.md +27 -41
- package/dist-templates/gemini-cli/agents/openlife-mesh.md +20 -0
- package/dist-templates/gemini-cli/agents/openlife-prism.md +20 -0
- package/dist-templates/gemini-cli/agents/openlife-sentinel.md +20 -0
- package/dist-templates/gemini-cli/agents/openlife-steward.md +20 -0
- package/dist-templates/gemini-cli/agents/openlife-vortex.md +20 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/atlas.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/builder.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/conductor.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/forge.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/genesis.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/lyra.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/maestro.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/mesh.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/prism.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/sentinel.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/steward.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/agents/vortex.md +28 -0
- package/dist-templates/gemini-cli/commands/openlife/ask.md +32 -9
- package/dist-templates/gemini-cli/commands/openlife/audit.md +43 -0
- package/dist-templates/gemini-cli/commands/openlife/doctor.md +9 -14
- package/dist-templates/gemini-cli/commands/openlife/dream.md +28 -13
- package/dist-templates/gemini-cli/commands/openlife/explore.md +32 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-discovery.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-fullstack.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-service.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/brownfield-ui.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/epic.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/greenfield-fullstack.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/greenfield-service.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/greenfield-ui.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/qa-loop.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/release.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/spec-pipeline.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/flow/story-cycle.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/health.md +37 -0
- package/dist-templates/gemini-cli/commands/openlife/plan.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/review.md +34 -0
- package/dist-templates/gemini-cli/commands/openlife/ship.md +35 -0
- package/dist-templates/gemini-cli/commands/openlife/start.md +38 -0
- package/dist-templates/gemini-cli/commands/openlife/status.md +8 -10
- package/dist-templates/gemini-cli/commands/openlife/story.md +34 -0
- package/dist-templates/workflows/brownfield-fullstack.yaml +131 -0
- package/dist-templates/workflows/brownfield-service.yaml +111 -0
- package/dist-templates/workflows/brownfield-ui.yaml +115 -0
- package/dist-templates/workflows/continuous-deployment.yaml +139 -0
- package/dist-templates/workflows/epic-orchestration.yaml +101 -0
- package/dist-templates/workflows/greenfield-service.yaml +154 -0
- package/dist-templates/workflows/greenfield-ui.yaml +140 -0
- package/dist-templates/workflows/spec-pipeline.yaml +135 -0
- package/package.json +5 -2
- package/scripts/generate-slash-commands.js +395 -0
- 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
|
+
}
|