@polymorphism-tech/morph-spec 1.0.4 → 2.0.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 (152) hide show
  1. package/CLAUDE.md +1381 -0
  2. package/LICENSE +72 -0
  3. package/README.md +89 -6
  4. package/bin/detect-agents.js +225 -0
  5. package/bin/morph-spec.js +120 -0
  6. package/bin/render-template.js +302 -0
  7. package/bin/semantic-detect-agents.js +246 -0
  8. package/bin/validate-agents-skills.js +239 -0
  9. package/bin/validate-agents.js +69 -0
  10. package/bin/validate-phase.js +263 -0
  11. package/content/.azure/README.md +293 -0
  12. package/content/.azure/docs/azure-devops-setup.md +454 -0
  13. package/content/.azure/docs/branch-strategy.md +398 -0
  14. package/content/.azure/docs/local-development.md +515 -0
  15. package/content/.azure/pipelines/pipeline-variables.yml +34 -0
  16. package/content/.azure/pipelines/prod-pipeline.yml +319 -0
  17. package/content/.azure/pipelines/staging-pipeline.yml +234 -0
  18. package/content/.azure/pipelines/templates/build-dotnet.yml +75 -0
  19. package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -0
  20. package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -0
  21. package/content/.azure/pipelines/templates/infra-deploy.yml +90 -0
  22. package/content/.claude/commands/morph-apply.md +118 -26
  23. package/content/.claude/commands/morph-archive.md +9 -9
  24. package/content/.claude/commands/morph-clarify.md +184 -0
  25. package/content/.claude/commands/morph-design.md +275 -0
  26. package/content/.claude/commands/morph-proposal.md +56 -15
  27. package/content/.claude/commands/morph-setup.md +100 -0
  28. package/content/.claude/commands/morph-status.md +47 -32
  29. package/content/.claude/commands/morph-tasks.md +319 -0
  30. package/content/.claude/commands/morph-uiux.md +211 -0
  31. package/content/.claude/skills/specialists/ai-system-architect.md +604 -0
  32. package/content/.claude/skills/specialists/ms-agent-expert.md +143 -89
  33. package/content/.claude/skills/specialists/ui-ux-designer.md +744 -9
  34. package/content/.claude/skills/stacks/dotnet-blazor.md +244 -8
  35. package/content/.claude/skills/stacks/dotnet-nextjs.md +2 -2
  36. package/content/.morph/.morphversion +5 -0
  37. package/content/.morph/config/agents.json +101 -8
  38. package/content/.morph/config/azure-pricing.json +70 -0
  39. package/content/.morph/config/azure-pricing.schema.json +50 -0
  40. package/content/.morph/config/config.template.json +15 -3
  41. package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -0
  42. package/content/.morph/hooks/README.md +239 -0
  43. package/content/.morph/hooks/pre-commit-agents.sh +24 -0
  44. package/content/.morph/hooks/pre-commit-all.sh +48 -0
  45. package/content/.morph/hooks/pre-commit-costs.sh +91 -0
  46. package/content/.morph/hooks/pre-commit-specs.sh +49 -0
  47. package/content/.morph/hooks/pre-commit-tests.sh +60 -0
  48. package/content/.morph/project.md +5 -4
  49. package/content/.morph/schemas/agent.schema.json +296 -0
  50. package/content/.morph/standards/agent-framework-setup.md +453 -0
  51. package/content/.morph/standards/architecture.md +142 -7
  52. package/content/.morph/standards/azure.md +218 -23
  53. package/content/.morph/standards/coding.md +47 -12
  54. package/content/.morph/standards/dotnet10-migration.md +494 -0
  55. package/content/.morph/standards/fluent-ui-setup.md +590 -0
  56. package/content/.morph/standards/migration-guide.md +514 -0
  57. package/content/.morph/standards/passkeys-auth.md +423 -0
  58. package/content/.morph/standards/vector-search-rag.md +536 -0
  59. package/content/.morph/state.json +18 -0
  60. package/content/.morph/templates/FluentDesignTheme.cs +149 -0
  61. package/content/.morph/templates/MudTheme.cs +281 -0
  62. package/content/.morph/templates/contracts.cs +55 -55
  63. package/content/.morph/templates/decisions.md +4 -4
  64. package/content/.morph/templates/design-system.css +226 -0
  65. package/content/.morph/templates/infra/.dockerignore.example +89 -0
  66. package/content/.morph/templates/infra/Dockerfile.example +82 -0
  67. package/content/.morph/templates/infra/README.md +286 -0
  68. package/content/.morph/templates/infra/app-service.bicep +164 -0
  69. package/content/.morph/templates/infra/deploy.ps1 +229 -0
  70. package/content/.morph/templates/infra/deploy.sh +208 -0
  71. package/content/.morph/templates/infra/main.bicep +41 -7
  72. package/content/.morph/templates/infra/parameters.dev.json +6 -0
  73. package/content/.morph/templates/infra/parameters.prod.json +6 -0
  74. package/content/.morph/templates/infra/parameters.staging.json +29 -0
  75. package/content/.morph/templates/proposal.md +3 -3
  76. package/content/.morph/templates/recap.md +3 -3
  77. package/content/.morph/templates/spec.md +9 -8
  78. package/content/.morph/templates/sprint-status.yaml +68 -0
  79. package/content/.morph/templates/state.template.json +222 -0
  80. package/content/.morph/templates/story.md +143 -0
  81. package/content/.morph/templates/tasks.md +1 -1
  82. package/content/.morph/templates/ui-components.md +276 -0
  83. package/content/.morph/templates/ui-design-system.md +286 -0
  84. package/content/.morph/templates/ui-flows.md +336 -0
  85. package/content/.morph/templates/ui-mockups.md +133 -0
  86. package/content/.morph/test-infra/example.bicep +59 -0
  87. package/content/CLAUDE.md +124 -0
  88. package/content/README.md +79 -0
  89. package/detectors/config-detector.js +223 -0
  90. package/detectors/conversation-analyzer.js +163 -0
  91. package/detectors/index.js +84 -0
  92. package/detectors/standards-generator.js +275 -0
  93. package/detectors/structure-detector.js +221 -0
  94. package/docs/README.md +149 -0
  95. package/docs/api/cost-calculator.js.html +513 -0
  96. package/docs/api/design-system-generator.js.html +382 -0
  97. package/docs/api/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  98. package/docs/api/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  99. package/docs/api/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  100. package/docs/api/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  101. package/docs/api/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  102. package/docs/api/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  103. package/docs/api/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  104. package/docs/api/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  105. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  106. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  107. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  108. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  109. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  110. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  111. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  112. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  113. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  114. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  115. package/docs/api/global.html +5263 -0
  116. package/docs/api/index.html +96 -0
  117. package/docs/api/scripts/collapse.js +39 -0
  118. package/docs/api/scripts/commonNav.js +28 -0
  119. package/docs/api/scripts/linenumber.js +25 -0
  120. package/docs/api/scripts/nav.js +12 -0
  121. package/docs/api/scripts/polyfill.js +4 -0
  122. package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
  123. package/docs/api/scripts/prettify/lang-css.js +2 -0
  124. package/docs/api/scripts/prettify/prettify.js +28 -0
  125. package/docs/api/scripts/search.js +99 -0
  126. package/docs/api/state-manager.js.html +423 -0
  127. package/docs/api/styles/jsdoc.css +776 -0
  128. package/docs/api/styles/prettify.css +80 -0
  129. package/docs/examples.md +328 -0
  130. package/docs/getting-started.md +302 -0
  131. package/docs/installation.md +361 -0
  132. package/docs/templates.md +418 -0
  133. package/docs/validation-checklist.md +266 -0
  134. package/package.json +39 -12
  135. package/src/commands/cost.js +181 -0
  136. package/src/commands/create-story.js +283 -0
  137. package/src/commands/detect.js +104 -0
  138. package/src/commands/doctor.js +67 -0
  139. package/src/commands/generate.js +149 -0
  140. package/src/commands/init.js +69 -45
  141. package/src/commands/shard-spec.js +224 -0
  142. package/src/commands/sprint-status.js +250 -0
  143. package/src/commands/state.js +333 -0
  144. package/src/commands/sync.js +167 -0
  145. package/src/commands/update-pricing.js +206 -0
  146. package/src/commands/update.js +88 -13
  147. package/src/lib/complexity-analyzer.js +292 -0
  148. package/src/lib/cost-calculator.js +429 -0
  149. package/src/lib/design-system-generator.js +298 -0
  150. package/src/lib/state-manager.js +340 -0
  151. package/src/utils/file-copier.js +59 -0
  152. package/src/utils/version-checker.js +175 -0
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Standards Generator - Generates inferred-standards.md from detection results
3
+ */
4
+
5
+ /**
6
+ * Generate inferred standards
7
+ * @param {Object} detectionResults - Results from all detectors
8
+ * @returns {Promise<Object>} Generated standards
9
+ */
10
+ export async function generateStandards(detectionResults) {
11
+ const { structure, config, conversation } = detectionResults;
12
+
13
+ const standards = {
14
+ markdown: generateMarkdown(structure, config, conversation),
15
+ recommendations: generateRecommendations(structure, config, conversation),
16
+ gaps: identifyGaps(structure, config)
17
+ };
18
+
19
+ return standards;
20
+ }
21
+
22
+ /**
23
+ * Generate markdown content for inferred-standards.md
24
+ */
25
+ function generateMarkdown(structure, config, conversation) {
26
+ const sections = [];
27
+
28
+ // Header
29
+ sections.push(`# Inferred Standards (Auto-generated)`);
30
+ sections.push(``);
31
+ sections.push(`> ⚠️ This file is auto-generated by MORPH-SPEC detection system.`);
32
+ sections.push(`> Manual edits will be overwritten. Create custom standards in \`overrides.md\`.`);
33
+ sections.push(``);
34
+ sections.push(`**Generated:** ${new Date().toISOString()}`);
35
+ sections.push(``);
36
+ sections.push(`---`);
37
+ sections.push(``);
38
+
39
+ // Stack Summary
40
+ sections.push(`## 🎯 Project Stack`);
41
+ sections.push(``);
42
+ sections.push(`- **Type**: ${structure?.stack || 'unknown'}`);
43
+ sections.push(`- **Language**: ${config?.language || 'unknown'}`);
44
+ sections.push(`- **Version**: ${config?.version || 'unknown'}`);
45
+ sections.push(`- **Architecture**: ${structure?.architecture || 'unknown'}`);
46
+ if (structure?.uiLibrary) {
47
+ sections.push(`- **UI Library**: ${structure.uiLibrary}`);
48
+ }
49
+ sections.push(``);
50
+
51
+ // Technologies
52
+ if (config?.technologies?.length > 0) {
53
+ sections.push(`## 🛠️ Technologies Detected`);
54
+ sections.push(``);
55
+ config.technologies.forEach(tech => {
56
+ sections.push(`- ${tech}`);
57
+ });
58
+ sections.push(``);
59
+ }
60
+
61
+ // Patterns
62
+ if (structure?.patterns?.length > 0) {
63
+ sections.push(`## 📐 Patterns in Use`);
64
+ sections.push(``);
65
+ structure.patterns.forEach(pattern => {
66
+ sections.push(`- ${pattern}`);
67
+ });
68
+ sections.push(``);
69
+ }
70
+
71
+ // Coding Standards (inferred)
72
+ sections.push(`## 💻 Inferred Coding Standards`);
73
+ sections.push(``);
74
+ sections.push(generateCodingStandards(structure, config));
75
+ sections.push(``);
76
+
77
+ // Architecture Patterns
78
+ if (structure?.architecture !== 'unknown') {
79
+ sections.push(`## 🏗️ Architecture Pattern`);
80
+ sections.push(``);
81
+ sections.push(generateArchitectureSection(structure));
82
+ sections.push(``);
83
+ }
84
+
85
+ // Dependencies
86
+ if (config?.dependencies?.length > 0) {
87
+ sections.push(`## 📦 Key Dependencies`);
88
+ sections.push(``);
89
+ const importantDeps = filterImportantDependencies(config.dependencies);
90
+ importantDeps.slice(0, 10).forEach(dep => {
91
+ sections.push(`- ${dep}`);
92
+ });
93
+ if (config.dependencies.length > 10) {
94
+ sections.push(`- ... and ${config.dependencies.length - 10} more`);
95
+ }
96
+ sections.push(``);
97
+ }
98
+
99
+ // User Preferences (from conversation)
100
+ if (conversation?.preferences && Object.keys(conversation.preferences).some(k => conversation.preferences[k])) {
101
+ sections.push(`## 🎨 User Preferences (from past decisions)`);
102
+ sections.push(``);
103
+ Object.entries(conversation.preferences).forEach(([key, value]) => {
104
+ if (value) {
105
+ sections.push(`- **${formatKey(key)}**: ${value}`);
106
+ }
107
+ });
108
+ sections.push(``);
109
+ }
110
+
111
+ return sections.join('\n');
112
+ }
113
+
114
+ /**
115
+ * Generate coding standards section
116
+ */
117
+ function generateCodingStandards(structure, config) {
118
+ if (config?.language === 'csharp') {
119
+ return `### C# / .NET Conventions
120
+
121
+ Based on detected patterns in your codebase:
122
+
123
+ - **Naming**: PascalCase for classes, camelCase for variables
124
+ - **Async**: Methods with \`Async\` suffix
125
+ - **DI**: Constructor injection (${structure.patterns.includes('Dependency Injection') ? '✅ detected' : '⚠️ not detected'})
126
+ - **Tests**: ${structure.patterns.includes('Unit Tests') ? '✅ Present' : '⚠️ Not detected'}
127
+
128
+ **Recommendation**: Refer to \`.morph/standards/coding.md\` for complete .NET standards.`;
129
+ }
130
+
131
+ if (config?.language === 'javascript') {
132
+ return `### JavaScript / TypeScript Conventions
133
+
134
+ Based on detected patterns in your codebase:
135
+
136
+ - **Package Manager**: ${config.packageManager}
137
+ - **Framework**: ${config.technologies.join(', ')}
138
+
139
+ **Recommendation**: Refer to framework standards for JavaScript best practices.`;
140
+ }
141
+
142
+ return 'No specific coding standards inferred. Check framework standards for guidance.';
143
+ }
144
+
145
+ /**
146
+ * Generate architecture section
147
+ */
148
+ function generateArchitectureSection(structure) {
149
+ const { architecture } = structure;
150
+
151
+ const descriptions = {
152
+ 'clean-architecture': `### Clean Architecture
153
+
154
+ Your project follows Clean Architecture pattern:
155
+
156
+ - ✅ **Domain** layer detected (core business logic)
157
+ - ✅ **Application** layer detected (use cases)
158
+ - ✅ **Infrastructure** layer detected (implementations)
159
+
160
+ **Key principles**:
161
+ - Domain has no dependencies
162
+ - Application depends on Domain
163
+ - Infrastructure implements Application interfaces`,
164
+
165
+ 'cqrs': `### CQRS Pattern
166
+
167
+ Your project uses Command Query Responsibility Segregation:
168
+
169
+ - ✅ **Commands** detected (write operations)
170
+ - ✅ **Queries** detected (read operations)
171
+
172
+ **Key principles**:
173
+ - Separate read and write models
174
+ - Commands return void or Task
175
+ - Queries return data`,
176
+
177
+ 'mvc': `### MVC Pattern
178
+
179
+ Your project uses Model-View-Controller pattern:
180
+
181
+ - ✅ **Controllers** detected
182
+ - ✅ **Models** detected
183
+ - ✅ **Views** detected`
184
+ };
185
+
186
+ return descriptions[architecture] || `Architecture: ${architecture}`;
187
+ }
188
+
189
+ /**
190
+ * Generate recommendations
191
+ */
192
+ function generateRecommendations(structure, config, conversation) {
193
+ const recommendations = [];
194
+
195
+ // Recommend based on stack
196
+ if (structure?.stack === 'blazor') {
197
+ if (!structure.uiLibrary) {
198
+ recommendations.push('Consider adding Fluent UI Blazor or MudBlazor for consistent UI components');
199
+ }
200
+
201
+ if (!structure.patterns.includes('AI Agents') && config?.technologies?.includes('Microsoft Agent Framework')) {
202
+ recommendations.push('Setup detected Agent Framework but no agents found - check .morph/standards/agent-framework-setup.md');
203
+ }
204
+ }
205
+
206
+ // Recommend tests
207
+ if (!structure?.patterns?.includes('Unit Tests')) {
208
+ recommendations.push('No unit tests detected - consider adding test project');
209
+ }
210
+
211
+ // Recommend DI
212
+ if (!structure?.patterns?.includes('Dependency Injection')) {
213
+ recommendations.push('Consider implementing Dependency Injection pattern');
214
+ }
215
+
216
+ // Architecture recommendations
217
+ if (structure?.architecture === 'unknown' && structure?.folders?.hasServices) {
218
+ recommendations.push('Service layer detected but no clear architecture - consider Clean Architecture or CQRS');
219
+ }
220
+
221
+ return recommendations;
222
+ }
223
+
224
+ /**
225
+ * Identify gaps between framework and project
226
+ */
227
+ function identifyGaps(structure, config) {
228
+ const gaps = [];
229
+
230
+ // Check for missing patterns
231
+ const expectedPatterns = {
232
+ blazor: ['Service Layer', 'Repository Pattern', 'Dependency Injection'],
233
+ nextjs: ['API Routes', 'Components'],
234
+ };
235
+
236
+ const expected = expectedPatterns[structure?.stack];
237
+ if (expected) {
238
+ expected.forEach(pattern => {
239
+ if (!structure?.patterns?.includes(pattern)) {
240
+ gaps.push(`Missing: ${pattern}`);
241
+ }
242
+ });
243
+ }
244
+
245
+ return gaps;
246
+ }
247
+
248
+ /**
249
+ * Filter important dependencies
250
+ */
251
+ function filterImportantDependencies(deps) {
252
+ const important = deps.filter(dep => {
253
+ // Framework packages
254
+ if (dep.includes('Microsoft.') || dep.includes('System.')) return true;
255
+ // UI libraries
256
+ if (dep.includes('Blazor') || dep.includes('FluentUI') || dep.includes('Mud')) return true;
257
+ // Common tools
258
+ if (dep.includes('Hangfire') || dep.includes('Serilog') || dep.includes('AutoMapper')) return true;
259
+ // AI/ML
260
+ if (dep.includes('Agents') || dep.includes('AI') || dep.includes('OpenAI')) return true;
261
+ return false;
262
+ });
263
+
264
+ return important.length > 0 ? important : deps;
265
+ }
266
+
267
+ /**
268
+ * Format key for display
269
+ */
270
+ function formatKey(key) {
271
+ return key
272
+ .replace(/([A-Z])/g, ' $1')
273
+ .replace(/^./, str => str.toUpperCase())
274
+ .trim();
275
+ }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Structure Detector - Analyzes folder structure to infer stack and architecture
3
+ */
4
+
5
+ import { glob } from 'glob';
6
+ import { join } from 'path';
7
+ import { existsSync } from 'fs';
8
+
9
+ /**
10
+ * Detect project structure
11
+ * @param {string} projectPath - Project root path
12
+ * @returns {Promise<Object>} Structure detection results
13
+ */
14
+ export async function detectStructure(projectPath) {
15
+ const result = {
16
+ stack: 'unknown',
17
+ architecture: 'unknown',
18
+ uiLibrary: null,
19
+ patterns: [],
20
+ folders: {
21
+ hasPages: false,
22
+ hasComponents: false,
23
+ hasServices: false,
24
+ hasRepositories: false,
25
+ hasAgents: false
26
+ }
27
+ };
28
+
29
+ // Detect stack
30
+ result.stack = await detectStack(projectPath);
31
+
32
+ // Detect architecture pattern
33
+ result.architecture = await detectArchitecture(projectPath);
34
+
35
+ // Detect UI library
36
+ if (result.stack === 'blazor') {
37
+ result.uiLibrary = await detectUILibrary(projectPath);
38
+ }
39
+
40
+ // Detect patterns
41
+ result.patterns = await detectPatterns(projectPath);
42
+
43
+ // Analyze folders
44
+ result.folders = await analyzeFolders(projectPath);
45
+
46
+ return result;
47
+ }
48
+
49
+ /**
50
+ * Detect stack type
51
+ */
52
+ async function detectStack(projectPath) {
53
+ const patterns = {
54
+ blazor: [
55
+ '**/*.razor',
56
+ '**/Pages/**/*.razor',
57
+ '**/Components/**/*.razor'
58
+ ],
59
+ nextjs: [
60
+ 'pages/**/*.tsx',
61
+ 'app/**/*.tsx',
62
+ 'next.config.js',
63
+ 'next.config.mjs'
64
+ ],
65
+ shopify: [
66
+ '**/*.liquid',
67
+ 'sections/**/*.liquid',
68
+ 'templates/**/*.liquid'
69
+ ],
70
+ dotnet: [
71
+ '**/*.csproj',
72
+ '**/Program.cs'
73
+ ]
74
+ };
75
+
76
+ for (const [stack, globs] of Object.entries(patterns)) {
77
+ for (const pattern of globs) {
78
+ const files = await glob(pattern, { cwd: projectPath, nodir: true });
79
+ if (files.length > 0) {
80
+ return stack;
81
+ }
82
+ }
83
+ }
84
+
85
+ return 'unknown';
86
+ }
87
+
88
+ /**
89
+ * Detect architecture pattern
90
+ */
91
+ async function detectArchitecture(projectPath) {
92
+ const checks = [
93
+ {
94
+ pattern: 'clean-architecture',
95
+ indicators: [
96
+ existsSync(join(projectPath, 'src', 'Application')),
97
+ existsSync(join(projectPath, 'src', 'Domain')),
98
+ existsSync(join(projectPath, 'src', 'Infrastructure'))
99
+ ]
100
+ },
101
+ {
102
+ pattern: 'cqrs',
103
+ indicators: [
104
+ await glob('**/Commands/**/*.cs', { cwd: projectPath }).then(f => f.length > 0),
105
+ await glob('**/Queries/**/*.cs', { cwd: projectPath }).then(f => f.length > 0)
106
+ ]
107
+ },
108
+ {
109
+ pattern: 'mvc',
110
+ indicators: [
111
+ existsSync(join(projectPath, 'Controllers')),
112
+ existsSync(join(projectPath, 'Models')),
113
+ existsSync(join(projectPath, 'Views'))
114
+ ]
115
+ }
116
+ ];
117
+
118
+ for (const { pattern, indicators } of checks) {
119
+ if (indicators.every(Boolean)) {
120
+ return pattern;
121
+ }
122
+ }
123
+
124
+ return 'unknown';
125
+ }
126
+
127
+ /**
128
+ * Detect UI library (Blazor projects)
129
+ */
130
+ async function detectUILibrary(projectPath) {
131
+ const csprojFiles = await glob('**/*.csproj', { cwd: projectPath });
132
+
133
+ for (const csprojFile of csprojFiles) {
134
+ const content = await import('fs').then(fs =>
135
+ fs.promises.readFile(join(projectPath, csprojFile), 'utf8')
136
+ );
137
+
138
+ if (content.includes('FluentUI.Blazor') || content.includes('Microsoft.FluentUI.AspNetCore.Components')) {
139
+ return 'fluent-ui';
140
+ }
141
+
142
+ if (content.includes('MudBlazor')) {
143
+ return 'mudblazor';
144
+ }
145
+ }
146
+
147
+ return null;
148
+ }
149
+
150
+ /**
151
+ * Detect common patterns
152
+ */
153
+ async function detectPatterns(projectPath) {
154
+ const patterns = [];
155
+
156
+ // Check for specific patterns
157
+ const checks = [
158
+ {
159
+ name: 'Repository Pattern',
160
+ glob: '**/*Repository.cs'
161
+ },
162
+ {
163
+ name: 'Service Layer',
164
+ glob: '**/*Service.cs'
165
+ },
166
+ {
167
+ name: 'DTOs',
168
+ glob: '**/*Dto.cs'
169
+ },
170
+ {
171
+ name: 'Entity Framework',
172
+ glob: '**/Migrations/**/*.cs'
173
+ },
174
+ {
175
+ name: 'Dependency Injection',
176
+ glob: '**/DependencyInjection.cs'
177
+ },
178
+ {
179
+ name: 'Hangfire Jobs',
180
+ glob: '**/*Job.cs'
181
+ },
182
+ {
183
+ name: 'AI Agents',
184
+ glob: '**/*Agent.cs'
185
+ },
186
+ {
187
+ name: 'Unit Tests',
188
+ glob: '**/*.Tests/**/*.cs'
189
+ }
190
+ ];
191
+
192
+ for (const { name, glob: pattern } of checks) {
193
+ const files = await glob(pattern, { cwd: projectPath, nodir: true });
194
+ if (files.length > 0) {
195
+ patterns.push(name);
196
+ }
197
+ }
198
+
199
+ return patterns;
200
+ }
201
+
202
+ /**
203
+ * Analyze folder structure
204
+ */
205
+ async function analyzeFolders(projectPath) {
206
+ const folders = {
207
+ hasPages: false,
208
+ hasComponents: false,
209
+ hasServices: false,
210
+ hasRepositories: false,
211
+ hasAgents: false
212
+ };
213
+
214
+ folders.hasPages = await glob('**/Pages/**/*', { cwd: projectPath }).then(f => f.length > 0);
215
+ folders.hasComponents = await glob('**/Components/**/*', { cwd: projectPath }).then(f => f.length > 0);
216
+ folders.hasServices = await glob('**/Services/**/*', { cwd: projectPath }).then(f => f.length > 0);
217
+ folders.hasRepositories = await glob('**/Repositories/**/*', { cwd: projectPath }).then(f => f.length > 0);
218
+ folders.hasAgents = await glob('**/Agents/**/*', { cwd: projectPath }).then(f => f.length > 0);
219
+
220
+ return folders;
221
+ }
package/docs/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # MORPH-SPEC API Documentation
2
+
3
+ This directory contains the API documentation for MORPH-SPEC Framework libraries.
4
+
5
+ ## Available Documentation
6
+
7
+ ### API Reference (`/api`)
8
+
9
+ Comprehensive API documentation generated from JSDoc comments in the source code.
10
+
11
+ **Libraries Documented:**
12
+ - **state-manager** - Feature state management, agents, checkpoints, outputs tracking
13
+ - **cost-calculator** - Azure infrastructure cost calculation from Bicep files
14
+ - **design-system-generator** - UI design system parsing and theme generation
15
+
16
+ **View Documentation:**
17
+ - Open `api/index.html` in your browser
18
+ - Or run `npm run docs:serve` to start a local server at http://localhost:8080
19
+
20
+ ## Running Tests
21
+
22
+ ### Run Tests
23
+
24
+ ```bash
25
+ npm test
26
+ ```
27
+
28
+ Runs all 85 unit tests with 100% pass rate.
29
+
30
+ ### Run Tests with Coverage
31
+
32
+ ```bash
33
+ npm run test:coverage
34
+ ```
35
+
36
+ Generates coverage report (HTML + text + lcov). **Current coverage: 98.03%**
37
+
38
+ - **Statements:** 98.03%
39
+ - **Branches:** 88.74%
40
+ - **Functions:** 100%
41
+ - **Lines:** 98.03%
42
+
43
+ Coverage reports are generated in `coverage/` directory.
44
+
45
+ ### Coverage Summary Only
46
+
47
+ ```bash
48
+ npm run test:coverage:summary
49
+ ```
50
+
51
+ Shows text summary without generating HTML report.
52
+
53
+ ## Generating Documentation
54
+
55
+ ### Build API Docs
56
+
57
+ ```bash
58
+ npm run docs
59
+ ```
60
+
61
+ Generates HTML documentation from JSDoc comments in `src/lib/` to `docs/api/`.
62
+
63
+ ### Watch Mode
64
+
65
+ ```bash
66
+ npm run docs:watch
67
+ ```
68
+
69
+ Automatically regenerates documentation when source files change.
70
+
71
+ ### Serve Locally
72
+
73
+ ```bash
74
+ npm run docs:serve
75
+ ```
76
+
77
+ Starts a local HTTP server at http://localhost:8080 to view documentation.
78
+
79
+ ## Documentation Standards
80
+
81
+ ### JSDoc Format
82
+
83
+ All library functions in `src/lib/` use JSDoc comments with:
84
+
85
+ - **@param** - Parameter descriptions with types
86
+ - **@returns** - Return value description with type
87
+ - **@throws** - Exceptions that may be thrown
88
+ - **@example** - Usage examples (when applicable)
89
+
90
+ **Example:**
91
+
92
+ ```javascript
93
+ /**
94
+ * Calculate cost of a single resource
95
+ * @param {Object} resource - Resource object with type, sku, minReplicas
96
+ * @param {string} resource.type - Azure resource type
97
+ * @param {string} resource.sku - SKU name
98
+ * @param {number} [resource.minReplicas] - Minimum replicas (Container Apps)
99
+ * @returns {Object} Cost result with cost, warning, estimated, details
100
+ * @throws {Error} If resource type is invalid
101
+ */
102
+ export function calculateResourceCost(resource) {
103
+ // Implementation
104
+ }
105
+ ```
106
+
107
+ ### Module-Level Documentation
108
+
109
+ Each library file starts with a block comment describing:
110
+
111
+ - Purpose and responsibilities
112
+ - Usage context (CLI commands, internal automation)
113
+ - Key features
114
+
115
+ **Example:**
116
+
117
+ ```javascript
118
+ /**
119
+ * MORPH-SPEC State Manager Library
120
+ *
121
+ * Manages state.json for tracking features, progress, agents, and checkpoints.
122
+ * Used both by CLI commands and internal automation.
123
+ */
124
+ ```
125
+
126
+ ## Updating Documentation
127
+
128
+ 1. **Update JSDoc comments** in source files (`src/lib/*.js`)
129
+ 2. **Regenerate docs:** `npm run docs`
130
+ 3. **Review:** Open `docs/api/index.html`
131
+ 4. **Commit:** Include updated `docs/api/` in your commit
132
+
133
+ ## Template
134
+
135
+ Documentation is generated using the [docdash](https://github.com/clenemt/docdash) template for JSDoc, configured in `jsdoc.json`.
136
+
137
+ **Features:**
138
+ - Clean, modern design
139
+ - Full-text search
140
+ - Responsive layout
141
+ - Syntax highlighting
142
+ - Type definitions
143
+ - Source code links
144
+
145
+ ## Links
146
+
147
+ - **GitHub:** https://github.com/lucasPolymorphism/morph-spec-framework
148
+ - **npm:** https://www.npmjs.com/package/@polymorphism-tech/morph-spec
149
+ - **Website:** https://polymorphism.com.br/morph-spec