mddd-cli 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.
- package/bin/cli.js +259 -0
- package/package.json +43 -0
- package/readme.md +32 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import pc from 'picocolors';
|
|
7
|
+
|
|
8
|
+
const program = new Command();
|
|
9
|
+
|
|
10
|
+
// Busca o macro (*.spec.md) mais próximo subindo recursivamente a árvore de diretórios
|
|
11
|
+
function findClosestMacro(currentDir) {
|
|
12
|
+
let dir = currentDir;
|
|
13
|
+
while (dir !== path.parse(dir).root) {
|
|
14
|
+
try {
|
|
15
|
+
const files = fs.readdirSync(dir);
|
|
16
|
+
// Procura por qualquer arquivo .spec.md que esteja acima na árvore
|
|
17
|
+
const macroFile = files.find(f => f.endsWith('.spec.md') && f !== `${path.basename(currentDir)}.spec.md`);
|
|
18
|
+
|
|
19
|
+
if (macroFile) {
|
|
20
|
+
return path.join(dir, macroFile);
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// Silencia erros de permissão de leitura em pastas do sistema
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
dir = path.dirname(dir);
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
program
|
|
32
|
+
.name('md')
|
|
33
|
+
.description('Gerenciador de especificações colocalizadas para Mermaid Diagram Driven Development (MDDD)')
|
|
34
|
+
.version('3.0.0');
|
|
35
|
+
|
|
36
|
+
// ==========================================
|
|
37
|
+
// COMANDO: md init
|
|
38
|
+
// ==========================================
|
|
39
|
+
program
|
|
40
|
+
.command('init')
|
|
41
|
+
.description('Inicializa o prompt de sistema universal para guiar qualquer IA no projeto sob a metodologia MDDD')
|
|
42
|
+
.action(() => {
|
|
43
|
+
const agentsDir = '.agents';
|
|
44
|
+
const skillsDir = path.join(agentsDir, 'skills');
|
|
45
|
+
|
|
46
|
+
// 1. Cria a estrutura de pastas
|
|
47
|
+
if (!fs.existsSync(agentsDir)) fs.mkdirSync(agentsDir);
|
|
48
|
+
if (!fs.existsSync(skillsDir)) fs.mkdirSync(skillsDir);
|
|
49
|
+
|
|
50
|
+
const promptContent = `# Protocolo Mermaid Diagram Driven Development (MDDD)
|
|
51
|
+
|
|
52
|
+
Você deve seguir estritamente a arquitetura de especificações modulares por feature antes de alterar, escrever ou auditar código produtivo.
|
|
53
|
+
|
|
54
|
+
## 1. Estrutura de Árvore e Co-location
|
|
55
|
+
As especificações visuais vivem universalmente em formato Markdown (.md) exatamente no mesmo nível do código que descrevem:
|
|
56
|
+
- Módulos/Domínios macros possuem um arquivo \`[nome].spec.md\` contendo o diagrama global (sintaxe stateDiagram-v2).
|
|
57
|
+
- Telas ou fluxos de sub-regras micros possuem um arquivo \`[nome].spec.md\` contendo o fluxo da interface (sintaxe graph LR) + Tabelas de Decisão.
|
|
58
|
+
|
|
59
|
+
## 2. Regra de Conexão Entre Fluxos Existentes
|
|
60
|
+
Sempre que você criar ou alterar uma funcionalidade usando um arquivo pai explícito:
|
|
61
|
+
1. Abra o arquivo pai indicado ANTES de desenhar o fluxo novo.
|
|
62
|
+
2. Localize o nó exato de onde a bifurcação de negócio deve nascer.
|
|
63
|
+
3. Modifique o código Mermaid do arquivo PAI para fazer a seta apontar para o novo estado gerado.
|
|
64
|
+
4. No arquivo FILHO, inicie o grafo usando um nó de entrada que herde o contexto do pai.
|
|
65
|
+
|
|
66
|
+
## 3. Regra Estrita de Versionamento de Diagramas
|
|
67
|
+
- Todo arquivo possui um cabeçalho de metadados \`\`.
|
|
68
|
+
- Sempre que você alterar um diagrama Mermaid ou uma tabela de decisão usando o comando \`/md-edit\`, você DEVE incrementar a versão semântica do arquivo no cabeçalho antes de salvar:
|
|
69
|
+
- Mude o Patch (\`v1.0.0\` -> \`v1.0.1\`) para correções de sintaxe ou pequenos ajustes de texto nos nós.
|
|
70
|
+
- Mude o Minor (\`v1.0.0\` -> \`v1.1.0\`) para novos estados, novas transições ou novas colunas na matriz de decisão.
|
|
71
|
+
- Nunca remova a tag de versão. Ela é a garantia de que a implementação de código está alinhada com o design correto.
|
|
72
|
+
|
|
73
|
+
** DIRETRIZ DE ESCRITA DE ESPECIFICAÇÃO: **
|
|
74
|
+
Sempre use Mermaid para descrever fluxos de negócio, arquitetura ou estados de máquina. Evite ao máximo o uso de texto corrido ou listas para descrever lógicas complexas.
|
|
75
|
+
As especificações (.spec.md) devem ser documentos vivos focados no Contrato Atual, não em auditorias passadas.
|
|
76
|
+
|
|
77
|
+
Se o arquivo for o Contrato da Feature: Foque apenas no:
|
|
78
|
+
- Diagrama Mermaid (Fluxo real).
|
|
79
|
+
- Matriz de Decisão (Regras de negócio).
|
|
80
|
+
- Assinatura das interfaces/serviços (API contract).
|
|
81
|
+
- Versionamento: Mantenha o SPEC_VERSION sempre no topo.
|
|
82
|
+
|
|
83
|
+
** REGRAS: **
|
|
84
|
+
1. Ao gerar diagramas a partir do código, sempre escape ou remova parênteses de nomes de funções. Use aspas duplas (ex: A["main()"]) se o nome da função precisar ser preservado, ou simplifique o texto do nó (ex: A[main]) para manter o diagrama limpo e evitar erros de renderização.
|
|
85
|
+
2. PROIBIDO Arte ASCII ou desenhos manuais.
|
|
86
|
+
2. Todo diagrama deve ser encapsulado em blocos de código markdown com a linguagem 'mermaid'.
|
|
87
|
+
3. Para fluxos de arquitetura ou lógica de negócio, use exclusivamente 'graph TD' ou 'graph LR'.
|
|
88
|
+
4. Para estados de máquina (finitos), use 'stateDiagram-v2'.
|
|
89
|
+
5. Nomeie os nós, use formas específicas ([...], ([...]), { ... }) para indicar intenção (Ação, Início/Fim, Decisão).
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
fs.writeFileSync('system_prompt.md', promptContent);
|
|
93
|
+
|
|
94
|
+
// 3. Definição das Skills
|
|
95
|
+
const skills = {
|
|
96
|
+
'md-new': "Modo Desenho. Você deve rodar o comando de terminal \`md new [caminho_da_nova_feature]\` (e incluir \`-p [caminho]\` se houver pai). Em seguida, monte o Mermaid e as tabelas dentro do arquivo gerado e pare para aguardar aprovação visual.",
|
|
97
|
+
'md-edit': "Modo Edição. Abra o arquivo especificado, aplique a alteração no Mermaid ou tabelas mantendo a sintaxe 100% válida e incremente o cabeçalho \`\`.",
|
|
98
|
+
'md-audit': "Modo Auditoria Drástica de Legado. Analise o arquivo de código existente sob a ótica de legibilidade visual (MDDD):\n1. Se o código for modular, coeso e limpo: Execute o comando de terminal \`md new [diretorio_do_arquivo]\`. Em seguida, mapeie o fluxo atual no Mermaid, preencha as tabelas de decisão e defina a versão inicial estável como \`\`.\n2. Se o código for caótico, acoplado ou complexo: VOCÊ ESTÁ PROIBIDO de criar um diagrama estável. Em vez disso, aponte os problemas arquiteturais, sugira uma proposta de REFATORAÇÃO separando as responsabilidades e monte o Mermaid de como o fluxo DEVERIA SER pós-refatoração. Salve este arquivo spec com o status de rascunho: \`\`.",
|
|
99
|
+
'md-impl': "Modo Implementação. Leia o arquivo \`.spec.md\` do caminho como sua única Fonte da Verdade e escreva o código produtivo e testes equivalentes."
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
Object.keys(skills).forEach(skillName => {
|
|
103
|
+
// 1. Cria a pasta da skill: .agents/skills/md-new/
|
|
104
|
+
const skillFolder = path.join(skillsDir, skillName);
|
|
105
|
+
if (!fs.existsSync(skillFolder)) {
|
|
106
|
+
fs.mkdirSync(skillFolder);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 2. Cria o arquivo SKILL.md dentro dela: .agents/skills/md-new/SKILL.md
|
|
110
|
+
const skillFile = path.join(skillFolder, 'SKILL.md');
|
|
111
|
+
|
|
112
|
+
if (!fs.existsSync(skillFile)) {
|
|
113
|
+
// Adicionando um título automático para ficar mais organizado
|
|
114
|
+
const content = `# ${skillName.toUpperCase()}\n\n${skills[skillName]}`;
|
|
115
|
+
fs.writeFileSync(skillFile, content);
|
|
116
|
+
console.log(pc.green(`✅ Skill encapsulada: ${skillFile}`));
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
console.log(pc.green('✅ Arquivo universal [system_prompt.md] gerado na raiz do projeto!'));
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// ==========================================
|
|
124
|
+
// COMANDO: md new <targetPath>
|
|
125
|
+
// ==========================================
|
|
126
|
+
program
|
|
127
|
+
.command('new')
|
|
128
|
+
.description('Cria uma nova especificação colocalizada em Markdown, injeta versionamento e vincula ao fluxo pai')
|
|
129
|
+
.argument('<targetPath>', 'Caminho do diretório da feature (ex: src/home/guest)')
|
|
130
|
+
.option('-m, --macro', 'Define se o novo arquivo será um macro de módulo contendo stateDiagram-v2')
|
|
131
|
+
.option('-p, --parent <parentFile>', 'Caminho de um arquivo spec (.spec.md) existente para conectar este novo fluxo')
|
|
132
|
+
.action((targetPath, options) => {
|
|
133
|
+
if (!fs.existsSync(targetPath)) {
|
|
134
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const folderName = path.basename(targetPath);
|
|
138
|
+
const isMacro = options.macro;
|
|
139
|
+
|
|
140
|
+
// Extensão universal .spec.md para absolutamente tudo
|
|
141
|
+
const finalFile = path.join(targetPath, `${folderName}.spec.md`);
|
|
142
|
+
|
|
143
|
+
if (fs.existsSync(finalFile)) {
|
|
144
|
+
console.log(pc.yellow(`⚠️ A especificação já existe em: ${finalFile}`));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Geração dos templates otimizados para Cline/MDDD
|
|
149
|
+
let template = '';
|
|
150
|
+
const version = 'v1.0.0';
|
|
151
|
+
|
|
152
|
+
if (isMacro) {
|
|
153
|
+
template = `\n# Macro Módulo: ${folderName} | ${version}\n\n` +
|
|
154
|
+
`\`\`\`mermaid\n%% @spec-version ${version}\nstateDiagram-v2\n [*] --> Inicial_${folderName}\n\`\`\`\n\n` +
|
|
155
|
+
`## 3. Histórico de Auditoria\n<details>\n<summary>Clique para expandir</summary>\n\n\n\n</details>\n`;
|
|
156
|
+
} else {
|
|
157
|
+
template = `\n# Especificação: ${folderName} | ${version}\n\n` +
|
|
158
|
+
`## 1. Contrato de Fluxo (Mermaid)\n\`\`\`mermaid\n%% @spec-version ${version}\ngraph LR\n A([Início]) --> B[Processo]\n\`\`\`\n\n` +
|
|
159
|
+
`## 2. Matriz de Decisão\n| Condição | Ação | Próximo Estado |\n| :--- | :--- | :--- |\n| | | |\n\n` +
|
|
160
|
+
`## 3. Histórico de Auditoria\n<details>\n<summary>Clique para expandir</summary>\n\n\n\n</details>\n`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
fs.writeFileSync(finalFile, template);
|
|
164
|
+
console.log(pc.green(`✅ Novo arquivo Markdown criado com controle de versão (v1.0.0): ${finalFile}`));
|
|
165
|
+
|
|
166
|
+
// Lógica de Vinculação entre os arquivos Markdown
|
|
167
|
+
let macroPath = null;
|
|
168
|
+
if (options.parent) {
|
|
169
|
+
if (fs.existsSync(options.parent)) {
|
|
170
|
+
macroPath = options.parent;
|
|
171
|
+
console.log(pc.cyan('🎯 Usando o arquivo pai explícito enviado por parâmetro.'));
|
|
172
|
+
} else {
|
|
173
|
+
console.log(pc.red(`❌ O arquivo pai indicado não foi encontrado: ${options.parent}`));
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
} else if (!isMacro) {
|
|
177
|
+
macroPath = findClosestMacro(targetPath);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (macroPath) {
|
|
181
|
+
const relativePath = path.relative(path.dirname(macroPath), finalFile);
|
|
182
|
+
const cleanLinkPath = relativePath.replace(/\\/g, '/'); // Normaliza barras para padrão POSIX/Web
|
|
183
|
+
|
|
184
|
+
// Como o pai é um arquivo Markdown, injetamos uma seção de navegação limpa no fim do documento
|
|
185
|
+
const injection = `\n\n%% Conexão automática para sub-fluxo\n- [Ir para as regras de ${folderName}](file://./${cleanLinkPath})\n`;
|
|
186
|
+
|
|
187
|
+
fs.appendFileSync(macroPath, injection);
|
|
188
|
+
console.log(pc.blue(`🔗 Vinculado com sucesso no arquivo pai: ${macroPath}`));
|
|
189
|
+
} else if (!isMacro) {
|
|
190
|
+
console.log(pc.yellow('⚠️ Aviso: Nenhum arquivo macro (*.spec.md) acima na árvore foi encontrado para auto-vinculação.'));
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// ==========================================
|
|
195
|
+
// COMANDO: md edit <specFilePath> <instruction>
|
|
196
|
+
// ==========================================
|
|
197
|
+
program
|
|
198
|
+
.command('edit')
|
|
199
|
+
.description('Sinaliza uma alteração pendente em um arquivo de especificação Mermaid existente')
|
|
200
|
+
.argument('<specFilePath>', 'Caminho do arquivo spec (.spec.md)')
|
|
201
|
+
.argument('<instruction...>', 'A instrução de alteração ou ajuste de fluxo')
|
|
202
|
+
.action((specFilePath, instruction) => {
|
|
203
|
+
if (!fs.existsSync(specFilePath)) {
|
|
204
|
+
console.log(pc.red(`❌ Arquivo de especificação não encontrado: ${specFilePath}`));
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const fullInstruction = instruction.join(' ');
|
|
209
|
+
console.log(pc.cyan(`📝 Solicitando alteração no fluxo: "${specFilePath}"`));
|
|
210
|
+
console.log(pc.yellow(`⚙️ Instrução avaliada: ${fullInstruction}`));
|
|
211
|
+
console.log(pc.green(`\n🚀 Pronto! Use o atalho /md-edit no chat para a IA aplicar as alterações e incrementar a versão.`));
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// ==========================================
|
|
215
|
+
// COMANDO: md audit <codeFilePath>
|
|
216
|
+
// ==========================================
|
|
217
|
+
program
|
|
218
|
+
.command('audit')
|
|
219
|
+
.description('Audita um arquivo de código existente para criar uma especificação retroativa ou sugerir refatoração')
|
|
220
|
+
.argument('<codeFilePath>', 'Caminho do arquivo de código existente (ex: src/services/user.go)')
|
|
221
|
+
.action((codeFilePath) => {
|
|
222
|
+
if (!fs.existsSync(codeFilePath)) {
|
|
223
|
+
console.log(pc.red(`❌ Arquivo de código não encontrado: ${codeFilePath}`));
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const targetDir = path.dirname(codeFilePath);
|
|
228
|
+
const fileName = path.basename(codeFilePath);
|
|
229
|
+
|
|
230
|
+
console.log(pc.cyan(`🔍 Auditando estrutura de código para acoplamento em: ${fileName}...`));
|
|
231
|
+
console.log(pc.yellow(`⚡ Solicitando que a IA valide a complexidade antes de gerar a especificação MDDD.`));
|
|
232
|
+
|
|
233
|
+
if (!fs.existsSync(targetDir)) {
|
|
234
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
console.log(pc.green(`\n🚀 Pronto! Use o atalho /md-audit no chat para receber a análise ou o diagrama de refatoração.`));
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// ==========================================
|
|
241
|
+
// COMANDO: md impl <specFilePath>
|
|
242
|
+
// ==========================================
|
|
243
|
+
program
|
|
244
|
+
.command('impl')
|
|
245
|
+
.description('Prepara o ecossistema para implementar código produtivo e testes com base no arquivo spec')
|
|
246
|
+
.argument('<specFilePath>', 'Caminho do arquivo de especificação (.spec.md)')
|
|
247
|
+
.action((specFilePath) => {
|
|
248
|
+
if (!fs.existsSync(specFilePath)) {
|
|
249
|
+
console.log(pc.red(`❌ Arquivo de especificação não encontrado: ${specFilePath}`));
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const fileName = path.basename(specFilePath);
|
|
254
|
+
console.log(pc.cyan(`🛠️ Lendo o blueprint de negócio a partir de: ${fileName}...`));
|
|
255
|
+
console.log(pc.yellow(`🎯 Estabelecendo o diagrama assinado como Fonte Única da Verdade.`));
|
|
256
|
+
console.log(pc.green(`\n🚀 Pronto! Use o atalho /md-impl no chat para a IA iniciar a geração do código produtivo e dos testes.`));
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mddd-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI oficial para Mermaid Diagram Driven Development (MDDD) modular, colocalizado e versionado.",
|
|
5
|
+
"main": "bin/cli.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"md": "./bin/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18.0.0"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
18
|
+
"prepublishOnly": "npm prune --production"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mermaid",
|
|
22
|
+
"md",
|
|
23
|
+
"ai",
|
|
24
|
+
"diagram-driven",
|
|
25
|
+
"architecture",
|
|
26
|
+
"cli",
|
|
27
|
+
"mddd"
|
|
28
|
+
],
|
|
29
|
+
"author": "Julio Cesar Reis Filho <reisfilho1116@gmail.com>",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/JulioCRFilho/mermaid-diagram-driven-development"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/JulioCRFilho/mermaid-diagram-driven-development/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/JulioCRFilho/mermaid-diagram-driven-development#readme",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"commander": "^12.0.0",
|
|
41
|
+
"picocolors": "^1.0.0"
|
|
42
|
+
}
|
|
43
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Mermaid Diagram Driven Development (MDDD) CLI 🚀
|
|
2
|
+
|
|
3
|
+
Uma CLI agnóstica, ultra-leve e cirúrgica para implementar **MDDD (Mermaid Diagram Driven Development)** de forma modular, colocalizada e estritamente versionada.
|
|
4
|
+
|
|
5
|
+
Esta ferramenta automatiza a criação e a conexão de arquivos de especificação visual (Markdown + Mermaid). O objetivo é envelopar as regras de negócio em arquivos `.spec.md` para que qualquer IA de mercado (**Cursor, Windsurf, Claude Code, GitHub Copilot**, etc.) use esses diagramas como a **Fonte Única da Verdade** antes de tocar no código produtivo.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📌 O Conceito: MDDD
|
|
10
|
+
|
|
11
|
+
No **Mermaid Diagram Driven Development**, invertemos o ciclo tradicional de desenvolvimento orientado por chat de IA:
|
|
12
|
+
|
|
13
|
+
1. **Desenho (`/md-new`):** A IA e você criam a regra de negócio visualmente dentro do arquivo colocalizado `.spec.md`.
|
|
14
|
+
2. **Aprovação:** Você revisa o fluxo visual direto no preview do Markdown do seu editor de código.
|
|
15
|
+
3. **Edição (`/md-edit`):** Ajustes de escopo alteram o diagrama primeiro e incrementam a versão semântica do arquivo.
|
|
16
|
+
4. **Implementação (`/md-impl`):** A IA lê a especificação assinada e versionada para escrever o código definitivo e os testes unitários.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 🏗️ Arquitetura de Especificação Colocalizada (Co-location)
|
|
21
|
+
|
|
22
|
+
As especificações visuais não ficam centralizadas em pastas distantes. Elas vivem no mesmo diretório do componente, tela ou feature que descrevem.
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
src/
|
|
26
|
+
└── home/
|
|
27
|
+
├── home.spec.md # 🌎 MACRO: Visão global do módulo (stateDiagram-v2)
|
|
28
|
+
├── guest/
|
|
29
|
+
│ ├── guest.spec.md # 🔬 MICRO: Fluxo de tela (graph LR) + Matriz de Decisão
|
|
30
|
+
│ └── guest_page.dart # 💻 Código produtivo gerado pela IA
|
|
31
|
+
└── consumer/
|
|
32
|
+
└── consumer.spec.md # 🔬 MICRO: Fluxo de tela (graph LR) + Matriz de Decisão
|