@polymorphism-tech/morph-spec 2.2.0 → 2.4.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 +314 -1673
- package/LICENSE +72 -72
- package/README.md +515 -516
- package/bin/detect-agents.js +225 -225
- package/bin/morph-spec.js +358 -173
- package/bin/render-template.js +302 -302
- package/bin/semantic-detect-agents.js +246 -246
- package/bin/task-manager.js +429 -0
- package/bin/validate-agents-skills.js +251 -251
- package/bin/validate-agents.js +69 -69
- package/bin/validate-phase.js +263 -263
- package/bin/validate.js +369 -0
- package/content/.azure/README.md +293 -293
- package/content/.azure/docs/azure-devops-setup.md +454 -454
- package/content/.azure/docs/branch-strategy.md +398 -398
- package/content/.azure/docs/local-development.md +515 -515
- package/content/.azure/pipelines/pipeline-variables.yml +34 -34
- package/content/.azure/pipelines/prod-pipeline.yml +319 -319
- package/content/.azure/pipelines/staging-pipeline.yml +234 -234
- package/content/.azure/pipelines/templates/build-dotnet.yml +75 -75
- package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -94
- package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -120
- package/content/.azure/pipelines/templates/infra-deploy.yml +90 -90
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-archive.md +79 -79
- package/content/.claude/commands/morph-infra.md +209 -209
- package/content/.claude/commands/morph-preflight.md +227 -0
- package/content/.claude/commands/morph-proposal.md +122 -101
- package/content/.claude/commands/morph-status.md +86 -86
- package/content/.claude/commands/morph-troubleshoot.md +122 -0
- package/content/.claude/settings.local.json +15 -15
- package/content/.claude/skills/checklists/code-review.md +226 -0
- package/content/.claude/skills/checklists/morph-checklist.md +117 -0
- package/content/.claude/skills/checklists/simulation-checklist.md +77 -0
- package/content/.claude/skills/infra/bicep-architect.md +126 -419
- package/content/.claude/skills/infra/container-specialist.md +131 -437
- package/content/.claude/skills/infra/devops-engineer.md +119 -405
- package/content/.claude/skills/integrations/asaas-financial.md +130 -333
- package/content/.claude/skills/integrations/azure-identity.md +142 -309
- package/content/.claude/skills/integrations/clerk-auth.md +108 -290
- package/content/.claude/skills/integrations/resend-email.md +119 -0
- package/content/.claude/skills/specialists/ai-system-architect.md +192 -604
- package/content/.claude/skills/specialists/azure-architect.md +142 -142
- package/content/.claude/skills/specialists/code-analyzer.md +235 -0
- package/content/.claude/skills/specialists/dotnet-senior.md +287 -0
- package/content/.claude/skills/specialists/ef-modeler.md +113 -200
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +126 -245
- package/content/.claude/skills/specialists/ms-agent-expert.md +109 -263
- package/content/.claude/skills/specialists/po-pm-advisor.md +197 -197
- package/content/.claude/skills/specialists/standards-architect.md +156 -78
- package/content/.claude/skills/specialists/testing-specialist.md +126 -0
- package/content/.claude/skills/specialists/ui-ux-designer.md +191 -1060
- package/content/.claude/skills/stacks/dotnet-blazor.md +210 -588
- package/content/.claude/skills/stacks/dotnet-nextjs.md +154 -402
- package/content/.claude/skills/workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/workflows/phase-clarify.md} +5 -58
- package/content/.claude/{commands/morph-design.md → skills/workflows/phase-design.md} +16 -86
- package/content/.claude/{commands/morph-setup.md → skills/workflows/phase-setup.md} +9 -17
- package/content/.claude/skills/workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/workflows/phase-uiux.md} +15 -88
- package/content/.morph/.morphversion +5 -5
- package/content/.morph/archive/.gitkeep +25 -25
- package/content/.morph/config/agents.json +378 -242
- package/content/.morph/config/config.template.json +89 -108
- package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -392
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/fast-track.md +29 -0
- package/content/.morph/docs/workflows/full-morph.md +76 -0
- package/content/.morph/docs/workflows/standard.md +44 -0
- package/content/.morph/docs/workflows/ui-refresh.md +39 -0
- package/content/.morph/examples/api-nextjs/README.md +241 -241
- package/content/.morph/examples/api-nextjs/contracts.ts +307 -307
- package/content/.morph/examples/api-nextjs/spec.md +399 -399
- package/content/.morph/examples/api-nextjs/tasks.md +168 -168
- package/content/.morph/examples/micro-saas/README.md +125 -125
- package/content/.morph/examples/micro-saas/contracts.cs +358 -358
- package/content/.morph/examples/micro-saas/decisions.md +246 -246
- package/content/.morph/examples/micro-saas/spec.md +236 -236
- package/content/.morph/examples/micro-saas/tasks.md +150 -150
- package/content/.morph/examples/multi-agent/README.md +309 -309
- package/content/.morph/examples/multi-agent/contracts.cs +433 -433
- package/content/.morph/examples/multi-agent/spec.md +479 -479
- package/content/.morph/examples/multi-agent/tasks.md +185 -185
- package/content/.morph/examples/scheduled-reports/decisions.md +158 -0
- package/content/.morph/examples/scheduled-reports/proposal.md +95 -0
- package/content/.morph/examples/scheduled-reports/spec.md +267 -0
- package/content/.morph/examples/state-v3.json +188 -0
- package/content/.morph/features/.gitkeep +25 -25
- package/content/.morph/hooks/README.md +190 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/pre-commit-all.sh +48 -48
- package/content/.morph/hooks/pre-commit-specs.sh +49 -49
- package/content/.morph/hooks/pre-commit-tests.sh +60 -60
- package/content/.morph/project.md +160 -160
- package/content/.morph/schemas/agent.schema.json +296 -296
- package/content/.morph/schemas/tasks.schema.json +220 -0
- package/content/.morph/specs/.gitkeep +20 -20
- package/content/.morph/standards/agent-framework-blazor-ui.md +359 -0
- package/content/.morph/standards/agent-framework-production.md +410 -0
- package/content/.morph/standards/agent-framework-setup.md +413 -453
- package/content/.morph/standards/agent-framework-workflows.md +349 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/coding.md +377 -377
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/standards/fluent-ui-setup.md +590 -590
- package/content/.morph/standards/migration-guide.md +514 -514
- package/content/.morph/standards/passkeys-auth.md +423 -423
- package/content/.morph/standards/vector-search-rag.md +536 -536
- package/content/.morph/state.json +17 -17
- package/content/.morph/templates/FluentDesignTheme.cs +149 -149
- package/content/.morph/templates/MudTheme.cs +281 -281
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- package/content/.morph/templates/component.razor +239 -239
- package/content/.morph/templates/contracts/Commands.cs +74 -0
- package/content/.morph/templates/contracts/Entities.cs +25 -0
- package/content/.morph/templates/contracts/Queries.cs +74 -0
- package/content/.morph/templates/contracts/README.md +74 -0
- package/content/.morph/templates/contracts.cs +217 -217
- package/content/.morph/templates/decisions.md +123 -106
- package/content/.morph/templates/design-system.css +226 -226
- package/content/.morph/templates/infra/.dockerignore.example +89 -89
- package/content/.morph/templates/infra/Dockerfile.example +82 -82
- package/content/.morph/templates/infra/README.md +286 -286
- package/content/.morph/templates/infra/app-insights.bicep +63 -63
- package/content/.morph/templates/infra/app-service.bicep +164 -164
- package/content/.morph/templates/infra/container-app-env.bicep +49 -49
- package/content/.morph/templates/infra/container-app.bicep +156 -156
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/infra/deploy.ps1 +229 -229
- package/content/.morph/templates/infra/deploy.sh +208 -208
- package/content/.morph/templates/infra/key-vault.bicep +91 -91
- package/content/.morph/templates/infra/main.bicep +189 -189
- package/content/.morph/templates/infra/parameters.dev.json +29 -29
- package/content/.morph/templates/infra/parameters.prod.json +29 -29
- package/content/.morph/templates/infra/parameters.staging.json +29 -29
- package/content/.morph/templates/infra/sql-database.bicep +103 -103
- package/content/.morph/templates/infra/storage.bicep +106 -106
- package/content/.morph/templates/integrations/asaas-client.cs +387 -387
- package/content/.morph/templates/integrations/asaas-webhook.cs +351 -351
- package/content/.morph/templates/integrations/azure-identity-config.cs +288 -288
- package/content/.morph/templates/integrations/clerk-config.cs +258 -258
- package/content/.morph/templates/job.cs +171 -171
- package/content/.morph/templates/migration.cs +83 -83
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/repository.cs +141 -141
- package/content/.morph/templates/saas/subscription.cs +347 -347
- package/content/.morph/templates/saas/tenant.cs +338 -338
- package/content/.morph/templates/service.cs +139 -139
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/sprint-status.yaml +68 -68
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/story.md +143 -143
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/test.cs +239 -239
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/.morph/templates/ui-design-system.md +286 -286
- package/content/.morph/templates/ui-flows.md +336 -336
- package/content/.morph/templates/ui-mockups.md +133 -133
- package/content/.morph/test-infra/example.bicep +59 -59
- package/content/CLAUDE.md +150 -442
- package/content/README.md +79 -79
- package/detectors/config-detector.js +223 -223
- package/detectors/conversation-analyzer.js +163 -163
- package/detectors/index.js +84 -84
- package/detectors/standards-generator.js +275 -275
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/templates.md +418 -418
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/scripts/postinstall.js +132 -132
- package/src/commands/advance-phase.js +183 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/create-story.js +351 -351
- package/src/commands/detect-agents.js +139 -0
- package/src/commands/detect.js +104 -104
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate.js +149 -149
- package/src/commands/init.js +258 -245
- package/src/commands/lint-fluent.js +352 -0
- package/src/commands/rollback-phase.js +185 -0
- package/src/commands/session-summary.js +291 -0
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/state.js +333 -333
- package/src/commands/sync.js +167 -167
- package/src/commands/task.js +78 -0
- package/src/commands/troubleshoot.js +222 -0
- package/src/commands/update.js +192 -159
- package/src/commands/validate-blazor-state.js +210 -0
- package/src/commands/validate-blazor.js +156 -0
- package/src/commands/validate-css.js +84 -0
- package/src/commands/validate-phase.js +221 -0
- package/src/lib/blazor-concurrency-analyzer.js +288 -0
- package/src/lib/blazor-state-validator.js +291 -0
- package/src/lib/blazor-validator.js +374 -0
- package/src/lib/complexity-analyzer.js +441 -292
- package/src/lib/continuous-validator.js +421 -0
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/learning-system.js +520 -0
- package/src/lib/mockup-generator.js +366 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/ui-detector.js +350 -0
- package/src/lib/validation-runner.js +231 -0
- package/src/lib/validators/architecture-validator.js +387 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/package-validator.js +360 -0
- package/src/lib/validators/ui-contrast-validator.js +422 -0
- package/src/utils/file-copier.js +179 -139
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/stacks/shopify.md +0 -445
- package/content/.morph/config/azure-pricing.json +0 -70
- package/content/.morph/config/azure-pricing.schema.json +0 -50
- package/content/.morph/hooks/pre-commit-costs.sh +0 -91
- package/docs/api/cost-calculator.js.html +0 -513
- package/docs/api/design-system-generator.js.html +0 -382
- package/docs/api/global.html +0 -5263
- package/docs/api/index.html +0 -96
- package/docs/api/state-manager.js.html +0 -423
- package/src/commands/cost.js +0 -181
- package/src/commands/update-pricing.js +0 -206
- package/src/lib/cost-calculator.js +0 -429
package/src/commands/init.js
CHANGED
|
@@ -1,245 +1,258 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import fs from 'fs-extra';
|
|
3
|
-
import ora from 'ora';
|
|
4
|
-
import chalk from 'chalk';
|
|
5
|
-
import { logger } from '../utils/logger.js';
|
|
6
|
-
import {
|
|
7
|
-
getContentDir,
|
|
8
|
-
copyDirectory,
|
|
9
|
-
copyFile,
|
|
10
|
-
pathExists,
|
|
11
|
-
readJson,
|
|
12
|
-
writeJson,
|
|
13
|
-
ensureDir,
|
|
14
|
-
writeFile,
|
|
15
|
-
readFile,
|
|
16
|
-
updateGitignore,
|
|
17
|
-
createSymlink
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
logger.
|
|
27
|
-
logger.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
logger.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
await ensureDir(join(projectPath, '
|
|
63
|
-
await ensureDir(join(projectPath, '
|
|
64
|
-
await ensureDir(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
let
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
await ensureDir(skillsDest);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
logger.
|
|
222
|
-
|
|
223
|
-
logger.
|
|
224
|
-
|
|
225
|
-
logger.
|
|
226
|
-
logger.
|
|
227
|
-
logger.
|
|
228
|
-
logger.
|
|
229
|
-
logger.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
logger.
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
import {
|
|
7
|
+
getContentDir,
|
|
8
|
+
copyDirectory,
|
|
9
|
+
copyFile,
|
|
10
|
+
pathExists,
|
|
11
|
+
readJson,
|
|
12
|
+
writeJson,
|
|
13
|
+
ensureDir,
|
|
14
|
+
writeFile,
|
|
15
|
+
readFile,
|
|
16
|
+
updateGitignore,
|
|
17
|
+
createSymlink,
|
|
18
|
+
createDirectoryLink
|
|
19
|
+
} from '../utils/file-copier.js';
|
|
20
|
+
import { saveProjectMorphVersion, getInstalledCLIVersion } from '../utils/version-checker.js';
|
|
21
|
+
|
|
22
|
+
export async function initCommand(options) {
|
|
23
|
+
const targetPath = options.path || process.cwd();
|
|
24
|
+
const claudeMdPath = join(import.meta.dirname, '..', '..', 'CLAUDE.md');
|
|
25
|
+
|
|
26
|
+
logger.header('MORPH-SPEC Framework Installation');
|
|
27
|
+
logger.dim(`Target: ${targetPath}`);
|
|
28
|
+
logger.blank();
|
|
29
|
+
|
|
30
|
+
// Check if already initialized
|
|
31
|
+
const morphPath = join(targetPath, '.morph');
|
|
32
|
+
if (await pathExists(morphPath)) {
|
|
33
|
+
if (!options.force) {
|
|
34
|
+
logger.warn('MORPH already initialized in this directory.');
|
|
35
|
+
logger.dim('Use --force to overwrite existing installation.');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
logger.warn('Overwriting existing MORPH installation...');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const spinner = ora('Installing MORPH-SPEC...').start();
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// 1. Copy CLAUDE.md
|
|
45
|
+
spinner.text = 'Copying CLAUDE.md...';
|
|
46
|
+
const claudeMdDest = join(targetPath, 'CLAUDE.md');
|
|
47
|
+
|
|
48
|
+
// Backup existing CLAUDE.md if not from MORPH
|
|
49
|
+
if (await pathExists(claudeMdDest)) {
|
|
50
|
+
const existingContent = await readFile(claudeMdDest);
|
|
51
|
+
if (!existingContent.includes('MORPH-SPEC')) {
|
|
52
|
+
await copyFile(claudeMdDest, `${claudeMdDest}.backup`);
|
|
53
|
+
logger.dim('Backed up existing CLAUDE.md');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
await copyFile(claudeMdPath, claudeMdDest);
|
|
57
|
+
|
|
58
|
+
// 2. Create .morph directory structure
|
|
59
|
+
spinner.text = 'Creating .morph structure...';
|
|
60
|
+
const projectPath = join(morphPath, 'project');
|
|
61
|
+
const configDir = join(morphPath, 'config');
|
|
62
|
+
await ensureDir(join(projectPath, 'context'));
|
|
63
|
+
await ensureDir(join(projectPath, 'standards'));
|
|
64
|
+
await ensureDir(join(projectPath, 'outputs'));
|
|
65
|
+
await ensureDir(configDir);
|
|
66
|
+
|
|
67
|
+
// 3. Create config.json
|
|
68
|
+
spinner.text = 'Generating config.json...';
|
|
69
|
+
const configPath = join(configDir, 'config.json');
|
|
70
|
+
const dirName = targetPath.split(/[\\/]/).pop();
|
|
71
|
+
|
|
72
|
+
const config = {
|
|
73
|
+
framework: 'global',
|
|
74
|
+
frameworkVersion: getInstalledCLIVersion(),
|
|
75
|
+
project: {
|
|
76
|
+
name: dirName,
|
|
77
|
+
stack: 'unknown',
|
|
78
|
+
architecture: 'unknown'
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
await writeJson(configPath, config);
|
|
83
|
+
|
|
84
|
+
// 4. Create context/README.md
|
|
85
|
+
spinner.text = 'Creating context README...';
|
|
86
|
+
const contextReadme = join(projectPath, 'context', 'README.md');
|
|
87
|
+
const readmeContent = `# ${dirName} - Project Context
|
|
88
|
+
|
|
89
|
+
## Overview
|
|
90
|
+
|
|
91
|
+
This file will be auto-updated by MORPH-SPEC detection system.
|
|
92
|
+
|
|
93
|
+
## Stack
|
|
94
|
+
|
|
95
|
+
Run \`morph-spec detect\` to analyze your project.
|
|
96
|
+
|
|
97
|
+
## Technologies
|
|
98
|
+
|
|
99
|
+
(To be detected)
|
|
100
|
+
|
|
101
|
+
## Architecture
|
|
102
|
+
|
|
103
|
+
(To be detected)
|
|
104
|
+
`;
|
|
105
|
+
await writeFile(contextReadme, readmeContent);
|
|
106
|
+
|
|
107
|
+
// 5. Copy templates from content
|
|
108
|
+
spinner.text = 'Copying templates...';
|
|
109
|
+
const contentDir = getContentDir();
|
|
110
|
+
const templatesSrc = join(contentDir, '.morph', 'templates');
|
|
111
|
+
const templatesDest = join(morphPath, 'templates');
|
|
112
|
+
if (await pathExists(templatesSrc)) {
|
|
113
|
+
await copyDirectory(templatesSrc, templatesDest);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 6. Copy standards from content
|
|
117
|
+
spinner.text = 'Copying standards...';
|
|
118
|
+
const standardsSrc = join(contentDir, '.morph', 'standards');
|
|
119
|
+
const standardsDest = join(morphPath, 'standards');
|
|
120
|
+
if (await pathExists(standardsSrc)) {
|
|
121
|
+
await copyDirectory(standardsSrc, standardsDest);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 7. Copy agents.json
|
|
125
|
+
spinner.text = 'Copying agents configuration...';
|
|
126
|
+
const agentsSrc = join(contentDir, '.morph', 'config', 'agents.json');
|
|
127
|
+
const agentsDest = join(configDir, 'agents.json');
|
|
128
|
+
if (await pathExists(agentsSrc)) {
|
|
129
|
+
await copyFile(agentsSrc, agentsDest);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 8. Copy azure-pricing files
|
|
133
|
+
spinner.text = 'Copying Azure pricing data...';
|
|
134
|
+
const pricingSrc = join(contentDir, '.morph', 'config', 'azure-pricing.json');
|
|
135
|
+
const pricingDest = join(configDir, 'azure-pricing.json');
|
|
136
|
+
if (await pathExists(pricingSrc)) {
|
|
137
|
+
await copyFile(pricingSrc, pricingDest);
|
|
138
|
+
}
|
|
139
|
+
const pricingSchemaSrc = join(contentDir, '.morph', 'config', 'azure-pricing.schema.json');
|
|
140
|
+
const pricingSchemaDest = join(configDir, 'azure-pricing.schema.json');
|
|
141
|
+
if (await pathExists(pricingSchemaSrc)) {
|
|
142
|
+
await copyFile(pricingSchemaSrc, pricingSchemaDest);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 9. Copy .claude commands and create symlinks for skills
|
|
146
|
+
spinner.text = 'Setting up Claude Code integration...';
|
|
147
|
+
const claudeSrc = join(contentDir, '.claude');
|
|
148
|
+
const claudeDest = join(targetPath, '.claude');
|
|
149
|
+
|
|
150
|
+
let symlinkCount = 0;
|
|
151
|
+
let copyCount = 0;
|
|
152
|
+
|
|
153
|
+
if (await pathExists(claudeSrc)) {
|
|
154
|
+
// Copy commands directory (slash commands)
|
|
155
|
+
const commandsSrc = join(claudeSrc, 'commands');
|
|
156
|
+
const commandsDest = join(claudeDest, 'commands');
|
|
157
|
+
if (await pathExists(commandsSrc)) {
|
|
158
|
+
await copyDirectory(commandsSrc, commandsDest);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Create directory links for skill categories (or copy if linking fails)
|
|
162
|
+
const skillsSrc = join(claudeSrc, 'skills');
|
|
163
|
+
const skillsDest = join(claudeDest, 'skills');
|
|
164
|
+
|
|
165
|
+
if (await pathExists(skillsSrc)) {
|
|
166
|
+
await ensureDir(skillsDest);
|
|
167
|
+
|
|
168
|
+
const entries = await fs.readdir(skillsSrc, { withFileTypes: true });
|
|
169
|
+
|
|
170
|
+
let linkedCategories = 0;
|
|
171
|
+
let copiedCategories = 0;
|
|
172
|
+
let totalSkillFiles = 0;
|
|
173
|
+
|
|
174
|
+
// Link category directories (specialists/, infra/, checklists/, etc.)
|
|
175
|
+
for (const entry of entries) {
|
|
176
|
+
if (entry.isDirectory()) {
|
|
177
|
+
const categorySrc = join(skillsSrc, entry.name);
|
|
178
|
+
const categoryDest = join(skillsDest, entry.name);
|
|
179
|
+
|
|
180
|
+
// Count .md files for reporting
|
|
181
|
+
const categoryEntries = await fs.readdir(categorySrc, { withFileTypes: true });
|
|
182
|
+
const mdFiles = categoryEntries.filter(e => e.isFile() && e.name.endsWith('.md'));
|
|
183
|
+
totalSkillFiles += mdFiles.length;
|
|
184
|
+
|
|
185
|
+
const result = await createDirectoryLink(categorySrc, categoryDest);
|
|
186
|
+
if (result === 'copy') {
|
|
187
|
+
copiedCategories++;
|
|
188
|
+
} else {
|
|
189
|
+
linkedCategories++;
|
|
190
|
+
}
|
|
191
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
192
|
+
// Handle .md files in skills root
|
|
193
|
+
totalSkillFiles++;
|
|
194
|
+
const result = await createSymlink(join(skillsSrc, entry.name), join(skillsDest, entry.name), 'file');
|
|
195
|
+
if (result === 'symlink') {
|
|
196
|
+
linkedCategories++;
|
|
197
|
+
} else {
|
|
198
|
+
copiedCategories++;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
symlinkCount = linkedCategories > 0 ? totalSkillFiles : 0;
|
|
204
|
+
copyCount = linkedCategories === 0 ? totalSkillFiles : 0;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 10. Save version info
|
|
209
|
+
spinner.text = 'Saving version info...';
|
|
210
|
+
const cliVersion = getInstalledCLIVersion();
|
|
211
|
+
await saveProjectMorphVersion(targetPath, cliVersion);
|
|
212
|
+
|
|
213
|
+
// 11. Update .gitignore
|
|
214
|
+
spinner.text = 'Updating .gitignore...';
|
|
215
|
+
await updateGitignore(targetPath);
|
|
216
|
+
|
|
217
|
+
spinner.succeed('MORPH-SPEC installed successfully!');
|
|
218
|
+
|
|
219
|
+
// Show next steps
|
|
220
|
+
logger.blank();
|
|
221
|
+
logger.success(`MORPH-SPEC v${cliVersion} installed successfully!`);
|
|
222
|
+
logger.blank();
|
|
223
|
+
logger.header('Next Steps');
|
|
224
|
+
|
|
225
|
+
logger.step(1, 'Run detection: morph-spec detect');
|
|
226
|
+
logger.step(2, 'Review .morph/config.json and .morph/project/standards/inferred.md');
|
|
227
|
+
logger.step(3, 'Open project in VS Code with Claude Code');
|
|
228
|
+
logger.step(4, 'Start your first feature:');
|
|
229
|
+
logger.blank();
|
|
230
|
+
logger.box([
|
|
231
|
+
'Ask Claude Code to implement a feature'
|
|
232
|
+
]);
|
|
233
|
+
logger.blank();
|
|
234
|
+
|
|
235
|
+
logger.info('Files installed:');
|
|
236
|
+
logger.dim(` ✓ CLAUDE.md`);
|
|
237
|
+
logger.dim(` ✓ .morph/config/ (config.json, agents.json, azure-pricing.json)`);
|
|
238
|
+
logger.dim(` ✓ .morph/standards/ (coding.md, architecture.md, azure.md, ...)`);
|
|
239
|
+
logger.dim(` ✓ .morph/templates/ (Bicep, integrations, saas, ...)`);
|
|
240
|
+
logger.dim(` ✓ .morph/project/ (context, standards, outputs)`);
|
|
241
|
+
logger.dim(` ✓ .claude/commands/ (slash commands)`);
|
|
242
|
+
|
|
243
|
+
if (symlinkCount > 0) {
|
|
244
|
+
const linkType = process.platform === 'win32' ? 'junction-linked' : 'symlinked';
|
|
245
|
+
logger.dim(` ✓ .claude/skills/ (${symlinkCount} ${linkType})`);
|
|
246
|
+
} else if (copyCount > 0) {
|
|
247
|
+
logger.dim(` ✓ .claude/skills/ (${copyCount} copied)`);
|
|
248
|
+
logger.warn(` ⚠ Directory links not supported (copied instead). Skills won't auto-update.`);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
logger.blank();
|
|
252
|
+
|
|
253
|
+
} catch (error) {
|
|
254
|
+
spinner.fail('Installation failed');
|
|
255
|
+
logger.error(error.message);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
}
|