@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/framework/agents.json
CHANGED
|
@@ -1282,7 +1282,7 @@
|
|
|
1282
1282
|
"teammate": {
|
|
1283
1283
|
"role": "CSS & Design System Specialist",
|
|
1284
1284
|
"icon": "🎨",
|
|
1285
|
-
"spawn_prompt": "You are the CSS & Design System Specialist (FASE 5 only). MANDATORY FIRST STEP: Read .morph/context/design-system.md. Validate all CSS follows the design system (
|
|
1285
|
+
"spawn_prompt": "You are the CSS & Design System Specialist (FASE 5 only). MANDATORY FIRST STEP: Read .morph/context/design-system.md. Validate all CSS follows the design system — colors (var(--color-*)), spacing (var(--space-*)), typography (var(--font-*, --text-*)), motion (var(--duration-*, --easing-*)), shadows (var(--shadow-*)), and advanced effects (var(--glass-*, --aurora-*, --perspective-*)). No off-palette hardcoded colors, no inline styles with raw values. Enforce naming conventions (BEM for custom classes). Verify WCAG AA contrast (4.5:1 text, 3:1 UI). Ref: framework/standards/frontend/design-system/design-trends.md for modern technique catalog. Run design-system, css, contrast validators. Any missing tokens must be added to design-system.md before proceeding."
|
|
1286
1286
|
}
|
|
1287
1287
|
},
|
|
1288
1288
|
"seo-growth-hacker": {
|
|
@@ -1988,7 +1988,11 @@
|
|
|
1988
1988
|
"design system",
|
|
1989
1989
|
"css",
|
|
1990
1990
|
"color palette",
|
|
1991
|
-
"spacing"
|
|
1991
|
+
"spacing",
|
|
1992
|
+
"motion tokens",
|
|
1993
|
+
"glassmorphism",
|
|
1994
|
+
"design trends",
|
|
1995
|
+
"advanced effects"
|
|
1992
1996
|
],
|
|
1993
1997
|
"validators": [
|
|
1994
1998
|
"design-system"
|
|
@@ -2008,13 +2012,16 @@
|
|
|
2008
2012
|
"teammate": {
|
|
2009
2013
|
"icon": "🎨",
|
|
2010
2014
|
"role": "Design System Validator (read-only)",
|
|
2011
|
-
"spawn_prompt": "You are the Design System Validator (Tier 4, READ-ONLY). Scan CSS/SCSS and component files for design system compliance:\n\n1. Color palette — look for hardcoded hex/rgb colors instead of CSS variables (var(--color-primary), var(--color-
|
|
2015
|
+
"spawn_prompt": "You are the Design System Validator (Tier 4, READ-ONLY). Scan CSS/SCSS and component files for design system compliance:\n\n1. Color palette — look for hardcoded hex/rgb colors instead of CSS variables (var(--color-primary), var(--color-accent), var(--color-surface-*), var(--color-text-*), etc.)\n2. Spacing — look for hardcoded px/rem values instead of spacing variables (var(--space-*))\n3. Typography — look for hardcoded font-size/font-family instead of typography variables (var(--font-display), var(--font-body), var(--text-*))\n4. Motion — look for hardcoded transition/animation durations instead of motion tokens (var(--duration-*), var(--easing-*))\n5. Shadows — look for hardcoded box-shadow instead of shadow tokens (var(--shadow-*), var(--shadow-colored-*), var(--shadow-layered-*))\n6. Advanced effects — verify glassmorphism uses tokens (var(--glass-*)), aurora uses tokens (var(--aurora-*)), perspective uses tokens (var(--perspective-*))\n7. Component naming — verify PascalCase for Blazor components (.razor) and kebab-case for CSS classes\n8. Check .morph/context/design-system.md for project-specific design tokens\n9. Ref: framework/standards/frontend/design-system/design-trends.md for modern technique catalog\n\nUse Grep and Glob to scan. Do NOT modify any files.\n\nOutput a JSON object: { \"passed\": boolean, \"issues\": [{ \"file\": string, \"line\": number, \"message\": string, \"severity\": \"warning\" }] }"
|
|
2012
2016
|
},
|
|
2013
2017
|
"hook_behavior": {
|
|
2014
2018
|
"validates": [
|
|
2015
|
-
"CSS color palette compliance (primary,
|
|
2016
|
-
"Spacing values (use var(--
|
|
2017
|
-
"Typography scale (use var(--font-*))",
|
|
2019
|
+
"CSS color palette compliance (primary, accent, surface, text, neutral, semantic)",
|
|
2020
|
+
"Spacing values (use var(--space-*))",
|
|
2021
|
+
"Typography scale (use var(--font-display), var(--font-body), var(--text-*))",
|
|
2022
|
+
"Motion tokens (use var(--duration-*), var(--easing-*))",
|
|
2023
|
+
"Shadow tokens (use var(--shadow-*), var(--shadow-colored-*), var(--shadow-layered-*))",
|
|
2024
|
+
"Advanced effects (glassmorphism: var(--glass-*), aurora: var(--aurora-*), perspective: var(--perspective-*))",
|
|
2018
2025
|
"Component naming (PascalCase for Blazor, kebab-case for CSS)"
|
|
2019
2026
|
],
|
|
2020
2027
|
"severity": "warning",
|
|
@@ -2129,6 +2136,9 @@
|
|
|
2129
2136
|
"active_phases": [
|
|
2130
2137
|
"implement"
|
|
2131
2138
|
],
|
|
2139
|
+
"domains": [
|
|
2140
|
+
"frontend-nextjs"
|
|
2141
|
+
],
|
|
2132
2142
|
"keywords": [
|
|
2133
2143
|
"nextjs",
|
|
2134
2144
|
"tsx",
|
|
@@ -110,6 +110,18 @@ morph-spec phase advance $ARGUMENTS
|
|
|
110
110
|
|
|
111
111
|
This validates phase eligibility and emits a SKILL DISPATCH block listing required skills for implementation (verification-before-completion, morph-checklist, etc.).
|
|
112
112
|
|
|
113
|
+
### Step 1.5: Create pipeline visibility task
|
|
114
|
+
|
|
115
|
+
> **MANDATORY** — Create umbrella task for implementation tracking.
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
TaskCreate: "Implement: {feature-name}"
|
|
119
|
+
→ description: "Execute T001-T00N from tasks.md with checkpoints"
|
|
120
|
+
→ activeForm: "Implementing feature"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Mark as `in_progress`. After all tasks complete (Step 5), mark as `completed`.
|
|
124
|
+
|
|
113
125
|
### Step 2: Initialize state tracking
|
|
114
126
|
|
|
115
127
|
```bash
|
|
@@ -145,6 +157,13 @@ morph-spec task done $ARGUMENTS {task-id}
|
|
|
145
157
|
- Re-run `task done` — do NOT use `--skip-validation` unless the user explicitly authorizes it
|
|
146
158
|
- After 3 consecutive failures, escalate to the user
|
|
147
159
|
|
|
160
|
+
**`--skip-validation` budget system:**
|
|
161
|
+
- Budget-limited: `min(5, ceil(totalTasks × 0.20))` — e.g., 5 tasks → 1 skip, 32 tasks → 5 skips
|
|
162
|
+
- Requires `--reason <text>` (minimum 5 characters) for audit trail
|
|
163
|
+
- Skipped tasks don't count as `passed` in validationHistory → degrades pass rate
|
|
164
|
+
- Usage: `morph-spec task done feat T001 --skip-validation --reason "CSS-only change, no logic"`
|
|
165
|
+
- When budget is exhausted, all remaining tasks must pass Tier-4 validation
|
|
166
|
+
|
|
148
167
|
**Parallel execution (agent teams):**
|
|
149
168
|
If `dispatch-agents` identified parallelizable task groups and agent teams are enabled, dispatch independent tasks to separate agents. Each agent still calls `task start` and `task done` for its assigned task.
|
|
150
169
|
|
|
@@ -212,7 +231,8 @@ Next: {next-task-id} — {next-task-title}
|
|
|
212
231
|
|
|
213
232
|
- Using `state set phase` instead of `phase advance` — phase advance validates eligibility first
|
|
214
233
|
- Skipping `task start` before implementing — the task-tracking guard will warn
|
|
215
|
-
- Using `--skip-validation` without user authorization
|
|
234
|
+
- Using `--skip-validation` without user authorization or without `--reason`
|
|
235
|
+
- Exhausting `--skip-validation` budget on trivial tasks — reserve for genuine emergencies
|
|
216
236
|
- Implementing without reading spec.md and contracts first
|
|
217
237
|
- Writing code before `phase advance` to implement — the hook will block writes
|
|
218
238
|
- Skipping checkpoints — they catch integration issues early
|
|
@@ -18,7 +18,7 @@ Check if the feature already has state:
|
|
|
18
18
|
morph-spec state get {feature-name}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
- **Exists:** Read the current phase and resume from where it stopped (skip completed phases)
|
|
21
|
+
- **Exists:** Read the current phase and resume from where it stopped (skip completed phases). Create pipeline master tasks (Step 6) and mark already-completed phases as `completed`.
|
|
22
22
|
- **Does not exist:** Start from scratch (PHASE 0)
|
|
23
23
|
|
|
24
24
|
---
|
|
@@ -75,6 +75,35 @@ morph-spec state set {feature-name} status draft
|
|
|
75
75
|
morph-spec state mark-output {feature-name} proposal
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
### Step 6: Create pipeline master tasks
|
|
79
|
+
|
|
80
|
+
> **MANDATORY** — Create one native task per pipeline phase for progress visibility.
|
|
81
|
+
> These are high-level tasks — one per phase, not per workflow step.
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
TaskCreate: "Phase 0: Proposal" → description: "Define feature scope and approach" → activeForm: "Proposal"
|
|
85
|
+
TaskCreate: "Phase 1: Setup" → description: "Load context, detect agents, confirm stack" → activeForm: "Setup"
|
|
86
|
+
TaskCreate: "Phase 2: Design" → description: "Schema analysis, spec, contracts, decisions" → activeForm: "Design"
|
|
87
|
+
TaskCreate: "Phase 3: Clarify" → description: "Resolve ambiguities and edge cases" → activeForm: "Clarify"
|
|
88
|
+
TaskCreate: "Phase 4: Plan" → description: "Implementation plan with TDD and file paths" → activeForm: "Plan"
|
|
89
|
+
TaskCreate: "Phase 5: Tasks" → description: "Break spec into T001-T00N with dependencies" → activeForm: "Tasks"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If `ui-designer` is among the activated agents, also create:
|
|
93
|
+
```
|
|
94
|
+
TaskCreate: "Phase 1.5: UI/UX" → description: "Design system, mockups, components, flows" → activeForm: "UI/UX"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Wire dependencies (addBlockedBy) matching the phase sequence:
|
|
98
|
+
- Setup ← Proposal
|
|
99
|
+
- UI/UX (if created) ← Setup
|
|
100
|
+
- Design ← UI/UX (or Setup if no UI/UX)
|
|
101
|
+
- Clarify ← Design
|
|
102
|
+
- Plan ← Clarify
|
|
103
|
+
- Tasks ← Plan
|
|
104
|
+
|
|
105
|
+
Mark "Phase 0: Proposal" as `in_progress` immediately.
|
|
106
|
+
|
|
78
107
|
### MANDATORY PAUSE
|
|
79
108
|
|
|
80
109
|
Use `AskUserQuestion` to present the approval gate with these elements:
|
|
@@ -100,6 +129,8 @@ Invoke the `morph-phase-setup` skill.
|
|
|
100
129
|
|
|
101
130
|
Summary: load project context, confirm stack, list active agents, update state.
|
|
102
131
|
|
|
132
|
+
> **Task lifecycle:** `TaskUpdate` the "Phase 0: Proposal" task → `completed`. `TaskUpdate` the "Phase 1: Setup" task → `in_progress`.
|
|
133
|
+
|
|
103
134
|
**No pause here.** Continue automatically to the next phase.
|
|
104
135
|
|
|
105
136
|
---
|
|
@@ -110,6 +141,8 @@ Check if `ui-designer` is in `activeAgents`:
|
|
|
110
141
|
- **Yes:** Invoke the `morph-phase-uiux` skill. **MANDATORY PAUSE** after generating UI deliverables.
|
|
111
142
|
- **No:** Skip to PHASE 2.
|
|
112
143
|
|
|
144
|
+
> **Task lifecycle:** `TaskUpdate` the "Phase 1: Setup" task → `completed`. `TaskUpdate` the "Phase 1.5: UI/UX" task → `in_progress` (if UI/UX), or the "Phase 2: Design" task → `in_progress` (if skipping UI/UX).
|
|
145
|
+
|
|
113
146
|
After approval:
|
|
114
147
|
```bash
|
|
115
148
|
morph-spec approve {feature-name} uiux
|
|
@@ -120,6 +153,8 @@ morph-spec phase advance {feature-name}
|
|
|
120
153
|
|
|
121
154
|
## 5. PHASE 2: DESIGN
|
|
122
155
|
|
|
156
|
+
> **Task lifecycle:** `TaskUpdate` the completing phase task (UI/UX or Setup) → `completed`. `TaskUpdate` the "Phase 2: Design" task → `in_progress`.
|
|
157
|
+
|
|
123
158
|
Invoke the `morph-phase-design` skill.
|
|
124
159
|
|
|
125
160
|
Summary: generate spec.md, contracts.cs (or contracts-vsa.cs for VSA), decisions.md with ADRs.
|
|
@@ -138,6 +173,8 @@ morph-spec phase advance {feature-name}
|
|
|
138
173
|
|
|
139
174
|
## 6. PHASE 3: CLARIFY (interactive)
|
|
140
175
|
|
|
176
|
+
> **Task lifecycle:** `TaskUpdate` the "Phase 2: Design" task → `completed`. `TaskUpdate` the "Phase 3: Clarify" task → `in_progress`.
|
|
177
|
+
|
|
141
178
|
Invoke the `morph-phase-clarify` skill.
|
|
142
179
|
|
|
143
180
|
Summary: identify ambiguities in spec.md, generate 3-7 targeted questions (building on the questions seeded in the proposal), wait for user answers, update spec with clarifications and edge cases.
|
|
@@ -148,6 +185,8 @@ Summary: identify ambiguities in spec.md, generate 3-7 targeted questions (build
|
|
|
148
185
|
|
|
149
186
|
## 7. PHASE 4: PLAN
|
|
150
187
|
|
|
188
|
+
> **Task lifecycle:** `TaskUpdate` the "Phase 3: Clarify" task → `completed`. `TaskUpdate` the "Phase 4: Plan" task → `in_progress`.
|
|
189
|
+
|
|
151
190
|
Invoke the `morph-phase-plan` skill.
|
|
152
191
|
|
|
153
192
|
Summary: generate a detailed implementation plan with exact file paths, TDD structure, and context-aware execution strategy.
|
|
@@ -166,6 +205,8 @@ morph-spec phase advance {feature-name}
|
|
|
166
205
|
|
|
167
206
|
## 8. PHASE 5: TASKS
|
|
168
207
|
|
|
208
|
+
> **Task lifecycle:** `TaskUpdate` the "Phase 4: Plan" task → `completed`. `TaskUpdate` the "Phase 5: Tasks" task → `in_progress`.
|
|
209
|
+
|
|
169
210
|
Invoke the `morph-phase-tasks` skill.
|
|
170
211
|
|
|
171
212
|
Summary: break spec into tasks T001-TXXX with dependencies, checkpoints, estimates.
|
|
@@ -184,6 +225,8 @@ morph-spec phase advance {feature-name}
|
|
|
184
225
|
|
|
185
226
|
## 9. Planning Complete
|
|
186
227
|
|
|
228
|
+
> **Task lifecycle:** `TaskUpdate` the "Phase 5: Tasks" task → `completed`.
|
|
229
|
+
|
|
187
230
|
After task approval:
|
|
188
231
|
|
|
189
232
|
```
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PostToolUse Hook: Agent Completion Tracker
|
|
5
|
+
*
|
|
6
|
+
* Event: PostToolUse | Matcher: Agent
|
|
7
|
+
*
|
|
8
|
+
* Detects when morph-spec subagents complete (dispatched via the Agent tool)
|
|
9
|
+
* and injects status notifications:
|
|
10
|
+
* - Partial: shows which agents are still pending
|
|
11
|
+
* - Complete: instructs to run validate-feature
|
|
12
|
+
*
|
|
13
|
+
* Only tracks tier 1-3 agents (not validators: morph-validator-*).
|
|
14
|
+
*
|
|
15
|
+
* Fail-open: exits 0 on any error.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { readStdin } from '../../shared/stdin-reader.js';
|
|
19
|
+
import { stateExists, getActiveFeature, getFeature, getFeaturePhase } from '../../shared/state-reader.js';
|
|
20
|
+
import { pass, injectContext } from '../../shared/hook-response.js';
|
|
21
|
+
import { logHookActivity } from '../../shared/activity-logger.js';
|
|
22
|
+
import { subagentTypeToAgentId } from '../../shared/dispatch-helpers.js';
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
if (!stateExists()) pass();
|
|
26
|
+
|
|
27
|
+
const payload = await readStdin();
|
|
28
|
+
if (!payload) pass();
|
|
29
|
+
|
|
30
|
+
const subagentType = payload?.tool_input?.subagent_type || '';
|
|
31
|
+
if (!subagentType) pass();
|
|
32
|
+
|
|
33
|
+
// Only track morph-* agents (not external subagents)
|
|
34
|
+
if (!subagentType.startsWith('morph-')) pass();
|
|
35
|
+
|
|
36
|
+
// Skip validators (tier 4) — they have their own tracking
|
|
37
|
+
if (subagentType.startsWith('morph-validator-')) pass();
|
|
38
|
+
|
|
39
|
+
const result = buildAgentCompleteContext(subagentType);
|
|
40
|
+
if (result) {
|
|
41
|
+
logHookActivity('agent-complete', 'PostToolUse', result.type);
|
|
42
|
+
injectContext(result.text);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
pass();
|
|
46
|
+
} catch {
|
|
47
|
+
// Fail-open
|
|
48
|
+
process.exit(0);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Build the agent completion notification context.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} subagentType - e.g. 'morph-nextjs-expert'
|
|
55
|
+
* @returns {{ text: string, type: string }|null}
|
|
56
|
+
*/
|
|
57
|
+
function buildAgentCompleteContext(subagentType) {
|
|
58
|
+
// Get active feature
|
|
59
|
+
const active = getActiveFeature();
|
|
60
|
+
if (!active) return null;
|
|
61
|
+
|
|
62
|
+
const { name: featureName, feature } = active;
|
|
63
|
+
|
|
64
|
+
// Only track during implement phase
|
|
65
|
+
const phase = getFeaturePhase(featureName);
|
|
66
|
+
if (phase !== 'implement') return null;
|
|
67
|
+
|
|
68
|
+
// Get dispatch log
|
|
69
|
+
const dispatchLog = feature.dispatchLog;
|
|
70
|
+
if (!Array.isArray(dispatchLog) || dispatchLog.length === 0) return null;
|
|
71
|
+
|
|
72
|
+
// Get the most recent dispatch entry
|
|
73
|
+
const latestDispatch = dispatchLog[dispatchLog.length - 1];
|
|
74
|
+
const agents = latestDispatch?.agents;
|
|
75
|
+
if (!Array.isArray(agents) || agents.length === 0) return null;
|
|
76
|
+
|
|
77
|
+
// Find the completing agent in the dispatch
|
|
78
|
+
const agentId = subagentTypeToAgentId(subagentType);
|
|
79
|
+
let matchedAgent = agents.find(a => a.subagentType === subagentType);
|
|
80
|
+
if (!matchedAgent && agentId) {
|
|
81
|
+
matchedAgent = agents.find(a => a.id === agentId);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!matchedAgent) return null;
|
|
85
|
+
|
|
86
|
+
// Mark this agent as completed (in-memory for evaluation only)
|
|
87
|
+
// Check which agents are still pending (no completedAt)
|
|
88
|
+
const pendingAgents = agents.filter(a => {
|
|
89
|
+
if (a === matchedAgent) return false; // The one just completed
|
|
90
|
+
return !a.completedAt;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const totalAgents = agents.length;
|
|
94
|
+
const completedCount = totalAgents - pendingAgents.length;
|
|
95
|
+
|
|
96
|
+
if (pendingAgents.length === 0) {
|
|
97
|
+
// All agents complete
|
|
98
|
+
return {
|
|
99
|
+
type: 'all_complete',
|
|
100
|
+
text: [
|
|
101
|
+
'✅ ALL MORPH-SPEC AGENTS COMPLETE',
|
|
102
|
+
'════════════════════════════════════════',
|
|
103
|
+
`All ${totalAgents} dispatched agents have completed their tasks.`,
|
|
104
|
+
'',
|
|
105
|
+
'NEXT STEP:',
|
|
106
|
+
` morph-spec validate-feature ${featureName} --phase implement`,
|
|
107
|
+
].join('\n'),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Partial completion
|
|
112
|
+
const remainingList = pendingAgents
|
|
113
|
+
.map(a => a.title || a.id || 'unknown')
|
|
114
|
+
.join(', ');
|
|
115
|
+
|
|
116
|
+
const agentTitle = matchedAgent.title || matchedAgent.id || subagentType;
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
type: 'partial_complete',
|
|
120
|
+
text: `✅ Agent '${agentTitle}' completed (${completedCount}/${totalAgents}). Remaining: ${remainingList}`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -27,7 +27,7 @@ import { readStdin } from '../../shared/stdin-reader.js';
|
|
|
27
27
|
import { stateExists, getFeature, getFeaturePhase } from '../../shared/state-reader.js';
|
|
28
28
|
import { pass, injectContext } from '../../shared/hook-response.js';
|
|
29
29
|
import { logHookActivity } from '../../shared/activity-logger.js';
|
|
30
|
-
import { extractValidationDispatch, formatValidatorInstruction, getToolOutput, parseTaskDoneCommand, parsePhaseAdvanceCommand } from '../../shared/dispatch-helpers.js';
|
|
30
|
+
import { extractValidationDispatch, formatValidatorInstruction, getToolOutput, parseTaskDoneCommand, parsePhaseAdvanceCommand, parseDispatchAgentsCommand } from '../../shared/dispatch-helpers.js';
|
|
31
31
|
|
|
32
32
|
try {
|
|
33
33
|
if (!stateExists()) pass();
|
|
@@ -73,8 +73,21 @@ async function dispatch(command, payload) {
|
|
|
73
73
|
const validatorText = await buildValidatorDispatchContext(featureName, payload);
|
|
74
74
|
if (validatorText) {
|
|
75
75
|
if (skipValidation) {
|
|
76
|
+
// Include budget info when available
|
|
77
|
+
let budgetInfo = '';
|
|
78
|
+
try {
|
|
79
|
+
const feature = getFeature(featureName);
|
|
80
|
+
if (feature) {
|
|
81
|
+
const total = feature.tasks?.total || 0;
|
|
82
|
+
const budget = total === 0 ? 1 : Math.max(1, Math.min(5, Math.ceil(total * 0.2)));
|
|
83
|
+
const used = (feature.skipValidationLog || []).length;
|
|
84
|
+
budgetInfo = ` (budget: ${used}/${budget})`;
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
// Non-blocking
|
|
88
|
+
}
|
|
76
89
|
contextParts.push(
|
|
77
|
-
|
|
90
|
+
`⏩ DEFERRED TO CHECKPOINT — validators skipped on this task${budgetInfo} but MUST run at next checkpoint:\n\n` +
|
|
78
91
|
validatorText
|
|
79
92
|
);
|
|
80
93
|
dispatchResult = 'task_done_deferred_validators';
|
|
@@ -107,6 +120,23 @@ async function dispatch(command, payload) {
|
|
|
107
120
|
const validatorText = await buildValidatorDispatchContext(featureName, payload);
|
|
108
121
|
if (validatorText) contextParts.push(validatorText);
|
|
109
122
|
|
|
123
|
+
// Mandatory dispatch instruction when advancing to implement phase
|
|
124
|
+
try {
|
|
125
|
+
const advancedPhase = getFeaturePhase(featureName);
|
|
126
|
+
if (advancedPhase === 'implement') {
|
|
127
|
+
contextParts.push(
|
|
128
|
+
'🔧 MANDATORY AGENT DISPATCH\n' +
|
|
129
|
+
'════════════════════════════════════════\n' +
|
|
130
|
+
`Run this command BEFORE starting any task:\n\n` +
|
|
131
|
+
` morph-spec dispatch-agents ${featureName} implement\n\n` +
|
|
132
|
+
`Task start will be BLOCKED until dispatch is recorded.\n` +
|
|
133
|
+
`Use the dispatch output to determine execution mode (single/subagents/agent-teams).`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
} catch {
|
|
137
|
+
// Non-blocking
|
|
138
|
+
}
|
|
139
|
+
|
|
110
140
|
logHookActivity('phase-dispatch', 'PostToolUse',
|
|
111
141
|
validatorText ? 'phase_advance_with_validators' : 'phase_chain');
|
|
112
142
|
|
|
@@ -116,6 +146,21 @@ async function dispatch(command, payload) {
|
|
|
116
146
|
pass();
|
|
117
147
|
}
|
|
118
148
|
|
|
149
|
+
// morph-spec dispatch-agents <feature> <phase>
|
|
150
|
+
const dispatchParsed = parseDispatchAgentsCommand(command);
|
|
151
|
+
if (dispatchParsed) {
|
|
152
|
+
const { featureName: dispFeature, phase: dispPhase } = dispatchParsed;
|
|
153
|
+
if (dispPhase === 'implement') {
|
|
154
|
+
injectContext(
|
|
155
|
+
`✓ Agent dispatch recorded for '${dispFeature}' (implement phase).\n` +
|
|
156
|
+
`You may now start tasks with: morph-spec task start ${dispFeature} <taskId>\n` +
|
|
157
|
+
`Use the dispatch config above to assign tasks to the correct typed agents.`
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
logHookActivity('phase-dispatch', 'PostToolUse', 'dispatch_agents_confirmed');
|
|
161
|
+
pass();
|
|
162
|
+
}
|
|
163
|
+
|
|
119
164
|
// morph-spec approve <feature> <gate>
|
|
120
165
|
const approveMatch = command.match(/morph-spec\s+approve\s+(\S+)\s+(\S+)/);
|
|
121
166
|
if (approveMatch) {
|
|
@@ -125,10 +125,11 @@ try {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// Task tracking guidance for work phases
|
|
128
|
-
if (['design', 'tasks', 'implement'].includes(phase)) {
|
|
128
|
+
if (['proposal', 'setup', 'uiux', 'design', 'clarify', 'plan', 'tasks', 'implement'].includes(phase)) {
|
|
129
129
|
lines.push('');
|
|
130
|
-
lines.push('
|
|
131
|
-
lines.push('
|
|
130
|
+
lines.push('⚠️ MANDATORY: Create session tasks (TaskCreate) BEFORE starting phase work.');
|
|
131
|
+
lines.push(' Analyze the phase workflow and create tasks reflecting your planned actions.');
|
|
132
|
+
lines.push(' Mark each in_progress → completed as you go. See phase skill for guidance.');
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
// Trust level visibility — warn when low trust may block approval gates
|
|
@@ -98,6 +98,37 @@ export function parsePhaseAdvanceCommand(command) {
|
|
|
98
98
|
return { featureName: match[1] };
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Parse `morph-spec dispatch-agents <feature> <phase>` from a bash command string.
|
|
103
|
+
* Returns { featureName, phase } or null if the command doesn't match.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} command
|
|
106
|
+
* @returns {{ featureName: string, phase: string } | null}
|
|
107
|
+
*/
|
|
108
|
+
export function parseDispatchAgentsCommand(command) {
|
|
109
|
+
if (!command || typeof command !== 'string') return null;
|
|
110
|
+
const match = command.match(/morph-spec\s+dispatch-agents\s+(\S+)\s+(\S+)/);
|
|
111
|
+
if (!match) return null;
|
|
112
|
+
return { featureName: match[1], phase: match[2] };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Convert a subagent_type string back to a morph agent ID.
|
|
117
|
+
* Reverses the mapping used when dispatching agents as subagents.
|
|
118
|
+
*
|
|
119
|
+
* Example: 'morph-nextjs-expert' → 'nextjs-expert'
|
|
120
|
+
*
|
|
121
|
+
* @param {string} subagentType - The subagent_type value (e.g. 'morph-nextjs-expert')
|
|
122
|
+
* @returns {string|null} - Agent ID without 'morph-' prefix, or null if invalid
|
|
123
|
+
*/
|
|
124
|
+
export function subagentTypeToAgentId(subagentType) {
|
|
125
|
+
if (!subagentType || typeof subagentType !== 'string') return null;
|
|
126
|
+
if (!subagentType.startsWith('morph-')) return null;
|
|
127
|
+
const agentId = subagentType.slice('morph-'.length);
|
|
128
|
+
if (!agentId) return null;
|
|
129
|
+
return agentId;
|
|
130
|
+
}
|
|
131
|
+
|
|
101
132
|
/**
|
|
102
133
|
* Extract the tool result string from a PostToolUse hook payload.
|
|
103
134
|
* Handles multiple possible formats.
|
|
@@ -142,7 +142,9 @@ export function getFeaturePhase(featureName, projectPath) {
|
|
|
142
142
|
*/
|
|
143
143
|
export function isGateApproved(featureName, gate, projectPath) {
|
|
144
144
|
const feature = getFeature(featureName, projectPath);
|
|
145
|
-
|
|
145
|
+
// Support both field names: 'approvals' (v5 state) and 'approvalGates' (legacy)
|
|
146
|
+
const gates = feature?.approvals || feature?.approvalGates;
|
|
147
|
+
return gates?.[gate]?.approved === true;
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
/**
|
|
@@ -153,9 +155,11 @@ export function isGateApproved(featureName, gate, projectPath) {
|
|
|
153
155
|
*/
|
|
154
156
|
export function getPendingGates(featureName, projectPath) {
|
|
155
157
|
const feature = getFeature(featureName, projectPath);
|
|
156
|
-
|
|
158
|
+
// Support both field names: 'approvals' (v5 state) and 'approvalGates' (legacy)
|
|
159
|
+
const gates = feature?.approvals || feature?.approvalGates;
|
|
160
|
+
if (!gates) return [];
|
|
157
161
|
|
|
158
|
-
return Object.entries(
|
|
162
|
+
return Object.entries(gates)
|
|
159
163
|
.filter(([, gate]) => !gate.approved)
|
|
160
164
|
.map(([name]) => name);
|
|
161
165
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
stacks:
|
|
3
|
+
- "*"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MORPH-SPEC Task Tracking
|
|
7
|
+
|
|
8
|
+
> Session tasks are MANDATORY in every MORPH-SPEC phase. They track real progress and must be
|
|
9
|
+
> created BEFORE any phase work begins.
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
|
|
13
|
+
1. **Every phase skill MUST create session tasks** using `TaskCreate` before reading files or generating outputs
|
|
14
|
+
2. **Tasks are dynamic** — analyze the phase workflow and create tasks that reflect YOUR actual planned actions for this session
|
|
15
|
+
3. **Every task MUST be updated**: `in_progress` before starting, `completed` after finishing
|
|
16
|
+
4. **Pipeline orchestrators** (`/morph-proposal`, `/morph-apply`) MUST create master tasks for each phase
|
|
17
|
+
5. **Never skip task creation** — even if resuming mid-phase, create tasks for remaining steps
|
|
18
|
+
6. **Granularity**: minimum 2, typically 3-7 tasks per phase — adjust to complexity
|
|
19
|
+
7. **For iterative work** (clarification rounds, quality loops): update task `subject` with round/score progress
|
|
20
|
+
|
|
21
|
+
## Task Update Pattern
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
TaskUpdate(taskId, status="in_progress") // before starting the step
|
|
25
|
+
// ... do the work ...
|
|
26
|
+
TaskUpdate(taskId, status="completed") // after step finishes
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For iterative tasks:
|
|
30
|
+
```
|
|
31
|
+
TaskUpdate(taskId, subject="Round 3 — score 82/100")
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Deviation Tracking
|
|
35
|
+
|
|
36
|
+
When completing a task differently than originally planned, record the reason:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
morph-spec task done <feature> <taskId> --note "Reason for deviation"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For after-the-fact annotation (supports multiple types):
|
|
43
|
+
```
|
|
44
|
+
morph-spec task annotate <feature> <taskId> "Reason" --type deviation
|
|
45
|
+
morph-spec task annotate <feature> <taskId> "Context info" --type context
|
|
46
|
+
morph-spec task annotate <feature> <taskId> "Resolved" --type blocker-resolved
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Note types: `deviation` (default), `context`, `blocker-resolved`
|
|
@@ -33,17 +33,13 @@ allowed-tools: Read, Bash, Glob, Grep, AskUserQuestion
|
|
|
33
33
|
|
|
34
34
|
## Workflow
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
## MANDATORY: Session Tasks
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
TaskCreate: "Document recommendation" → activeForm: "Documenting"
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Update each to `in_progress` before its step and `completed` after.
|
|
38
|
+
> **BEFORE starting any brainstorming work**, analyze what you need to do and create session tasks.
|
|
39
|
+
>
|
|
40
|
+
> **Rules:** Minimum 2 tasks, typically 3-5. Mark `in_progress` before starting, `completed` after.
|
|
41
|
+
>
|
|
42
|
+
> **Typical tasks:** context exploration, clarifying questions, approach analysis, recommendation, documentation
|
|
47
43
|
|
|
48
44
|
### Step 1: Explore Context
|
|
49
45
|
|
|
@@ -4,7 +4,7 @@ description: MORPH-SPEC Phase 3 (Clarify). Iterative clarification loop driven b
|
|
|
4
4
|
argument-hint: "[feature-name]"
|
|
5
5
|
user-invocable: false
|
|
6
6
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
|
|
7
|
-
cliVersion: "4.
|
|
7
|
+
cliVersion: "4.12.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MORPH Clarify — Phase 3
|
|
@@ -94,6 +94,15 @@ Read: .morph/features/$ARGUMENTS/1-design/spec.md
|
|
|
94
94
|
|
|
95
95
|
Calculate the initial score. Track accumulated answers from prior rounds to avoid repeating already-answered questions.
|
|
96
96
|
|
|
97
|
+
## MANDATORY: Session Tasks
|
|
98
|
+
|
|
99
|
+
> **BEFORE starting clarification work**, analyze the spec quality and create session tasks.
|
|
100
|
+
>
|
|
101
|
+
> **Rules:** Minimum 2 tasks, typically 2-4. Mark `in_progress` before starting, `completed` after.
|
|
102
|
+
> For the clarification loop, update the task `subject` with round and score progress.
|
|
103
|
+
>
|
|
104
|
+
> **Typical tasks:** initial score calculation, clarification rounds (iterative), output generation
|
|
105
|
+
|
|
97
106
|
---
|
|
98
107
|
|
|
99
108
|
### Main Loop
|
|
@@ -3,7 +3,7 @@ name: morph-phase-codebase-analysis
|
|
|
3
3
|
description: MORPH-SPEC Design sub-phase that analyzes existing codebase and database schema, producing schema-analysis.md with real column names, types, relationships, and field mismatches. Use at the start of Design phase before generating contracts.cs to prevent incorrect field names or types.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
|
|
6
|
-
cliVersion: "4.
|
|
6
|
+
cliVersion: "4.12.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# MORPH Codebase Analysis - Design Sub-phase
|
|
@@ -4,7 +4,7 @@ description: MORPH-SPEC Phase 2 (Design). Schema-first interactive design: reads
|
|
|
4
4
|
argument-hint: "[feature-name]"
|
|
5
5
|
user-invocable: false
|
|
6
6
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent
|
|
7
|
-
cliVersion: "4.
|
|
7
|
+
cliVersion: "4.12.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MORPH Design — Phase 2
|
|
@@ -53,19 +53,13 @@ Schema-first interactive design: read the real schema, validate with user, gener
|
|
|
53
53
|
|
|
54
54
|
## PRE-FLIGHT
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
## MANDATORY: Session Tasks
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
TaskCreate: "Generate contracts" → activeForm: "Writing contracts"
|
|
64
|
-
TaskCreate: "Generate decisions.md" → activeForm: "Documenting decisions"
|
|
65
|
-
TaskCreate: "Design approval" → activeForm: "Awaiting design approval"
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Update each to `in_progress` before starting and `completed` after finishing.
|
|
58
|
+
> **BEFORE starting any design work**, analyze the workflow below and create session tasks.
|
|
59
|
+
>
|
|
60
|
+
> **Rules:** Minimum 3 tasks, typically 5-7. Mark `in_progress` before starting, `completed` after.
|
|
61
|
+
>
|
|
62
|
+
> **Typical tasks:** pre-flight validation, schema analysis, architecture blueprint, spec generation, contracts generation, decisions documentation, design approval
|
|
69
63
|
|
|
70
64
|
---
|
|
71
65
|
|
|
@@ -5,7 +5,7 @@ argument-hint: "[feature-name]"
|
|
|
5
5
|
context: fork
|
|
6
6
|
agent: general-purpose
|
|
7
7
|
user-invocable: false
|
|
8
|
-
cliVersion: "4.
|
|
8
|
+
cliVersion: "4.12.0"
|
|
9
9
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -150,6 +150,12 @@ Use `AskUserQuestion` with header `"{MCP}"` and options:
|
|
|
150
150
|
|
|
151
151
|
## Context Loading
|
|
152
152
|
|
|
153
|
+
## MANDATORY: Session Tasks
|
|
154
|
+
|
|
155
|
+
> **You MUST create one native task per T001-T00N from tasks.md BEFORE starting implementation.**
|
|
156
|
+
> After creating all tasks, wire dependencies using `addBlockedBy`.
|
|
157
|
+
> Update each to `in_progress` before starting and `completed` after `task done` succeeds.
|
|
158
|
+
|
|
153
159
|
### 1. Read full context in PARALLEL
|
|
154
160
|
|
|
155
161
|
```
|