@semacode/cli 0.8.2

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 (93) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +52 -0
  3. package/dist/cpp-symbols.d.ts +10 -0
  4. package/dist/cpp-symbols.js +71 -0
  5. package/dist/cpp-symbols.js.map +1 -0
  6. package/dist/dotnet-http.d.ts +23 -0
  7. package/dist/dotnet-http.js +301 -0
  8. package/dist/dotnet-http.js.map +1 -0
  9. package/dist/drift.d.ts +74 -0
  10. package/dist/drift.js +878 -0
  11. package/dist/drift.js.map +1 -0
  12. package/dist/go-http.d.ts +23 -0
  13. package/dist/go-http.js +90 -0
  14. package/dist/go-http.js.map +1 -0
  15. package/dist/importador.d.ts +29 -0
  16. package/dist/importador.js +2094 -0
  17. package/dist/importador.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +2150 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/java-http.d.ts +23 -0
  22. package/dist/java-http.js +204 -0
  23. package/dist/java-http.js.map +1 -0
  24. package/dist/projeto.d.ts +48 -0
  25. package/dist/projeto.js +560 -0
  26. package/dist/projeto.js.map +1 -0
  27. package/dist/python-http.d.ts +23 -0
  28. package/dist/python-http.js +200 -0
  29. package/dist/python-http.js.map +1 -0
  30. package/dist/rust-http.d.ts +23 -0
  31. package/dist/rust-http.js +95 -0
  32. package/dist/rust-http.js.map +1 -0
  33. package/dist/tipos.d.ts +3 -0
  34. package/dist/tipos.js +2 -0
  35. package/dist/tipos.js.map +1 -0
  36. package/dist/typescript-http.d.ts +35 -0
  37. package/dist/typescript-http.js +854 -0
  38. package/dist/typescript-http.js.map +1 -0
  39. package/logo.png +0 -0
  40. package/node_modules/@sema/gerador-dart/dist/index.d.ts +3 -0
  41. package/node_modules/@sema/gerador-dart/dist/index.js +44 -0
  42. package/node_modules/@sema/gerador-dart/dist/index.js.map +1 -0
  43. package/node_modules/@sema/gerador-dart/package.json +7 -0
  44. package/node_modules/@sema/gerador-python/dist/index.d.ts +6 -0
  45. package/node_modules/@sema/gerador-python/dist/index.js +510 -0
  46. package/node_modules/@sema/gerador-python/dist/index.js.map +1 -0
  47. package/node_modules/@sema/gerador-python/package.json +7 -0
  48. package/node_modules/@sema/gerador-typescript/dist/index.d.ts +6 -0
  49. package/node_modules/@sema/gerador-typescript/dist/index.js +646 -0
  50. package/node_modules/@sema/gerador-typescript/dist/index.js.map +1 -0
  51. package/node_modules/@sema/gerador-typescript/package.json +7 -0
  52. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +103 -0
  53. package/node_modules/@sema/nucleo/dist/ast/tipos.js +2 -0
  54. package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +1 -0
  55. package/node_modules/@sema/nucleo/dist/diagnosticos/index.d.ts +21 -0
  56. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js +12 -0
  57. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +1 -0
  58. package/node_modules/@sema/nucleo/dist/formatador/index.d.ts +9 -0
  59. package/node_modules/@sema/nucleo/dist/formatador/index.js +289 -0
  60. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -0
  61. package/node_modules/@sema/nucleo/dist/index.d.ts +34 -0
  62. package/node_modules/@sema/nucleo/dist/index.js +95 -0
  63. package/node_modules/@sema/nucleo/dist/index.js.map +1 -0
  64. package/node_modules/@sema/nucleo/dist/ir/conversor.d.ts +5 -0
  65. package/node_modules/@sema/nucleo/dist/ir/conversor.js +241 -0
  66. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -0
  67. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +131 -0
  68. package/node_modules/@sema/nucleo/dist/ir/modelos.js +2 -0
  69. package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +1 -0
  70. package/node_modules/@sema/nucleo/dist/lexer/lexer.d.ts +7 -0
  71. package/node_modules/@sema/nucleo/dist/lexer/lexer.js +122 -0
  72. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +1 -0
  73. package/node_modules/@sema/nucleo/dist/lexer/tokens.d.ts +8 -0
  74. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +30 -0
  75. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -0
  76. package/node_modules/@sema/nucleo/dist/parser/parser.d.ts +9 -0
  77. package/node_modules/@sema/nucleo/dist/parser/parser.js +423 -0
  78. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -0
  79. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +52 -0
  80. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +837 -0
  81. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -0
  82. package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +99 -0
  83. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +395 -0
  84. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +1 -0
  85. package/node_modules/@sema/nucleo/dist/util/arquivos.d.ts +2 -0
  86. package/node_modules/@sema/nucleo/dist/util/arquivos.js +25 -0
  87. package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +1 -0
  88. package/node_modules/@sema/nucleo/package.json +7 -0
  89. package/node_modules/@sema/padroes/dist/index.d.ts +20 -0
  90. package/node_modules/@sema/padroes/dist/index.js +79 -0
  91. package/node_modules/@sema/padroes/dist/index.js.map +1 -0
  92. package/node_modules/@sema/padroes/package.json +7 -0
  93. package/package.json +57 -0
package/dist/index.js ADDED
@@ -0,0 +1,2150 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { spawnSync } from "node:child_process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { compilarCodigo, formatarCodigo, formatarDiagnosticos, lerArquivoTexto, temErros, } from "@sema/nucleo";
7
+ import { descreverEstruturaModulo } from "@sema/padroes";
8
+ import { gerarDart } from "@sema/gerador-dart";
9
+ import { gerarPython } from "@sema/gerador-python";
10
+ import { gerarTypeScript } from "@sema/gerador-typescript";
11
+ import { carregarConfiguracaoProjeto, carregarProjeto, resolverAlvoPadrao, resolverAlvosVerificacao, resolverEstruturaSaidaPadrao, resolverFrameworkPadrao, resolverSaidaPadrao, } from "./projeto.js";
12
+ import { importarProjetoLegado, resumoImportacao } from "./importador.js";
13
+ import { analisarDriftLegado } from "./drift.js";
14
+ const STARTER_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao para IA e backend vivo.
15
+
16
+ Importante:
17
+ - a Sema se apresenta publicamente como protocolo e funciona tecnicamente como linguagem de intencao
18
+ - a Sema modela contratos, estados, fluxos, erros, efeitos e garantias
19
+ - a Sema gera codigo e scaffolding real para TypeScript, Python e Dart
20
+ - a Sema pode servir de base para interfaces graficas elegantes e coerentes
21
+ - a Sema nao gera uma interface completa sozinha no estado atual
22
+ - trate a Sema como cerebro semantico da aplicacao, nao como gerador magico de front-end pronto
23
+ - se a tarefa envolver UI, prefira pedir Sema + React + TypeScript ou Sema + arquitetura de front-end
24
+ - evite pedir HTML unico solto quando a intencao for testar a Sema de verdade
25
+
26
+ Regras:
27
+ - nao invente sintaxe fora da gramatica e dos exemplos oficiais
28
+ - trate \`ir --json\` como fonte de verdade semantica
29
+ - trate \`diagnosticos --json\` como fonte de correcao
30
+ - use \`sema formatar\` como fonte unica de estilo
31
+ - preserve a intencao do contrato
32
+
33
+ Comandos essenciais:
34
+ - contexto completo do modulo: \`sema contexto-ia <arquivo.sema>\`
35
+ - estrutura sintatica: \`sema ast <arquivo.sema> --json\`
36
+ - estrutura semantica: \`sema ir <arquivo.sema> --json\`
37
+ - validacao: \`sema validar <arquivo.sema> --json\`
38
+ - diagnosticos: \`sema diagnosticos <arquivo.sema> --json\`
39
+ - formatacao: \`sema formatar <arquivo.sema>\`
40
+ - geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>\`
41
+ - verificacao final: \`sema verificar <arquivo-ou-pasta> [--json]\`
42
+
43
+ Antes de editar:
44
+ 1. leia README, docs de IA e um exemplo oficial parecido
45
+ 2. consulte AST e IR do modulo alvo
46
+
47
+ Depois de editar:
48
+ 1. rode \`sema formatar\`
49
+ 2. rode \`sema validar --json\`
50
+ 3. se houver falha, use \`diagnosticos --json\`
51
+ 4. se a tarefa pedir codigo derivado, rode \`sema compilar\`
52
+ 5. feche com \`sema verificar\` ou \`npm run project:check\`
53
+
54
+ Priorize sempre:
55
+ - exemplos oficiais
56
+ - JSON da CLI
57
+ - consistencia semantica
58
+
59
+ Nao improvise quando faltar contexto.
60
+ `;
61
+ const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para facilitar entendimento e operacao por IA.
62
+
63
+ Trate a Sema como camada semantica e linguagem de especificacao executavel. Nao invente sintaxe, palavras-chave ou blocos fora da gramatica e dos exemplos oficiais.
64
+
65
+ Fontes de verdade, em ordem:
66
+ 1. README do projeto
67
+ 2. gramatica e documentacao de sintaxe da Sema
68
+ 3. especificacao semantica da linguagem
69
+ 4. exemplos oficiais, com prioridade para o vertical de pagamento
70
+ 5. AST, IR e diagnosticos exportados pela CLI em JSON
71
+
72
+ Regras de operacao:
73
+ - preserve o significado semantico
74
+ - use o formatador oficial da Sema como fonte unica de estilo
75
+ - use diagnosticos estruturados como contrato de correcao
76
+ - use a IR como fonte de verdade semantica quando houver duvida
77
+ - nao conclua uma alteracao sem validar e verificar o modulo
78
+
79
+ Antes de editar \`.sema\`, entenda:
80
+ - o module alvo
81
+ - os contratos de task, route, error, effects, guarantees, state e flow
82
+ - os exemplos oficiais relacionados
83
+
84
+ Depois de editar \`.sema\`, execute este fluxo:
85
+ 1. formatar
86
+ 2. validar
87
+ 3. diagnosticar, se houver falha
88
+ 4. verificar
89
+
90
+ Se houver conflito entre texto livre e IR/diagnosticos, priorize a IR e os diagnosticos da CLI.
91
+
92
+ Se algo nao estiver claro, siga a forma ja usada nos exemplos oficiais. Nao improvise sem base.
93
+ `;
94
+ const PROMPT_IA_UI = `Atue como Engenheiro de Software Senior e UX/UI Designer de elite.
95
+
96
+ Quero que voce trabalhe com Sema como fonte de verdade semantica do sistema e com React + TypeScript como camada de interface.
97
+
98
+ Entregue obrigatoriamente duas partes integradas:
99
+ 1. os arquivos \`.sema\` do dominio
100
+ 2. a proposta ou implementacao da interface em React + TypeScript
101
+
102
+ Regras:
103
+ - nao entregue apenas HTML solto em arquivo unico
104
+ - nao trate a Sema como enfeite conceitual
105
+ - a interface deve nascer do contrato semantico definido em Sema
106
+ - use os exemplos oficiais da Sema como referencia de estilo e semantica
107
+ - nao invente sintaxe fora da gramatica suportada
108
+
109
+ A Sema deve modelar, quando fizer sentido:
110
+ - \`module\`
111
+ - \`use\`
112
+ - \`entity\`
113
+ - \`enum\`
114
+ - \`state\`
115
+ - \`task\`
116
+ - \`flow\`
117
+ - \`route\`
118
+ - \`effects\`
119
+ - \`error\`
120
+ - \`guarantees\`
121
+ - \`tests\`
122
+ - \`docs\`
123
+
124
+ A interface deve refletir visualmente:
125
+ - \`state\` como status e progresso observavel
126
+ - \`flow\` como etapas ou orquestracao visivel
127
+ - \`error\` como falhas tratadas com clareza
128
+ - \`effects\` como operacoes relevantes para usuario ou operacao
129
+ - \`guarantees\` como confianca, confirmacao ou consistencia final
130
+
131
+ Estruture a entrega assim:
132
+ 1. visao do produto
133
+ 2. dominio modelado em Sema
134
+ 3. arquitetura de pastas em React + TypeScript
135
+ 4. componentes principais
136
+ 5. estrategia visual
137
+ 6. codigo principal da interface
138
+ 7. explicacao curta de como a UI conversa com a semantica da Sema
139
+
140
+ Se a tarefa envolver app visual, a Sema governa o significado e o React renderiza a experiencia. Nao atropele essa separacao.
141
+ `;
142
+ const PROMPT_IA_REACT = `Crie uma solucao com Sema + React + TypeScript.
143
+
144
+ Regras principais:
145
+ - a Sema deve ser a fonte de verdade semantica do dominio
146
+ - React + TypeScript deve ser a camada de interface e experiencia
147
+ - nao entregue HTML unico solto
148
+ - nao trate a Sema como enfeite
149
+
150
+ Entregue obrigatoriamente:
151
+ 1. arquivos \`.sema\` do dominio
152
+ 2. arquitetura de pastas do frontend
153
+ 3. componentes React principais
154
+ 4. contratos e tipos derivados da semantica
155
+ 5. interface elegante e implementavel
156
+
157
+ A modelagem Sema deve cobrir, quando fizer sentido:
158
+ - \`entity\`
159
+ - \`enum\`
160
+ - \`state\`
161
+ - \`task\`
162
+ - \`flow\`
163
+ - \`route\`
164
+ - \`effects\`
165
+ - \`error\`
166
+ - \`guarantees\`
167
+ - \`tests\`
168
+
169
+ A interface React deve tornar visiveis:
170
+ - estado atual e transicoes relevantes
171
+ - fluxo operacional
172
+ - erros publicos
173
+ - efeitos operacionais importantes
174
+ - garantias ou confirmacoes finais
175
+
176
+ Estruture a entrega assim:
177
+ 1. visao do produto
178
+ 2. arquivos \`.sema\`
179
+ 3. arquitetura React + TypeScript
180
+ 4. componentes e telas
181
+ 5. codigo principal
182
+ 6. explicacao de como a UI deriva da semantica da Sema
183
+
184
+ Se houver duvida, siga os exemplos oficiais e mantenha a separacao:
185
+ - Sema governa o significado
186
+ - React governa a apresentacao
187
+ `;
188
+ const PROMPT_IA_SEMA_PRIMEIRO = `Quero que voce trabalhe no modo "Sema primeiro".
189
+
190
+ Regra principal:
191
+ - modele primeiro o dominio em arquivos \`.sema\`
192
+ - so depois proponha ou gere codigo de aplicacao derivado disso
193
+
194
+ Fluxo obrigatorio:
195
+ 1. entender o dominio pedido
196
+ 2. modelar o contrato em Sema
197
+ 3. validar coerencia entre \`task\`, \`route\`, \`state\`, \`flow\`, \`error\`, \`effects\` e \`guarantees\`
198
+ 4. so depois gerar TypeScript, Python, React ou outra camada de implementacao
199
+
200
+ Nao entregue apenas codigo de interface ou codigo imperativo direto sem antes entregar a camada semantica.
201
+
202
+ A modelagem em Sema deve:
203
+ - preservar a intencao do dominio
204
+ - explicitar entradas, saidas, erros, efeitos e garantias
205
+ - usar apenas blocos e sintaxe oficiais
206
+ - incluir testes embutidos quando fizer sentido
207
+
208
+ Se houver interface grafica:
209
+ - entregue a modelagem Sema primeiro
210
+ - depois explique como a interface deve refletir a semantica
211
+ - se gerar UI, use React + TypeScript em vez de HTML unico solto
212
+
213
+ Se houver backend:
214
+ - entregue a modelagem Sema primeiro
215
+ - depois gere a borda publica e a implementacao derivada
216
+
217
+ Nao pule a etapa semantica. A camada \`.sema\` e a ancora principal da solucao.
218
+ `;
219
+ const EXEMPLOS_PROMPT_IA = `Exemplos de prompt oficial para trabalhar com Sema
220
+
221
+ 1. Sema primeiro
222
+
223
+ Crie uma solucao seguindo a estrategia "Sema primeiro".
224
+ Entregue primeiro os arquivos \`.sema\` do dominio e so depois a implementacao derivada.
225
+ Nao entregue apenas codigo imperativo.
226
+ Use Sema como fonte de verdade para contratos, estados, erros, efeitos e garantias.
227
+
228
+ 2. Sema + React + TypeScript
229
+
230
+ Crie um projeto com Sema + React + TypeScript.
231
+ Entregue:
232
+ - os arquivos \`.sema\` do dominio
233
+ - a arquitetura de pastas do frontend
234
+ - componentes React que reflitam \`state\`, \`flow\`, \`error\`, \`effects\` e \`guarantees\`
235
+ - uma interface elegante e implementavel
236
+ - nao entregue HTML solto em arquivo unico
237
+
238
+ 3. Revisar ou corrigir um modulo Sema
239
+
240
+ Revise e corrija um modulo \`.sema\`.
241
+ Antes de editar:
242
+ - leia os exemplos oficiais parecidos
243
+ - consulte AST e IR
244
+ Depois de editar:
245
+ - rode \`sema formatar\`
246
+ - rode \`sema validar --json\`
247
+ - use \`diagnosticos --json\` se houver falha
248
+ - feche com \`sema verificar\`
249
+
250
+ 4. Caso de UI sem perder a semantica
251
+
252
+ Quero uma interface premium para este dominio, mas a solucao deve continuar ancorada em Sema.
253
+ Modele primeiro o dominio em \`.sema\`.
254
+ Depois proponha uma interface em React + TypeScript que torne visiveis:
255
+ - estado
256
+ - fluxo
257
+ - erros
258
+ - efeitos
259
+ - garantias
260
+ Nao transforme isso em um \`index.html\` solto.
261
+
262
+ Comandos uteis da CLI para esse fluxo:
263
+ - \`sema starter-ia\`
264
+ - \`sema ajuda-ia\`
265
+ - \`sema prompt-ia\`
266
+ - \`sema prompt-ia-ui\`
267
+ - \`sema prompt-ia-react\`
268
+ - \`sema prompt-ia-sema-primeiro\`
269
+ - \`sema contexto-ia <arquivo.sema>\`
270
+ `;
271
+ const DIRETORIO_CLI_ATUAL = path.dirname(fileURLToPath(import.meta.url));
272
+ function obterArgumentos() {
273
+ const [, , comando, ...resto] = process.argv;
274
+ return { comando: comando, resto };
275
+ }
276
+ function ajuda() {
277
+ return `Sema CLI
278
+
279
+ Comandos:
280
+ sema iniciar
281
+ sema validar <arquivo-ou-pasta>
282
+ sema ast <arquivo.sema>
283
+ sema ir <arquivo.sema>
284
+ sema compilar <arquivo-ou-pasta> --alvo <python|typescript|dart> --saida <diretorio> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]
285
+ sema gerar <python|typescript|dart> <arquivo-ou-pasta> --saida <diretorio> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]
286
+ sema testar <arquivo.sema> --alvo <python|typescript|dart> --saida <diretorio-temporario> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]
287
+ sema diagnosticos <arquivo.sema> [--json]
288
+ sema verificar <arquivo-ou-pasta> [--saida <diretorio-base>] [--json]
289
+ sema inspecionar [arquivo-ou-pasta] [--json]
290
+ sema drift <arquivo-ou-pasta> [--json]
291
+ sema importar <nestjs|fastapi|flask|nextjs|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]
292
+ sema doctor
293
+ sema formatar <arquivo-ou-pasta> [--check] [--json]
294
+ sema ajuda-ia
295
+ sema starter-ia
296
+ sema prompt-ia
297
+ sema prompt-ia-ui
298
+ sema prompt-ia-react
299
+ sema prompt-ia-sema-primeiro
300
+ sema exemplos-prompt-ia
301
+ sema contexto-ia <arquivo.sema> [--saida <diretorio>] [--json]
302
+ `;
303
+ }
304
+ async function carregarModulos(entrada, cwd = process.cwd()) {
305
+ return (await carregarProjeto(entrada, cwd)).modulosSelecionados;
306
+ }
307
+ async function escreverArquivos(base, arquivos) {
308
+ await mkdir(base, { recursive: true });
309
+ for (const arquivo of arquivos) {
310
+ const destino = path.join(base, arquivo.caminhoRelativo);
311
+ await mkdir(path.dirname(destino), { recursive: true });
312
+ await writeFile(destino, arquivo.conteudo, "utf8");
313
+ }
314
+ }
315
+ function obterOpcao(args, nome, padrao) {
316
+ const indice = args.findIndex((arg) => arg === nome);
317
+ if (indice === -1) {
318
+ return padrao;
319
+ }
320
+ return args[indice + 1] ?? padrao;
321
+ }
322
+ function possuiFlag(args, nome) {
323
+ return args.includes(nome);
324
+ }
325
+ function obterPosicionais(args) {
326
+ const posicionais = [];
327
+ for (let indice = 0; indice < args.length; indice += 1) {
328
+ const atual = args[indice];
329
+ if (atual.startsWith("--")) {
330
+ indice += 1;
331
+ continue;
332
+ }
333
+ posicionais.push(atual);
334
+ }
335
+ return posicionais;
336
+ }
337
+ function comandoDisponivel(comando, argumentos = ["--version"]) {
338
+ const execucao = spawnSync(comando, argumentos, { stdio: "ignore", shell: process.platform === "win32" });
339
+ return (execucao.status ?? 1) === 0;
340
+ }
341
+ async function comandoDoctor() {
342
+ const checks = [
343
+ { nome: "node", ok: comandoDisponivel("node") },
344
+ { nome: "npm", ok: comandoDisponivel("npm") },
345
+ { nome: "python", ok: comandoDisponivel("python") || comandoDisponivel("py") },
346
+ { nome: "dotnet", ok: comandoDisponivel("dotnet") },
347
+ { nome: "go", ok: comandoDisponivel("go") },
348
+ { nome: "cargo", ok: comandoDisponivel("cargo") },
349
+ { nome: "java", ok: comandoDisponivel("java") },
350
+ { nome: "code", ok: comandoDisponivel("code", ["--version"]) },
351
+ ];
352
+ console.log("Sema doctor");
353
+ for (const check of checks) {
354
+ console.log(`- ${check.nome}: ${check.ok ? "ok" : "ausente"}`);
355
+ }
356
+ const obrigatorios = checks.filter((check) => ["node", "npm"].includes(check.nome));
357
+ return obrigatorios.every((check) => check.ok) ? 0 : 1;
358
+ }
359
+ function validarCompatibilidadeFramework(alvo, framework) {
360
+ if (framework === "base") {
361
+ return undefined;
362
+ }
363
+ if (framework === "nestjs" && alvo !== "typescript") {
364
+ return `Framework "${framework}" so pode ser usado com o alvo typescript.`;
365
+ }
366
+ if (framework === "fastapi" && alvo !== "python") {
367
+ return `Framework "${framework}" so pode ser usado com o alvo python.`;
368
+ }
369
+ if (alvo === "dart") {
370
+ return `Framework "${framework}" nao e suportado para o alvo dart.`;
371
+ }
372
+ return undefined;
373
+ }
374
+ function normalizarFonteImportacao(valor) {
375
+ if (!valor) {
376
+ return undefined;
377
+ }
378
+ if (valor === "ts") {
379
+ return "typescript";
380
+ }
381
+ if (valor === "py") {
382
+ return "python";
383
+ }
384
+ if (valor === "nest") {
385
+ return "nestjs";
386
+ }
387
+ if (valor === "api") {
388
+ return "fastapi";
389
+ }
390
+ if (valor === "next") {
391
+ return "nextjs";
392
+ }
393
+ if (valor === "fb") {
394
+ return "firebase";
395
+ }
396
+ if (valor === "csharp" || valor === "cs" || valor === "dotnet") {
397
+ return "dotnet";
398
+ }
399
+ if (valor === "java") {
400
+ return "java";
401
+ }
402
+ if (valor === "go" || valor === "golang") {
403
+ return "go";
404
+ }
405
+ if (valor === "rust" || valor === "rs") {
406
+ return "rust";
407
+ }
408
+ if (valor === "cpp" || valor === "cxx" || valor === "cc" || valor === "c++") {
409
+ return "cpp";
410
+ }
411
+ if (valor === "nestjs"
412
+ || valor === "fastapi"
413
+ || valor === "flask"
414
+ || valor === "nextjs"
415
+ || valor === "firebase"
416
+ || valor === "dotnet"
417
+ || valor === "java"
418
+ || valor === "go"
419
+ || valor === "rust"
420
+ || valor === "cpp"
421
+ || valor === "typescript"
422
+ || valor === "python"
423
+ || valor === "dart") {
424
+ return valor;
425
+ }
426
+ return undefined;
427
+ }
428
+ function normalizarTemplateIniciar(valor) {
429
+ if (valor === "nestjs"
430
+ || valor === "fastapi"
431
+ || valor === "nextjs-api"
432
+ || valor === "node-firebase-worker"
433
+ || valor === "aspnet-api"
434
+ || valor === "springboot-api"
435
+ || valor === "go-http-api"
436
+ || valor === "rust-axum-api"
437
+ || valor === "cpp-service-bridge") {
438
+ return valor;
439
+ }
440
+ return "base";
441
+ }
442
+ function garantirIr(resultado, caminho) {
443
+ if (!resultado.ir) {
444
+ throw new Error(`Nao foi possivel gerar IR para ${caminho}.\n${formatarDiagnosticos(resultado.diagnosticos)}`);
445
+ }
446
+ return resultado.ir;
447
+ }
448
+ function gerarArquivosPorAlvo(ir, alvo, framework) {
449
+ if (alvo === "python") {
450
+ return gerarPython(ir, { framework });
451
+ }
452
+ if (alvo === "dart") {
453
+ return gerarDart(ir);
454
+ }
455
+ return gerarTypeScript(ir, { framework });
456
+ }
457
+ function aplicarEstruturaSaida(arquivos, ir, estrutura) {
458
+ if (estrutura === "flat" || estrutura === "backend") {
459
+ return arquivos;
460
+ }
461
+ const estruturaModulo = descreverEstruturaModulo(ir.nome);
462
+ const pastaModulo = estruturaModulo.contextoSegmentos.join(path.sep);
463
+ const nomeArquivo = estruturaModulo.nomeArquivo;
464
+ const nomeBaseAntigo = estruturaModulo.nomeBase;
465
+ return arquivos.map((arquivo) => {
466
+ const basename = path.basename(arquivo.caminhoRelativo);
467
+ let novoBasename = basename;
468
+ let conteudo = arquivo.conteudo;
469
+ if (basename === `${nomeBaseAntigo}.ts`) {
470
+ novoBasename = `${nomeArquivo}.ts`;
471
+ }
472
+ else if (basename === `${nomeBaseAntigo}.test.ts`) {
473
+ novoBasename = `${nomeArquivo}.test.ts`;
474
+ conteudo = conteudo.replace(`./${nomeBaseAntigo}.ts`, `./${nomeArquivo}.ts`);
475
+ }
476
+ else if (basename === `${nomeBaseAntigo}.py`) {
477
+ novoBasename = `${nomeArquivo}.py`;
478
+ }
479
+ else if (basename === `test_${nomeBaseAntigo}.py`) {
480
+ novoBasename = `test_${nomeArquivo}.py`;
481
+ conteudo = conteudo.replace(`from ${nomeBaseAntigo} import *`, `from ${nomeArquivo} import *`);
482
+ }
483
+ else if (basename === `${nomeBaseAntigo}.dart`) {
484
+ novoBasename = `${nomeArquivo}.dart`;
485
+ }
486
+ return {
487
+ caminhoRelativo: pastaModulo ? path.join(pastaModulo, novoBasename) : novoBasename,
488
+ conteudo,
489
+ };
490
+ });
491
+ }
492
+ function contarCasosDeTesteGerados(alvo, arquivos) {
493
+ if (alvo === "dart") {
494
+ return 0;
495
+ }
496
+ if (alvo === "typescript") {
497
+ const arquivoTeste = arquivos.find((item) => item.caminhoRelativo.endsWith(".test.ts"));
498
+ if (!arquivoTeste) {
499
+ return 0;
500
+ }
501
+ return (arquivoTeste.conteudo.match(/\btest\(/g) ?? []).length;
502
+ }
503
+ const arquivoTeste = arquivos.find((item) => path.basename(item.caminhoRelativo).startsWith("test_"));
504
+ if (!arquivoTeste) {
505
+ return 0;
506
+ }
507
+ return (arquivoTeste.conteudo.match(/\bdef test_/g) ?? []).length;
508
+ }
509
+ function executarTestesGerados(alvo, baseSaida, arquivos, silencioso = false) {
510
+ const quantidadeTestes = contarCasosDeTesteGerados(alvo, arquivos);
511
+ if (quantidadeTestes === 0) {
512
+ if (!silencioso) {
513
+ console.log(`Nenhum teste ${alvo === "typescript" ? "TypeScript" : "Python"} foi gerado.`);
514
+ }
515
+ return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
516
+ }
517
+ if (alvo === "typescript") {
518
+ const arquivoTeste = arquivos.find((item) => item.caminhoRelativo.endsWith(".test.ts"))?.caminhoRelativo;
519
+ if (!arquivoTeste) {
520
+ if (!silencioso) {
521
+ console.log("Nenhum teste TypeScript foi gerado.");
522
+ }
523
+ return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
524
+ }
525
+ const execucao = spawnSync("node", ["--import", "tsx", path.join(baseSaida, arquivoTeste)], {
526
+ stdio: silencioso ? "pipe" : "inherit",
527
+ encoding: silencioso ? "utf8" : undefined,
528
+ });
529
+ return {
530
+ codigoSaida: execucao.status ?? 1,
531
+ quantidadeTestes,
532
+ saidaPadrao: typeof execucao.stdout === "string" ? execucao.stdout : "",
533
+ saidaErro: typeof execucao.stderr === "string" ? execucao.stderr : "",
534
+ };
535
+ }
536
+ const arquivoTeste = arquivos.find((item) => path.basename(item.caminhoRelativo).startsWith("test_"))?.caminhoRelativo;
537
+ if (!arquivoTeste) {
538
+ if (!silencioso) {
539
+ console.log("Nenhum teste Python foi gerado.");
540
+ }
541
+ return { codigoSaida: 0, quantidadeTestes, saidaPadrao: "", saidaErro: "" };
542
+ }
543
+ const execucao = spawnSync("pytest", [arquivoTeste], {
544
+ stdio: silencioso ? "pipe" : "inherit",
545
+ cwd: baseSaida,
546
+ encoding: silencioso ? "utf8" : undefined,
547
+ });
548
+ return {
549
+ codigoSaida: execucao.status ?? 1,
550
+ quantidadeTestes,
551
+ saidaPadrao: typeof execucao.stdout === "string" ? execucao.stdout : "",
552
+ saidaErro: typeof execucao.stderr === "string" ? execucao.stderr : "",
553
+ };
554
+ }
555
+ function nomeSubpastaModulo(caminhoArquivo) {
556
+ return path.basename(caminhoArquivo, ".sema");
557
+ }
558
+ async function caminhoExiste(caminhoAlvo) {
559
+ try {
560
+ await stat(caminhoAlvo);
561
+ return true;
562
+ }
563
+ catch {
564
+ return false;
565
+ }
566
+ }
567
+ async function descobrirDocsIa() {
568
+ const candidatosBase = [];
569
+ let atual = DIRETORIO_CLI_ATUAL;
570
+ for (let tentativas = 0; tentativas < 8; tentativas += 1) {
571
+ candidatosBase.push(atual);
572
+ const proximo = path.dirname(atual);
573
+ if (proximo === atual) {
574
+ break;
575
+ }
576
+ atual = proximo;
577
+ }
578
+ const nomesDocs = [
579
+ "AGENT_STARTER.md",
580
+ "como-ensinar-a-sema-para-ia.md",
581
+ "prompt-base-ia-sema.md",
582
+ "fluxo-pratico-ia-sema.md",
583
+ ];
584
+ for (const base of candidatosBase) {
585
+ const documentos = [];
586
+ let encontrouTodos = true;
587
+ for (const nome of nomesDocs) {
588
+ const caminhoDoc = path.join(base, "docs", nome);
589
+ if (!(await caminhoExiste(caminhoDoc))) {
590
+ encontrouTodos = false;
591
+ break;
592
+ }
593
+ documentos.push({ nome, caminho: caminhoDoc });
594
+ }
595
+ if (encontrouTodos) {
596
+ return {
597
+ origemInstalacao: DIRETORIO_CLI_ATUAL,
598
+ baseDetectada: base,
599
+ documentos,
600
+ };
601
+ }
602
+ }
603
+ return {
604
+ origemInstalacao: DIRETORIO_CLI_ATUAL,
605
+ baseDetectada: null,
606
+ documentos: [],
607
+ };
608
+ }
609
+ function renderizarCabecalhoDocsIa(descoberta) {
610
+ const linhas = [
611
+ "Informacoes da instalacao atual",
612
+ `- Origem da instalacao: ${descoberta.origemInstalacao}`,
613
+ `- Base detectada: ${descoberta.baseDetectada ?? "nao encontrada"}`,
614
+ ];
615
+ if (descoberta.documentos.length > 0) {
616
+ linhas.push("- Documentos locais encontrados:");
617
+ for (const documento of descoberta.documentos) {
618
+ linhas.push(` - ${documento.nome}: ${documento.caminho}`);
619
+ }
620
+ }
621
+ else {
622
+ linhas.push("- Documentos locais encontrados: nenhum");
623
+ linhas.push(" - Esta instalacao da CLI nao conseguiu localizar a pasta docs ao redor do pacote atual.");
624
+ }
625
+ return linhas.join("\n");
626
+ }
627
+ function falharContextoIa(mensagem) {
628
+ throw new Error(mensagem);
629
+ }
630
+ function garantirArquivoSema(caminhoArquivo) {
631
+ if (!caminhoArquivo.toLowerCase().endsWith(".sema")) {
632
+ falharContextoIa("O caminho informado precisa apontar para um arquivo .sema.");
633
+ }
634
+ }
635
+ function resumirDriftPorModulo(modulo, caminho, resultadoDrift) {
636
+ const tasks = modulo
637
+ ? resultadoDrift.tasks.filter((task) => task.modulo === modulo)
638
+ : [];
639
+ const implsValidos = modulo
640
+ ? resultadoDrift.impls_validos.filter((impl) => impl.modulo === modulo)
641
+ : [];
642
+ const implsQuebrados = modulo
643
+ ? resultadoDrift.impls_quebrados.filter((impl) => impl.modulo === modulo)
644
+ : [];
645
+ const rotasDivergentes = modulo
646
+ ? resultadoDrift.rotas_divergentes.filter((rota) => rota.modulo === modulo)
647
+ : [];
648
+ const recursosValidos = modulo
649
+ ? resultadoDrift.recursos_validos.filter((recurso) => recurso.modulo === modulo)
650
+ : [];
651
+ const recursosDivergentes = modulo
652
+ ? resultadoDrift.recursos_divergentes.filter((recurso) => recurso.modulo === modulo)
653
+ : [];
654
+ return {
655
+ caminho,
656
+ modulo,
657
+ implsValidos: implsValidos.length,
658
+ implsQuebrados: implsQuebrados.length,
659
+ recursosValidos: recursosValidos.length,
660
+ recursosDivergentesCount: recursosDivergentes.length,
661
+ tasksSemImplementacao: tasks.filter((task) => task.semImplementacao).length,
662
+ arquivosRelacionados: [...new Set([
663
+ ...tasks.flatMap((task) => task.arquivosReferenciados),
664
+ ...implsValidos.map((impl) => impl.arquivo).filter((item) => Boolean(item)),
665
+ ...implsQuebrados.flatMap((impl) => impl.candidatos?.map((candidato) => candidato.arquivo) ?? []),
666
+ ...recursosValidos.map((recurso) => recurso.arquivo).filter(Boolean),
667
+ ...recursosDivergentes.map((recurso) => recurso.arquivo).filter(Boolean),
668
+ ])].sort((a, b) => a.localeCompare(b, "pt-BR")),
669
+ tasks,
670
+ rotasDivergentes,
671
+ recursosDivergentes,
672
+ };
673
+ }
674
+ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
675
+ const arquivo = path.resolve(arquivoEntrada);
676
+ garantirArquivoSema(arquivo);
677
+ const pastaBase = pastaSaidaOpcional
678
+ ? path.resolve(pastaSaidaOpcional)
679
+ : path.resolve(process.cwd(), ".tmp", "contexto-ia", path.basename(arquivo, ".sema"));
680
+ await mkdir(pastaBase, { recursive: true });
681
+ const contextoProjeto = await carregarProjeto(arquivo, process.cwd());
682
+ const resultadoModulo = contextoProjeto.modulosSelecionados.find((item) => path.resolve(item.caminho) === arquivo)?.resultado;
683
+ if (!resultadoModulo) {
684
+ falharContextoIa(`Nao foi possivel encontrar o modulo correspondente ao arquivo ${arquivo}.`);
685
+ }
686
+ const sucesso = !temErros(resultadoModulo.diagnosticos);
687
+ const modulo = resultadoModulo.modulo?.nome ?? path.basename(arquivo, ".sema");
688
+ const resultadoDrift = await analisarDriftLegado(contextoProjeto);
689
+ const drift = {
690
+ comando: "drift",
691
+ caminho: arquivo,
692
+ modulo: resultadoModulo.modulo?.nome ?? null,
693
+ sucesso: resultadoDrift.sucesso,
694
+ resumo: resumirDriftPorModulo(resultadoModulo.modulo?.nome ?? null, arquivo, resultadoDrift),
695
+ drift: resultadoDrift,
696
+ };
697
+ const validar = {
698
+ comando: "validar",
699
+ sucesso,
700
+ resultados: [
701
+ {
702
+ caminho: arquivo,
703
+ modulo: resultadoModulo.modulo?.nome ?? null,
704
+ sucesso,
705
+ diagnosticos: resultadoModulo.diagnosticos,
706
+ },
707
+ ],
708
+ };
709
+ const diagnosticos = {
710
+ comando: "diagnosticos",
711
+ caminho: arquivo,
712
+ modulo: resultadoModulo.modulo?.nome ?? null,
713
+ diagnosticos: resultadoModulo.diagnosticos,
714
+ };
715
+ const ast = {
716
+ comando: "ast",
717
+ caminho: arquivo,
718
+ modulo: resultadoModulo.modulo?.nome ?? null,
719
+ sucesso,
720
+ diagnosticos: resultadoModulo.diagnosticos,
721
+ ast: resultadoModulo.modulo ?? null,
722
+ };
723
+ const ir = {
724
+ comando: "ir",
725
+ caminho: arquivo,
726
+ modulo: resultadoModulo.modulo?.nome ?? null,
727
+ sucesso,
728
+ diagnosticos: resultadoModulo.diagnosticos,
729
+ ir: resultadoModulo.ir ?? null,
730
+ };
731
+ await writeFile(path.join(pastaBase, "validar.json"), `${JSON.stringify(validar, null, 2)}\n`, "utf8");
732
+ await writeFile(path.join(pastaBase, "diagnosticos.json"), `${JSON.stringify(diagnosticos, null, 2)}\n`, "utf8");
733
+ await writeFile(path.join(pastaBase, "ast.json"), `${JSON.stringify(ast, null, 2)}\n`, "utf8");
734
+ await writeFile(path.join(pastaBase, "ir.json"), `${JSON.stringify(ir, null, 2)}\n`, "utf8");
735
+ await writeFile(path.join(pastaBase, "drift.json"), `${JSON.stringify(drift, null, 2)}\n`, "utf8");
736
+ const resumo = `# Contexto de IA para ${modulo}
737
+
738
+ - Arquivo alvo: \`${arquivo}\`
739
+ - Modulo: \`${modulo}\`
740
+ - Sucesso em validar: \`${sucesso}\`
741
+ - Quantidade de diagnosticos: \`${resultadoModulo.diagnosticos.length}\`
742
+
743
+ ## Arquivos gerados neste pacote
744
+
745
+ - \`validar.json\`
746
+ - \`diagnosticos.json\`
747
+ - \`ast.json\`
748
+ - \`ir.json\`
749
+ - \`drift.json\`
750
+
751
+ ## Fluxo recomendado para o agente
752
+
753
+ 1. Ler \`ast.json\` para entender a forma escrita.
754
+ 2. Ler \`ir.json\` para entender a forma semantica resolvida.
755
+ 3. Ler \`drift.json\` para ver quais arquivos e simbolos vivos sustentam a implementacao.
756
+ 4. Ler \`diagnosticos.json\` se houver falha ou aviso relevante.
757
+ 5. Editar o arquivo \`.sema\`.
758
+ 6. Rodar \`sema formatar "${arquivo}"\`.
759
+ 7. Rodar \`sema validar "${arquivo}" --json\`.
760
+ 8. Fechar com \`sema verificar exemplos --json --saida ./.tmp/verificacao-ia\` ou \`npm run project:check\`.
761
+
762
+ ## Textos base para onboarding do agente
763
+
764
+ - \`sema starter-ia\`
765
+ - \`sema prompt-ia\`
766
+ `;
767
+ await writeFile(path.join(pastaBase, "README.md"), resumo, "utf8");
768
+ return {
769
+ sucesso: true,
770
+ arquivo,
771
+ modulo,
772
+ pastaSaida: pastaBase,
773
+ artefatos: ["validar.json", "diagnosticos.json", "ast.json", "ir.json", "drift.json", "README.md"],
774
+ };
775
+ }
776
+ async function comandoIniciar(cwd, template) {
777
+ const arquivosBase = [
778
+ {
779
+ caminhoRelativo: "contratos/pedidos.sema",
780
+ conteudo: `module app.pedidos {
781
+ entity Pedido {
782
+ fields {
783
+ id: Id
784
+ status: Texto
785
+ total: Decimal
786
+ }
787
+ }
788
+
789
+ task criar_pedido {
790
+ input {
791
+ cliente_id: Id required
792
+ total: Decimal required
793
+ }
794
+ output {
795
+ pedido_id: Id
796
+ status: Texto
797
+ }
798
+ rules {
799
+ total > 0
800
+ }
801
+ effects {
802
+ persistencia Pedido criticidade=alta
803
+ auditoria pedidos
804
+ }
805
+ guarantees {
806
+ pedido_id existe
807
+ status existe
808
+ }
809
+ tests {
810
+ caso "pedido valido" {
811
+ given {
812
+ cliente_id: "cli-1"
813
+ total: 10
814
+ }
815
+ expect {
816
+ sucesso: verdadeiro
817
+ }
818
+ }
819
+ }
820
+ }
821
+
822
+ route criar_pedido_publico {
823
+ metodo: POST
824
+ caminho: /pedidos
825
+ task: criar_pedido
826
+ }
827
+ }
828
+ `,
829
+ },
830
+ ];
831
+ let arquivos = arquivosBase;
832
+ if (template === "nestjs") {
833
+ arquivos = [
834
+ {
835
+ caminhoRelativo: "sema.config.json",
836
+ conteudo: `{
837
+ "origens": ["./contratos"],
838
+ "saida": "./generated/nestjs",
839
+ "alvos": ["typescript"],
840
+ "alvoPadrao": "typescript",
841
+ "estruturaSaida": "backend",
842
+ "framework": "nestjs",
843
+ "modoEstrito": true,
844
+ "diretoriosSaidaPorAlvo": {
845
+ "typescript": "./generated/nestjs"
846
+ },
847
+ "convencoesGeracaoPorProjeto": "backend"
848
+ }
849
+ `,
850
+ },
851
+ { caminhoRelativo: "src/.gitkeep", conteudo: "" },
852
+ { caminhoRelativo: "test/.gitkeep", conteudo: "" },
853
+ ...arquivosBase,
854
+ ];
855
+ }
856
+ else if (template === "fastapi") {
857
+ arquivos = [
858
+ {
859
+ caminhoRelativo: "sema.config.json",
860
+ conteudo: `{
861
+ "origens": ["./contratos"],
862
+ "saida": "./generated/fastapi",
863
+ "alvos": ["python"],
864
+ "alvoPadrao": "python",
865
+ "estruturaSaida": "backend",
866
+ "framework": "fastapi",
867
+ "modoEstrito": true,
868
+ "diretoriosSaidaPorAlvo": {
869
+ "python": "./generated/fastapi"
870
+ },
871
+ "convencoesGeracaoPorProjeto": "backend"
872
+ }
873
+ `,
874
+ },
875
+ { caminhoRelativo: "app/.gitkeep", conteudo: "" },
876
+ { caminhoRelativo: "tests/.gitkeep", conteudo: "" },
877
+ ...arquivosBase,
878
+ ];
879
+ }
880
+ else if (template === "nextjs-api") {
881
+ arquivos = [
882
+ {
883
+ caminhoRelativo: "sema.config.json",
884
+ conteudo: `{
885
+ "origens": ["./contratos"],
886
+ "saida": "./generated",
887
+ "alvos": ["typescript"],
888
+ "alvoPadrao": "typescript",
889
+ "estruturaSaida": "modulos",
890
+ "framework": "base",
891
+ "modoEstrito": true,
892
+ "diretoriosCodigo": ["./src"],
893
+ "fontesLegado": ["nextjs", "typescript"],
894
+ "diretoriosSaidaPorAlvo": {
895
+ "typescript": "./generated/typescript"
896
+ },
897
+ "convencoesGeracaoPorProjeto": "base"
898
+ }
899
+ `,
900
+ },
901
+ {
902
+ caminhoRelativo: "contratos/health.sema",
903
+ conteudo: `module app.health {
904
+ task get_api_health {
905
+ output {
906
+ status: Texto
907
+ runtime: Texto
908
+ }
909
+ impl {
910
+ ts: src.app.api.health.route.GET
911
+ }
912
+ guarantees {
913
+ status existe
914
+ runtime existe
915
+ }
916
+ }
917
+
918
+ route get_api_health_publico {
919
+ metodo: GET
920
+ caminho: /api/health
921
+ task: get_api_health
922
+ }
923
+ }
924
+ `,
925
+ },
926
+ {
927
+ caminhoRelativo: "src/app/api/health/route.ts",
928
+ conteudo: `export async function GET() {
929
+ return Response.json({
930
+ status: "ok",
931
+ runtime: "nextjs",
932
+ });
933
+ }
934
+ `,
935
+ },
936
+ {
937
+ caminhoRelativo: "README.md",
938
+ conteudo: `# Starter Next.js API + Sema
939
+
940
+ - Contratos em \`contratos/\`
941
+ - Handlers App Router em \`src/app/api/\`
942
+ - Rota de exemplo validada por \`drift\`
943
+ `,
944
+ },
945
+ ];
946
+ }
947
+ else if (template === "node-firebase-worker") {
948
+ arquivos = [
949
+ {
950
+ caminhoRelativo: "sema.config.json",
951
+ conteudo: `{
952
+ "origens": ["./contratos"],
953
+ "saida": "./generated",
954
+ "alvos": ["typescript"],
955
+ "alvoPadrao": "typescript",
956
+ "estruturaSaida": "modulos",
957
+ "framework": "base",
958
+ "modoEstrito": true,
959
+ "diretoriosCodigo": ["./src"],
960
+ "fontesLegado": ["firebase", "typescript"],
961
+ "diretoriosSaidaPorAlvo": {
962
+ "typescript": "./generated/typescript"
963
+ },
964
+ "convencoesGeracaoPorProjeto": "base"
965
+ }
966
+ `,
967
+ },
968
+ {
969
+ caminhoRelativo: "contratos/worker_runtime.sema",
970
+ conteudo: `module worker.runtime {
971
+ task publicar_payload_health {
972
+ output {
973
+ status: Texto
974
+ timestamp: Texto
975
+ }
976
+ effects {
977
+ evento payload_health criticidade = alta
978
+ }
979
+ impl {
980
+ ts: src.sema_contract_bridge.semaWorkerHealthPayload
981
+ }
982
+ guarantees {
983
+ status existe
984
+ timestamp existe
985
+ }
986
+ }
987
+
988
+ task inventariar_colecoes {
989
+ output {
990
+ collections: Json
991
+ }
992
+ effects {
993
+ consulta runtime criticidade = baixa
994
+ }
995
+ impl {
996
+ ts: src.sema_contract_bridge.semaCollectionNames
997
+ }
998
+ guarantees {
999
+ collections existe
1000
+ }
1001
+ }
1002
+
1003
+ route get_health_worker {
1004
+ metodo: GET
1005
+ caminho: /health
1006
+ task: publicar_payload_health
1007
+ }
1008
+ }
1009
+ `,
1010
+ },
1011
+ {
1012
+ caminhoRelativo: "src/config/collections.ts",
1013
+ conteudo: `export const COLLECTIONS = {
1014
+ worker_status: "worker_status",
1015
+ audit_log: "audit_log",
1016
+ } as const;
1017
+ `,
1018
+ },
1019
+ {
1020
+ caminhoRelativo: "src/services/health-check.ts",
1021
+ conteudo: `import http from "node:http";
1022
+
1023
+ export type HealthStatus = {
1024
+ status: "healthy" | "degraded" | "unhealthy" | "initializing";
1025
+ timestamp: string;
1026
+ };
1027
+
1028
+ export type HealthProvider = () => HealthStatus;
1029
+
1030
+ export function startHealthCheckServer(port: number, provider: HealthProvider) {
1031
+ const server = http.createServer((req, res) => {
1032
+ if (req.url === "/health" && req.method === "GET") {
1033
+ res.writeHead(200, { "Content-Type": "application/json" });
1034
+ res.end(JSON.stringify(provider()));
1035
+ return;
1036
+ }
1037
+ res.writeHead(404);
1038
+ res.end();
1039
+ });
1040
+
1041
+ server.listen(port);
1042
+ return server;
1043
+ }
1044
+ `,
1045
+ },
1046
+ {
1047
+ caminhoRelativo: "src/sema_contract_bridge.ts",
1048
+ conteudo: `import { COLLECTIONS } from "./config/collections";
1049
+ import { startHealthCheckServer, type HealthProvider, type HealthStatus } from "./services/health-check";
1050
+
1051
+ export function semaStartWorkerHealthServer(port: number, provider: HealthProvider) {
1052
+ return startHealthCheckServer(port, provider);
1053
+ }
1054
+
1055
+ export function semaWorkerHealthPayload(payload: HealthStatus): HealthStatus {
1056
+ return payload;
1057
+ }
1058
+
1059
+ export function semaCollectionNames() {
1060
+ return COLLECTIONS;
1061
+ }
1062
+ `,
1063
+ },
1064
+ {
1065
+ caminhoRelativo: "README.md",
1066
+ conteudo: `# Starter Node Firebase Worker + Sema
1067
+
1068
+ - Contratos em \`contratos/\`
1069
+ - Worker e bridges em \`src/\`
1070
+ - \`drift\` valida impl, endpoint de health e recursos Firestore declarados
1071
+ `,
1072
+ },
1073
+ ];
1074
+ }
1075
+ else if (template === "aspnet-api") {
1076
+ arquivos = [
1077
+ {
1078
+ caminhoRelativo: "sema.config.json",
1079
+ conteudo: `{
1080
+ "origens": ["./contratos"],
1081
+ "saida": "./generated",
1082
+ "alvos": ["typescript"],
1083
+ "alvoPadrao": "typescript",
1084
+ "estruturaSaida": "modulos",
1085
+ "framework": "base",
1086
+ "modoEstrito": true,
1087
+ "diretoriosCodigo": ["./src"],
1088
+ "fontesLegado": ["dotnet"],
1089
+ "diretoriosSaidaPorAlvo": {
1090
+ "typescript": "./generated/typescript"
1091
+ },
1092
+ "convencoesGeracaoPorProjeto": "base"
1093
+ }
1094
+ `,
1095
+ },
1096
+ {
1097
+ caminhoRelativo: "contratos/health.sema",
1098
+ conteudo: `module app.health {
1099
+ task get_health {
1100
+ output {
1101
+ status: Texto
1102
+ runtime: Texto
1103
+ }
1104
+ impl {
1105
+ cs: src.Controllers.HealthController.Get
1106
+ }
1107
+ guarantees {
1108
+ status existe
1109
+ runtime existe
1110
+ }
1111
+ }
1112
+
1113
+ route get_health_publico {
1114
+ metodo: GET
1115
+ caminho: /api/health
1116
+ task: get_health
1117
+ }
1118
+ }
1119
+ `,
1120
+ },
1121
+ {
1122
+ caminhoRelativo: "src/Controllers/HealthController.cs",
1123
+ conteudo: `using Microsoft.AspNetCore.Mvc;
1124
+
1125
+ [ApiController]
1126
+ [Route("api/health")]
1127
+ public class HealthController : ControllerBase
1128
+ {
1129
+ [HttpGet]
1130
+ public object Get()
1131
+ {
1132
+ return new { status = "ok", runtime = "aspnet" };
1133
+ }
1134
+ }
1135
+ `,
1136
+ },
1137
+ {
1138
+ caminhoRelativo: "README.md",
1139
+ conteudo: `# Starter ASP.NET Core API + Sema
1140
+
1141
+ - Contratos em \`contratos/\`
1142
+ - Controllers/Minimal API em \`src/\`
1143
+ - \`drift\` valida impl e rota publica
1144
+ `,
1145
+ },
1146
+ ];
1147
+ }
1148
+ else if (template === "springboot-api") {
1149
+ arquivos = [
1150
+ {
1151
+ caminhoRelativo: "sema.config.json",
1152
+ conteudo: `{
1153
+ "origens": ["./contratos"],
1154
+ "saida": "./generated",
1155
+ "alvos": ["typescript"],
1156
+ "alvoPadrao": "typescript",
1157
+ "estruturaSaida": "modulos",
1158
+ "framework": "base",
1159
+ "modoEstrito": true,
1160
+ "diretoriosCodigo": ["./src"],
1161
+ "fontesLegado": ["java"],
1162
+ "diretoriosSaidaPorAlvo": {
1163
+ "typescript": "./generated/typescript"
1164
+ },
1165
+ "convencoesGeracaoPorProjeto": "base"
1166
+ }
1167
+ `,
1168
+ },
1169
+ {
1170
+ caminhoRelativo: "contratos/health.sema",
1171
+ conteudo: `module app.health {
1172
+ task get_health {
1173
+ output {
1174
+ status: Texto
1175
+ runtime: Texto
1176
+ }
1177
+ impl {
1178
+ java: src.main.java.com.acme.health.HealthController.health
1179
+ }
1180
+ guarantees {
1181
+ status existe
1182
+ runtime existe
1183
+ }
1184
+ }
1185
+
1186
+ route get_health_publico {
1187
+ metodo: GET
1188
+ caminho: /api/health
1189
+ task: get_health
1190
+ }
1191
+ }
1192
+ `,
1193
+ },
1194
+ {
1195
+ caminhoRelativo: "src/main/java/com/acme/health/HealthController.java",
1196
+ conteudo: `package com.acme.health;
1197
+
1198
+ import java.util.Map;
1199
+ import org.springframework.web.bind.annotation.GetMapping;
1200
+ import org.springframework.web.bind.annotation.RequestMapping;
1201
+ import org.springframework.web.bind.annotation.RestController;
1202
+
1203
+ @RestController
1204
+ @RequestMapping("/api/health")
1205
+ public class HealthController {
1206
+ @GetMapping
1207
+ public Map<String, String> health() {
1208
+ return Map.of("status", "ok", "runtime", "spring");
1209
+ }
1210
+ }
1211
+ `,
1212
+ },
1213
+ {
1214
+ caminhoRelativo: "README.md",
1215
+ conteudo: `# Starter Spring Boot API + Sema
1216
+
1217
+ - Contratos em \`contratos/\`
1218
+ - Controllers REST em \`src/main/java/\`
1219
+ - \`drift\` valida impl e rota publica
1220
+ `,
1221
+ },
1222
+ ];
1223
+ }
1224
+ else if (template === "go-http-api") {
1225
+ arquivos = [
1226
+ {
1227
+ caminhoRelativo: "sema.config.json",
1228
+ conteudo: `{
1229
+ "origens": ["./contratos"],
1230
+ "saida": "./generated",
1231
+ "alvos": ["typescript"],
1232
+ "alvoPadrao": "typescript",
1233
+ "estruturaSaida": "modulos",
1234
+ "framework": "base",
1235
+ "modoEstrito": true,
1236
+ "diretoriosCodigo": ["./internal"],
1237
+ "fontesLegado": ["go"],
1238
+ "diretoriosSaidaPorAlvo": {
1239
+ "typescript": "./generated/typescript"
1240
+ },
1241
+ "convencoesGeracaoPorProjeto": "base"
1242
+ }
1243
+ `,
1244
+ },
1245
+ {
1246
+ caminhoRelativo: "contratos/health.sema",
1247
+ conteudo: `module app.health {
1248
+ task get_health {
1249
+ output {
1250
+ resultado: Json
1251
+ }
1252
+ impl {
1253
+ go: internal.health.getHealth
1254
+ }
1255
+ guarantees {
1256
+ resultado existe
1257
+ }
1258
+ }
1259
+
1260
+ route get_health_publico {
1261
+ metodo: GET
1262
+ caminho: /health
1263
+ task: get_health
1264
+ }
1265
+ }
1266
+ `,
1267
+ },
1268
+ {
1269
+ caminhoRelativo: "internal/health.go",
1270
+ conteudo: `package internal
1271
+
1272
+ import "github.com/gin-gonic/gin"
1273
+
1274
+ func registerRoutes(router *gin.Engine) {
1275
+ router.GET("/health", getHealth)
1276
+ }
1277
+
1278
+ func getHealth(ctx *gin.Context) {
1279
+ ctx.JSON(200, gin.H{"status": "ok", "runtime": "go"})
1280
+ }
1281
+ `,
1282
+ },
1283
+ {
1284
+ caminhoRelativo: "README.md",
1285
+ conteudo: `# Starter Go HTTP API + Sema
1286
+
1287
+ - Contratos em \`contratos/\`
1288
+ - Handlers em \`internal/\`
1289
+ - \`drift\` valida impl e rota publica
1290
+ `,
1291
+ },
1292
+ ];
1293
+ }
1294
+ else if (template === "rust-axum-api") {
1295
+ arquivos = [
1296
+ {
1297
+ caminhoRelativo: "sema.config.json",
1298
+ conteudo: `{
1299
+ "origens": ["./contratos"],
1300
+ "saida": "./generated",
1301
+ "alvos": ["typescript"],
1302
+ "alvoPadrao": "typescript",
1303
+ "estruturaSaida": "modulos",
1304
+ "framework": "base",
1305
+ "modoEstrito": true,
1306
+ "diretoriosCodigo": ["./src"],
1307
+ "fontesLegado": ["rust"],
1308
+ "diretoriosSaidaPorAlvo": {
1309
+ "typescript": "./generated/typescript"
1310
+ },
1311
+ "convencoesGeracaoPorProjeto": "base"
1312
+ }
1313
+ `,
1314
+ },
1315
+ {
1316
+ caminhoRelativo: "contratos/health.sema",
1317
+ conteudo: `module app.health {
1318
+ task get_health {
1319
+ output {
1320
+ resultado: Json
1321
+ }
1322
+ impl {
1323
+ rust: src.handlers.health
1324
+ }
1325
+ guarantees {
1326
+ resultado existe
1327
+ }
1328
+ }
1329
+
1330
+ route get_health_publico {
1331
+ metodo: GET
1332
+ caminho: /health
1333
+ task: get_health
1334
+ }
1335
+ }
1336
+ `,
1337
+ },
1338
+ {
1339
+ caminhoRelativo: "src/main.rs",
1340
+ conteudo: `use axum::{routing::get, Router};
1341
+
1342
+ mod handlers;
1343
+
1344
+ fn app() -> Router {
1345
+ Router::new().route("/health", get(handlers::health))
1346
+ }
1347
+ `,
1348
+ },
1349
+ {
1350
+ caminhoRelativo: "src/handlers.rs",
1351
+ conteudo: `pub async fn health() -> &'static str {
1352
+ "ok"
1353
+ }
1354
+ `,
1355
+ },
1356
+ {
1357
+ caminhoRelativo: "README.md",
1358
+ conteudo: `# Starter Rust Axum API + Sema
1359
+
1360
+ - Contratos em \`contratos/\`
1361
+ - Handlers em \`src/\`
1362
+ - \`drift\` valida impl e rota publica
1363
+ `,
1364
+ },
1365
+ ];
1366
+ }
1367
+ else if (template === "cpp-service-bridge") {
1368
+ arquivos = [
1369
+ {
1370
+ caminhoRelativo: "sema.config.json",
1371
+ conteudo: `{
1372
+ "origens": ["./contratos"],
1373
+ "saida": "./generated",
1374
+ "alvos": ["typescript"],
1375
+ "alvoPadrao": "typescript",
1376
+ "estruturaSaida": "modulos",
1377
+ "framework": "base",
1378
+ "modoEstrito": true,
1379
+ "diretoriosCodigo": ["./src"],
1380
+ "fontesLegado": ["cpp"],
1381
+ "diretoriosSaidaPorAlvo": {
1382
+ "typescript": "./generated/typescript"
1383
+ },
1384
+ "convencoesGeracaoPorProjeto": "base"
1385
+ }
1386
+ `,
1387
+ },
1388
+ {
1389
+ caminhoRelativo: "contratos/runtime_bridge.sema",
1390
+ conteudo: `module app.runtime_bridge {
1391
+ task processar_snapshot {
1392
+ input {
1393
+ payload: Json required
1394
+ }
1395
+ output {
1396
+ resultado: Json
1397
+ }
1398
+ impl {
1399
+ cpp: src.runtime.RuntimeBridge.processSnapshot
1400
+ }
1401
+ guarantees {
1402
+ resultado existe
1403
+ }
1404
+ }
1405
+ }
1406
+ `,
1407
+ },
1408
+ {
1409
+ caminhoRelativo: "src/runtime.cpp",
1410
+ conteudo: `class RuntimeBridge {
1411
+ public:
1412
+ int processSnapshot(int payload) {
1413
+ return payload;
1414
+ }
1415
+ };
1416
+ `,
1417
+ },
1418
+ {
1419
+ caminhoRelativo: "README.md",
1420
+ conteudo: `# Starter C++ Service Bridge + Sema
1421
+
1422
+ - Contratos em \`contratos/\`
1423
+ - Symbols e bridges em \`src/\`
1424
+ - \`drift\` valida impl de simbolos, sem prometer rota HTTP
1425
+ `,
1426
+ },
1427
+ ];
1428
+ }
1429
+ else {
1430
+ arquivos = [
1431
+ {
1432
+ caminhoRelativo: "sema.config.json",
1433
+ conteudo: `{
1434
+ "origens": ["./contratos"],
1435
+ "saida": "./generated",
1436
+ "alvos": ["typescript", "python", "dart"],
1437
+ "alvoPadrao": "typescript",
1438
+ "estruturaSaida": "modulos",
1439
+ "framework": "base",
1440
+ "modoEstrito": true,
1441
+ "diretoriosSaidaPorAlvo": {
1442
+ "typescript": "./generated/typescript",
1443
+ "python": "./generated/python",
1444
+ "dart": "./generated/dart"
1445
+ },
1446
+ "convencoesGeracaoPorProjeto": "base"
1447
+ }
1448
+ `,
1449
+ },
1450
+ ...arquivosBase,
1451
+ ];
1452
+ }
1453
+ await escreverArquivos(cwd, arquivos);
1454
+ console.log(`Projeto Sema inicializado com template ${template}.`);
1455
+ return 0;
1456
+ }
1457
+ async function comandoValidar(entrada) {
1458
+ const modulos = await carregarModulos(entrada);
1459
+ const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
1460
+ console.log(formatarDiagnosticos(diagnosticos));
1461
+ return temErros(diagnosticos) ? 1 : 0;
1462
+ }
1463
+ async function comandoValidarJson(entrada) {
1464
+ const modulos = await carregarModulos(entrada);
1465
+ const resultados = modulos.map((item) => ({
1466
+ caminho: item.caminho,
1467
+ modulo: item.resultado.modulo?.nome ?? null,
1468
+ sucesso: !temErros(item.resultado.diagnosticos),
1469
+ diagnosticos: item.resultado.diagnosticos,
1470
+ }));
1471
+ console.log(JSON.stringify({
1472
+ comando: "validar",
1473
+ sucesso: resultados.every((resultado) => resultado.sucesso),
1474
+ resultados,
1475
+ }, null, 2));
1476
+ return resultados.every((resultado) => resultado.sucesso) ? 0 : 1;
1477
+ }
1478
+ async function comandoInspecionar(entrada, emJson, cwd = process.cwd()) {
1479
+ const contextoProjeto = await carregarProjeto(entrada, cwd);
1480
+ const resultadoDrift = await analisarDriftLegado(contextoProjeto);
1481
+ const framework = resolverFrameworkPadrao(undefined, contextoProjeto.configCarregada);
1482
+ const estruturaSaida = resolverEstruturaSaidaPadrao(undefined, framework, contextoProjeto.configCarregada);
1483
+ const alvos = resolverAlvosVerificacao(contextoProjeto.configCarregada);
1484
+ const saidas = Object.fromEntries(alvos.map((alvo) => [alvo, resolverSaidaPadrao(undefined, alvo, contextoProjeto.configCarregada)]));
1485
+ const payload = {
1486
+ comando: "inspecionar",
1487
+ entrada: contextoProjeto.entradaResolvida,
1488
+ configuracao: {
1489
+ caminho: contextoProjeto.configCarregada?.caminho ?? null,
1490
+ baseProjeto: contextoProjeto.baseProjeto,
1491
+ framework,
1492
+ estruturaSaida,
1493
+ alvos,
1494
+ saidas,
1495
+ origens: contextoProjeto.origensProjeto,
1496
+ diretoriosCodigo: contextoProjeto.diretoriosCodigo,
1497
+ fontesLegado: contextoProjeto.fontesLegado,
1498
+ modoAdocao: contextoProjeto.modoAdocao,
1499
+ },
1500
+ projeto: {
1501
+ arquivos: contextoProjeto.arquivosProjeto,
1502
+ modulos: contextoProjeto.modulosSelecionados.map((item) => ({
1503
+ caminho: item.caminho,
1504
+ modulo: item.resultado.modulo?.nome ?? null,
1505
+ sucesso: !temErros(item.resultado.diagnosticos),
1506
+ diagnosticos: item.resultado.diagnosticos.length,
1507
+ implementacao: resumirDriftPorModulo(item.resultado.modulo?.nome ?? null, item.caminho, resultadoDrift),
1508
+ })),
1509
+ },
1510
+ };
1511
+ if (emJson) {
1512
+ console.log(JSON.stringify(payload, null, 2));
1513
+ return 0;
1514
+ }
1515
+ console.log("Inspecao de projeto Sema");
1516
+ console.log(`- Entrada: ${payload.entrada}`);
1517
+ console.log(`- Configuracao: ${payload.configuracao.caminho ?? "nenhuma"}`);
1518
+ console.log(`- Base do projeto: ${payload.configuracao.baseProjeto}`);
1519
+ console.log(`- Framework: ${payload.configuracao.framework}`);
1520
+ console.log(`- Estrutura de saida: ${payload.configuracao.estruturaSaida}`);
1521
+ console.log(`- Alvos: ${payload.configuracao.alvos.join(", ")}`);
1522
+ console.log(`- Modo de adocao: ${payload.configuracao.modoAdocao}`);
1523
+ console.log("- Saidas por alvo:");
1524
+ for (const [alvo, saida] of Object.entries(payload.configuracao.saidas)) {
1525
+ console.log(` - ${alvo}: ${saida}`);
1526
+ }
1527
+ console.log("- Origens do projeto:");
1528
+ for (const origem of payload.configuracao.origens) {
1529
+ console.log(` - ${origem}`);
1530
+ }
1531
+ console.log("- Diretorios de codigo:");
1532
+ for (const diretorio of payload.configuracao.diretoriosCodigo) {
1533
+ console.log(` - ${diretorio}`);
1534
+ }
1535
+ console.log(`- Fontes de legado detectadas: ${payload.configuracao.fontesLegado.join(", ") || "nenhuma"}`);
1536
+ console.log("- Modulos selecionados:");
1537
+ for (const modulo of payload.projeto.modulos) {
1538
+ console.log(` - ${modulo.modulo ?? "(sem modulo)"} :: ${modulo.caminho} :: diagnosticos=${modulo.diagnosticos}`);
1539
+ console.log(` impls validos=${modulo.implementacao.implsValidos} quebrados=${modulo.implementacao.implsQuebrados} recursos divergentes=${modulo.implementacao.recursosDivergentesCount} sem_impl=${modulo.implementacao.tasksSemImplementacao}`);
1540
+ for (const arquivoRelacionado of modulo.implementacao.arquivosRelacionados.slice(0, 5)) {
1541
+ console.log(` arquivo relacionado: ${arquivoRelacionado}`);
1542
+ }
1543
+ }
1544
+ return 0;
1545
+ }
1546
+ async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
1547
+ const contextoProjeto = await carregarProjeto(entrada, cwd);
1548
+ const resultado = await analisarDriftLegado(contextoProjeto);
1549
+ if (emJson) {
1550
+ console.log(JSON.stringify(resultado, null, 2));
1551
+ return resultado.sucesso ? 0 : 1;
1552
+ }
1553
+ console.log("Drift entre Sema e codigo legado");
1554
+ console.log(`- Modulos analisados: ${resultado.modulos.length}`);
1555
+ console.log(`- Tasks analisadas: ${resultado.tasks.length}`);
1556
+ console.log(`- Impl validos: ${resultado.impls_validos.length}`);
1557
+ console.log(`- Impl quebrados: ${resultado.impls_quebrados.length}`);
1558
+ console.log(`- Rotas divergentes: ${resultado.rotas_divergentes.length}`);
1559
+ console.log(`- Recursos vivos validos: ${resultado.recursos_validos.length}`);
1560
+ console.log(`- Recursos vivos divergentes: ${resultado.recursos_divergentes.length}`);
1561
+ if (resultado.impls_quebrados.length > 0) {
1562
+ console.log("- Impl quebrados:");
1563
+ for (const impl of resultado.impls_quebrados) {
1564
+ console.log(` - ${impl.modulo}.${impl.task} :: ${impl.origem}:${impl.caminho}`);
1565
+ if (impl.candidatos && impl.candidatos.length > 0) {
1566
+ console.log(" candidatos provaveis:");
1567
+ for (const candidato of impl.candidatos) {
1568
+ console.log(` - [${candidato.confianca}] ${candidato.caminho} :: ${candidato.arquivo} :: ${candidato.simbolo}`);
1569
+ }
1570
+ }
1571
+ }
1572
+ }
1573
+ if (resultado.rotas_divergentes.length > 0) {
1574
+ console.log("- Rotas divergentes:");
1575
+ for (const rota of resultado.rotas_divergentes) {
1576
+ console.log(` - ${rota.modulo}.${rota.route} :: ${rota.metodo ?? "?"} ${rota.caminho ?? "?"}`);
1577
+ }
1578
+ }
1579
+ if (resultado.recursos_divergentes.length > 0) {
1580
+ console.log("- Recursos divergentes:");
1581
+ for (const recurso of resultado.recursos_divergentes) {
1582
+ console.log(` - ${recurso.modulo}.${recurso.task} :: ${recurso.categoria} ${recurso.alvo}`);
1583
+ }
1584
+ }
1585
+ const semImpl = resultado.tasks.filter((task) => task.semImplementacao);
1586
+ if (semImpl.length > 0) {
1587
+ console.log("- Tasks sem implementacao vinculada:");
1588
+ for (const task of semImpl) {
1589
+ console.log(` - ${task.modulo}.${task.task}`);
1590
+ if (task.candidatosImpl.length > 0) {
1591
+ console.log(" candidatos provaveis:");
1592
+ for (const candidato of task.candidatosImpl) {
1593
+ console.log(` - [${candidato.confianca}] ${candidato.caminho} :: ${candidato.arquivo} :: ${candidato.simbolo}`);
1594
+ }
1595
+ }
1596
+ }
1597
+ }
1598
+ if (resultado.diagnosticos.length === 0) {
1599
+ console.log("Nenhum drift relevante encontrado.");
1600
+ }
1601
+ return resultado.sucesso ? 0 : 1;
1602
+ }
1603
+ async function comandoImportar(fonte, diretorio, saida, namespaceBase, emJson) {
1604
+ const resultado = await importarProjetoLegado(fonte, diretorio, namespaceBase);
1605
+ const resumo = resumoImportacao(resultado);
1606
+ if (!resumo.sucesso) {
1607
+ const payloadErro = {
1608
+ comando: "importar",
1609
+ fonte,
1610
+ diretorio: path.resolve(diretorio),
1611
+ namespaceBase: resultado.namespaceBase,
1612
+ resumo,
1613
+ arquivos: resultado.arquivos.map((arquivo) => ({
1614
+ caminho: path.join(path.resolve(saida), arquivo.caminhoRelativo),
1615
+ modulo: arquivo.modulo,
1616
+ tarefas: arquivo.tarefas,
1617
+ rotas: arquivo.rotas,
1618
+ entidades: arquivo.entidades,
1619
+ enums: arquivo.enums,
1620
+ })),
1621
+ diagnosticos: resultado.diagnosticos,
1622
+ };
1623
+ if (emJson) {
1624
+ console.log(JSON.stringify(payloadErro, null, 2));
1625
+ }
1626
+ else {
1627
+ console.error("Falha na importacao assistida. O rascunho gerado ainda nao ficou semanticamente valido.");
1628
+ console.error(formatarDiagnosticos(resultado.diagnosticos));
1629
+ }
1630
+ return 1;
1631
+ }
1632
+ await escreverArquivos(saida, resultado.arquivos.map((arquivo) => ({
1633
+ caminhoRelativo: arquivo.caminhoRelativo,
1634
+ conteudo: arquivo.conteudo,
1635
+ })));
1636
+ const payload = {
1637
+ comando: "importar",
1638
+ fonte,
1639
+ diretorio: path.resolve(diretorio),
1640
+ saida: path.resolve(saida),
1641
+ namespaceBase: resultado.namespaceBase,
1642
+ resumo,
1643
+ arquivos: resultado.arquivos.map((arquivo) => ({
1644
+ caminho: path.join(path.resolve(saida), arquivo.caminhoRelativo),
1645
+ modulo: arquivo.modulo,
1646
+ tarefas: arquivo.tarefas,
1647
+ rotas: arquivo.rotas,
1648
+ entidades: arquivo.entidades,
1649
+ enums: arquivo.enums,
1650
+ })),
1651
+ };
1652
+ if (emJson) {
1653
+ console.log(JSON.stringify(payload, null, 2));
1654
+ return 0;
1655
+ }
1656
+ console.log("Importacao assistida para Sema concluida.");
1657
+ console.log(`- Fonte: ${fonte}`);
1658
+ console.log(`- Diretorio analisado: ${payload.diretorio}`);
1659
+ console.log(`- Namespace base: ${payload.namespaceBase}`);
1660
+ console.log(`- Saida: ${payload.saida}`);
1661
+ console.log(`- Modulos: ${resumo.modulos}`);
1662
+ console.log(`- Tarefas: ${resumo.tarefas}`);
1663
+ console.log(`- Rotas: ${resumo.rotas}`);
1664
+ console.log(`- Entidades: ${resumo.entidades}`);
1665
+ console.log(`- Enums: ${resumo.enums}`);
1666
+ console.log("- Arquivos gerados:");
1667
+ for (const arquivo of payload.arquivos) {
1668
+ console.log(` - ${arquivo.caminho} :: modulo=${arquivo.modulo} tarefas=${arquivo.tarefas} rotas=${arquivo.rotas}`);
1669
+ }
1670
+ console.log("Ajuste os rascunhos .sema, rode `sema formatar`, `sema validar --json` e depois `sema compilar`.");
1671
+ return 0;
1672
+ }
1673
+ async function comandoAst(arquivo) {
1674
+ const codigo = await lerArquivoTexto(arquivo);
1675
+ const resultado = compilarCodigo(codigo, arquivo);
1676
+ console.log(JSON.stringify(resultado.modulo ?? null, null, 2));
1677
+ return temErros(resultado.diagnosticos) ? 1 : 0;
1678
+ }
1679
+ async function comandoAstJson(arquivo) {
1680
+ const codigo = await lerArquivoTexto(arquivo);
1681
+ const resultado = compilarCodigo(codigo, arquivo);
1682
+ console.log(JSON.stringify({
1683
+ comando: "ast",
1684
+ caminho: path.resolve(arquivo),
1685
+ modulo: resultado.modulo?.nome ?? null,
1686
+ sucesso: !temErros(resultado.diagnosticos),
1687
+ diagnosticos: resultado.diagnosticos,
1688
+ ast: resultado.modulo ?? null,
1689
+ }, null, 2));
1690
+ return temErros(resultado.diagnosticos) ? 1 : 0;
1691
+ }
1692
+ async function comandoIr(arquivo) {
1693
+ const codigo = await lerArquivoTexto(arquivo);
1694
+ const resultado = compilarCodigo(codigo, arquivo);
1695
+ console.log(JSON.stringify(resultado.ir ?? null, null, 2));
1696
+ return temErros(resultado.diagnosticos) ? 1 : 0;
1697
+ }
1698
+ async function comandoIrJson(arquivo) {
1699
+ const codigo = await lerArquivoTexto(arquivo);
1700
+ const resultado = compilarCodigo(codigo, arquivo);
1701
+ console.log(JSON.stringify({
1702
+ comando: "ir",
1703
+ caminho: path.resolve(arquivo),
1704
+ modulo: resultado.modulo?.nome ?? null,
1705
+ sucesso: !temErros(resultado.diagnosticos),
1706
+ diagnosticos: resultado.diagnosticos,
1707
+ ir: resultado.ir ?? null,
1708
+ }, null, 2));
1709
+ return temErros(resultado.diagnosticos) ? 1 : 0;
1710
+ }
1711
+ async function comandoCompilar(entrada, alvo, saida, estrutura, framework, cwd = process.cwd()) {
1712
+ const incompatibilidade = validarCompatibilidadeFramework(alvo, framework);
1713
+ if (incompatibilidade) {
1714
+ console.error(incompatibilidade);
1715
+ return 1;
1716
+ }
1717
+ const modulos = await carregarModulos(entrada, cwd);
1718
+ const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
1719
+ if (temErros(diagnosticos)) {
1720
+ console.error(formatarDiagnosticos(diagnosticos));
1721
+ return 1;
1722
+ }
1723
+ for (const modulo of modulos) {
1724
+ const ir = garantirIr(modulo.resultado, modulo.caminho);
1725
+ const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
1726
+ await escreverArquivos(saida, arquivos);
1727
+ }
1728
+ console.log(`Compilacao concluida para o alvo ${alvo} com estrutura ${estrutura} e framework ${framework}.`);
1729
+ return 0;
1730
+ }
1731
+ async function comandoDiagnosticos(arquivo, emJson) {
1732
+ const codigo = await lerArquivoTexto(arquivo);
1733
+ const resultado = compilarCodigo(codigo, arquivo);
1734
+ if (emJson) {
1735
+ console.log(JSON.stringify(resultado.diagnosticos, null, 2));
1736
+ }
1737
+ else {
1738
+ console.log(formatarDiagnosticos(resultado.diagnosticos));
1739
+ }
1740
+ return temErros(resultado.diagnosticos) ? 1 : 0;
1741
+ }
1742
+ async function comandoFormatar(entrada, verificarApenas, emJson) {
1743
+ const contextoProjeto = await carregarProjeto(entrada, process.cwd());
1744
+ const entradaResolvida = contextoProjeto.entradaResolvida;
1745
+ const estatisticas = await stat(entradaResolvida);
1746
+ const arquivos = estatisticas.isFile()
1747
+ ? [entradaResolvida]
1748
+ : contextoProjeto.arquivosProjeto.filter((arquivo) => arquivo.startsWith(path.resolve(entradaResolvida)));
1749
+ const resultados = [];
1750
+ for (const arquivo of arquivos) {
1751
+ const codigo = await lerArquivoTexto(arquivo);
1752
+ const resultado = formatarCodigo(codigo, arquivo);
1753
+ const sucesso = !temErros(resultado.diagnosticos) && Boolean(resultado.codigoFormatado);
1754
+ resultados.push({
1755
+ caminho: arquivo,
1756
+ alterado: resultado.alterado,
1757
+ sucesso,
1758
+ diagnosticos: resultado.diagnosticos,
1759
+ });
1760
+ if (sucesso && !verificarApenas && resultado.alterado && resultado.codigoFormatado) {
1761
+ await writeFile(arquivo, resultado.codigoFormatado, "utf8");
1762
+ }
1763
+ }
1764
+ const possuiErros = resultados.some((resultado) => !resultado.sucesso);
1765
+ const possuiDiferencas = resultados.some((resultado) => resultado.alterado);
1766
+ const codigoSaida = possuiErros ? 1 : verificarApenas && possuiDiferencas ? 1 : 0;
1767
+ if (emJson) {
1768
+ console.log(JSON.stringify({
1769
+ comando: "formatar",
1770
+ sucesso: codigoSaida === 0,
1771
+ modo: verificarApenas ? "check" : "write",
1772
+ arquivos: resultados,
1773
+ totais: {
1774
+ arquivos: resultados.length,
1775
+ alterados: resultados.filter((resultado) => resultado.alterado).length,
1776
+ erros: resultados.filter((resultado) => !resultado.sucesso).length,
1777
+ },
1778
+ }, null, 2));
1779
+ return codigoSaida;
1780
+ }
1781
+ if (possuiErros) {
1782
+ console.error(formatarDiagnosticos(resultados.flatMap((resultado) => resultado.diagnosticos)));
1783
+ return 1;
1784
+ }
1785
+ if (verificarApenas) {
1786
+ if (possuiDiferencas) {
1787
+ console.error("Arquivos fora do formato canonico:");
1788
+ for (const resultado of resultados.filter((item) => item.alterado)) {
1789
+ console.error(`- ${resultado.caminho}`);
1790
+ }
1791
+ return 1;
1792
+ }
1793
+ console.log("Todos os arquivos ja estao no formato canonico.");
1794
+ return 0;
1795
+ }
1796
+ console.log(`Formatacao concluida. Arquivos verificados=${resultados.length} alterados=${resultados.filter((resultado) => resultado.alterado).length}`);
1797
+ return 0;
1798
+ }
1799
+ async function comandoStarterIa() {
1800
+ const descoberta = await descobrirDocsIa();
1801
+ console.log("Starter de IA da Sema");
1802
+ console.log("");
1803
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1804
+ console.log("");
1805
+ console.log(STARTER_IA);
1806
+ return 0;
1807
+ }
1808
+ async function comandoAjudaIa() {
1809
+ const descoberta = await descobrirDocsIa();
1810
+ console.log("Ajuda de IA da Sema");
1811
+ console.log("");
1812
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1813
+ console.log("");
1814
+ console.log("Fluxo recomendado");
1815
+ console.log("- Use `sema starter-ia` para um texto curto de onboarding.");
1816
+ console.log("- Use `sema prompt-ia` para o prompt-base geral.");
1817
+ console.log("- Use `sema prompt-ia-ui` para tarefas visuais com Sema + UI.");
1818
+ console.log("- Use `sema prompt-ia-react` para projeto com Sema + React + TypeScript.");
1819
+ console.log("- Use `sema prompt-ia-sema-primeiro` para forcar modelagem semantica antes da implementacao.");
1820
+ console.log("- Use `sema exemplos-prompt-ia` para pegar modelos prontos de prompt.");
1821
+ console.log("- Use `sema contexto-ia <arquivo.sema>` para gerar AST, IR e diagnosticos do modulo alvo.");
1822
+ console.log("- Use `sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>` quando a tarefa pedir codigo derivado.");
1823
+ console.log("");
1824
+ console.log("Regra pratica");
1825
+ console.log("- Se voce quer testar a Sema de verdade, nao peca so HTML solto.");
1826
+ console.log("- Peca `.sema` + arquitetura + React + TypeScript, ou use o modo `Sema primeiro`.");
1827
+ return 0;
1828
+ }
1829
+ async function comandoPromptIa() {
1830
+ const descoberta = await descobrirDocsIa();
1831
+ console.log("Prompt-base de IA da Sema");
1832
+ console.log("");
1833
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1834
+ console.log("");
1835
+ console.log(PROMPT_BASE_IA);
1836
+ return 0;
1837
+ }
1838
+ async function comandoPromptIaUi() {
1839
+ const descoberta = await descobrirDocsIa();
1840
+ console.log("Prompt de IA da Sema para UI");
1841
+ console.log("");
1842
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1843
+ console.log("");
1844
+ console.log(PROMPT_IA_UI);
1845
+ return 0;
1846
+ }
1847
+ async function comandoPromptIaReact() {
1848
+ const descoberta = await descobrirDocsIa();
1849
+ console.log("Prompt de IA da Sema para React");
1850
+ console.log("");
1851
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1852
+ console.log("");
1853
+ console.log(PROMPT_IA_REACT);
1854
+ return 0;
1855
+ }
1856
+ async function comandoPromptIaSemaPrimeiro() {
1857
+ const descoberta = await descobrirDocsIa();
1858
+ console.log("Prompt de IA da Sema no modo Sema primeiro");
1859
+ console.log("");
1860
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1861
+ console.log("");
1862
+ console.log(PROMPT_IA_SEMA_PRIMEIRO);
1863
+ return 0;
1864
+ }
1865
+ async function comandoExemplosPromptIa() {
1866
+ const descoberta = await descobrirDocsIa();
1867
+ console.log("Exemplos de prompt de IA da Sema");
1868
+ console.log("");
1869
+ console.log(renderizarCabecalhoDocsIa(descoberta));
1870
+ console.log("");
1871
+ console.log(EXEMPLOS_PROMPT_IA);
1872
+ return 0;
1873
+ }
1874
+ async function comandoContextoIa(arquivo, pastaSaida, emJson) {
1875
+ const resultado = await gerarContextoIa(arquivo, pastaSaida);
1876
+ if (emJson) {
1877
+ console.log(JSON.stringify(resultado, null, 2));
1878
+ return 0;
1879
+ }
1880
+ const resumoGerado = await readFile(path.join(resultado.pastaSaida, "README.md"), "utf8");
1881
+ console.log(`Pacote de contexto gerado em ${resultado.pastaSaida}`);
1882
+ console.log("");
1883
+ console.log(resumoGerado);
1884
+ return 0;
1885
+ }
1886
+ async function comandoTestar(arquivo, alvo, saida, estrutura, framework) {
1887
+ const incompatibilidade = validarCompatibilidadeFramework(alvo, framework);
1888
+ if (incompatibilidade) {
1889
+ console.error(incompatibilidade);
1890
+ return 1;
1891
+ }
1892
+ const codigo = await lerArquivoTexto(arquivo);
1893
+ const resultado = compilarCodigo(codigo, arquivo);
1894
+ if (temErros(resultado.diagnosticos)) {
1895
+ console.error(formatarDiagnosticos(resultado.diagnosticos));
1896
+ return 1;
1897
+ }
1898
+ const ir = garantirIr(resultado, arquivo);
1899
+ const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
1900
+ await escreverArquivos(saida, arquivos);
1901
+ if (framework !== "base") {
1902
+ console.log(`Scaffold ${framework} gerado em ${saida}. A execucao automatica de testes continua focada no framework base da Sema.`);
1903
+ return 0;
1904
+ }
1905
+ return executarTestesGerados(alvo, saida, arquivos).codigoSaida;
1906
+ }
1907
+ function imprimirResumoVerificacao(resumos) {
1908
+ console.log("\nResumo da verificacao:");
1909
+ let totalArquivos = 0;
1910
+ let totalTestes = 0;
1911
+ let totalAlvos = 0;
1912
+ for (const resumo of resumos) {
1913
+ console.log(`- Modulo ${resumo.modulo} (${resumo.arquivoFonte})`);
1914
+ for (const alvo of resumo.alvos) {
1915
+ totalArquivos += alvo.arquivosGerados;
1916
+ totalTestes += alvo.quantidadeTestes;
1917
+ totalAlvos += 1;
1918
+ console.log(` alvo=${alvo.alvo} status=${alvo.sucesso ? "ok" : "falhou"} arquivos=${alvo.arquivosGerados} testes=${alvo.quantidadeTestes} saida=${alvo.pastaSaida}`);
1919
+ }
1920
+ }
1921
+ console.log(`Totais: modulos=${resumos.length} alvos=${totalAlvos} arquivos=${totalArquivos} testes=${totalTestes}`);
1922
+ }
1923
+ async function comandoVerificar(entrada, baseSaida, cwd = process.cwd()) {
1924
+ const contextoProjeto = await carregarProjeto(entrada, cwd);
1925
+ const modulos = contextoProjeto.modulosSelecionados;
1926
+ const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
1927
+ if (temErros(diagnosticos)) {
1928
+ console.error(formatarDiagnosticos(diagnosticos));
1929
+ return 1;
1930
+ }
1931
+ const alvos = resolverAlvosVerificacao(contextoProjeto.configCarregada);
1932
+ const resumos = [];
1933
+ for (const modulo of modulos) {
1934
+ const ir = garantirIr(modulo.resultado, modulo.caminho);
1935
+ console.log(`Verificando modulo ${modulo.caminho}`);
1936
+ const resumoModulo = {
1937
+ modulo: ir.nome,
1938
+ arquivoFonte: modulo.caminho,
1939
+ alvos: [],
1940
+ };
1941
+ for (const alvo of alvos) {
1942
+ const pastaAlvo = path.join(baseSaida, alvo, nomeSubpastaModulo(modulo.caminho));
1943
+ const framework = alvo === "typescript" ? "base" : alvo === "python" ? "base" : "base";
1944
+ const arquivos = gerarArquivosPorAlvo(ir, alvo, framework);
1945
+ await escreverArquivos(pastaAlvo, arquivos);
1946
+ const execucao = executarTestesGerados(alvo, pastaAlvo, arquivos);
1947
+ resumoModulo.alvos.push({
1948
+ alvo,
1949
+ arquivosGerados: arquivos.length,
1950
+ quantidadeTestes: execucao.quantidadeTestes,
1951
+ pastaSaida: pastaAlvo,
1952
+ sucesso: execucao.codigoSaida === 0,
1953
+ });
1954
+ if (execucao.codigoSaida !== 0) {
1955
+ imprimirResumoVerificacao([...resumos, resumoModulo]);
1956
+ console.error(`Falha na verificacao do modulo ${modulo.caminho} para o alvo ${alvo}.`);
1957
+ return execucao.codigoSaida;
1958
+ }
1959
+ }
1960
+ resumos.push(resumoModulo);
1961
+ }
1962
+ imprimirResumoVerificacao(resumos);
1963
+ console.log("Verificacao completa concluida com sucesso.");
1964
+ return 0;
1965
+ }
1966
+ async function comandoVerificarJson(entrada, baseSaida, cwd = process.cwd()) {
1967
+ const contextoProjeto = await carregarProjeto(entrada, cwd);
1968
+ const modulos = contextoProjeto.modulosSelecionados;
1969
+ const diagnosticos = modulos.flatMap((item) => item.resultado.diagnosticos);
1970
+ if (temErros(diagnosticos)) {
1971
+ console.log(JSON.stringify({
1972
+ comando: "verificar",
1973
+ sucesso: false,
1974
+ diagnosticos,
1975
+ modulos: [],
1976
+ totais: { modulos: 0, alvos: 0, arquivos: 0, testes: 0 },
1977
+ }, null, 2));
1978
+ return 1;
1979
+ }
1980
+ const alvos = resolverAlvosVerificacao(contextoProjeto.configCarregada);
1981
+ const resumos = [];
1982
+ let codigoSaida = 0;
1983
+ for (const modulo of modulos) {
1984
+ const ir = garantirIr(modulo.resultado, modulo.caminho);
1985
+ const resumoModulo = {
1986
+ modulo: ir.nome,
1987
+ arquivoFonte: modulo.caminho,
1988
+ alvos: [],
1989
+ saidaTestes: [],
1990
+ };
1991
+ for (const alvo of alvos) {
1992
+ const pastaAlvo = path.join(baseSaida, alvo, nomeSubpastaModulo(modulo.caminho));
1993
+ const arquivos = gerarArquivosPorAlvo(ir, alvo, "base");
1994
+ await escreverArquivos(pastaAlvo, arquivos);
1995
+ const execucao = executarTestesGerados(alvo, pastaAlvo, arquivos, true);
1996
+ resumoModulo.alvos.push({
1997
+ alvo,
1998
+ arquivosGerados: arquivos.length,
1999
+ quantidadeTestes: execucao.quantidadeTestes,
2000
+ pastaSaida: pastaAlvo,
2001
+ sucesso: execucao.codigoSaida === 0,
2002
+ });
2003
+ resumoModulo.saidaTestes.push({ alvo, stdout: execucao.saidaPadrao, stderr: execucao.saidaErro });
2004
+ if (execucao.codigoSaida !== 0) {
2005
+ codigoSaida = execucao.codigoSaida;
2006
+ }
2007
+ }
2008
+ resumos.push(resumoModulo);
2009
+ }
2010
+ const totais = {
2011
+ modulos: resumos.length,
2012
+ alvos: resumos.reduce((total, resumo) => total + resumo.alvos.length, 0),
2013
+ arquivos: resumos.reduce((total, resumo) => total + resumo.alvos.reduce((subTotal, alvo) => subTotal + alvo.arquivosGerados, 0), 0),
2014
+ testes: resumos.reduce((total, resumo) => total + resumo.alvos.reduce((subTotal, alvo) => subTotal + alvo.quantidadeTestes, 0), 0),
2015
+ };
2016
+ console.log(JSON.stringify({
2017
+ comando: "verificar",
2018
+ sucesso: codigoSaida === 0,
2019
+ modulos: resumos,
2020
+ totais,
2021
+ }, null, 2));
2022
+ return codigoSaida;
2023
+ }
2024
+ async function principal() {
2025
+ const { comando, resto } = obterArgumentos();
2026
+ const comandoCru = process.argv[2];
2027
+ if (!comando || comandoCru === "--help" || comandoCru === "-h") {
2028
+ console.log(ajuda());
2029
+ process.exit(0);
2030
+ }
2031
+ const cwd = process.cwd();
2032
+ const posicionais = obterPosicionais(resto);
2033
+ let codigoSaida = 0;
2034
+ switch (comando) {
2035
+ case "iniciar":
2036
+ codigoSaida = await comandoIniciar(cwd, normalizarTemplateIniciar(obterOpcao(resto, "--template")));
2037
+ break;
2038
+ case "validar":
2039
+ codigoSaida = possuiFlag(resto, "--json")
2040
+ ? await comandoValidarJson(posicionais[0])
2041
+ : await comandoValidar(posicionais[0]);
2042
+ break;
2043
+ case "ast":
2044
+ codigoSaida = possuiFlag(resto, "--json")
2045
+ ? await comandoAstJson(resto[0] ?? "")
2046
+ : await comandoAst(resto[0] ?? "");
2047
+ break;
2048
+ case "ir":
2049
+ codigoSaida = possuiFlag(resto, "--json")
2050
+ ? await comandoIrJson(resto[0] ?? "")
2051
+ : await comandoIr(resto[0] ?? "");
2052
+ break;
2053
+ case "compilar":
2054
+ {
2055
+ const config = await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd);
2056
+ const alvo = resolverAlvoPadrao(obterOpcao(resto, "--alvo"), config);
2057
+ const framework = resolverFrameworkPadrao(obterOpcao(resto, "--framework"), config);
2058
+ const estrutura = resolverEstruturaSaidaPadrao(obterOpcao(resto, "--estrutura"), framework, config);
2059
+ const saida = resolverSaidaPadrao(obterOpcao(resto, "--saida"), alvo, config);
2060
+ codigoSaida = await comandoCompilar(posicionais[0], alvo, saida, estrutura, framework, cwd);
2061
+ }
2062
+ break;
2063
+ case "gerar":
2064
+ {
2065
+ const config = await carregarConfiguracaoProjeto(posicionais[1] ? path.resolve(cwd, posicionais[1]) : cwd);
2066
+ const alvo = resolverAlvoPadrao(posicionais[0] ?? obterOpcao(resto, "--alvo"), config);
2067
+ const framework = resolverFrameworkPadrao(obterOpcao(resto, "--framework"), config);
2068
+ const estrutura = resolverEstruturaSaidaPadrao(obterOpcao(resto, "--estrutura"), framework, config);
2069
+ const saida = resolverSaidaPadrao(obterOpcao(resto, "--saida"), alvo, config);
2070
+ codigoSaida = await comandoCompilar(posicionais[1], alvo, saida, estrutura, framework, cwd);
2071
+ }
2072
+ break;
2073
+ case "diagnosticos":
2074
+ codigoSaida = await comandoDiagnosticos(posicionais[0] ?? "", resto.includes("--json"));
2075
+ break;
2076
+ case "testar":
2077
+ {
2078
+ const config = await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd);
2079
+ const alvo = resolverAlvoPadrao(obterOpcao(resto, "--alvo"), config);
2080
+ const framework = resolverFrameworkPadrao(obterOpcao(resto, "--framework"), config);
2081
+ const estrutura = resolverEstruturaSaidaPadrao(obterOpcao(resto, "--estrutura"), framework, config);
2082
+ const saida = resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-testes"), alvo, config);
2083
+ codigoSaida = await comandoTestar(path.resolve(cwd, posicionais[0] ?? ""), alvo, saida, estrutura, framework);
2084
+ }
2085
+ break;
2086
+ case "verificar":
2087
+ codigoSaida = possuiFlag(resto, "--json")
2088
+ ? await comandoVerificarJson(posicionais[0], resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)), cwd)
2089
+ : await comandoVerificar(posicionais[0], resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)), cwd);
2090
+ break;
2091
+ case "inspecionar":
2092
+ codigoSaida = await comandoInspecionar(posicionais[0], possuiFlag(resto, "--json"), cwd);
2093
+ break;
2094
+ case "drift":
2095
+ codigoSaida = await comandoDrift(posicionais[0], possuiFlag(resto, "--json"), cwd);
2096
+ break;
2097
+ case "importar":
2098
+ {
2099
+ const fonte = normalizarFonteImportacao(posicionais[0]);
2100
+ if (!fonte || !posicionais[1]) {
2101
+ console.error("Uso: sema importar <nestjs|fastapi|flask|nextjs|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]");
2102
+ codigoSaida = 1;
2103
+ break;
2104
+ }
2105
+ codigoSaida = await comandoImportar(fonte, path.resolve(cwd, posicionais[1]), path.resolve(cwd, obterOpcao(resto, "--saida", "./sema/importado")), obterOpcao(resto, "--namespace"), possuiFlag(resto, "--json"));
2106
+ }
2107
+ break;
2108
+ case "formatar":
2109
+ codigoSaida = await comandoFormatar(posicionais[0], possuiFlag(resto, "--check"), possuiFlag(resto, "--json"));
2110
+ break;
2111
+ case "doctor":
2112
+ codigoSaida = await comandoDoctor();
2113
+ break;
2114
+ case "ajuda-ia":
2115
+ codigoSaida = await comandoAjudaIa();
2116
+ break;
2117
+ case "starter-ia":
2118
+ codigoSaida = await comandoStarterIa();
2119
+ break;
2120
+ case "prompt-ia":
2121
+ codigoSaida = await comandoPromptIa();
2122
+ break;
2123
+ case "prompt-ia-ui":
2124
+ codigoSaida = await comandoPromptIaUi();
2125
+ break;
2126
+ case "prompt-ia-react":
2127
+ codigoSaida = await comandoPromptIaReact();
2128
+ break;
2129
+ case "prompt-ia-sema-primeiro":
2130
+ codigoSaida = await comandoPromptIaSemaPrimeiro();
2131
+ break;
2132
+ case "exemplos-prompt-ia":
2133
+ codigoSaida = await comandoExemplosPromptIa();
2134
+ break;
2135
+ case "contexto-ia":
2136
+ codigoSaida = await comandoContextoIa(posicionais[0] ?? "", obterOpcao(resto, "--saida"), possuiFlag(resto, "--json"));
2137
+ break;
2138
+ default:
2139
+ console.log(ajuda());
2140
+ codigoSaida = 1;
2141
+ break;
2142
+ }
2143
+ process.exit(codigoSaida);
2144
+ }
2145
+ principal().catch((erro) => {
2146
+ console.error("Falha ao executar a CLI da Sema.");
2147
+ console.error(erro instanceof Error ? erro.stack ?? erro.message : erro);
2148
+ process.exit(1);
2149
+ });
2150
+ //# sourceMappingURL=index.js.map