@polymorphism-tech/morph-spec 4.19.0 → 4.20.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 +11 -0
- package/bin/task-manager.js +35 -10
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +1 -1
- package/docs/QUICKSTART.md +1 -1
- package/framework/agents/architecture/architecture-expert.md +12 -0
- package/framework/agents/architecture/packages-validator.md +12 -0
- package/framework/agents/architecture/security-expert.md +12 -0
- package/framework/agents/frontend/design-system-validator.md +12 -0
- package/framework/agents/frontend/nextjs-component-validator.md +12 -0
- package/framework/hooks/claude-code/post-tool-use/dispatch.js +20 -3
- package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +60 -11
- package/framework/rubrics/backend.json +36 -0
- package/framework/rubrics/default.json +36 -0
- package/framework/rubrics/frontend.json +36 -0
- package/framework/skills/level-0-meta/morph-frontend-review/SKILL.md +1 -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 +1 -1
- package/framework/skills/level-1-workflows/morph-phase-implement/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-tasks/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-phase-uiux/SKILL.md +1 -1
- package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +1 -1
- package/package.json +1 -1
- package/src/commands/dashboard/dashboard.js +53 -0
- package/src/dashboard/app/App.jsx +31 -0
- package/src/dashboard/app/components/DetailPanel.jsx +11 -0
- package/src/dashboard/app/components/FlowGraph.jsx +17 -0
- package/src/dashboard/app/components/SearchFilter.jsx +22 -0
- package/src/dashboard/app/components/Sidebar.jsx +45 -0
- package/src/dashboard/app/hooks/useDetailPanel.js +15 -0
- package/src/dashboard/app/main.jsx +13 -0
- package/src/dashboard/app/pages/AgentMap.jsx +371 -0
- package/src/dashboard/app/pages/HookInspector.jsx +418 -0
- package/src/dashboard/app/pages/LiveState.jsx +239 -0
- package/src/dashboard/app/pages/PhasePipeline.jsx +410 -0
- package/src/dashboard/app/pages/RulesMap.jsx +273 -0
- package/src/dashboard/app/pages/SkillsLibrary.jsx +367 -0
- package/src/dashboard/app/pages/Standards.jsx +332 -0
- package/src/dashboard/app/pages/Workflows.jsx +346 -0
- package/src/dashboard/app/styles/index.css +47 -0
- package/src/dashboard/index.html +12 -0
- package/src/dashboard/package.json +24 -0
- package/src/dashboard/scanner/agents-scanner.js +35 -0
- package/src/dashboard/scanner/hooks-scanner.js +41 -0
- package/src/dashboard/scanner/index.js +21 -0
- package/src/dashboard/scanner/phases-scanner.js +15 -0
- package/src/dashboard/scanner/rubrics-scanner.js +12 -0
- package/src/dashboard/scanner/rules-scanner.js +37 -0
- package/src/dashboard/scanner/skills-scanner.js +43 -0
- package/src/dashboard/scanner/squads-scanner.js +13 -0
- package/src/dashboard/scanner/standards-scanner.js +26 -0
- package/src/dashboard/scanner/state-scanner.js +8 -0
- package/src/dashboard/scanner/workflows-scanner.js +18 -0
- package/src/dashboard/vite-plugin-morph-data.js +17 -0
- package/src/dashboard/vite.config.js +24 -0
- package/src/lib/checkpoints/checkpoint-hooks.js +2 -1
- package/src/lib/generators/recap-generator.js +15 -0
- package/src/lib/validators/score-aggregator.js +244 -0
- package/src/lib/validators/validation-runner.js +44 -0
- package/src/scripts/setup-infra.js +8 -0
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.20.0
|
|
7
7
|
**Requires:** Node.js 18+, Claude Code
|
|
8
8
|
|
|
9
9
|
---
|
|
@@ -364,4 +364,4 @@ Code generated by morph-spec (contracts, templates, implementation output) belon
|
|
|
364
364
|
|
|
365
365
|
---
|
|
366
366
|
|
|
367
|
-
*morph-spec v4.
|
|
367
|
+
*morph-spec v4.20.0 by [Polymorphism Tech](https://polymorphism.tech)*
|
package/bin/morph-spec.js
CHANGED
|
@@ -65,6 +65,9 @@ import { projectMetricsCommand } from '../src/commands/agents/project-metrics.js
|
|
|
65
65
|
// Context commands
|
|
66
66
|
import { contextRefreshCommand } from '../src/commands/context/context-refresh.js';
|
|
67
67
|
|
|
68
|
+
// Dashboard commands
|
|
69
|
+
import { dashboardCommand } from '../src/commands/dashboard/dashboard.js';
|
|
70
|
+
|
|
68
71
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
69
72
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
70
73
|
|
|
@@ -477,4 +480,12 @@ contextCommand
|
|
|
477
480
|
.option('--json', 'Output scan result as JSON')
|
|
478
481
|
.action((options) => contextRefreshCommand(options));
|
|
479
482
|
|
|
483
|
+
// Dashboard / Inspector
|
|
484
|
+
program
|
|
485
|
+
.command('dashboard')
|
|
486
|
+
.description('Open the morph-spec inspector dashboard')
|
|
487
|
+
.option('-p, --port <port>', 'Port number', '3200')
|
|
488
|
+
.option('--no-open', 'Don\'t auto-open browser')
|
|
489
|
+
.action(dashboardCommand);
|
|
490
|
+
|
|
480
491
|
program.parse();
|
package/bin/task-manager.js
CHANGED
|
@@ -208,13 +208,20 @@ class TaskManager {
|
|
|
208
208
|
console.log(chalk.cyan('\n ℹ️ Dry-run — tasks NOT marked as complete'));
|
|
209
209
|
return [];
|
|
210
210
|
}
|
|
211
|
-
if
|
|
211
|
+
// Score-based retry decision (falls back to pass/fail if scores unavailable)
|
|
212
|
+
const scoreAction = validationResult.scores?.action;
|
|
213
|
+
const shouldFail = scoreAction ? scoreAction !== 'approve' : !validationResult.passed;
|
|
214
|
+
|
|
215
|
+
if (shouldFail) {
|
|
212
216
|
// Reload state to ensure we have the latest (may have been modified by validation)
|
|
213
217
|
const currentState = loadState();
|
|
214
218
|
const currentFeature = currentState.features[featureName];
|
|
215
219
|
if (currentFeature) {
|
|
220
|
+
// Score-based escalation: 'escalate' action blocks immediately
|
|
221
|
+
const forceEscalate = scoreAction === 'escalate';
|
|
222
|
+
|
|
216
223
|
for (const task of tasksToComplete) {
|
|
217
|
-
this.persistValidationHistory(currentFeature, task.id, validationResult);
|
|
224
|
+
this.persistValidationHistory(currentFeature, task.id, validationResult, forceEscalate);
|
|
218
225
|
}
|
|
219
226
|
saveState(currentState);
|
|
220
227
|
|
|
@@ -224,11 +231,18 @@ class TaskManager {
|
|
|
224
231
|
return hist?.status === 'blocked';
|
|
225
232
|
});
|
|
226
233
|
if (blockedTasks.length > 0) {
|
|
227
|
-
|
|
228
|
-
console.error(chalk.red(
|
|
234
|
+
const scoreInfo = validationResult.scores ? ` (score: ${validationResult.scores.score}/10)` : '';
|
|
235
|
+
console.error(chalk.red(`\n⛔ ESCALATION — Task(s) ${blockedTasks.map(t => t.id).join(', ')}${scoreInfo}`));
|
|
236
|
+
if (forceEscalate) {
|
|
237
|
+
console.error(chalk.red(' Score below retry threshold — immediate escalation'));
|
|
238
|
+
} else {
|
|
239
|
+
console.error(chalk.red(' Failed 3 times — human review required'));
|
|
240
|
+
}
|
|
241
|
+
console.error(chalk.red(' Mark resolved with: morph-spec state set <feature> validationHistory.<taskId>.status passed'));
|
|
229
242
|
} else {
|
|
230
243
|
const attempt = currentFeature.validationHistory?.[tasksToComplete[0]?.id]?.attempt || 1;
|
|
231
|
-
|
|
244
|
+
const scoreInfo = validationResult.scores ? ` | score: ${validationResult.scores.score}/10` : '';
|
|
245
|
+
console.error(chalk.red(`\n❌ Validation failed (attempt ${attempt}/3${scoreInfo}) — tasks NOT marked as complete`));
|
|
232
246
|
console.log(chalk.gray(' Fix the issues above, then run task done again'));
|
|
233
247
|
if (attempt >= 2) {
|
|
234
248
|
console.log(chalk.yellow(` ⚠️ Next failure will escalate to human review`));
|
|
@@ -436,14 +450,14 @@ class TaskManager {
|
|
|
436
450
|
? validatorEntries.filter(v => v.passed).length / validatorEntries.length
|
|
437
451
|
: (result.passed ? 1.0 : 0.0);
|
|
438
452
|
|
|
439
|
-
return { passed: result.passed, validators, passRate };
|
|
453
|
+
return { passed: result.passed, validators, passRate, scores: result.scores || null };
|
|
440
454
|
} catch (error) {
|
|
441
455
|
// If validation runner fails to load, warn but don't block task completion.
|
|
442
456
|
// This is fail-open by design: a broken validator shouldn't block commits.
|
|
443
457
|
// Common cause: missing optional deps.
|
|
444
458
|
console.log(chalk.yellow(`\n⚠️ Validation skipped (${error.message})`));
|
|
445
459
|
console.log(chalk.gray(` Run manually: morph-spec validate-feature ${featureName}`));
|
|
446
|
-
return { passed: true, validators: {}, passRate: 1.0 };
|
|
460
|
+
return { passed: true, validators: {}, passRate: 1.0, scores: null };
|
|
447
461
|
}
|
|
448
462
|
}
|
|
449
463
|
|
|
@@ -455,21 +469,32 @@ class TaskManager {
|
|
|
455
469
|
* @param {string} taskId - Task ID
|
|
456
470
|
* @param {{ passed: boolean, validators: Object, passRate: number }} validationResult
|
|
457
471
|
*/
|
|
458
|
-
persistValidationHistory(feature, taskId, validationResult) {
|
|
472
|
+
persistValidationHistory(feature, taskId, validationResult, forceEscalate = false) {
|
|
459
473
|
if (!feature.validationHistory) {
|
|
460
474
|
feature.validationHistory = {};
|
|
461
475
|
}
|
|
462
476
|
const existing = feature.validationHistory[taskId] || { attempt: 0 };
|
|
463
477
|
const attempt = (existing.attempt || 0) + 1;
|
|
464
|
-
const status = attempt >= 3 ? 'blocked' : 'failed';
|
|
478
|
+
const status = forceEscalate ? 'blocked' : (attempt >= 3 ? 'blocked' : 'failed');
|
|
465
479
|
|
|
466
|
-
|
|
480
|
+
const entry = {
|
|
467
481
|
attempt,
|
|
468
482
|
validators: validationResult.validators || {},
|
|
469
483
|
passRate: validationResult.passRate || 0,
|
|
470
484
|
status,
|
|
471
485
|
updatedAt: new Date().toISOString(),
|
|
472
486
|
};
|
|
487
|
+
|
|
488
|
+
// Attach score data when available
|
|
489
|
+
if (validationResult.scores) {
|
|
490
|
+
entry.scores = {
|
|
491
|
+
score: validationResult.scores.score,
|
|
492
|
+
action: validationResult.scores.action,
|
|
493
|
+
breakdown: validationResult.scores.breakdown,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
feature.validationHistory[taskId] = entry;
|
|
473
498
|
}
|
|
474
499
|
|
|
475
500
|
/**
|
package/claude-plugin.json
CHANGED
package/docs/CHEATSHEET.md
CHANGED
package/docs/QUICKSTART.md
CHANGED
|
@@ -19,6 +19,18 @@ READ-ONLY scanner for architectural violations in .NET VSA projects.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## Evaluation Posture
|
|
23
|
+
|
|
24
|
+
You are an ADVERSARIAL evaluator. Your default assumption is that architectural violations exist.
|
|
25
|
+
|
|
26
|
+
- **Assume violations exist** until proven otherwise — your job is to FIND them, not confirm the architecture is clean
|
|
27
|
+
- **Challenge surface appearances** — code that compiles and runs may hide dependency violations or SRP breaches
|
|
28
|
+
- **A clean report is suspicious** — if you found nothing, dig deeper before concluding
|
|
29
|
+
- **Prioritize by severity** — wrong dependency direction and DI violations before style warnings
|
|
30
|
+
- **Be specific** — every finding needs file path, line number, violation type, and concrete fix
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
22
34
|
## Scan Categories
|
|
23
35
|
|
|
24
36
|
### Critical (Severity: Error)
|
|
@@ -19,6 +19,18 @@ READ-ONLY scanner for NuGet and npm package issues.
|
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
|
+
## Evaluation Posture
|
|
23
|
+
|
|
24
|
+
You are an ADVERSARIAL evaluator. Your default assumption is that dependency issues exist.
|
|
25
|
+
|
|
26
|
+
- **Assume problems exist** until proven otherwise — your job is to FIND version conflicts and deprecated packages, not confirm everything is up to date
|
|
27
|
+
- **Challenge surface appearances** — packages that install without errors may still have version conflicts, security advisories, or deprecated APIs
|
|
28
|
+
- **A clean report is suspicious** — if you found nothing, dig deeper before concluding
|
|
29
|
+
- **Prioritize by severity** — version conflicts and security advisories before style preferences
|
|
30
|
+
- **Be specific** — every finding needs file path, package name, installed version, and concrete fix
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
22
34
|
## Scan Categories
|
|
23
35
|
|
|
24
36
|
### NuGet (.csproj)
|
|
@@ -18,6 +18,18 @@ READ-ONLY scanner for security vulnerabilities across all source files.
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
## Evaluation Posture
|
|
22
|
+
|
|
23
|
+
You are an ADVERSARIAL evaluator. Your default assumption is that security vulnerabilities exist.
|
|
24
|
+
|
|
25
|
+
- **Assume vulnerabilities exist** until proven otherwise — your job is to FIND them, not confirm the code is safe
|
|
26
|
+
- **Challenge surface appearances** — code that looks secure may hide subtle injection vectors or auth bypasses
|
|
27
|
+
- **A clean report is suspicious** — if you found nothing, dig deeper before concluding
|
|
28
|
+
- **Prioritize by severity** — critical vulnerabilities (injection, secrets) before style issues
|
|
29
|
+
- **Be specific** — every finding needs file path, line number, vulnerability type, and concrete fix
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
21
33
|
## Scan Categories
|
|
22
34
|
|
|
23
35
|
### Critical (Severity: Error)
|
|
@@ -29,6 +29,18 @@ READ-ONLY scanner for design token compliance across CSS and component files.
|
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
32
|
+
## Evaluation Posture
|
|
33
|
+
|
|
34
|
+
You are an ADVERSARIAL evaluator. Your default assumption is that design token violations exist.
|
|
35
|
+
|
|
36
|
+
- **Assume violations exist** until proven otherwise — your job is to FIND hardcoded values and naming inconsistencies, not confirm compliance
|
|
37
|
+
- **Challenge surface appearances** — components that look correct visually may use hardcoded colors, spacing, or typography that bypass the design system
|
|
38
|
+
- **A clean report is suspicious** — if you found nothing, dig deeper before concluding
|
|
39
|
+
- **Prioritize by severity** — hardcoded colors and spacing before naming convention warnings
|
|
40
|
+
- **Be specific** — every finding needs file path, line number, the hardcoded value found, and the correct design token to use
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
32
44
|
## Scan Categories
|
|
33
45
|
|
|
34
46
|
### Colors
|
|
@@ -21,6 +21,18 @@ READ-ONLY scanner for App Router compliance in Next.js projects.
|
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
+
## Evaluation Posture
|
|
25
|
+
|
|
26
|
+
You are an ADVERSARIAL evaluator. Your default assumption is that App Router violations exist.
|
|
27
|
+
|
|
28
|
+
- **Assume violations exist** until proven otherwise — your job is to FIND boundary errors and pattern misuse, not confirm compliance
|
|
29
|
+
- **Challenge surface appearances** — components that render correctly may have wrong `'use client'` placement, missing Suspense boundaries, or server/client leaks
|
|
30
|
+
- **A clean report is suspicious** — if you found nothing, dig deeper before concluding
|
|
31
|
+
- **Prioritize by severity** — server/client boundary violations before performance optimizations
|
|
32
|
+
- **Be specific** — every finding needs file path, line number, the violation type, and concrete fix
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
24
36
|
## Scan Categories
|
|
25
37
|
|
|
26
38
|
### Server/Client Boundaries
|
|
@@ -83,6 +83,19 @@ async function dispatch(command, payload) {
|
|
|
83
83
|
}).trim();
|
|
84
84
|
} catch { /* no git */ }
|
|
85
85
|
|
|
86
|
+
// Include score context from latest validation if available
|
|
87
|
+
let scoreContext = '';
|
|
88
|
+
try {
|
|
89
|
+
const evalFeature = getFeature(featureName);
|
|
90
|
+
const taskScores = evalFeature?.validationHistory?.[taskId]?.scores;
|
|
91
|
+
if (taskScores) {
|
|
92
|
+
scoreContext = `\n## Previous Validation Score: ${taskScores.score}/10\n` +
|
|
93
|
+
Object.entries(taskScores.breakdown || {})
|
|
94
|
+
.map(([cat, d]) => ` ${cat}: ${Math.round(d.score * 10) / 10}/10 (weight ${Math.round(d.weight * 100)}%)`)
|
|
95
|
+
.join('\n') + '\n\nFocus your evaluation on categories with the lowest scores.\n';
|
|
96
|
+
}
|
|
97
|
+
} catch { /* non-blocking */ }
|
|
98
|
+
|
|
86
99
|
contextParts.push(
|
|
87
100
|
`🔍 EVALUATOR DISPATCH\n` +
|
|
88
101
|
`════════════════════════════════════════\n` +
|
|
@@ -92,14 +105,18 @@ async function dispatch(command, payload) {
|
|
|
92
105
|
` model: "sonnet"\n` +
|
|
93
106
|
` prompt: (see below)\n\n` +
|
|
94
107
|
`--- EVALUATOR PROMPT ---\n` +
|
|
95
|
-
`You are an
|
|
108
|
+
`You are an ADVERSARIAL evaluator. Your default assumption is that defects exist.\n` +
|
|
109
|
+
`Do NOT confirm correctness — actively search for problems.\n\n` +
|
|
96
110
|
`## Contract\n${contractContent}\n\n` +
|
|
97
|
-
`## Changed Files\n${changedFiles || '(unable to determine)'}\n
|
|
111
|
+
`## Changed Files\n${changedFiles || '(unable to determine)'}\n` +
|
|
112
|
+
`${scoreContext}\n` +
|
|
98
113
|
`## Instructions\n` +
|
|
99
114
|
`1. Read each changed file\n` +
|
|
100
115
|
`2. Run the verification commands from the contract\n` +
|
|
101
116
|
`3. Evaluate each definitionOfDone item: PASS or FAIL with evidence\n` +
|
|
102
|
-
`4.
|
|
117
|
+
`4. For each category, score 0-10 and explain deficiencies found\n` +
|
|
118
|
+
`5. A clean report is suspicious — dig deeper before declaring PASS\n` +
|
|
119
|
+
`6. Return a structured result with overall PASS/FAIL and score breakdown\n` +
|
|
103
120
|
`--- END EVALUATOR PROMPT ---`
|
|
104
121
|
);
|
|
105
122
|
}
|
|
@@ -79,6 +79,7 @@ try {
|
|
|
79
79
|
function buildRemediationContext(featureName, taskId, taskHistory) {
|
|
80
80
|
const attempt = taskHistory.attempt || 1;
|
|
81
81
|
const validators = taskHistory.validators || {};
|
|
82
|
+
const scores = taskHistory.scores || null;
|
|
82
83
|
|
|
83
84
|
// Collect all issues across all validators
|
|
84
85
|
const allIssues = [];
|
|
@@ -95,28 +96,60 @@ function buildRemediationContext(featureName, taskId, taskHistory) {
|
|
|
95
96
|
const lines = [];
|
|
96
97
|
|
|
97
98
|
if (taskHistory.status === 'blocked') {
|
|
98
|
-
// Max attempts reached
|
|
99
|
-
|
|
100
|
-
lines.push(
|
|
99
|
+
// Max attempts reached OR score-based escalation
|
|
100
|
+
const scoreInfo = scores ? ` (score: ${scores.score}/10)` : '';
|
|
101
|
+
lines.push(`⛔ ESCALATION REQUIRED — Task ${taskId} in feature '${featureName}'${scoreInfo}`);
|
|
102
|
+
if (scores?.action === 'escalate') {
|
|
103
|
+
lines.push(` Score below retry threshold — immediate escalation.`);
|
|
104
|
+
} else {
|
|
105
|
+
lines.push(` Validation failed ${attempt} times (max attempts reached).`);
|
|
106
|
+
}
|
|
101
107
|
lines.push(` Human review required before proceeding.`);
|
|
108
|
+
if (scores) {
|
|
109
|
+
lines.push(``);
|
|
110
|
+
lines.push(` Score breakdown:`);
|
|
111
|
+
appendScoreBreakdown(lines, scores);
|
|
112
|
+
}
|
|
102
113
|
lines.push(` Last failures:`);
|
|
103
114
|
for (const issue of allIssues.slice(0, 5)) {
|
|
104
115
|
lines.push(` • [${issue.validator}] ${issue.message} ${issue.file ? `(${issue.file}${issue.line ? ':' + issue.line : ''})` : ''}`);
|
|
105
116
|
}
|
|
106
117
|
} else {
|
|
107
118
|
// Active remediation — attempt N of 3
|
|
108
|
-
|
|
119
|
+
const scoreInfo = scores ? ` | score: ${scores.score}/10` : '';
|
|
120
|
+
lines.push(`🔄 REMEDIATION REQUIRED — Task ${taskId} (attempt ${attempt}/3${scoreInfo})`);
|
|
109
121
|
lines.push(` Validation failed. Fix the following issues and re-run:`);
|
|
110
122
|
lines.push(` morph-spec task done ${featureName} ${taskId}`);
|
|
111
123
|
lines.push(``);
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
// Score-based prioritized feedback (when available)
|
|
126
|
+
if (scores?.breakdown) {
|
|
127
|
+
lines.push(` Priority fixes (by impact):`);
|
|
128
|
+
const sorted = Object.entries(scores.breakdown)
|
|
129
|
+
.filter(([, cat]) => (cat.issues?.length || 0) > 0)
|
|
130
|
+
.sort((a, b) => ((10 - b[1].score) * b[1].weight) - ((10 - a[1].score) * a[1].weight));
|
|
131
|
+
|
|
132
|
+
for (const [category, cat] of sorted) {
|
|
133
|
+
const topIssue = cat.issues[0];
|
|
134
|
+
const location = topIssue?.file ? ` (${topIssue.file}${topIssue.line ? ':' + topIssue.line : ''})` : '';
|
|
135
|
+
const msg = topIssue?.message || 'Issues detected';
|
|
136
|
+
lines.push(` ${Math.round(cat.score * 10) / 10}/10 [${category}] ${msg}${location}`);
|
|
137
|
+
if (cat.issues.length > 1) {
|
|
138
|
+
lines.push(` ... and ${cat.issues.length - 1} more issue(s)`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
lines.push(``);
|
|
142
|
+
appendScoreBreakdown(lines, scores);
|
|
143
|
+
} else {
|
|
144
|
+
// Fallback: original issue-by-issue format
|
|
145
|
+
for (const issue of allIssues) {
|
|
146
|
+
const refKey = getRefKey(issue.rule || issue.validator);
|
|
147
|
+
const ref = refKey ? ` — Ref: ${STANDARD_REFS[refKey] || refKey}` : '';
|
|
148
|
+
const location = issue.file
|
|
149
|
+
? ` (${issue.file}${issue.line ? ':' + issue.line : ''})`
|
|
150
|
+
: '';
|
|
151
|
+
lines.push(` • [${issue.validator}] ${issue.message}${location}${ref}`);
|
|
152
|
+
}
|
|
120
153
|
}
|
|
121
154
|
|
|
122
155
|
if (attempt >= 2) {
|
|
@@ -128,6 +161,22 @@ function buildRemediationContext(featureName, taskId, taskHistory) {
|
|
|
128
161
|
injectContext(lines.join('\n'));
|
|
129
162
|
}
|
|
130
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Append score breakdown lines to output.
|
|
166
|
+
* @param {string[]} lines - Output array
|
|
167
|
+
* @param {Object} scores - { score, action, breakdown }
|
|
168
|
+
*/
|
|
169
|
+
function appendScoreBreakdown(lines, scores) {
|
|
170
|
+
if (!scores?.breakdown) return;
|
|
171
|
+
const approveThreshold = scores.approveThreshold ?? 8.0;
|
|
172
|
+
for (const [category, data] of Object.entries(scores.breakdown)) {
|
|
173
|
+
if (category === '_unmapped') continue; // skip internal unmapped category
|
|
174
|
+
const pct = Math.round(data.weight * 100);
|
|
175
|
+
const indicator = data.score >= approveThreshold ? '\u2713' : data.score >= 6 ? '\u2193' : '\u2193\u2193';
|
|
176
|
+
lines.push(` ${category}: ${Math.round(data.score * 10) / 10}/10 (weight ${pct}%) ${indicator}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
131
180
|
/**
|
|
132
181
|
* Map a rule/validator name to a STANDARD_REFS key.
|
|
133
182
|
* @param {string} ruleOrValidator
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "backend",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Backend-focused rubric. Higher weight on architecture, security, and package health.",
|
|
5
|
+
"categories": {
|
|
6
|
+
"functionality": {
|
|
7
|
+
"weight": 0.30,
|
|
8
|
+
"validators": ["contract-compliance"],
|
|
9
|
+
"description": "Core feature correctness and contract compliance"
|
|
10
|
+
},
|
|
11
|
+
"code_quality": {
|
|
12
|
+
"weight": 0.30,
|
|
13
|
+
"validators": ["architecture"],
|
|
14
|
+
"description": "Architecture patterns, dependency direction, and code structure"
|
|
15
|
+
},
|
|
16
|
+
"design_ui": {
|
|
17
|
+
"weight": 0.05,
|
|
18
|
+
"validators": ["design-system", "css", "contrast", "nextjs-component"],
|
|
19
|
+
"description": "Design system compliance (minimal weight for backend projects)"
|
|
20
|
+
},
|
|
21
|
+
"security": {
|
|
22
|
+
"weight": 0.15,
|
|
23
|
+
"validators": [],
|
|
24
|
+
"description": "Security posture (agent-evaluated, no automated validator)"
|
|
25
|
+
},
|
|
26
|
+
"packages": {
|
|
27
|
+
"weight": 0.20,
|
|
28
|
+
"validators": ["packages"],
|
|
29
|
+
"description": "Dependency health, version compatibility, and deprecated packages"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"thresholds": {
|
|
33
|
+
"approve": 8.0,
|
|
34
|
+
"retry": 6.0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "default",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Default rubric for general-purpose projects. Balanced weights across all categories.",
|
|
5
|
+
"categories": {
|
|
6
|
+
"functionality": {
|
|
7
|
+
"weight": 0.30,
|
|
8
|
+
"validators": ["contract-compliance"],
|
|
9
|
+
"description": "Core feature correctness and contract compliance"
|
|
10
|
+
},
|
|
11
|
+
"code_quality": {
|
|
12
|
+
"weight": 0.25,
|
|
13
|
+
"validators": ["architecture"],
|
|
14
|
+
"description": "Architecture patterns and code structure"
|
|
15
|
+
},
|
|
16
|
+
"design_ui": {
|
|
17
|
+
"weight": 0.15,
|
|
18
|
+
"validators": ["design-system", "css", "contrast", "nextjs-component"],
|
|
19
|
+
"description": "Design system compliance, CSS quality, and UI correctness"
|
|
20
|
+
},
|
|
21
|
+
"security": {
|
|
22
|
+
"weight": 0.15,
|
|
23
|
+
"validators": [],
|
|
24
|
+
"description": "Security posture (agent-evaluated, no automated validator)"
|
|
25
|
+
},
|
|
26
|
+
"packages": {
|
|
27
|
+
"weight": 0.15,
|
|
28
|
+
"validators": ["packages"],
|
|
29
|
+
"description": "Dependency health and compatibility"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"thresholds": {
|
|
33
|
+
"approve": 8.0,
|
|
34
|
+
"retry": 6.0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "frontend",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Frontend-focused rubric. Higher weight on design system compliance and UI quality.",
|
|
5
|
+
"categories": {
|
|
6
|
+
"functionality": {
|
|
7
|
+
"weight": 0.25,
|
|
8
|
+
"validators": ["contract-compliance"],
|
|
9
|
+
"description": "Core feature correctness and contract compliance"
|
|
10
|
+
},
|
|
11
|
+
"code_quality": {
|
|
12
|
+
"weight": 0.15,
|
|
13
|
+
"validators": ["architecture"],
|
|
14
|
+
"description": "Architecture patterns and code structure"
|
|
15
|
+
},
|
|
16
|
+
"design_ui": {
|
|
17
|
+
"weight": 0.35,
|
|
18
|
+
"validators": ["design-system", "css", "contrast", "nextjs-component"],
|
|
19
|
+
"description": "Design system compliance, CSS quality, contrast ratios, and component correctness"
|
|
20
|
+
},
|
|
21
|
+
"security": {
|
|
22
|
+
"weight": 0.10,
|
|
23
|
+
"validators": [],
|
|
24
|
+
"description": "Security posture (agent-evaluated, no automated validator)"
|
|
25
|
+
},
|
|
26
|
+
"packages": {
|
|
27
|
+
"weight": 0.15,
|
|
28
|
+
"validators": ["packages"],
|
|
29
|
+
"description": "Dependency health and compatibility"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"thresholds": {
|
|
33
|
+
"approve": 8.0,
|
|
34
|
+
"retry": 6.0
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -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.
|
|
13
|
+
cliVersion: "4.20.0"
|
|
14
14
|
stacks:
|
|
15
15
|
- nextjs
|
|
16
16
|
---
|
|
@@ -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.20.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.20.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MORPH Design — Phase 2
|
|
@@ -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.
|
|
7
|
+
cliVersion: "4.20.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.
|
|
7
|
+
cliVersion: "4.20.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MORPH Tasks — Phase 4
|
|
@@ -4,7 +4,7 @@ description: MORPH-SPEC Phase 2 (UI/UX). Creates design-system.md, mockups.md, c
|
|
|
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.20.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MORPH UI/UX Design - Phase 2
|
|
@@ -4,7 +4,7 @@ description: Guided workflow for mid-implementation scope escalation — analyze
|
|
|
4
4
|
user-invocable: true
|
|
5
5
|
argument-hint: "[feature-name]"
|
|
6
6
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion
|
|
7
|
-
cliVersion: "4.
|
|
7
|
+
cliVersion: "4.20.0"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Scope Escalation Workflow
|