@polymorphism-tech/morph-spec 4.11.0 → 4.12.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 +106 -2
- package/README.md +2 -2
- package/bin/morph-spec.js +31 -3
- package/bin/task-manager.js +391 -35
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents.json +16 -6
- package/framework/commands/morph-apply.md +21 -1
- package/framework/commands/morph-proposal.md +44 -1
- package/framework/hooks/claude-code/post-tool-use/agent-complete.js +122 -0
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +47 -2
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +4 -3
- package/framework/hooks/shared/dispatch-helpers.js +31 -0
- package/framework/hooks/shared/state-reader.js +7 -3
- package/framework/rules/morph-task-tracking.md +49 -0
- package/framework/skills/level-0-meta/morph-brainstorming/SKILL.md +6 -10
- package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +10 -1
- package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +7 -13
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +7 -1
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +9 -12
- package/framework/skills/level-1-workflows/morph-phase-setup/SKILL.md +7 -10
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +10 -18
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +256 -14
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/framework/standards/STANDARDS.json +31 -0
- package/framework/standards/frontend/design-system/aesthetic-direction.md +60 -7
- package/framework/standards/frontend/design-system/design-trends.md +171 -0
- package/framework/templates/context/CONTEXT.md +2 -2
- package/framework/templates/context/design-system.md +346 -211
- package/framework/templates/meta-prompts/squad-leaders/frontend-squad.md +1 -1
- package/package.json +1 -1
- package/src/commands/agents/dispatch-agents.js +25 -1
- package/src/commands/mcp/mcp-setup.js +28 -6
- package/src/commands/project/init.js +20 -1
- package/src/commands/tasks/task.js +54 -0
- package/src/lib/build/build-runner.js +99 -0
- package/src/lib/checkpoints/checkpoint-hooks.js +110 -0
- package/src/lib/generators/design-system-generator.js +340 -51
- package/src/lib/generators/recap-generator.js +27 -4
- package/src/lib/stack/stack-profile.js +3 -0
- package/src/lib/tasks/task-parser.js +23 -9
- package/src/lib/validators/design-system/design-system-validator.js +11 -5
- package/src/utils/file-copier.js +1 -0
- package/src/utils/hooks-installer.js +11 -1
- package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +0 -7
package/CLAUDE.md
CHANGED
|
@@ -1,3 +1,107 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CLAUDE.md
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What This Is
|
|
6
|
+
|
|
7
|
+
morph-spec is a spec-driven development framework CLI (`@polymorphism-tech/morph-spec`). It orchestrates AI-first feature development through structured phases with approval gates. This repo is the **framework source code** — not a project that uses morph-spec.
|
|
8
|
+
|
|
9
|
+
## Build & Test Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Run all tests (sequential — required due to process.chdir state)
|
|
13
|
+
npm test
|
|
14
|
+
|
|
15
|
+
# Run a single test file
|
|
16
|
+
node --test test/commands/task-done.test.js
|
|
17
|
+
|
|
18
|
+
# Run tests matching a name pattern
|
|
19
|
+
node --test --test-name-pattern="should advance phase" test/commands/advance-phase.test.js
|
|
20
|
+
|
|
21
|
+
# Coverage
|
|
22
|
+
npm run test:coverage # text + html + lcov
|
|
23
|
+
npm run test:coverage:summary # text-summary only
|
|
24
|
+
|
|
25
|
+
# Generate JSDoc API docs
|
|
26
|
+
npm run docs
|
|
27
|
+
|
|
28
|
+
# Regenerate derived reference files from output-schema.js
|
|
29
|
+
npm run generate
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
No build step — pure ESM JavaScript, runs directly via Node.js 18+.
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
### Module Layout
|
|
37
|
+
|
|
38
|
+
- **`bin/morph-spec.js`** — Commander.js CLI entry point. All commands registered here.
|
|
39
|
+
- **`src/commands/`** — CLI command handlers organized by domain (state/, tasks/, agents/, validation/, trust/, etc.)
|
|
40
|
+
- **`src/core/`** — Core domain logic (not CLI-coupled):
|
|
41
|
+
- `state/state-manager.js` — Atomic state I/O with process-ID temp files to prevent race conditions
|
|
42
|
+
- `paths/output-schema.js` — **Single source of truth** for all 15 output types, their filenames, phase directories, and gate associations
|
|
43
|
+
- `templates/` — Handlebars template registry and renderer
|
|
44
|
+
- `workflows/` — Workflow type detector (standard vs nodejs-cli)
|
|
45
|
+
- **`src/lib/`** — Libraries and subsystems:
|
|
46
|
+
- `validators/` — 25+ data-driven validators (architecture, blazor, css, design-system, nextjs, etc.)
|
|
47
|
+
- `generators/` — Code generation (design-system, context, recap, metadata)
|
|
48
|
+
- `trust/trust-manager.js` — 3-level trust model (manual/high/auto)
|
|
49
|
+
- `stack-filter.js` — Stack-aware asset filtering via YAML frontmatter `stacks:` tags
|
|
50
|
+
- `hooks/` — Hook executor
|
|
51
|
+
- `installers/` — Agents, skills, hooks installers for target projects
|
|
52
|
+
- **`src/utils/`** — Shared utilities (logger, banner, file-copier, claude-settings-manager, etc.)
|
|
53
|
+
- **`framework/`** — Metadata installed into target projects (READ-ONLY at runtime):
|
|
54
|
+
- `agents.json` (v4.0.0, 46 agents in 4 tiers)
|
|
55
|
+
- `phases.json` (8 phases + sync)
|
|
56
|
+
- `standards/STANDARDS.json` (86 entries)
|
|
57
|
+
- `hooks/claude-code/` — Hook scripts (10 hooks, fail-open design)
|
|
58
|
+
- `skills/` — Morph skills (level-0-meta + level-1-workflows)
|
|
59
|
+
- `templates/` — Handlebars templates for code generation
|
|
60
|
+
|
|
61
|
+
### Key Architectural Patterns
|
|
62
|
+
|
|
63
|
+
**Dual-layer phase tracking:** Phase is derived from filesystem (`derivePhase()` scans for highest-numbered phase folder) — state.json only overrides for lightweight phases (setup, clarify, sync).
|
|
64
|
+
|
|
65
|
+
**Output schema as single source of truth:** `src/core/paths/output-schema.js` defines all output types. Run `npm run generate` after modifying it to update derived reference files.
|
|
66
|
+
|
|
67
|
+
**Data-driven validation:** `agents.json` lists validators per agent. The validation runner reads active agents from state and orchestrates only relevant validators.
|
|
68
|
+
|
|
69
|
+
**Fail-open hooks:** All hooks in `framework/hooks/claude-code/` check `stateExists()` first and return `{}` (empty/pass-through) if state is missing or corrupt. Hooks never throw or write state.
|
|
70
|
+
|
|
71
|
+
**Atomic state writes:** `state-manager.js` writes to a process-ID temp file then renames, preventing corruption from concurrent CLI invocations.
|
|
72
|
+
|
|
73
|
+
**Stack-aware filtering:** Assets declare `stacks: ['dotnet', 'blazor']` in YAML frontmatter. `setup-infra.js` reads `config.json → project.stack`, splits into tags, and installs only matching assets. `stacks: ['*']` = universal.
|
|
74
|
+
|
|
75
|
+
### Phase Sequence
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
proposal → setup → [uiux] → design → clarify → plan → tasks → implement → [sync]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Phases in brackets are optional. Approval gates exist at: proposal, design, plan, tasks, uiux.
|
|
82
|
+
|
|
83
|
+
### State Schema (v5.0.0)
|
|
84
|
+
|
|
85
|
+
State lives in `.morph/state.json` in target projects. Phase and outputs are **derived from filesystem**, not stored in state. State tracks: features (status, activeAgents, taskList, trustConfig, metadata), project info, and version.
|
|
86
|
+
|
|
87
|
+
## Testing Conventions
|
|
88
|
+
|
|
89
|
+
- **Framework:** Node.js native `node:test` — no Jest or Mocha
|
|
90
|
+
- **Concurrency:** Always sequential (`--test-concurrency=1`) — tests use `process.chdir()`
|
|
91
|
+
- **Temp dirs:** Use `createTempDir()` / `cleanupTempDir()` from `test/helpers/test-utils.js` — creates dirs with `morph-test-` prefix
|
|
92
|
+
- **Mock state:** Use `createMockState(overrides)` and `createStateFile(tempDir, state)` from test-utils
|
|
93
|
+
- **Pattern:** Each test creates a temp dir, chdir into it, sets up mock state/filesystem, runs the function, asserts, then restores cwd and cleans up in afterEach
|
|
94
|
+
|
|
95
|
+
## Code Conventions
|
|
96
|
+
|
|
97
|
+
- **ESM only** — all files use `import`/`export`, package.json has `"type": "module"`
|
|
98
|
+
- **Output type normalization** — `normalizeOutputType()` auto-converts kebab-case to camelCase via regex
|
|
99
|
+
- **Template helpers** — Handlebars v2.0 helpers: pascalCase, camelCase, snakeCase, kebabCase, pluralize, plus comparison/logic helpers
|
|
100
|
+
- **CLI structure** — Commands are thin wrappers that delegate to `src/core/` or `src/lib/` modules. Keep business logic out of command files.
|
|
101
|
+
|
|
102
|
+
## Framework vs Runtime Distinction
|
|
103
|
+
|
|
104
|
+
- **This repo** (`morph-spec-framework/`) = the CLI tool source code
|
|
105
|
+
- **`framework/`** = files installed into target projects via `morph-spec init`
|
|
106
|
+
- **`framework/CLAUDE.md`** = the CLAUDE.md injected into target projects (not for this repo)
|
|
107
|
+
- When editing `framework/` files, you're changing what gets installed in user projects, not runtime behavior of the CLI itself
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Spec-driven development framework for multi-stack projects. Turns feature requests into implementation-ready code through structured, AI-orchestrated phases.
|
|
4
4
|
|
|
5
5
|
**Package:** `@polymorphism-tech/morph-spec`
|
|
6
|
-
**Version:** 4.
|
|
6
|
+
**Version:** 4.12.0
|
|
7
7
|
**Requires:** Node.js 18+, Claude Code
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -370,4 +370,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
|
|
|
370
370
|
|
|
371
371
|
---
|
|
372
372
|
|
|
373
|
-
*morph-spec v4.
|
|
373
|
+
*morph-spec v4.12.0 by [Polymorphism Tech](https://polymorphism.tech)*
|
package/bin/morph-spec.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { program } from 'commander';
|
|
4
4
|
import chalk from 'chalk';
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
} from '../src/commands/agents/manage-agents.js';
|
|
39
39
|
|
|
40
40
|
// Task commands
|
|
41
|
-
import { taskDoneCommand, taskStartCommand, taskNextCommand } from '../src/commands/tasks/task.js';
|
|
41
|
+
import { taskDoneCommand, taskStartCommand, taskNextCommand, taskBulkStartCommand, taskBulkDoneCommand, taskAnnotateCommand } from '../src/commands/tasks/task.js';
|
|
42
42
|
|
|
43
43
|
// Scope escalation commands
|
|
44
44
|
import { scopeEscalateCommand } from '../src/commands/scope/escalate.js';
|
|
@@ -153,7 +153,9 @@ const taskCommand = program
|
|
|
153
153
|
taskCommand
|
|
154
154
|
.command('done <feature> <task-ids...>')
|
|
155
155
|
.description('Mark tasks as completed (runs validation first)')
|
|
156
|
-
.option('--
|
|
156
|
+
.option('--note <text>', 'Add a deviation note explaining why task was done differently than planned')
|
|
157
|
+
.option('--skip-validation', 'Skip code validation (budget-limited, requires --reason)')
|
|
158
|
+
.option('--reason <text>', 'Reason for skipping validation (required with --skip-validation)')
|
|
157
159
|
.option('--dry-run', 'Show validation results without marking tasks as complete')
|
|
158
160
|
.action((feature, taskIds, options) => taskDoneCommand(feature, taskIds, options));
|
|
159
161
|
|
|
@@ -173,6 +175,32 @@ taskCommand
|
|
|
173
175
|
.option('--into <subtasks...>', 'Sub-task definitions ("T017a: Title")')
|
|
174
176
|
.action((feature, taskId, options) => taskExpandCommand(feature, taskId, options));
|
|
175
177
|
|
|
178
|
+
taskCommand
|
|
179
|
+
.command('bulk-start <feature> [range]')
|
|
180
|
+
.description('Start multiple tasks at once (mark as in_progress)')
|
|
181
|
+
.option('--all', 'Start all pending tasks with met dependencies')
|
|
182
|
+
.option('--from <id>', 'Start of task range (e.g. T007)')
|
|
183
|
+
.option('--to <id>', 'End of task range (e.g. T014)')
|
|
184
|
+
.action((feature, range, options) => taskBulkStartCommand(feature, range, options));
|
|
185
|
+
|
|
186
|
+
taskCommand
|
|
187
|
+
.command('bulk-done <feature> [range]')
|
|
188
|
+
.description('Complete multiple tasks with a single validation pass')
|
|
189
|
+
.option('--all', 'Complete all non-completed tasks')
|
|
190
|
+
.option('--from <id>', 'Start of task range (e.g. T007)')
|
|
191
|
+
.option('--to <id>', 'End of task range (e.g. T014)')
|
|
192
|
+
.option('--note <text>', 'Add a deviation note explaining why tasks were done differently than planned')
|
|
193
|
+
.option('--skip-validation', 'Skip code validation (budget-limited, requires --reason)')
|
|
194
|
+
.option('--reason <text>', 'Reason for skipping validation (required with --skip-validation)')
|
|
195
|
+
.option('--dry-run', 'Show validation results without marking tasks as complete')
|
|
196
|
+
.action((feature, range, options) => taskBulkDoneCommand(feature, range, options));
|
|
197
|
+
|
|
198
|
+
taskCommand
|
|
199
|
+
.command('annotate <feature> <task-id> <text>')
|
|
200
|
+
.description('Add a note to a task (deviation, context, or blocker resolution)')
|
|
201
|
+
.option('--type <type>', 'Note type: deviation | context | blocker-resolved', 'deviation')
|
|
202
|
+
.action((feature, taskId, text, options) => taskAnnotateCommand(feature, taskId, text, options));
|
|
203
|
+
|
|
176
204
|
// Generation commands
|
|
177
205
|
const generateCommand = program
|
|
178
206
|
.command('generate')
|