@polymorphism-tech/morph-spec 1.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 (83) hide show
  1. package/README.md +279 -0
  2. package/bin/morph-spec.js +53 -0
  3. package/content/.claude/commands/morph-apply.md +66 -0
  4. package/content/.claude/commands/morph-archive.md +79 -0
  5. package/content/.claude/commands/morph-costs.md +206 -0
  6. package/content/.claude/commands/morph-infra.md +209 -0
  7. package/content/.claude/commands/morph-proposal.md +60 -0
  8. package/content/.claude/commands/morph-status.md +71 -0
  9. package/content/.claude/settings.local.json +15 -0
  10. package/content/.claude/skills/infra/bicep-architect.md +419 -0
  11. package/content/.claude/skills/infra/container-specialist.md +437 -0
  12. package/content/.claude/skills/infra/devops-engineer.md +405 -0
  13. package/content/.claude/skills/integrations/asaas-financial.md +333 -0
  14. package/content/.claude/skills/integrations/azure-identity.md +309 -0
  15. package/content/.claude/skills/integrations/clerk-auth.md +290 -0
  16. package/content/.claude/skills/specialists/azure-architect.md +142 -0
  17. package/content/.claude/skills/specialists/cost-guardian.md +110 -0
  18. package/content/.claude/skills/specialists/ef-modeler.md +200 -0
  19. package/content/.claude/skills/specialists/hangfire-orchestrator.md +245 -0
  20. package/content/.claude/skills/specialists/ms-agent-expert.md +209 -0
  21. package/content/.claude/skills/specialists/po-pm-advisor.md +197 -0
  22. package/content/.claude/skills/specialists/standards-architect.md +78 -0
  23. package/content/.claude/skills/specialists/ui-ux-designer.md +325 -0
  24. package/content/.claude/skills/stacks/dotnet-blazor.md +352 -0
  25. package/content/.claude/skills/stacks/dotnet-nextjs.md +402 -0
  26. package/content/.claude/skills/stacks/shopify.md +445 -0
  27. package/content/.morph/archive/.gitkeep +25 -0
  28. package/content/.morph/config/agents.json +149 -0
  29. package/content/.morph/config/config.template.json +96 -0
  30. package/content/.morph/examples/api-nextjs/README.md +241 -0
  31. package/content/.morph/examples/api-nextjs/contracts.ts +307 -0
  32. package/content/.morph/examples/api-nextjs/spec.md +399 -0
  33. package/content/.morph/examples/api-nextjs/tasks.md +168 -0
  34. package/content/.morph/examples/micro-saas/README.md +125 -0
  35. package/content/.morph/examples/micro-saas/contracts.cs +358 -0
  36. package/content/.morph/examples/micro-saas/decisions.md +246 -0
  37. package/content/.morph/examples/micro-saas/spec.md +236 -0
  38. package/content/.morph/examples/micro-saas/tasks.md +150 -0
  39. package/content/.morph/examples/multi-agent/README.md +309 -0
  40. package/content/.morph/examples/multi-agent/contracts.cs +433 -0
  41. package/content/.morph/examples/multi-agent/spec.md +479 -0
  42. package/content/.morph/examples/multi-agent/tasks.md +185 -0
  43. package/content/.morph/features/.gitkeep +25 -0
  44. package/content/.morph/project.md +159 -0
  45. package/content/.morph/specs/.gitkeep +20 -0
  46. package/content/.morph/standards/architecture.md +190 -0
  47. package/content/.morph/standards/azure.md +184 -0
  48. package/content/.morph/standards/coding.md +342 -0
  49. package/content/.morph/templates/agent.cs +172 -0
  50. package/content/.morph/templates/component.razor +239 -0
  51. package/content/.morph/templates/contracts.cs +217 -0
  52. package/content/.morph/templates/decisions.md +106 -0
  53. package/content/.morph/templates/infra/app-insights.bicep +63 -0
  54. package/content/.morph/templates/infra/container-app-env.bicep +49 -0
  55. package/content/.morph/templates/infra/container-app.bicep +156 -0
  56. package/content/.morph/templates/infra/key-vault.bicep +91 -0
  57. package/content/.morph/templates/infra/main.bicep +155 -0
  58. package/content/.morph/templates/infra/parameters.dev.json +23 -0
  59. package/content/.morph/templates/infra/parameters.prod.json +23 -0
  60. package/content/.morph/templates/infra/sql-database.bicep +103 -0
  61. package/content/.morph/templates/infra/storage.bicep +106 -0
  62. package/content/.morph/templates/integrations/asaas-client.cs +387 -0
  63. package/content/.morph/templates/integrations/asaas-webhook.cs +351 -0
  64. package/content/.morph/templates/integrations/azure-identity-config.cs +288 -0
  65. package/content/.morph/templates/integrations/clerk-config.cs +258 -0
  66. package/content/.morph/templates/job.cs +171 -0
  67. package/content/.morph/templates/migration.cs +83 -0
  68. package/content/.morph/templates/proposal.md +155 -0
  69. package/content/.morph/templates/recap.md +105 -0
  70. package/content/.morph/templates/repository.cs +141 -0
  71. package/content/.morph/templates/saas/subscription.cs +347 -0
  72. package/content/.morph/templates/saas/tenant.cs +338 -0
  73. package/content/.morph/templates/service.cs +139 -0
  74. package/content/.morph/templates/spec.md +147 -0
  75. package/content/.morph/templates/tasks.md +235 -0
  76. package/content/.morph/templates/test.cs +239 -0
  77. package/content/CLAUDE.md +318 -0
  78. package/package.json +50 -0
  79. package/src/commands/doctor.js +132 -0
  80. package/src/commands/init.js +121 -0
  81. package/src/commands/update.js +84 -0
  82. package/src/utils/file-copier.js +50 -0
  83. package/src/utils/logger.js +32 -0
@@ -0,0 +1,318 @@
1
+ # MORPH-SPEC - Instruções para Claude Code
2
+
3
+ **M**ethodical **O**rchestration for **R**eliable **P**roduction-ready **SPEC**-driven development
4
+
5
+ > by Polymorphism Tech
6
+
7
+ Você é um sistema de desenvolvimento orientado por especificações. Opera como um **hub de agentes especializados** em desenvolvimento multi-stack (.NET/Blazor, .NET/Next.js, Shopify) com Infrastructure as Code.
8
+
9
+ ---
10
+
11
+ ## REGRAS CRÍTICAS
12
+
13
+ ### NUNCA:
14
+ - Pular direto para código sem especificação
15
+ - Implementar sem aprovação do design
16
+ - Ignorar os padrões em `.morph/standards/`
17
+ - Ultrapassar limites de custo sem aprovação
18
+ - Criar recursos Azure manualmente no portal (use Bicep)
19
+ - Gerar código sem contracts definidos
20
+
21
+ ### SEMPRE:
22
+ - Seguir as 5 fases obrigatórias
23
+ - Gerar outputs em `.morph/features/{feature}/`
24
+ - Validar custos antes de propor recursos Azure
25
+ - Documentar decisões em `decisions.md`
26
+ - Checkpoint a cada 3 tasks implementadas
27
+ - Usar Infrastructure as Code (Bicep)
28
+
29
+ ---
30
+
31
+ ## WORKFLOW (5 Fases)
32
+
33
+ ```
34
+ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
35
+ │ SETUP │ ─▶ │ DESIGN │ ─▶ │ CLARIFY │ ─▶ │ TASKS │ ─▶ │IMPLEMENT │
36
+ │ │ │ │ │ │ │ │ │ │
37
+ │ Context │ │ Spec + │ │ Q&A + │ │ Break │ │ Execute │
38
+ │ + Agents │ │ Contracts│ │ Edge │ │ Down │ │ + Test │
39
+ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
40
+ ⛔ │ ⛔
41
+ User Approval │ User Approval
42
+ ```
43
+
44
+ ### Fase 1: SETUP
45
+ ```
46
+ Gatilho: Nova feature request
47
+ Comando: /morph-proposal {feature-name}
48
+
49
+ Ações:
50
+ 1. Ler `.morph/project.md` para contexto
51
+ 2. Identificar stack (Blazor, Next.js, Shopify)
52
+ 3. Analisar keywords para ativar agentes
53
+ 4. Criar `.morph/features/{feature}/`
54
+ 5. Gerar proposal.md inicial
55
+
56
+ Output: Proposta para revisão
57
+ ```
58
+
59
+ ### Fase 2: DESIGN
60
+ ```
61
+ Gatilho: Setup concluído
62
+
63
+ Ações:
64
+ 1. Expandir spec.md com detalhes técnicos
65
+ 2. Gerar contracts.cs com interfaces/DTOs
66
+ 3. Iniciar decisions.md com ADRs relevantes
67
+ 4. Estimar custos e documentar
68
+ 5. Definir infraestrutura necessária (Bicep)
69
+
70
+ Outputs:
71
+ - .morph/features/{feature}/spec.md
72
+ - .morph/features/{feature}/contracts.cs
73
+ - .morph/features/{feature}/decisions.md
74
+
75
+ ⛔ PARE e aguarde aprovação do usuário
76
+ ```
77
+
78
+ ### Fase 3: CLARIFY
79
+ ```
80
+ Gatilho: Design aprovado
81
+
82
+ Ações:
83
+ 1. Identificar ambiguidades
84
+ 2. Fazer perguntas de clarificação
85
+ 3. Documentar respostas no spec.md
86
+ 4. Validar edge cases
87
+
88
+ Output: Spec atualizado com clarificações
89
+ ```
90
+
91
+ ### Fase 4: TASKS
92
+ ```
93
+ Gatilho: Clarificações resolvidas
94
+
95
+ Ações:
96
+ 1. Quebrar spec em tasks detalhadas
97
+ 2. Definir ordem de execução
98
+ 3. Estabelecer checkpoints
99
+ 4. Mapear dependências
100
+ 5. Incluir tasks de IaC se necessário
101
+
102
+ Output: .morph/features/{feature}/tasks.md
103
+
104
+ ⛔ PARE e aguarde aprovação do task breakdown
105
+ ```
106
+
107
+ ### Fase 5: IMPLEMENT
108
+ ```
109
+ Gatilho: Tasks aprovadas
110
+ Comando: /morph-apply {feature-name}
111
+
112
+ Ações:
113
+ 1. Implementar task por task
114
+ 2. Atualizar status de cada task
115
+ 3. Checkpoint a cada 3 tasks
116
+ 4. Gerar recap.md ao final
117
+
118
+ Outputs:
119
+ - Código implementado
120
+ - Testes criados
121
+ - .morph/features/{feature}/recap.md
122
+ ```
123
+
124
+ ---
125
+
126
+ ## ESTRUTURA DO PROJETO
127
+
128
+ ```
129
+ projeto/
130
+ ├── CLAUDE.md # Este arquivo
131
+ ├── .morph/
132
+ │ ├── project.md # Contexto do projeto
133
+ │ ├── config/
134
+ │ │ ├── config.json # Configuração
135
+ │ │ └── agents.json # Definição dos agentes
136
+ │ ├── standards/
137
+ │ │ ├── coding.md # Padrões de código
138
+ │ │ ├── architecture.md # Padrões de arquitetura
139
+ │ │ └── azure.md # Padrões Azure e IaC
140
+ │ ├── templates/ # Templates para outputs
141
+ │ ├── specs/ # Specs ATIVAS (verdade atual)
142
+ │ ├── features/ # Features EM DESENVOLVIMENTO
143
+ │ │ └── {feature-name}/
144
+ │ │ ├── proposal.md
145
+ │ │ ├── spec.md
146
+ │ │ ├── tasks.md
147
+ │ │ ├── contracts.cs
148
+ │ │ ├── decisions.md
149
+ │ │ └── recap.md
150
+ │ └── archive/ # Features CONCLUÍDAS
151
+ ├── .claude/
152
+ │ ├── commands/ # Slash commands
153
+ │ │ ├── morph-proposal.md
154
+ │ │ ├── morph-apply.md
155
+ │ │ ├── morph-status.md
156
+ │ │ ├── morph-archive.md
157
+ │ │ ├── morph-infra.md # (new)
158
+ │ │ └── morph-costs.md # (new)
159
+ │ └── skills/ # Agent skills (new)
160
+ │ ├── specialists/
161
+ │ ├── integrations/
162
+ │ ├── stacks/
163
+ │ └── infra/
164
+ └── infra/ # IaC templates (new)
165
+ ├── main.bicep
166
+ └── modules/
167
+ ```
168
+
169
+ ---
170
+
171
+ ## AGENTES
172
+
173
+ ### Core Agents (Sempre Ativos)
174
+
175
+ | Agente | Responsabilidades |
176
+ |--------|-------------------|
177
+ | **Standards Architect** | Padrões em `.morph/standards/`, nomenclatura, revisão |
178
+ | **Azure Architect** | Infra Azure, Bicep IaC, Container Apps, SQL |
179
+ | **Cost Guardian** | Validar custos, alertar recursos caros, bloquear não aprovados |
180
+
181
+ ### Stack Agents (Por Stack)
182
+
183
+ | Agente | Stack | Keywords |
184
+ |--------|-------|----------|
185
+ | **Blazor Builder** | .NET + Blazor | blazor, razor, server-side |
186
+ | **NextJS Expert** | .NET + Next.js | nextjs, react, api, frontend |
187
+ | **Shopify Expert** | Shopify | shopify, hydrogen, liquid |
188
+
189
+ ### Specialist Agents (Sob Demanda)
190
+
191
+ | Agente | Keywords de Ativação |
192
+ |--------|---------------------|
193
+ | **EF Modeler** | entity, database, migration, ef core |
194
+ | **MS Agent Expert** | agent, ai, semantic kernel, llm |
195
+ | **Hangfire Orchestrator** | scheduled, job, background, cron |
196
+ | **UI/UX Designer** | wizard, dashboard, complex form, drag-drop |
197
+ | **PO/PM Advisor** | unclear, requirements, priority, ROI |
198
+
199
+ ### Integration Agents (Sob Demanda)
200
+
201
+ | Agente | Keywords | Docs |
202
+ |--------|----------|------|
203
+ | **Asaas Financial** | asaas, payment, pix, boleto | [API](https://docs.asaas.com/) |
204
+ | **Clerk Auth** | clerk, auth, login, signup | [SDK](https://clerk.com/) |
205
+ | **Azure Identity** | identity, entra, microsoft auth | [Docs](https://learn.microsoft.com/entra/) |
206
+
207
+ ### Infra Agents (Sob Demanda)
208
+
209
+ | Agente | Keywords | Docs |
210
+ |--------|----------|------|
211
+ | **Bicep Architect** | bicep, iac, infra, provision | [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/) |
212
+ | **DevOps Engineer** | pipeline, ci/cd, deploy, release | [Pipelines](https://learn.microsoft.com/azure/devops/pipelines/) |
213
+ | **Container Specialist** | docker, container, containerize | [Container Apps](https://learn.microsoft.com/azure/container-apps/) |
214
+
215
+ ---
216
+
217
+ ## LIMITES DE CUSTO
218
+
219
+ | Nível | Limite | Requisito |
220
+ |-------|--------|-----------|
221
+ | Sem aprovação | Free tier apenas | Nenhum |
222
+ | Com aprovação | Até $10/mês | Confirmação |
223
+ | Acima de $10 | Justificativa detalhada | ADR |
224
+
225
+ ---
226
+
227
+ ## INFRASTRUCTURE AS CODE
228
+
229
+ ### Princípio: Zero Portal
230
+
231
+ > NUNCA criar recursos Azure manualmente. Tudo via Bicep.
232
+
233
+ ### Estrutura IaC
234
+
235
+ ```
236
+ infra/
237
+ ├── main.bicep # Entry point
238
+ ├── parameters.dev.json # Params dev
239
+ ├── parameters.prod.json # Params prod
240
+ └── modules/
241
+ ├── container-app.bicep
242
+ ├── sql-database.bicep
243
+ ├── storage.bicep
244
+ ├── key-vault.bicep
245
+ └── app-insights.bicep
246
+ ```
247
+
248
+ ### Quando usar SDK .NET vs Bicep
249
+
250
+ | Recurso | Abordagem |
251
+ |---------|-----------|
252
+ | Infra estática (SQL, Storage, Container Apps) | Bicep |
253
+ | Recursos dinâmicos (Fabric, Azure AI) | SDK .NET |
254
+ | CI/CD | YAML + Bicep |
255
+
256
+ ---
257
+
258
+ ## COMANDOS (Slash Commands)
259
+
260
+ | Comando | Ação |
261
+ |---------|------|
262
+ | `/morph-proposal {feature}` | Criar nova proposta |
263
+ | `/morph-apply {feature}` | Implementar feature aprovada |
264
+ | `/morph-status` | Mostrar status do projeto |
265
+ | `/morph-archive {feature}` | Arquivar feature concluída |
266
+ | `/morph-infra {action}` | Gerenciar infraestrutura (new) |
267
+ | `/morph-costs` | Estimar e reportar custos (new) |
268
+
269
+ ---
270
+
271
+ ## REFERÊNCIAS
272
+
273
+ Consulte sempre:
274
+ - `.morph/project.md` - Contexto do projeto
275
+ - `.morph/standards/coding.md` - Padrões de código
276
+ - `.morph/standards/architecture.md` - Padrões de arquitetura
277
+ - `.morph/standards/azure.md` - Padrões Azure e IaC
278
+ - `.morph/templates/` - Templates para outputs
279
+ - `.morph/config/agents.json` - Definição dos agentes
280
+
281
+ ---
282
+
283
+ ## QUICK START
284
+
285
+ ```
286
+ 1. Usuário: "Quero implementar relatórios agendados"
287
+
288
+ 2. Claude: /morph-proposal scheduled-reports
289
+ → Carrega contexto
290
+ → Ativa agentes: Hangfire Orchestrator, Blazor Builder
291
+ → Cria proposta
292
+
293
+ 3. Usuário: "Aprovado"
294
+
295
+ 4. Claude: Expande spec, contracts, decisions
296
+ → Aguarda aprovação do design
297
+
298
+ 5. Usuário: "Aprovado"
299
+
300
+ 6. Claude: Quebra em tasks detalhadas
301
+ → Aguarda aprovação do breakdown
302
+
303
+ 7. Usuário: "Aprovado"
304
+
305
+ 8. Claude: /morph-apply scheduled-reports
306
+ → Implementa task por task
307
+ → Checkpoints a cada 3 tasks
308
+
309
+ 9. Usuário: "Feature concluída"
310
+
311
+ 10. Claude: /morph-archive scheduled-reports
312
+ → Move para archive
313
+ → Extrai specs
314
+ ```
315
+
316
+ ---
317
+
318
+ *MORPH-SPEC by Polymorphism Tech © 2024-2025*
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@polymorphism-tech/morph-spec",
3
+ "version": "1.0.0",
4
+ "description": "MORPH-SPEC: Methodical Orchestration for Reliable Production-ready SPEC-driven development framework for Claude Code",
5
+ "keywords": [
6
+ "claude-code",
7
+ "claude",
8
+ "ai-coding",
9
+ "spec-driven",
10
+ "dotnet",
11
+ "blazor",
12
+ "framework",
13
+ "developer-tools",
14
+ "morph",
15
+ "polymorphism"
16
+ ],
17
+ "main": "src/index.js",
18
+ "bin": {
19
+ "morph-spec": "./bin/morph-spec.js"
20
+ },
21
+ "files": [
22
+ "bin/",
23
+ "src/",
24
+ "content/"
25
+ ],
26
+ "type": "module",
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "scripts": {
31
+ "start": "node bin/morph-spec.js",
32
+ "test": "node --test"
33
+ },
34
+ "dependencies": {
35
+ "chalk": "^5.3.0",
36
+ "commander": "^12.0.0",
37
+ "fs-extra": "^11.2.0",
38
+ "ora": "^8.0.0"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/polymorphism-tech/morph-spec-framework.git"
43
+ },
44
+ "author": "Polymorphism Tech",
45
+ "license": "MIT",
46
+ "homepage": "https://github.com/polymorphism-tech/morph-spec-framework#readme",
47
+ "bugs": {
48
+ "url": "https://github.com/polymorphism-tech/morph-spec-framework/issues"
49
+ }
50
+ }
@@ -0,0 +1,132 @@
1
+ import { join } from 'path';
2
+ import chalk from 'chalk';
3
+ import { logger } from '../utils/logger.js';
4
+ import { pathExists, readJson } from '../utils/file-copier.js';
5
+
6
+ export async function doctorCommand() {
7
+ const targetPath = process.cwd();
8
+
9
+ logger.header('MORPH-SPEC Health Check');
10
+
11
+ const checks = [];
12
+ let hasErrors = false;
13
+
14
+ // Check CLAUDE.md
15
+ const claudeMd = join(targetPath, 'CLAUDE.md');
16
+ if (await pathExists(claudeMd)) {
17
+ checks.push({ name: 'CLAUDE.md', status: 'ok' });
18
+ } else {
19
+ checks.push({ name: 'CLAUDE.md', status: 'missing' });
20
+ hasErrors = true;
21
+ }
22
+
23
+ // Check .morph folder
24
+ const morphPath = join(targetPath, '.morph');
25
+ if (await pathExists(morphPath)) {
26
+ checks.push({ name: '.morph/', status: 'ok' });
27
+ } else {
28
+ checks.push({ name: '.morph/', status: 'missing' });
29
+ hasErrors = true;
30
+ }
31
+
32
+ // Check config.json
33
+ const configPath = join(morphPath, 'config', 'config.json');
34
+ if (await pathExists(configPath)) {
35
+ try {
36
+ const config = await readJson(configPath);
37
+ if (config.project?.name) {
38
+ checks.push({ name: 'config.json', status: 'ok' });
39
+ } else {
40
+ checks.push({ name: 'config.json', status: 'warn', msg: 'project.name not set' });
41
+ }
42
+ } catch {
43
+ checks.push({ name: 'config.json', status: 'error', msg: 'invalid JSON' });
44
+ hasErrors = true;
45
+ }
46
+ } else {
47
+ checks.push({ name: 'config.json', status: 'missing' });
48
+ hasErrors = true;
49
+ }
50
+
51
+ // Check agents.json
52
+ const agentsPath = join(morphPath, 'config', 'agents.json');
53
+ if (await pathExists(agentsPath)) {
54
+ checks.push({ name: 'agents.json', status: 'ok' });
55
+ } else {
56
+ checks.push({ name: 'agents.json', status: 'missing' });
57
+ hasErrors = true;
58
+ }
59
+
60
+ // Check standards
61
+ const standardsPath = join(morphPath, 'standards');
62
+ if (await pathExists(standardsPath)) {
63
+ const codingStd = join(standardsPath, 'coding.md');
64
+ const archStd = join(standardsPath, 'architecture.md');
65
+ const azureStd = join(standardsPath, 'azure.md');
66
+
67
+ const hasAll = await Promise.all([
68
+ pathExists(codingStd),
69
+ pathExists(archStd),
70
+ pathExists(azureStd)
71
+ ]).then(results => results.every(Boolean));
72
+
73
+ if (hasAll) {
74
+ checks.push({ name: 'standards/', status: 'ok' });
75
+ } else {
76
+ checks.push({ name: 'standards/', status: 'warn', msg: 'some files missing' });
77
+ }
78
+ } else {
79
+ checks.push({ name: 'standards/', status: 'missing' });
80
+ hasErrors = true;
81
+ }
82
+
83
+ // Check templates
84
+ const templatesPath = join(morphPath, 'templates');
85
+ if (await pathExists(templatesPath)) {
86
+ checks.push({ name: 'templates/', status: 'ok' });
87
+ } else {
88
+ checks.push({ name: 'templates/', status: 'missing' });
89
+ hasErrors = true;
90
+ }
91
+
92
+ // Check .claude folder
93
+ const claudePath = join(targetPath, '.claude');
94
+ if (await pathExists(claudePath)) {
95
+ const commandsPath = join(claudePath, 'commands');
96
+ const skillsPath = join(claudePath, 'skills');
97
+
98
+ const hasCommands = await pathExists(commandsPath);
99
+ const hasSkills = await pathExists(skillsPath);
100
+
101
+ if (hasCommands && hasSkills) {
102
+ checks.push({ name: '.claude/', status: 'ok' });
103
+ } else {
104
+ checks.push({ name: '.claude/', status: 'warn', msg: 'incomplete structure' });
105
+ }
106
+ } else {
107
+ checks.push({ name: '.claude/', status: 'missing' });
108
+ hasErrors = true;
109
+ }
110
+
111
+ // Display results
112
+ for (const check of checks) {
113
+ if (check.status === 'ok') {
114
+ console.log(chalk.green(` ✓ ${check.name}`));
115
+ } else if (check.status === 'warn') {
116
+ console.log(chalk.yellow(` ⚠ ${check.name}`) + chalk.gray(` (${check.msg})`));
117
+ } else if (check.status === 'missing') {
118
+ console.log(chalk.red(` ✗ ${check.name}`) + chalk.gray(' (missing)'));
119
+ } else if (check.status === 'error') {
120
+ console.log(chalk.red(` ✗ ${check.name}`) + chalk.gray(` (${check.msg})`));
121
+ }
122
+ }
123
+
124
+ logger.blank();
125
+
126
+ if (hasErrors) {
127
+ logger.error('Some checks failed. Run "morph-spec init --force" to fix.');
128
+ process.exit(1);
129
+ } else {
130
+ logger.success('All checks passed!');
131
+ }
132
+ }
@@ -0,0 +1,121 @@
1
+ import { join } from 'path';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { logger } from '../utils/logger.js';
5
+ import {
6
+ getContentDir,
7
+ copyDirectory,
8
+ copyFile,
9
+ pathExists,
10
+ readJson,
11
+ writeJson,
12
+ ensureDir,
13
+ writeFile
14
+ } from '../utils/file-copier.js';
15
+
16
+ export async function initCommand(options) {
17
+ const targetPath = options.path || process.cwd();
18
+ const contentDir = getContentDir();
19
+
20
+ logger.header('MORPH-SPEC Framework Installation');
21
+ logger.dim(`Target: ${targetPath}`);
22
+ logger.blank();
23
+
24
+ // Check if already initialized
25
+ const morphPath = join(targetPath, '.morph');
26
+ if (await pathExists(morphPath)) {
27
+ if (!options.force) {
28
+ logger.warn('MORPH already initialized in this directory.');
29
+ logger.dim('Use --force to overwrite existing installation.');
30
+ process.exit(1);
31
+ }
32
+ logger.warn('Overwriting existing MORPH installation...');
33
+ }
34
+
35
+ const spinner = ora('Installing MORPH-SPEC...').start();
36
+
37
+ try {
38
+ // 1. Copy CLAUDE.md
39
+ spinner.text = 'Copying CLAUDE.md...';
40
+ const claudeMdSrc = join(contentDir, 'CLAUDE.md');
41
+ const claudeMdDest = join(targetPath, 'CLAUDE.md');
42
+
43
+ // Backup existing CLAUDE.md if not from MORPH
44
+ if (await pathExists(claudeMdDest)) {
45
+ const existingContent = await import('fs-extra').then(fs => fs.readFile(claudeMdDest, 'utf8'));
46
+ if (!existingContent.includes('MORPH-SPEC')) {
47
+ await copyFile(claudeMdDest, `${claudeMdDest}.backup`);
48
+ logger.dim('Backed up existing CLAUDE.md');
49
+ }
50
+ }
51
+ await copyFile(claudeMdSrc, claudeMdDest);
52
+
53
+ // 2. Copy .morph folder
54
+ spinner.text = 'Copying .morph/...';
55
+ const morphSrc = join(contentDir, '.morph');
56
+ await copyDirectory(morphSrc, morphPath);
57
+
58
+ // 3. Create empty directories with .gitkeep
59
+ for (const dir of ['specs', 'features', 'archive']) {
60
+ const dirPath = join(morphPath, dir);
61
+ await ensureDir(dirPath);
62
+ const gitkeepPath = join(dirPath, '.gitkeep');
63
+ if (!(await pathExists(gitkeepPath))) {
64
+ await writeFile(gitkeepPath, '');
65
+ }
66
+ }
67
+
68
+ // 4. Create config.json from template
69
+ spinner.text = 'Generating config.json...';
70
+ const configPath = join(morphPath, 'config', 'config.json');
71
+ const templatePath = join(morphPath, 'config', 'config.template.json');
72
+
73
+ if (await pathExists(templatePath)) {
74
+ const config = await readJson(templatePath);
75
+
76
+ // Try to detect project name from directory or .sln
77
+ const dirName = targetPath.split(/[\\/]/).pop();
78
+ config.project = config.project || {};
79
+ config.project.name = dirName;
80
+ config.project.description = `Projeto ${dirName} gerenciado pelo MORPH-SPEC Framework`;
81
+
82
+ await writeJson(configPath, config);
83
+ }
84
+
85
+ // 5. Copy .claude folder
86
+ spinner.text = 'Copying .claude/...';
87
+ const claudeSrc = join(contentDir, '.claude');
88
+ const claudeDest = join(targetPath, '.claude');
89
+
90
+ if (await pathExists(claudeSrc)) {
91
+ await copyDirectory(claudeSrc, claudeDest);
92
+ }
93
+
94
+ spinner.succeed('MORPH-SPEC installed successfully!');
95
+
96
+ // Show next steps
97
+ logger.blank();
98
+ logger.header('Next Steps');
99
+
100
+ logger.step(1, 'Edit .morph/project.md with your project details');
101
+ logger.step(2, 'Review .morph/config/config.json');
102
+ logger.step(3, 'Open project in VS Code with Claude Code');
103
+ logger.step(4, 'Start your first feature:');
104
+ logger.blank();
105
+ logger.box([
106
+ '/morph-proposal [feature-name]'
107
+ ]);
108
+ logger.blank();
109
+
110
+ logger.info('Documentation:');
111
+ logger.dim(`CLAUDE.md → ${join(targetPath, 'CLAUDE.md')}`);
112
+ logger.dim(`Standards → ${join(targetPath, '.morph', 'standards')}`);
113
+ logger.dim(`Templates → ${join(targetPath, '.morph', 'templates')}`);
114
+ logger.blank();
115
+
116
+ } catch (error) {
117
+ spinner.fail('Installation failed');
118
+ logger.error(error.message);
119
+ process.exit(1);
120
+ }
121
+ }
@@ -0,0 +1,84 @@
1
+ import { join } from 'path';
2
+ import ora from 'ora';
3
+ import { logger } from '../utils/logger.js';
4
+ import {
5
+ getContentDir,
6
+ copyDirectory,
7
+ pathExists
8
+ } from '../utils/file-copier.js';
9
+
10
+ export async function updateCommand(options) {
11
+ const targetPath = process.cwd();
12
+ const contentDir = getContentDir();
13
+ const morphPath = join(targetPath, '.morph');
14
+
15
+ logger.header('MORPH-SPEC Update');
16
+
17
+ // Check if MORPH is initialized
18
+ if (!(await pathExists(morphPath))) {
19
+ logger.error('MORPH not initialized in this directory.');
20
+ logger.dim('Run "morph-spec init" first.');
21
+ process.exit(1);
22
+ }
23
+
24
+ const spinner = ora('Updating MORPH-SPEC...').start();
25
+
26
+ try {
27
+ const updateTemplates = !options.standards || options.templates;
28
+ const updateStandards = !options.templates || options.standards;
29
+
30
+ // Update templates
31
+ if (updateTemplates) {
32
+ spinner.text = 'Updating templates...';
33
+ const templatesSrc = join(contentDir, '.morph', 'templates');
34
+ const templatesDest = join(morphPath, 'templates');
35
+ await copyDirectory(templatesSrc, templatesDest);
36
+ logger.dim('Updated .morph/templates/');
37
+ }
38
+
39
+ // Update standards
40
+ if (updateStandards) {
41
+ spinner.text = 'Updating standards...';
42
+ const standardsSrc = join(contentDir, '.morph', 'standards');
43
+ const standardsDest = join(morphPath, 'standards');
44
+ await copyDirectory(standardsSrc, standardsDest);
45
+ logger.dim('Updated .morph/standards/');
46
+ }
47
+
48
+ // Update agents.json
49
+ spinner.text = 'Updating agents configuration...';
50
+ const agentsSrc = join(contentDir, '.morph', 'config', 'agents.json');
51
+ const agentsDest = join(morphPath, 'config', 'agents.json');
52
+ if (await pathExists(agentsSrc)) {
53
+ await copyDirectory(agentsSrc, agentsDest);
54
+ logger.dim('Updated .morph/config/agents.json');
55
+ }
56
+
57
+ // Update .claude commands and skills
58
+ spinner.text = 'Updating Claude commands and skills...';
59
+ const claudeSrc = join(contentDir, '.claude');
60
+ const claudeDest = join(targetPath, '.claude');
61
+ if (await pathExists(claudeSrc)) {
62
+ await copyDirectory(claudeSrc, claudeDest);
63
+ logger.dim('Updated .claude/commands/ and .claude/skills/');
64
+ }
65
+
66
+ // Update CLAUDE.md
67
+ spinner.text = 'Updating CLAUDE.md...';
68
+ const claudeMdSrc = join(contentDir, 'CLAUDE.md');
69
+ const claudeMdDest = join(targetPath, 'CLAUDE.md');
70
+ await copyDirectory(claudeMdSrc, claudeMdDest);
71
+ logger.dim('Updated CLAUDE.md');
72
+
73
+ spinner.succeed('MORPH-SPEC updated successfully!');
74
+ logger.blank();
75
+ logger.info('Your config.json was preserved.');
76
+ logger.dim('Review the updated files for any new features.');
77
+ logger.blank();
78
+
79
+ } catch (error) {
80
+ spinner.fail('Update failed');
81
+ logger.error(error.message);
82
+ process.exit(1);
83
+ }
84
+ }