@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.
- package/CLAUDE.md +98 -0
- package/README.md +2 -2
- package/bin/morph-spec.js +15 -56
- package/bin/task-manager.js +115 -14
- package/bin/validate.js +67 -33
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +201 -203
- package/docs/QUICKSTART.md +2 -2
- package/framework/CLAUDE.md +21 -0
- package/framework/agents.json +758 -164
- package/framework/hooks/claude-code/post-tool-use/context-refresh.js +1 -1
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +2 -2
- package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +155 -0
- package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +1 -1
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +71 -2
- package/framework/hooks/claude-code/statusline.py +76 -30
- package/framework/hooks/claude-code/user-prompt/set-terminal-title.js +14 -6
- package/framework/hooks/shared/activity-logger.js +0 -24
- package/framework/hooks/shared/phase-utils.js +3 -0
- package/framework/hooks/shared/skill-reminder-helpers.js +79 -0
- package/framework/hooks/shared/stale-task-reset.js +57 -0
- package/framework/hooks/shared/state-reader.js +2 -2
- package/framework/hooks/shared/worktree-helpers.js +53 -0
- package/framework/phases.json +40 -8
- package/framework/skills/level-0-meta/brainstorming/SKILL.md +1 -1
- package/framework/skills/level-0-meta/code-review/SKILL.md +1 -1
- package/framework/skills/level-0-meta/code-review-nextjs/SKILL.md +163 -163
- package/framework/skills/level-0-meta/frontend-review/SKILL.md +5 -5
- package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
- package/framework/skills/level-0-meta/morph-init/SKILL.md +5 -5
- package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
- package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +1 -1
- package/framework/skills/level-0-meta/post-implementation/SKILL.md +59 -12
- package/framework/skills/level-0-meta/simulation-checklist/SKILL.md +1 -1
- package/framework/skills/level-0-meta/terminal-title/SKILL.md +1 -1
- package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +1 -1
- package/framework/skills/level-0-meta/tool-usage-guide/references/tools-per-phase.md +6 -5
- package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +215 -189
- package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +251 -251
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +382 -365
- package/framework/skills/level-1-workflows/phase-implement/SKILL.md +492 -450
- package/framework/skills/level-1-workflows/phase-setup/SKILL.md +194 -190
- package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +270 -270
- package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +285 -285
- package/framework/standards/STANDARDS.json +640 -88
- package/framework/standards/infrastructure/vercel/vercel-database.md +106 -0
- package/framework/templates/REGISTRY.json +1825 -1909
- package/framework/templates/context/CONTEXT-FEATURE.md +276 -276
- package/framework/templates/docs/onboarding.md +1 -5
- package/framework/workflows/configs/nodejs-cli.json +40 -0
- package/package.json +2 -6
- package/src/commands/agents/dispatch-agents.js +55 -4
- package/src/commands/project/doctor.js +16 -47
- package/src/commands/project/init.js +1 -1
- package/src/commands/project/status.js +2 -2
- package/src/commands/project/update.js +381 -365
- package/src/commands/project/worktree.js +154 -0
- package/src/commands/state/advance-phase.js +120 -30
- package/src/commands/state/approve.js +2 -2
- package/src/commands/state/index.js +7 -8
- package/src/commands/state/phase-runner.js +1 -1
- package/src/commands/state/state.js +61 -6
- package/src/commands/tasks/task.js +78 -99
- package/src/commands/templates/template-render.js +93 -173
- package/src/commands/trust/trust.js +26 -21
- package/src/core/paths/output-schema.js +15 -0
- package/src/core/state/state-manager.js +28 -54
- package/src/core/workflows/workflow-detector.js +9 -87
- package/src/lib/phase-chain/phase-validator.js +330 -0
- package/src/lib/stack/stack-profile.js +88 -0
- package/src/lib/tasks/task-classifier.js +16 -0
- package/src/lib/tasks/test-runner.js +77 -0
- package/src/lib/trust/trust-manager.js +32 -144
- package/src/lib/validators/spec-validator.js +58 -4
- package/src/lib/validators/validation-runner.js +23 -11
- package/src/scripts/setup-infra.js +240 -224
- package/src/utils/agents-installer.js +2 -2
- package/src/utils/banner.js +1 -1
- package/src/utils/claude-settings-manager.js +1 -1
- package/src/utils/file-copier.js +1 -0
- package/src/utils/hooks-installer.js +258 -8
- package/framework/hooks/dev/check-sync-health.js +0 -117
- package/framework/hooks/dev/guard-version-numbers.js +0 -57
- package/framework/hooks/dev/sync-standards-registry.js +0 -60
- package/framework/hooks/dev/sync-template-registry.js +0 -60
- package/framework/hooks/dev/validate-skill-format.js +0 -70
- package/framework/hooks/dev/validate-standard-format.js +0 -73
- package/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
- package/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
- package/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
- package/framework/workflows/configs/design-impl.json +0 -49
- package/framework/workflows/configs/express.json +0 -45
- package/framework/workflows/configs/fast-track.json +0 -42
- package/framework/workflows/configs/full-morph.json +0 -79
- package/framework/workflows/configs/fusion.json +0 -39
- package/framework/workflows/configs/long-running.json +0 -33
- package/framework/workflows/configs/spec-only.json +0 -43
- package/framework/workflows/configs/ui-refresh.json +0 -49
- package/framework/workflows/configs/zero-touch.json +0 -82
- package/src/commands/project/monitor.js +0 -295
- package/src/commands/project/tutorial.js +0 -115
- package/src/commands/state/validate-phase.js +0 -238
- package/src/commands/templates/generate-contracts.js +0 -445
- package/src/core/orchestrator.js +0 -171
- package/src/core/registry/command-registry.js +0 -28
- package/src/core/registry/index.js +0 -8
- package/src/core/registry/validator-registry.js +0 -204
- package/src/core/templates/template-validator.js +0 -296
- package/src/generator/config-generator.js +0 -206
- package/src/generator/templates/config.json.template +0 -40
- package/src/generator/templates/project.md.template +0 -67
- package/src/lib/agents/micro-agent-factory.js +0 -161
- package/src/lib/analysis/complexity-analyzer.js +0 -441
- package/src/lib/analysis/index.js +0 -7
- package/src/lib/analytics/analytics-engine.js +0 -345
- package/src/lib/checkpoints/checkpoint-hooks.js +0 -298
- package/src/lib/checkpoints/index.js +0 -7
- package/src/lib/context/context-bundler.js +0 -241
- package/src/lib/context/context-optimizer.js +0 -212
- package/src/lib/context/context-tracker.js +0 -273
- package/src/lib/context/core-four-tracker.js +0 -201
- package/src/lib/context/mcp-optimizer.js +0 -200
- package/src/lib/execution/fusion-executor.js +0 -304
- package/src/lib/execution/parallel-executor.js +0 -270
- package/src/lib/hooks/stop-hook-executor.js +0 -286
- package/src/lib/hops/hop-composer.js +0 -221
- package/src/lib/phase-chain/eligibility-checker.js +0 -243
- package/src/lib/threads/thread-coordinator.js +0 -238
- package/src/lib/threads/thread-manager.js +0 -317
- package/src/lib/tracking/artifact-trail.js +0 -202
- package/src/scanner/project-scanner.js +0 -242
- package/src/ui/diff-display.js +0 -91
- package/src/ui/interactive-wizard.js +0 -96
- package/src/ui/user-review.js +0 -211
- package/src/ui/wizard-questions.js +0 -188
- package/src/utils/color-utils.js +0 -70
- 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
|
-
}
|