@polymorphism-tech/morph-spec 4.17.0 → 4.19.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.
Files changed (70) hide show
  1. package/CLAUDE.md +36 -0
  2. package/README.md +2 -2
  3. package/bin/task-manager.js +12 -0
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/agents/architecture/architecture-expert.md +86 -0
  8. package/framework/agents/architecture/morph-spec-architect.md +66 -0
  9. package/framework/agents/architecture/packages-validator.md +77 -0
  10. package/framework/agents/architecture/security-expert.md +67 -0
  11. package/framework/agents/backend/ms-agent-expert.md +1 -1
  12. package/framework/agents/backend/neon-expert.md +9 -27
  13. package/framework/agents/frontend/design-system-validator.md +88 -0
  14. package/framework/agents/frontend/nextjs-component-validator.md +85 -0
  15. package/framework/agents/frontend/{ui-ux-designer.md → ui-designer.md} +31 -0
  16. package/framework/agents/integrations/neon-auth.md +151 -0
  17. package/framework/agents.json +22 -14
  18. package/framework/hooks/claude-code/post-tool-use/dispatch.js +39 -0
  19. package/framework/hooks/claude-code/post-tool-use/handle-tool-failure.js +78 -44
  20. package/framework/hooks/claude-code/post-tool-use/loop-detect.js +103 -0
  21. package/framework/hooks/claude-code/session-start/inject-morph-context.js +21 -2
  22. package/framework/hooks/claude-code/stop/validate-completion.js +48 -1
  23. package/framework/hooks/shared/activity-logger.js +56 -1
  24. package/framework/hooks/shared/build-check.js +79 -0
  25. package/framework/hooks/shared/payload-utils.js +39 -0
  26. package/framework/hooks/shared/session-snapshot.js +105 -0
  27. package/framework/phases.json +1 -1
  28. package/framework/rules/neon-auth-standards.md +13 -0
  29. package/framework/rules/neon-standards.md +1 -0
  30. package/framework/skills/level-0-meta/mcp-registry.json +34 -1
  31. package/framework/skills/level-0-meta/morph-agent-teams/SKILL.md +3 -3
  32. package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +1 -1
  33. package/framework/skills/level-0-meta/morph-init/SKILL.md +4 -4
  34. package/framework/skills/level-1-workflows/morph-phase-codebase-analysis/SKILL.md +1 -1
  35. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +11 -1
  36. package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +12 -1
  37. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
  38. package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
  39. package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +119 -11
  40. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
  41. package/framework/standards/STANDARDS.json +13 -9
  42. package/framework/standards/ai-agents/production.md +5 -2
  43. package/framework/standards/ai-agents/setup.md +13 -14
  44. package/framework/standards/ai-agents/workflows.md +8 -6
  45. package/framework/standards/backend/database/postgresql/database.md +5 -5
  46. package/framework/standards/backend/database/vector-search-rag.md +1 -1
  47. package/framework/standards/backend/integrations/asaas/asaas-api.md +1 -1
  48. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +364 -0
  49. package/framework/standards/frontend/nextjs/nextjs-patterns.md +9 -9
  50. package/framework/templates/README.md +2 -2
  51. package/framework/templates/REGISTRY.json +5 -5
  52. package/framework/templates/code/dotnet/jobs/agent.cs +0 -1
  53. package/framework/templates/code/sql/postgresql-migration.sql +10 -10
  54. package/framework/templates/code/sql/postgresql-migration.template.sql +12 -14
  55. package/framework/templates/code/sql/postgresql-rls-policy.sql +6 -9
  56. package/framework/templates/feature/decisions.md +8 -7
  57. package/framework/templates/integrations/neon-auth-config.cs +133 -0
  58. package/framework/workflows/docs/full-morph.md +1 -1
  59. package/package.json +1 -1
  60. package/src/commands/mcp/mcp-setup.js +21 -0
  61. package/src/commands/project/init.js +11 -0
  62. package/src/lib/contracts/sprint-contract-generator.js +137 -0
  63. package/src/lib/detectors/index.js +2 -2
  64. package/src/lib/generators/architecture-scanner.js +2 -3
  65. package/src/lib/installers/mcp-installer.js +25 -0
  66. package/src/utils/hooks-installer.js +12 -1
  67. package/framework/agents/integrations/clerk-auth.md +0 -109
  68. package/framework/rules/clerk-standards.md +0 -13
  69. package/framework/standards/backend/integrations/clerk/clerk-auth.md +0 -292
  70. package/framework/templates/integrations/clerk-config.cs +0 -217
@@ -20,11 +20,13 @@
20
20
 
21
21
  import { readFileSync, writeFileSync, existsSync } from 'fs';
22
22
  import { join } from 'path';
23
+ import { runBuildCheck } from '../../shared/build-check.js';
24
+ import { saveSessionSnapshot } from '../../shared/session-snapshot.js';
23
25
  import {
24
26
  stateExists, getActiveFeature, getMostRecentFeature, getMissingOutputs, derivePhaseForFeature,
25
27
  } from '../../shared/state-reader.js';
26
28
  import { injectContext, pass } from '../../shared/hook-response.js';
27
- import { logHookActivity } from '../../shared/activity-logger.js';
29
+ import { logHookActivity, logEvent } from '../../shared/activity-logger.js';
28
30
 
29
31
  // Phases where compaction is strongly recommended before starting
30
32
  const COMPACT_TRIGGER_PHASES = new Set(['implement']);
@@ -82,6 +84,50 @@ try {
82
84
  );
83
85
  }
84
86
 
87
+ // ── Build/typecheck verification ──────────────────────────────────────────
88
+ // Stack-aware build check — advisory warning if build fails.
89
+ // Success is silent (no output on pass).
90
+ try {
91
+ const configPath = join(cwd, '.morph', 'config', 'config.json');
92
+ if (existsSync(configPath)) {
93
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
94
+ const stack = config?.project?.stack;
95
+ if (stack && currentPhase === 'implement') {
96
+ const buildResult = runBuildCheck(cwd, stack);
97
+ if (buildResult.status === 'fail') {
98
+ warnings.push('⚠ Build/typecheck failed:');
99
+ warnings.push(buildResult.output);
100
+ warnings.push('Fix build errors before ending session.');
101
+ }
102
+ // pass and skip → silent (success is silent)
103
+ }
104
+ }
105
+ } catch {
106
+ // Fail-open — build check must never block Stop
107
+ }
108
+ // ────────────────────────────────────────────────────────────────────────
109
+
110
+ // ── Session snapshot ──────────────────────────────────────────────────────
111
+ // Save session state for next session's "getting up to speed" routine.
112
+ try {
113
+ if (active) {
114
+ const { name, feature } = active;
115
+ const taskList = feature.taskList || [];
116
+ saveSessionSnapshot({
117
+ feature: name,
118
+ phase: currentPhase,
119
+ tasksCompleted: taskList.filter(t => t.status === 'completed').map(t => t.id),
120
+ tasksRemaining: taskList.filter(t => t.status === 'pending').map(t => t.id),
121
+ tasksInProgress: taskList.filter(t => t.status === 'in_progress').map(t => t.id),
122
+ buildStatus: 'skip',
123
+ lastEditedFiles: [],
124
+ }, cwd);
125
+ }
126
+ } catch {
127
+ // Fail-open — snapshot save must never block Stop
128
+ }
129
+ // ────────────────────────────────────────────────────────────────────────
130
+
85
131
  // ── Incomplete work checks ────────────────────────────────────────────────
86
132
 
87
133
  // Incomplete tasks during implement phase
@@ -152,6 +198,7 @@ try {
152
198
  ].join('\n');
153
199
 
154
200
  logHookActivity('validate-completion', 'Stop', `warnings(${warnings.length})`);
201
+ logEvent('session_end', { feature: name, phase: currentPhase, warnings: warnings.length });
155
202
  injectContext(message);
156
203
  } catch {
157
204
  process.exit(0);
@@ -11,7 +11,7 @@
11
11
  * - Windows-safe paths via path.join
12
12
  */
13
13
 
14
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
14
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
15
15
  import { join } from 'path';
16
16
 
17
17
  const LOGS_DIR = '.morph/logs';
@@ -103,3 +103,58 @@ export function resetActivity(sessionId, feature, phase, projectPath) {
103
103
  // Fail-silent
104
104
  }
105
105
  }
106
+
107
+ /**
108
+ * Log a structured event to the session activity log.
109
+ *
110
+ * @param {string} type - Event type (e.g., 'task_start', 'loop_detected')
111
+ * @param {Object} data - Event data payload
112
+ * @param {string} [projectPath] - Project root (defaults to cwd)
113
+ */
114
+ export function logEvent(type, data, projectPath) {
115
+ try {
116
+ const activityPath = getActivityPath(projectPath);
117
+ ensureLogsDir(projectPath);
118
+
119
+ const now = new Date();
120
+ const ts = now.toTimeString().slice(0, 8); // HH:MM:SS
121
+
122
+ const activity = readRaw(activityPath) || { sessionId: '', feature: '', phase: '', hooks: [], events: [] };
123
+ activity.events = activity.events || [];
124
+ activity.events.push({ type, data, ts });
125
+
126
+ writeFileSync(activityPath, JSON.stringify(activity, null, 2), 'utf-8');
127
+ } catch {
128
+ // Fail-silent
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Archive current activity.json to sessions/ directory for historical logging.
134
+ * Called at the start of a new session.
135
+ *
136
+ * @param {string} [projectPath] - Project root (defaults to cwd)
137
+ */
138
+ export function archiveSession(projectPath) {
139
+ try {
140
+ const activityPath = getActivityPath(projectPath);
141
+ if (!existsSync(activityPath)) return;
142
+
143
+ const data = readRaw(activityPath);
144
+ if (!data) return;
145
+
146
+ // Only archive if there are meaningful events
147
+ if ((!data.hooks || data.hooks.length === 0) && (!data.events || data.events.length === 0)) return;
148
+
149
+ const sessionsDir = join(projectPath || process.cwd(), LOGS_DIR, 'sessions');
150
+ mkdirSync(sessionsDir, { recursive: true });
151
+
152
+ const sessionId = (data.sessionId || new Date().toISOString()).replace(/[:.]/g, '-');
153
+ const archivePath = join(sessionsDir, `${sessionId}.json`);
154
+ writeFileSync(archivePath, JSON.stringify(data, null, 2), 'utf-8');
155
+
156
+ unlinkSync(activityPath);
157
+ } catch {
158
+ // Fail-silent
159
+ }
160
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Build/Typecheck verification utility.
3
+ *
4
+ * Stack-aware: determines the correct build command based on project stack.
5
+ * Used by the Stop hook to verify code health before session ends.
6
+ *
7
+ * Pure functions — no I/O except the actual build execution.
8
+ */
9
+
10
+ import { execSync } from 'child_process';
11
+ import { existsSync } from 'fs';
12
+ import { join } from 'path';
13
+
14
+ /**
15
+ * Determine the build command for a given stack.
16
+ *
17
+ * @param {string} stack - Project stack (e.g., 'dotnet-nextjs', 'nextjs')
18
+ * @param {boolean} [hasTsConfig] - Whether tsconfig.json exists (for TS projects)
19
+ * @returns {string|null} Build command or null if no check available
20
+ */
21
+ export function getBuildCommand(stack, hasTsConfig = false) {
22
+ if (!stack) return null;
23
+ const s = stack.toLowerCase();
24
+
25
+ if (s.includes('dotnet')) {
26
+ return 'dotnet build --no-restore --nologo -v q 2>&1 | tail -20';
27
+ }
28
+
29
+ if ((s.includes('nextjs') || s.includes('node') || s.includes('react')) && hasTsConfig) {
30
+ return 'npx tsc --noEmit 2>&1 | tail -20';
31
+ }
32
+
33
+ return null;
34
+ }
35
+
36
+ /**
37
+ * Parse build command result into a structured object.
38
+ *
39
+ * @param {number} exitCode - Process exit code (0 = success)
40
+ * @param {string} output - stdout+stderr from build
41
+ * @returns {{ status: 'pass'|'fail', output: string }}
42
+ */
43
+ export function parseBuildResult(exitCode, output) {
44
+ const trimmed = (output || '').trim();
45
+ if (exitCode === 0) {
46
+ return { status: 'pass', output: '' };
47
+ }
48
+ // Truncate to last 20 lines
49
+ const lines = trimmed.split('\n');
50
+ const truncated = lines.slice(-20).join('\n');
51
+ return { status: 'fail', output: truncated };
52
+ }
53
+
54
+ /**
55
+ * Run build check for a project.
56
+ *
57
+ * @param {string} cwd - Project root directory
58
+ * @param {string} stack - Project stack string
59
+ * @param {number} [timeout=30000] - Timeout in ms
60
+ * @returns {{ status: 'pass'|'fail'|'skip', output: string }}
61
+ */
62
+ export function runBuildCheck(cwd, stack, timeout = 30000) {
63
+ const hasTsConfig = existsSync(join(cwd, 'tsconfig.json'));
64
+ const cmd = getBuildCommand(stack, hasTsConfig);
65
+ if (!cmd) return { status: 'skip', output: '' };
66
+
67
+ try {
68
+ const output = execSync(cmd, {
69
+ cwd,
70
+ encoding: 'utf-8',
71
+ timeout,
72
+ stdio: ['pipe', 'pipe', 'pipe']
73
+ });
74
+ return parseBuildResult(0, output);
75
+ } catch (err) {
76
+ const output = (err.stdout || '') + (err.stderr || '');
77
+ return parseBuildResult(err.status || 1, output);
78
+ }
79
+ }
@@ -37,3 +37,42 @@ export function getContentToValidate(payload) {
37
37
  export function isWriteOperation(payload) {
38
38
  return typeof payload?.tool_input?.content === 'string';
39
39
  }
40
+
41
+ /**
42
+ * Get the tool name from a hook payload.
43
+ * @param {Object} payload - Hook payload from stdin
44
+ * @returns {string} Tool name or 'unknown'
45
+ */
46
+ export function getToolName(payload) {
47
+ return payload?.tool_name || 'unknown';
48
+ }
49
+
50
+ /**
51
+ * Build a normalized signature for loop detection.
52
+ * - Edit/Write: "Edit:normalized/file/path"
53
+ * - Bash: "Bash:first two words" (e.g., "Bash:npm test")
54
+ * - Other: just the tool name
55
+ *
56
+ * @param {Object} payload - Hook payload from stdin
57
+ * @returns {string} Signature string
58
+ */
59
+ export function getCommandSignature(payload) {
60
+ const tool = getToolName(payload);
61
+ if (tool === 'unknown') return 'unknown';
62
+
63
+ const input = payload?.tool_input;
64
+ if (!input) return tool;
65
+
66
+ if (tool === 'Edit' || tool === 'Write') {
67
+ const path = (input.file_path || input.path || '').replace(/\\/g, '/');
68
+ return path ? `${tool}:${path}` : tool;
69
+ }
70
+
71
+ if (tool === 'Bash') {
72
+ const cmd = (input.command || '').trim();
73
+ const words = cmd.split(/\s+/).slice(0, 2).join(' ');
74
+ return words ? `Bash:${words}` : 'Bash';
75
+ }
76
+
77
+ return tool;
78
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Session Snapshot — cross-session persistence utility
3
+ *
4
+ * Saves and loads session state for "getting up to speed" on next session.
5
+ * Single file (overwrites) — history preserved via git.
6
+ *
7
+ * Fail-silent: never throws.
8
+ */
9
+
10
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync, unlinkSync } from 'fs';
11
+ import { join } from 'path';
12
+
13
+ const SNAPSHOT_PATH = '.morph/memory/session-snapshot.json';
14
+
15
+ /**
16
+ * Save session snapshot atomically.
17
+ * @param {Object} data - Snapshot data
18
+ * @param {string} [projectPath] - Project root (defaults to cwd)
19
+ */
20
+ export function saveSessionSnapshot(data, projectPath) {
21
+ try {
22
+ const root = projectPath || process.cwd();
23
+ const dir = join(root, '.morph', 'memory');
24
+ mkdirSync(dir, { recursive: true });
25
+
26
+ const snapshot = { ...data, savedAt: new Date().toISOString() };
27
+ const filePath = join(root, SNAPSHOT_PATH);
28
+ const tmpPath = `${filePath}.tmp.${process.pid}`;
29
+
30
+ writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), 'utf-8');
31
+ try {
32
+ renameSync(tmpPath, filePath);
33
+ } catch {
34
+ writeFileSync(filePath, JSON.stringify(snapshot, null, 2), 'utf-8');
35
+ try { unlinkSync(tmpPath); } catch { /* ignore */ }
36
+ }
37
+ } catch {
38
+ // Fail-silent
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Load session snapshot.
44
+ * @param {string} [projectPath] - Project root (defaults to cwd)
45
+ * @returns {Object|null} Parsed snapshot or null
46
+ */
47
+ export function loadSessionSnapshot(projectPath) {
48
+ try {
49
+ const filePath = join(projectPath || process.cwd(), SNAPSHOT_PATH);
50
+ if (!existsSync(filePath)) return null;
51
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Format snapshot as concise context string for SessionStart injection.
59
+ * Budget: max ~150 tokens (~600 chars).
60
+ *
61
+ * @param {Object|null} snapshot
62
+ * @returns {string|null} Formatted context or null
63
+ */
64
+ export function formatPreviousSession(snapshot) {
65
+ if (!snapshot) return null;
66
+
67
+ const lines = ['=== PREVIOUS SESSION ==='];
68
+
69
+ // Header line
70
+ const date = snapshot.savedAt ? new Date(snapshot.savedAt).toISOString().slice(0, 16).replace('T', ' ') : '?';
71
+ const phase = snapshot.phase || '?';
72
+ const build = snapshot.buildStatus || 'unknown';
73
+ lines.push(`Last: ${date} | Phase: ${phase} | Build: ${build}`);
74
+
75
+ // Tasks (truncated)
76
+ const done = snapshot.tasksCompleted || [];
77
+ if (done.length > 0) {
78
+ const shown = done.slice(-5).join(', ');
79
+ const prefix = done.length > 5 ? `...${done.length} total, last: ` : '';
80
+ lines.push(`Done: ${prefix}${shown}`);
81
+ }
82
+
83
+ const wip = snapshot.tasksInProgress || [];
84
+ if (wip.length > 0) {
85
+ lines.push(`WIP: ${wip.join(', ')}`);
86
+ }
87
+
88
+ const remaining = snapshot.tasksRemaining || [];
89
+ if (remaining.length > 0) {
90
+ const shown = remaining.slice(0, 5).join(', ');
91
+ const suffix = remaining.length > 5 ? ` +${remaining.length - 5} more` : '';
92
+ lines.push(`Remaining: ${shown}${suffix}`);
93
+ }
94
+
95
+ // Files (truncated)
96
+ const files = snapshot.lastEditedFiles || [];
97
+ if (files.length > 0) {
98
+ const shown = files.slice(0, 3).join(', ');
99
+ const suffix = files.length > 3 ? ` +${files.length - 3} more` : '';
100
+ lines.push(`Files: ${shown}${suffix}`);
101
+ }
102
+
103
+ lines.push('===');
104
+ return lines.join('\n');
105
+ }
@@ -35,7 +35,7 @@
35
35
  ],
36
36
  "requiredOutputs": ["uiDesignSystem"],
37
37
  "optionalOutputs": ["uiMockups", "uiComponents", "uiFlows"],
38
- "recommendedMCPs": ["playwright", "context7"],
38
+ "recommendedMCPs": ["playwright", "context7", "stitch"],
39
39
  "pausePoints": [
40
40
  { "id": "uiux", "label": "Approve UI/UX Design" }
41
41
  ],
@@ -0,0 +1,13 @@
1
+ ---
2
+ paths:
3
+ - "**/Auth/**"
4
+ - "**/auth/**"
5
+ - "**/Identity/**"
6
+ - "**/neon-auth/**"
7
+ stacks:
8
+ - neon
9
+ ---
10
+
11
+ # Neon Auth Standards
12
+
13
+ @.morph/framework/standards/backend/integrations/neon-auth/neon-auth.md
@@ -14,6 +14,7 @@ stacks:
14
14
  @.morph/framework/standards/infrastructure/neon/neon-pgvector.md
15
15
  @.morph/framework/standards/infrastructure/neon/neon-pgrag.md
16
16
  @.morph/framework/standards/infrastructure/neon/neon-semantic-kernel.md
17
+ @.morph/framework/standards/backend/integrations/neon-auth/neon-auth.md
17
18
 
18
19
  ## SQL Templates
19
20
 
@@ -152,11 +152,44 @@
152
152
  "warnings": ["API call execution requires your Asaas access_token. Doc search works without authentication."],
153
153
  "setupGuide": "Run: claude mcp add --transport http asaas https://docs.asaas.com/mcp"
154
154
  }
155
+ },
156
+ "stitch": {
157
+ "phases": ["uiux"],
158
+ "tools": ["create_project", "list_projects", "get_project", "list_screens", "get_screen", "generate_screen_from_text", "fetch_screen_code", "fetch_screen_image"],
159
+ "detection": "mcpServers includes stitch",
160
+ "fallback": "HTML mockup + Playwright screenshots (Step 3.5 workflow)",
161
+ "usage": "AI-generated screen designs, design.md export, visual design exploration",
162
+ "healthCheck": {
163
+ "toolPattern": "stitch",
164
+ "testCall": "Call list_projects to verify connectivity",
165
+ "testParams": {},
166
+ "successIndicator": "Returns a list of projects (possibly empty) without auth errors",
167
+ "failureHint": "Stitch MCP not responding. Ensure @_davideast/stitch-mcp is installed or configure official MCP: claude mcp add stitch --transport http https://stitch.googleapis.com/mcp"
168
+ },
169
+ "install": {
170
+ "autoInstall": true,
171
+ "transport": "stdio",
172
+ "config": {
173
+ "command": "cmd",
174
+ "args": ["/c", "npx", "-y", "@_davideast/stitch-mcp@latest", "proxy"]
175
+ },
176
+ "credentials": [],
177
+ "prerequisites": [],
178
+ "stackRelevance": ["nextjs", "nextjs-neon", "vite"],
179
+ "warnings": ["Community MCP tool. Official alternative: claude mcp add stitch --transport http https://stitch.googleapis.com/mcp (requires gcloud auth)"],
180
+ "setupGuide": "Auto-installed via npx. For official Google MCP: claude mcp add stitch --transport http https://stitch.googleapis.com/mcp"
181
+ },
182
+ "companionSkills": {
183
+ "repo": "google-labs-code/stitch-skills",
184
+ "installCommand": "npx skills add google-labs-code/stitch-skills",
185
+ "skills": ["stitch-design", "stitch-loop", "design-md", "prompt-enhance", "react-components", "shadcn-ui"],
186
+ "description": "Official Stitch agent skills for Claude Code — design generation, multi-page loops, design.md export"
187
+ }
155
188
  }
156
189
  },
157
190
  "phaseMatrix": {
158
191
  "proposal": ["context7"],
159
- "uiux": ["playwright", "context7"],
192
+ "uiux": ["playwright", "context7", "stitch"],
160
193
  "design": ["context7", "github"],
161
194
  "tasks": ["context7", "github"],
162
195
  "implement": ["context7", "playwright", "github", "vercel"]
@@ -67,7 +67,7 @@ allowed-tools: Read, Bash, Glob, Grep, Edit, Write, AskUserQuestion
67
67
  - Testing teammate (unit + integration)
68
68
 
69
69
  4. **Research & Standards Validation (Phases 0-3)**
70
- - Investigate multiple integration options (Clerk vs Neon Auth vs custom)
70
+ - Investigate multiple integration options (Neon Auth vs custom JWT vs Passkeys)
71
71
  - Compare UI patterns (shadcn/ui component composition strategies)
72
72
  - Validate architecture patterns (CQRS vs simple Repository)
73
73
 
@@ -195,8 +195,8 @@ morph-spec state set scheduled-reports phase implement
195
195
  ```
196
196
  Create an agent team to decide on the authentication architecture.
197
197
  Spawn 3 debate teammates:
198
- - Pro-Clerk: Argue for Clerk.com (ease of use, modern UI, MFA built-in)
199
- - Pro-Neon-Auth: Argue for PostgreSQL RLS with Neon (integrated with existing DB, Row Level Security)
198
+ - Pro-Neon-Auth: Argue for Neon Auth (database-native, no external deps, branch isolation, Better Auth)
199
+ - Pro-NextAuth: Argue for NextAuth.js (flexible providers, community ecosystem, self-hosted)
200
200
  - Pro-Custom: Argue for custom JWT + Passkeys (full control, no vendor lock-in)
201
201
 
202
202
  Have them debate, challenge each other's assumptions, and document pros/cons.
@@ -10,7 +10,7 @@ allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion,
10
10
  mcp__playwright__browser_navigate, mcp__playwright__browser_resize,
11
11
  mcp__playwright__browser_take_screenshot, mcp__playwright__browser_snapshot,
12
12
  mcp__playwright__browser_evaluate, mcp__playwright__browser_console_messages
13
- cliVersion: "4.8.19"
13
+ cliVersion: "4.19.0"
14
14
  stacks:
15
15
  - nextjs
16
16
  ---
@@ -101,7 +101,7 @@ Gather evidence to build a stack map. Run these in parallel:
101
101
 
102
102
  | Tool | Pattern | Signal |
103
103
  |------|---------|--------|
104
- | `Glob` | `**/package.json` | Detect next, neon, clerk, stripe in deps |
104
+ | `Glob` | `**/package.json` | Detect next, neon, @neondatabase/auth, stripe in deps |
105
105
  | `Glob` | `**/*.csproj` | .NET projects at any depth |
106
106
  | `Glob` | `**/next.config.{js,ts,mjs}` | Next.js in any subdirectory |
107
107
  | `Glob` | `**/components.json` | shadcn/ui |
@@ -115,14 +115,14 @@ Gather evidence to build a stack map. Run these in parallel:
115
115
  | `Read` | `.env.example` | Env vars reveal integrations |
116
116
  | `Read` | `README.md` | Existing project description |
117
117
  | `Grep` | `@neondatabase/serverless` | Neon dep in any package.json |
118
- | `Grep` | `clerk\|auth0\|nextauth` | Auth provider |
118
+ | `Grep` | `@neondatabase/auth\|auth0\|nextauth` | Auth provider |
119
119
  | `Grep` | `stripe\|asaas` | Payment provider |
120
120
 
121
121
  Read each found `package.json` for dependency names. Build an **evidence map**:
122
122
 
123
123
  ```
124
124
  stack: [nextjs, dotnet, ...]
125
- integrations: [neon, docker, clerk, ...]
125
+ integrations: [neon, docker, neon-auth, ...]
126
126
  uiLibrary: shadcn | null
127
127
  monorepo: true | false
128
128
  frontendPath: src/frontend (if monorepo)
@@ -326,7 +326,7 @@ Read `.morph/config/config.json` and merge into `project`:
326
326
  "stack": "[stacks joined with +, e.g. nextjs+dotnet]",
327
327
  "architecture": "[monorepo | single-stack | detected pattern]",
328
328
  "uiLibrary": "[detected or null]",
329
- "integrations": ["neon", "docker", "clerk"],
329
+ "integrations": ["neon", "docker", "neon-auth"],
330
330
  "frontendPath": "[path if monorepo, else omit]",
331
331
  "backendPath": "[path if monorepo, else omit]"
332
332
  }
@@ -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.17.0"
6
+ cliVersion: "4.19.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.17.0"
7
+ cliVersion: "4.19.0"
8
8
  ---
9
9
 
10
10
  # MORPH Design — Phase 2
@@ -440,4 +440,14 @@ morph-spec state set $ARGUMENTS costs.estimated {X.XX}
440
440
  | `decisions` | `.morph/features/{feature}/2-design/decisions.md` |
441
441
  <!-- /morph-outputs -->
442
442
 
443
+ ## Relevant Standards
444
+
445
+ Before starting the design phase, proactively read standards relevant to the project's stack:
446
+ - Architecture standards: `.morph/framework/standards/architecture/` — especially vertical-slice patterns
447
+ - Backend standards: `.morph/framework/standards/backend/` — for API contracts and patterns
448
+ - Data standards: `.morph/framework/standards/data/` — for database schema and access patterns
449
+ - These standards are also available as rules that auto-load when editing matching file types.
450
+
451
+ ---
452
+
443
453
  Continue automatically to Plan phase after approval.
@@ -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.17.0"
8
+ cliVersion: "4.19.0"
9
9
  allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Agent
10
10
  ---
11
11
 
@@ -479,4 +479,15 @@ Agent(subagent_type=morph-standards-architect, prompt=<filled prompts/code-quali
479
479
 
480
480
  ---
481
481
 
482
+ ## Relevant Standards
483
+
484
+ During implementation, standards auto-load via rules when editing relevant file types.
485
+ For proactive reference:
486
+ - Architecture: `.morph/framework/standards/architecture/` — structural compliance
487
+ - Backend/Frontend: `.morph/framework/standards/backend/` or `.morph/framework/standards/frontend/`
488
+ - Security: `.morph/framework/standards/security/` — authentication, authorization patterns
489
+ - Testing: follow the project's existing test patterns (check `test/` or `tests/` directory)
490
+
491
+ ---
492
+
482
493
  Feature complete! Consider creating a PR and running `morph-spec generate recap $ARGUMENTS`.
@@ -4,7 +4,7 @@ description: MORPH-SPEC Phase 3 (Plan). Generates a detailed implementation plan
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.17.0"
7
+ cliVersion: "4.19.0"
8
8
  ---
9
9
 
10
10
  # MORPH Plan — Phase 3
@@ -4,7 +4,7 @@ description: MORPH-SPEC Phase 4 (Tasks). Breaks approved spec into bottom-up ord
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.17.0"
7
+ cliVersion: "4.19.0"
8
8
  ---
9
9
 
10
10
  # MORPH Tasks — Phase 4