@polymorphism-tech/morph-spec 4.8.19 → 4.10.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 (214) hide show
  1. package/CLAUDE.md +21 -0
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +44 -55
  4. package/bin/task-manager.js +133 -20
  5. package/bin/validate.js +67 -33
  6. package/claude-plugin.json +1 -1
  7. package/docs/CHEATSHEET.md +201 -203
  8. package/docs/QUICKSTART.md +2 -2
  9. package/framework/CLAUDE.md +99 -77
  10. package/framework/agents.json +734 -182
  11. package/framework/commands/commit.md +166 -0
  12. package/framework/commands/morph-apply.md +13 -2
  13. package/framework/commands/morph-archive.md +8 -2
  14. package/framework/commands/morph-infra.md +6 -0
  15. package/framework/commands/morph-preflight.md +6 -0
  16. package/framework/commands/morph-proposal.md +56 -7
  17. package/framework/commands/morph-status.md +6 -0
  18. package/framework/commands/morph-troubleshoot.md +6 -0
  19. package/framework/hooks/claude-code/notification/approval-reminder.js +3 -2
  20. package/framework/hooks/claude-code/post-tool-use/context-refresh.js +1 -1
  21. package/framework/hooks/claude-code/post-tool-use/dispatch.js +155 -32
  22. package/framework/hooks/claude-code/post-tool-use/skill-reminder.js +78 -0
  23. package/framework/hooks/claude-code/post-tool-use/validator-feedback.js +8 -17
  24. package/framework/hooks/claude-code/pre-compact/save-morph-context.js +16 -3
  25. package/framework/hooks/claude-code/pre-tool-use/enforce-phase-writes.js +4 -3
  26. package/framework/hooks/claude-code/pre-tool-use/protect-spec-files.js +4 -3
  27. package/framework/hooks/claude-code/pre-tool-use/task-tracking-guard.js +60 -0
  28. package/framework/hooks/claude-code/session-start/inject-morph-context.js +124 -2
  29. package/framework/hooks/claude-code/session-start/post-compact-restore.js +41 -0
  30. package/framework/hooks/claude-code/statusline.py +76 -30
  31. package/framework/hooks/claude-code/stop/validate-completion.js +2 -15
  32. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +23 -5
  33. package/framework/hooks/claude-code/user-prompt/set-terminal-title.js +14 -6
  34. package/framework/hooks/shared/activity-logger.js +0 -24
  35. package/framework/hooks/shared/compact-restore.js +100 -0
  36. package/framework/hooks/shared/dispatch-helpers.js +116 -0
  37. package/framework/hooks/shared/phase-utils.js +12 -5
  38. package/framework/hooks/shared/skill-reminder-helpers.js +79 -0
  39. package/framework/hooks/shared/stale-task-reset.js +57 -0
  40. package/framework/hooks/shared/state-reader.js +29 -5
  41. package/framework/hooks/shared/worktree-helpers.js +53 -0
  42. package/framework/phases.json +69 -14
  43. package/framework/rules/morph-workflow.md +88 -86
  44. package/framework/skills/level-0-meta/mcp-registry.json +86 -51
  45. package/framework/skills/level-0-meta/{brainstorming → morph-brainstorming}/SKILL.md +14 -17
  46. package/framework/skills/level-0-meta/morph-checklist/SKILL.md +2 -2
  47. package/framework/skills/level-0-meta/{code-review → morph-code-review}/SKILL.md +2 -2
  48. package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/SKILL.md +163 -163
  49. package/framework/skills/level-0-meta/{frontend-review → morph-frontend-review}/SKILL.md +9 -9
  50. package/framework/skills/level-0-meta/morph-init/SKILL.md +77 -12
  51. package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/SKILL.md +62 -15
  52. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +5 -5
  53. package/framework/skills/level-0-meta/morph-replicate/references/blazor-html-mapping.md +1 -1
  54. package/framework/skills/level-0-meta/{simulation-checklist → morph-simulation-checklist}/SKILL.md +1 -1
  55. package/framework/skills/level-0-meta/{terminal-title → morph-terminal-title}/SKILL.md +2 -2
  56. package/framework/skills/level-0-meta/{tool-usage-guide → morph-tool-usage-guide}/SKILL.md +3 -4
  57. package/framework/skills/level-0-meta/{tool-usage-guide → morph-tool-usage-guide}/references/tools-per-phase.md +7 -7
  58. package/framework/skills/level-0-meta/{verification-before-completion → morph-verification-before-completion}/SKILL.md +2 -2
  59. package/framework/skills/level-0-meta/{verification-before-completion → morph-verification-before-completion}/scripts/check-phase-outputs.mjs +2 -2
  60. package/framework/skills/level-1-workflows/morph-phase-clarify/SKILL.md +238 -0
  61. package/framework/skills/level-1-workflows/{phase-codebase-analysis → morph-phase-codebase-analysis}/SKILL.md +3 -3
  62. package/framework/skills/level-1-workflows/morph-phase-design/SKILL.md +507 -0
  63. package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/SKILL.md +168 -27
  64. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/code-quality-reviewer-prompt.md +50 -0
  65. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/implementer-prompt.md +45 -0
  66. package/framework/skills/level-1-workflows/morph-phase-implement/prompts/spec-reviewer-prompt.md +47 -0
  67. package/framework/skills/level-1-workflows/morph-phase-plan/SKILL.md +254 -0
  68. package/framework/skills/level-1-workflows/{phase-setup → morph-phase-setup}/SKILL.md +50 -3
  69. package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/SKILL.md +48 -11
  70. package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/scripts/validate-tasks.mjs +3 -3
  71. package/framework/skills/level-1-workflows/{phase-uiux → morph-phase-uiux}/SKILL.md +46 -11
  72. package/framework/skills/level-1-workflows/morph-scope-escalation/SKILL.md +97 -0
  73. package/framework/standards/STANDARDS.json +640 -88
  74. package/framework/standards/infrastructure/vercel/vercel-database.md +106 -0
  75. package/framework/standards/integration/mcp/mcp-tools.md +25 -7
  76. package/framework/templates/REGISTRY.json +1825 -1909
  77. package/framework/templates/context/CONTEXT-FEATURE.md +276 -276
  78. package/framework/templates/docs/onboarding.md +3 -7
  79. package/package.json +2 -7
  80. package/src/commands/agents/dispatch-agents.js +104 -6
  81. package/src/commands/mcp/mcp-setup.js +39 -2
  82. package/src/commands/phase/phase-reset.js +74 -0
  83. package/src/commands/project/doctor.js +34 -51
  84. package/src/commands/project/init.js +1 -1
  85. package/src/commands/project/status.js +2 -2
  86. package/src/commands/project/update.js +381 -365
  87. package/src/commands/project/worktree.js +154 -0
  88. package/src/commands/scope/escalate.js +215 -0
  89. package/src/commands/state/advance-phase.js +132 -68
  90. package/src/commands/state/approve.js +2 -2
  91. package/src/commands/state/index.js +7 -8
  92. package/src/commands/state/phase-runner.js +1 -1
  93. package/src/commands/state/state.js +61 -6
  94. package/src/commands/task/expand.js +100 -0
  95. package/src/commands/tasks/task.js +78 -99
  96. package/src/commands/templates/template-render.js +93 -173
  97. package/src/commands/trust/trust.js +26 -21
  98. package/src/core/paths/output-schema.js +19 -3
  99. package/src/core/state/phase-state-machine.js +7 -4
  100. package/src/core/state/state-manager.js +32 -57
  101. package/src/core/workflows/workflow-detector.js +9 -87
  102. package/src/lib/detectors/claude-config-detector.js +93 -347
  103. package/src/lib/detectors/design-system-detector.js +189 -189
  104. package/src/lib/detectors/index.js +155 -57
  105. package/src/lib/generators/context-generator.js +2 -2
  106. package/src/lib/installers/mcp-installer.js +37 -5
  107. package/src/lib/phase-chain/phase-validator.js +336 -0
  108. package/src/lib/scope/impact-analyzer.js +106 -0
  109. package/src/lib/stack/stack-profile.js +88 -0
  110. package/src/lib/tasks/task-classifier.js +16 -0
  111. package/src/lib/tasks/task-parser.js +1 -1
  112. package/src/lib/tasks/test-runner.js +77 -0
  113. package/src/lib/trust/trust-manager.js +32 -144
  114. package/src/lib/validators/shared/emit-validator-dispatch.js +64 -0
  115. package/src/lib/validators/spec-validator.js +58 -4
  116. package/src/lib/validators/validation-runner.js +23 -11
  117. package/src/scripts/setup-infra.js +255 -224
  118. package/src/utils/agents-installer.js +34 -14
  119. package/src/utils/banner.js +1 -1
  120. package/src/utils/claude-settings-manager.js +1 -1
  121. package/src/utils/file-copier.js +1 -1
  122. package/src/utils/hooks-installer.js +272 -8
  123. package/framework/hooks/dev/check-sync-health.js +0 -117
  124. package/framework/hooks/dev/guard-version-numbers.js +0 -57
  125. package/framework/hooks/dev/sync-standards-registry.js +0 -60
  126. package/framework/hooks/dev/sync-template-registry.js +0 -60
  127. package/framework/hooks/dev/validate-skill-format.js +0 -70
  128. package/framework/hooks/dev/validate-standard-format.js +0 -73
  129. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +0 -190
  130. package/framework/skills/level-1-workflows/phase-design/SKILL.md +0 -366
  131. package/framework/templates/meta-prompts/hops/hop-retry.md +0 -78
  132. package/framework/templates/meta-prompts/hops/hop-validation.md +0 -97
  133. package/framework/templates/meta-prompts/hops/hop-wrapper.md +0 -36
  134. package/framework/workflows/configs/design-impl.json +0 -49
  135. package/framework/workflows/configs/express.json +0 -45
  136. package/framework/workflows/configs/fast-track.json +0 -42
  137. package/framework/workflows/configs/full-morph.json +0 -79
  138. package/framework/workflows/configs/fusion.json +0 -39
  139. package/framework/workflows/configs/long-running.json +0 -33
  140. package/framework/workflows/configs/spec-only.json +0 -43
  141. package/framework/workflows/configs/ui-refresh.json +0 -49
  142. package/framework/workflows/configs/zero-touch.json +0 -82
  143. package/src/commands/project/index.js +0 -8
  144. package/src/commands/project/monitor.js +0 -295
  145. package/src/commands/project/tutorial.js +0 -115
  146. package/src/commands/state/validate-phase.js +0 -238
  147. package/src/commands/templates/generate-contracts.js +0 -445
  148. package/src/core/index.js +0 -10
  149. package/src/core/orchestrator.js +0 -171
  150. package/src/core/registry/command-registry.js +0 -28
  151. package/src/core/registry/index.js +0 -8
  152. package/src/core/registry/validator-registry.js +0 -204
  153. package/src/core/state/index.js +0 -8
  154. package/src/core/templates/index.js +0 -9
  155. package/src/core/templates/template-data-sources.js +0 -325
  156. package/src/core/templates/template-validator.js +0 -296
  157. package/src/core/workflows/index.js +0 -7
  158. package/src/generator/config-generator.js +0 -206
  159. package/src/generator/templates/config.json.template +0 -40
  160. package/src/generator/templates/project.md.template +0 -67
  161. package/src/lib/agents/micro-agent-factory.js +0 -161
  162. package/src/lib/analysis/complexity-analyzer.js +0 -441
  163. package/src/lib/analysis/index.js +0 -7
  164. package/src/lib/analytics/analytics-engine.js +0 -345
  165. package/src/lib/checkpoints/checkpoint-hooks.js +0 -298
  166. package/src/lib/checkpoints/index.js +0 -7
  167. package/src/lib/context/context-bundler.js +0 -241
  168. package/src/lib/context/context-optimizer.js +0 -212
  169. package/src/lib/context/context-tracker.js +0 -273
  170. package/src/lib/context/core-four-tracker.js +0 -201
  171. package/src/lib/context/mcp-optimizer.js +0 -200
  172. package/src/lib/detectors/config-detector.js +0 -223
  173. package/src/lib/detectors/standards-generator.js +0 -335
  174. package/src/lib/detectors/structure-detector.js +0 -275
  175. package/src/lib/execution/fusion-executor.js +0 -304
  176. package/src/lib/execution/parallel-executor.js +0 -270
  177. package/src/lib/hooks/stop-hook-executor.js +0 -286
  178. package/src/lib/hops/hop-composer.js +0 -221
  179. package/src/lib/monitor/agent-resolver.js +0 -144
  180. package/src/lib/monitor/renderer.js +0 -230
  181. package/src/lib/orchestration/index.js +0 -7
  182. package/src/lib/orchestration/team-orchestrator.js +0 -404
  183. package/src/lib/phase-chain/eligibility-checker.js +0 -243
  184. package/src/lib/threads/thread-coordinator.js +0 -238
  185. package/src/lib/threads/thread-manager.js +0 -317
  186. package/src/lib/tracking/artifact-trail.js +0 -202
  187. package/src/sanitizer/context-sanitizer.js +0 -221
  188. package/src/sanitizer/patterns.js +0 -163
  189. package/src/scanner/project-scanner.js +0 -242
  190. package/src/ui/diff-display.js +0 -91
  191. package/src/ui/interactive-wizard.js +0 -96
  192. package/src/ui/user-review.js +0 -211
  193. package/src/ui/wizard-questions.js +0 -188
  194. package/src/utils/color-utils.js +0 -70
  195. package/src/utils/process-handler.js +0 -97
  196. package/src/writer/file-writer.js +0 -86
  197. /package/framework/skills/level-0-meta/{brainstorming → morph-brainstorming}/references/proposal-example.md +0 -0
  198. /package/framework/skills/level-0-meta/{code-review → morph-code-review}/references/review-example.md +0 -0
  199. /package/framework/skills/level-0-meta/{code-review → morph-code-review}/references/review-guidelines.md +0 -0
  200. /package/framework/skills/level-0-meta/{code-review → morph-code-review}/scripts/scan-csharp.mjs +0 -0
  201. /package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/references/review-example-nextjs.md +0 -0
  202. /package/framework/skills/level-0-meta/{code-review-nextjs → morph-code-review-nextjs}/scripts/scan-nextjs.mjs +0 -0
  203. /package/framework/skills/level-0-meta/{frontend-review → morph-frontend-review}/scripts/scan-accessibility.mjs +0 -0
  204. /package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/scripts/detect-dev-server.mjs +0 -0
  205. /package/framework/skills/level-0-meta/{post-implementation → morph-post-implementation}/scripts/detect-stack.mjs +0 -0
  206. /package/framework/skills/level-0-meta/{terminal-title → morph-terminal-title}/scripts/set_title.sh +0 -0
  207. /package/framework/skills/level-1-workflows/{phase-clarify → morph-phase-clarify}/references/clarifications-example.md +0 -0
  208. /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/architecture-analysis-guide.md +0 -0
  209. /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/spec-authoring-guide.md +0 -0
  210. /package/framework/skills/level-1-workflows/{phase-design → morph-phase-design}/references/spec-example.md +0 -0
  211. /package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/references/recap-example.md +0 -0
  212. /package/framework/skills/level-1-workflows/{phase-implement → morph-phase-implement}/references/vsa-implementation-guide.md +0 -0
  213. /package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/references/task-planning-patterns.md +0 -0
  214. /package/framework/skills/level-1-workflows/{phase-tasks → morph-phase-tasks}/references/tasks-example.md +0 -0
@@ -1,296 +0,0 @@
1
- /**
2
- * Template Validator - Validates Handlebars templates
3
- * Checks for:
4
- * - Required placeholders are present
5
- * - No deprecated pre-computed variables ({FEATURE_NAME_PASCAL})
6
- * - Valid Handlebars syntax
7
- * - Proper helper usage
8
- */
9
-
10
- import { readFileSync } from 'fs';
11
- import { getTemplateById, getAllTemplates } from './template-registry.js';
12
-
13
- /**
14
- * Deprecated placeholder patterns (v1.0 pre-computed variables)
15
- */
16
- const DEPRECATED_PATTERNS = [
17
- { pattern: /\{\{FEATURE_NAME_PASCAL\}\}/g, replacement: '{{pascalCase FEATURE_NAME}}' },
18
- { pattern: /\{\{FEATURE_NAME_CAMEL\}\}/g, replacement: '{{camelCase FEATURE_NAME}}' },
19
- { pattern: /\{\{FEATURE_NAME_SNAKE\}\}/g, replacement: '{{snakeCase FEATURE_NAME}}' },
20
- { pattern: /\{\{FEATURE_NAME_UPPER_SNAKE\}\}/g, replacement: '{{upperSnakeCase FEATURE_NAME}}' },
21
- { pattern: /\{\{FEATURE_NAME_TITLE\}\}/g, replacement: '{{titleCase FEATURE_NAME}}' },
22
- { pattern: /\{\{FEATURE_NAME_KEBAB\}\}/g, replacement: '{{kebabCase FEATURE_NAME}}' },
23
- ];
24
-
25
- /**
26
- * Old template syntax (non-Handlebars)
27
- */
28
- const OLD_SYNTAX_PATTERNS = [
29
- { pattern: /\{Feature\}/g, description: 'Old {Feature} syntax (use {{pascalCase FEATURE_NAME}})' },
30
- { pattern: /\{feature\}/g, description: 'Old {feature} syntax (use {{kebabCase FEATURE_NAME}})' },
31
- ];
32
-
33
- /**
34
- * Validation result
35
- */
36
- class ValidationResult {
37
- constructor(templateId, templatePath) {
38
- this.templateId = templateId;
39
- this.templatePath = templatePath;
40
- this.valid = true;
41
- this.errors = [];
42
- this.warnings = [];
43
- this.info = [];
44
- }
45
-
46
- addError(message) {
47
- this.errors.push(message);
48
- this.valid = false;
49
- }
50
-
51
- addWarning(message) {
52
- this.warnings.push(message);
53
- }
54
-
55
- addInfo(message) {
56
- this.info.push(message);
57
- }
58
-
59
- get hasIssues() {
60
- return this.errors.length > 0 || this.warnings.length > 0;
61
- }
62
- }
63
-
64
- /**
65
- * Validates a single template
66
- * @param {string} templateId - Template ID
67
- * @param {string} projectPath - Project root path
68
- * @returns {ValidationResult}
69
- */
70
- export function validateTemplate(templateId, projectPath = process.cwd()) {
71
- const template = getTemplateById(templateId, projectPath);
72
-
73
- if (!template) {
74
- const result = new ValidationResult(templateId, null);
75
- result.addError(`Template not found: ${templateId}`);
76
- return result;
77
- }
78
-
79
- const result = new ValidationResult(templateId, template.path);
80
-
81
- // Read template content
82
- let content;
83
- try {
84
- const fullPath = `${projectPath}/framework/templates/${template.path}`;
85
- content = readFileSync(fullPath, 'utf-8');
86
- } catch (error) {
87
- result.addError(`Failed to read template: ${error.message}`);
88
- return result;
89
- }
90
-
91
- // Check for deprecated pre-computed variables
92
- for (const { pattern, replacement } of DEPRECATED_PATTERNS) {
93
- const matches = content.match(pattern);
94
- if (matches) {
95
- result.addError(
96
- `Deprecated placeholder found: ${matches[0]} (use ${replacement} instead)`
97
- );
98
- }
99
- }
100
-
101
- // Check for old non-Handlebars syntax
102
- for (const { pattern, description } of OLD_SYNTAX_PATTERNS) {
103
- const matches = content.match(pattern);
104
- if (matches) {
105
- const count = matches.length;
106
- result.addWarning(
107
- `${count} occurrence(s) of old syntax: ${description}`
108
- );
109
- }
110
- }
111
-
112
- // Check for required placeholders if specified
113
- if (template.placeholders && template.placeholders.length > 0) {
114
- const missingPlaceholders = [];
115
-
116
- for (const placeholder of template.placeholders) {
117
- // Check for exact placeholder or helper usage
118
- const exactMatch = new RegExp(`\\{\\{${placeholder}\\}\\}`, 'g');
119
- const helperMatch = new RegExp(`\\{\\{\\w+\\s+${placeholder}\\}\\}`, 'g');
120
-
121
- if (!exactMatch.test(content) && !helperMatch.test(content)) {
122
- missingPlaceholders.push(placeholder);
123
- }
124
- }
125
-
126
- if (missingPlaceholders.length > 0) {
127
- result.addWarning(
128
- `Template declares placeholders but they're not used: ${missingPlaceholders.join(', ')}`
129
- );
130
- }
131
- }
132
-
133
- // Check for balanced Handlebars blocks
134
- const openBlocks = (content.match(/\{\{#\w+/g) || []).length;
135
- const closeBlocks = (content.match(/\{\{\/\w+/g) || []).length;
136
-
137
- if (openBlocks !== closeBlocks) {
138
- result.addError(
139
- `Unbalanced Handlebars blocks: ${openBlocks} opening, ${closeBlocks} closing`
140
- );
141
- }
142
-
143
- // Info: Count Handlebars placeholders
144
- const placeholderMatches = content.match(/\{\{[^}]+\}\}/g) || [];
145
- const uniquePlaceholders = [...new Set(placeholderMatches)];
146
- result.addInfo(`Found ${uniquePlaceholders.length} unique Handlebars expressions`);
147
-
148
- // Info: Check if template uses helpers
149
- const helperMatches = content.match(/\{\{(pascalCase|camelCase|snakeCase|titleCase|kebabCase|upperSnakeCase|pluralize|singularize|formatDate|uppercase|lowercase|capitalize|trim|replace|concat|substr|startsWith|endsWith|contains|length|add|subtract|multiply|divide|mod|round|join|first|last|slice|now|year|default|json)/g) || [];
150
- if (helperMatches.length > 0) {
151
- const uniqueHelpers = [...new Set(helperMatches.map(m => m.replace('{{', '')))];
152
- result.addInfo(`Uses helpers: ${uniqueHelpers.join(', ')}`);
153
- }
154
-
155
- return result;
156
- }
157
-
158
- /**
159
- * Validates all templates
160
- * @param {string} projectPath - Project root path
161
- * @param {Object} options - Validation options
162
- * @returns {Array<ValidationResult>}
163
- */
164
- export function validateAllTemplates(projectPath = process.cwd(), options = {}) {
165
- const {
166
- skipDeprecated = true,
167
- category = null,
168
- technology = null,
169
- } = options;
170
-
171
- const templates = getAllTemplates(projectPath);
172
- const results = [];
173
-
174
- for (const template of templates) {
175
- // Skip deprecated if requested
176
- if (skipDeprecated && template.deprecated) {
177
- continue;
178
- }
179
-
180
- // Filter by category if specified
181
- if (category && template.category !== category) {
182
- continue;
183
- }
184
-
185
- // Filter by technology if specified
186
- if (technology && template.technology !== technology) {
187
- continue;
188
- }
189
-
190
- const result = validateTemplate(template.id, projectPath);
191
- results.push(result);
192
- }
193
-
194
- return results;
195
- }
196
-
197
- /**
198
- * Generates a validation summary
199
- * @param {Array<ValidationResult>} results - Validation results
200
- * @returns {Object}
201
- */
202
- export function summarizeValidation(results) {
203
- const summary = {
204
- total: results.length,
205
- valid: 0,
206
- hasErrors: 0,
207
- hasWarnings: 0,
208
- errors: [],
209
- warnings: [],
210
- };
211
-
212
- for (const result of results) {
213
- if (result.valid && result.warnings.length === 0) {
214
- summary.valid++;
215
- }
216
-
217
- if (result.errors.length > 0) {
218
- summary.hasErrors++;
219
- summary.errors.push({
220
- templateId: result.templateId,
221
- errors: result.errors,
222
- });
223
- }
224
-
225
- if (result.warnings.length > 0) {
226
- summary.hasWarnings++;
227
- summary.warnings.push({
228
- templateId: result.templateId,
229
- warnings: result.warnings,
230
- });
231
- }
232
- }
233
-
234
- return summary;
235
- }
236
-
237
- /**
238
- * Formats validation results for display
239
- * @param {Array<ValidationResult>} results - Validation results
240
- * @param {Object} options - Display options
241
- * @returns {string}
242
- */
243
- export function formatValidationResults(results, options = {}) {
244
- const { showInfo = false, showValid = false } = options;
245
-
246
- let output = '';
247
- let validCount = 0;
248
- let errorCount = 0;
249
- let warningCount = 0;
250
-
251
- for (const result of results) {
252
- if (result.valid && result.warnings.length === 0) {
253
- validCount++;
254
- if (showValid) {
255
- output += `✅ ${result.templateId}\n`;
256
- }
257
- continue;
258
- }
259
-
260
- if (result.errors.length > 0) {
261
- errorCount++;
262
- output += `\n❌ ${result.templateId}\n`;
263
- output += ` Path: ${result.templatePath}\n`;
264
- for (const error of result.errors) {
265
- output += ` ERROR: ${error}\n`;
266
- }
267
- }
268
-
269
- if (result.warnings.length > 0) {
270
- warningCount++;
271
- if (result.errors.length === 0) {
272
- output += `\n⚠️ ${result.templateId}\n`;
273
- output += ` Path: ${result.templatePath}\n`;
274
- }
275
- for (const warning of result.warnings) {
276
- output += ` WARNING: ${warning}\n`;
277
- }
278
- }
279
-
280
- if (showInfo && result.info.length > 0) {
281
- for (const info of result.info) {
282
- output += ` INFO: ${info}\n`;
283
- }
284
- }
285
- }
286
-
287
- // Summary
288
- output += `\n${'='.repeat(60)}\n`;
289
- output += `SUMMARY:\n`;
290
- output += ` Total templates: ${results.length}\n`;
291
- output += ` ✅ Valid: ${validCount}\n`;
292
- output += ` ❌ Errors: ${errorCount}\n`;
293
- output += ` ⚠️ Warnings: ${warningCount}\n`;
294
-
295
- return output;
296
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Core Workflow System
3
- *
4
- * Workflow detection and classification (fast-track, standard, full-morph, etc.)
5
- */
6
-
7
- export { WorkflowDetector, detectWorkflow } from './workflow-detector.js';
@@ -1,206 +0,0 @@
1
- /**
2
- * @fileoverview ConfigGenerator - Renders templates and generates config files
3
- * @module morph-spec/generator/config-generator
4
- */
5
-
6
- import { readFile, access, copyFile } from 'fs/promises';
7
- import { join, dirname } from 'path';
8
- import Handlebars from 'handlebars';
9
- import { fileURLToPath } from 'url';
10
- import Ajv from 'ajv';
11
-
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
-
15
- /**
16
- * @typedef {import('../types/index.js').ProjectConfig} ProjectConfig
17
- * @typedef {import('../types/index.js').GeneratedConfigs} GeneratedConfigs
18
- */
19
-
20
- /**
21
- * Validation Error
22
- */
23
- export class ValidationError extends Error {
24
- constructor(message, field, value) {
25
- super(message);
26
- this.name = 'ValidationError';
27
- this.field = field;
28
- this.value = value;
29
- }
30
- }
31
-
32
- /**
33
- * ConfigGenerator - Generates configuration files from ProjectConfig
34
- * @class
35
- */
36
- export class ConfigGenerator {
37
- constructor() {
38
- this.projectMdTemplate = null;
39
- this.configJsonTemplate = null;
40
- this.ajv = new Ajv({ allErrors: true });
41
- }
42
-
43
- /**
44
- * Load templates from filesystem
45
- * @private
46
- */
47
- async loadTemplates() {
48
- if (this.projectMdTemplate && this.configJsonTemplate) {
49
- return; // Already loaded
50
- }
51
-
52
- const templatesDir = join(__dirname, 'templates');
53
-
54
- const [projectMdSource, configJsonSource] = await Promise.all([
55
- readFile(join(templatesDir, 'project.md.template'), 'utf-8'),
56
- readFile(join(templatesDir, 'config.json.template'), 'utf-8')
57
- ]);
58
-
59
- this.projectMdTemplate = Handlebars.compile(projectMdSource);
60
- this.configJsonTemplate = Handlebars.compile(configJsonSource);
61
- }
62
-
63
- /**
64
- * Generate configuration files from project config
65
- * @param {ProjectConfig} projectConfig - Detected project config
66
- * @returns {Promise<GeneratedConfigs>}
67
- */
68
- async generate(projectConfig) {
69
- // Load templates if not already loaded
70
- await this.loadTemplates();
71
-
72
- // Add generation timestamp
73
- const context = {
74
- ...projectConfig,
75
- generatedAt: new Date().toISOString()
76
- };
77
-
78
- // Render templates
79
- const projectMd = this.renderProjectMd(context);
80
- const configJson = this.renderConfigJson(context);
81
-
82
- // Parse config.json to object
83
- const configObject = JSON.parse(configJson);
84
-
85
- // Validate config.json (optional, but good practice)
86
- // Note: agent-schema.json validation would happen here if we had the schema
87
- // For now, we just ensure it's valid JSON
88
-
89
- return {
90
- projectMd,
91
- configJson,
92
- configObject
93
- };
94
- }
95
-
96
- /**
97
- * Render project.md template
98
- * @param {ProjectConfig} config - Project config
99
- * @returns {string} Rendered markdown
100
- */
101
- renderProjectMd(config) {
102
- if (!this.projectMdTemplate) {
103
- throw new Error('Templates not loaded. Call loadTemplates() first.');
104
- }
105
-
106
- return this.projectMdTemplate(config);
107
- }
108
-
109
- /**
110
- * Render config.json template
111
- * @param {ProjectConfig} config - Project config
112
- * @returns {string} Rendered JSON string
113
- */
114
- renderConfigJson(config) {
115
- if (!this.configJsonTemplate) {
116
- throw new Error('Templates not loaded. Call loadTemplates() first.');
117
- }
118
-
119
- const rendered = this.configJsonTemplate(config);
120
-
121
- // Validate that rendered output is valid JSON
122
- try {
123
- JSON.parse(rendered);
124
- return rendered;
125
- } catch (error) {
126
- throw new ValidationError(
127
- `Rendered config.json is not valid JSON: ${error.message}`,
128
- 'configJson',
129
- rendered
130
- );
131
- }
132
- }
133
-
134
- /**
135
- * Validate config.json against agent schema
136
- * @param {string} configJson - JSON string
137
- * @returns {boolean} True if valid
138
- * @throws {ValidationError} If validation fails
139
- */
140
- validateConfigJson(configJson) {
141
- // Parse JSON
142
- let parsed;
143
- try {
144
- parsed = JSON.parse(configJson);
145
- } catch (error) {
146
- throw new ValidationError(
147
- `Invalid JSON: ${error.message}`,
148
- 'configJson',
149
- configJson
150
- );
151
- }
152
-
153
- // Basic validation - ensure required fields exist
154
- const requiredFields = ['name', 'type', 'description', 'stack', 'architecture'];
155
- for (const field of requiredFields) {
156
- if (!parsed[field]) {
157
- throw new ValidationError(
158
- `Missing required field: ${field}`,
159
- field,
160
- parsed
161
- );
162
- }
163
- }
164
-
165
- // Validate stack.backend is required
166
- if (!parsed.stack || !parsed.stack.backend) {
167
- throw new ValidationError(
168
- 'stack.backend is required',
169
- 'stack.backend',
170
- parsed
171
- );
172
- }
173
-
174
- return true;
175
- }
176
-
177
- /**
178
- * Backup existing configuration files
179
- * @param {string} cwd - Current working directory
180
- * @returns {Promise<void>}
181
- */
182
- async backupExisting(cwd) {
183
- const projectMdPath = join(cwd, '.morph', 'project.md');
184
- const configJsonPath = join(cwd, '.morph', 'config', 'config.json');
185
-
186
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
187
-
188
- // Backup project.md if exists
189
- try {
190
- await access(projectMdPath);
191
- const backupPath = join(cwd, '.morph', `project.md.${timestamp}.backup`);
192
- await copyFile(projectMdPath, backupPath);
193
- } catch (error) {
194
- // File doesn't exist, no need to backup
195
- }
196
-
197
- // Backup config.json if exists
198
- try {
199
- await access(configJsonPath);
200
- const backupPath = join(cwd, '.morph', 'config', `config.json.${timestamp}.backup`);
201
- await copyFile(configJsonPath, backupPath);
202
- } catch (error) {
203
- // File doesn't exist, no need to backup
204
- }
205
- }
206
- }
@@ -1,40 +0,0 @@
1
- {
2
- "$schema": "../schema/agent-schema.json",
3
- "name": "{{name}}",
4
- "type": "{{type}}",
5
- "description": "{{description}}",
6
- "stack": {
7
- {{#if stack.frontend}}
8
- "frontend": {
9
- "tech": "{{stack.frontend.tech}}",
10
- "version": "{{stack.frontend.version}}"{{#if stack.frontend.details}},
11
- "details": "{{stack.frontend.details}}"{{/if}}
12
- },
13
- {{/if}}
14
- "backend": {
15
- "tech": "{{stack.backend.tech}}",
16
- "version": "{{stack.backend.version}}"{{#if stack.backend.details}},
17
- "details": "{{stack.backend.details}}"{{/if}}
18
- }{{#if stack.database}},
19
- "database": {
20
- "tech": "{{stack.database.tech}}",
21
- "version": "{{stack.database.version}}"{{#if stack.database.details}},
22
- "details": "{{stack.database.details}}"{{/if}}
23
- }{{/if}}{{#if stack.hosting}},
24
- "hosting": "{{stack.hosting}}"{{/if}}
25
- },
26
- "architecture": "{{architecture}}",
27
- "conventions": "{{conventions}}",
28
- "infrastructure": {
29
- "azure": {{hasAzure}},
30
- "docker": {{hasDocker}},
31
- "devops": {{hasDevOps}}
32
- }{{#if repository}},
33
- "repository": "{{repository}}"{{/if}},
34
- "meta": {
35
- "generatedBy": "morph-spec-cli",
36
- "generatedAt": "{{generatedAt}}",
37
- "llmConfidence": {{confidence}},
38
- "autoDetected": true
39
- }
40
- }
@@ -1,67 +0,0 @@
1
- # {{name}}
2
-
3
- > {{description}}
4
-
5
- ## Stack
6
-
7
- | Component | Technology |
8
- |-----------|------------|
9
- {{#if stack.frontend}}
10
- | **Frontend** | {{stack.frontend.tech}} {{stack.frontend.version}}{{#if stack.frontend.details}} - {{stack.frontend.details}}{{/if}} |
11
- {{/if}}
12
- | **Backend** | {{stack.backend.tech}} {{stack.backend.version}}{{#if stack.backend.details}} - {{stack.backend.details}}{{/if}} |
13
- {{#if stack.database}}
14
- | **Database** | {{stack.database.tech}} {{stack.database.version}}{{#if stack.database.details}} - {{stack.database.details}}{{/if}} |
15
- {{/if}}
16
- {{#if stack.hosting}}
17
- | **Hosting** | {{stack.hosting}} |
18
- {{/if}}
19
-
20
- ## Architecture
21
-
22
- **Pattern:** {{architecture}}
23
-
24
- {{projectStructure}}
25
-
26
- ## Code Conventions
27
-
28
- {{conventions}}
29
-
30
- ## Infrastructure
31
-
32
- {{#if hasAzure}}
33
- - ✅ **Azure** - Uses Azure infrastructure (Bicep files detected)
34
- {{else}}
35
- - ❌ **Azure** - No Azure resources detected
36
- {{/if}}
37
-
38
- {{#if hasDocker}}
39
- - ✅ **Docker** - Containerized (Dockerfile/docker-compose.yml detected)
40
- {{else}}
41
- - ❌ **Docker** - Not containerized
42
- {{/if}}
43
-
44
- {{#if hasDevOps}}
45
- - ✅ **CI/CD** - Pipelines detected
46
- {{else}}
47
- - ❌ **CI/CD** - No pipelines detected
48
- {{/if}}
49
-
50
- {{#if repository}}
51
- ## Repository
52
-
53
- {{repository}}
54
- {{/if}}
55
-
56
- {{#if warnings.length}}
57
- ## ⚠️ Warnings
58
-
59
- {{#each warnings}}
60
- - {{this}}
61
- {{/each}}
62
- {{/if}}
63
-
64
- ---
65
-
66
- *Auto-generated by MORPH-SPEC CLI on {{generatedAt}}*
67
- *LLM Confidence: {{confidence}}%*