@polymorphism-tech/morph-spec 4.9.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/morph-spec.js +30 -0
- package/bin/task-manager.js +34 -22
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +99 -98
- package/framework/agents.json +37 -7
- package/framework/commands/commit.md +166 -0
- package/framework/commands/morph-apply.md +13 -2
- package/framework/commands/morph-archive.md +8 -2
- package/framework/commands/morph-infra.md +6 -0
- package/framework/commands/morph-preflight.md +6 -0
- package/framework/commands/morph-proposal.md +56 -7
- package/framework/commands/morph-status.md +6 -0
- package/framework/commands/morph-troubleshoot.md +6 -0
- package/framework/hooks/claude-code/notification/approval-reminder.js +3 -2
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +154 -31
- package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +7 -84
- package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +8 -17
- package/framework/hooks/claude-code/pre-compact/save-morph-context.js +16 -3
- package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +4 -3
- package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +3 -2
- package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +60 -0
- package/framework/hooks/claude-code/session-start/inject-morph-context.js +55 -2
- package/framework/hooks/claude-code/session-start/post-compact-restore.js +41 -0
- package/framework/hooks/claude-code/stop/validate-completion.js +2 -15
- package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +23 -5
- package/framework/hooks/shared/compact-restore.js +100 -0
- package/framework/hooks/shared/dispatch-helpers.js +116 -0
- package/framework/hooks/shared/phase-utils.js +9 -5
- package/framework/hooks/shared/state-reader.js +27 -3
- package/framework/phases.json +30 -7
- package/framework/rules/morph-workflow.md +88 -86
- package/framework/skills/level-0-meta/mcp-registry.json +86 -51
- package/framework/skills/level-0-meta/{brainstorming → morph-brainstorming}/SKILL.md +13 -16
- package/framework/skills/level-0-meta/{code-review → morph-code-review}/SKILL.md +1 -1
- package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/SKILL.md +2 -2
- package/framework/skills/level-0-meta/{frontend-review → morph-frontend-review}/SKILL.md +5 -5
- package/framework/skills/level-0-meta/morph-init/SKILL.md +72 -7
- package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/SKILL.md +9 -9
- package/framework/skills/level-0-meta/morph-replicate/SKILL.md +1 -1
- package/framework/skills/level-0-meta/{terminal-title → morph-terminal-title}/SKILL.md +1 -1
- package/framework/skills/level-0-meta/{tool-usage-guide → morph-tool-usage-guide}/SKILL.md +2 -3
- package/framework/skills/level-0-meta/{tool-usage-guide → morph-tool-usage-guide}/references/tools-per-phase.md +1 -2
- package/framework/skills/level-0-meta/{verification-before-completion → morph-verification-before-completion}/SKILL.md +1 -1
- package/framework/skills/level-0-meta/{verification-before-completion → morph-verification-before-completion}/scripts/check-phase-outputs.mjs +2 -2
- package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +238 -0
- package/framework/skills/level-1-workflows/{phase-codebase-analysis → morph-phase-codebase-analysis}/SKILL.md +251 -251
- package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +507 -0
- package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/SKILL.md +590 -491
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +50 -0
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +45 -0
- package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +47 -0
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +254 -0
- package/framework/skills/level-1-workflows/{phase-setup → morph-phase-setup}/SKILL.md +237 -194
- package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/SKILL.md +307 -270
- package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/scripts/validate-tasks.mjs +3 -3
- package/framework/skills/level-1-workflows/{phase-uiux → morph-phase-uiux}/SKILL.md +320 -285
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +97 -0
- package/framework/standards/integration/mcp/mcp-tools.md +25 -7
- package/framework/templates/docs/onboarding.md +2 -2
- package/package.json +1 -2
- package/src/commands/agents/dispatch-agents.js +50 -3
- package/src/commands/mcp/mcp-setup.js +39 -2
- package/src/commands/phase/phase-reset.js +74 -0
- package/src/commands/project/doctor.js +19 -5
- package/src/commands/scope/escalate.js +215 -0
- package/src/commands/state/advance-phase.js +27 -53
- package/src/commands/state/state.js +1 -1
- package/src/commands/task/expand.js +100 -0
- package/src/core/paths/output-schema.js +4 -3
- package/src/core/state/phase-state-machine.js +7 -4
- package/src/core/state/state-manager.js +4 -3
- package/src/lib/detectors/claude-config-detector.js +93 -347
- package/src/lib/detectors/design-system-detector.js +189 -189
- package/src/lib/detectors/index.js +155 -57
- package/src/lib/generators/context-generator.js +2 -2
- package/src/lib/installers/mcp-installer.js +37 -5
- package/src/lib/phase-chain/phase-validator.js +22 -16
- package/src/lib/scope/impact-analyzer.js +106 -0
- package/src/lib/tasks/task-parser.js +1 -1
- package/src/lib/validators/shared/emit-validator-dispatch.js +64 -0
- package/src/scripts/setup-infra.js +15 -0
- package/src/utils/agents-installer.js +32 -12
- package/src/utils/file-copier.js +0 -1
- package/src/utils/hooks-installer.js +15 -1
- package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +0 -216
- package/framework/skills/level-1-workflows/phase-design/SKILL.md +0 -383
- package/src/commands/project/index.js +0 -8
- package/src/core/index.js +0 -10
- package/src/core/state/index.js +0 -8
- package/src/core/templates/index.js +0 -9
- package/src/core/templates/template-data-sources.js +0 -325
- package/src/core/workflows/index.js +0 -7
- package/src/lib/detectors/config-detector.js +0 -223
- package/src/lib/detectors/standards-generator.js +0 -335
- package/src/lib/detectors/structure-detector.js +0 -275
- package/src/lib/monitor/agent-resolver.js +0 -144
- package/src/lib/monitor/renderer.js +0 -230
- package/src/lib/orchestration/index.js +0 -7
- package/src/lib/orchestration/team-orchestrator.js +0 -404
- package/src/sanitizer/context-sanitizer.js +0 -221
- package/src/sanitizer/patterns.js +0 -163
- package/src/writer/file-writer.js +0 -86
- /package/framework/skills/level-0-meta/{brainstorming → morph-brainstorming}/references/proposal-example.md +0 -0
- /package/framework/skills/level-0-meta/{code-review → morph-code-review}/references/review-example.md +0 -0
- /package/framework/skills/level-0-meta/{code-review → morph-code-review}/references/review-guidelines.md +0 -0
- /package/framework/skills/level-0-meta/{code-review → morph-code-review}/scripts/scan-csharp.mjs +0 -0
- /package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/references/review-example-nextjs.md +0 -0
- /package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/scripts/scan-nextjs.mjs +0 -0
- /package/framework/skills/level-0-meta/{frontend-review → morph-frontend-review}/scripts/scan-accessibility.mjs +0 -0
- /package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/scripts/detect-dev-server.mjs +0 -0
- /package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/scripts/detect-stack.mjs +0 -0
- /package/framework/skills/level-0-meta/{simulation-checklist → morph-simulation-checklist}/SKILL.md +0 -0
- /package/framework/skills/level-0-meta/{terminal-title → morph-terminal-title}/scripts/set_title.sh +0 -0
- /package/framework/skills/level-1-workflows/{phase-clarify → morph-phase-clarify}/references/clarifications-example.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/architecture-analysis-guide.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/spec-authoring-guide.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/spec-example.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/references/recap-example.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/references/vsa-implementation-guide.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/references/task-planning-patterns.md +0 -0
- /package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/references/tasks-example.md +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure helper functions for the dispatch PostToolUse hook.
|
|
3
|
+
*
|
|
4
|
+
* Extracted for testability — no I/O, no process.exit, no stdin/stdout.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Extract VALIDATION DISPATCH JSON from tool output string.
|
|
9
|
+
* Strips ANSI escape codes and parses the JSON block between delimiters.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} toolOutput - Raw tool output (may contain ANSI codes)
|
|
12
|
+
* @returns {object|null} - Parsed dispatch object or null
|
|
13
|
+
*/
|
|
14
|
+
export function extractValidationDispatch(toolOutput) {
|
|
15
|
+
if (!toolOutput || typeof toolOutput !== 'string') return null;
|
|
16
|
+
|
|
17
|
+
// Strip ANSI escape codes (chalk colors)
|
|
18
|
+
const clean = toolOutput.replace(/\x1B\[[0-9;]*m/g, '');
|
|
19
|
+
|
|
20
|
+
const match = clean.match(/--- VALIDATION DISPATCH ---\s*\n([\s\S]*?)\n\s*--- END VALIDATION DISPATCH ---/);
|
|
21
|
+
if (!match) return null;
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const dispatch = JSON.parse(match[1]);
|
|
25
|
+
if (!dispatch?.validators?.length) return null;
|
|
26
|
+
return dispatch;
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Format a dispatch object as a mandatory instruction string for Claude.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} dispatch - Dispatch object with validators array
|
|
36
|
+
* @returns {string} - Formatted injection text
|
|
37
|
+
*/
|
|
38
|
+
export function formatValidatorInstruction(dispatch) {
|
|
39
|
+
if (!dispatch?.validators?.length) return '';
|
|
40
|
+
|
|
41
|
+
const lines = [
|
|
42
|
+
'🔍 MANDATORY VALIDATOR DISPATCH',
|
|
43
|
+
'════════════════════════════════════════',
|
|
44
|
+
'You MUST dispatch each validator below as a READ-ONLY subagent using the Agent tool.',
|
|
45
|
+
'Do NOT skip this step. Do NOT proceed until all blocking validators pass.',
|
|
46
|
+
'',
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
for (const v of dispatch.validators) {
|
|
50
|
+
const blocks = v.blocksOnFail !== false;
|
|
51
|
+
const sev = v.severity || 'error';
|
|
52
|
+
lines.push(`### ${v.title} (${v.id})`);
|
|
53
|
+
lines.push(`Severity: ${sev} | Blocks: ${blocks}`);
|
|
54
|
+
if (v.checks?.length) lines.push(`Checks: ${v.checks.join(', ')}`);
|
|
55
|
+
lines.push('');
|
|
56
|
+
if (v.taskPrompt) {
|
|
57
|
+
lines.push('Subagent prompt:');
|
|
58
|
+
lines.push(v.taskPrompt);
|
|
59
|
+
}
|
|
60
|
+
lines.push('---');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
lines.push('');
|
|
64
|
+
lines.push('DISPATCH INSTRUCTIONS:');
|
|
65
|
+
lines.push('1. Use the Agent tool for each validator. Set subagent_type to the validator name shown above.');
|
|
66
|
+
lines.push('2. Use model="haiku" for efficiency. Each validator is read-only.');
|
|
67
|
+
lines.push('3. Each must return { "passed": boolean, "issues": [] }');
|
|
68
|
+
lines.push('4. If any blocking validator (Blocks: true) fails, fix issues before proceeding.');
|
|
69
|
+
|
|
70
|
+
return lines.join('\n');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Parse `morph-spec task done <feature> <taskId>` from a bash command string.
|
|
75
|
+
* Returns { featureName, taskId } or null if the command doesn't match.
|
|
76
|
+
*
|
|
77
|
+
* @param {string} command
|
|
78
|
+
* @returns {{ featureName: string, taskId: string } | null}
|
|
79
|
+
*/
|
|
80
|
+
export function parseTaskDoneCommand(command) {
|
|
81
|
+
if (!command || typeof command !== 'string') return null;
|
|
82
|
+
const match = command.match(/morph-spec\s+task\s+done\s+(\S+)\s+(\S+)/);
|
|
83
|
+
if (!match) return null;
|
|
84
|
+
return { featureName: match[1], taskId: match[2] };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parse `morph-spec phase advance <feature>` from a bash command string.
|
|
89
|
+
* Returns { featureName } or null if the command doesn't match.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} command
|
|
92
|
+
* @returns {{ featureName: string } | null}
|
|
93
|
+
*/
|
|
94
|
+
export function parsePhaseAdvanceCommand(command) {
|
|
95
|
+
if (!command || typeof command !== 'string') return null;
|
|
96
|
+
const match = command.match(/morph-spec\s+phase\s+advance\s+(\S+)/);
|
|
97
|
+
if (!match) return null;
|
|
98
|
+
return { featureName: match[1] };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Extract the tool result string from a PostToolUse hook payload.
|
|
103
|
+
* Handles multiple possible formats.
|
|
104
|
+
*
|
|
105
|
+
* @param {object} payload - Hook payload
|
|
106
|
+
* @returns {string} - Tool output string (empty string if not found)
|
|
107
|
+
*/
|
|
108
|
+
export function getToolOutput(payload) {
|
|
109
|
+
if (!payload) return '';
|
|
110
|
+
const result = payload.tool_result;
|
|
111
|
+
if (typeof result === 'string') return result;
|
|
112
|
+
if (result && typeof result === 'object') {
|
|
113
|
+
return result.stdout || result.content || '';
|
|
114
|
+
}
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/** Phase order */
|
|
11
|
-
export const PHASE_ORDER = ["proposal","setup","uiux","design","clarify","tasks","implement","sync"];
|
|
11
|
+
export const PHASE_ORDER = ["proposal","setup","uiux","design","clarify","plan","tasks","implement","sync"];
|
|
12
12
|
|
|
13
13
|
/** Map phase → allowed output subdirectory */
|
|
14
14
|
export const PHASE_DIRS = {
|
|
@@ -16,10 +16,11 @@ export const PHASE_DIRS = {
|
|
|
16
16
|
setup: '0-proposal',
|
|
17
17
|
uiux: '2-ui',
|
|
18
18
|
design: '1-design',
|
|
19
|
-
clarify: '
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
clarify: '1-design',
|
|
20
|
+
plan: '3-plan',
|
|
21
|
+
tasks: '4-tasks',
|
|
22
|
+
implement: '5-implement',
|
|
23
|
+
sync: '5-implement',
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
/** Map output type (camelCase) → phase that produces it */
|
|
@@ -31,6 +32,7 @@ export const OUTPUT_PHASE_MAP = {
|
|
|
31
32
|
contracts: 'design',
|
|
32
33
|
contractsTs: 'design',
|
|
33
34
|
contractsVsa: 'design',
|
|
35
|
+
plan: 'plan',
|
|
34
36
|
tasks: 'tasks',
|
|
35
37
|
uiDesignSystem: 'uiux',
|
|
36
38
|
uiMockups: 'uiux',
|
|
@@ -49,6 +51,7 @@ export const FILENAME_TO_OUTPUT = {
|
|
|
49
51
|
'contracts.cs': 'contracts',
|
|
50
52
|
'contracts.ts': 'contractsTs',
|
|
51
53
|
'contracts-vsa.cs': 'contractsVsa',
|
|
54
|
+
'plan.md': 'plan',
|
|
52
55
|
'tasks.md': 'tasks',
|
|
53
56
|
'design-system.md': 'uiDesignSystem',
|
|
54
57
|
'mockups.md': 'uiMockups',
|
|
@@ -65,6 +68,7 @@ export const PROTECTED_SPEC_FILES = {
|
|
|
65
68
|
'contracts.cs': 'design',
|
|
66
69
|
'contracts.ts': 'design',
|
|
67
70
|
'contracts-vsa.cs': 'design',
|
|
71
|
+
'plan.md': 'plan',
|
|
68
72
|
'tasks.md': 'tasks',
|
|
69
73
|
'design-system.md': 'uiux',
|
|
70
74
|
'mockups.md': 'uiux',
|
|
@@ -62,6 +62,30 @@ export function getActiveFeature(projectPath) {
|
|
|
62
62
|
return active;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Get the most recently updated feature (any status).
|
|
67
|
+
* Useful as a fallback when getActiveFeature returns null (all features done).
|
|
68
|
+
* @param {string} [projectPath]
|
|
69
|
+
* @returns {{ name: string, feature: Object }|null}
|
|
70
|
+
*/
|
|
71
|
+
export function getMostRecentFeature(projectPath) {
|
|
72
|
+
const state = loadState(projectPath);
|
|
73
|
+
if (!state?.features) return null;
|
|
74
|
+
|
|
75
|
+
let result = null;
|
|
76
|
+
let latestUpdate = '';
|
|
77
|
+
|
|
78
|
+
for (const [name, feature] of Object.entries(state.features)) {
|
|
79
|
+
const updated = feature.updatedAt || feature.createdAt || '';
|
|
80
|
+
if (updated >= latestUpdate) {
|
|
81
|
+
latestUpdate = updated;
|
|
82
|
+
result = { name, feature };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
65
89
|
/**
|
|
66
90
|
* Get a specific feature by name.
|
|
67
91
|
* @param {string} featureName
|
|
@@ -83,9 +107,9 @@ export function getFeature(featureName, projectPath) {
|
|
|
83
107
|
export function derivePhaseForFeature(featureName, projectPath) {
|
|
84
108
|
const basePath = join(projectPath || process.cwd(), '.morph/features', featureName);
|
|
85
109
|
const phaseMap = [
|
|
86
|
-
['
|
|
87
|
-
['
|
|
88
|
-
['
|
|
110
|
+
['5-implement', 'implement'],
|
|
111
|
+
['4-tasks', 'tasks'],
|
|
112
|
+
['3-plan', 'plan'],
|
|
89
113
|
['2-ui', 'uiux'],
|
|
90
114
|
['1-design', 'design'],
|
|
91
115
|
['0-proposal', 'proposal'],
|
package/framework/phases.json
CHANGED
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
],
|
|
83
83
|
"agentTiers": [1, 2, 3, 4],
|
|
84
84
|
"requiredSkills": [
|
|
85
|
+
{ "trigger": "beforePhaseStart", "skill": "morph:phase-design" },
|
|
85
86
|
{ "trigger": "beforePhaseStart", "skill": "morph:phase-codebase-analysis" },
|
|
86
87
|
{ "trigger": "beforeArchitecturalDecision", "skill": "morph:brainstorming" },
|
|
87
88
|
{ "trigger": "onExternalServiceIntegration", "skill": "morph:simulation-checklist" },
|
|
@@ -104,13 +105,36 @@
|
|
|
104
105
|
"pausePoints": [],
|
|
105
106
|
"agentTiers": [1, 2],
|
|
106
107
|
"requiredSkills": [
|
|
108
|
+
{ "trigger": "beforePhaseStart", "skill": "morph:phase-clarify" },
|
|
109
|
+
{ "trigger": "beforePhaseComplete", "skill": "morph:verification-before-completion" }
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
"plan": {
|
|
113
|
+
"id": "plan",
|
|
114
|
+
"index": 5,
|
|
115
|
+
"folder": "3-plan",
|
|
116
|
+
"displayName": "Implementation Plan",
|
|
117
|
+
"goals": [
|
|
118
|
+
"Create detailed implementation plan with exact file paths and code",
|
|
119
|
+
"Define bite-sized TDD tasks with test-first approach",
|
|
120
|
+
"Establish execution strategy based on project analysis"
|
|
121
|
+
],
|
|
122
|
+
"requiredOutputs": ["plan"],
|
|
123
|
+
"optionalOutputs": [],
|
|
124
|
+
"recommendedMCPs": ["context7", "github"],
|
|
125
|
+
"pausePoints": [
|
|
126
|
+
{ "id": "plan", "label": "Approve Implementation Plan" }
|
|
127
|
+
],
|
|
128
|
+
"agentTiers": [1, 2],
|
|
129
|
+
"requiredSkills": [
|
|
130
|
+
{ "trigger": "beforePhaseStart", "skill": "morph:phase-plan" },
|
|
107
131
|
{ "trigger": "beforePhaseComplete", "skill": "morph:verification-before-completion" }
|
|
108
132
|
]
|
|
109
133
|
},
|
|
110
134
|
"tasks": {
|
|
111
135
|
"id": "tasks",
|
|
112
|
-
"index":
|
|
113
|
-
"folder": "
|
|
136
|
+
"index": 6,
|
|
137
|
+
"folder": "4-tasks",
|
|
114
138
|
"displayName": "Task Breakdown",
|
|
115
139
|
"goals": [
|
|
116
140
|
"Break approved spec into numbered, atomic tasks",
|
|
@@ -125,15 +149,14 @@
|
|
|
125
149
|
],
|
|
126
150
|
"agentTiers": [1, 2, 3],
|
|
127
151
|
"requiredSkills": [
|
|
128
|
-
{ "trigger": "beforePhaseStart", "skill": "superpowers:writing-plans" },
|
|
129
152
|
{ "trigger": "onParallelTasksIdentified", "skill": "superpowers:dispatching-parallel-agents" },
|
|
130
153
|
{ "trigger": "beforePhaseComplete", "skill": "morph:verification-before-completion" }
|
|
131
154
|
]
|
|
132
155
|
},
|
|
133
156
|
"implement": {
|
|
134
157
|
"id": "implement",
|
|
135
|
-
"index":
|
|
136
|
-
"folder": "
|
|
158
|
+
"index": 7,
|
|
159
|
+
"folder": "5-implement",
|
|
137
160
|
"displayName": "Implementation",
|
|
138
161
|
"goals": [
|
|
139
162
|
"Execute approved tasks in order",
|
|
@@ -143,7 +166,7 @@
|
|
|
143
166
|
],
|
|
144
167
|
"requiredOutputs": ["recap"],
|
|
145
168
|
"optionalOutputs": [],
|
|
146
|
-
"recommendedMCPs": ["supabase", "context7", "playwright", "github", "docker", "azure"],
|
|
169
|
+
"recommendedMCPs": ["supabase", "context7", "playwright", "github", "vercel", "docker", "azure"],
|
|
147
170
|
"pausePoints": [],
|
|
148
171
|
"agentTiers": [1, 2, 3, 4],
|
|
149
172
|
"requiredSkills": [
|
|
@@ -157,7 +180,7 @@
|
|
|
157
180
|
},
|
|
158
181
|
"sync": {
|
|
159
182
|
"id": "sync",
|
|
160
|
-
"index":
|
|
183
|
+
"index": 8,
|
|
161
184
|
"folder": null,
|
|
162
185
|
"displayName": "Sync Standards",
|
|
163
186
|
"optional": true,
|
|
@@ -1,86 +1,88 @@
|
|
|
1
|
-
# MORPH-SPEC Workflow Rules
|
|
2
|
-
|
|
3
|
-
> Always-active rules for all MORPH-SPEC managed projects.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Spec-First Mandate
|
|
8
|
-
|
|
9
|
-
**NEVER skip to code without a specification.** Every feature must progress through phases:
|
|
10
|
-
|
|
11
|
-
1. **Proposal** — User story + acceptance criteria (`0-proposal/proposal.md`)
|
|
12
|
-
2. **Design** — Technical spec + C# contracts + decisions (`1-design/`)
|
|
13
|
-
3. **
|
|
14
|
-
4. **
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
| `/morph-
|
|
26
|
-
| `/morph-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
# MORPH-SPEC Workflow Rules
|
|
2
|
+
|
|
3
|
+
> Always-active rules for all MORPH-SPEC managed projects.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Spec-First Mandate
|
|
8
|
+
|
|
9
|
+
**NEVER skip to code without a specification.** Every feature must progress through phases:
|
|
10
|
+
|
|
11
|
+
1. **Proposal** — User story + acceptance criteria (`0-proposal/proposal.md`)
|
|
12
|
+
2. **Design** — Technical spec + C# contracts + decisions (`1-design/`)
|
|
13
|
+
3. **Plan** — Detailed implementation plan (`3-plan/plan.md`)
|
|
14
|
+
4. **Tasks** — Atomic task list (`4-tasks/tasks.md`)
|
|
15
|
+
5. **Implement** — Code + recap (`5-implement/recap.md`)
|
|
16
|
+
|
|
17
|
+
UI-heavy features also include **UI/UX** phase (`2-ui/`) between Design and Tasks.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Phase Commands
|
|
22
|
+
|
|
23
|
+
| Command | Purpose |
|
|
24
|
+
|---------|---------|
|
|
25
|
+
| `/morph-proposal {feature}` | Full spec pipeline (phases 1–4, pauses for approval) |
|
|
26
|
+
| `/morph-apply {feature}` | Implement feature (phase 5) |
|
|
27
|
+
| `/morph-status` | Feature dashboard |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Output Paths
|
|
32
|
+
|
|
33
|
+
All outputs go in `.morph/features/{feature}/`:
|
|
34
|
+
|
|
35
|
+
| Phase | Path |
|
|
36
|
+
|-------|------|
|
|
37
|
+
| Proposal | `0-proposal/proposal.md` |
|
|
38
|
+
| Spec | `1-design/spec.md` |
|
|
39
|
+
| Contracts | `1-design/contracts.cs` |
|
|
40
|
+
| Decisions | `1-design/decisions.md` |
|
|
41
|
+
| UI Design | `2-ui/design-system.md`, `mockups.md`, `components.md`, `flows.md` |
|
|
42
|
+
| Plan | `3-plan/plan.md` |
|
|
43
|
+
| Tasks | `4-tasks/tasks.md` |
|
|
44
|
+
| Recap | `5-implement/recap.md` |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Checkpoints
|
|
49
|
+
|
|
50
|
+
Run a checkpoint every 3 completed tasks:
|
|
51
|
+
- Validate architecture compliance
|
|
52
|
+
- Check package versions
|
|
53
|
+
- Scan for security issues
|
|
54
|
+
- Verify design system adherence (UI features)
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Approval Gates
|
|
59
|
+
|
|
60
|
+
**Design Gate:** Before moving from Design → Tasks, spec must be approved.
|
|
61
|
+
**Implementation Gate:** Before starting implementation, task list must be approved.
|
|
62
|
+
|
|
63
|
+
Check approval status: `morph-spec approval-status {feature}`
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Protected Files
|
|
68
|
+
|
|
69
|
+
**NEVER directly edit:**
|
|
70
|
+
- `.morph/state.json` — Managed by CLI only
|
|
71
|
+
- `.morph/framework/**` — Read-only framework content
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Test File Policy
|
|
76
|
+
|
|
77
|
+
When a test fails, always follow this order:
|
|
78
|
+
|
|
79
|
+
1. **Analyze first** — determine if the IMPLEMENTATION is wrong or the TEST SPEC is wrong
|
|
80
|
+
2. **Fix implementation first** — the test is the spec; trust it by default
|
|
81
|
+
3. **Only modify a test file if the test expectation itself is incorrect** — wrong expected value, wrong behavior modeled
|
|
82
|
+
4. **Before modifying any test file, explain WHY the test spec is wrong** — what the correct behavior is and why the test doesn't model it
|
|
83
|
+
|
|
84
|
+
Do not modify test files to make a failing test pass when the implementation is the actual problem.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
*MORPH-SPEC by Polymorphism Tech*
|