@polymorphism-tech/morph-spec 1.0.4 → 2.1.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/CLAUDE.md +1381 -0
- package/LICENSE +72 -0
- package/README.md +89 -6
- package/bin/detect-agents.js +225 -0
- package/bin/morph-spec.js +120 -0
- package/bin/render-template.js +302 -0
- package/bin/semantic-detect-agents.js +246 -0
- package/bin/validate-agents-skills.js +239 -0
- package/bin/validate-agents.js +69 -0
- package/bin/validate-phase.js +263 -0
- package/content/.azure/README.md +293 -0
- package/content/.azure/docs/azure-devops-setup.md +454 -0
- package/content/.azure/docs/branch-strategy.md +398 -0
- package/content/.azure/docs/local-development.md +515 -0
- package/content/.azure/pipelines/pipeline-variables.yml +34 -0
- package/content/.azure/pipelines/prod-pipeline.yml +319 -0
- package/content/.azure/pipelines/staging-pipeline.yml +234 -0
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -0
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -0
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -0
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -0
- package/content/.claude/commands/morph-apply.md +118 -26
- package/content/.claude/commands/morph-archive.md +9 -9
- package/content/.claude/commands/morph-clarify.md +184 -0
- package/content/.claude/commands/morph-design.md +275 -0
- package/content/.claude/commands/morph-proposal.md +56 -15
- package/content/.claude/commands/morph-setup.md +100 -0
- package/content/.claude/commands/morph-status.md +47 -32
- package/content/.claude/commands/morph-tasks.md +319 -0
- package/content/.claude/commands/morph-uiux.md +211 -0
- package/content/.claude/skills/specialists/ai-system-architect.md +604 -0
- package/content/.claude/skills/specialists/ms-agent-expert.md +143 -89
- package/content/.claude/skills/specialists/ui-ux-designer.md +744 -9
- package/content/.claude/skills/stacks/dotnet-blazor.md +244 -8
- package/content/.claude/skills/stacks/dotnet-nextjs.md +2 -2
- package/content/.morph/.morphversion +5 -0
- package/content/.morph/config/agents.json +101 -8
- package/content/.morph/config/azure-pricing.json +70 -0
- package/content/.morph/config/azure-pricing.schema.json +50 -0
- package/content/.morph/config/config.template.json +15 -3
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -0
- package/content/.morph/hooks/README.md +239 -0
- package/content/.morph/hooks/pre-commit-agents.sh +24 -0
- package/content/.morph/hooks/pre-commit-all.sh +48 -0
- package/content/.morph/hooks/pre-commit-costs.sh +91 -0
- package/content/.morph/hooks/pre-commit-specs.sh +49 -0
- package/content/.morph/hooks/pre-commit-tests.sh +60 -0
- package/content/.morph/project.md +5 -4
- package/content/.morph/schemas/agent.schema.json +296 -0
- package/content/.morph/standards/agent-framework-setup.md +453 -0
- package/content/.morph/standards/architecture.md +142 -7
- package/content/.morph/standards/azure.md +218 -23
- package/content/.morph/standards/coding.md +47 -12
- package/content/.morph/standards/dotnet10-migration.md +494 -0
- package/content/.morph/standards/fluent-ui-setup.md +590 -0
- package/content/.morph/standards/migration-guide.md +514 -0
- package/content/.morph/standards/passkeys-auth.md +423 -0
- package/content/.morph/standards/vector-search-rag.md +536 -0
- package/content/.morph/state.json +18 -0
- package/content/.morph/templates/FluentDesignTheme.cs +149 -0
- package/content/.morph/templates/MudTheme.cs +281 -0
- package/content/.morph/templates/contracts.cs +55 -55
- package/content/.morph/templates/decisions.md +4 -4
- package/content/.morph/templates/design-system.css +226 -0
- package/content/.morph/templates/infra/.dockerignore.example +89 -0
- package/content/.morph/templates/infra/Dockerfile.example +82 -0
- package/content/.morph/templates/infra/README.md +286 -0
- package/content/.morph/templates/infra/app-service.bicep +164 -0
- package/content/.morph/templates/infra/deploy.ps1 +229 -0
- package/content/.morph/templates/infra/deploy.sh +208 -0
- package/content/.morph/templates/infra/main.bicep +41 -7
- package/content/.morph/templates/infra/parameters.dev.json +6 -0
- package/content/.morph/templates/infra/parameters.prod.json +6 -0
- package/content/.morph/templates/infra/parameters.staging.json +29 -0
- package/content/.morph/templates/proposal.md +3 -3
- package/content/.morph/templates/recap.md +3 -3
- package/content/.morph/templates/spec.md +9 -8
- package/content/.morph/templates/sprint-status.yaml +68 -0
- package/content/.morph/templates/state.template.json +222 -0
- package/content/.morph/templates/story.md +143 -0
- package/content/.morph/templates/tasks.md +1 -1
- package/content/.morph/templates/ui-components.md +276 -0
- package/content/.morph/templates/ui-design-system.md +286 -0
- package/content/.morph/templates/ui-flows.md +336 -0
- package/content/.morph/templates/ui-mockups.md +133 -0
- package/content/.morph/test-infra/example.bicep +59 -0
- package/content/CLAUDE.md +124 -0
- package/content/README.md +79 -0
- package/detectors/config-detector.js +223 -0
- package/detectors/conversation-analyzer.js +163 -0
- package/detectors/index.js +84 -0
- package/detectors/standards-generator.js +275 -0
- package/detectors/structure-detector.js +221 -0
- package/docs/README.md +149 -0
- package/docs/api/cost-calculator.js.html +513 -0
- package/docs/api/design-system-generator.js.html +382 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/api/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/api/global.html +5263 -0
- package/docs/api/index.html +96 -0
- package/docs/api/scripts/collapse.js +39 -0
- package/docs/api/scripts/commonNav.js +28 -0
- package/docs/api/scripts/linenumber.js +25 -0
- package/docs/api/scripts/nav.js +12 -0
- package/docs/api/scripts/polyfill.js +4 -0
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/prettify/lang-css.js +2 -0
- package/docs/api/scripts/prettify/prettify.js +28 -0
- package/docs/api/scripts/search.js +99 -0
- package/docs/api/state-manager.js.html +423 -0
- package/docs/api/styles/jsdoc.css +776 -0
- package/docs/api/styles/prettify.css +80 -0
- package/docs/examples.md +328 -0
- package/docs/getting-started.md +302 -0
- package/docs/installation.md +361 -0
- package/docs/templates.md +418 -0
- package/docs/validation-checklist.md +266 -0
- package/package.json +39 -12
- package/src/commands/cost.js +181 -0
- package/src/commands/create-story.js +283 -0
- package/src/commands/detect.js +104 -0
- package/src/commands/doctor.js +67 -0
- package/src/commands/generate.js +149 -0
- package/src/commands/init.js +69 -45
- package/src/commands/shard-spec.js +224 -0
- package/src/commands/sprint-status.js +250 -0
- package/src/commands/state.js +333 -0
- package/src/commands/sync.js +167 -0
- package/src/commands/update-pricing.js +206 -0
- package/src/commands/update.js +88 -13
- package/src/lib/complexity-analyzer.js +292 -0
- package/src/lib/cost-calculator.js +429 -0
- package/src/lib/design-system-generator.js +298 -0
- package/src/lib/state-manager.js +340 -0
- package/src/utils/file-copier.js +59 -0
- package/src/utils/version-checker.js +175 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MORPH-SPEC Complexity Analyzer Library
|
|
3
|
+
*
|
|
4
|
+
* Analyzes user requests and classifies them into workflows:
|
|
5
|
+
* - fast-track: Trivial changes (bug fixes, small adjustments)
|
|
6
|
+
* - standard: Medium features (simple additions, improvements)
|
|
7
|
+
* - full-morph: Complex features (new subsystems, architecture)
|
|
8
|
+
*
|
|
9
|
+
* Used both by CLI commands and internal automation.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// COMPLEXITY THRESHOLDS
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
export const COMPLEXITY_THRESHOLDS = {
|
|
17
|
+
'fast-track': {
|
|
18
|
+
maxFiles: 3,
|
|
19
|
+
maxLines: 50,
|
|
20
|
+
maxComponents: 0,
|
|
21
|
+
requiresInfrastructure: false,
|
|
22
|
+
requiresArchitecturalDecisions: false,
|
|
23
|
+
description: 'Bug fixes, small adjustments, edge cases, hotfixes'
|
|
24
|
+
},
|
|
25
|
+
'standard': {
|
|
26
|
+
maxFiles: 10,
|
|
27
|
+
maxLines: 500,
|
|
28
|
+
maxComponents: 2,
|
|
29
|
+
requiresInfrastructure: false,
|
|
30
|
+
requiresArchitecturalDecisions: false, // Only tactical decisions
|
|
31
|
+
description: 'Simple features, refactorings, incremental improvements'
|
|
32
|
+
},
|
|
33
|
+
'full-morph': {
|
|
34
|
+
maxFiles: Infinity,
|
|
35
|
+
maxLines: Infinity,
|
|
36
|
+
maxComponents: Infinity,
|
|
37
|
+
requiresInfrastructure: true, // Can have infrastructure
|
|
38
|
+
requiresArchitecturalDecisions: true, // Strategic decisions
|
|
39
|
+
description: 'Complex features, new subsystems, architectural changes'
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// KEYWORD DETECTION
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Keywords that indicate different complexity levels
|
|
49
|
+
*/
|
|
50
|
+
const COMPLEXITY_KEYWORDS = {
|
|
51
|
+
trivial: [
|
|
52
|
+
'bug', 'fix', 'corrigir', 'ajustar', 'typo', 'correção',
|
|
53
|
+
'edge case', 'hotfix', 'urgente', 'rápido', 'quick',
|
|
54
|
+
'cor', 'color', 'texto', 'text', 'label', 'validação',
|
|
55
|
+
'mensagem', 'message', 'css', 'style', 'espaçamento'
|
|
56
|
+
],
|
|
57
|
+
|
|
58
|
+
infrastructure: [
|
|
59
|
+
'azure', 'bicep', 'deploy', 'infra', 'infrastructure',
|
|
60
|
+
'container', 'kubernetes', 'k8s', 'database', 'sql',
|
|
61
|
+
'storage', 'queue', 'service bus', 'redis', 'cosmos'
|
|
62
|
+
],
|
|
63
|
+
|
|
64
|
+
architectural: [
|
|
65
|
+
'sistema', 'system', 'arquitetura', 'architecture',
|
|
66
|
+
'pattern', 'cqrs', 'event sourcing', 'microservice',
|
|
67
|
+
'subsistema', 'subsystem', 'integração', 'integration',
|
|
68
|
+
'autenticação', 'authentication', 'autorização', 'authorization'
|
|
69
|
+
],
|
|
70
|
+
|
|
71
|
+
newComponents: [
|
|
72
|
+
'novo', 'new', 'criar', 'create', 'adicionar', 'add',
|
|
73
|
+
'implementar', 'implement', 'desenvolver', 'develop',
|
|
74
|
+
'componente', 'component', 'serviço', 'service',
|
|
75
|
+
'tela', 'screen', 'página', 'page', 'formulário', 'form'
|
|
76
|
+
]
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// ANALYSIS FUNCTIONS
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Detect keywords in user input
|
|
85
|
+
* @param {string} userInput - User request
|
|
86
|
+
* @param {Array<string>} keywords - Keywords to search for
|
|
87
|
+
* @returns {number} Count of keyword matches
|
|
88
|
+
*/
|
|
89
|
+
function detectKeywords(userInput, keywords) {
|
|
90
|
+
const lowerInput = userInput.toLowerCase();
|
|
91
|
+
return keywords.filter(keyword => lowerInput.includes(keyword)).length;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Estimate code impact from user input
|
|
96
|
+
* @param {string} userInput - User request
|
|
97
|
+
* @returns {Object} Estimated impact
|
|
98
|
+
*/
|
|
99
|
+
export function estimateCodeImpact(userInput) {
|
|
100
|
+
const lowerInput = userInput.toLowerCase();
|
|
101
|
+
|
|
102
|
+
// Trivial indicators
|
|
103
|
+
const trivialCount = detectKeywords(lowerInput, COMPLEXITY_KEYWORDS.trivial);
|
|
104
|
+
if (trivialCount > 0) {
|
|
105
|
+
return {
|
|
106
|
+
estimatedFiles: 1,
|
|
107
|
+
estimatedLines: 10,
|
|
108
|
+
estimatedComponents: 0,
|
|
109
|
+
confidence: 'high'
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Count indicators of new components
|
|
114
|
+
const newComponentCount = detectKeywords(lowerInput, COMPLEXITY_KEYWORDS.newComponents);
|
|
115
|
+
|
|
116
|
+
// Multiple components/features mentioned (separated by "e", "and", or commas)
|
|
117
|
+
const separators = [' e ', ' and ', ','];
|
|
118
|
+
const hasSeparator = separators.some(sep => lowerInput.includes(sep));
|
|
119
|
+
|
|
120
|
+
if (hasSeparator) {
|
|
121
|
+
// Split by any separator
|
|
122
|
+
let parts = [lowerInput];
|
|
123
|
+
for (const sep of separators) {
|
|
124
|
+
parts = parts.flatMap(part => part.split(sep));
|
|
125
|
+
}
|
|
126
|
+
parts = parts.filter(p => p.trim().length > 0);
|
|
127
|
+
|
|
128
|
+
// If we found multiple parts, estimate high complexity
|
|
129
|
+
if (parts.length > 1) {
|
|
130
|
+
return {
|
|
131
|
+
estimatedFiles: Math.min(parts.length * 3, 15),
|
|
132
|
+
estimatedLines: Math.min(parts.length * 200, 1000),
|
|
133
|
+
estimatedComponents: Math.min(parts.length, 5),
|
|
134
|
+
confidence: 'medium'
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// New component indicators
|
|
140
|
+
if (newComponentCount > 0) {
|
|
141
|
+
return {
|
|
142
|
+
estimatedFiles: 5,
|
|
143
|
+
estimatedLines: 200,
|
|
144
|
+
estimatedComponents: 1,
|
|
145
|
+
confidence: 'medium'
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Default to standard complexity
|
|
150
|
+
return {
|
|
151
|
+
estimatedFiles: 5,
|
|
152
|
+
estimatedLines: 150,
|
|
153
|
+
estimatedComponents: 1,
|
|
154
|
+
confidence: 'low'
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Detect if request involves infrastructure
|
|
160
|
+
* @param {string} userInput - User request
|
|
161
|
+
* @returns {boolean} True if infrastructure is involved
|
|
162
|
+
*/
|
|
163
|
+
export function detectInfrastructure(userInput) {
|
|
164
|
+
const infraCount = detectKeywords(userInput, COMPLEXITY_KEYWORDS.infrastructure);
|
|
165
|
+
return infraCount > 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Detect if request involves architectural decisions
|
|
170
|
+
* @param {string} userInput - User request
|
|
171
|
+
* @returns {boolean} True if architectural decisions are involved
|
|
172
|
+
*/
|
|
173
|
+
export function detectArchitecturalDecisions(userInput) {
|
|
174
|
+
const archCount = detectKeywords(userInput, COMPLEXITY_KEYWORDS.architectural);
|
|
175
|
+
return archCount > 0;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Classify workflow based on analysis
|
|
180
|
+
* @param {Object} impact - Code impact estimation
|
|
181
|
+
* @param {boolean} hasInfrastructure - Has infrastructure
|
|
182
|
+
* @param {boolean} hasArchitecturalDecisions - Has architectural decisions
|
|
183
|
+
* @returns {string} Workflow type: "fast-track" | "standard" | "full-morph"
|
|
184
|
+
*/
|
|
185
|
+
export function classifyWorkflow(impact, hasInfrastructure, hasArchitecturalDecisions) {
|
|
186
|
+
const { estimatedFiles, estimatedLines, estimatedComponents } = impact;
|
|
187
|
+
|
|
188
|
+
// Full MORPH: Infrastructure or architectural decisions
|
|
189
|
+
if (hasInfrastructure || hasArchitecturalDecisions) {
|
|
190
|
+
return 'full-morph';
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Full MORPH: Large code impact
|
|
194
|
+
if (estimatedFiles > COMPLEXITY_THRESHOLDS.standard.maxFiles ||
|
|
195
|
+
estimatedLines > COMPLEXITY_THRESHOLDS.standard.maxLines ||
|
|
196
|
+
estimatedComponents > COMPLEXITY_THRESHOLDS.standard.maxComponents) {
|
|
197
|
+
return 'full-morph';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Fast Track: Trivial changes
|
|
201
|
+
if (estimatedFiles <= COMPLEXITY_THRESHOLDS['fast-track'].maxFiles &&
|
|
202
|
+
estimatedLines <= COMPLEXITY_THRESHOLDS['fast-track'].maxLines &&
|
|
203
|
+
estimatedComponents <= COMPLEXITY_THRESHOLDS['fast-track'].maxComponents) {
|
|
204
|
+
return 'fast-track';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Default: Standard workflow
|
|
208
|
+
return 'standard';
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Analyze request complexity - Main entry point
|
|
213
|
+
* @param {string} userInput - User request
|
|
214
|
+
* @param {Object} options - Options
|
|
215
|
+
* @param {string} options.forceWorkflow - Force specific workflow
|
|
216
|
+
* @returns {Object} Complete analysis
|
|
217
|
+
*/
|
|
218
|
+
export function analyzeRequestComplexity(userInput, options = {}) {
|
|
219
|
+
// Check for forced workflow
|
|
220
|
+
if (options.forceWorkflow) {
|
|
221
|
+
return {
|
|
222
|
+
workflow: options.forceWorkflow,
|
|
223
|
+
forced: true,
|
|
224
|
+
reason: 'Manually overridden by user'
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Analyze request
|
|
229
|
+
const impact = estimateCodeImpact(userInput);
|
|
230
|
+
const hasInfrastructure = detectInfrastructure(userInput);
|
|
231
|
+
const hasArchitecturalDecisions = detectArchitecturalDecisions(userInput);
|
|
232
|
+
|
|
233
|
+
const workflow = classifyWorkflow(impact, hasInfrastructure, hasArchitecturalDecisions);
|
|
234
|
+
|
|
235
|
+
// Build reason
|
|
236
|
+
let reason = `Estimated ${impact.estimatedFiles} files, ${impact.estimatedLines} lines, ${impact.estimatedComponents} components`;
|
|
237
|
+
if (hasInfrastructure) reason += ', requires infrastructure';
|
|
238
|
+
if (hasArchitecturalDecisions) reason += ', requires architectural decisions';
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
workflow,
|
|
242
|
+
forced: false,
|
|
243
|
+
impact,
|
|
244
|
+
hasInfrastructure,
|
|
245
|
+
hasArchitecturalDecisions,
|
|
246
|
+
confidence: impact.confidence,
|
|
247
|
+
reason,
|
|
248
|
+
thresholds: COMPLEXITY_THRESHOLDS[workflow]
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Get workflow phases
|
|
254
|
+
* @param {string} workflow - Workflow type
|
|
255
|
+
* @returns {Array<string>} List of phases to execute
|
|
256
|
+
*/
|
|
257
|
+
export function getWorkflowPhases(workflow) {
|
|
258
|
+
switch (workflow) {
|
|
259
|
+
case 'fast-track':
|
|
260
|
+
return ['quick-analysis', 'implement'];
|
|
261
|
+
|
|
262
|
+
case 'standard':
|
|
263
|
+
return ['proposal', 'design', 'tasks', 'implement'];
|
|
264
|
+
|
|
265
|
+
case 'full-morph':
|
|
266
|
+
return ['context', 'proposal', 'setup', 'uiux', 'design', 'clarify', 'tasks', 'implement', 'sync'];
|
|
267
|
+
|
|
268
|
+
default:
|
|
269
|
+
return ['context', 'proposal', 'setup', 'uiux', 'design', 'clarify', 'tasks', 'implement', 'sync'];
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get workflow description
|
|
275
|
+
* @param {string} workflow - Workflow type
|
|
276
|
+
* @returns {string} Human-readable description
|
|
277
|
+
*/
|
|
278
|
+
export function getWorkflowDescription(workflow) {
|
|
279
|
+
switch (workflow) {
|
|
280
|
+
case 'fast-track':
|
|
281
|
+
return 'Fast Track: Quick fixes without formal spec (1 pause, no outputs)';
|
|
282
|
+
|
|
283
|
+
case 'standard':
|
|
284
|
+
return 'Standard: Medium complexity with simplified workflow (2-3 pauses, minimal outputs)';
|
|
285
|
+
|
|
286
|
+
case 'full-morph':
|
|
287
|
+
return 'Full MORPH: Complete 8-phase workflow with all outputs';
|
|
288
|
+
|
|
289
|
+
default:
|
|
290
|
+
return 'Unknown workflow';
|
|
291
|
+
}
|
|
292
|
+
}
|