@polymorphism-tech/morph-spec 1.0.4 → 2.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.
- 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
package/LICENSE
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2025 Polymorphism Tech
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
MORPH-SPEC Framework - Proprietary Software License
|
|
7
|
+
|
|
8
|
+
1. GRANT OF LICENSE
|
|
9
|
+
|
|
10
|
+
Subject to the terms and conditions of this License, Polymorphism Tech ("Licensor")
|
|
11
|
+
grants you a limited, non-exclusive, non-transferable license to:
|
|
12
|
+
|
|
13
|
+
a) Install and use the MORPH-SPEC CLI tool for personal or commercial projects
|
|
14
|
+
b) Use the generated templates and code in your own projects
|
|
15
|
+
c) Modify generated code for your specific use cases
|
|
16
|
+
|
|
17
|
+
2. RESTRICTIONS
|
|
18
|
+
|
|
19
|
+
You may NOT:
|
|
20
|
+
|
|
21
|
+
a) Redistribute, sell, lease, or sublicense the MORPH-SPEC framework itself
|
|
22
|
+
b) Modify, decompile, reverse engineer, or create derivative works of the framework
|
|
23
|
+
c) Remove or modify any copyright notices or proprietary markings
|
|
24
|
+
d) Use the framework to create competing products or services
|
|
25
|
+
e) Publicly fork or redistribute the source code
|
|
26
|
+
f) Share access credentials to private repositories
|
|
27
|
+
|
|
28
|
+
3. OWNERSHIP
|
|
29
|
+
|
|
30
|
+
The MORPH-SPEC framework, including all code, documentation, templates, and
|
|
31
|
+
associated materials, remains the exclusive property of Polymorphism Tech.
|
|
32
|
+
|
|
33
|
+
4. GENERATED CODE
|
|
34
|
+
|
|
35
|
+
Code and projects generated using MORPH-SPEC are yours to use, modify, and
|
|
36
|
+
distribute as you see fit, including commercial use.
|
|
37
|
+
|
|
38
|
+
5. SUPPORT AND UPDATES
|
|
39
|
+
|
|
40
|
+
- CLI tool updates are provided via npm registry
|
|
41
|
+
- Support is available at: support@polymorphism.tech
|
|
42
|
+
- Documentation updates are included with each release
|
|
43
|
+
|
|
44
|
+
6. WARRANTY DISCLAIMER
|
|
45
|
+
|
|
46
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
47
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
48
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
49
|
+
|
|
50
|
+
7. LIMITATION OF LIABILITY
|
|
51
|
+
|
|
52
|
+
IN NO EVENT SHALL POLYMORPHISM TECH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
53
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
54
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
55
|
+
SOFTWARE.
|
|
56
|
+
|
|
57
|
+
8. TERMINATION
|
|
58
|
+
|
|
59
|
+
This license is effective until terminated. Your rights under this license will
|
|
60
|
+
terminate automatically without notice if you fail to comply with any term of
|
|
61
|
+
this license.
|
|
62
|
+
|
|
63
|
+
9. CONTACT
|
|
64
|
+
|
|
65
|
+
For licensing inquiries, custom licenses, or commercial support:
|
|
66
|
+
Email: contact@polymorphism.com.br
|
|
67
|
+
Website: https://polymorphism.com.br
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
MORPH-SPEC v2.0.0
|
|
72
|
+
by Polymorphism Tech
|
package/README.md
CHANGED
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
<a href="docs/">Documentação</a>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
|
+
<p align="center">
|
|
23
|
+
<strong>📚 Guias de Uso:</strong>
|
|
24
|
+
<a href="QUICKSTART.md">Quick Start</a> •
|
|
25
|
+
<a href="CHEATSHEET.md">Cheat Sheet</a> •
|
|
26
|
+
<a href="docs/README.md">API Docs</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
22
29
|
---
|
|
23
30
|
|
|
24
31
|
## O que é MORPH-SPEC?
|
|
@@ -86,8 +93,10 @@ npx @polymorphism-tech/morph-spec init
|
|
|
86
93
|
|---------|-----------|
|
|
87
94
|
| `morph-spec init` | Inicializa MORPH no diretório atual |
|
|
88
95
|
| `morph-spec init --force` | Sobrescreve instalação existente |
|
|
89
|
-
| `morph-spec update` | Atualiza
|
|
90
|
-
| `morph-spec
|
|
96
|
+
| `morph-spec update` | Atualiza projeto para versão mais recente |
|
|
97
|
+
| `morph-spec update --templates` | Atualiza apenas templates |
|
|
98
|
+
| `morph-spec update --standards` | Atualiza apenas standards |
|
|
99
|
+
| `morph-spec doctor` | Verifica saúde e versões da instalação |
|
|
91
100
|
|
|
92
101
|
### Verificar Instalação
|
|
93
102
|
|
|
@@ -95,6 +104,11 @@ npx @polymorphism-tech/morph-spec init
|
|
|
95
104
|
morph-spec doctor
|
|
96
105
|
```
|
|
97
106
|
|
|
107
|
+
O comando `doctor` verifica:
|
|
108
|
+
- ✓ Versão do CLI (se está atualizada)
|
|
109
|
+
- ✓ Versão do MORPH no projeto
|
|
110
|
+
- ✓ Estrutura de arquivos e configurações
|
|
111
|
+
|
|
98
112
|
Ou abra seu projeto no Claude Code e execute:
|
|
99
113
|
```
|
|
100
114
|
/morph-status
|
|
@@ -102,6 +116,48 @@ Ou abra seu projeto no Claude Code e execute:
|
|
|
102
116
|
|
|
103
117
|
---
|
|
104
118
|
|
|
119
|
+
## Mantendo Atualizado
|
|
120
|
+
|
|
121
|
+
### 1. Verificar se há atualizações
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
morph-spec doctor
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Isso mostrará se há versões mais recentes disponíveis.
|
|
128
|
+
|
|
129
|
+
### 2. Atualizar para a versão mais recente
|
|
130
|
+
|
|
131
|
+
**Instalação Global:**
|
|
132
|
+
```bash
|
|
133
|
+
# Primeiro, atualize o CLI
|
|
134
|
+
npm install -g @polymorphism-tech/morph-spec@latest
|
|
135
|
+
|
|
136
|
+
# Depois, atualize seu projeto
|
|
137
|
+
cd /caminho/do/seu/projeto
|
|
138
|
+
morph-spec update
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Usando npx (Recomendado - sempre pega a versão mais recente):**
|
|
142
|
+
```bash
|
|
143
|
+
cd /caminho/do/seu/projeto
|
|
144
|
+
npx @polymorphism-tech/morph-spec@latest update
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 3. O que é atualizado?
|
|
148
|
+
|
|
149
|
+
O comando `update` sincroniza:
|
|
150
|
+
- ✅ Templates (`.morph/templates/`)
|
|
151
|
+
- ✅ Standards (`.morph/standards/`)
|
|
152
|
+
- ✅ Agentes (`.morph/config/agents.json`)
|
|
153
|
+
- ✅ Comandos Claude (`.claude/commands/`)
|
|
154
|
+
- ✅ Skills (`.claude/skills/`)
|
|
155
|
+
- ✅ Instruções (CLAUDE.md)
|
|
156
|
+
|
|
157
|
+
**Importante:** Seu `config.json` é preservado!
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
105
161
|
## Começando
|
|
106
162
|
|
|
107
163
|
### 1. Criar uma Proposta
|
|
@@ -286,18 +342,45 @@ O MORPH segue a filosofia **"Free tier first"**:
|
|
|
286
342
|
|
|
287
343
|
---
|
|
288
344
|
|
|
289
|
-
## Licença
|
|
345
|
+
## 📄 Licença e Distribuição
|
|
346
|
+
|
|
347
|
+
**Repositório:** Privado (código fonte protegido)
|
|
348
|
+
**Package npm:** Público e gratuito via `@polymorphism-tech/morph-spec`
|
|
349
|
+
|
|
350
|
+
### Licença Proprietária
|
|
351
|
+
|
|
352
|
+
O MORPH-SPEC framework é software proprietário da Polymorphism Tech. Veja [LICENSE](LICENSE) para detalhes.
|
|
353
|
+
|
|
354
|
+
**Você PODE:**
|
|
355
|
+
- ✅ Usar o CLI tool gratuitamente
|
|
356
|
+
- ✅ Gerar projetos para uso pessoal ou comercial
|
|
357
|
+
- ✅ Modificar código gerado pelos templates
|
|
358
|
+
- ✅ Distribuir seus projetos criados com MORPH-SPEC
|
|
359
|
+
|
|
360
|
+
**Você NÃO PODE:**
|
|
361
|
+
- ❌ Redistribuir ou vender o framework
|
|
362
|
+
- ❌ Criar produtos derivados competidores
|
|
363
|
+
- ❌ Modificar ou fazer engenharia reversa do framework
|
|
364
|
+
- ❌ Remover avisos de copyright
|
|
365
|
+
|
|
366
|
+
### Código Gerado
|
|
367
|
+
|
|
368
|
+
Todo código gerado usando MORPH-SPEC é **100% seu** para usar como quiser, incluindo uso comercial.
|
|
369
|
+
|
|
370
|
+
### Suporte
|
|
290
371
|
|
|
291
|
-
|
|
372
|
+
- 📧 Email: support@polymorphism.com.br
|
|
373
|
+
- 🌐 Website: https://polymorphism.com.br
|
|
374
|
+
- 📦 npm: [@polymorphism-tech/morph-spec](https://www.npmjs.com/package/@polymorphism-tech/morph-spec)
|
|
292
375
|
|
|
293
376
|
---
|
|
294
377
|
|
|
295
378
|
## Links
|
|
296
379
|
|
|
297
|
-
- 📦 [npm](https://www.npmjs.com/package/@polymorphism-tech/morph-spec)
|
|
380
|
+
- 📦 [npm Package](https://www.npmjs.com/package/@polymorphism-tech/morph-spec)
|
|
298
381
|
- 📚 [Documentação](docs/)
|
|
299
382
|
- 💡 [Exemplos](content/.morph/examples/)
|
|
300
|
-
-
|
|
383
|
+
- 🌐 [Polymorphism Tech](https://polymorphism.com.br)
|
|
301
384
|
|
|
302
385
|
---
|
|
303
386
|
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MORPH-SPEC Agent Detection CLI
|
|
5
|
+
*
|
|
6
|
+
* Detecta automaticamente quais agentes devem ser ativados baseado
|
|
7
|
+
* em keywords no input do usuário.
|
|
8
|
+
*
|
|
9
|
+
* Uso:
|
|
10
|
+
* node bin/detect-agents.js "implementar jobs agendados"
|
|
11
|
+
* node bin/detect-agents.js --verbose "criar dashboard com charts"
|
|
12
|
+
* node bin/detect-agents.js --json "adicionar background tasks"
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFileSync } from 'fs';
|
|
16
|
+
import { join, dirname } from 'path';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const AGENTS_CONFIG_PATH = join(__dirname, '../content/.morph/config/agents.json');
|
|
21
|
+
|
|
22
|
+
// Cores para output no terminal
|
|
23
|
+
const colors = {
|
|
24
|
+
reset: '\x1b[0m',
|
|
25
|
+
bright: '\x1b[1m',
|
|
26
|
+
green: '\x1b[32m',
|
|
27
|
+
yellow: '\x1b[33m',
|
|
28
|
+
blue: '\x1b[34m',
|
|
29
|
+
cyan: '\x1b[36m',
|
|
30
|
+
gray: '\x1b[90m'
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function log(message, color = 'reset') {
|
|
34
|
+
console.log(`${colors[color]}${message}${colors.reset}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Carrega configuração de agentes
|
|
39
|
+
* @returns {Object} Configuração de agentes
|
|
40
|
+
*/
|
|
41
|
+
function loadAgentsConfig() {
|
|
42
|
+
try {
|
|
43
|
+
const content = readFileSync(AGENTS_CONFIG_PATH, 'utf8');
|
|
44
|
+
return JSON.parse(content);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error(`ERROR: Failed to load agents config: ${err.message}`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Detecta agentes baseado em user input
|
|
53
|
+
* @param {string} userInput - Input do usuário
|
|
54
|
+
* @param {Object} config - Configuração de agentes
|
|
55
|
+
* @returns {Object} Resultado da detecção { core, specialists, all, matches }
|
|
56
|
+
*/
|
|
57
|
+
function detectAgents(userInput, config) {
|
|
58
|
+
const input = userInput.toLowerCase();
|
|
59
|
+
const coreAgents = config.agents.core || [];
|
|
60
|
+
const specialists = config.agents.specialists || [];
|
|
61
|
+
|
|
62
|
+
// Core agents sempre ativos
|
|
63
|
+
const coreIds = coreAgents.map(a => a.id);
|
|
64
|
+
|
|
65
|
+
// Detectar specialists por keyword matching
|
|
66
|
+
const specialistMatches = [];
|
|
67
|
+
|
|
68
|
+
for (const agent of specialists) {
|
|
69
|
+
const keywords = agent.autoActivation?.keywords || [];
|
|
70
|
+
const matchedKeywords = [];
|
|
71
|
+
|
|
72
|
+
for (const keyword of keywords) {
|
|
73
|
+
if (input.includes(keyword.toLowerCase())) {
|
|
74
|
+
matchedKeywords.push(keyword);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (matchedKeywords.length > 0) {
|
|
79
|
+
specialistMatches.push({
|
|
80
|
+
id: agent.id,
|
|
81
|
+
name: agent.name,
|
|
82
|
+
emoji: agent.emoji,
|
|
83
|
+
matchedKeywords: matchedKeywords,
|
|
84
|
+
matchCount: matchedKeywords.length
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Ordenar por número de matches (mais relevante primeiro)
|
|
90
|
+
specialistMatches.sort((a, b) => b.matchCount - a.matchCount);
|
|
91
|
+
|
|
92
|
+
const specialistIds = specialistMatches.map(m => m.id);
|
|
93
|
+
const allIds = [...new Set([...coreIds, ...specialistIds])];
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
core: coreIds,
|
|
97
|
+
specialists: specialistIds,
|
|
98
|
+
all: allIds,
|
|
99
|
+
matches: specialistMatches,
|
|
100
|
+
input: userInput
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Formata output em modo verbose
|
|
106
|
+
* @param {Object} result - Resultado da detecção
|
|
107
|
+
*/
|
|
108
|
+
function formatVerbose(result) {
|
|
109
|
+
log('\n╔════════════════════════════════════════════════════════════════╗', 'cyan');
|
|
110
|
+
log('║ AGENT DETECTION RESULT ║', 'cyan');
|
|
111
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
112
|
+
log(`║ Input: ${result.input.substring(0, 54).padEnd(54)} ║`, 'bright');
|
|
113
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
114
|
+
log('║ CORE AGENTS (always active) ║', 'cyan');
|
|
115
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
116
|
+
|
|
117
|
+
result.core.forEach(id => {
|
|
118
|
+
log(`║ ✓ ${id.padEnd(58)}║`, 'green');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
if (result.specialists.length > 0) {
|
|
122
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
123
|
+
log('║ SPECIALIST AGENTS (keyword matched) ║', 'cyan');
|
|
124
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
125
|
+
|
|
126
|
+
result.matches.forEach(match => {
|
|
127
|
+
const line = `${match.emoji} ${match.name} (${match.matchCount} matches)`;
|
|
128
|
+
log(`║ ${line.padEnd(61)}║`, 'yellow');
|
|
129
|
+
const keywords = match.matchedKeywords.join(', ');
|
|
130
|
+
const keywordLine = `Keywords: ${keywords}`;
|
|
131
|
+
// Quebrar em múltiplas linhas se necessário
|
|
132
|
+
if (keywordLine.length > 58) {
|
|
133
|
+
const chunks = keywordLine.match(/.{1,58}/g) || [];
|
|
134
|
+
chunks.forEach((chunk, i) => {
|
|
135
|
+
log(`║ ${chunk.padEnd(59)}║`, 'gray');
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
log(`║ ${keywordLine.padEnd(59)}║`, 'gray');
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
143
|
+
log('║ No specialist agents matched ║', 'gray');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
log('╠════════════════════════════════════════════════════════════════╣', 'cyan');
|
|
147
|
+
log(`║ TOTAL: ${result.all.length} agents activated ║`, 'bright');
|
|
148
|
+
log('╚════════════════════════════════════════════════════════════════╝\n', 'cyan');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Formata output em modo simples (apenas IDs)
|
|
153
|
+
* @param {Object} result - Resultado da detecção
|
|
154
|
+
*/
|
|
155
|
+
function formatSimple(result) {
|
|
156
|
+
result.all.forEach(id => console.log(id));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Formata output em modo JSON
|
|
161
|
+
* @param {Object} result - Resultado da detecção
|
|
162
|
+
*/
|
|
163
|
+
function formatJSON(result) {
|
|
164
|
+
console.log(JSON.stringify(result, null, 2));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// MAIN
|
|
169
|
+
// ============================================================================
|
|
170
|
+
|
|
171
|
+
function main() {
|
|
172
|
+
const args = process.argv.slice(2);
|
|
173
|
+
|
|
174
|
+
// Parse flags
|
|
175
|
+
const hasVerbose = args.includes('--verbose') || args.includes('-v');
|
|
176
|
+
const hasJSON = args.includes('--json') || args.includes('-j');
|
|
177
|
+
const hasHelp = args.includes('--help') || args.includes('-h');
|
|
178
|
+
const hasIdsOnly = args.includes('--ids-only') || args.includes('-i');
|
|
179
|
+
|
|
180
|
+
// Remove flags para pegar user input
|
|
181
|
+
const userInput = args
|
|
182
|
+
.filter(arg => !arg.startsWith('--') && !arg.startsWith('-'))
|
|
183
|
+
.join(' ');
|
|
184
|
+
|
|
185
|
+
if (hasHelp || args.length === 0) {
|
|
186
|
+
log('\nMORPH-SPEC Agent Detection CLI', 'bright');
|
|
187
|
+
log('\nUsage:', 'cyan');
|
|
188
|
+
log(' node bin/detect-agents.js [options] "<user input>"', 'gray');
|
|
189
|
+
log('\nOptions:', 'cyan');
|
|
190
|
+
log(' -v, --verbose Show detailed detection results', 'gray');
|
|
191
|
+
log(' -j, --json Output full result as JSON', 'gray');
|
|
192
|
+
log(' -i, --ids-only Output only agent IDs (one per line)', 'gray');
|
|
193
|
+
log(' -h, --help Show this help', 'gray');
|
|
194
|
+
log('\nExamples:', 'cyan');
|
|
195
|
+
log(' node bin/detect-agents.js "criar dashboard com charts"', 'gray');
|
|
196
|
+
log(' node bin/detect-agents.js --verbose "implementar jobs agendados"', 'gray');
|
|
197
|
+
log(' node bin/detect-agents.js --json "adicionar RAG pipeline"', 'gray');
|
|
198
|
+
log(' node bin/detect-agents.js --ids-only "background tasks"\n', 'gray');
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!userInput) {
|
|
203
|
+
console.error('ERROR: User input is required');
|
|
204
|
+
console.error('Run with --help for usage information');
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Carregar config e detectar agentes
|
|
209
|
+
const config = loadAgentsConfig();
|
|
210
|
+
const result = detectAgents(userInput, config);
|
|
211
|
+
|
|
212
|
+
// Formatar output
|
|
213
|
+
if (hasJSON) {
|
|
214
|
+
formatJSON(result);
|
|
215
|
+
} else if (hasVerbose) {
|
|
216
|
+
formatVerbose(result);
|
|
217
|
+
} else if (hasIdsOnly) {
|
|
218
|
+
formatSimple(result);
|
|
219
|
+
} else {
|
|
220
|
+
// Default: JSON compact (só all array)
|
|
221
|
+
console.log(JSON.stringify(result.all));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
main();
|
package/bin/morph-spec.js
CHANGED
|
@@ -9,6 +9,15 @@ import { readFileSync } from 'fs';
|
|
|
9
9
|
import { initCommand } from '../src/commands/init.js';
|
|
10
10
|
import { updateCommand } from '../src/commands/update.js';
|
|
11
11
|
import { doctorCommand } from '../src/commands/doctor.js';
|
|
12
|
+
import { detectCommand } from '../src/commands/detect.js';
|
|
13
|
+
import { syncCommand } from '../src/commands/sync.js';
|
|
14
|
+
import { createStoryCommand } from '../src/commands/create-story.js';
|
|
15
|
+
import { shardSpecCommand } from '../src/commands/shard-spec.js';
|
|
16
|
+
import { sprintStatusCommand } from '../src/commands/sprint-status.js';
|
|
17
|
+
import { stateCommand } from '../src/commands/state.js';
|
|
18
|
+
import { costCommand } from '../src/commands/cost.js';
|
|
19
|
+
import { generateDesignSystemCommand } from '../src/commands/generate.js';
|
|
20
|
+
import { updateResourcePricing, showPricing, validatePricing } from '../src/commands/update-pricing.js';
|
|
12
21
|
|
|
13
22
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
23
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
@@ -50,4 +59,115 @@ program
|
|
|
50
59
|
.description('Check MORPH installation health')
|
|
51
60
|
.action(doctorCommand);
|
|
52
61
|
|
|
62
|
+
program
|
|
63
|
+
.command('detect')
|
|
64
|
+
.description('Detect project stack, architecture, and patterns')
|
|
65
|
+
.option('-p, --path <path>', 'Project path (default: current directory)')
|
|
66
|
+
.option('-v, --verbose', 'Show detailed detection results')
|
|
67
|
+
.option('--no-save', 'Do not save results to .morph/project/')
|
|
68
|
+
.action(detectCommand);
|
|
69
|
+
|
|
70
|
+
program
|
|
71
|
+
.command('sync')
|
|
72
|
+
.description('Sync standards from feature decisions')
|
|
73
|
+
.option('-p, --path <path>', 'Project path (default: current directory)')
|
|
74
|
+
.option('--dry-run', 'Show what would be synced without updating files')
|
|
75
|
+
.action(syncCommand);
|
|
76
|
+
|
|
77
|
+
// Story-driven development commands
|
|
78
|
+
const storyCommand = program
|
|
79
|
+
.command('story')
|
|
80
|
+
.description('Story-driven development commands');
|
|
81
|
+
|
|
82
|
+
storyCommand
|
|
83
|
+
.command('create <feature> <story-id>')
|
|
84
|
+
.description('Create a new story with auto-injected Dev Notes')
|
|
85
|
+
.option('--title <title>', 'Story title')
|
|
86
|
+
.option('--epic <epic>', 'Epic name')
|
|
87
|
+
.option('--context <context>', 'Story context')
|
|
88
|
+
.option('--tasks <tasks>', 'Comma-separated tasks')
|
|
89
|
+
.option('--dry-run', 'Preview without writing file')
|
|
90
|
+
.action(createStoryCommand);
|
|
91
|
+
|
|
92
|
+
storyCommand
|
|
93
|
+
.command('shard <feature>')
|
|
94
|
+
.description('Shard spec.md into manageable chunks (90% token savings)')
|
|
95
|
+
.option('--dry-run', 'Preview shards without writing files')
|
|
96
|
+
.option('--verbose', 'Show detailed shard info')
|
|
97
|
+
.action(shardSpecCommand);
|
|
98
|
+
|
|
99
|
+
storyCommand
|
|
100
|
+
.command('status <feature> [action] [story-id]')
|
|
101
|
+
.description('Manage sprint status (show | start | qa | done | next)')
|
|
102
|
+
.action(sprintStatusCommand);
|
|
103
|
+
|
|
104
|
+
// State management commands
|
|
105
|
+
program
|
|
106
|
+
.command('state <action> [args...]')
|
|
107
|
+
.description('Manage state.json (init | get | set | checkpoint | list | add-agent | remove-agent | mark-output)')
|
|
108
|
+
.option('--force', 'Force overwrite (init command)')
|
|
109
|
+
.option('--project <name>', 'Project name (init command)')
|
|
110
|
+
.option('--type <type>', 'Project type (init command)')
|
|
111
|
+
.option('--json', 'Output as JSON (get command)')
|
|
112
|
+
.action((action, args, options) => stateCommand(action, args, options));
|
|
113
|
+
|
|
114
|
+
// Cost calculation command
|
|
115
|
+
program
|
|
116
|
+
.command('cost <bicep-files>')
|
|
117
|
+
.description('Calculate Azure infrastructure costs from Bicep files')
|
|
118
|
+
.option('--config <path>', 'Custom config path')
|
|
119
|
+
.option('--verbose', 'Show detailed breakdown')
|
|
120
|
+
.option('--json', 'Output as JSON')
|
|
121
|
+
.option('--strict', 'Exit with error if cost exceeds ADR threshold')
|
|
122
|
+
.action(costCommand);
|
|
123
|
+
|
|
124
|
+
// Pricing management commands
|
|
125
|
+
const pricingCommand = program
|
|
126
|
+
.command('pricing')
|
|
127
|
+
.description('Manage Azure pricing table');
|
|
128
|
+
|
|
129
|
+
pricingCommand
|
|
130
|
+
.command('show [resource-type]')
|
|
131
|
+
.description('Show current pricing (all or specific resource type)')
|
|
132
|
+
.option('--json', 'Output as JSON')
|
|
133
|
+
.action((resourceType, options) => showPricing({ resourceType, format: options.json ? 'json' : 'table' }));
|
|
134
|
+
|
|
135
|
+
pricingCommand
|
|
136
|
+
.command('update <resource-type> <sku> <price>')
|
|
137
|
+
.description('Update pricing for a specific SKU')
|
|
138
|
+
.option('--dry-run', 'Preview without saving')
|
|
139
|
+
.option('--no-validate', 'Skip validation')
|
|
140
|
+
.action((resourceType, sku, price, options) =>
|
|
141
|
+
updateResourcePricing({
|
|
142
|
+
resourceType,
|
|
143
|
+
sku,
|
|
144
|
+
price: parseFloat(price),
|
|
145
|
+
dryRun: options.dryRun,
|
|
146
|
+
validate: options.validate !== false
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
pricingCommand
|
|
151
|
+
.command('validate')
|
|
152
|
+
.description('Validate pricing file against JSON schema')
|
|
153
|
+
.action(validatePricing);
|
|
154
|
+
|
|
155
|
+
// Generation commands
|
|
156
|
+
const generateCommand = program
|
|
157
|
+
.command('generate')
|
|
158
|
+
.description('Generate code from templates');
|
|
159
|
+
|
|
160
|
+
generateCommand
|
|
161
|
+
.command('design-system <ui-design-system-md>')
|
|
162
|
+
.description('Generate CSS + theme files from ui-design-system.md')
|
|
163
|
+
.option('--fluent', 'Generate only Fluent UI theme')
|
|
164
|
+
.option('--mud', 'Generate only MudBlazor theme')
|
|
165
|
+
.option('--both', 'Generate both themes (default)')
|
|
166
|
+
.option('--namespace <ns>', 'C# namespace (default: YourProject.Themes)')
|
|
167
|
+
.option('--css-output <path>', 'CSS output path (default: wwwroot/css/design-system.css)')
|
|
168
|
+
.option('--fluent-output <path>', 'Fluent theme output path (default: Themes/FluentDesignTheme.cs)')
|
|
169
|
+
.option('--mud-output <path>', 'MudBlazor theme output path (default: Themes/MudDesignTheme.cs)')
|
|
170
|
+
.option('--dry-run', 'Preview without writing files')
|
|
171
|
+
.action(generateDesignSystemCommand);
|
|
172
|
+
|
|
53
173
|
program.parse();
|