@polymorphism-tech/morph-spec 2.3.0 → 3.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 +446 -1730
- package/README.md +515 -516
- package/bin/morph-spec.js +366 -294
- package/bin/task-manager.js +429 -368
- package/bin/validate.js +369 -268
- package/content/.claude/commands/morph-apply.md +221 -158
- package/content/.claude/commands/morph-deploy.md +529 -0
- 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/skills/infra/azure-deploy-specialist.md +699 -0
- package/content/.claude/skills/level-0-meta/README.md +7 -0
- package/content/.claude/skills/level-0-meta/code-review.md +226 -0
- package/content/.claude/skills/level-0-meta/morph-checklist.md +117 -0
- package/content/.claude/skills/level-0-meta/simulation-checklist.md +77 -0
- package/content/.claude/skills/level-1-workflows/README.md +7 -0
- package/content/.claude/skills/level-1-workflows/morph-replicate.md +213 -0
- package/content/.claude/{commands/morph-clarify.md → skills/level-1-workflows/phase-clarify.md} +131 -184
- package/content/.claude/{commands/morph-design.md → skills/level-1-workflows/phase-design.md} +213 -275
- package/content/.claude/skills/level-1-workflows/phase-setup.md +106 -0
- package/content/.claude/skills/level-1-workflows/phase-tasks.md +164 -0
- package/content/.claude/{commands/morph-uiux.md → skills/level-1-workflows/phase-uiux.md} +169 -211
- package/content/.claude/skills/level-2-domains/README.md +14 -0
- package/content/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +192 -0
- package/content/.claude/skills/{specialists → level-2-domains/architecture}/po-pm-advisor.md +197 -197
- package/content/.claude/skills/level-2-domains/architecture/standards-architect.md +156 -0
- package/content/.claude/skills/level-2-domains/backend/dotnet-senior.md +287 -0
- package/content/.claude/skills/level-2-domains/backend/ef-modeler.md +113 -0
- package/content/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +126 -0
- package/content/.claude/skills/level-2-domains/backend/ms-agent-expert.md +109 -0
- package/content/.claude/skills/level-2-domains/frontend/blazor-builder.md +210 -0
- package/content/.claude/skills/level-2-domains/frontend/nextjs-expert.md +154 -0
- package/content/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +191 -0
- package/content/.claude/skills/{specialists → level-2-domains/infrastructure}/azure-architect.md +142 -142
- package/content/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +126 -0
- package/content/.claude/skills/level-2-domains/infrastructure/container-specialist.md +131 -0
- package/content/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +119 -0
- package/content/.claude/skills/level-2-domains/integrations/asaas-financial.md +130 -0
- package/content/.claude/skills/level-2-domains/integrations/azure-identity.md +142 -0
- package/content/.claude/skills/level-2-domains/integrations/clerk-auth.md +108 -0
- package/content/.claude/skills/level-2-domains/integrations/resend-email.md +119 -0
- package/content/.claude/skills/level-2-domains/quality/code-analyzer.md +235 -0
- package/content/.claude/skills/level-2-domains/quality/testing-specialist.md +126 -0
- package/content/.claude/skills/level-3-technologies/README.md +7 -0
- package/content/.claude/skills/level-4-patterns/README.md +7 -0
- package/content/.claude/skills/specialists/prompt-engineer.md +189 -0
- package/content/.claude/skills/specialists/seo-growth-hacker.md +320 -0
- package/content/.morph/config/agents.json +762 -242
- package/content/.morph/config/config.template.json +122 -108
- package/content/.morph/docs/workflows/design-impl.md +37 -0
- package/content/.morph/docs/workflows/enforcement-pipeline.md +668 -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/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/hooks/README.md +348 -239
- package/content/.morph/hooks/pre-commit-agents.sh +24 -24
- package/content/.morph/hooks/task-completed.js +73 -0
- package/content/.morph/hooks/teammate-idle.js +68 -0
- package/content/.morph/schemas/tasks.schema.json +220 -0
- 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/agent-teams-workflow.md +474 -0
- package/content/.morph/standards/architecture.md +325 -325
- package/content/.morph/standards/azure.md +605 -379
- package/content/.morph/standards/dotnet10-migration.md +520 -494
- package/content/.morph/templates/CONTEXT-FEATURE.md +276 -0
- package/content/.morph/templates/CONTEXT.md +170 -0
- package/content/.morph/templates/agent.cs +163 -172
- package/content/.morph/templates/clarify-questions.md +159 -0
- 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/decisions.md +123 -106
- package/content/.morph/templates/infra/azure-pipelines-deploy.yml +480 -0
- package/content/.morph/templates/infra/deploy-checklist.md +426 -0
- package/content/.morph/templates/proposal.md +141 -155
- package/content/.morph/templates/recap.md +94 -105
- package/content/.morph/templates/simulation.md +353 -0
- package/content/.morph/templates/spec.md +149 -148
- package/content/.morph/templates/state.template.json +222 -222
- package/content/.morph/templates/tasks.md +257 -235
- package/content/.morph/templates/ui-components.md +362 -276
- package/content/CLAUDE.md +150 -442
- package/detectors/structure-detector.js +245 -250
- package/docs/README.md +144 -149
- package/docs/getting-started.md +301 -302
- package/docs/installation.md +361 -361
- package/docs/validation-checklist.md +265 -266
- package/package.json +80 -80
- package/src/commands/advance-phase.js +266 -0
- package/src/commands/analyze-blazor-concurrency.js +193 -0
- package/src/commands/deploy.js +780 -0
- package/src/commands/detect-agents.js +167 -0
- package/src/commands/doctor.js +356 -280
- package/src/commands/generate-context.js +40 -0
- 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/task.js +78 -75
- 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/context-generator.js +513 -0
- package/src/lib/continuous-validator.js +421 -440
- package/src/lib/css-validator.js +352 -0
- package/src/lib/decision-constraint-loader.js +109 -0
- package/src/lib/design-system-detector.js +187 -0
- package/src/lib/design-system-scaffolder.js +299 -0
- package/src/lib/hook-executor.js +256 -0
- package/src/lib/recap-generator.js +205 -0
- package/src/lib/spec-validator.js +258 -0
- package/src/lib/standards-context-injector.js +287 -0
- package/src/lib/state-manager.js +397 -340
- package/src/lib/team-orchestrator.js +322 -0
- package/src/lib/troubleshoot-grep.js +194 -0
- package/src/lib/troubleshoot-index.js +144 -0
- package/src/lib/validation-runner.js +283 -0
- package/src/lib/validators/contract-compliance-validator.js +273 -0
- package/src/lib/validators/design-system-validator.js +231 -0
- package/src/utils/file-copier.js +187 -139
- package/content/.claude/commands/morph-costs.md +0 -206
- package/content/.claude/commands/morph-setup.md +0 -100
- package/content/.claude/commands/morph-tasks.md +0 -319
- package/content/.claude/skills/infra/bicep-architect.md +0 -419
- package/content/.claude/skills/infra/container-specialist.md +0 -437
- package/content/.claude/skills/infra/devops-engineer.md +0 -405
- package/content/.claude/skills/integrations/asaas-financial.md +0 -333
- package/content/.claude/skills/integrations/azure-identity.md +0 -309
- package/content/.claude/skills/integrations/clerk-auth.md +0 -290
- package/content/.claude/skills/specialists/ai-system-architect.md +0 -604
- package/content/.claude/skills/specialists/cost-guardian.md +0 -110
- package/content/.claude/skills/specialists/ef-modeler.md +0 -211
- package/content/.claude/skills/specialists/hangfire-orchestrator.md +0 -255
- package/content/.claude/skills/specialists/ms-agent-expert.md +0 -263
- package/content/.claude/skills/specialists/standards-architect.md +0 -78
- package/content/.claude/skills/specialists/ui-ux-designer.md +0 -1100
- package/content/.claude/skills/stacks/dotnet-blazor.md +0 -606
- package/content/.claude/skills/stacks/dotnet-nextjs.md +0 -402
- 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
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Workflow: FULL MORPH (Alta Complexidade)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** on-keyword | **Keywords:** sistema, autenticação, integração, pattern, cqrs, subsistema
|
|
4
|
+
|
|
5
|
+
## Critérios
|
|
6
|
+
|
|
7
|
+
- > 10 arquivos, > 500 linhas, múltiplos componentes novos
|
|
8
|
+
- Infraestrutura Azure (Bicep), decisões arquiteturais estratégicas
|
|
9
|
+
|
|
10
|
+
## Fases (TODAS obrigatórias)
|
|
11
|
+
|
|
12
|
+
### FASE 0.5: CONTEXT (automática)
|
|
13
|
+
1. Detectar framework MORPH (`@polymorphism-tech/morph-spec`)
|
|
14
|
+
2. Detectar/criar estrutura `.morph/project/`
|
|
15
|
+
3. Análise automática: stack (glob patterns), arquitetura (pastas), configs, UI library
|
|
16
|
+
4. Analisar histórico: decisions.md passados, preferências do usuário
|
|
17
|
+
5. Gerar/atualizar `.morph/project/standards/inferred.md`
|
|
18
|
+
6. Ativar agentes baseado em stack + keywords
|
|
19
|
+
|
|
20
|
+
### FASE 0: PROPOSAL
|
|
21
|
+
1. `npx morph-spec detect "{user-request}"`
|
|
22
|
+
2. Analisar solicitação, identificar stack, estimar complexidade
|
|
23
|
+
3. Gerar proposal.md, registrar agentes no state.json
|
|
24
|
+
- **⛔ PAUSA:** 3 itens (1 ação + 1 pergunta + 1 sugestão)
|
|
25
|
+
|
|
26
|
+
### FASE 1: SETUP
|
|
27
|
+
1. Ler `.morph/config.json`
|
|
28
|
+
2. Confirmar stack, ativar agentes, criar pasta outputs
|
|
29
|
+
3. Carregar padrões (framework/standards/ > project/standards/)
|
|
30
|
+
|
|
31
|
+
### FASE 1.5: UI/UX (condicional - se keywords UI detectadas)
|
|
32
|
+
1. **Perguntar ao usuário:** layout, referências visuais, fluxo, imagens
|
|
33
|
+
2. Analisar referências fornecidas
|
|
34
|
+
3. Gerar deliverables AGNÓSTICOS de biblioteca (ui-mockups, ui-components, ui-flows)
|
|
35
|
+
4. Validar acessibilidade (WCAG 2.1) e responsividade
|
|
36
|
+
- **⛔ PAUSA:** Aprovar / Ajustar wireframes / Adicionar fluxos
|
|
37
|
+
|
|
38
|
+
### FASE 2: DESIGN
|
|
39
|
+
1. Gerar spec.md com requisitos completos
|
|
40
|
+
2. **DECISION POINTS** (cada um requer aprovação):
|
|
41
|
+
- Biblioteca UI (Fluent UI vs MudBlazor)
|
|
42
|
+
- Padrões Arquiteturais (CQRS vs simples, Repository vs EF direto)
|
|
43
|
+
- Estrutura de Dados (entidades, relacionamentos)
|
|
44
|
+
- Infraestrutura Azure (recursos, SKUs, custos)
|
|
45
|
+
- Bibliotecas/SDKs (NuGet packages)
|
|
46
|
+
3. Gerar contracts.cs, documentar decisões em decisions.md
|
|
47
|
+
- **⛔ PAUSA:** Aprovar / Ajustar escopo / Modificar contracts
|
|
48
|
+
|
|
49
|
+
### FASE 3: CLARIFY
|
|
50
|
+
1. Identificar ambiguidades, fazer perguntas, documentar em spec.md, validar edge cases
|
|
51
|
+
|
|
52
|
+
### FASE 4: TASKS
|
|
53
|
+
1. Quebrar spec em tasks T001-TXXX, definir ordem, checkpoints, dependências
|
|
54
|
+
- **⛔ PAUSA:** Aprovar / Repriorizar / Adicionar-remover tasks
|
|
55
|
+
|
|
56
|
+
### FASE 5: IMPLEMENT
|
|
57
|
+
1. Implementar task por task
|
|
58
|
+
2. `npx morph-spec task done {feature} {task-id}` após cada task
|
|
59
|
+
3. Framework gerencia checkpoints automaticamente (a cada 3 tasks)
|
|
60
|
+
4. Gerar recap.md ao final
|
|
61
|
+
|
|
62
|
+
### FASE 6: SYNC (condicional - se complexidade média/alta)
|
|
63
|
+
1. Revisar decisions.md, categorizar (coding, architecture, azure, integrations, ui-ux)
|
|
64
|
+
2. Promover para `.morph/project/standards/{category}.md`
|
|
65
|
+
3. Gerar commit dedicado de sync
|
|
66
|
+
- **⛔ PAUSA:** Aprovar promoção de decisões para standards
|
|
67
|
+
|
|
68
|
+
## Outputs Completos
|
|
69
|
+
proposal.md, ui-design-system.md, ui-mockups.md, ui-components.md, ui-flows.md, spec.md, contracts.cs, tasks.json, decisions.md, recap.md
|
|
70
|
+
|
|
71
|
+
## Exemplos
|
|
72
|
+
- "Sistema de relatórios com jobs agendados Hangfire"
|
|
73
|
+
- "Autenticação completa com Clerk (login, signup, OAuth)"
|
|
74
|
+
- "Dashboard com gráficos, tabelas e filtros complexos"
|
|
75
|
+
- "RAG pipeline com Azure AI Search e embeddings"
|
|
76
|
+
- "Infraestrutura Azure completa com Bicep"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Workflow: STANDARD (Média Complexidade)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** on-keyword | **Keywords:** paginação, filtro, refatorar, performance, exportar
|
|
4
|
+
|
|
5
|
+
## Critérios
|
|
6
|
+
|
|
7
|
+
- 3-10 arquivos, 50-500 linhas, 1-2 componentes simples
|
|
8
|
+
- Sem infraestrutura complexa, decisões táticas (não estratégicas)
|
|
9
|
+
|
|
10
|
+
## Fases
|
|
11
|
+
|
|
12
|
+
### 1. FASE 0: PROPOSAL (simplificada)
|
|
13
|
+
- Análise inicial em 1 parágrafo
|
|
14
|
+
- Detecta agentes relevantes
|
|
15
|
+
- **PAUSA:** Aprovar?
|
|
16
|
+
|
|
17
|
+
### 2. FASE 2: DESIGN (apenas spec.md)
|
|
18
|
+
- Spec técnico conciso (1-2 páginas)
|
|
19
|
+
- Sem contracts.cs se trivial
|
|
20
|
+
- Decisões táticas em decisions.md
|
|
21
|
+
- **PAUSA:** Aprovar?
|
|
22
|
+
|
|
23
|
+
### 3. FASE 4: TASKS (se > 5 tasks)
|
|
24
|
+
- Breakdown em tasks
|
|
25
|
+
- **PAUSA:** Aprovar?
|
|
26
|
+
|
|
27
|
+
### 4. FASE 5: IMPLEMENT
|
|
28
|
+
- Implementa task por task
|
|
29
|
+
- Gera recap.md ao final
|
|
30
|
+
|
|
31
|
+
## Outputs
|
|
32
|
+
proposal.md, spec.md, recap.md (mínimo necessário)
|
|
33
|
+
|
|
34
|
+
## Fases Puladas
|
|
35
|
+
- FASE 1 (SETUP) - contexto já carregado
|
|
36
|
+
- FASE 1.5 (UI/UX) - se não tiver front-end significativo
|
|
37
|
+
- FASE 3 (CLARIFY) - se spec for claro
|
|
38
|
+
- FASE 6 (SYNC) - decisões não são estratégicas
|
|
39
|
+
|
|
40
|
+
## Exemplos
|
|
41
|
+
- "Adicionar paginação na tabela de usuários"
|
|
42
|
+
- "Criar filtro por data no relatório"
|
|
43
|
+
- "Refatorar serviço de email para async"
|
|
44
|
+
- "Adicionar botão de exportar CSV"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Workflow: UI REFRESH (Redesign Visual)
|
|
2
|
+
|
|
3
|
+
> **Layer:** 1 | **Load:** on-keyword | **Keywords:** redesign, redesenhar, bonito, visual, estetica, modernizar
|
|
4
|
+
|
|
5
|
+
## Critérios
|
|
6
|
+
|
|
7
|
+
- Páginas existentes com código funcional
|
|
8
|
+
- Apenas mudanças visuais (CSS, HTML, layout)
|
|
9
|
+
- Sem mudanças em lógica de negócio, sem infraestrutura
|
|
10
|
+
|
|
11
|
+
## Fases
|
|
12
|
+
|
|
13
|
+
### 1. ANÁLISE VISUAL (FASE 0+1 combinadas)
|
|
14
|
+
- Listar páginas a redesenhar
|
|
15
|
+
- Identificar componentes compartilhados e design system existente
|
|
16
|
+
- Se protótipo existir: ler e extrair padrões
|
|
17
|
+
- **PAUSA:** Escolher direção estética
|
|
18
|
+
|
|
19
|
+
### 2. DESIGN SYSTEM (FASE 1.5 simplificada)
|
|
20
|
+
- Definir variáveis CSS novas
|
|
21
|
+
- Listar componentes CSS a criar (checklist)
|
|
22
|
+
- Gerar/atualizar design-system.css
|
|
23
|
+
- **PAUSA:** Aprovar componentes
|
|
24
|
+
|
|
25
|
+
### 3. IMPLEMENT (por página)
|
|
26
|
+
- Atualizar CSS primeiro, depois cada página .razor
|
|
27
|
+
- Build incremental a cada 2-3 páginas
|
|
28
|
+
- Validar com `morph-spec validate-css`
|
|
29
|
+
|
|
30
|
+
## Outputs
|
|
31
|
+
design-refresh-checklist.md, CSS atualizado, páginas .razor, recap.md
|
|
32
|
+
|
|
33
|
+
## Fases Puladas
|
|
34
|
+
Setup completo, Contracts, Tasks detalhadas, Infra, Clarify, Sync
|
|
35
|
+
|
|
36
|
+
## Exemplos
|
|
37
|
+
- "Redesenhar as páginas do checkout para ficar mais bonito"
|
|
38
|
+
- "Modernizar visual do dashboard"
|
|
39
|
+
- "Aplicar novo design system nas telas existentes"
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Decisões Arquiteturais - Scheduled Reports
|
|
2
|
+
|
|
3
|
+
> Exemplo real de decisions.md gerado pelo MORPH-SPEC
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ADR-001: Biblioteca de Background Jobs
|
|
8
|
+
|
|
9
|
+
**Data:** 2024-01-15
|
|
10
|
+
**Status:** Aceito
|
|
11
|
+
**Contexto:** Precisamos executar relatórios em horários agendados.
|
|
12
|
+
|
|
13
|
+
### Opções Consideradas
|
|
14
|
+
|
|
15
|
+
| Opção | Pros | Cons |
|
|
16
|
+
|-------|------|------|
|
|
17
|
+
| **Hangfire** | Dashboard, retry, SQL storage | Licença para recursos avançados |
|
|
18
|
+
| Azure Functions (Timer) | Serverless, escalável | Mais complexo, cold start |
|
|
19
|
+
| Quartz.NET | Open source completo | Sem dashboard built-in |
|
|
20
|
+
|
|
21
|
+
### Decisão
|
|
22
|
+
|
|
23
|
+
**Hangfire** - Já usado no projeto, dashboard útil para monitoramento, integração simples com DI.
|
|
24
|
+
|
|
25
|
+
### Consequências
|
|
26
|
+
- ✅ Fácil implementação
|
|
27
|
+
- ✅ Dashboard para operações
|
|
28
|
+
- ⚠️ Considerar licença Pro se precisar de batches
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## ADR-002: Geração de PDF
|
|
33
|
+
|
|
34
|
+
**Data:** 2024-01-15
|
|
35
|
+
**Status:** Aceito
|
|
36
|
+
**Contexto:** Precisamos gerar PDFs dos relatórios.
|
|
37
|
+
|
|
38
|
+
### Opções Consideradas
|
|
39
|
+
|
|
40
|
+
| Opção | Pros | Cons |
|
|
41
|
+
|-------|------|------|
|
|
42
|
+
| **QuestPDF** | Fluent API, .NET nativo, gratuito | Mais novo, menos exemplos |
|
|
43
|
+
| iTextSharp | Maduro, muitos exemplos | Licença AGPL (viral) |
|
|
44
|
+
| PuppeteerSharp | HTML→PDF | Requer Chrome, pesado |
|
|
45
|
+
|
|
46
|
+
### Decisão
|
|
47
|
+
|
|
48
|
+
**QuestPDF** - API moderna, totalmente .NET, licença MIT.
|
|
49
|
+
|
|
50
|
+
### Consequências
|
|
51
|
+
- ✅ Código limpo e legível
|
|
52
|
+
- ✅ Sem dependências externas
|
|
53
|
+
- ⚠️ Curva de aprendizado para layouts complexos
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## ADR-003: Biblioteca UI
|
|
58
|
+
|
|
59
|
+
**Data:** 2024-01-15
|
|
60
|
+
**Status:** Aceito
|
|
61
|
+
**Contexto:** Componentes UI para as telas de relatórios.
|
|
62
|
+
|
|
63
|
+
### Opções Consideradas
|
|
64
|
+
|
|
65
|
+
| Opção | Pros | Cons |
|
|
66
|
+
|-------|------|------|
|
|
67
|
+
| **Fluent UI Blazor** | Já no projeto, design MS | Menos componentes |
|
|
68
|
+
| MudBlazor | Mais componentes | Adicionar dependência |
|
|
69
|
+
|
|
70
|
+
### Decisão
|
|
71
|
+
|
|
72
|
+
**Fluent UI Blazor** - Já instalado no projeto, manter consistência.
|
|
73
|
+
|
|
74
|
+
### Consequências
|
|
75
|
+
- ✅ Sem nova dependência
|
|
76
|
+
- ✅ Visual consistente
|
|
77
|
+
- ⚠️ Pode precisar criar componentes custom
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## ADR-004: Armazenamento de Arquivos
|
|
82
|
+
|
|
83
|
+
**Data:** 2024-01-15
|
|
84
|
+
**Status:** Aceito
|
|
85
|
+
**Contexto:** Onde armazenar os PDFs/Excels gerados.
|
|
86
|
+
|
|
87
|
+
### Opções Consideradas
|
|
88
|
+
|
|
89
|
+
| Opção | Pros | Cons |
|
|
90
|
+
|-------|------|------|
|
|
91
|
+
| **Azure Blob Storage** | Escalável, barato, SAS tokens | Requer setup |
|
|
92
|
+
| Sistema de arquivos | Simples | Não escala, perde em redeploy |
|
|
93
|
+
| Database (BLOB) | Tudo junto | Performance ruim |
|
|
94
|
+
|
|
95
|
+
### Decisão
|
|
96
|
+
|
|
97
|
+
**Azure Blob Storage** - Já usado para outros arquivos, suporta SAS tokens para links temporários.
|
|
98
|
+
|
|
99
|
+
### Consequências
|
|
100
|
+
- ✅ Escalável
|
|
101
|
+
- ✅ Links com expiração
|
|
102
|
+
- ⚠️ Custo adicional (baixo)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## ADR-005: Padrão CQRS
|
|
107
|
+
|
|
108
|
+
**Data:** 2024-01-15
|
|
109
|
+
**Status:** Aceito
|
|
110
|
+
**Contexto:** Estruturar commands e queries.
|
|
111
|
+
|
|
112
|
+
### Decisão
|
|
113
|
+
|
|
114
|
+
**CQRS com MediatR** - Separação clara de responsabilidades, já é o padrão do projeto.
|
|
115
|
+
|
|
116
|
+
### Commands
|
|
117
|
+
- `CreateScheduledReportCommand`
|
|
118
|
+
- `UpdateScheduledReportCommand`
|
|
119
|
+
- `DeleteScheduledReportCommand`
|
|
120
|
+
- `ExecuteReportCommand`
|
|
121
|
+
|
|
122
|
+
### Queries
|
|
123
|
+
- `GetScheduledReportByIdQuery`
|
|
124
|
+
- `GetScheduledReportsQuery`
|
|
125
|
+
- `GetReportExecutionsQuery`
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## ADR-006: Estratégia de Retry
|
|
130
|
+
|
|
131
|
+
**Data:** 2024-01-15
|
|
132
|
+
**Status:** Aceito
|
|
133
|
+
**Contexto:** Como lidar com falhas na execução de jobs.
|
|
134
|
+
|
|
135
|
+
### Decisão
|
|
136
|
+
|
|
137
|
+
**Exponential backoff com limite:**
|
|
138
|
+
- Retry 1: 1 minuto
|
|
139
|
+
- Retry 2: 5 minutos
|
|
140
|
+
- Retry 3: 15 minutos
|
|
141
|
+
- Após 3 falhas: marcar como Error, notificar admin
|
|
142
|
+
|
|
143
|
+
```csharp
|
|
144
|
+
[AutomaticRetry(Attempts = 3, DelaysInSeconds = new[] { 60, 300, 900 })]
|
|
145
|
+
public async Task ExecuteReportJob(int reportId) { ... }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Histórico de Mudanças
|
|
151
|
+
|
|
152
|
+
| Data | ADR | Mudança |
|
|
153
|
+
|------|-----|---------|
|
|
154
|
+
| 2024-01-15 | 001-006 | Decisões iniciais |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
_Gerado por MORPH-SPEC Framework_
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Proposta: Sistema de Relatórios Agendados
|
|
2
|
+
|
|
3
|
+
> Exemplo real de proposal.md gerado pelo MORPH-SPEC
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📋 Resumo da Solicitação
|
|
8
|
+
|
|
9
|
+
O usuário solicitou um sistema para agendar e executar relatórios automaticamente, com suporte a diferentes formatos de saída (PDF, Excel) e notificação por email.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🎯 Análise Inicial
|
|
14
|
+
|
|
15
|
+
### Stack Identificado
|
|
16
|
+
- **Backend:** .NET 8 + Blazor Server
|
|
17
|
+
- **Database:** SQL Server (Entity Framework Core)
|
|
18
|
+
- **Background Jobs:** Hangfire
|
|
19
|
+
- **UI:** Fluent UI Blazor (detectado no projeto)
|
|
20
|
+
|
|
21
|
+
### Complexidade Estimada
|
|
22
|
+
**ALTA** - Justificativa:
|
|
23
|
+
- Múltiplos componentes (entidades, jobs, UI)
|
|
24
|
+
- Integração com sistema de email
|
|
25
|
+
- Geração de arquivos (PDF, Excel)
|
|
26
|
+
- CRON expressions para agendamento
|
|
27
|
+
|
|
28
|
+
### Agentes Ativados
|
|
29
|
+
1. 📐 Standards Architect
|
|
30
|
+
2. ☁️ Azure Architect
|
|
31
|
+
3. 🔥 Blazor Builder
|
|
32
|
+
4. 🗄️ EF Modeler
|
|
33
|
+
5. ⏰ Hangfire Orchestrator
|
|
34
|
+
6. 🎨 UI/UX Designer
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 📊 Escopo Preliminar
|
|
39
|
+
|
|
40
|
+
### Funcionalidades Core
|
|
41
|
+
1. CRUD de relatórios agendados
|
|
42
|
+
2. Configuração de periodicidade (CRON)
|
|
43
|
+
3. Seleção de formato de saída (PDF/Excel)
|
|
44
|
+
4. Execução manual e automática
|
|
45
|
+
5. Histórico de execuções
|
|
46
|
+
6. Notificação por email
|
|
47
|
+
|
|
48
|
+
### Fora do Escopo (MVP)
|
|
49
|
+
- [ ] Dashboard com métricas de execução
|
|
50
|
+
- [ ] Relatórios customizáveis pelo usuário
|
|
51
|
+
- [ ] Integração com BI tools
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 💰 Estimativa de Custos Azure
|
|
56
|
+
|
|
57
|
+
| Recurso | SKU | Custo Estimado/mês |
|
|
58
|
+
|---------|-----|-------------------|
|
|
59
|
+
| Container App | 0.5 vCPU, 1GB | ~$15 |
|
|
60
|
+
| SQL Database | Basic (5 DTU) | ~$5 |
|
|
61
|
+
| Storage (blobs) | LRS | ~$1 |
|
|
62
|
+
| **Total** | | **~$21/mês** |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## ⏱️ Estimativa de Esforço
|
|
67
|
+
|
|
68
|
+
| Fase | Tasks Estimadas |
|
|
69
|
+
|------|-----------------|
|
|
70
|
+
| Design | 2-3 |
|
|
71
|
+
| Entities + EF | 3-4 |
|
|
72
|
+
| Handlers/Services | 4-5 |
|
|
73
|
+
| Background Jobs | 2-3 |
|
|
74
|
+
| UI Components | 4-5 |
|
|
75
|
+
| Testes | 3-4 |
|
|
76
|
+
| **Total** | **18-24 tasks** |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## ⛔ PAUSA OBRIGATÓRIA
|
|
81
|
+
|
|
82
|
+
**Próximos passos sugeridos:**
|
|
83
|
+
|
|
84
|
+
1. ✅ **Aprovar proposta e prosseguir para Setup**
|
|
85
|
+
Carregar contexto completo e ativar agentes detectados
|
|
86
|
+
|
|
87
|
+
2. ❓ **Esclarecer escopo**
|
|
88
|
+
Você precisa de dashboard de métricas no MVP? Ou apenas a lista de relatórios?
|
|
89
|
+
|
|
90
|
+
3. 💡 **Considerar MVP mais enxuto**
|
|
91
|
+
Começar apenas com PDF e adicionar Excel em iteração futura?
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
_Gerado por MORPH-SPEC Framework_
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Especificação Técnica: Sistema de Relatórios Agendados
|
|
2
|
+
|
|
3
|
+
> Exemplo real de spec.md gerado pelo MORPH-SPEC
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 📋 Informações do Documento
|
|
8
|
+
|
|
9
|
+
| Campo | Valor |
|
|
10
|
+
|-------|-------|
|
|
11
|
+
| Feature | scheduled-reports |
|
|
12
|
+
| Versão | 1.0 |
|
|
13
|
+
| Status | Aprovado |
|
|
14
|
+
| Data | 2024-01-15 |
|
|
15
|
+
| Autor | MORPH-SPEC + User |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 1. Visão Geral
|
|
20
|
+
|
|
21
|
+
### 1.1 Objetivo
|
|
22
|
+
Permitir que usuários criem relatórios que são executados automaticamente em horários configurados, gerando arquivos PDF ou Excel e notificando via email.
|
|
23
|
+
|
|
24
|
+
### 1.2 Contexto
|
|
25
|
+
O sistema atual não possui funcionalidade de relatórios agendados. Usuários precisam gerar relatórios manualmente, o que é ineficiente para relatórios recorrentes.
|
|
26
|
+
|
|
27
|
+
### 1.3 Stakeholders
|
|
28
|
+
- **Usuários finais:** Gestores que precisam de relatórios periódicos
|
|
29
|
+
- **Administradores:** Configuração e monitoramento de jobs
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. Requisitos Funcionais
|
|
34
|
+
|
|
35
|
+
### 2.1 CRUD de Relatórios Agendados
|
|
36
|
+
|
|
37
|
+
#### RF-001: Criar Relatório Agendado
|
|
38
|
+
- [ ] Usuário pode criar relatório com nome e descrição
|
|
39
|
+
- [ ] Usuário pode selecionar tipo de relatório (vendas, estoque, financeiro)
|
|
40
|
+
- [ ] Usuário pode definir formato de saída (PDF, Excel)
|
|
41
|
+
- [ ] Usuário pode definir periodicidade (diário, semanal, mensal, custom CRON)
|
|
42
|
+
- [ ] Usuário pode definir destinatários de email
|
|
43
|
+
|
|
44
|
+
#### RF-002: Listar Relatórios
|
|
45
|
+
- [ ] Listar relatórios do usuário com paginação
|
|
46
|
+
- [ ] Filtrar por status (ativo, pausado, erro)
|
|
47
|
+
- [ ] Ordenar por última execução ou próxima execução
|
|
48
|
+
|
|
49
|
+
#### RF-003: Editar Relatório
|
|
50
|
+
- [ ] Editar todas as propriedades exceto tipo
|
|
51
|
+
- [ ] Pausar/retomar agendamento
|
|
52
|
+
|
|
53
|
+
#### RF-004: Excluir Relatório
|
|
54
|
+
- [ ] Soft delete com confirmação
|
|
55
|
+
- [ ] Cancelar jobs pendentes ao excluir
|
|
56
|
+
|
|
57
|
+
### 2.2 Execução de Relatórios
|
|
58
|
+
|
|
59
|
+
#### RF-005: Execução Automática
|
|
60
|
+
- [ ] Hangfire executa job no horário configurado
|
|
61
|
+
- [ ] Job gera arquivo no formato selecionado
|
|
62
|
+
- [ ] Arquivo é salvo em Azure Blob Storage
|
|
63
|
+
- [ ] Email é enviado aos destinatários com link para download
|
|
64
|
+
|
|
65
|
+
#### RF-006: Execução Manual
|
|
66
|
+
- [ ] Botão "Executar Agora" na UI
|
|
67
|
+
- [ ] Mesma lógica do job automático
|
|
68
|
+
- [ ] Feedback imediato de "em execução"
|
|
69
|
+
|
|
70
|
+
### 2.3 Histórico
|
|
71
|
+
|
|
72
|
+
#### RF-007: Histórico de Execuções
|
|
73
|
+
- [ ] Listar últimas 50 execuções por relatório
|
|
74
|
+
- [ ] Mostrar: data, duração, status, link do arquivo
|
|
75
|
+
- [ ] Filtrar por período
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. Requisitos Não-Funcionais
|
|
80
|
+
|
|
81
|
+
### 3.1 Performance
|
|
82
|
+
- **RNF-001:** Geração de PDF deve completar em < 30 segundos
|
|
83
|
+
- **RNF-002:** Lista de relatórios deve carregar em < 500ms
|
|
84
|
+
|
|
85
|
+
### 3.2 Segurança
|
|
86
|
+
- **RNF-003:** Usuário só pode ver/editar seus próprios relatórios
|
|
87
|
+
- **RNF-004:** Links de download expiram em 24h
|
|
88
|
+
- **RNF-005:** Arquivos são criptografados em repouso
|
|
89
|
+
|
|
90
|
+
### 3.3 Escalabilidade
|
|
91
|
+
- **RNF-006:** Suportar até 1000 relatórios agendados simultâneos
|
|
92
|
+
- **RNF-007:** Jobs executam em fila separada para não bloquear app
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 4. Modelo de Dados
|
|
97
|
+
|
|
98
|
+
### 4.1 Entidade: ScheduledReport
|
|
99
|
+
|
|
100
|
+
```csharp
|
|
101
|
+
public class ScheduledReport
|
|
102
|
+
{
|
|
103
|
+
public int Id { get; private set; }
|
|
104
|
+
public int UserId { get; private set; }
|
|
105
|
+
public string Name { get; private set; }
|
|
106
|
+
public string? Description { get; private set; }
|
|
107
|
+
public ReportType Type { get; private set; }
|
|
108
|
+
public OutputFormat Format { get; private set; }
|
|
109
|
+
public string CronExpression { get; private set; }
|
|
110
|
+
public ReportStatus Status { get; private set; }
|
|
111
|
+
public List<string> Recipients { get; private set; }
|
|
112
|
+
public DateTime? LastExecutedAt { get; private set; }
|
|
113
|
+
public DateTime? NextExecutionAt { get; private set; }
|
|
114
|
+
public DateTime CreatedAt { get; private set; }
|
|
115
|
+
public DateTime? UpdatedAt { get; private set; }
|
|
116
|
+
public bool IsDeleted { get; private set; }
|
|
117
|
+
|
|
118
|
+
// Navigation
|
|
119
|
+
public User User { get; private set; }
|
|
120
|
+
public ICollection<ReportExecution> Executions { get; private set; }
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 4.2 Entidade: ReportExecution
|
|
125
|
+
|
|
126
|
+
```csharp
|
|
127
|
+
public class ReportExecution
|
|
128
|
+
{
|
|
129
|
+
public int Id { get; private set; }
|
|
130
|
+
public int ScheduledReportId { get; private set; }
|
|
131
|
+
public ExecutionStatus Status { get; private set; }
|
|
132
|
+
public DateTime StartedAt { get; private set; }
|
|
133
|
+
public DateTime? CompletedAt { get; private set; }
|
|
134
|
+
public string? FilePath { get; private set; }
|
|
135
|
+
public long? FileSizeBytes { get; private set; }
|
|
136
|
+
public string? ErrorMessage { get; private set; }
|
|
137
|
+
|
|
138
|
+
// Navigation
|
|
139
|
+
public ScheduledReport ScheduledReport { get; private set; }
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 4.3 Enums
|
|
144
|
+
|
|
145
|
+
```csharp
|
|
146
|
+
public enum ReportType { Sales, Inventory, Financial }
|
|
147
|
+
public enum OutputFormat { Pdf, Excel }
|
|
148
|
+
public enum ReportStatus { Active, Paused, Error }
|
|
149
|
+
public enum ExecutionStatus { Pending, Running, Completed, Failed }
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 5. Arquitetura
|
|
155
|
+
|
|
156
|
+
### 5.1 Componentes
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
160
|
+
│ Blazor UI │
|
|
161
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
162
|
+
│ │ ReportList │ │ ReportForm │ │ ExecutionHistory │ │
|
|
163
|
+
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
|
164
|
+
└─────────────────────────────────────────────────────────────┘
|
|
165
|
+
│
|
|
166
|
+
▼
|
|
167
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
168
|
+
│ Application Layer │
|
|
169
|
+
│ ┌───────────────┐ ┌───────────────┐ ┌─────────────────┐ │
|
|
170
|
+
│ │ CreateReport │ │ ExecuteReport │ │ GetExecutions │ │
|
|
171
|
+
│ │ Handler │ │ Handler │ │ Handler │ │
|
|
172
|
+
│ └───────────────┘ └───────────────┘ └─────────────────┘ │
|
|
173
|
+
└─────────────────────────────────────────────────────────────┘
|
|
174
|
+
│
|
|
175
|
+
▼
|
|
176
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
177
|
+
│ Infrastructure │
|
|
178
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
179
|
+
│ │ Hangfire │ │ Blob Storage│ │ Email Service │ │
|
|
180
|
+
│ │ Jobs │ │ │ │ │ │
|
|
181
|
+
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
|
182
|
+
└─────────────────────────────────────────────────────────────┘
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 5.2 Fluxo de Execução
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
1. Hangfire dispara job baseado em CRON
|
|
189
|
+
2. Job carrega config do relatório
|
|
190
|
+
3. Job chama ReportGenerator.Generate()
|
|
191
|
+
4. Arquivo é salvo em Blob Storage
|
|
192
|
+
5. EmailService envia notificação
|
|
193
|
+
6. ReportExecution é registrado
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 6. API/Commands
|
|
199
|
+
|
|
200
|
+
### 6.1 Commands
|
|
201
|
+
|
|
202
|
+
| Command | Descrição |
|
|
203
|
+
|---------|-----------|
|
|
204
|
+
| `CreateScheduledReportCommand` | Criar novo relatório |
|
|
205
|
+
| `UpdateScheduledReportCommand` | Atualizar relatório |
|
|
206
|
+
| `DeleteScheduledReportCommand` | Soft delete |
|
|
207
|
+
| `ExecuteReportCommand` | Execução manual |
|
|
208
|
+
| `PauseReportCommand` | Pausar agendamento |
|
|
209
|
+
| `ResumeReportCommand` | Retomar agendamento |
|
|
210
|
+
|
|
211
|
+
### 6.2 Queries
|
|
212
|
+
|
|
213
|
+
| Query | Descrição |
|
|
214
|
+
|-------|-----------|
|
|
215
|
+
| `GetScheduledReportByIdQuery` | Buscar por ID |
|
|
216
|
+
| `GetScheduledReportsQuery` | Listar com paginação |
|
|
217
|
+
| `GetReportExecutionsQuery` | Histórico de execuções |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## 7. Dependências
|
|
222
|
+
|
|
223
|
+
### 7.1 NuGet Packages
|
|
224
|
+
- `Hangfire.Core` - Background jobs
|
|
225
|
+
- `Hangfire.SqlServer` - Storage para Hangfire
|
|
226
|
+
- `QuestPDF` - Geração de PDF
|
|
227
|
+
- `ClosedXML` - Geração de Excel
|
|
228
|
+
- `Azure.Storage.Blobs` - Blob storage
|
|
229
|
+
|
|
230
|
+
### 7.2 Serviços Externos
|
|
231
|
+
- Azure Blob Storage (arquivos gerados)
|
|
232
|
+
- SendGrid ou SMTP (emails)
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 8. Edge Cases
|
|
237
|
+
|
|
238
|
+
| Cenário | Comportamento |
|
|
239
|
+
|---------|---------------|
|
|
240
|
+
| Job falha no meio | Status = Error, retry em 5 min (max 3x) |
|
|
241
|
+
| Email inválido | Log warning, continua com outros |
|
|
242
|
+
| Blob storage offline | Status = Error, retry |
|
|
243
|
+
| Relatório sem dados | Gera arquivo vazio com mensagem |
|
|
244
|
+
| Usuário deleta enquanto job roda | Job completa, não envia email |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 9. Validações
|
|
249
|
+
|
|
250
|
+
| Campo | Regras |
|
|
251
|
+
|-------|--------|
|
|
252
|
+
| Name | Required, 3-100 chars |
|
|
253
|
+
| CronExpression | Valid CRON, mínimo 1h entre execuções |
|
|
254
|
+
| Recipients | 1-10 emails válidos |
|
|
255
|
+
| Format | Enum válido |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 10. Aprovações
|
|
260
|
+
|
|
261
|
+
- [x] **Requisitos:** Aprovados em 2024-01-15
|
|
262
|
+
- [x] **Modelo de Dados:** Aprovado em 2024-01-15
|
|
263
|
+
- [x] **Arquitetura:** Aprovada em 2024-01-15
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
_Gerado por MORPH-SPEC Framework_
|