@polymorphism-tech/morph-spec 4.8.1 → 4.8.4

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 (44) hide show
  1. package/README.md +2 -2
  2. package/claude-plugin.json +1 -1
  3. package/docs/CHEATSHEET.md +1 -1
  4. package/docs/QUICKSTART.md +1 -1
  5. package/framework/hooks/dev/guard-version-numbers.js +1 -1
  6. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +1 -1
  7. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +1 -1
  8. package/framework/skills/level-1-workflows/phase-design/SKILL.md +1 -1
  9. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +1 -1
  10. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +1 -1
  11. package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +1 -1
  12. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +1 -1
  13. package/package.json +4 -4
  14. package/.morph/analytics/threads-log.jsonl +0 -54
  15. package/.morph/state.json +0 -198
  16. package/docs/ARCHITECTURE.md +0 -328
  17. package/docs/COMMAND-FLOWS.md +0 -398
  18. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +0 -514
  19. package/docs/plans/2026-02-22-claude-settings.md +0 -517
  20. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +0 -730
  21. package/docs/plans/2026-02-22-morph-spec-next.md +0 -480
  22. package/docs/plans/2026-02-22-native-alignment-design.md +0 -201
  23. package/docs/plans/2026-02-22-native-alignment-impl.md +0 -927
  24. package/docs/plans/2026-02-22-native-enrichment-design.md +0 -246
  25. package/docs/plans/2026-02-22-native-enrichment.md +0 -737
  26. package/docs/plans/2026-02-23-ddd-architecture-refactor.md +0 -1155
  27. package/docs/plans/2026-02-23-ddd-nextsteps.md +0 -684
  28. package/docs/plans/2026-02-23-infra-architect-refactor.md +0 -439
  29. package/docs/plans/2026-02-23-nextjs-code-review-design.md +0 -157
  30. package/docs/plans/2026-02-23-nextjs-code-review-impl.md +0 -1256
  31. package/docs/plans/2026-02-23-nextjs-standards-design.md +0 -150
  32. package/docs/plans/2026-02-23-nextjs-standards-impl.md +0 -1848
  33. package/docs/plans/2026-02-24-cli-radical-simplification.md +0 -592
  34. package/docs/plans/2026-02-24-framework-failure-points.md +0 -125
  35. package/docs/plans/2026-02-24-morph-init-design.md +0 -337
  36. package/docs/plans/2026-02-24-morph-init-impl.md +0 -1269
  37. package/docs/plans/2026-02-24-tutorial-command-design.md +0 -71
  38. package/docs/plans/2026-02-24-tutorial-command.md +0 -298
  39. package/scripts/bump-version.js +0 -248
  40. package/scripts/generate-refs.js +0 -336
  41. package/scripts/generate-standards-registry.js +0 -44
  42. package/scripts/install-dev-hooks.js +0 -138
  43. package/scripts/scan-nextjs.mjs +0 -169
  44. package/scripts/validate-real.mjs +0 -255
@@ -1,480 +0,0 @@
1
- # morph-spec-next Implementation Plan
2
-
3
- **Status:** COMPLETE
4
-
5
- > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
6
-
7
- **Goal:** Close the remaining gaps left after Claude Code Native Alignment Rounds 1 & 2 — specifically: make `morph-spec update` sync all Claude-native artifacts introduced in recent rounds, add `.claude/rules/` and `.claude/agents/` health checks to `doctor`, and bump the version to 4.4.0 to signal the alignment work to users.
8
-
9
- **Architecture:** Four focused changes to existing files. No new files created. All changes are additive within the existing command/utility patterns. Tests follow the established pattern of testing utility functions directly (not interactive CLI commands).
10
-
11
- **Tech Stack:** Node.js ESM, `fs-extra`, existing `installSkills` / `installAgents` utilities, `node:test`
12
-
13
- ---
14
-
15
- ## Background: What update.js is missing
16
-
17
- `morph-spec update` currently:
18
- - Cleans the entire `.claude/` directory (`cleanFrameworkDirs` line 62)
19
- - Rebuilds: commands, skills (manual junction-linking), hooks, CLAUDE.md (via `copyDirectory` — bug)
20
- - **Missing:** flat skills (`installSkills`), agents (`installAgents`), rules copy, `CLAUDE_runtime.md` copy
21
-
22
- Also: line 311 calls `copyDirectory(claudeMdSrc, claudeMdDest)` on a single FILE — should be `copyFile`.
23
-
24
- ---
25
-
26
- ## Task 1: Fix update.js — imports + copyFile bug
27
-
28
- **Files:**
29
- - Modify: `src/commands/project/update.js`
30
-
31
- **Step 1: Add missing imports**
32
-
33
- At the top of `update.js`, after the existing `import { installClaudeHooks }` line (line 29), add:
34
-
35
- ```javascript
36
- import { installSkills } from '../../utils/skills-installer.js';
37
- import { installAgents } from '../../utils/agents-installer.js';
38
- ```
39
-
40
- **Step 2: Fix the copyDirectory → copyFile bug on CLAUDE.md**
41
-
42
- Find this block (around line 307–311):
43
- ```javascript
44
- // Update CLAUDE.md
45
- updateSpinner.text = 'Updating CLAUDE.md...';
46
- const claudeMdSrc = join(contentDir, 'CLAUDE.md');
47
- const claudeMdDest = join(targetPath, 'CLAUDE.md');
48
- await copyDirectory(claudeMdSrc, claudeMdDest);
49
- ```
50
-
51
- Replace `copyDirectory` with `copyFile`:
52
- ```javascript
53
- // Update CLAUDE.md
54
- updateSpinner.text = 'Updating CLAUDE.md...';
55
- const claudeMdSrc = join(contentDir, 'framework', 'CLAUDE.md');
56
- const claudeMdDest = join(targetPath, 'CLAUDE.md');
57
- await copyFile(claudeMdSrc, claudeMdDest);
58
- ```
59
-
60
- Note: `contentDir` is the framework root (returned by `getContentDir()`), so `CLAUDE.md` is at `join(contentDir, 'framework', 'CLAUDE.md')`.
61
-
62
- **Step 3: Run the existing update-related tests to confirm nothing broke**
63
-
64
- ```bash
65
- npm test -- test/commands/init.test.js
66
- ```
67
-
68
- Expected: 16 pass, 0 fail.
69
-
70
- **Step 4: Commit**
71
-
72
- ```bash
73
- git add src/commands/project/update.js
74
- git commit -m "fix(update): import installSkills/installAgents and fix copyFile bug on CLAUDE.md"
75
- ```
76
-
77
- ---
78
-
79
- ## Task 2: Add new artifact sync steps to update.js
80
-
81
- **Files:**
82
- - Modify: `src/commands/project/update.js`
83
-
84
- After the existing skills symlinking block (the closing `}` of the `{ const skillsSrc = ...}` block, around line 301) and BEFORE the hooks update line (`// Update Claude Code hooks`), insert these four steps:
85
-
86
- **Step 1: Add flat skills sync (installSkills)**
87
-
88
- ```javascript
89
- // Sync morph skills to .claude/skills/ for native Claude Code discovery
90
- updateSpinner.text = 'Syncing morph skills to .claude/skills/...';
91
- await installSkills(targetPath);
92
- ```
93
-
94
- **Step 2: Add agents sync (installAgents)**
95
-
96
- ```javascript
97
- // Sync native subagents to .claude/agents/
98
- updateSpinner.text = 'Syncing agents to .claude/agents/...';
99
- await installAgents(targetPath, frameworkDir);
100
- ```
101
-
102
- **Step 3: Add rules sync**
103
-
104
- ```javascript
105
- // Sync path-scoped rules to .claude/rules/
106
- updateSpinner.text = 'Syncing rules to .claude/rules/...';
107
- const rulesSrc = join(frameworkDir, 'rules');
108
- const rulesDest = join(claudeDest, 'rules');
109
- if (await pathExists(rulesSrc)) {
110
- await copyDirectory(rulesSrc, rulesDest);
111
- }
112
- ```
113
-
114
- **Step 4: Add CLAUDE_runtime.md sync**
115
-
116
- ```javascript
117
- // Sync runtime CLAUDE.md to .claude/CLAUDE.md
118
- updateSpinner.text = 'Syncing .claude/CLAUDE.md...';
119
- const runtimeSrc = join(frameworkDir, 'CLAUDE_runtime.md');
120
- const runtimeDest = join(claudeDest, 'CLAUDE.md');
121
- if (await pathExists(runtimeSrc)) {
122
- await copyFile(runtimeSrc, runtimeDest);
123
- }
124
- ```
125
-
126
- **Step 5: Update the success output block**
127
-
128
- Find the "Updated files:" logger section (around line 336–350) and add these lines after the existing hooks line:
129
-
130
- ```javascript
131
- logger.dim(' ✓ .claude/skills/ (flat .md for /skill-name discovery)');
132
- logger.dim(' ✓ .claude/agents/ (native subagents refreshed)');
133
- logger.dim(' ✓ .claude/rules/ (path-scoped rules synced)');
134
- logger.dim(' ✓ .claude/CLAUDE.md (runtime quick reference)');
135
- ```
136
-
137
- **Step 6: Run syntax check**
138
-
139
- ```bash
140
- node --check src/commands/project/update.js && echo "Syntax OK"
141
- ```
142
-
143
- Expected: `Syntax OK`
144
-
145
- **Step 7: Commit**
146
-
147
- ```bash
148
- git add src/commands/project/update.js
149
- git commit -m "feat(update): sync rules, agents, flat skills, and .claude/CLAUDE.md on update"
150
- ```
151
-
152
- ---
153
-
154
- ## Task 3: Write tests for update artifact sync
155
-
156
- **Files:**
157
- - Create: `test/commands/update.test.js`
158
-
159
- The update command is interactive, so test the underlying utility functions directly — the same pattern used in `test/commands/init.test.js`.
160
-
161
- **Step 1: Write the test file**
162
-
163
- ```javascript
164
- /**
165
- * Tests for update command artifact sync.
166
- * Tests utility functions directly to avoid interactive prompts.
167
- */
168
-
169
- import { test, describe, beforeEach, afterEach } from 'node:test';
170
- import assert from 'node:assert/strict';
171
- import { existsSync, readdirSync } from 'fs';
172
- import { join } from 'path';
173
- import { fileURLToPath } from 'url';
174
- import { dirname } from 'path';
175
- import { createTempDir, cleanupTempDir } from '../helpers/test-utils.js';
176
- import { installSkills } from '../../src/utils/skills-installer.js';
177
- import { installAgents } from '../../src/utils/agents-installer.js';
178
- import { copyDirectory, copyFile, pathExists } from '../../src/utils/file-copier.js';
179
-
180
- const __dirname = dirname(fileURLToPath(import.meta.url));
181
- const FRAMEWORK_DIR = join(__dirname, '..', '..', 'framework');
182
-
183
- describe('update — artifact sync', () => {
184
- let tempDir;
185
-
186
- beforeEach(() => {
187
- tempDir = createTempDir();
188
- });
189
-
190
- afterEach(() => {
191
- cleanupTempDir(tempDir);
192
- });
193
-
194
- test('installSkills produces flat .claude/skills/ .md files', async () => {
195
- await installSkills(tempDir);
196
- const skillsDir = join(tempDir, '.claude', 'skills');
197
- assert.ok(existsSync(skillsDir), '.claude/skills/ must exist');
198
- const files = readdirSync(skillsDir).filter(f => f.endsWith('.md'));
199
- assert.ok(files.length >= 4, `must have at least 4 flat skill files, got ${files.length}`);
200
- });
201
-
202
- test('installAgents produces .claude/agents/ with morph- prefixed files', async () => {
203
- await installAgents(tempDir, FRAMEWORK_DIR);
204
- const agentsDir = join(tempDir, '.claude', 'agents');
205
- assert.ok(existsSync(agentsDir), '.claude/agents/ must exist');
206
- const files = readdirSync(agentsDir);
207
- assert.ok(files.every(f => f.startsWith('morph-')), 'all agent files must have morph- prefix');
208
- assert.ok(files.length >= 6, `must have at least 6 agents, got ${files.length}`);
209
- });
210
-
211
- test('rules copy produces .claude/rules/ with 5 files', async () => {
212
- const rulesSrc = join(FRAMEWORK_DIR, 'rules');
213
- const rulesDest = join(tempDir, '.claude', 'rules');
214
- const exists = await pathExists(rulesSrc);
215
- assert.ok(exists, 'framework/rules/ source must exist');
216
- await copyDirectory(rulesSrc, rulesDest);
217
- const files = readdirSync(rulesDest).filter(f => f.endsWith('.md'));
218
- assert.equal(files.length, 5, `must install 5 rule files, got ${files.length}`);
219
- });
220
-
221
- test('CLAUDE_runtime.md copy produces .claude/CLAUDE.md', async () => {
222
- const src = join(FRAMEWORK_DIR, 'CLAUDE_runtime.md');
223
- const dest = join(tempDir, '.claude', 'CLAUDE.md');
224
- const claudeDir = join(tempDir, '.claude');
225
- // ensure parent exists
226
- await (await import('node:fs/promises')).mkdir(claudeDir, { recursive: true });
227
- await copyFile(src, dest);
228
- assert.ok(existsSync(dest), '.claude/CLAUDE.md must exist after copy');
229
- const content = (await import('node:fs/promises')).readFile(dest, 'utf-8');
230
- assert.ok(content instanceof Promise, 'content must be readable');
231
- });
232
-
233
- test('clean-recreate is idempotent — second run replaces without error', async () => {
234
- // First run
235
- await installSkills(tempDir);
236
- await installAgents(tempDir, FRAMEWORK_DIR);
237
- const rulesSrc = join(FRAMEWORK_DIR, 'rules');
238
- const rulesDest = join(tempDir, '.claude', 'rules');
239
- await copyDirectory(rulesSrc, rulesDest);
240
-
241
- // Second run (simulates update running again)
242
- await installSkills(tempDir);
243
- await installAgents(tempDir, FRAMEWORK_DIR);
244
- await copyDirectory(rulesSrc, rulesDest);
245
-
246
- const ruleFiles = readdirSync(rulesDest).filter(f => f.endsWith('.md'));
247
- assert.equal(ruleFiles.length, 5, 'idempotent: must still have 5 rule files after second run');
248
- });
249
- });
250
- ```
251
-
252
- **Step 2: Run the new tests**
253
-
254
- ```bash
255
- npm test -- test/commands/update.test.js
256
- ```
257
-
258
- Expected: 5 pass, 0 fail.
259
-
260
- **Step 3: Commit**
261
-
262
- ```bash
263
- git add test/commands/update.test.js
264
- git commit -m "test(update): add artifact sync tests for update command"
265
- ```
266
-
267
- ---
268
-
269
- ## Task 4: Version bump to 4.4.0
270
-
271
- **Files:**
272
- - Modify: `package.json`
273
-
274
- **Step 1: Update version**
275
-
276
- Find: `"version": "4.3.7"`
277
- Replace with: `"version": "4.4.0"`
278
-
279
- **Step 2: Update version reference in framework/CLAUDE.md and framework/CLAUDE_runtime.md**
280
-
281
- In `framework/CLAUDE.md`, find: `*MORPH-SPEC v4.3.7 by Polymorphism Tech*`
282
- Replace with: `*MORPH-SPEC v4.4.0 by Polymorphism Tech*`
283
-
284
- In `framework/CLAUDE_runtime.md`, find: `*MORPH-SPEC v4.3.7 by Polymorphism Tech*`
285
- Replace with: `*MORPH-SPEC v4.4.0 by Polymorphism Tech*`
286
-
287
- **Step 3: Verify version is consistent**
288
-
289
- ```bash
290
- node -e "import('./package.json', {assert:{type:'json'}}).then(m=>console.log(m.default.version))" 2>/dev/null || grep '"version"' package.json
291
- ```
292
-
293
- Expected: `4.4.0`
294
-
295
- **Step 4: Commit**
296
-
297
- ```bash
298
- git add package.json framework/CLAUDE.md framework/CLAUDE_runtime.md
299
- git commit -m "chore: bump version to 4.4.0 — Claude Code native alignment rounds 1 & 2"
300
- ```
301
-
302
- ---
303
-
304
- ## Task 5: Doctor — add .claude/rules/ and .claude/agents/ checks
305
-
306
- **Files:**
307
- - Modify: `src/commands/project/doctor.js`
308
-
309
- The `.claude/` check block (line ~454–494) checks commands and skills. Add rules and agents checks inside the `if (hasCommands && hasSkills)` block, after the skills link status check ends (after the closing `}` of the `if (skillDirs.length > 0)` block).
310
-
311
- **Step 1: Add the rules check**
312
-
313
- After the skills link block ends (around line 487), and still inside `if (hasCommands && hasSkills) {`, add:
314
-
315
- ```javascript
316
- // Check .claude/rules/
317
- const rulesPath = join(claudePath, 'rules');
318
- if (await pathExists(rulesPath)) {
319
- const ruleFiles = await fs.readdir(rulesPath);
320
- const mdRules = ruleFiles.filter(f => f.endsWith('.md'));
321
- checks.push({ name: '.claude/rules/', status: 'ok', msg: `${mdRules.length} rules` });
322
- } else {
323
- checks.push({ name: '.claude/rules/', status: 'warn', msg: 'missing — run morph-spec update' });
324
- hasWarnings = true;
325
- }
326
-
327
- // Check .claude/agents/
328
- const agentsPath = join(claudePath, 'agents');
329
- if (await pathExists(agentsPath)) {
330
- const agentFiles = await fs.readdir(agentsPath);
331
- const morphAgents = agentFiles.filter(f => f.startsWith('morph-') && f.endsWith('.md'));
332
- checks.push({ name: '.claude/agents/', status: 'ok', msg: `${morphAgents.length} agents` });
333
- } else {
334
- checks.push({ name: '.claude/agents/', status: 'warn', msg: 'missing — run morph-spec update' });
335
- hasWarnings = true;
336
- }
337
- ```
338
-
339
- **Step 2: Verify syntax**
340
-
341
- ```bash
342
- node --check src/commands/project/doctor.js && echo "Syntax OK"
343
- ```
344
-
345
- Expected: `Syntax OK`
346
-
347
- **Step 3: Commit**
348
-
349
- ```bash
350
- git add src/commands/project/doctor.js
351
- git commit -m "feat(doctor): add .claude/rules/ and .claude/agents/ health checks"
352
- ```
353
-
354
- ---
355
-
356
- ## Task 6: Write tests for doctor enhancements
357
-
358
- **Files:**
359
- - Create: `test/commands/doctor.test.js`
360
-
361
- **Step 1: Write tests that directly exercise the check logic**
362
-
363
- ```javascript
364
- /**
365
- * Tests for doctor command health check additions.
366
- * Tests the check logic by setting up temp dirs with/without the expected artifacts.
367
- */
368
-
369
- import { test, describe, beforeEach, afterEach } from 'node:test';
370
- import assert from 'node:assert/strict';
371
- import { mkdirSync, writeFileSync } from 'fs';
372
- import { join } from 'path';
373
- import { createTempDir, cleanupTempDir } from '../helpers/test-utils.js';
374
- import { pathExists } from '../../src/utils/file-copier.js';
375
- import { installSkills } from '../../src/utils/skills-installer.js';
376
- import { installAgents } from '../../src/utils/agents-installer.js';
377
- import { copyDirectory } from '../../src/utils/file-copier.js';
378
- import { fileURLToPath } from 'url';
379
- import { dirname } from 'path';
380
-
381
- const __dirname = dirname(fileURLToPath(import.meta.url));
382
- const FRAMEWORK_DIR = join(__dirname, '..', '..', 'framework');
383
-
384
- describe('doctor — .claude artifact checks', () => {
385
- let tempDir;
386
-
387
- beforeEach(() => {
388
- tempDir = createTempDir();
389
- });
390
-
391
- afterEach(() => {
392
- cleanupTempDir(tempDir);
393
- });
394
-
395
- test('.claude/rules/ missing → would produce warn', async () => {
396
- const rulesPath = join(tempDir, '.claude', 'rules');
397
- const exists = await pathExists(rulesPath);
398
- assert.equal(exists, false, '.claude/rules/ should not exist in fresh temp dir');
399
- // Confirms doctor would add a warning
400
- });
401
-
402
- test('.claude/rules/ present with 5 files → would produce ok', async () => {
403
- const rulesSrc = join(FRAMEWORK_DIR, 'rules');
404
- const rulesDest = join(tempDir, '.claude', 'rules');
405
- await copyDirectory(rulesSrc, rulesDest);
406
- const exists = await pathExists(rulesDest);
407
- assert.ok(exists, '.claude/rules/ must exist after copy');
408
- const { readdirSync } = await import('fs');
409
- const files = readdirSync(rulesDest).filter(f => f.endsWith('.md'));
410
- assert.equal(files.length, 5, 'must have 5 rule files for an ok check');
411
- });
412
-
413
- test('.claude/agents/ missing → would produce warn', async () => {
414
- const agentsPath = join(tempDir, '.claude', 'agents');
415
- const exists = await pathExists(agentsPath);
416
- assert.equal(exists, false, '.claude/agents/ should not exist in fresh temp dir');
417
- });
418
-
419
- test('.claude/agents/ present with morph- agents → would produce ok', async () => {
420
- await installAgents(tempDir, FRAMEWORK_DIR);
421
- const agentsPath = join(tempDir, '.claude', 'agents');
422
- const exists = await pathExists(agentsPath);
423
- assert.ok(exists, '.claude/agents/ must exist after installAgents');
424
- const { readdirSync } = await import('fs');
425
- const files = readdirSync(agentsPath).filter(f => f.startsWith('morph-'));
426
- assert.ok(files.length >= 6, `must have at least 6 morph- agents, got ${files.length}`);
427
- });
428
- });
429
- ```
430
-
431
- **Step 2: Run the tests**
432
-
433
- ```bash
434
- npm test -- test/commands/doctor.test.js
435
- ```
436
-
437
- Expected: 4 pass, 0 fail.
438
-
439
- **Step 3: Commit**
440
-
441
- ```bash
442
- git add test/commands/doctor.test.js
443
- git commit -m "test(doctor): add tests for .claude/rules/ and .claude/agents/ check logic"
444
- ```
445
-
446
- ---
447
-
448
- ## Task 7: Full test suite + final commit
449
-
450
- **Step 1: Run full test suite**
451
-
452
- ```bash
453
- npm test 2>&1 | tail -10
454
- ```
455
-
456
- Expected: `pass` count ≥ 596, `fail` 0, `skipped` 1. (Previous baseline: 587 pass.)
457
-
458
- **Step 2: If any failures, fix them before proceeding**
459
-
460
- Failing tests mean the plan has a bug. Stop, diagnose, fix — do NOT skip tests.
461
-
462
- **Step 3: Update memory**
463
-
464
- Update `MEMORY.md` to reflect the new test count and version.
465
-
466
- **Step 4: Final commit if anything was missed**
467
-
468
- ```bash
469
- git status
470
- # If clean: nothing to do
471
- # If not: git add <files> && git commit -m "chore: final cleanup for morph-spec-next"
472
- ```
473
-
474
- ---
475
-
476
- ## What this plan does NOT include (intentionally)
477
-
478
- - `.wiki/prompts/` — only one prompt file, still useful for future alignment rounds; no cleanup needed
479
- - Level 3–4 skill audit — both directories contain only `README.md`; nothing to audit
480
- - `morph-workflow.md` live injection — rules are static files; the `enrich-prompt.js` hook already handles dynamic state injection and is already focused (no trim needed)
@@ -1,201 +0,0 @@
1
- # Design: MORPH-SPEC Native Alignment + State.json Simplification
2
-
3
- **Status:** COMPLETE (see implementation plan)
4
-
5
- **Date:** 2026-02-22
6
- **Version target:** 4.5.0
7
- **Branch:** single branch, all changes together
8
-
9
- ---
10
-
11
- ## Summary
12
-
13
- Six focused changes that align MORPH-SPEC closer to Claude Code's native platform patterns and reduce architectural complexity without breaking existing functionality.
14
-
15
- ---
16
-
17
- ## Section 1 — Skills File Format Fix
18
-
19
- **Problem:** `skills-installer.js` installs skills as flat files (`.claude/skills/brainstorming.md`). Native Claude Code format is subdirectory + `SKILL.md` (`.claude/skills/brainstorming/SKILL.md`). Flat format prevents frontmatter features from working (allowed-tools, argument-hint, context:fork).
20
-
21
- **Design:**
22
- - `installSkillsFromDir()` creates `<destDir>/<skillName>/SKILL.md` instead of `<destDir>/<skillName>.md`
23
- - Skill name derived from filename without extension (same as today)
24
- - All level-0-meta, level-1-workflows, level-2-domains affected
25
-
26
- **Files:**
27
- - `src/utils/skills-installer.js` — change flat copy to mkdir + write SKILL.md
28
- - `test/utils/skills-installer.test.js` — update assertions to check subdirectory format
29
- - `src/commands/project/update.js` — no change needed (calls installSkills which is updated)
30
-
31
- ---
32
-
33
- ## Section 2 — Rules as Dynamic @-imports
34
-
35
- **Problem:** `framework/rules/*.md` contain static copies of standards content. When standards change, rules become stale until next `morph-spec update`.
36
-
37
- **Design:** Replace static body content with `@-import` directives pointing to `.morph/framework/standards/` paths in the user project. The `morph-workflow.md` rule keeps its own content (not a standards file).
38
-
39
- **Files changed:**
40
- - `framework/rules/csharp-standards.md` — body → @-imports to core/coding.md + backend/dotnet.md
41
- - `framework/rules/frontend-standards.md` — body → @-imports to frontend/ standards
42
- - `framework/rules/testing-standards.md` — body → @-imports to core/testing.md
43
- - `framework/rules/infrastructure-standards.md` — body → @-imports to infrastructure/ standards
44
- - `framework/rules/morph-workflow.md` — gets new "Test File Policy" section (see Section 4), no @-imports
45
-
46
- **@-import paths** use `.morph/framework/standards/` because rules are installed into user projects where that path is valid.
47
-
48
- ---
49
-
50
- ## Section 3 — CLAUDE.md Consolidation
51
-
52
- **Problem:** Two separate user-facing CLAUDE.md files (`framework/CLAUDE.md` and `framework/CLAUDE_runtime.md`) with duplicated content and no @-imports for dynamic context.
53
-
54
- **Design:** Single `framework/CLAUDE.md` that merges both files. Installed to `.claude/CLAUDE.md` in user projects. Uses `@.morph/context/README.md` import for dynamic project context. `framework/CLAUDE_runtime.md` deleted.
55
-
56
- **New `framework/CLAUDE.md` structure:**
57
- 1. Header + project context @-import
58
- 2. Critical Rules (from current CLAUDE.md)
59
- 3. Quick Reference commands table (from CLAUDE_runtime.md)
60
- 4. State & Outputs table (from CLAUDE_runtime.md)
61
- 5. Phase Sequence (from CLAUDE_runtime.md)
62
- 6. Agents section (from CLAUDE_runtime.md)
63
- 7. MCP CLI deferred mode note (new)
64
- 8. Footer
65
-
66
- **Files:**
67
- - `framework/CLAUDE.md` — merged content
68
- - `framework/CLAUDE_runtime.md` — **deleted**
69
- - `src/commands/project/init.js` — change source from `CLAUDE_runtime.md` to `CLAUDE.md` for `.claude/CLAUDE.md` install
70
- - `src/commands/project/update.js` — same change
71
- - `test/commands/init.test.js` — update source file reference
72
- - `test/commands/update.test.js` — update source file reference
73
-
74
- ---
75
-
76
- ## Section 4 — Test File Policy in morph-workflow Rule
77
-
78
- **Problem:** Claude modifies test files to make failing tests pass instead of fixing the implementation. A blocking hook is not appropriate because Claude also needs to legitimately fix incorrect test specs.
79
-
80
- **Design:** Behavioral rule in `framework/rules/morph-workflow.md` (always-active, no paths filter):
81
-
82
- ```markdown
83
- ## Test File Policy
84
-
85
- When a test fails, always follow this order:
86
- 1. Analyze whether the IMPLEMENTATION is wrong or the TEST SPEC is wrong
87
- 2. Fix the implementation first
88
- 3. Only modify a test file if the test expectation itself is incorrect
89
- 4. Before modifying a test file, explain WHY the test spec is wrong
90
- ```
91
-
92
- No new hook. Declarative behavioral guidance over imperative blocking.
93
-
94
- **Files:**
95
- - `framework/rules/morph-workflow.md` — add Test File Policy section
96
-
97
- ---
98
-
99
- ## Section 5 — Standards and Templates Additions
100
-
101
- **5a. TypeScript Strict Mode**
102
-
103
- Add explicit strict mode section to `framework/rules/frontend-standards.md`:
104
- - `"strict": true` in tsconfig.json is required
105
- - Explains why: agents rely on compiler errors to self-correct at compile time
106
-
107
- **5b. MCP CLI Deferred Mode**
108
-
109
- Add note to merged `framework/CLAUDE.md`:
110
- - With 3+ MCPs, add `"experimental": { "mcpCliMode": true }` to settings.json
111
- - Keeps context window clean; MCP tools load on-demand
112
-
113
- **5c. User Stories Template**
114
-
115
- New file `framework/templates/docs/user-stories.md` with format:
116
- - Story header (feature, priority)
117
- - Optimal path steps
118
- - Edge cases
119
- - Acceptance criteria checklist
120
-
121
- **Files:**
122
- - `framework/rules/frontend-standards.md` — add TypeScript strict section (also in @-import content)
123
- - `framework/CLAUDE.md` — add MCP deferred mode note
124
- - `framework/templates/docs/user-stories.md` — new template file
125
-
126
- ---
127
-
128
- ## Section 6 — State.json Simplification
129
-
130
- **Problem:** `state.json` tracks `outputs.{type}.created` and `phase` — both derivable from the filesystem. The `track-output-creation.js` hook exists solely to maintain these two fields and has been the source of synchronization bugs.
131
-
132
- **Design:**
133
-
134
- Remove from state.json schema (per feature):
135
- - `outputs` object (all 12 output types with `created` booleans and `path` strings)
136
- - `phase` string field
137
-
138
- Keep in state.json (unchanged):
139
- - `workflow` — which workflow was auto-selected
140
- - `approvalGates` — approval status per gate
141
- - `tasks` — total/completed counts
142
- - `createdAt` — timestamp
143
- - `activeAgents` — for display/analytics
144
-
145
- Derive at runtime:
146
- ```javascript
147
- // Phase: highest-numbered folder present
148
- function derivePhase(featurePath) {
149
- const folders = ['4-implement', '3-tasks', '2-ui', '1-design', '0-proposal'];
150
- return folders.find(f => fs.existsSync(path.join(featurePath, f))) ?? 'setup';
151
- }
152
-
153
- // Output existence: file exists check
154
- function deriveOutputs(feature, outputDefs) {
155
- return Object.fromEntries(
156
- Object.entries(outputDefs).map(([type, relPath]) => [
157
- type, { created: fs.existsSync(path.join(featureBase, relPath)), path: relPath }
158
- ])
159
- );
160
- }
161
- ```
162
-
163
- **Migration:** `state-manager.js` migration from v4.x → v5.0 removes `outputs` and `phase` fields on first load if present. Backwards compatible read.
164
-
165
- **Files:**
166
- - `src/core/state/state-manager.js` — remove `outputs` + `phase` from `ensureFeature()`, add migration, add `derivePhase()` + `deriveOutputs()` helpers
167
- - `framework/hooks/claude-code/post-tool-use/track-output-creation.js` — **deleted**
168
- - `src/utils/hooks-installer.js` — remove `track-output-creation.js` from PostToolUse hook list
169
- - `src/commands/project/status.js` — update to call `derivePhase()` + `deriveOutputs()`
170
- - `test/core/state/state-manager.test.js` — remove `outputs`/`phase` tests, add derive helper tests
171
-
172
- ---
173
-
174
- ## What Does NOT Change
175
-
176
- - `approvalGates` in state.json — kept, protected by permissions.deny
177
- - `protect-spec-files.js` hook — kept, still reads approvalGates from state.json
178
- - All 37 agents in agents.json — unchanged
179
- - All validators — unchanged
180
- - All workflow configs — unchanged
181
- - All Handlebars templates (except new user-stories.md addition)
182
- - Git hooks — unchanged
183
- - Agent Teams hooks — unchanged
184
-
185
- ---
186
-
187
- ## Test Strategy
188
-
189
- All 614 existing tests must pass after changes. New tests added for:
190
- - `skills-installer.test.js` — verify subdirectory format
191
- - `state-manager.test.js` — verify `derivePhase()`, `deriveOutputs()`, migration from v4
192
- - `hooks-installer.test.js` — verify track-output-creation no longer registered
193
-
194
- No integration tests needed — all changes are unit-testable.
195
-
196
- ---
197
-
198
- ## Version Bump
199
-
200
- `package.json`: `4.4.0` → `4.5.0`
201
- `framework/CLAUDE.md`: update version in footer