@polymorphism-tech/morph-spec 2.3.0 → 3.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 (166) hide show
  1. package/CLAUDE.md +446 -1730
  2. package/README.md +515 -516
  3. package/bin/morph-spec.js +366 -294
  4. package/bin/task-manager.js +429 -368
  5. package/bin/validate.js +369 -268
  6. package/content/.claude/commands/morph-apply.md +221 -158
  7. package/content/.claude/commands/morph-deploy.md +529 -0
  8. package/content/.claude/commands/morph-preflight.md +227 -0
  9. package/content/.claude/commands/morph-proposal.md +122 -101
  10. package/content/.claude/commands/morph-status.md +86 -86
  11. package/content/.claude/commands/morph-troubleshoot.md +122 -0
  12. package/content/.claude/skills/infra/azure-deploy-specialist.md +699 -0
  13. package/content/.claude/skills/level-0-meta/README.md +7 -0
  14. package/content/.claude/skills/level-0-meta/code-review.md +226 -0
  15. package/content/.claude/skills/level-0-meta/morph-checklist.md +117 -0
  16. package/content/.claude/skills/level-0-meta/simulation-checklist.md +77 -0
  17. package/content/.claude/skills/level-1-workflows/README.md +7 -0
  18. package/content/.claude/skills/level-1-workflows/morph-replicate.md +213 -0
  19. package/content/.claude/{commands/morph-clarify.md → skills/level-1-workflows/phase-clarify.md} +131 -184
  20. package/content/.claude/{commands/morph-design.md → skills/level-1-workflows/phase-design.md} +213 -275
  21. package/content/.claude/skills/level-1-workflows/phase-setup.md +106 -0
  22. package/content/.claude/skills/level-1-workflows/phase-tasks.md +164 -0
  23. package/content/.claude/{commands/morph-uiux.md → skills/level-1-workflows/phase-uiux.md} +169 -211
  24. package/content/.claude/skills/level-2-domains/README.md +14 -0
  25. package/content/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +192 -0
  26. package/content/.claude/skills/{specialists → level-2-domains/architecture}/po-pm-advisor.md +197 -197
  27. package/content/.claude/skills/level-2-domains/architecture/standards-architect.md +156 -0
  28. package/content/.claude/skills/level-2-domains/backend/dotnet-senior.md +287 -0
  29. package/content/.claude/skills/level-2-domains/backend/ef-modeler.md +113 -0
  30. package/content/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +126 -0
  31. package/content/.claude/skills/level-2-domains/backend/ms-agent-expert.md +109 -0
  32. package/content/.claude/skills/level-2-domains/frontend/blazor-builder.md +210 -0
  33. package/content/.claude/skills/level-2-domains/frontend/nextjs-expert.md +154 -0
  34. package/content/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +191 -0
  35. package/content/.claude/skills/{specialists → level-2-domains/infrastructure}/azure-architect.md +142 -142
  36. package/content/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +126 -0
  37. package/content/.claude/skills/level-2-domains/infrastructure/container-specialist.md +131 -0
  38. package/content/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +119 -0
  39. package/content/.claude/skills/level-2-domains/integrations/asaas-financial.md +130 -0
  40. package/content/.claude/skills/level-2-domains/integrations/azure-identity.md +142 -0
  41. package/content/.claude/skills/level-2-domains/integrations/clerk-auth.md +108 -0
  42. package/content/.claude/skills/level-2-domains/integrations/resend-email.md +119 -0
  43. package/content/.claude/skills/level-2-domains/quality/code-analyzer.md +235 -0
  44. package/content/.claude/skills/level-2-domains/quality/testing-specialist.md +126 -0
  45. package/content/.claude/skills/level-3-technologies/README.md +7 -0
  46. package/content/.claude/skills/level-4-patterns/README.md +7 -0
  47. package/content/.claude/skills/specialists/prompt-engineer.md +189 -0
  48. package/content/.claude/skills/specialists/seo-growth-hacker.md +320 -0
  49. package/content/.morph/config/agents.json +762 -242
  50. package/content/.morph/config/config.template.json +122 -108
  51. package/content/.morph/docs/workflows/design-impl.md +37 -0
  52. package/content/.morph/docs/workflows/enforcement-pipeline.md +668 -0
  53. package/content/.morph/docs/workflows/fast-track.md +29 -0
  54. package/content/.morph/docs/workflows/full-morph.md +76 -0
  55. package/content/.morph/docs/workflows/standard.md +44 -0
  56. package/content/.morph/docs/workflows/ui-refresh.md +39 -0
  57. package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
  58. package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
  59. package/content/.morph/examples/scheduled-reports/spec.md +267 -0
  60. package/content/.morph/hooks/README.md +348 -239
  61. package/content/.morph/hooks/pre-commit-agents.sh +24 -24
  62. package/content/.morph/hooks/task-completed.js +73 -0
  63. package/content/.morph/hooks/teammate-idle.js +68 -0
  64. package/content/.morph/schemas/tasks.schema.json +220 -0
  65. package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
  66. package/content/.morph/standards/agent-framework-production.md +410 -0
  67. package/content/.morph/standards/agent-framework-setup.md +413 -453
  68. package/content/.morph/standards/agent-framework-workflows.md +349 -0
  69. package/content/.morph/standards/agent-teams-workflow.md +474 -0
  70. package/content/.morph/standards/architecture.md +325 -325
  71. package/content/.morph/standards/azure.md +605 -379
  72. package/content/.morph/standards/dotnet10-migration.md +520 -494
  73. package/content/.morph/templates/CONTEXT-FEATURE.md +276 -0
  74. package/content/.morph/templates/CONTEXT.md +170 -0
  75. package/content/.morph/templates/agent.cs +163 -172
  76. package/content/.morph/templates/clarify-questions.md +159 -0
  77. package/content/.morph/templates/contracts/Commands.cs +74 -0
  78. package/content/.morph/templates/contracts/Entities.cs +25 -0
  79. package/content/.morph/templates/contracts/Queries.cs +74 -0
  80. package/content/.morph/templates/contracts/README.md +74 -0
  81. package/content/.morph/templates/decisions.md +123 -106
  82. package/content/.morph/templates/infra/azure-pipelines-deploy.yml +480 -0
  83. package/content/.morph/templates/infra/deploy-checklist.md +426 -0
  84. package/content/.morph/templates/proposal.md +141 -155
  85. package/content/.morph/templates/recap.md +94 -105
  86. package/content/.morph/templates/simulation.md +353 -0
  87. package/content/.morph/templates/spec.md +149 -148
  88. package/content/.morph/templates/state.template.json +222 -222
  89. package/content/.morph/templates/tasks.md +257 -235
  90. package/content/.morph/templates/ui-components.md +362 -276
  91. package/content/CLAUDE.md +150 -442
  92. package/detectors/structure-detector.js +245 -250
  93. package/docs/README.md +144 -149
  94. package/docs/getting-started.md +301 -302
  95. package/docs/installation.md +361 -361
  96. package/docs/validation-checklist.md +265 -266
  97. package/package.json +80 -80
  98. package/src/commands/advance-phase.js +266 -0
  99. package/src/commands/analyze-blazor-concurrency.js +193 -0
  100. package/src/commands/deploy.js +780 -0
  101. package/src/commands/detect-agents.js +167 -0
  102. package/src/commands/doctor.js +356 -280
  103. package/src/commands/generate-context.js +40 -0
  104. package/src/commands/init.js +258 -245
  105. package/src/commands/lint-fluent.js +352 -0
  106. package/src/commands/rollback-phase.js +185 -0
  107. package/src/commands/session-summary.js +291 -0
  108. package/src/commands/task.js +78 -75
  109. package/src/commands/troubleshoot.js +222 -0
  110. package/src/commands/update.js +192 -159
  111. package/src/commands/validate-blazor-state.js +210 -0
  112. package/src/commands/validate-blazor.js +156 -0
  113. package/src/commands/validate-css.js +84 -0
  114. package/src/commands/validate-phase.js +221 -0
  115. package/src/lib/blazor-concurrency-analyzer.js +288 -0
  116. package/src/lib/blazor-state-validator.js +291 -0
  117. package/src/lib/blazor-validator.js +374 -0
  118. package/src/lib/complexity-analyzer.js +441 -292
  119. package/src/lib/context-generator.js +513 -0
  120. package/src/lib/continuous-validator.js +421 -440
  121. package/src/lib/css-validator.js +352 -0
  122. package/src/lib/decision-constraint-loader.js +109 -0
  123. package/src/lib/design-system-detector.js +187 -0
  124. package/src/lib/design-system-scaffolder.js +299 -0
  125. package/src/lib/hook-executor.js +256 -0
  126. package/src/lib/recap-generator.js +205 -0
  127. package/src/lib/spec-validator.js +258 -0
  128. package/src/lib/standards-context-injector.js +287 -0
  129. package/src/lib/state-manager.js +397 -340
  130. package/src/lib/team-orchestrator.js +322 -0
  131. package/src/lib/troubleshoot-grep.js +194 -0
  132. package/src/lib/troubleshoot-index.js +144 -0
  133. package/src/lib/validation-runner.js +283 -0
  134. package/src/lib/validators/contract-compliance-validator.js +273 -0
  135. package/src/lib/validators/design-system-validator.js +231 -0
  136. package/src/utils/file-copier.js +187 -139
  137. package/content/.claude/commands/morph-costs.md +0 -206
  138. package/content/.claude/commands/morph-setup.md +0 -100
  139. package/content/.claude/commands/morph-tasks.md +0 -319
  140. package/content/.claude/skills/infra/bicep-architect.md +0 -419
  141. package/content/.claude/skills/infra/container-specialist.md +0 -437
  142. package/content/.claude/skills/infra/devops-engineer.md +0 -405
  143. package/content/.claude/skills/integrations/asaas-financial.md +0 -333
  144. package/content/.claude/skills/integrations/azure-identity.md +0 -309
  145. package/content/.claude/skills/integrations/clerk-auth.md +0 -290
  146. package/content/.claude/skills/specialists/ai-system-architect.md +0 -604
  147. package/content/.claude/skills/specialists/cost-guardian.md +0 -110
  148. package/content/.claude/skills/specialists/ef-modeler.md +0 -211
  149. package/content/.claude/skills/specialists/hangfire-orchestrator.md +0 -255
  150. package/content/.claude/skills/specialists/ms-agent-expert.md +0 -263
  151. package/content/.claude/skills/specialists/standards-architect.md +0 -78
  152. package/content/.claude/skills/specialists/ui-ux-designer.md +0 -1100
  153. package/content/.claude/skills/stacks/dotnet-blazor.md +0 -606
  154. package/content/.claude/skills/stacks/dotnet-nextjs.md +0 -402
  155. package/content/.claude/skills/stacks/shopify.md +0 -445
  156. package/content/.morph/config/azure-pricing.json +0 -70
  157. package/content/.morph/config/azure-pricing.schema.json +0 -50
  158. package/content/.morph/hooks/pre-commit-costs.sh +0 -91
  159. package/docs/api/cost-calculator.js.html +0 -513
  160. package/docs/api/design-system-generator.js.html +0 -382
  161. package/docs/api/global.html +0 -5263
  162. package/docs/api/index.html +0 -96
  163. package/docs/api/state-manager.js.html +0 -423
  164. package/src/commands/cost.js +0 -181
  165. package/src/commands/update-pricing.js +0 -206
  166. package/src/lib/cost-calculator.js +0 -429
package/package.json CHANGED
@@ -1,80 +1,80 @@
1
- {
2
- "name": "@polymorphism-tech/morph-spec",
3
- "version": "2.3.0",
4
- "description": "MORPH-SPEC v2.0: AI-First development framework with .NET 10, Microsoft Agent Framework, and Fluent UI Blazor",
5
- "keywords": [
6
- "claude-code",
7
- "claude",
8
- "ai-coding",
9
- "ai-first",
10
- "spec-driven",
11
- "dotnet",
12
- "dotnet10",
13
- "blazor",
14
- "agent-framework",
15
- "fluent-ui",
16
- "framework",
17
- "developer-tools",
18
- "morph",
19
- "polymorphism",
20
- "micro-saas"
21
- ],
22
- "main": "src/index.js",
23
- "bin": {
24
- "morph-spec": "bin/morph-spec.js"
25
- },
26
- "files": [
27
- "bin/",
28
- "src/",
29
- "scripts/",
30
- "detectors/",
31
- "content/",
32
- "docs/",
33
- "README.md",
34
- "LICENSE",
35
- "CLAUDE.md"
36
- ],
37
- "type": "module",
38
- "engines": {
39
- "node": ">=18.0.0"
40
- },
41
- "scripts": {
42
- "postinstall": "node scripts/postinstall.js",
43
- "start": "node bin/morph-spec.js",
44
- "test": "node --test",
45
- "test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov node --test",
46
- "test:coverage:summary": "c8 --reporter=text-summary node --test",
47
- "docs": "jsdoc -c jsdoc.json",
48
- "docs:watch": "jsdoc -c jsdoc.json --watch",
49
- "docs:serve": "npx http-server docs/api -p 8080 -o"
50
- },
51
- "dependencies": {
52
- "ajv": "^8.12.0",
53
- "ajv-formats": "^3.0.1",
54
- "chalk": "^5.3.0",
55
- "commander": "^12.0.0",
56
- "fs-extra": "^11.2.0",
57
- "glob": "^10.3.0",
58
- "ora": "^8.0.0",
59
- "yaml": "^2.3.4"
60
- },
61
- "repository": {
62
- "type": "git",
63
- "url": "git+https://github.com/lucasPolymorphism/morph-spec-framework.git"
64
- },
65
- "author": "Polymorphism Tech <contact@polymorphism.com.br>",
66
- "license": "SEE LICENSE IN LICENSE",
67
- "homepage": "https://polymorphism.com.br/morph-spec",
68
- "bugs": {
69
- "email": "support@polymorphism.com.br"
70
- },
71
- "private": false,
72
- "publishConfig": {
73
- "access": "public"
74
- },
75
- "devDependencies": {
76
- "c8": "^10.1.3",
77
- "docdash": "^2.0.2",
78
- "jsdoc": "^4.0.5"
79
- }
80
- }
1
+ {
2
+ "name": "@polymorphism-tech/morph-spec",
3
+ "version": "3.0.0",
4
+ "description": "MORPH-SPEC v2.0: AI-First development framework with .NET 10, Microsoft Agent Framework, and Fluent UI Blazor",
5
+ "keywords": [
6
+ "claude-code",
7
+ "claude",
8
+ "ai-coding",
9
+ "ai-first",
10
+ "spec-driven",
11
+ "dotnet",
12
+ "dotnet10",
13
+ "blazor",
14
+ "agent-framework",
15
+ "fluent-ui",
16
+ "framework",
17
+ "developer-tools",
18
+ "morph",
19
+ "polymorphism",
20
+ "micro-saas"
21
+ ],
22
+ "main": "src/index.js",
23
+ "bin": {
24
+ "morph-spec": "bin/morph-spec.js"
25
+ },
26
+ "files": [
27
+ "bin/",
28
+ "src/",
29
+ "scripts/",
30
+ "detectors/",
31
+ "content/",
32
+ "docs/",
33
+ "README.md",
34
+ "LICENSE",
35
+ "CLAUDE.md"
36
+ ],
37
+ "type": "module",
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
41
+ "scripts": {
42
+ "postinstall": "node scripts/postinstall.js",
43
+ "start": "node bin/morph-spec.js",
44
+ "test": "node --test",
45
+ "test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov node --test",
46
+ "test:coverage:summary": "c8 --reporter=text-summary node --test",
47
+ "docs": "jsdoc -c jsdoc.json",
48
+ "docs:watch": "jsdoc -c jsdoc.json --watch",
49
+ "docs:serve": "npx http-server docs/api -p 8080 -o"
50
+ },
51
+ "dependencies": {
52
+ "ajv": "^8.12.0",
53
+ "ajv-formats": "^3.0.1",
54
+ "chalk": "^5.3.0",
55
+ "commander": "^12.0.0",
56
+ "fs-extra": "^11.2.0",
57
+ "glob": "^10.3.0",
58
+ "ora": "^8.0.0",
59
+ "yaml": "^2.3.4"
60
+ },
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/lucasPolymorphism/morph-spec-framework.git"
64
+ },
65
+ "author": "Polymorphism Tech <contact@polymorphism.com.br>",
66
+ "license": "SEE LICENSE IN LICENSE",
67
+ "homepage": "https://polymorphism.com.br/morph-spec",
68
+ "bugs": {
69
+ "email": "support@polymorphism.com.br"
70
+ },
71
+ "private": false,
72
+ "publishConfig": {
73
+ "access": "public"
74
+ },
75
+ "devDependencies": {
76
+ "c8": "^10.1.3",
77
+ "docdash": "^2.0.2",
78
+ "jsdoc": "^4.0.5"
79
+ }
80
+ }
@@ -0,0 +1,266 @@
1
+ /**
2
+ * MORPH-SPEC Phase Advance Command
3
+ *
4
+ * Validates current phase → advances to next → shows requirements.
5
+ * Replaces the two-step `state set` + `validate-phase` dance.
6
+ *
7
+ * Usage:
8
+ * morph-spec phase advance <feature>
9
+ * morph-spec phase advance <feature> --skip-optional
10
+ */
11
+
12
+ import chalk from 'chalk';
13
+ import { loadState, saveState, getFeature } from '../lib/state-manager.js';
14
+ import { PHASES, validatePhase } from './validate-phase.js';
15
+ import { detectDesignSystem, hasUIAgentsActive } from '../lib/design-system-detector.js';
16
+ import { validateSpec } from '../lib/spec-validator.js';
17
+
18
+ // Phase order for advancing (skips optional phases unless active)
19
+ const PHASE_ORDER = ['proposal', 'setup', 'uiux', 'design', 'clarify', 'tasks', 'implement', 'sync'];
20
+
21
+ /**
22
+ * Get the next phase after the current one
23
+ */
24
+ function getNextPhase(currentPhase, feature, skipOptional) {
25
+ const currentIndex = PHASE_ORDER.indexOf(currentPhase);
26
+ if (currentIndex === -1 || currentIndex >= PHASE_ORDER.length - 1) {
27
+ return null;
28
+ }
29
+
30
+ for (let i = currentIndex + 1; i < PHASE_ORDER.length; i++) {
31
+ const candidate = PHASE_ORDER[i];
32
+ const phaseDef = PHASES[candidate];
33
+
34
+ // Skip optional phases if flag set or no relevant agents/outputs
35
+ if (phaseDef?.optional && skipOptional) {
36
+ continue;
37
+ }
38
+
39
+ // Skip uiux if no UI agents are active
40
+ if (candidate === 'uiux') {
41
+ const uiAgents = ['blazor-builder', 'uiux-designer'];
42
+ const hasUiAgent = feature.activeAgents?.some(a => uiAgents.includes(a));
43
+ if (!hasUiAgent && skipOptional !== false) {
44
+ continue;
45
+ }
46
+ }
47
+
48
+ // Skip sync for simple workflows
49
+ if (candidate === 'sync') {
50
+ const isSimple = feature.workflow === 'fast-track';
51
+ if (isSimple && skipOptional !== false) {
52
+ continue;
53
+ }
54
+ }
55
+
56
+ return candidate;
57
+ }
58
+
59
+ return null;
60
+ }
61
+
62
+ /**
63
+ * Main command handler
64
+ */
65
+ export async function advancePhaseCommand(feature, options = {}) {
66
+ console.log(chalk.cyan('\n╔════════════════════════════════════════════════╗'));
67
+ console.log(chalk.cyan('║ MORPH-SPEC PHASE ADVANCE ║'));
68
+ console.log(chalk.cyan('╚════════════════════════════════════════════════╝\n'));
69
+
70
+ // Get current feature state
71
+ const featureData = getFeature(feature);
72
+ if (!featureData) {
73
+ console.log(chalk.red(`✗ Feature not found: ${feature}`));
74
+ console.log(chalk.yellow(` Run: morph-spec state set ${feature} phase proposal`));
75
+ process.exit(1);
76
+ }
77
+
78
+ const currentPhase = featureData.phase;
79
+ const currentPhaseDef = PHASES[currentPhase];
80
+
81
+ console.log(chalk.gray('Feature:'), feature);
82
+ console.log(chalk.gray('Current Phase:'), currentPhaseDef?.name || currentPhase);
83
+ console.log(chalk.gray('Workflow:'), featureData.workflow || 'auto');
84
+
85
+ // Determine next phase
86
+ const nextPhase = getNextPhase(currentPhase, featureData, options.skipOptional);
87
+
88
+ if (!nextPhase) {
89
+ console.log(chalk.green('\n✓ Feature is at the final phase!'));
90
+ if (currentPhase === 'implement' || currentPhase === 'sync') {
91
+ console.log(chalk.green(' Consider running: morph-spec generate recap ' + feature));
92
+ }
93
+ return;
94
+ }
95
+
96
+ const nextPhaseDef = PHASES[nextPhase];
97
+ console.log(chalk.gray('Next Phase:'), nextPhaseDef.name);
98
+
99
+ // Validate that current phase requirements are met before advancing
100
+ const validation = validatePhase(feature, nextPhase);
101
+
102
+ if (!validation.valid) {
103
+ console.log(chalk.red('\n✗ Cannot advance — missing requirements:'));
104
+ validation.missingOutputs.forEach(output => {
105
+ console.log(chalk.red(` - ${output}`));
106
+ });
107
+ console.log(chalk.yellow(`\n Complete these before advancing to ${nextPhaseDef.name}`));
108
+ process.exit(1);
109
+ }
110
+
111
+ if (validation.stateWarning) {
112
+ console.log(chalk.yellow(`\n⚠️ ${validation.stateWarning}`));
113
+ }
114
+
115
+ // Gate: Validate spec.md and contracts.cs when advancing from design phase
116
+ if (currentPhase === 'design' && (nextPhase === 'clarify' || nextPhase === 'tasks')) {
117
+ const specValidation = await validateSpec('.', feature);
118
+
119
+ if (specValidation.errors > 0) {
120
+ console.log(chalk.red('\n✗ Spec validation failed — fix errors before advancing:'));
121
+ specValidation.issues.filter(i => i.level === 'error').forEach(issue => {
122
+ console.log(chalk.red(` - ${issue.message}`));
123
+ console.log(chalk.yellow(` → ${issue.solution}`));
124
+ });
125
+ console.log('');
126
+ process.exit(1);
127
+ }
128
+
129
+ if (specValidation.warnings > 0 && !options.skipWarnings) {
130
+ console.log(chalk.yellow('\n⚠️ Spec validation warnings:'));
131
+ specValidation.issues.filter(i => i.level === 'warning').forEach(issue => {
132
+ console.log(chalk.yellow(` - ${issue.message}`));
133
+ });
134
+ console.log(chalk.gray('\n (Use --skip-warnings to ignore warnings)\n'));
135
+ }
136
+ }
137
+
138
+ // Gate: Check design system when advancing to implement with UI agents
139
+ if (nextPhase === 'implement') {
140
+ const gateResult = designSystemGate(feature);
141
+
142
+ if (gateResult.blocked) {
143
+ console.log(chalk.red(`\n✗ ${gateResult.message}`));
144
+ console.log('');
145
+ gateResult.solution.forEach(line => {
146
+ if (line === '') {
147
+ console.log('');
148
+ } else {
149
+ console.log(chalk.yellow(` ${line}`));
150
+ }
151
+ });
152
+ console.log('');
153
+ process.exit(1);
154
+ }
155
+ }
156
+
157
+ // Advance the phase
158
+ const state = loadState();
159
+ state.features[feature].phase = nextPhase;
160
+ state.features[feature].updatedAt = new Date().toISOString();
161
+ saveState(state);
162
+
163
+ console.log(chalk.green(`\n✓ Advanced to ${nextPhaseDef.name}`));
164
+
165
+ // Show what's needed in the new phase
166
+ console.log(chalk.cyan('\n📋 Phase requirements:'));
167
+ console.log(chalk.gray(` ${nextPhaseDef.description}`));
168
+
169
+ if (nextPhaseDef.requiredOutputs?.length > 0) {
170
+ console.log(chalk.cyan('\n Required outputs:'));
171
+ nextPhaseDef.requiredOutputs.forEach(output => {
172
+ const exists = validation.phase ? true : false; // Already validated
173
+ console.log(chalk.gray(` ✓ ${output} (exists)`));
174
+ });
175
+ }
176
+
177
+ // Show phase-specific guidance
178
+ const guidance = getPhaseGuidance(nextPhase, feature);
179
+ if (guidance) {
180
+ console.log(chalk.cyan('\n Next steps:'));
181
+ guidance.forEach(step => console.log(chalk.white(` → ${step}`)));
182
+ }
183
+
184
+ console.log('');
185
+ }
186
+
187
+ /**
188
+ * Get guidance for what to do in a phase
189
+ */
190
+ function getPhaseGuidance(phase, feature) {
191
+ const guides = {
192
+ 'setup': [
193
+ `Resume spec pipeline: /morph-proposal ${feature}`,
194
+ 'Auto-continues from setup phase'
195
+ ],
196
+ 'uiux': [
197
+ `Resume spec pipeline: /morph-proposal ${feature}`,
198
+ 'Provide layout references and preferences',
199
+ 'Review wireframes before proceeding'
200
+ ],
201
+ 'design': [
202
+ `Resume spec pipeline: /morph-proposal ${feature}`,
203
+ 'Review DECISION POINTS carefully',
204
+ 'Approve spec.md and contracts.cs'
205
+ ],
206
+ 'clarify': [
207
+ `Resume spec pipeline: /morph-proposal ${feature}`,
208
+ 'Resolve edge cases and unknowns'
209
+ ],
210
+ 'tasks': [
211
+ `Resume spec pipeline: /morph-proposal ${feature}`,
212
+ 'Review task order and dependencies',
213
+ 'Approve task list before implementing'
214
+ ],
215
+ 'implement': [
216
+ `Start implementing: /morph-apply ${feature}`,
217
+ 'Complete tasks one by one with: morph-spec task done',
218
+ 'Validators run automatically on task completion'
219
+ ],
220
+ 'sync': [
221
+ 'Review decisions.md for standards to promote',
222
+ `Sync: morph-spec sync --path .morph/project/outputs/${feature}/decisions.md`
223
+ ]
224
+ };
225
+
226
+ return guides[phase] || null;
227
+ }
228
+
229
+ /**
230
+ * Gate: Check design system exists when advancing to implement with UI agents
231
+ * @param {string} feature - Feature name
232
+ * @param {string} projectPath - Project root path
233
+ * @returns {Object} { blocked: boolean, message?: string, solution?: string[] }
234
+ */
235
+ function designSystemGate(feature, projectPath = '.') {
236
+ // Check if UI agents are active
237
+ const hasUIAgents = hasUIAgentsActive(projectPath, feature);
238
+
239
+ if (!hasUIAgents) {
240
+ return { blocked: false }; // No UI agents, gate doesn't apply
241
+ }
242
+
243
+ // Check if design system exists
244
+ const dsDetection = detectDesignSystem(projectPath, feature);
245
+
246
+ if (dsDetection.hasDesignSystem) {
247
+ return { blocked: false }; // Design system exists, gate passed
248
+ }
249
+
250
+ // Block advancement - no design system found with UI agents active
251
+ return {
252
+ blocked: true,
253
+ message: 'Cannot advance to implementation — UI agents are active but no design system found',
254
+ solution: [
255
+ 'Design system is required when UI agents (blazor-builder, ui-designer, css-specialist) are active',
256
+ '',
257
+ 'Create a design system with one of these options:',
258
+ ' 1. Project-level: .morph/project/design-system.md (shared across features)',
259
+ ` 2. Feature-level: .morph/project/outputs/${feature}/ui-design-system.md (feature-specific)`,
260
+ ' 3. Auto-generate: morph-spec generate design-system (scans existing CSS)',
261
+ '',
262
+ 'Or remove UI agents if they are not needed:',
263
+ ` morph-spec state remove-agent ${feature} blazor-builder`
264
+ ]
265
+ };
266
+ }
@@ -0,0 +1,193 @@
1
+ /**
2
+ * analyze-blazor-concurrency command
3
+ *
4
+ * Analyzes Blazor Server code for DbContext concurrency issues.
5
+ *
6
+ * Usage:
7
+ * morph-spec analyze-blazor-concurrency [path]
8
+ * morph-spec analyze-blazor-concurrency src/Services --verbose
9
+ */
10
+
11
+ import { glob } from 'glob';
12
+ import { readFileSync, existsSync, statSync } from 'fs';
13
+ import { join, resolve } from 'path';
14
+ import chalk from 'chalk';
15
+ import ora from 'ora';
16
+
17
+ import {
18
+ analyzeConcurrency,
19
+ countIssues,
20
+ } from '../lib/blazor-concurrency-analyzer.js';
21
+
22
+ /**
23
+ * Main command handler for analyze-blazor-concurrency.
24
+ *
25
+ * @param {string} [targetPath] - Path to analyze (file or directory)
26
+ * @param {Object} options - Command options
27
+ * @param {boolean} [options.verbose] - Show detailed output
28
+ */
29
+ export async function analyzeBlazorConcurrencyCommand(targetPath, options = {}) {
30
+ const { verbose = false } = options;
31
+
32
+ console.log('');
33
+ console.log(
34
+ chalk.cyan('\uD83D\uDD0D Analisando concorrencia DbContext em Blazor Server...')
35
+ );
36
+ console.log('');
37
+
38
+ // Determine target path
39
+ const basePath = targetPath ? resolve(targetPath) : process.cwd();
40
+
41
+ if (!existsSync(basePath)) {
42
+ console.log(chalk.red(`\u274C Path not found: ${basePath}`));
43
+ process.exit(1);
44
+ }
45
+
46
+ const spinner = ora('Scanning for C# files...').start();
47
+
48
+ let files = [];
49
+
50
+ try {
51
+ const stats = statSync(basePath);
52
+
53
+ if (stats.isFile()) {
54
+ if (basePath.endsWith('.cs')) {
55
+ files = [basePath];
56
+ } else {
57
+ spinner.fail('File must be .cs');
58
+ process.exit(1);
59
+ }
60
+ } else {
61
+ // Find all C# files (services, repositories, handlers)
62
+ const pattern = join(basePath, '**/*.cs');
63
+ files = await glob(pattern, {
64
+ ignore: [
65
+ '**/node_modules/**',
66
+ '**/bin/**',
67
+ '**/obj/**',
68
+ '**/Migrations/**',
69
+ ],
70
+ windowsPathsNoEscape: true,
71
+ });
72
+ }
73
+
74
+ spinner.succeed(`Found ${files.length} C# file(s)`);
75
+ } catch (error) {
76
+ spinner.fail(`Error scanning files: ${error.message}`);
77
+ process.exit(1);
78
+ }
79
+
80
+ if (files.length === 0) {
81
+ console.log(chalk.yellow('\n\u26A0\uFE0F No C# files found to analyze'));
82
+ return;
83
+ }
84
+
85
+ // Analyze each file
86
+ const allIssues = [];
87
+ const fileResults = [];
88
+
89
+ for (const file of files) {
90
+ try {
91
+ const content = readFileSync(file, 'utf-8');
92
+ const issues = analyzeConcurrency(content, file);
93
+
94
+ if (issues.length > 0) {
95
+ allIssues.push(...issues);
96
+ fileResults.push({ file, issues });
97
+ }
98
+ } catch (error) {
99
+ if (verbose) {
100
+ console.log(chalk.red(`\u274C Error reading ${file}: ${error.message}`));
101
+ }
102
+ }
103
+ }
104
+
105
+ // Output results
106
+ console.log('');
107
+
108
+ if (allIssues.length === 0) {
109
+ console.log(
110
+ chalk.green(
111
+ '\u2705 Nenhum problema de concorrencia detectado!'
112
+ )
113
+ );
114
+ console.log(
115
+ chalk.gray(
116
+ ' Dica: Certifique-se de usar IDbContextFactory para operacoes background.'
117
+ )
118
+ );
119
+ console.log('');
120
+ return;
121
+ }
122
+
123
+ // Display issues
124
+ if (verbose) {
125
+ fileResults.forEach(({ file, issues }) => {
126
+ console.log(chalk.white.bold(`\n${file}`));
127
+ console.log(chalk.gray('-'.repeat(60)));
128
+
129
+ issues.forEach((issue) => {
130
+ const icon =
131
+ issue.type === 'error'
132
+ ? '\u274C'
133
+ : issue.type === 'warning'
134
+ ? '\u26A0\uFE0F'
135
+ : '\u2139\uFE0F';
136
+
137
+ console.log(`${icon} ${issue.message}`);
138
+ if (issue.suggestion) {
139
+ console.log(chalk.gray(` \u2192 ${issue.suggestion}`));
140
+ }
141
+ if (issue.line) {
142
+ console.log(chalk.dim(` Linha: ${issue.line}`));
143
+ }
144
+ if (issue.code) {
145
+ console.log(chalk.dim(` Codigo: ${issue.code}`));
146
+ }
147
+ console.log('');
148
+ });
149
+ });
150
+ } else {
151
+ allIssues.forEach((issue) => {
152
+ const icon =
153
+ issue.type === 'error'
154
+ ? '\u274C'
155
+ : issue.type === 'warning'
156
+ ? '\u26A0\uFE0F'
157
+ : '\u2139\uFE0F';
158
+
159
+ const location = issue.line ? `${issue.file}:${issue.line}` : issue.file;
160
+
161
+ console.log(`${icon} ${issue.message}`);
162
+ if (issue.suggestion) {
163
+ console.log(chalk.gray(` \u2192 ${issue.suggestion}`));
164
+ }
165
+ console.log(chalk.dim(` ${location}`));
166
+ console.log('');
167
+ });
168
+ }
169
+
170
+ // Summary
171
+ const { errors, warnings, infos } = countIssues(allIssues);
172
+ const summaryColor = errors > 0 ? chalk.red : chalk.yellow;
173
+
174
+ console.log(chalk.gray('-'.repeat(60)));
175
+ console.log(
176
+ summaryColor(
177
+ `\n${files.length} arquivo(s) analisado(s) | ${errors} erro(s) | ${warnings} warning(s) | ${infos} info(s)\n`
178
+ )
179
+ );
180
+
181
+ // Recommendation
182
+ if (errors > 0) {
183
+ console.log(
184
+ chalk.cyan(
185
+ '\uD83D\uDCD6 Consulte: framework/standards/blazor-efcore.md para padroes corretos'
186
+ )
187
+ );
188
+ console.log('');
189
+ process.exit(1);
190
+ }
191
+ }
192
+
193
+ export default analyzeBlazorConcurrencyCommand;