@polymorphism-tech/morph-spec 4.5.0 → 4.6.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/.morph/.morphversion +3 -3
- package/.morph/analytics/threads-log.jsonl +6 -44
- package/.morph/config/config.json +1 -1
- package/.morph/framework/standards/frontend/nextjs/nextjs-patterns.md +17 -0
- package/.morph/framework/templates/docs/user-stories.md +34 -0
- package/.morph/logs/tool-failures.log +7 -51
- package/.morph/memory/{pre-compact-2026-02-22T17-01-01-658Z.json → pre-compact-2026-02-23T15-43-03-521Z.json} +1 -1
- package/CLAUDE.md +77 -56
- package/framework/{skills/level-2-domains → agents}/ai-agents/ai-system-architect.md +1 -4
- package/framework/{skills/level-2-domains → agents}/architecture/po-pm-advisor.md +1 -2
- package/framework/{skills/level-2-domains → agents}/architecture/prompt-engineer.md +1 -2
- package/framework/{skills/level-2-domains → agents}/architecture/seo-growth-hacker.md +1 -2
- package/framework/{skills/level-2-domains → agents}/architecture/standards-architect.md +1 -4
- package/framework/agents/backend/api-designer.md +103 -0
- package/framework/{skills/level-2-domains → agents}/backend/dotnet-senior.md +1 -2
- package/framework/agents/backend/ef-modeler.md +119 -0
- package/framework/{skills/level-2-domains → agents}/backend/hangfire-orchestrator.md +1 -4
- package/framework/{skills/level-2-domains → agents}/backend/ms-agent-expert.md +1 -4
- package/framework/{skills/level-2-domains → agents}/frontend/blazor-builder.md +1 -4
- package/framework/{skills/level-2-domains → agents}/frontend/nextjs-expert.md +1 -4
- package/framework/{skills/level-2-domains → agents}/frontend/ui-ux-designer.md +1 -2
- package/framework/{skills/level-2-domains → agents}/infrastructure/azure-architect.md +1 -2
- package/framework/{skills/level-2-domains → agents}/infrastructure/azure-deploy-specialist.md +1 -2
- package/framework/{skills/level-2-domains → agents}/infrastructure/bicep-architect.md +1 -4
- package/framework/{skills/level-2-domains → agents}/infrastructure/container-specialist.md +1 -4
- package/framework/{skills/level-2-domains → agents}/infrastructure/devops-engineer.md +1 -4
- package/framework/{skills/level-2-domains → agents}/integrations/asaas-financial.md +1 -4
- package/framework/{skills/level-2-domains → agents}/integrations/azure-identity.md +1 -4
- package/framework/{skills/level-2-domains → agents}/integrations/clerk-auth.md +1 -4
- package/framework/{skills/level-2-domains → agents}/integrations/hangfire-integration.md +1 -2
- package/framework/{skills/level-2-domains → agents}/integrations/resend-email.md +1 -4
- package/framework/{skills/level-2-domains → agents}/quality/code-analyzer.md +1 -4
- package/framework/{skills/level-2-domains → agents}/quality/testing-specialist.md +1 -4
- package/framework/hooks/claude-code/statusline.py +384 -85
- package/framework/hooks/shared/phase-utils.js +129 -129
- package/framework/skills/README.md +66 -0
- package/framework/skills/level-0-meta/{brainstorming.md → brainstorming/SKILL.md} +3 -1
- package/framework/skills/level-0-meta/brainstorming/references/proposal-example.md +138 -0
- package/framework/skills/level-0-meta/{code-review.md → code-review/SKILL.md} +3 -2
- package/framework/skills/level-0-meta/code-review/references/review-example.md +164 -0
- package/framework/skills/level-0-meta/code-review/scripts/scan-csharp.mjs +121 -0
- package/framework/skills/level-0-meta/{morph-checklist.md → morph-checklist/SKILL.md} +2 -5
- package/framework/skills/{level-1-workflows/morph-replicate.md → level-0-meta/morph-replicate/SKILL.md} +6 -7
- package/framework/skills/level-0-meta/{simulation-checklist.md → simulation-checklist/SKILL.md} +3 -6
- package/framework/skills/level-0-meta/{tool-usage-guide.md → tool-usage-guide/SKILL.md} +1 -2
- package/framework/skills/level-0-meta/{verification-before-completion.md → verification-before-completion/SKILL.md} +3 -1
- package/framework/skills/level-0-meta/verification-before-completion/scripts/check-phase-outputs.mjs +110 -0
- package/framework/skills/level-1-workflows/{phase-clarify.md → phase-clarify/SKILL.md} +3 -3
- package/framework/skills/level-1-workflows/phase-clarify/references/clarifications-example.md +117 -0
- package/framework/skills/level-1-workflows/{phase-codebase-analysis.md → phase-codebase-analysis/SKILL.md} +2 -3
- package/framework/skills/level-1-workflows/{phase-design.md → phase-design/SKILL.md} +13 -185
- package/framework/skills/level-1-workflows/phase-design/references/spec-example.md +253 -0
- package/framework/skills/level-1-workflows/{phase-implement.md → phase-implement/SKILL.md} +3 -3
- package/framework/skills/level-1-workflows/phase-implement/references/recap-example.md +132 -0
- package/framework/skills/level-1-workflows/{phase-setup.md → phase-setup/SKILL.md} +2 -3
- package/framework/skills/level-1-workflows/{phase-tasks.md → phase-tasks/SKILL.md} +4 -3
- package/framework/skills/level-1-workflows/phase-tasks/references/tasks-example.md +231 -0
- package/framework/skills/level-1-workflows/phase-tasks/scripts/validate-tasks.mjs +112 -0
- package/framework/skills/level-1-workflows/{phase-uiux.md → phase-uiux/SKILL.md} +2 -3
- package/package.json +1 -1
- package/src/commands/project/init.js +4 -64
- package/src/commands/project/update.js +1 -62
- package/src/lib/detectors/claude-config-detector.js +1 -3
- package/src/utils/agents-installer.js +2 -2
- package/src/utils/skills-installer.js +59 -15
- package/.morph/context/README.md +0 -17
- package/framework/skills/level-2-domains/backend/api-designer.md +0 -66
- package/framework/skills/level-2-domains/backend/ef-modeler.md +0 -65
- package/framework/skills/level-3-technologies/README.md +0 -7
- package/framework/skills/level-4-patterns/README.md +0 -7
- /package/framework/{skills/level-2-domains → agents}/README.md +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* scan-csharp.mjs
|
|
4
|
+
*
|
|
5
|
+
* Scans .cs files for MORPH-SPEC coding standard violations.
|
|
6
|
+
* Executed locally by Claude via Bash — output returned to Claude.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node scan-csharp.mjs [path] # scan directory or file
|
|
10
|
+
* node scan-csharp.mjs src/ # scan src/ recursively
|
|
11
|
+
* node scan-csharp.mjs --summary # counts only, no details
|
|
12
|
+
*
|
|
13
|
+
* Checks (ref: framework/standards/core/coding.md):
|
|
14
|
+
* - UPPER_SNAKE_CASE constants → should be PascalCase
|
|
15
|
+
* - Hungarian notation → strName, iCount, btnSubmit
|
|
16
|
+
* - Missing CancellationToken → async methods without CT param
|
|
17
|
+
* - String interpolation in logging → $"" in ILogger calls
|
|
18
|
+
* - Empty catch blocks → catch { } or catch (E) { }
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { readdirSync, readFileSync, statSync, existsSync } from 'fs';
|
|
22
|
+
import { join, extname, relative } from 'path';
|
|
23
|
+
|
|
24
|
+
const targetPath = process.argv[2] ?? '.';
|
|
25
|
+
const summaryOnly = process.argv.includes('--summary');
|
|
26
|
+
|
|
27
|
+
const CHECKS = [
|
|
28
|
+
{
|
|
29
|
+
id: 'UPPER_SNAKE_CASE',
|
|
30
|
+
severity: 'CRITICAL',
|
|
31
|
+
pattern: /\bconst\s+\w+\s+([A-Z][A-Z_]{2,})\s*=/g,
|
|
32
|
+
message: (m) => `Constant '${m[1]}' uses UPPER_SNAKE_CASE (anti-pattern in C#) → use PascalCase`,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'HUNGARIAN_NOTATION',
|
|
36
|
+
severity: 'CRITICAL',
|
|
37
|
+
pattern: /\b(str|int|bool|btn|lbl|txt|dbl|flt|obj|arr|lst)([A-Z]\w*)\b/g,
|
|
38
|
+
message: (m) => `'${m[0]}' looks like Hungarian notation → rename to '${m[2].charAt(0).toLowerCase() + m[2].slice(1)}'`,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'MISSING_CANCELLATION_TOKEN',
|
|
42
|
+
severity: 'HIGH',
|
|
43
|
+
pattern: /public\s+async\s+Task(?:<[^>]+>)?\s+(\w+Async)\s*\(([^)]*)\)/g,
|
|
44
|
+
message: (m) => {
|
|
45
|
+
const params = m[2];
|
|
46
|
+
if (params.includes('CancellationToken') || params.includes('ct ') || params.includes('ct,') || params.includes('ct)')) return null;
|
|
47
|
+
return `Async method '${m[1]}' missing CancellationToken parameter`;
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'LOG_STRING_INTERPOLATION',
|
|
52
|
+
severity: 'HIGH',
|
|
53
|
+
pattern: /\.(LogInformation|LogWarning|LogError|LogDebug|LogCritical)\s*\(\s*\$"/g,
|
|
54
|
+
message: () => 'String interpolation ($"") in log call → use message template with structured parameters',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'EMPTY_CATCH',
|
|
58
|
+
severity: 'CRITICAL',
|
|
59
|
+
pattern: /catch\s*(\([^)]*\))?\s*\{\s*\}/g,
|
|
60
|
+
message: () => 'Empty catch block — exceptions are silently swallowed',
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
function collectCsFiles(dir) {
|
|
65
|
+
if (!existsSync(dir)) return [];
|
|
66
|
+
const stat = statSync(dir);
|
|
67
|
+
if (stat.isFile()) return dir.endsWith('.cs') ? [dir] : [];
|
|
68
|
+
const results = [];
|
|
69
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
70
|
+
if (entry.isDirectory() && entry.name !== 'bin' && entry.name !== 'obj' && entry.name !== '.git') {
|
|
71
|
+
results.push(...collectCsFiles(join(dir, entry.name)));
|
|
72
|
+
} else if (entry.isFile() && extname(entry.name) === '.cs') {
|
|
73
|
+
results.push(join(dir, entry.name));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return results;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const files = collectCsFiles(targetPath);
|
|
80
|
+
const findings = [];
|
|
81
|
+
|
|
82
|
+
for (const file of files) {
|
|
83
|
+
const content = readFileSync(file, 'utf-8');
|
|
84
|
+
const lines = content.split('\n');
|
|
85
|
+
|
|
86
|
+
for (const check of CHECKS) {
|
|
87
|
+
const regex = new RegExp(check.pattern.source, check.pattern.flags);
|
|
88
|
+
let match;
|
|
89
|
+
while ((match = regex.exec(content)) !== null) {
|
|
90
|
+
const msg = check.message(match);
|
|
91
|
+
if (!msg) continue;
|
|
92
|
+
const lineNum = content.slice(0, match.index).split('\n').length;
|
|
93
|
+
findings.push({
|
|
94
|
+
severity: check.severity,
|
|
95
|
+
id: check.id,
|
|
96
|
+
file: relative(process.cwd(), file).replace(/\\/g, '/'),
|
|
97
|
+
line: lineNum,
|
|
98
|
+
message: msg,
|
|
99
|
+
snippet: lines[lineNum - 1]?.trim().slice(0, 100),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const bySeverity = { CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0 };
|
|
106
|
+
for (const f of findings) bySeverity[f.severity] = (bySeverity[f.severity] ?? 0) + 1;
|
|
107
|
+
|
|
108
|
+
const summary = {
|
|
109
|
+
scanned: files.length,
|
|
110
|
+
findings: findings.length,
|
|
111
|
+
bySeverity,
|
|
112
|
+
clean: findings.length === 0,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (summaryOnly) {
|
|
116
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
117
|
+
} else {
|
|
118
|
+
console.log(JSON.stringify({ summary, findings }, null, 2));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
process.exit(findings.some(f => f.severity === 'CRITICAL') ? 1 : 0);
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: morph-checklist
|
|
3
|
-
description:
|
|
4
|
-
Pre-implementation checklist verifying that all MORPH-SPEC phases are complete and outputs exist before starting code. Use before any implementation work begins.
|
|
3
|
+
description: Pre-deploy, security, SEO, performance, accessibility, and LGPD compliance checklists for MORPH-SPEC projects. Use before deploying to production, during security audits, when optimizing for SEO or performance, or when validating Brazilian LGPD data protection compliance.
|
|
5
4
|
user-invocable: true
|
|
6
5
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
7
6
|
---
|
|
8
7
|
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
> **Layer:** 2 | **Load:** on-keyword | **Keywords:** checklist, deploy, security, seo, performance, accessibility, lgpd, legal
|
|
8
|
+
# MORPH Checklists
|
|
12
9
|
|
|
13
10
|
Types: `deploy`, `security`, `seo`, `performance`, `accessibility`, `legal-brazil`, `simulation` (see [simulation-checklist.md](simulation-checklist.md))
|
|
14
11
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: morph-replicate
|
|
3
|
-
description:
|
|
4
|
-
Replicates a completed MORPH-SPEC feature into a new feature, copying and adapting phase outputs. Called when a user wants to clone an existing feature as a starting point.
|
|
3
|
+
description: Simplified workflow for converting HTML prototypes into functional Blazor components, extracting design patterns and mapping HTML elements to Fluent UI/MudBlazor equivalents. Use when an approved HTML prototype exists and needs conversion to Blazor without a full MORPH-SPEC spec pipeline.
|
|
5
4
|
user-invocable: false
|
|
6
5
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
7
6
|
---
|
|
@@ -209,12 +208,12 @@ Mapeamento HTML → Blazor:
|
|
|
209
208
|
|
|
210
209
|
---
|
|
211
210
|
|
|
212
|
-
##
|
|
211
|
+
## Referências
|
|
213
212
|
|
|
214
|
-
-
|
|
215
|
-
-
|
|
216
|
-
-
|
|
217
|
-
-
|
|
213
|
+
- **Ref:** `framework/standards/frontend/blazor/html-conversion.md`
|
|
214
|
+
- **Ref:** `framework/standards/frontend/design-system/naming.md`
|
|
215
|
+
- **Ref:** `framework/standards/frontend/design-system/animations.md`
|
|
216
|
+
- **Ref:** `framework/standards/frontend/blazor/fluent-ui.md`
|
|
218
217
|
|
|
219
218
|
---
|
|
220
219
|
|
package/framework/skills/level-0-meta/{simulation-checklist.md → simulation-checklist/SKILL.md}
RENAMED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: simulation-checklist
|
|
3
|
-
description:
|
|
4
|
-
Checklist for simulating a full MORPH-SPEC workflow run to validate phase outputs and state consistency. Use to verify the framework is working correctly.
|
|
3
|
+
description: Checklist for implementing mock/simulation clients for external .NET services (AI APIs, payments, email). Use when setting up simulation mode without real API access, when creating fake service implementations for development/testing, or when debugging external service integrations.
|
|
5
4
|
user-invocable: true
|
|
6
5
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
7
6
|
---
|
|
8
7
|
|
|
9
|
-
#
|
|
8
|
+
# Simulation Checklist
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Checklist for simulating external services (AI, payment, email APIs).
|
|
10
|
+
Checklist for simulating external services (AI, payment, email APIs) in .NET projects.
|
|
14
11
|
|
|
15
12
|
## Pre-Implementation
|
|
16
13
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tool-usage-guide
|
|
3
|
-
description:
|
|
4
|
-
Decision guide for selecting the right Claude Code tool (Read, Grep, Glob, Bash, Task) for each situation in MORPH-SPEC workflows. Reference when unsure which tool to use.
|
|
3
|
+
description: Decision flowchart and per-phase reference for selecting the right Claude Code tool (Read, Grep, Glob, Bash, Task) or MCP tool in MORPH-SPEC workflows. Use when unsure which tool to use for a given action, when choosing between native tools and MCPs, or when deciding whether to use a subagent vs direct tools.
|
|
5
4
|
user-invocable: true
|
|
6
5
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
7
6
|
---
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: verification-before-completion
|
|
3
|
-
description:
|
|
3
|
+
description: Phase-specific verification checklists and morph-spec validation commands for confirming MORPH-SPEC outputs are complete and correct. Use before marking any task done, before advancing to the next phase, before committing, or before creating PRs.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Verification Before Completion — MORPH-SPEC Integrated
|
|
7
7
|
|
|
8
8
|
> Never claim work is complete without running verification. Evidence before assertions.
|
|
9
|
+
>
|
|
10
|
+
> **Script:** Run `node scripts/check-phase-outputs.mjs <feature> [phase]` to check required output files exist.
|
|
9
11
|
|
|
10
12
|
## When to Use
|
|
11
13
|
|
package/framework/skills/level-0-meta/verification-before-completion/scripts/check-phase-outputs.mjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* check-phase-outputs.mjs
|
|
4
|
+
*
|
|
5
|
+
* Verifies that required MORPH-SPEC output files exist for a feature/phase.
|
|
6
|
+
* Executed locally by Claude via Bash — output is returned to Claude.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node check-phase-outputs.mjs <feature> [phase]
|
|
10
|
+
*
|
|
11
|
+
* Examples:
|
|
12
|
+
* node check-phase-outputs.mjs photo-processing design
|
|
13
|
+
* node check-phase-outputs.mjs photo-processing # checks all phases
|
|
14
|
+
*
|
|
15
|
+
* Output: JSON array of { phase, file, exists, required }
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { existsSync } from 'fs';
|
|
19
|
+
import { join } from 'path';
|
|
20
|
+
|
|
21
|
+
const PHASE_OUTPUTS = {
|
|
22
|
+
proposal: [
|
|
23
|
+
{ file: '0-proposal/proposal.md', required: true },
|
|
24
|
+
],
|
|
25
|
+
design: [
|
|
26
|
+
{ file: '1-design/spec.md', required: true },
|
|
27
|
+
{ file: '1-design/contracts.cs', required: true },
|
|
28
|
+
{ file: '1-design/decisions.md', required: true },
|
|
29
|
+
{ file: '1-design/schema-analysis.md', required: false },
|
|
30
|
+
],
|
|
31
|
+
uiux: [
|
|
32
|
+
{ file: '2-ui/design-system.md', required: true },
|
|
33
|
+
{ file: '2-ui/mockups.md', required: true },
|
|
34
|
+
{ file: '2-ui/components.md', required: true },
|
|
35
|
+
{ file: '2-ui/flows.md', required: false },
|
|
36
|
+
],
|
|
37
|
+
tasks: [
|
|
38
|
+
{ file: '3-tasks/tasks.md', required: true },
|
|
39
|
+
],
|
|
40
|
+
implement: [
|
|
41
|
+
{ file: '4-implement/recap.md', required: true },
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const feature = process.argv[2];
|
|
46
|
+
const targetPhase = process.argv[3];
|
|
47
|
+
|
|
48
|
+
if (!feature) {
|
|
49
|
+
console.error(JSON.stringify({ error: 'Usage: check-phase-outputs.mjs <feature> [phase]' }));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Walk up to find .morph/ directory
|
|
54
|
+
let cwd = process.cwd();
|
|
55
|
+
let morphDir = null;
|
|
56
|
+
for (let i = 0; i < 5; i++) {
|
|
57
|
+
const candidate = join(cwd, '.morph');
|
|
58
|
+
if (existsSync(candidate)) {
|
|
59
|
+
morphDir = candidate;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
const parent = join(cwd, '..');
|
|
63
|
+
if (parent === cwd) break;
|
|
64
|
+
cwd = parent;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!morphDir) {
|
|
68
|
+
console.error(JSON.stringify({ error: '.morph/ directory not found. Run from inside a MORPH-SPEC project.' }));
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const featureDir = join(morphDir, 'features', feature);
|
|
73
|
+
if (!existsSync(featureDir)) {
|
|
74
|
+
console.error(JSON.stringify({ error: `Feature directory not found: .morph/features/${feature}` }));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const phases = targetPhase
|
|
79
|
+
? { [targetPhase]: PHASE_OUTPUTS[targetPhase] }
|
|
80
|
+
: PHASE_OUTPUTS;
|
|
81
|
+
|
|
82
|
+
if (targetPhase && !PHASE_OUTPUTS[targetPhase]) {
|
|
83
|
+
console.error(JSON.stringify({ error: `Unknown phase: ${targetPhase}. Valid: ${Object.keys(PHASE_OUTPUTS).join(', ')}` }));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const results = [];
|
|
88
|
+
let missingRequired = 0;
|
|
89
|
+
|
|
90
|
+
for (const [phase, outputs] of Object.entries(phases)) {
|
|
91
|
+
for (const { file, required } of outputs) {
|
|
92
|
+
const fullPath = join(featureDir, file);
|
|
93
|
+
const exists = existsSync(fullPath);
|
|
94
|
+
if (required && !exists) missingRequired++;
|
|
95
|
+
results.push({ phase, file, exists, required });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const summary = {
|
|
100
|
+
feature,
|
|
101
|
+
featureDir: featureDir.replace(/\\/g, '/'),
|
|
102
|
+
checks: results.length,
|
|
103
|
+
passed: results.filter(r => r.exists).length,
|
|
104
|
+
missingRequired,
|
|
105
|
+
ready: missingRequired === 0,
|
|
106
|
+
results,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
110
|
+
process.exit(missingRequired > 0 ? 1 : 0);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: phase-clarify
|
|
3
|
-
description:
|
|
4
|
-
MORPH-SPEC Phase 3 (Clarify). Resolves ambiguities from the design phase, producing clarifications.md and updating the spec. Called after design approval.
|
|
3
|
+
description: MORPH-SPEC Phase 3 (Clarify). Reviews spec.md for ambiguities, generates 3-7 targeted clarification questions, waits for user answers, then updates spec with edge cases and clarification sections. Use after design approval to eliminate spec ambiguities before task breakdown begins.
|
|
5
4
|
argument-hint: "[feature-name]"
|
|
6
5
|
user-invocable: false
|
|
7
6
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
@@ -21,8 +20,9 @@ Identifique ambiguidades na especificação e faça perguntas de clarificação
|
|
|
21
20
|
|
|
22
21
|
## Ferramentas Recomendadas
|
|
23
22
|
|
|
24
|
-
> **Ref:** `framework/skills/level-0-meta/tool-usage-guide.md` para guia completo.
|
|
23
|
+
> **Ref:** `framework/skills/level-0-meta/tool-usage-guide/SKILL.md` para guia completo.
|
|
25
24
|
> **Ref:** `framework/standards/integration/mcp/mcp-tools.md` para referência MCP.
|
|
25
|
+
> **Example:** `references/clarifications-example.md` — filled-in clarifications.md showing expected Q&A format.
|
|
26
26
|
|
|
27
27
|
| Ação | Ferramenta | Alternativa |
|
|
28
28
|
|------|------------|-------------|
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Clarifications - Photo Processing Pipeline
|
|
2
|
+
|
|
3
|
+
> Example of a well-structured clarifications.md. Filled-in reference — not a template.
|
|
4
|
+
> Each Q&A is concise: question raised during design review → answer → spec update.
|
|
5
|
+
|
|
6
|
+
**Feature**: photo-processing
|
|
7
|
+
**Phase**: CLARIFY (Phase 3)
|
|
8
|
+
**Status**: Resolved — all items incorporated into spec.md
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Questions & Answers
|
|
13
|
+
|
|
14
|
+
### Q1: File size limit — 10MB for all users or tiered?
|
|
15
|
+
|
|
16
|
+
**Question:** The spec says max 10MB but the proposal mentioned "higher for pro users." Should we implement tiered limits now?
|
|
17
|
+
|
|
18
|
+
**Answer:** Free tier: 10MB. Pro tier: 50MB. Enforce via `[Authorize]` + claims check in the upload endpoint. YAGNI — don't build a generic tier system, just check the plan claim directly.
|
|
19
|
+
|
|
20
|
+
**Spec Updates:**
|
|
21
|
+
- Updated `spec.md` FR1 to specify tiered limits
|
|
22
|
+
- Added `CanUploadLargeFile` policy to Security section
|
|
23
|
+
- Updated `UploadPhotoCommand` to accept `userPlan` claim
|
|
24
|
+
|
|
25
|
+
**Priority:** High — affects contracts
|
|
26
|
+
**Resolved:** ✅ Yes
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### Q2: Processed photo retention — indefinite or expiring?
|
|
31
|
+
|
|
32
|
+
**Question:** Should processed photos in Blob Storage be kept forever, or do they expire?
|
|
33
|
+
|
|
34
|
+
**Answer:** Auto-delete after 30 days via Blob lifecycle policy (no code needed, configured in Azure). Free tier: 7 days. Pro tier: 30 days. This is infrastructure-only — `ProcessingJob.ProcessedPhotoUrl` stays in DB but becomes a dead link after expiry.
|
|
35
|
+
|
|
36
|
+
**Spec Updates:**
|
|
37
|
+
- Added ADR-003 (Blob lifecycle policy over code-based cleanup)
|
|
38
|
+
- Added note to `AzureBlobStorageService` about lifecycle dependency
|
|
39
|
+
|
|
40
|
+
**Priority:** Low — no code change
|
|
41
|
+
**Resolved:** ✅ Yes
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### Q3: AI API — async webhook or polling?
|
|
46
|
+
|
|
47
|
+
**Question:** spec.md assumed Hangfire polls job completion, but the AI vendor docs mention a webhook callback option.
|
|
48
|
+
|
|
49
|
+
**Answer:** Use fire-and-forget HTTP call + Hangfire continuation (not webhook). The AI API's webhook requires a public URL we don't have in dev. Fire-and-forget is simpler and testable. If the vendor SLA changes, we can swap to webhook via `IPhotoProcessingJob` interface — no consumer changes needed.
|
|
50
|
+
|
|
51
|
+
**Spec Updates:**
|
|
52
|
+
- Clarified Processing Flow in spec.md to show fire-and-forget + await pattern
|
|
53
|
+
- Added to Risks: "AI API webhook migration path if needed"
|
|
54
|
+
|
|
55
|
+
**Priority:** High — affects job implementation
|
|
56
|
+
**Resolved:** ✅ Yes
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Edge Cases
|
|
61
|
+
|
|
62
|
+
### EC1: Upload during Hangfire downtime
|
|
63
|
+
|
|
64
|
+
**Scenario:** User uploads successfully but Hangfire server is stopped — job never executes.
|
|
65
|
+
|
|
66
|
+
**Expected Behavior:** Job stays in `Pending` indefinitely. On next Hangfire server start, job auto-resumes (Hangfire persistent storage).
|
|
67
|
+
|
|
68
|
+
**Solution:** No code change. Add monitoring alert if job stays Pending > 10 minutes.
|
|
69
|
+
|
|
70
|
+
**Acceptance Criteria:**
|
|
71
|
+
- [ ] `ProcessingJob` with status `Pending` survives Hangfire restart
|
|
72
|
+
- [ ] Hangfire picks up orphaned jobs on startup (built-in behavior, covered by docs)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### EC2: Concurrent uploads of same file
|
|
77
|
+
|
|
78
|
+
**Scenario:** User double-clicks Upload button, sending two identical requests simultaneously.
|
|
79
|
+
|
|
80
|
+
**Expected Behavior:** Two separate `ProcessingJob` records created. Both process independently. No deduplication (not required at MVP scale).
|
|
81
|
+
|
|
82
|
+
**Solution:** No code change. Each request gets a fresh GUID. If deduplication becomes needed, add idempotency key header in v2.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Business Rules Clarified
|
|
87
|
+
|
|
88
|
+
### BR1: Only the uploading user can download their processed photo
|
|
89
|
+
|
|
90
|
+
**Rule:** `GET /api/download/{jobId}` must check `job.UserId == currentUserId`. Return 403 if mismatch.
|
|
91
|
+
|
|
92
|
+
**Rationale:** Users might guess sequential GUIDs (they can't since we use random GUIDs, but defense in depth).
|
|
93
|
+
|
|
94
|
+
**Implementation:** Add `[Authorize]` + ownership check to download endpoint. Already in Security section of spec.md.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Summary
|
|
99
|
+
|
|
100
|
+
| | Count |
|
|
101
|
+
|---|---|
|
|
102
|
+
| Questions Answered | 3 / 3 |
|
|
103
|
+
| Edge Cases Documented | 2 |
|
|
104
|
+
| Business Rules Clarified | 1 |
|
|
105
|
+
| Spec Updates Made | 6 |
|
|
106
|
+
|
|
107
|
+
## Next Steps
|
|
108
|
+
|
|
109
|
+
1. [x] All questions resolved
|
|
110
|
+
2. [x] `spec.md` updated with all clarifications
|
|
111
|
+
3. [x] `contracts.cs` updated (`UploadPhotoCommand` + plan claim)
|
|
112
|
+
4. [x] Stakeholder approval received
|
|
113
|
+
5. [ ] Advance to Phase 4 (Tasks)
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
*MORPH-SPEC by Polymorphism Tech*
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: phase-codebase-analysis
|
|
3
|
-
description:
|
|
4
|
-
MORPH-SPEC sub-phase of Design. Analyzes existing codebase patterns, architecture, and conventions before writing the spec. Called automatically at the start of Design phase.
|
|
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.
|
|
5
4
|
user-invocable: false
|
|
6
5
|
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
7
6
|
---
|
|
@@ -21,7 +20,7 @@ Automatiza a análise de código existente para gerar `schema-analysis.md` com d
|
|
|
21
20
|
|
|
22
21
|
## Ferramentas Recomendadas
|
|
23
22
|
|
|
24
|
-
> **Ref:** `framework/skills/level-0-meta/tool-usage-guide.md` para guia completo.
|
|
23
|
+
> **Ref:** `framework/skills/level-0-meta/tool-usage-guide/SKILL.md` para guia completo.
|
|
25
24
|
> **Ref:** `framework/standards/integration/mcp/mcp-tools.md` para referência MCP.
|
|
26
25
|
|
|
27
26
|
| Ação | Ferramenta | Alternativa |
|