@polymorphism-tech/morph-spec 8.0.0 → 8.1.1

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 (168) hide show
  1. package/README.md +2 -2
  2. package/bin/validate.js +379 -379
  3. package/claude-plugin.json +1 -1
  4. package/docs/CHEATSHEET.md +1 -1
  5. package/docs/QUICKSTART.md +1 -1
  6. package/framework/CLAUDE.md +1 -1
  7. package/framework/MORPH.md +5 -5
  8. package/framework/agents.json +1 -1
  9. package/framework/commands/commit.md +166 -166
  10. package/framework/commands/morph-infra.md +215 -215
  11. package/framework/commands/morph-preflight.md +205 -205
  12. package/framework/commands/morph-troubleshoot.md +124 -124
  13. package/framework/hooks/README.md +0 -1
  14. package/framework/hooks/claude-code/statusline.py +679 -679
  15. package/framework/hooks/claude-code/statusline.sh +11 -11
  16. package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
  17. package/framework/hooks/git/pre-commit/agents.sh +25 -25
  18. package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
  19. package/framework/hooks/git/pre-commit/specs.sh +50 -50
  20. package/framework/hooks/git/pre-push/run-tests.sh +44 -44
  21. package/framework/hooks/shared/activity-logger.js +160 -160
  22. package/framework/hooks/shared/stdin-reader.js +26 -26
  23. package/framework/rubrics/backend.json +41 -41
  24. package/framework/rules/ai-agents-standards.md +45 -45
  25. package/framework/rules/dotnet-templates.md +86 -86
  26. package/framework/rules/frontend-standards.md +13 -13
  27. package/framework/rules/infrastructure-standards.md +27 -27
  28. package/framework/rules/neon-standards.md +25 -25
  29. package/framework/rules/nextjs-standards.md +20 -20
  30. package/framework/rules/nextjs-templates.md +40 -40
  31. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  32. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  33. package/framework/skills/core/morph-apply/SKILL.md +12 -21
  34. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  35. package/framework/skills/core/morph-eval/SKILL.md +1 -1
  36. package/framework/skills/core/morph-hotfix/SKILL.md +2 -4
  37. package/framework/skills/core/morph-implement/SKILL.md +10 -19
  38. package/framework/skills/core/morph-plan/SKILL.md +1 -1
  39. package/framework/skills/core/morph-proposal/SKILL.md +1 -1
  40. package/framework/skills/core/morph-review/SKILL.md +11 -15
  41. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  42. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  43. package/framework/standards/ai-agents/agent-session.md +160 -160
  44. package/framework/standards/ai-agents/batching.md +193 -193
  45. package/framework/standards/ai-agents/context-providers.md +188 -188
  46. package/framework/standards/ai-agents/mcp-server.md +250 -250
  47. package/framework/standards/ai-agents/mcp-tools.md +197 -197
  48. package/framework/standards/ai-agents/middleware-patterns.md +207 -207
  49. package/framework/standards/ai-agents/modalities-image-gen.md +173 -173
  50. package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -171
  51. package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -181
  52. package/framework/standards/ai-agents/modalities-vision.md +201 -201
  53. package/framework/standards/ai-agents/multi-agent-patterns.md +155 -155
  54. package/framework/standards/ai-agents/production.md +275 -275
  55. package/framework/standards/ai-agents/prompts-in-db.md +214 -214
  56. package/framework/standards/ai-agents/providers/model-registry.md +158 -158
  57. package/framework/standards/ai-agents/service-tier-flex.md +135 -135
  58. package/framework/standards/ai-agents/structured-output.md +249 -249
  59. package/framework/standards/ai-agents/sweet-spot.md +109 -109
  60. package/framework/templates/IDE-SNIPPETS.md +262 -262
  61. package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
  62. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
  63. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
  64. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
  65. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
  66. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
  67. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
  68. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
  69. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
  70. package/framework/templates/code/dotnet/database/migration.cs +83 -83
  71. package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
  72. package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
  73. package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
  74. package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
  75. package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
  76. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
  77. package/framework/templates/code/typescript/contracts.ts +167 -167
  78. package/framework/templates/docs/clarifications.md +253 -253
  79. package/framework/templates/docs/schema-analysis.md +119 -119
  80. package/framework/templates/docs/ui-components.md +52 -52
  81. package/framework/templates/docs/ui-design-system.md +76 -76
  82. package/framework/templates/docs/ui-flows.md +167 -167
  83. package/framework/templates/docs/ui-mockups.md +98 -98
  84. package/framework/templates/feature/decisions.md +122 -122
  85. package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
  86. package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
  87. package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
  88. package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
  89. package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
  90. package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
  91. package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
  92. package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
  93. package/framework/templates/infrastructure/docker/docker-compose.template.yml +50 -50
  94. package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
  95. package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
  96. package/framework/templates/infrastructure/github/README.md +56 -56
  97. package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
  98. package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
  99. package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
  100. package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
  101. package/framework/templates/integrations/asaas-client.cs +387 -387
  102. package/framework/templates/integrations/asaas-webhook.cs +351 -351
  103. package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
  104. package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
  105. package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
  106. package/framework/templates/project/validate.js +120 -120
  107. package/framework/templates/state.template.json +17 -17
  108. package/framework/templates/ui/design-system.css +226 -226
  109. package/package.json +1 -1
  110. package/src/commands/dashboard/dashboard.js +53 -53
  111. package/src/commands/index.js +13 -13
  112. package/src/commands/mcp/mcp-setup.js +519 -519
  113. package/src/commands/project/checkpoint.js +209 -209
  114. package/src/commands/project/worktree.js +83 -1
  115. package/src/core/state/phase-state-machine.js +197 -197
  116. package/src/core/templates/template-renderer.js +477 -477
  117. package/src/dashboard/app/components/DetailPanel.jsx +11 -11
  118. package/src/dashboard/app/components/FlowGraph.jsx +17 -17
  119. package/src/dashboard/app/components/SearchFilter.jsx +22 -22
  120. package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
  121. package/src/dashboard/app/main.jsx +13 -13
  122. package/src/dashboard/app/pages/AgentMap.jsx +370 -370
  123. package/src/dashboard/app/pages/HookInspector.jsx +418 -418
  124. package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
  125. package/src/dashboard/app/pages/RulesMap.jsx +273 -273
  126. package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
  127. package/src/dashboard/app/pages/Standards.jsx +332 -332
  128. package/src/dashboard/app/styles/index.css +47 -47
  129. package/src/dashboard/index.html +12 -12
  130. package/src/dashboard/package.json +24 -24
  131. package/src/dashboard/scanner/hooks-scanner.js +41 -41
  132. package/src/dashboard/scanner/phases-scanner.js +15 -15
  133. package/src/dashboard/scanner/rubrics-scanner.js +12 -12
  134. package/src/dashboard/scanner/rules-scanner.js +37 -37
  135. package/src/dashboard/scanner/skills-scanner.js +43 -43
  136. package/src/dashboard/scanner/squads-scanner.js +13 -13
  137. package/src/dashboard/scanner/standards-scanner.js +26 -26
  138. package/src/dashboard/vite-plugin-morph-data.js +17 -17
  139. package/src/dashboard/vite.config.js +24 -24
  140. package/src/lib/agents/metrics-aggregator.js +56 -56
  141. package/src/lib/agents/metrics-calculator.js +125 -125
  142. package/src/lib/agents/output-collector.js +73 -73
  143. package/src/lib/detectors/claude-config-detector.js +152 -152
  144. package/src/lib/detectors/design-system-detector.js +231 -231
  145. package/src/lib/detectors/index.js +217 -217
  146. package/src/lib/generators/architecture-scanner.js +639 -639
  147. package/src/lib/generators/design-system-generator.js +508 -508
  148. package/src/lib/generators/index.js +13 -13
  149. package/src/lib/generators/settings-generator.js +209 -209
  150. package/src/lib/hooks/hook-executor.js +167 -167
  151. package/src/lib/installers/mcp-installer.js +719 -719
  152. package/src/lib/tasks/task-classifier.js +30 -30
  153. package/src/lib/tasks/task-parser.js +209 -209
  154. package/src/lib/validators/architecture/architecture-validator.js +259 -259
  155. package/src/lib/validators/checkpoint-persistence.js +39 -39
  156. package/src/lib/validators/contracts/contract-compliance-validator.js +274 -274
  157. package/src/lib/validators/css/css-validator.js +340 -340
  158. package/src/lib/validators/packages/package-validator.js +347 -347
  159. package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
  160. package/src/lib/validators/shared/issue-counter.js +14 -14
  161. package/src/lib/validators/validation-runner.js +349 -349
  162. package/src/utils/agent-id-mapper.js +11 -11
  163. package/src/utils/claude-settings-manager.js +300 -300
  164. package/src/utils/hooks-installer.js +3 -24
  165. package/src/utils/skills-installer.js +174 -174
  166. package/framework/hooks/claude-code/core/subagent-report-guard.js +0 -95
  167. package/framework/templates/.idea/morph-templates.xml +0 -92
  168. package/framework/templates/.vscode/morph-templates.code-snippets +0 -186
@@ -1,259 +1,259 @@
1
- /**
2
- * Architecture Pattern Validator
3
- *
4
- * Validates architectural patterns and detects anti-patterns in .NET apps.
5
- * Checks Program.cs configuration, middleware order, and common DI issues.
6
- *
7
- * MORPH-SPEC 3.0 - Sprint 4
8
- */
9
-
10
- import { readFileSync } from 'fs';
11
- import chalk from 'chalk';
12
-
13
- /**
14
- * Architecture Validation Rules
15
- */
16
- const VALIDATION_RULES = {
17
- // Program.cs Issues
18
- missingHttpClient: {
19
- pattern: /AddHttpClient\(\)/,
20
- inverse: true, // Rule triggers if pattern NOT found
21
- level: 'error',
22
- message: 'AddHttpClient() missing in Program.cs',
23
- reference: 'framework/standards/program-cs-checklist.md',
24
- solution: 'Add builder.Services.AddHttpClient() before builder.Build()'
25
- },
26
-
27
- missingHttpContextAccessor: {
28
- pattern: /AddHttpContextAccessor\(\)/,
29
- inverse: true,
30
- level: 'warning',
31
- message: 'AddHttpContextAccessor() missing (needed for auth contexts)',
32
- reference: 'framework/standards/program-cs-checklist.md',
33
- solution: 'Add builder.Services.AddHttpContextAccessor()'
34
- },
35
-
36
- missingStaticFiles: {
37
- pattern: /app\.UseStaticFiles\(\)/,
38
- inverse: true,
39
- level: 'error',
40
- message: 'app.UseStaticFiles() missing (CSS/JS won\'t load)',
41
- reference: 'framework/standards/program-cs-checklist.md',
42
- solution: 'Add app.UseStaticFiles() before app.UseAntiforgery()'
43
- },
44
-
45
- wrongMiddlewareOrder: {
46
- // Custom validator (checked in validateProgramCs)
47
- level: 'error',
48
- message: 'app.UseStaticFiles() must come BEFORE app.UseAntiforgery()',
49
- reference: 'framework/standards/program-cs-checklist.md',
50
- solution: 'Reorder: UseStaticFiles() → UseAntiforgery() → UseAuthorization()'
51
- }
52
- };
53
-
54
- /**
55
- * Architecture Validator Class
56
- */
57
- export class ArchitectureValidator {
58
- constructor(projectPath = '.') {
59
- this.projectPath = projectPath;
60
- }
61
-
62
- /**
63
- * Validate all architecture rules
64
- */
65
- async validateAll() {
66
- const results = {
67
- programCs: await this.validateProgramCs()
68
- };
69
-
70
- const allIssues = [
71
- ...results.programCs.issues
72
- ];
73
-
74
- return {
75
- status: allIssues.length === 0 ? 'ok' : 'error',
76
- totalIssues: allIssues.length,
77
- errors: allIssues.filter(i => i.level === 'error').length,
78
- warnings: allIssues.filter(i => i.level === 'warning').length,
79
- results
80
- };
81
- }
82
-
83
- /**
84
- * Validate Program.cs
85
- */
86
- async validateProgramCs() {
87
- const programCsPath = 'Program.cs';
88
-
89
- try {
90
- const content = readFileSync(programCsPath, 'utf-8');
91
- return this.validateProgramCsContent(content);
92
- } catch (error) {
93
- // No Program.cs found (not a .NET project)
94
- return {
95
- exists: false,
96
- issues: []
97
- };
98
- }
99
- }
100
-
101
- /**
102
- * Validate Program.cs content
103
- */
104
- validateProgramCsContent(content) {
105
- const issues = [];
106
-
107
- // Check missing patterns (inverse rules)
108
- const inverseRules = ['missingHttpClient', 'missingHttpContextAccessor', 'missingStaticFiles'];
109
-
110
- for (const ruleId of inverseRules) {
111
- const rule = VALIDATION_RULES[ruleId];
112
- const found = rule.pattern.test(content);
113
-
114
- if (!found) {
115
- issues.push({
116
- file: 'Program.cs',
117
- rule: ruleId,
118
- level: rule.level,
119
- message: rule.message,
120
- reference: rule.reference,
121
- solution: rule.solution
122
- });
123
- }
124
- }
125
-
126
- // Check middleware order
127
- const staticFilesIndex = content.indexOf('UseStaticFiles');
128
- const antiforgeryIndex = content.indexOf('UseAntiforgery');
129
-
130
- if (staticFilesIndex > 0 && antiforgeryIndex > 0 && staticFilesIndex > antiforgeryIndex) {
131
- const rule = VALIDATION_RULES.wrongMiddlewareOrder;
132
- issues.push({
133
- file: 'Program.cs',
134
- rule: 'wrongMiddlewareOrder',
135
- level: rule.level,
136
- message: rule.message,
137
- reference: rule.reference,
138
- solution: rule.solution,
139
- lineNumber: this.findLineNumber(content, /UseStaticFiles/)
140
- });
141
- }
142
-
143
- return {
144
- exists: true,
145
- issues
146
- };
147
- }
148
-
149
- /**
150
- * Find line number of pattern match
151
- */
152
- findLineNumber(content, pattern) {
153
- const lines = content.split('\n');
154
- for (let i = 0; i < lines.length; i++) {
155
- if (pattern.test(lines[i])) {
156
- return i + 1;
157
- }
158
- }
159
- return null;
160
- }
161
-
162
- /**
163
- * Format validation results for console output
164
- */
165
- formatResults(results) {
166
- if (results.status === 'ok') {
167
- console.log(chalk.green('āœ… No architecture issues found'));
168
- return;
169
- }
170
-
171
- console.log(chalk.yellow(`\nāš ļø Found ${results.totalIssues} architecture issue(s):\n`));
172
-
173
- // Group by file
174
- const issuesByFile = new Map();
175
- const allIssues = [
176
- ...results.results.programCs.issues
177
- ];
178
-
179
- for (const issue of allIssues) {
180
- if (!issuesByFile.has(issue.file)) {
181
- issuesByFile.set(issue.file, []);
182
- }
183
- issuesByFile.get(issue.file).push(issue);
184
- }
185
-
186
- // Display by file
187
- for (const [file, issues] of issuesByFile) {
188
- console.log(chalk.cyan(`\nšŸ“„ ${file}`));
189
-
190
- const errors = issues.filter(i => i.level === 'error');
191
- const warnings = issues.filter(i => i.level === 'warning');
192
-
193
- if (errors.length > 0) {
194
- console.log(chalk.red(` āŒ ${errors.length} error(s):`));
195
- errors.forEach(e => {
196
- const location = e.lineNumber ? `:${e.lineNumber}` : '';
197
- console.log(chalk.red(` ${file}${location}`));
198
- console.log(chalk.red(` - ${e.message}`));
199
- console.log(chalk.gray(` Solution: ${e.solution}`));
200
- console.log(chalk.blue(` Reference: ${e.reference}`));
201
- });
202
- }
203
-
204
- if (warnings.length > 0) {
205
- console.log(chalk.yellow(` āš ļø ${warnings.length} warning(s):`));
206
- warnings.forEach(w => {
207
- const location = w.lineNumber ? `:${w.lineNumber}` : '';
208
- console.log(chalk.yellow(` ${file}${location}`));
209
- console.log(chalk.yellow(` - ${w.message}`));
210
- console.log(chalk.gray(` Solution: ${w.solution}`));
211
- });
212
- }
213
- }
214
-
215
- console.log('');
216
- }
217
-
218
- /**
219
- * Get suggested fixes
220
- */
221
- getSuggestedFixes(results) {
222
- const fixes = [];
223
- const allIssues = [
224
- ...results.results.programCs.issues
225
- ];
226
-
227
- for (const issue of allIssues) {
228
- fixes.push({
229
- file: issue.file,
230
- line: issue.lineNumber,
231
- issue: issue.message,
232
- solution: issue.solution,
233
- reference: issue.reference,
234
- severity: issue.level
235
- });
236
- }
237
-
238
- return fixes;
239
- }
240
- }
241
-
242
- /**
243
- * Quick validation function (for imports)
244
- */
245
- export async function validateArchitecture(projectPath = '.', options = {}) {
246
- const validator = new ArchitectureValidator(projectPath);
247
- const results = await validator.validateAll();
248
-
249
- if (options.verbose) {
250
- validator.formatResults(results);
251
- }
252
-
253
- if (options.fixes) {
254
- const fixes = validator.getSuggestedFixes(results);
255
- return { ...results, fixes };
256
- }
257
-
258
- return results;
259
- }
1
+ /**
2
+ * Architecture Pattern Validator
3
+ *
4
+ * Validates architectural patterns and detects anti-patterns in .NET apps.
5
+ * Checks Program.cs configuration, middleware order, and common DI issues.
6
+ *
7
+ * MORPH-SPEC 3.0 - Sprint 4
8
+ */
9
+
10
+ import { readFileSync } from 'fs';
11
+ import chalk from 'chalk';
12
+
13
+ /**
14
+ * Architecture Validation Rules
15
+ */
16
+ const VALIDATION_RULES = {
17
+ // Program.cs Issues
18
+ missingHttpClient: {
19
+ pattern: /AddHttpClient\(\)/,
20
+ inverse: true, // Rule triggers if pattern NOT found
21
+ level: 'error',
22
+ message: 'AddHttpClient() missing in Program.cs',
23
+ reference: 'framework/standards/program-cs-checklist.md',
24
+ solution: 'Add builder.Services.AddHttpClient() before builder.Build()'
25
+ },
26
+
27
+ missingHttpContextAccessor: {
28
+ pattern: /AddHttpContextAccessor\(\)/,
29
+ inverse: true,
30
+ level: 'warning',
31
+ message: 'AddHttpContextAccessor() missing (needed for auth contexts)',
32
+ reference: 'framework/standards/program-cs-checklist.md',
33
+ solution: 'Add builder.Services.AddHttpContextAccessor()'
34
+ },
35
+
36
+ missingStaticFiles: {
37
+ pattern: /app\.UseStaticFiles\(\)/,
38
+ inverse: true,
39
+ level: 'error',
40
+ message: 'app.UseStaticFiles() missing (CSS/JS won\'t load)',
41
+ reference: 'framework/standards/program-cs-checklist.md',
42
+ solution: 'Add app.UseStaticFiles() before app.UseAntiforgery()'
43
+ },
44
+
45
+ wrongMiddlewareOrder: {
46
+ // Custom validator (checked in validateProgramCs)
47
+ level: 'error',
48
+ message: 'app.UseStaticFiles() must come BEFORE app.UseAntiforgery()',
49
+ reference: 'framework/standards/program-cs-checklist.md',
50
+ solution: 'Reorder: UseStaticFiles() → UseAntiforgery() → UseAuthorization()'
51
+ }
52
+ };
53
+
54
+ /**
55
+ * Architecture Validator Class
56
+ */
57
+ export class ArchitectureValidator {
58
+ constructor(projectPath = '.') {
59
+ this.projectPath = projectPath;
60
+ }
61
+
62
+ /**
63
+ * Validate all architecture rules
64
+ */
65
+ async validateAll() {
66
+ const results = {
67
+ programCs: await this.validateProgramCs()
68
+ };
69
+
70
+ const allIssues = [
71
+ ...results.programCs.issues
72
+ ];
73
+
74
+ return {
75
+ status: allIssues.length === 0 ? 'ok' : 'error',
76
+ totalIssues: allIssues.length,
77
+ errors: allIssues.filter(i => i.level === 'error').length,
78
+ warnings: allIssues.filter(i => i.level === 'warning').length,
79
+ results
80
+ };
81
+ }
82
+
83
+ /**
84
+ * Validate Program.cs
85
+ */
86
+ async validateProgramCs() {
87
+ const programCsPath = 'Program.cs';
88
+
89
+ try {
90
+ const content = readFileSync(programCsPath, 'utf-8');
91
+ return this.validateProgramCsContent(content);
92
+ } catch (error) {
93
+ // No Program.cs found (not a .NET project)
94
+ return {
95
+ exists: false,
96
+ issues: []
97
+ };
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Validate Program.cs content
103
+ */
104
+ validateProgramCsContent(content) {
105
+ const issues = [];
106
+
107
+ // Check missing patterns (inverse rules)
108
+ const inverseRules = ['missingHttpClient', 'missingHttpContextAccessor', 'missingStaticFiles'];
109
+
110
+ for (const ruleId of inverseRules) {
111
+ const rule = VALIDATION_RULES[ruleId];
112
+ const found = rule.pattern.test(content);
113
+
114
+ if (!found) {
115
+ issues.push({
116
+ file: 'Program.cs',
117
+ rule: ruleId,
118
+ level: rule.level,
119
+ message: rule.message,
120
+ reference: rule.reference,
121
+ solution: rule.solution
122
+ });
123
+ }
124
+ }
125
+
126
+ // Check middleware order
127
+ const staticFilesIndex = content.indexOf('UseStaticFiles');
128
+ const antiforgeryIndex = content.indexOf('UseAntiforgery');
129
+
130
+ if (staticFilesIndex > 0 && antiforgeryIndex > 0 && staticFilesIndex > antiforgeryIndex) {
131
+ const rule = VALIDATION_RULES.wrongMiddlewareOrder;
132
+ issues.push({
133
+ file: 'Program.cs',
134
+ rule: 'wrongMiddlewareOrder',
135
+ level: rule.level,
136
+ message: rule.message,
137
+ reference: rule.reference,
138
+ solution: rule.solution,
139
+ lineNumber: this.findLineNumber(content, /UseStaticFiles/)
140
+ });
141
+ }
142
+
143
+ return {
144
+ exists: true,
145
+ issues
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Find line number of pattern match
151
+ */
152
+ findLineNumber(content, pattern) {
153
+ const lines = content.split('\n');
154
+ for (let i = 0; i < lines.length; i++) {
155
+ if (pattern.test(lines[i])) {
156
+ return i + 1;
157
+ }
158
+ }
159
+ return null;
160
+ }
161
+
162
+ /**
163
+ * Format validation results for console output
164
+ */
165
+ formatResults(results) {
166
+ if (results.status === 'ok') {
167
+ console.log(chalk.green('āœ… No architecture issues found'));
168
+ return;
169
+ }
170
+
171
+ console.log(chalk.yellow(`\nāš ļø Found ${results.totalIssues} architecture issue(s):\n`));
172
+
173
+ // Group by file
174
+ const issuesByFile = new Map();
175
+ const allIssues = [
176
+ ...results.results.programCs.issues
177
+ ];
178
+
179
+ for (const issue of allIssues) {
180
+ if (!issuesByFile.has(issue.file)) {
181
+ issuesByFile.set(issue.file, []);
182
+ }
183
+ issuesByFile.get(issue.file).push(issue);
184
+ }
185
+
186
+ // Display by file
187
+ for (const [file, issues] of issuesByFile) {
188
+ console.log(chalk.cyan(`\nšŸ“„ ${file}`));
189
+
190
+ const errors = issues.filter(i => i.level === 'error');
191
+ const warnings = issues.filter(i => i.level === 'warning');
192
+
193
+ if (errors.length > 0) {
194
+ console.log(chalk.red(` āŒ ${errors.length} error(s):`));
195
+ errors.forEach(e => {
196
+ const location = e.lineNumber ? `:${e.lineNumber}` : '';
197
+ console.log(chalk.red(` ${file}${location}`));
198
+ console.log(chalk.red(` - ${e.message}`));
199
+ console.log(chalk.gray(` Solution: ${e.solution}`));
200
+ console.log(chalk.blue(` Reference: ${e.reference}`));
201
+ });
202
+ }
203
+
204
+ if (warnings.length > 0) {
205
+ console.log(chalk.yellow(` āš ļø ${warnings.length} warning(s):`));
206
+ warnings.forEach(w => {
207
+ const location = w.lineNumber ? `:${w.lineNumber}` : '';
208
+ console.log(chalk.yellow(` ${file}${location}`));
209
+ console.log(chalk.yellow(` - ${w.message}`));
210
+ console.log(chalk.gray(` Solution: ${w.solution}`));
211
+ });
212
+ }
213
+ }
214
+
215
+ console.log('');
216
+ }
217
+
218
+ /**
219
+ * Get suggested fixes
220
+ */
221
+ getSuggestedFixes(results) {
222
+ const fixes = [];
223
+ const allIssues = [
224
+ ...results.results.programCs.issues
225
+ ];
226
+
227
+ for (const issue of allIssues) {
228
+ fixes.push({
229
+ file: issue.file,
230
+ line: issue.lineNumber,
231
+ issue: issue.message,
232
+ solution: issue.solution,
233
+ reference: issue.reference,
234
+ severity: issue.level
235
+ });
236
+ }
237
+
238
+ return fixes;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Quick validation function (for imports)
244
+ */
245
+ export async function validateArchitecture(projectPath = '.', options = {}) {
246
+ const validator = new ArchitectureValidator(projectPath);
247
+ const results = await validator.validateAll();
248
+
249
+ if (options.verbose) {
250
+ validator.formatResults(results);
251
+ }
252
+
253
+ if (options.fixes) {
254
+ const fixes = validator.getSuggestedFixes(results);
255
+ return { ...results, fixes };
256
+ }
257
+
258
+ return results;
259
+ }
@@ -1,39 +1,39 @@
1
- /**
2
- * Checkpoint Validation Persistence
3
- *
4
- * Persists checkpoint validation results to disk for traceability.
5
- * Each checkpoint writes a JSON file to:
6
- * .morph/features/{feature}/3-implement/validations/checkpoint-{N}.json
7
- */
8
-
9
- import { mkdirSync, writeFileSync } from 'fs';
10
- import { join } from 'path';
11
-
12
- /**
13
- * Persist a checkpoint validation result to disk.
14
- *
15
- * @param {string} projectPath - Project root
16
- * @param {string} featureName - Feature name
17
- * @param {{ checkpointNum: number, timestamp: string, passed: boolean, validators: Object, summary: string, feature?: string, phase?: string }} result - Validation result
18
- * @returns {string} Path to the saved JSON file
19
- */
20
- export function persistCheckpointValidation(projectPath, featureName, result) {
21
- const dir = join(projectPath, `.morph/features/${featureName}/3-implement/validations`);
22
- mkdirSync(dir, { recursive: true });
23
-
24
- const filename = `checkpoint-${result.checkpointNum}.json`;
25
- const filePath = join(dir, filename);
26
-
27
- const output = {
28
- checkpointNum: result.checkpointNum,
29
- timestamp: result.timestamp || new Date().toISOString(),
30
- passed: result.passed,
31
- validators: result.validators || {},
32
- summary: result.summary || '',
33
- feature: result.feature || featureName,
34
- phase: result.phase || 'implement',
35
- };
36
-
37
- writeFileSync(filePath, JSON.stringify(output, null, 2), 'utf8');
38
- return filePath;
39
- }
1
+ /**
2
+ * Checkpoint Validation Persistence
3
+ *
4
+ * Persists checkpoint validation results to disk for traceability.
5
+ * Each checkpoint writes a JSON file to:
6
+ * .morph/features/{feature}/3-implement/validations/checkpoint-{N}.json
7
+ */
8
+
9
+ import { mkdirSync, writeFileSync } from 'fs';
10
+ import { join } from 'path';
11
+
12
+ /**
13
+ * Persist a checkpoint validation result to disk.
14
+ *
15
+ * @param {string} projectPath - Project root
16
+ * @param {string} featureName - Feature name
17
+ * @param {{ checkpointNum: number, timestamp: string, passed: boolean, validators: Object, summary: string, feature?: string, phase?: string }} result - Validation result
18
+ * @returns {string} Path to the saved JSON file
19
+ */
20
+ export function persistCheckpointValidation(projectPath, featureName, result) {
21
+ const dir = join(projectPath, `.morph/features/${featureName}/3-implement/validations`);
22
+ mkdirSync(dir, { recursive: true });
23
+
24
+ const filename = `checkpoint-${result.checkpointNum}.json`;
25
+ const filePath = join(dir, filename);
26
+
27
+ const output = {
28
+ checkpointNum: result.checkpointNum,
29
+ timestamp: result.timestamp || new Date().toISOString(),
30
+ passed: result.passed,
31
+ validators: result.validators || {},
32
+ summary: result.summary || '',
33
+ feature: result.feature || featureName,
34
+ phase: result.phase || 'implement',
35
+ };
36
+
37
+ writeFileSync(filePath, JSON.stringify(output, null, 2), 'utf8');
38
+ return filePath;
39
+ }