@polymorphism-tech/morph-spec 4.8.18 → 4.9.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 (138) hide show
  1. package/CLAUDE.md +98 -0
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +15 -56
  4. package/bin/task-manager.js +115 -14
  5. package/bin/validate.js +67 -33
  6. package/claude-plugin.json +1 -1
  7. package/docs/CHEATSHEET.md +201 -203
  8. package/docs/QUICKSTART.md +2 -2
  9. package/framework/CLAUDE.md +21 -0
  10. package/framework/agents.json +758 -164
  11. package/framework/hooks/claude-code/post-tool-use/context-refresh.js +1 -1
  12. package/framework/hooks/claude-code/post-tool-use/dispatch.js +2 -2
  13. package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +155 -0
  14. package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +1 -1
  15. package/framework/hooks/claude-code/session-start/inject-morph-context.js +71 -2
  16. package/framework/hooks/claude-code/statusline.py +76 -30
  17. package/framework/hooks/claude-code/user-prompt/set-terminal-title.js +14 -6
  18. package/framework/hooks/shared/activity-logger.js +0 -24
  19. package/framework/hooks/shared/phase-utils.js +3 -0
  20. package/framework/hooks/shared/skill-reminder-helpers.js +79 -0
  21. package/framework/hooks/shared/stale-task-reset.js +57 -0
  22. package/framework/hooks/shared/state-reader.js +2 -2
  23. package/framework/hooks/shared/worktree-helpers.js +53 -0
  24. package/framework/phases.json +40 -8
  25. package/framework/skills/level-0-meta/brainstorming/SKILL.md +1 -1
  26. package/framework/skills/level-0-meta/code-review/SKILL.md +1 -1
  27. package/framework/skills/level-0-meta/code-review-nextjs/SKILL.md +163 -163
  28. package/framework/skills/level-0-meta/frontend-review/SKILL.md +5 -5
  29. package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
  30. package/framework/skills/level-0-meta/morph-init/SKILL.md +5 -5
  31. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
  32. package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +1 -1
  33. package/framework/skills/level-0-meta/post-implementation/SKILL.md +59 -12
  34. package/framework/skills/level-0-meta/simulation-checklist/SKILL.md +1 -1
  35. package/framework/skills/level-0-meta/terminal-title/SKILL.md +1 -1
  36. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +1 -1
  37. package/framework/skills/level-0-meta/tool-usage-guide/references/tools-per-phase.md +6 -5
  38. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
  39. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +215 -189
  40. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +251 -251
  41. package/framework/skills/level-1-workflows/phase-design/SKILL.md +382 -365
  42. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +492 -450
  43. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +194 -190
  44. package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +270 -270
  45. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +285 -285
  46. package/framework/standards/STANDARDS.json +640 -88
  47. package/framework/standards/infrastructure/vercel/vercel-database.md +106 -0
  48. package/framework/templates/REGISTRY.json +1825 -1909
  49. package/framework/templates/context/CONTEXT-FEATURE.md +276 -276
  50. package/framework/templates/docs/onboarding.md +1 -5
  51. package/framework/workflows/configs/nodejs-cli.json +40 -0
  52. package/package.json +2 -6
  53. package/src/commands/agents/dispatch-agents.js +55 -4
  54. package/src/commands/project/doctor.js +16 -47
  55. package/src/commands/project/init.js +1 -1
  56. package/src/commands/project/status.js +2 -2
  57. package/src/commands/project/update.js +381 -365
  58. package/src/commands/project/worktree.js +154 -0
  59. package/src/commands/state/advance-phase.js +120 -30
  60. package/src/commands/state/approve.js +2 -2
  61. package/src/commands/state/index.js +7 -8
  62. package/src/commands/state/phase-runner.js +1 -1
  63. package/src/commands/state/state.js +61 -6
  64. package/src/commands/tasks/task.js +78 -99
  65. package/src/commands/templates/template-render.js +93 -173
  66. package/src/commands/trust/trust.js +26 -21
  67. package/src/core/paths/output-schema.js +15 -0
  68. package/src/core/state/state-manager.js +28 -54
  69. package/src/core/workflows/workflow-detector.js +9 -87
  70. package/src/lib/phase-chain/phase-validator.js +330 -0
  71. package/src/lib/stack/stack-profile.js +88 -0
  72. package/src/lib/tasks/task-classifier.js +16 -0
  73. package/src/lib/tasks/test-runner.js +77 -0
  74. package/src/lib/trust/trust-manager.js +32 -144
  75. package/src/lib/validators/spec-validator.js +58 -4
  76. package/src/lib/validators/validation-runner.js +23 -11
  77. package/src/scripts/setup-infra.js +240 -224
  78. package/src/utils/agents-installer.js +2 -2
  79. package/src/utils/banner.js +1 -1
  80. package/src/utils/claude-settings-manager.js +1 -1
  81. package/src/utils/file-copier.js +1 -0
  82. package/src/utils/hooks-installer.js +258 -8
  83. package/framework/hooks/dev/check-sync-health.js +0 -117
  84. package/framework/hooks/dev/guard-version-numbers.js +0 -57
  85. package/framework/hooks/dev/sync-standards-registry.js +0 -60
  86. package/framework/hooks/dev/sync-template-registry.js +0 -60
  87. package/framework/hooks/dev/validate-skill-format.js +0 -70
  88. package/framework/hooks/dev/validate-standard-format.js +0 -73
  89. package/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
  90. package/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
  91. package/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
  92. package/framework/workflows/configs/design-impl.json +0 -49
  93. package/framework/workflows/configs/express.json +0 -45
  94. package/framework/workflows/configs/fast-track.json +0 -42
  95. package/framework/workflows/configs/full-morph.json +0 -79
  96. package/framework/workflows/configs/fusion.json +0 -39
  97. package/framework/workflows/configs/long-running.json +0 -33
  98. package/framework/workflows/configs/spec-only.json +0 -43
  99. package/framework/workflows/configs/ui-refresh.json +0 -49
  100. package/framework/workflows/configs/zero-touch.json +0 -82
  101. package/src/commands/project/monitor.js +0 -295
  102. package/src/commands/project/tutorial.js +0 -115
  103. package/src/commands/state/validate-phase.js +0 -238
  104. package/src/commands/templates/generate-contracts.js +0 -445
  105. package/src/core/orchestrator.js +0 -171
  106. package/src/core/registry/command-registry.js +0 -28
  107. package/src/core/registry/index.js +0 -8
  108. package/src/core/registry/validator-registry.js +0 -204
  109. package/src/core/templates/template-validator.js +0 -296
  110. package/src/generator/config-generator.js +0 -206
  111. package/src/generator/templates/config.json.template +0 -40
  112. package/src/generator/templates/project.md.template +0 -67
  113. package/src/lib/agents/micro-agent-factory.js +0 -161
  114. package/src/lib/analysis/complexity-analyzer.js +0 -441
  115. package/src/lib/analysis/index.js +0 -7
  116. package/src/lib/analytics/analytics-engine.js +0 -345
  117. package/src/lib/checkpoints/checkpoint-hooks.js +0 -298
  118. package/src/lib/checkpoints/index.js +0 -7
  119. package/src/lib/context/context-bundler.js +0 -241
  120. package/src/lib/context/context-optimizer.js +0 -212
  121. package/src/lib/context/context-tracker.js +0 -273
  122. package/src/lib/context/core-four-tracker.js +0 -201
  123. package/src/lib/context/mcp-optimizer.js +0 -200
  124. package/src/lib/execution/fusion-executor.js +0 -304
  125. package/src/lib/execution/parallel-executor.js +0 -270
  126. package/src/lib/hooks/stop-hook-executor.js +0 -286
  127. package/src/lib/hops/hop-composer.js +0 -221
  128. package/src/lib/phase-chain/eligibility-checker.js +0 -243
  129. package/src/lib/threads/thread-coordinator.js +0 -238
  130. package/src/lib/threads/thread-manager.js +0 -317
  131. package/src/lib/tracking/artifact-trail.js +0 -202
  132. package/src/scanner/project-scanner.js +0 -242
  133. package/src/ui/diff-display.js +0 -91
  134. package/src/ui/interactive-wizard.js +0 -96
  135. package/src/ui/user-review.js +0 -211
  136. package/src/ui/wizard-questions.js +0 -188
  137. package/src/utils/color-utils.js +0 -70
  138. package/src/utils/process-handler.js +0 -97
@@ -1,82 +0,0 @@
1
- {
2
- "id": "zero-touch",
3
- "name": "Zero-Touch Execution",
4
- "description": "Fully autonomous execution with auto-approval gates. Requires maximum trust level (>95% checkpoint pass rate).",
5
- "version": "3.0.0",
6
-
7
- "eligibility": {
8
- "trustLevel": "maximum",
9
- "minCheckpoints": 10,
10
- "minPassRate": 0.95,
11
- "requiredPhases": ["proposal", "design", "tasks"],
12
- "blockedIfHas": ["manual_override_pending", "escalation_required"]
13
- },
14
-
15
- "autoApproval": {
16
- "design": true,
17
- "tasks": true,
18
- "proposal": true,
19
- "enabled": true,
20
- "auditLog": true
21
- },
22
-
23
- "autoCommit": {
24
- "enabled": true,
25
- "convention": "conventional-commits",
26
- "signOff": "morph-spec-agent",
27
- "requirePassingCheckpoints": true
28
- },
29
-
30
- "rollback": {
31
- "enabled": true,
32
- "onCheckpointFailure": true,
33
- "strategy": "git-revert",
34
- "maxRollbackDepth": 3
35
- },
36
-
37
- "escalation": {
38
- "triggers": [
39
- "checkpoint_failed_3_times",
40
- "architecture_error",
41
- "security_error",
42
- "circular_dependency_detected",
43
- "out_of_scope_change"
44
- ],
45
- "action": "pause_and_notify"
46
- },
47
-
48
- "phases": {
49
- "run": ["proposal", "design", "clarify", "tasks", "implement", "sync"],
50
- "skip": ["uiux"],
51
- "pauses": []
52
- },
53
-
54
- "monitoring": {
55
- "checkpointFrequency": 3,
56
- "stopHooks": {
57
- "enabled": true,
58
- "interval": 30,
59
- "hooks": ["validate-and-continue", "validate-checkpoints"]
60
- },
61
- "analyticsTracking": true
62
- },
63
-
64
- "restrictions": {
65
- "maxFilesPerSession": 50,
66
- "noInfraChanges": false,
67
- "noDatabaseMigrations": false,
68
- "requireHumanForBreakingChanges": true,
69
- "requireHumanForSchemaChanges": false
70
- },
71
-
72
- "phaseChain": {
73
- "enabled": true,
74
- "pauseOn": ["blocked_tasks", "escalation_required", "low_pass_rate"],
75
- "continueOn": ["missing_optional_outputs"],
76
- "maxAutoPhases": 6
77
- },
78
-
79
- "keywords": ["zero-touch", "autonomous", "fully automated", "hands-off", "auto-pilot"],
80
-
81
- "priority": 5
82
- }
@@ -1,295 +0,0 @@
1
- /**
2
- * morph-spec monitor — Live TUI Dashboard
3
- *
4
- * Opens a live-updating terminal UI showing:
5
- * - Active agents by tier
6
- * - Hook events (chronological feed)
7
- * - Skills invoked this session
8
- * - Rules in effect
9
- * - Overview summary
10
- *
11
- * Reads .morph/logs/activity.json (written by hooks via activity-logger.js).
12
- * Uses fs.watch for live updates (no polling, no chokidar).
13
- *
14
- * Usage:
15
- * morph-spec monitor [feature]
16
- * morph-spec monitor --compact
17
- * morph-spec monitor --mode hooks
18
- */
19
-
20
- import { watch, existsSync, readFileSync, readdirSync, statSync } from 'fs';
21
- import { join, basename } from 'path';
22
- import chalk from 'chalk';
23
-
24
- import {
25
- renderBox,
26
- renderFeed,
27
- renderAgents,
28
- renderSkills,
29
- renderRules,
30
- renderOverview,
31
- renderStatusBar,
32
- renderHeader,
33
- } from '../../lib/monitor/renderer.js';
34
-
35
- import { getActiveAgents } from '../../lib/monitor/agent-resolver.js';
36
- import { readActivity } from '../../../framework/hooks/shared/activity-logger.js';
37
- import { loadState, getActiveFeature, derivePhaseForFeature } from '../../../framework/hooks/shared/state-reader.js';
38
-
39
- const MODES = ['overview', 'hooks', 'agents', 'skills', 'rules'];
40
- const ACTIVITY_FILE = '.morph/logs/activity.json';
41
- const RULES_DIR_PROJECT = '.claude/rules';
42
- const RULES_DIR_FRAMEWORK = '.morph/framework/rules';
43
-
44
- // ─────────────────────────────────────────────────────────
45
- // Rules loading
46
- // ─────────────────────────────────────────────────────────
47
-
48
- function loadRules(cwd) {
49
- const rules = [];
50
- const dirs = [
51
- join(cwd, RULES_DIR_PROJECT),
52
- join(cwd, RULES_DIR_FRAMEWORK),
53
- join(cwd, 'framework/rules'),
54
- ];
55
-
56
- for (const dir of dirs) {
57
- if (!existsSync(dir)) continue;
58
- try {
59
- const files = readdirSync(dir).filter(f => f.endsWith('.md'));
60
- for (const file of files) {
61
- // Parse front-matter paths glob if present
62
- let glob = '*';
63
- try {
64
- const content = readFileSync(join(dir, file), 'utf-8');
65
- const match = content.match(/paths:\s*\n((?:\s*-\s*.+\n?)+)/);
66
- if (match) {
67
- const paths = match[1].match(/- (.+)/g);
68
- if (paths) glob = paths.map(p => p.replace('- ', '').trim()).join(', ');
69
- }
70
- } catch { /* skip */ }
71
- rules.push({ name: basename(file, '.md'), glob });
72
- }
73
- } catch { /* skip */ }
74
- }
75
- return rules;
76
- }
77
-
78
- // ─────────────────────────────────────────────────────────
79
- // Available skills loading
80
- // ─────────────────────────────────────────────────────────
81
-
82
- function loadAvailableSkills(cwd) {
83
- const skillDirs = [
84
- join(cwd, '.claude/skills'),
85
- join(cwd, 'framework/skills'),
86
- ];
87
- const names = [];
88
- for (const dir of skillDirs) {
89
- if (!existsSync(dir)) continue;
90
- try {
91
- const entries = readdirSync(dir, { withFileTypes: true });
92
- for (const entry of entries) {
93
- if (entry.isDirectory()) {
94
- // Level-N-meta/skill-name or direct skill dirs
95
- const sub = readdirSync(join(dir, entry.name), { withFileTypes: true });
96
- for (const s of sub) {
97
- if (s.isDirectory()) names.push(s.name);
98
- }
99
- }
100
- }
101
- } catch { /* skip */ }
102
- }
103
- return [...new Set(names)];
104
- }
105
-
106
- // ─────────────────────────────────────────────────────────
107
- // Screen rendering
108
- // ─────────────────────────────────────────────────────────
109
-
110
- function render(state) {
111
- const { feature, phase, tasks, agentsByTier, activity, rules, availableSkills, mode, compact } = state;
112
-
113
- const hooks = activity?.hooks || [];
114
- const skills = activity?.skills || [];
115
-
116
- // Clear screen
117
- process.stdout.write('\x1Bc');
118
-
119
- // Header
120
- process.stdout.write(renderHeader(feature, phase, tasks) + '\n');
121
-
122
- if (compact) {
123
- // Compact: just show overview
124
- const overviewData = { feature, phase, agentsByTier, hooks, skills, rules };
125
- process.stdout.write(renderOverview(overviewData) + '\n');
126
- } else {
127
- switch (mode) {
128
- case 'hooks':
129
- process.stdout.write(renderFeed(hooks) + '\n');
130
- break;
131
-
132
- case 'agents':
133
- process.stdout.write(renderAgents(agentsByTier, phase) + '\n');
134
- break;
135
-
136
- case 'skills':
137
- process.stdout.write(renderSkills(skills, availableSkills) + '\n');
138
- break;
139
-
140
- case 'rules':
141
- process.stdout.write(renderRules(rules) + '\n');
142
- break;
143
-
144
- case 'overview':
145
- default: {
146
- const overviewData = { feature, phase, agentsByTier, hooks, skills, rules };
147
- process.stdout.write(renderOverview(overviewData) + '\n');
148
- break;
149
- }
150
- }
151
- }
152
-
153
- // Status bar
154
- process.stdout.write(renderStatusBar(mode, MODES) + '\n');
155
- }
156
-
157
- // ─────────────────────────────────────────────────────────
158
- // State loading
159
- // ─────────────────────────────────────────────────────────
160
-
161
- function loadMonitorState(cwd, featureArg) {
162
- let feature = featureArg || '';
163
- let phase = '';
164
- let tasks = null;
165
-
166
- try {
167
- const morphState = loadState(cwd);
168
- if (!feature && morphState) {
169
- const active = getActiveFeature(cwd);
170
- if (active) {
171
- feature = active.name;
172
- tasks = active.feature.tasks || null;
173
- }
174
- }
175
- if (feature) {
176
- phase = derivePhaseForFeature(feature, cwd);
177
- }
178
- } catch { /* fail-open */ }
179
-
180
- const agentsByTier = getActiveAgents(cwd, phase);
181
- const activity = readActivity(cwd);
182
- const rules = loadRules(cwd);
183
- const availableSkills = loadAvailableSkills(cwd);
184
-
185
- return { feature, phase, tasks, agentsByTier, activity, rules, availableSkills };
186
- }
187
-
188
- // ─────────────────────────────────────────────────────────
189
- // Main command
190
- // ─────────────────────────────────────────────────────────
191
-
192
- /**
193
- * @param {string|undefined} featureArg
194
- * @param {{ compact: boolean, mode: string }} opts
195
- */
196
- export function monitorCommand(featureArg, opts = {}) {
197
- const cwd = process.cwd();
198
- const compact = !!opts.compact;
199
- const startMode = MODES.includes(opts.mode) ? opts.mode : 'overview';
200
-
201
- let modeIndex = MODES.indexOf(startMode);
202
- let currentMode = startMode;
203
-
204
- // Initial render
205
- let monitorState = loadMonitorState(cwd, featureArg);
206
- render({ ...monitorState, mode: currentMode, compact });
207
-
208
- // Watch activity.json for changes
209
- const activityPath = join(cwd, ACTIVITY_FILE);
210
- let watcher = null;
211
-
212
- function startWatcher() {
213
- if (!existsSync(activityPath)) {
214
- // Retry watch setup when file is created
215
- setTimeout(startWatcher, 2000);
216
- return;
217
- }
218
-
219
- try {
220
- watcher = watch(activityPath, { persistent: true }, () => {
221
- try {
222
- monitorState = loadMonitorState(cwd, featureArg);
223
- render({ ...monitorState, mode: currentMode, compact });
224
- } catch { /* fail-open */ }
225
- });
226
- } catch {
227
- // fs.watch not supported — fall back to polling
228
- setInterval(() => {
229
- try {
230
- monitorState = loadMonitorState(cwd, featureArg);
231
- render({ ...monitorState, mode: currentMode, compact });
232
- } catch { /* fail-open */ }
233
- }, 2000);
234
- }
235
- }
236
-
237
- startWatcher();
238
-
239
- // Keyboard input: raw mode
240
- if (process.stdin.isTTY) {
241
- process.stdin.setRawMode(true);
242
- process.stdin.resume();
243
- process.stdin.setEncoding('utf8');
244
-
245
- process.stdin.on('data', (key) => {
246
- // q or Ctrl-C → quit
247
- if (key === 'q' || key === '\u0003') {
248
- if (watcher) watcher.close();
249
- process.stdin.setRawMode(false);
250
- process.stdout.write('\n' + chalk.gray('morph-spec monitor closed.\n'));
251
- process.exit(0);
252
- }
253
-
254
- // shift+tab → cycle modes (forward)
255
- // \x1b[Z is the standard escape for shift+tab
256
- if (key === '\x1b[Z' || key === '\t') {
257
- modeIndex = (modeIndex + 1) % MODES.length;
258
- currentMode = MODES[modeIndex];
259
- render({ ...monitorState, mode: currentMode, compact });
260
- }
261
-
262
- // Arrow keys: left/right also cycle
263
- if (key === '\x1b[C') { // right arrow
264
- modeIndex = (modeIndex + 1) % MODES.length;
265
- currentMode = MODES[modeIndex];
266
- render({ ...monitorState, mode: currentMode, compact });
267
- }
268
- if (key === '\x1b[D') { // left arrow
269
- modeIndex = (modeIndex - 1 + MODES.length) % MODES.length;
270
- currentMode = MODES[modeIndex];
271
- render({ ...monitorState, mode: currentMode, compact });
272
- }
273
-
274
- // r → force refresh
275
- if (key === 'r') {
276
- monitorState = loadMonitorState(cwd, featureArg);
277
- render({ ...monitorState, mode: currentMode, compact });
278
- }
279
- });
280
- } else {
281
- // Non-TTY: just render once and exit (useful for scripting/piping)
282
- process.stdout.write('\n' + chalk.gray('(non-interactive mode — run in a real terminal for live updates)\n'));
283
- }
284
-
285
- // Handle process signals
286
- process.on('SIGINT', () => {
287
- if (watcher) watcher.close();
288
- process.stdout.write('\n' + chalk.gray('morph-spec monitor closed.\n'));
289
- process.exit(0);
290
- });
291
- process.on('SIGTERM', () => {
292
- if (watcher) watcher.close();
293
- process.exit(0);
294
- });
295
- }
@@ -1,115 +0,0 @@
1
- /**
2
- * Tutorial Command
3
- *
4
- * Prints the MORPH-SPEC workflow pipeline and getting-started steps.
5
- * Pure stdout — no file I/O, no network, no side effects.
6
- *
7
- * Usage: morph-spec tutorial
8
- */
9
-
10
- import chalk from 'chalk';
11
-
12
- const PHASES = [
13
- {
14
- label: 'FASE 0 · PROPOSAL',
15
- what: 'Captures user story + acceptance criteria.',
16
- produces: '0-proposal/proposal.md',
17
- how: '/morph-proposal <feature> (in Claude Code)',
18
- },
19
- {
20
- label: 'FASE 1 · SETUP',
21
- what: 'Detects stack, activates agents, confirms environment.',
22
- produces: '.morph/state.json initialized',
23
- how: 'auto-triggered inside /morph-proposal',
24
- },
25
- {
26
- label: 'FASE 1.5 · UI/UX',
27
- what: 'Design system, mockups, component specs, user flows.',
28
- produces: '2-ui/{design-system,mockups,components,flows}.md',
29
- how: '/phase-uiux <feature> (in Claude Code)',
30
- optional: true,
31
- },
32
- {
33
- label: 'FASE 2 · DESIGN',
34
- what: 'Technical spec + C# contracts + architecture decisions.',
35
- produces: '1-design/{spec.md, contracts-level{N}.cs, decisions.md}',
36
- how: '/phase-design <feature> (in Claude Code)',
37
- },
38
- {
39
- label: 'FASE 3 · CLARIFY',
40
- what: 'Reviews spec for ambiguities, adds edge cases.',
41
- produces: '1-design/spec.md (updated with clarifications)',
42
- how: '/phase-clarify <feature> (in Claude Code)',
43
- },
44
- {
45
- label: 'FASE 4 · TASKS',
46
- what: 'Atomic task breakdown, DDD-aware.',
47
- produces: '3-tasks/tasks.md',
48
- how: 'auto-generated during /morph-proposal, or /phase-tasks <feature>',
49
- },
50
- {
51
- label: 'FASE 5 · IMPLEMENT',
52
- what: 'Code implementation with checkpoints every 3 tasks.',
53
- produces: '4-implement/recap.md + source code',
54
- how: '/morph-apply <feature> (in Claude Code)',
55
- },
56
- {
57
- label: 'FASE 6 · SYNC',
58
- what: 'Syncs decisions back to project standards.',
59
- produces: '.morph/framework/standards/ (updated)',
60
- how: 'morph-spec sync <feature>',
61
- optional: true,
62
- },
63
- ];
64
-
65
- const SEP = chalk.dim('─'.repeat(58));
66
-
67
- export function tutorialCommand() {
68
- console.log('');
69
- console.log(chalk.cyan.bold(' MORPH-SPEC Workflow Tutorial'));
70
- console.log(SEP);
71
- console.log('');
72
- console.log(
73
- chalk.white(
74
- ' MORPH-SPEC is spec-first: every feature goes through phases\n' +
75
- ' before any code is written. Each phase produces structured\n' +
76
- ' outputs that feed the next.'
77
- )
78
- );
79
- console.log('');
80
- console.log(SEP);
81
- console.log(chalk.cyan.bold(' PIPELINE'));
82
- console.log(SEP);
83
- console.log('');
84
- console.log(
85
- chalk.white(' proposal → setup → ') +
86
- chalk.dim('[uiux]') +
87
- chalk.white(' → design → clarify → tasks → implement → ') +
88
- chalk.dim('[sync]')
89
- );
90
- console.log(chalk.dim(' (phases in brackets are optional)'));
91
- console.log('');
92
-
93
- for (const phase of PHASES) {
94
- console.log(SEP);
95
- const label = phase.optional
96
- ? chalk.cyan.bold(` ${phase.label}`) + chalk.dim(' [optional]')
97
- : chalk.cyan.bold(` ${phase.label}`);
98
- console.log(label);
99
- console.log(chalk.white(` What: ${phase.what}`));
100
- console.log(chalk.dim(` Produces: ${phase.produces}`));
101
- console.log(chalk.green(` How: ${phase.how}`));
102
- console.log('');
103
- }
104
-
105
- console.log(SEP);
106
- console.log(chalk.cyan.bold(' GETTING STARTED'));
107
- console.log(SEP);
108
- console.log('');
109
- console.log(chalk.white(' 1. Open Claude Code in your project'));
110
- console.log(chalk.white(' 2. Run: ') + chalk.green('/morph-proposal <your-feature-name>'));
111
- console.log(chalk.white(' 3. Answer the questions — morph-spec handles the rest'));
112
- console.log('');
113
- console.log(chalk.dim(' Tip: run `morph-spec doctor` to verify your installation first.'));
114
- console.log('');
115
- }