@semacode/cli 0.9.0 → 1.1.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/AGENTS.md +50 -0
- package/README.md +24 -3
- package/SEMA_BRIEF.curto.txt +9 -0
- package/SEMA_BRIEF.md +49 -0
- package/SEMA_BRIEF.micro.txt +7 -0
- package/SEMA_INDEX.json +501 -0
- package/dist/drift.d.ts +15 -0
- package/dist/drift.js +496 -5
- package/dist/drift.js.map +1 -1
- package/dist/importador.d.ts +1 -1
- package/dist/importador.js +681 -3
- package/dist/importador.js.map +1 -1
- package/dist/index.js +1578 -123
- package/dist/index.js.map +1 -1
- package/dist/projeto.js +49 -1
- package/dist/projeto.js.map +1 -1
- package/dist/tipos.d.ts +1 -1
- package/docs/AGENT_STARTER.md +40 -8
- package/docs/como-ensinar-a-sema-para-ia.md +17 -11
- package/docs/fluxo-pratico-ia-sema.md +42 -38
- package/docs/instalacao-e-primeiro-uso.md +196 -0
- package/docs/integracao-com-ia.md +228 -0
- package/docs/pagamento-ponta-a-ponta.md +155 -0
- package/docs/prompt-base-ia-sema.md +10 -3
- package/docs/sintaxe.md +267 -0
- package/exemplos/automacao.sema +107 -0
- package/exemplos/cadastro_usuario.sema +54 -0
- package/exemplos/calculadora.sema +78 -0
- package/exemplos/crud_simples.sema +89 -0
- package/exemplos/operacao_estrategia.sema +402 -0
- package/exemplos/pagamento.sema +222 -0
- package/exemplos/pagamento_dominio.sema +35 -0
- package/exemplos/testes_embutidos.sema +45 -0
- package/exemplos/tratamento_erro.sema +157 -0
- package/llms-full.txt +34 -0
- package/llms.txt +17 -0
- package/node_modules/@sema/gerador-dart/package.json +1 -1
- package/node_modules/@sema/gerador-python/dist/index.js +92 -10
- package/node_modules/@sema/gerador-python/dist/index.js.map +1 -1
- package/node_modules/@sema/gerador-python/package.json +1 -1
- package/node_modules/@sema/gerador-typescript/package.json +1 -1
- package/node_modules/@sema/nucleo/package.json +1 -1
- package/node_modules/@sema/padroes/dist/index.js +47 -1
- package/node_modules/@sema/padroes/dist/index.js.map +1 -1
- package/node_modules/@sema/padroes/package.json +1 -1
- package/package.json +15 -7
package/dist/index.js
CHANGED
|
@@ -12,11 +12,13 @@ import { gerarTypeScript } from "@sema/gerador-typescript";
|
|
|
12
12
|
import { carregarConfiguracaoProjeto, carregarProjeto, resolverAlvoPadrao, resolverAlvosVerificacao, resolverEstruturaSaidaPadrao, resolverFrameworkPadrao, resolverSaidaPadrao, } from "./projeto.js";
|
|
13
13
|
import { importarProjetoLegado, resumoImportacao } from "./importador.js";
|
|
14
14
|
import { analisarDriftLegado } from "./drift.js";
|
|
15
|
-
const STARTER_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao para IA
|
|
15
|
+
const STARTER_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao para IA sobre software vivo em backend e front consumer.
|
|
16
16
|
|
|
17
17
|
Importante:
|
|
18
18
|
- a Sema se apresenta publicamente como protocolo e funciona tecnicamente como linguagem de intencao
|
|
19
|
-
- a Sema e protocolo de governanca semantica
|
|
19
|
+
- a Sema e protocolo de governanca semantica desenhado para IA, nao para ergonomia humana
|
|
20
|
+
- leitura humana e bonus toleravel, nao objetivo de produto
|
|
21
|
+
- a Sema nao e gerador magico que deveria fazer tudo
|
|
20
22
|
- a Sema modela contratos, estados, fluxos, erros, efeitos, garantias, vinculos e execucao
|
|
21
23
|
- a Sema gera codigo e scaffolding real para TypeScript, Python e Dart
|
|
22
24
|
- a Sema usa \`importar\` para bootstrap revisavel, nao para contrato final automatico
|
|
@@ -24,7 +26,8 @@ Importante:
|
|
|
24
26
|
- a Sema usa \`vinculos\` para ligar contrato a arquivo, simbolo, recurso e superficie real
|
|
25
27
|
- a Sema usa \`execucao\` para explicitar timeout, retry, compensacao e criticidade
|
|
26
28
|
- a Sema usa \`drift\` para medir diferenca entre contrato e codigo vivo com score, confianca e lacunas
|
|
27
|
-
- a Sema usa \`
|
|
29
|
+
- a Sema usa \`resumo\` e \`prompt-curto\` para IA pequena ou gratuita
|
|
30
|
+
- a Sema usa \`contexto-ia\` para gerar \`ast.json\`, \`ir.json\`, \`drift.json\`, \`briefing.json\` e artefatos compactos antes da edicao
|
|
28
31
|
- a Sema pode servir de base para interfaces graficas elegantes e coerentes
|
|
29
32
|
- a Sema nao gera uma interface completa sozinha no estado atual
|
|
30
33
|
- trate a Sema como cerebro semantico da aplicacao, nao como gerador magico de front-end pronto
|
|
@@ -33,6 +36,8 @@ Importante:
|
|
|
33
36
|
|
|
34
37
|
Regras:
|
|
35
38
|
- nao invente sintaxe fora da gramatica e dos exemplos oficiais
|
|
39
|
+
- se a IA for pequena, nao tente abrir tudo de uma vez
|
|
40
|
+
- use \`sema resumo\` e \`briefing.min.json\` antes de subir para o pacote completo
|
|
36
41
|
- trate \`ir --json\` como fonte de verdade semantica
|
|
37
42
|
- trate \`briefing.json\` como plano de intervencao antes de editar projeto vivo
|
|
38
43
|
- trate \`diagnosticos --json\` como fonte de correcao
|
|
@@ -41,6 +46,8 @@ Regras:
|
|
|
41
46
|
- nao cobre da Sema adivinhacao de negocio que nao esta no contrato nem no codigo
|
|
42
47
|
|
|
43
48
|
Comandos essenciais:
|
|
49
|
+
- resumo compacto por capacidade: \`sema resumo <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>]\`
|
|
50
|
+
- prompt curto para IA pequena: \`sema prompt-curto <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>]\`
|
|
44
51
|
- descoberta do projeto: \`sema inspecionar [arquivo-ou-pasta] --json\`
|
|
45
52
|
- auditoria do contrato vivo: \`sema drift <arquivo-ou-pasta> [--json]\`
|
|
46
53
|
- contexto completo do modulo: \`sema contexto-ia <arquivo.sema>\`
|
|
@@ -49,16 +56,16 @@ Comandos essenciais:
|
|
|
49
56
|
- validacao: \`sema validar <arquivo.sema> --json\`
|
|
50
57
|
- diagnosticos: \`sema diagnosticos <arquivo.sema> --json\`
|
|
51
58
|
- formatacao: \`sema formatar <arquivo.sema>\`
|
|
52
|
-
- importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
|
|
59
|
+
- importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
|
|
53
60
|
- geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>\`
|
|
54
61
|
- verificacao final: \`sema verificar <arquivo-ou-pasta> [--json]\`
|
|
55
62
|
|
|
56
63
|
Antes de editar:
|
|
57
64
|
1. leia README, docs de IA e um exemplo oficial parecido
|
|
58
|
-
2. rode \`sema
|
|
59
|
-
3. rode \`sema drift\` para medir impls, vinculos, rotas, score e lacunas
|
|
60
|
-
4. rode \`sema contexto-ia\` e leia \`briefing.json\`
|
|
61
|
-
5. consulte AST e IR do modulo alvo
|
|
65
|
+
2. se a IA for pequena, rode \`sema resumo <arquivo> --micro\` e leia \`briefing.min.json\`
|
|
66
|
+
3. se a IA aguentar mais, rode \`sema drift\` para medir impls, vinculos, rotas, score e lacunas
|
|
67
|
+
4. se a tarefa for pesada, rode \`sema contexto-ia\` e leia \`briefing.json\`
|
|
68
|
+
5. consulte AST e IR do modulo alvo so quando a capacidade realmente aguentar
|
|
62
69
|
|
|
63
70
|
Depois de editar:
|
|
64
71
|
1. rode \`sema formatar\`
|
|
@@ -66,11 +73,12 @@ Depois de editar:
|
|
|
66
73
|
3. se houver falha, use \`diagnosticos --json\`
|
|
67
74
|
4. rode \`sema drift\` de novo quando mexer em codigo vivo
|
|
68
75
|
5. se a tarefa pedir codigo derivado, rode \`sema compilar\`
|
|
69
|
-
6. feche com \`sema verificar
|
|
76
|
+
6. feche com \`sema verificar <arquivo-ou-pasta> --json\`
|
|
70
77
|
|
|
71
78
|
Priorize sempre:
|
|
72
79
|
- exemplos oficiais
|
|
73
80
|
- JSON da CLI
|
|
81
|
+
- o menor artefato que resolva a tarefa da IA atual
|
|
74
82
|
- score, confianca e lacunas do \`drift\`
|
|
75
83
|
- \`briefing.json\` como guia de mudanca
|
|
76
84
|
- consistencia semantica
|
|
@@ -88,16 +96,17 @@ Superficies que a IA deve enxergar como first-class:
|
|
|
88
96
|
|
|
89
97
|
Nao improvise quando faltar contexto.
|
|
90
98
|
`;
|
|
91
|
-
const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para
|
|
99
|
+
const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para operacao por IA.
|
|
92
100
|
|
|
93
|
-
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.
|
|
101
|
+
Trate a Sema como camada semantica e linguagem de especificacao executavel feita para IA, nao para leitura humana confortavel. Nao invente sintaxe, palavras-chave ou blocos fora da gramatica e dos exemplos oficiais.
|
|
94
102
|
|
|
95
103
|
Fontes de verdade, em ordem:
|
|
96
104
|
1. README do projeto
|
|
97
105
|
2. gramatica e documentacao de sintaxe da Sema
|
|
98
106
|
3. especificacao semantica da linguagem
|
|
99
107
|
4. exemplos oficiais, com prioridade para o vertical de pagamento
|
|
100
|
-
5.
|
|
108
|
+
5. \`sema resumo\` e \`briefing.min.json\` quando a IA for pequena
|
|
109
|
+
6. AST, IR e diagnosticos exportados pela CLI em JSON quando a capacidade aguentar
|
|
101
110
|
|
|
102
111
|
Regras de operacao:
|
|
103
112
|
- preserve o significado semantico
|
|
@@ -105,6 +114,7 @@ Regras de operacao:
|
|
|
105
114
|
- use diagnosticos estruturados como contrato de correcao
|
|
106
115
|
- use a IR como fonte de verdade semantica quando houver duvida
|
|
107
116
|
- nao conclua uma alteracao sem validar e verificar o modulo
|
|
117
|
+
- comece pelo menor artefato semantico que resolva a tarefa
|
|
108
118
|
|
|
109
119
|
Antes de editar \`.sema\`, entenda:
|
|
110
120
|
- o module alvo
|
|
@@ -292,6 +302,8 @@ Nao transforme isso em um \`index.html\` solto.
|
|
|
292
302
|
Comandos uteis da CLI para esse fluxo:
|
|
293
303
|
- \`sema starter-ia\`
|
|
294
304
|
- \`sema ajuda-ia\`
|
|
305
|
+
- \`sema resumo <arquivo-ou-pasta>\`
|
|
306
|
+
- \`sema prompt-curto <arquivo-ou-pasta>\`
|
|
295
307
|
- \`sema prompt-ia\`
|
|
296
308
|
- \`sema prompt-ia-ui\`
|
|
297
309
|
- \`sema prompt-ia-react\`
|
|
@@ -300,40 +312,106 @@ Comandos uteis da CLI para esse fluxo:
|
|
|
300
312
|
`;
|
|
301
313
|
const DIRETORIO_CLI_ATUAL = path.dirname(fileURLToPath(import.meta.url));
|
|
302
314
|
const VERSAO_CLI = pacoteCli.version;
|
|
315
|
+
const ARQUIVOS_CANONICOS_IA_RAIZ = [
|
|
316
|
+
"llms.txt",
|
|
317
|
+
"SEMA_BRIEF.md",
|
|
318
|
+
"SEMA_INDEX.json",
|
|
319
|
+
"AGENTS.md",
|
|
320
|
+
"README.md",
|
|
321
|
+
"llms-full.txt",
|
|
322
|
+
];
|
|
323
|
+
const DOCUMENTOS_SUPORTE_IA = [
|
|
324
|
+
"docs/AGENT_STARTER.md",
|
|
325
|
+
"docs/integracao-com-ia.md",
|
|
326
|
+
"docs/fluxo-pratico-ia-sema.md",
|
|
327
|
+
"docs/como-ensinar-a-sema-para-ia.md",
|
|
328
|
+
"docs/sintaxe.md",
|
|
329
|
+
"docs/cli.md",
|
|
330
|
+
];
|
|
303
331
|
function obterArgumentos() {
|
|
304
332
|
const [, , comando, ...resto] = process.argv;
|
|
305
333
|
return { comando: comando, resto };
|
|
306
334
|
}
|
|
335
|
+
function renderizarCaixaAscii(linhas) {
|
|
336
|
+
const largura = Math.max(...linhas.map((linha) => linha.length), 12);
|
|
337
|
+
const borda = `+${"-".repeat(largura + 2)}+`;
|
|
338
|
+
return [
|
|
339
|
+
borda,
|
|
340
|
+
...linhas.map((linha) => `| ${linha.padEnd(largura, " ")} |`),
|
|
341
|
+
borda,
|
|
342
|
+
].join("\n");
|
|
343
|
+
}
|
|
344
|
+
function renderizarSecaoAscii(titulo, linhas) {
|
|
345
|
+
return [
|
|
346
|
+
titulo,
|
|
347
|
+
...linhas.map((linha) => ` ${linha}`),
|
|
348
|
+
].join("\n");
|
|
349
|
+
}
|
|
307
350
|
function ajuda() {
|
|
308
|
-
return
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
351
|
+
return [
|
|
352
|
+
renderizarCaixaAscii([
|
|
353
|
+
`Sema CLI v${VERSAO_CLI}`,
|
|
354
|
+
"IA-first para contrato, geracao e adocao incremental",
|
|
355
|
+
"novo projeto, edicao guiada e legado sem contrato inicial",
|
|
356
|
+
]),
|
|
357
|
+
"",
|
|
358
|
+
renderizarSecaoAscii("Fluxos rapidos", [
|
|
359
|
+
"[1] Projeto novo / producao inicial",
|
|
360
|
+
"sema iniciar --template <base|nestjs|fastapi|nextjs-api|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer>",
|
|
361
|
+
"sema validar contratos/<modulo>.sema --json",
|
|
362
|
+
"sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>",
|
|
363
|
+
"sema verificar <arquivo-ou-pasta> --json",
|
|
364
|
+
"",
|
|
365
|
+
"[2] Editar projeto que ja usa Sema",
|
|
366
|
+
"sema inspecionar . --json",
|
|
367
|
+
"sema resumo <arquivo-ou-pasta> --micro --para mudanca",
|
|
368
|
+
"sema drift <arquivo-ou-pasta> --json",
|
|
369
|
+
"sema contexto-ia <arquivo.sema> --saida ./.tmp/contexto --json",
|
|
370
|
+
"",
|
|
371
|
+
"[3] Adotar Sema em projeto que ainda nao usa",
|
|
372
|
+
"sema importar <fonte> <diretorio> --saida <diretorio> --json",
|
|
373
|
+
"sema formatar <arquivo-ou-pasta>",
|
|
374
|
+
"sema validar <arquivo-ou-pasta> --json",
|
|
375
|
+
"sema drift <arquivo-ou-pasta> --json",
|
|
376
|
+
]),
|
|
377
|
+
"",
|
|
378
|
+
renderizarSecaoAscii("IA por capacidade", [
|
|
379
|
+
"pequena: sema resumo --micro + briefing.min.json + prompt-curto.txt",
|
|
380
|
+
"media: sema resumo --curto + drift.json + briefing.min.json",
|
|
381
|
+
"grande: sema contexto-ia + briefing.json + ir.json + ast.json",
|
|
382
|
+
]),
|
|
383
|
+
"",
|
|
384
|
+
renderizarSecaoAscii("Comandos principais", [
|
|
385
|
+
"descoberta: sema inspecionar [arquivo-ou-pasta] [--json]",
|
|
386
|
+
"auditoria: sema drift <arquivo-ou-pasta> [--json]",
|
|
387
|
+
"importacao: sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]",
|
|
388
|
+
"validacao: sema validar <arquivo-ou-pasta> [--json]",
|
|
389
|
+
"diagnostico: sema diagnosticos <arquivo.sema> [--json]",
|
|
390
|
+
"geracao: sema compilar <arquivo-ou-pasta> --alvo <python|typescript|dart> --saida <diretorio> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]",
|
|
391
|
+
"teste local: sema testar <arquivo.sema> --alvo <python|typescript|dart> --saida <diretorio-temporario> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]",
|
|
392
|
+
"verificacao final: sema verificar <arquivo-ou-pasta> [--saida <diretorio-base>] [--json]",
|
|
393
|
+
"formatacao: sema formatar <arquivo-ou-pasta> [--check] [--json]",
|
|
394
|
+
]),
|
|
395
|
+
"",
|
|
396
|
+
renderizarSecaoAscii("Ajuda IA-first", [
|
|
397
|
+
"sema ajuda-ia",
|
|
398
|
+
"sema starter-ia",
|
|
399
|
+
"sema resumo <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>] [--saida <diretorio>] [--raiz] [--json]",
|
|
400
|
+
"sema prompt-curto <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>] [--json]",
|
|
401
|
+
"sema prompt-ia",
|
|
402
|
+
"sema prompt-ia-ui",
|
|
403
|
+
"sema prompt-ia-react",
|
|
404
|
+
"sema prompt-ia-sema-primeiro",
|
|
405
|
+
"sema exemplos-prompt-ia",
|
|
406
|
+
"sema contexto-ia <arquivo.sema> [--saida <diretorio>] [--json]",
|
|
407
|
+
"sema sync-ai-entrypoints [--json]",
|
|
408
|
+
]),
|
|
409
|
+
"",
|
|
410
|
+
renderizarSecaoAscii("Operacional", [
|
|
411
|
+
"sema doctor",
|
|
412
|
+
"sema --versao | --version | -v",
|
|
413
|
+
]),
|
|
414
|
+
].join("\n");
|
|
337
415
|
}
|
|
338
416
|
async function carregarModulos(entrada, cwd = process.cwd()) {
|
|
339
417
|
return (await carregarProjeto(entrada, cwd)).modulosSelecionados;
|
|
@@ -356,18 +434,51 @@ function obterOpcao(args, nome, padrao) {
|
|
|
356
434
|
function possuiFlag(args, nome) {
|
|
357
435
|
return args.includes(nome);
|
|
358
436
|
}
|
|
437
|
+
const OPCOES_COM_VALOR = new Set([
|
|
438
|
+
"--template",
|
|
439
|
+
"--alvo",
|
|
440
|
+
"--saida",
|
|
441
|
+
"--estrutura",
|
|
442
|
+
"--framework",
|
|
443
|
+
"--namespace",
|
|
444
|
+
"--para",
|
|
445
|
+
]);
|
|
359
446
|
function obterPosicionais(args) {
|
|
360
447
|
const posicionais = [];
|
|
361
448
|
for (let indice = 0; indice < args.length; indice += 1) {
|
|
362
449
|
const atual = args[indice];
|
|
363
450
|
if (atual.startsWith("--")) {
|
|
364
|
-
|
|
451
|
+
if (OPCOES_COM_VALOR.has(atual)) {
|
|
452
|
+
indice += 1;
|
|
453
|
+
}
|
|
365
454
|
continue;
|
|
366
455
|
}
|
|
367
456
|
posicionais.push(atual);
|
|
368
457
|
}
|
|
369
458
|
return posicionais;
|
|
370
459
|
}
|
|
460
|
+
function normalizarTamanhoResumo(args) {
|
|
461
|
+
const escolhas = [
|
|
462
|
+
possuiFlag(args, "--micro") ? "micro" : null,
|
|
463
|
+
possuiFlag(args, "--curto") ? "curto" : null,
|
|
464
|
+
possuiFlag(args, "--medio") ? "medio" : null,
|
|
465
|
+
].filter((item) => item !== null);
|
|
466
|
+
if (escolhas.length > 1) {
|
|
467
|
+
throw new Error("Use apenas uma entre as flags --micro, --curto ou --medio.");
|
|
468
|
+
}
|
|
469
|
+
return escolhas[0] ?? "curto";
|
|
470
|
+
}
|
|
471
|
+
function normalizarModoResumo(valor) {
|
|
472
|
+
if (valor === "resumo"
|
|
473
|
+
|| valor === "onboarding"
|
|
474
|
+
|| valor === "review"
|
|
475
|
+
|| valor === "mudanca"
|
|
476
|
+
|| valor === "bug"
|
|
477
|
+
|| valor === "arquitetura") {
|
|
478
|
+
return valor;
|
|
479
|
+
}
|
|
480
|
+
return "resumo";
|
|
481
|
+
}
|
|
371
482
|
function comandoDisponivel(comando, argumentos = ["--version"]) {
|
|
372
483
|
const execucao = spawnSync(comando, argumentos, { stdio: "ignore", shell: process.platform === "win32" });
|
|
373
484
|
return (execucao.status ?? 1) === 0;
|
|
@@ -383,7 +494,10 @@ async function comandoDoctor() {
|
|
|
383
494
|
{ nome: "java", ok: comandoDisponivel("java") },
|
|
384
495
|
{ nome: "code", ok: comandoDisponivel("code", ["--version"]) },
|
|
385
496
|
];
|
|
386
|
-
console.log(
|
|
497
|
+
console.log(renderizarCaixaAscii([
|
|
498
|
+
"Sema doctor",
|
|
499
|
+
"checa a toolchain minima para validar, gerar e operar a CLI",
|
|
500
|
+
]));
|
|
387
501
|
for (const check of checks) {
|
|
388
502
|
console.log(`- ${check.nome}: ${check.ok ? "ok" : "ausente"}`);
|
|
389
503
|
}
|
|
@@ -424,6 +538,18 @@ function normalizarFonteImportacao(valor) {
|
|
|
424
538
|
if (valor === "next") {
|
|
425
539
|
return "nextjs";
|
|
426
540
|
}
|
|
541
|
+
if (valor === "next-consumer" || valor === "nextjs-consumer") {
|
|
542
|
+
return "nextjs-consumer";
|
|
543
|
+
}
|
|
544
|
+
if (valor === "react-vite" || valor === "react-vite-consumer" || valor === "react-consumer") {
|
|
545
|
+
return "react-vite-consumer";
|
|
546
|
+
}
|
|
547
|
+
if (valor === "angular" || valor === "angular-consumer") {
|
|
548
|
+
return "angular-consumer";
|
|
549
|
+
}
|
|
550
|
+
if (valor === "flutter" || valor === "flutter-consumer") {
|
|
551
|
+
return "flutter-consumer";
|
|
552
|
+
}
|
|
427
553
|
if (valor === "fb") {
|
|
428
554
|
return "firebase";
|
|
429
555
|
}
|
|
@@ -446,6 +572,10 @@ function normalizarFonteImportacao(valor) {
|
|
|
446
572
|
|| valor === "fastapi"
|
|
447
573
|
|| valor === "flask"
|
|
448
574
|
|| valor === "nextjs"
|
|
575
|
+
|| valor === "nextjs-consumer"
|
|
576
|
+
|| valor === "react-vite-consumer"
|
|
577
|
+
|| valor === "angular-consumer"
|
|
578
|
+
|| valor === "flutter-consumer"
|
|
449
579
|
|| valor === "firebase"
|
|
450
580
|
|| valor === "dotnet"
|
|
451
581
|
|| valor === "java"
|
|
@@ -463,6 +593,10 @@ function normalizarTemplateIniciar(valor) {
|
|
|
463
593
|
if (valor === "nestjs"
|
|
464
594
|
|| valor === "fastapi"
|
|
465
595
|
|| valor === "nextjs-api"
|
|
596
|
+
|| valor === "nextjs-consumer"
|
|
597
|
+
|| valor === "react-vite-consumer"
|
|
598
|
+
|| valor === "angular-consumer"
|
|
599
|
+
|| valor === "flutter-consumer"
|
|
466
600
|
|| valor === "node-firebase-worker"
|
|
467
601
|
|| valor === "aspnet-api"
|
|
468
602
|
|| valor === "springboot-api"
|
|
@@ -641,23 +775,377 @@ async function descobrirDocsIa() {
|
|
|
641
775
|
};
|
|
642
776
|
}
|
|
643
777
|
function renderizarCabecalhoDocsIa(descoberta) {
|
|
778
|
+
const documentos = descoberta.documentos.map((documento) => `\`${documento.nome}\``);
|
|
644
779
|
const linhas = [
|
|
645
|
-
"
|
|
646
|
-
|
|
647
|
-
|
|
780
|
+
"Modo IA-first da instalacao atual",
|
|
781
|
+
"- Use `sema` como interface publica principal.",
|
|
782
|
+
"- A Sema entra em projeto novo, projeto ja semantizado e adocao incremental em legado sem contrato inicial.",
|
|
783
|
+
"- Nao assuma monorepo, `node pacotes/cli/dist/index.js`, `npm run project:check` ou uma pasta `exemplos` externa ao projeto atual.",
|
|
784
|
+
"- Se a IA tiver contexto curto, comece por `sema resumo` e `sema prompt-curto`.",
|
|
785
|
+
"- Se a IA aguentar mais contexto, suba para `sema drift --json` e `sema contexto-ia`.",
|
|
786
|
+
"- So leia `ast.json` e `ir.json` completos quando a capacidade da IA realmente aguentar esse volume.",
|
|
648
787
|
];
|
|
649
|
-
if (
|
|
650
|
-
linhas.push(
|
|
651
|
-
for (const documento of descoberta.documentos) {
|
|
652
|
-
linhas.push(` - ${documento.nome}: ${documento.caminho}`);
|
|
653
|
-
}
|
|
788
|
+
if (documentos.length > 0) {
|
|
789
|
+
linhas.push(`- Documentos locais empacotados: ${documentos.join(", ")}.`);
|
|
654
790
|
}
|
|
655
791
|
else {
|
|
656
|
-
linhas.push("- Documentos locais
|
|
657
|
-
linhas.push(" - Esta instalacao da CLI nao conseguiu localizar a pasta docs ao redor do pacote atual.");
|
|
792
|
+
linhas.push("- Documentos locais empacotados: nenhum extra detectado. Siga a CLI, o contrato atual e os artefatos JSON.");
|
|
658
793
|
}
|
|
659
794
|
return linhas.join("\n");
|
|
660
795
|
}
|
|
796
|
+
function unicos(itens) {
|
|
797
|
+
return [...new Set(itens)];
|
|
798
|
+
}
|
|
799
|
+
function unicosOrdenados(itens) {
|
|
800
|
+
return unicos(itens).sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
801
|
+
}
|
|
802
|
+
function limitarLista(itens, limite) {
|
|
803
|
+
return itens.slice(0, limite);
|
|
804
|
+
}
|
|
805
|
+
function resumirListaTexto(itens, limite, padrao = "nenhum") {
|
|
806
|
+
if (itens.length === 0) {
|
|
807
|
+
return padrao;
|
|
808
|
+
}
|
|
809
|
+
const visiveis = itens.slice(0, limite);
|
|
810
|
+
const restante = itens.length - visiveis.length;
|
|
811
|
+
return restante > 0 ? `${visiveis.join(", ")} (+${restante})` : visiveis.join(", ");
|
|
812
|
+
}
|
|
813
|
+
function normalizarIdentificadorResumo(valor) {
|
|
814
|
+
return valor.replace(/[._]/g, " ").replace(/\s+/g, " ").trim();
|
|
815
|
+
}
|
|
816
|
+
function resumirCamposTask(task, campo, limiteCampos) {
|
|
817
|
+
const campos = (task[campo] ?? []).map((item) => item.nome).slice(0, limiteCampos);
|
|
818
|
+
if (campos.length === 0) {
|
|
819
|
+
return `${task.nome}(-)`;
|
|
820
|
+
}
|
|
821
|
+
return `${task.nome}(${campos.join(", ")})`;
|
|
822
|
+
}
|
|
823
|
+
function formatarEfeitoSemanticoResumido(efeito) {
|
|
824
|
+
if (efeito.textoOriginal) {
|
|
825
|
+
return efeito.textoOriginal;
|
|
826
|
+
}
|
|
827
|
+
const partes = [`${efeito.categoria} ${efeito.alvo}`];
|
|
828
|
+
if (efeito.criticidade) {
|
|
829
|
+
partes.push(`criticidade=${efeito.criticidade}`);
|
|
830
|
+
}
|
|
831
|
+
if (efeito.detalhe) {
|
|
832
|
+
partes.push(efeito.detalhe);
|
|
833
|
+
}
|
|
834
|
+
return partes.join(" ");
|
|
835
|
+
}
|
|
836
|
+
function calcularRiscoOperacionalResumo(resumoDrift) {
|
|
837
|
+
if (resumoDrift.tasks.some((task) => task.riscoOperacional === "alto")) {
|
|
838
|
+
return "alto";
|
|
839
|
+
}
|
|
840
|
+
if (resumoDrift.tasks.some((task) => task.riscoOperacional === "medio")) {
|
|
841
|
+
return "medio";
|
|
842
|
+
}
|
|
843
|
+
return "baixo";
|
|
844
|
+
}
|
|
845
|
+
function descreverFazModulo(ir, modulo) {
|
|
846
|
+
if (!ir) {
|
|
847
|
+
return `governa o modulo ${normalizarIdentificadorResumo(modulo)}`;
|
|
848
|
+
}
|
|
849
|
+
const partes = [];
|
|
850
|
+
if (ir.routes.length > 0) {
|
|
851
|
+
partes.push(`${ir.routes.length} rota(s)`);
|
|
852
|
+
}
|
|
853
|
+
if (ir.superficies.length > 0) {
|
|
854
|
+
partes.push(`${ir.superficies.length} superficie(s)`);
|
|
855
|
+
}
|
|
856
|
+
if (ir.tasks.length > 0) {
|
|
857
|
+
partes.push(`${ir.tasks.length} task(s)`);
|
|
858
|
+
}
|
|
859
|
+
const foco = ir.routes[0]?.nome ?? ir.superficies[0]?.nome ?? ir.tasks[0]?.nome ?? modulo;
|
|
860
|
+
return partes.length > 0
|
|
861
|
+
? `governa ${partes.join(", ")} com foco em ${normalizarIdentificadorResumo(foco)}`
|
|
862
|
+
: `governa o modulo ${normalizarIdentificadorResumo(modulo)}`;
|
|
863
|
+
}
|
|
864
|
+
function criarGuiaCapacidadeIa() {
|
|
865
|
+
return {
|
|
866
|
+
pequena: {
|
|
867
|
+
descricao: "IA gratuita ou com contexto curto. Leia so o cartao semantico e o briefing minimo.",
|
|
868
|
+
artefatos: ["resumo.micro.txt", "briefing.min.json", "prompt-curto.txt"],
|
|
869
|
+
ordemLeitura: ["resumo.micro.txt", "briefing.min.json", "resumo.curto.txt"],
|
|
870
|
+
evitar: ["ast.json", "ir.json", "diagnosticos.json"],
|
|
871
|
+
},
|
|
872
|
+
media: {
|
|
873
|
+
descricao: "IA com contexto medio. Aguenta resumo expandido, briefing minimo e drift.",
|
|
874
|
+
artefatos: ["resumo.curto.txt", "briefing.min.json", "drift.json", "prompt-curto.txt"],
|
|
875
|
+
ordemLeitura: ["resumo.curto.txt", "briefing.min.json", "drift.json", "resumo.md"],
|
|
876
|
+
evitar: ["ast.json"],
|
|
877
|
+
},
|
|
878
|
+
grande: {
|
|
879
|
+
descricao: "IA com contexto grande ou tool use. Pode consumir o pacote completo.",
|
|
880
|
+
artefatos: ["README.md", "resumo.md", "briefing.json", "drift.json", "ir.json", "ast.json"],
|
|
881
|
+
ordemLeitura: ["README.md", "resumo.md", "briefing.json", "drift.json", "ir.json", "ast.json"],
|
|
882
|
+
evitar: [],
|
|
883
|
+
},
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
function coletarResumoSemanticoModulo(contexto) {
|
|
887
|
+
const { arquivo, modulo, geradoEm, ir, briefing, drift } = contexto;
|
|
888
|
+
const tarefas = ir?.tasks ?? [];
|
|
889
|
+
const rotas = ir?.routes ?? [];
|
|
890
|
+
const superficies = ir?.superficies ?? [];
|
|
891
|
+
const regrasCriticas = unicosOrdenados([
|
|
892
|
+
...tarefas.flatMap((task) => task.rules),
|
|
893
|
+
...tarefas.flatMap((task) => task.guarantees),
|
|
894
|
+
]);
|
|
895
|
+
const efeitos = unicosOrdenados([
|
|
896
|
+
...tarefas.flatMap((task) => task.effects),
|
|
897
|
+
...rotas.flatMap((route) => route.efeitosPublicos.map((efeito) => formatarEfeitoSemanticoResumido(efeito))),
|
|
898
|
+
...superficies.flatMap((superficie) => superficie.effects.map((efeito) => formatarEfeitoSemanticoResumido(efeito))),
|
|
899
|
+
]);
|
|
900
|
+
const erros = unicosOrdenados([
|
|
901
|
+
...tarefas.flatMap((task) => Object.keys(task.errors)),
|
|
902
|
+
...tarefas.flatMap((task) => task.errosDetalhados.map((erro) => erro.codigo)),
|
|
903
|
+
...rotas.flatMap((route) => route.errosPublicos.map((erro) => erro.codigo)),
|
|
904
|
+
]);
|
|
905
|
+
const entidadesAfetadas = unicosOrdenados([
|
|
906
|
+
...(ir?.resumoAgente.entidadesAfetadas ?? []),
|
|
907
|
+
...tarefas.flatMap((task) => task.resumoAgente.entidadesAfetadas),
|
|
908
|
+
...rotas.flatMap((route) => route.resumoAgente.entidadesAfetadas),
|
|
909
|
+
...superficies.flatMap((superficie) => superficie.resumoAgente.entidadesAfetadas),
|
|
910
|
+
]);
|
|
911
|
+
return {
|
|
912
|
+
geradoEm,
|
|
913
|
+
arquivo,
|
|
914
|
+
modulo,
|
|
915
|
+
perfilCompatibilidade: ir?.perfilCompatibilidade ?? briefing.perfilCompatibilidade,
|
|
916
|
+
scoreSemantico: briefing.scoreSemantico,
|
|
917
|
+
confiancaGeral: briefing.confiancaGeral,
|
|
918
|
+
riscoOperacional: calcularRiscoOperacionalResumo(drift.resumo),
|
|
919
|
+
faz: descreverFazModulo(ir, modulo),
|
|
920
|
+
tarefasPrincipais: limitarLista(tarefas.map((task) => task.nome), 6),
|
|
921
|
+
entradasChave: limitarLista(tarefas.map((task) => resumirCamposTask(task, "input", 4)), 4),
|
|
922
|
+
saidasChave: limitarLista(tarefas.map((task) => resumirCamposTask(task, "output", 4)), 4),
|
|
923
|
+
superficiesPublicas: limitarLista(unicosOrdenados([
|
|
924
|
+
...briefing.superficiesImpactadas,
|
|
925
|
+
...rotas.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`),
|
|
926
|
+
]), 8),
|
|
927
|
+
regrasCriticas: limitarLista(regrasCriticas, 8),
|
|
928
|
+
efeitos: limitarLista(efeitos, 8),
|
|
929
|
+
erros: limitarLista(erros, 8),
|
|
930
|
+
entidadesAfetadas: limitarLista(entidadesAfetadas, 8),
|
|
931
|
+
arquivosProvaveis: limitarLista(unicosOrdenados(briefing.oQueTocar), 8),
|
|
932
|
+
simbolosRelacionados: limitarLista(unicosOrdenados(briefing.simbolosRelacionados), 8),
|
|
933
|
+
riscosPrincipais: limitarLista(unicosOrdenados(briefing.riscosPrincipais), 6),
|
|
934
|
+
lacunas: limitarLista(unicosOrdenados(briefing.oQueEstaFrouxo), 6),
|
|
935
|
+
inferido: limitarLista(unicosOrdenados(briefing.oQueFoiInferido), 6),
|
|
936
|
+
checksSugeridos: limitarLista(unicosOrdenados(briefing.oQueValidar), 6),
|
|
937
|
+
testesMinimos: limitarLista(unicosOrdenados(briefing.testesMinimos), 6),
|
|
938
|
+
consumerFramework: briefing.consumerFramework ?? drift.drift.consumerFramework ?? null,
|
|
939
|
+
appRoutes: limitarLista(unicosOrdenados(briefing.appRoutes ?? drift.drift.appRoutes ?? []), 8),
|
|
940
|
+
consumerSurfaces: limitarLista(unicosOrdenados(briefing.consumerSurfaces ?? []), 8),
|
|
941
|
+
consumerBridges: limitarLista(unicosOrdenados(briefing.consumerBridges ?? []), 8),
|
|
942
|
+
arquivosProvaveisEditar: limitarLista(unicosOrdenados(briefing.arquivosProvaveisEditar ?? briefing.oQueTocar), 8),
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
function renderizarResumoModuloTexto(resumo, tamanho, modo) {
|
|
946
|
+
const limite = tamanho === "micro" ? 2 : tamanho === "curto" ? 4 : 6;
|
|
947
|
+
const linhas = [
|
|
948
|
+
`MODO: ${modo}`,
|
|
949
|
+
`MODULO: ${resumo.modulo}`,
|
|
950
|
+
`FAZ: ${resumo.faz}`,
|
|
951
|
+
`PERFIL: ${resumo.perfilCompatibilidade}`,
|
|
952
|
+
`CONSUMER_FRAMEWORK: ${resumo.consumerFramework ?? "nenhum"}`,
|
|
953
|
+
`APP_ROUTES: ${resumirListaTexto(resumo.appRoutes, limite)}`,
|
|
954
|
+
`CONSUMER_SURFACES: ${resumirListaTexto(resumo.consumerSurfaces, limite)}`,
|
|
955
|
+
`CONSUMER_BRIDGES: ${resumirListaTexto(resumo.consumerBridges, limite)}`,
|
|
956
|
+
`PUBLICO: ${resumirListaTexto(resumo.superficiesPublicas, limite)}`,
|
|
957
|
+
`TAREFAS: ${resumirListaTexto(resumo.tarefasPrincipais, limite)}`,
|
|
958
|
+
`ENTRADAS: ${resumirListaTexto(resumo.entradasChave, limite)}`,
|
|
959
|
+
`SAIDAS: ${resumirListaTexto(resumo.saidasChave, limite)}`,
|
|
960
|
+
`REGRAS: ${resumirListaTexto(resumo.regrasCriticas, limite)}`,
|
|
961
|
+
`EFEITOS: ${resumirListaTexto(resumo.efeitos, limite)}`,
|
|
962
|
+
`ERROS: ${resumirListaTexto(resumo.erros, limite)}`,
|
|
963
|
+
`TOCAR: ${resumirListaTexto(resumo.arquivosProvaveis, limite)}`,
|
|
964
|
+
`VALIDAR: ${resumirListaTexto(resumo.checksSugeridos, limite)}`,
|
|
965
|
+
`TESTES: ${resumirListaTexto(resumo.testesMinimos, limite)}`,
|
|
966
|
+
`RISCOS: ${resumirListaTexto(resumo.riscosPrincipais, limite)}`,
|
|
967
|
+
`LACUNAS: ${resumirListaTexto(resumo.lacunas, limite)}`,
|
|
968
|
+
`INFERIDO: ${resumirListaTexto(resumo.inferido, limite)}`,
|
|
969
|
+
`CONFIANCA: ${resumo.confiancaGeral}`,
|
|
970
|
+
`RISCO_OPERACIONAL: ${resumo.riscoOperacional}`,
|
|
971
|
+
`SCORE: ${resumo.scoreSemantico}`,
|
|
972
|
+
`GERADO_EM: ${resumo.geradoEm}`,
|
|
973
|
+
];
|
|
974
|
+
if (tamanho === "micro") {
|
|
975
|
+
return `${linhas.slice(0, 12).join("\n")}\n`;
|
|
976
|
+
}
|
|
977
|
+
return `${linhas.join("\n")}\n`;
|
|
978
|
+
}
|
|
979
|
+
function renderizarResumoModuloMarkdown(resumo, modo, guiaPorCapacidade) {
|
|
980
|
+
const linhas = [
|
|
981
|
+
`# Resumo Sema para ${resumo.modulo}`,
|
|
982
|
+
"",
|
|
983
|
+
`- Modo: \`${modo}\``,
|
|
984
|
+
`- Gerado em: \`${resumo.geradoEm}\``,
|
|
985
|
+
`- Arquivo: \`${resumo.arquivo}\``,
|
|
986
|
+
`- Perfil: \`${resumo.perfilCompatibilidade}\``,
|
|
987
|
+
`- Score: \`${resumo.scoreSemantico}\``,
|
|
988
|
+
`- Confianca: \`${resumo.confiancaGeral}\``,
|
|
989
|
+
`- Risco operacional: \`${resumo.riscoOperacional}\``,
|
|
990
|
+
"",
|
|
991
|
+
"## O que este modulo faz",
|
|
992
|
+
"",
|
|
993
|
+
`- ${resumo.faz}`,
|
|
994
|
+
`- Superficies publicas: ${resumirListaTexto(resumo.superficiesPublicas, 8)}`,
|
|
995
|
+
`- Tarefas principais: ${resumirListaTexto(resumo.tarefasPrincipais, 8)}`,
|
|
996
|
+
"",
|
|
997
|
+
"## Contrato util para IA",
|
|
998
|
+
"",
|
|
999
|
+
`- Entradas chave: ${resumirListaTexto(resumo.entradasChave, 6)}`,
|
|
1000
|
+
`- Saidas chave: ${resumirListaTexto(resumo.saidasChave, 6)}`,
|
|
1001
|
+
`- Regras criticas: ${resumirListaTexto(resumo.regrasCriticas, 6)}`,
|
|
1002
|
+
`- Efeitos: ${resumirListaTexto(resumo.efeitos, 6)}`,
|
|
1003
|
+
`- Erros: ${resumirListaTexto(resumo.erros, 6)}`,
|
|
1004
|
+
`- Entidades afetadas: ${resumirListaTexto(resumo.entidadesAfetadas, 6)}`,
|
|
1005
|
+
"",
|
|
1006
|
+
...(resumo.consumerFramework
|
|
1007
|
+
? [
|
|
1008
|
+
"## Consumer IA-first",
|
|
1009
|
+
"",
|
|
1010
|
+
`- Framework consumer: ${resumo.consumerFramework}`,
|
|
1011
|
+
`- Rotas de app: ${resumirListaTexto(resumo.appRoutes, 6)}`,
|
|
1012
|
+
`- Superficies consumer: ${resumirListaTexto(resumo.consumerSurfaces, 6)}`,
|
|
1013
|
+
`- Bridges consumer: ${resumirListaTexto(resumo.consumerBridges, 6)}`,
|
|
1014
|
+
"",
|
|
1015
|
+
]
|
|
1016
|
+
: []),
|
|
1017
|
+
"## Intervencao segura",
|
|
1018
|
+
"",
|
|
1019
|
+
`- Arquivos provaveis: ${resumirListaTexto(resumo.arquivosProvaveis, 6)}`,
|
|
1020
|
+
`- Simbolos relacionados: ${resumirListaTexto(resumo.simbolosRelacionados, 6)}`,
|
|
1021
|
+
`- Riscos principais: ${resumirListaTexto(resumo.riscosPrincipais, 6)}`,
|
|
1022
|
+
`- Lacunas: ${resumirListaTexto(resumo.lacunas, 6)}`,
|
|
1023
|
+
`- O que foi inferido: ${resumirListaTexto(resumo.inferido, 6)}`,
|
|
1024
|
+
`- Checks sugeridos: ${resumirListaTexto(resumo.checksSugeridos, 6)}`,
|
|
1025
|
+
`- Testes minimos: ${resumirListaTexto(resumo.testesMinimos, 6)}`,
|
|
1026
|
+
"",
|
|
1027
|
+
"## Guia por capacidade de IA",
|
|
1028
|
+
"",
|
|
1029
|
+
];
|
|
1030
|
+
for (const capacidade of ["pequena", "media", "grande"]) {
|
|
1031
|
+
const guia = guiaPorCapacidade[capacidade];
|
|
1032
|
+
linhas.push(`### ${capacidade}`);
|
|
1033
|
+
linhas.push("");
|
|
1034
|
+
linhas.push(`- ${guia.descricao}`);
|
|
1035
|
+
linhas.push(`- Artefatos: ${guia.artefatos.map((item) => `\`${item}\``).join(", ")}`);
|
|
1036
|
+
linhas.push(`- Ordem de leitura: ${guia.ordemLeitura.map((item) => `\`${item}\``).join(" -> ")}`);
|
|
1037
|
+
linhas.push(`- Evitar: ${guia.evitar.length > 0 ? guia.evitar.map((item) => `\`${item}\``).join(", ") : "nada obrigatorio"}`);
|
|
1038
|
+
linhas.push("");
|
|
1039
|
+
}
|
|
1040
|
+
return `${linhas.join("\n").trim()}\n`;
|
|
1041
|
+
}
|
|
1042
|
+
function criarBriefingMinimo(resumo, modo, tamanho) {
|
|
1043
|
+
return {
|
|
1044
|
+
comando: "briefing-minimo",
|
|
1045
|
+
geradoEm: resumo.geradoEm,
|
|
1046
|
+
cliVersao: VERSAO_CLI,
|
|
1047
|
+
modo,
|
|
1048
|
+
tamanho,
|
|
1049
|
+
arquivo: resumo.arquivo,
|
|
1050
|
+
modulo: resumo.modulo,
|
|
1051
|
+
perfilCompatibilidade: resumo.perfilCompatibilidade,
|
|
1052
|
+
scoreSemantico: resumo.scoreSemantico,
|
|
1053
|
+
confiancaGeral: resumo.confiancaGeral,
|
|
1054
|
+
riscoOperacional: resumo.riscoOperacional,
|
|
1055
|
+
faz: resumo.faz,
|
|
1056
|
+
publico: resumo.superficiesPublicas,
|
|
1057
|
+
tarefasPrincipais: resumo.tarefasPrincipais,
|
|
1058
|
+
entradasChave: resumo.entradasChave,
|
|
1059
|
+
saidasChave: resumo.saidasChave,
|
|
1060
|
+
regrasCriticas: resumo.regrasCriticas,
|
|
1061
|
+
efeitos: resumo.efeitos,
|
|
1062
|
+
erros: resumo.erros,
|
|
1063
|
+
arquivosProvaveis: resumo.arquivosProvaveis,
|
|
1064
|
+
arquivosProvaveisEditar: resumo.arquivosProvaveisEditar,
|
|
1065
|
+
simbolosRelacionados: resumo.simbolosRelacionados,
|
|
1066
|
+
riscosPrincipais: resumo.riscosPrincipais,
|
|
1067
|
+
lacunas: resumo.lacunas,
|
|
1068
|
+
inferido: resumo.inferido,
|
|
1069
|
+
checksSugeridos: resumo.checksSugeridos,
|
|
1070
|
+
testesMinimos: resumo.testesMinimos,
|
|
1071
|
+
consumerFramework: resumo.consumerFramework,
|
|
1072
|
+
appRoutes: resumo.appRoutes,
|
|
1073
|
+
consumerSurfaces: resumo.consumerSurfaces,
|
|
1074
|
+
consumerBridges: resumo.consumerBridges,
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
function criarPromptCurtoModulo(resumo, modo, tamanho, capacidade) {
|
|
1078
|
+
const resumoTexto = renderizarResumoModuloTexto(resumo, tamanho, modo).trim();
|
|
1079
|
+
return `Voce esta operando Sema em modo IA-first.
|
|
1080
|
+
|
|
1081
|
+
Esta linguagem nao foi desenhada para agradar humano; ela existe para reduzir ambiguidade para IA.
|
|
1082
|
+
|
|
1083
|
+
Capacidade alvo: ${capacidade}
|
|
1084
|
+
Modo da tarefa: ${modo}
|
|
1085
|
+
|
|
1086
|
+
Regras:
|
|
1087
|
+
- nao invente sintaxe nem bloco fora da gramatica oficial
|
|
1088
|
+
- preserve a intencao do contrato
|
|
1089
|
+
- use este resumo como fonte compacta inicial
|
|
1090
|
+
- se a tarefa pedir mais contexto, suba para \`briefing.min.json\`, \`drift.json\` e depois \`ir.json\`
|
|
1091
|
+
- nao saia editando software vivo sem olhar risco, lacuna e checks sugeridos
|
|
1092
|
+
${resumo.consumerFramework ? "- se for tarefa visual consumer, priorize `appRoutes`, `consumerSurfaces` e `consumerBridges` antes de abrir arquivos aleatorios" : ""}
|
|
1093
|
+
|
|
1094
|
+
Contexto compacto:
|
|
1095
|
+
${resumoTexto}
|
|
1096
|
+
`;
|
|
1097
|
+
}
|
|
1098
|
+
function renderizarResumoProjetoMarkdown(geradoEm, modulos, guiaPorCapacidade) {
|
|
1099
|
+
const entradaCanonica = criarEntradaCanonicaProjeto(guiaPorCapacidade);
|
|
1100
|
+
const linhas = [
|
|
1101
|
+
"# SEMA_BRIEF",
|
|
1102
|
+
"",
|
|
1103
|
+
"Sema e IA-first. Este arquivo existe para IA achar o ponto de entrada do projeto sem ter que catar o repo inteiro feito barata tonta.",
|
|
1104
|
+
"",
|
|
1105
|
+
`- Gerado em: \`${geradoEm}\``,
|
|
1106
|
+
`- Modulos: \`${modulos.length}\``,
|
|
1107
|
+
"",
|
|
1108
|
+
"## Entrada canonica para IA",
|
|
1109
|
+
"",
|
|
1110
|
+
`- Ordem minima: ${entradaCanonica.ordemLeitura.join(" -> ")}`,
|
|
1111
|
+
`- IA pequena: ${entradaCanonica.porCapacidade.pequena.join(" -> ")}`,
|
|
1112
|
+
`- IA media: ${entradaCanonica.porCapacidade.media.join(" -> ")}`,
|
|
1113
|
+
`- IA grande: ${entradaCanonica.porCapacidade.grande.join(" -> ")}`,
|
|
1114
|
+
"",
|
|
1115
|
+
"## Guia por capacidade",
|
|
1116
|
+
"",
|
|
1117
|
+
];
|
|
1118
|
+
for (const capacidade of ["pequena", "media", "grande"]) {
|
|
1119
|
+
const guia = guiaPorCapacidade[capacidade];
|
|
1120
|
+
linhas.push(`- ${capacidade}: ${guia.descricao} Artefatos: ${guia.artefatos.join(", ")}.`);
|
|
1121
|
+
}
|
|
1122
|
+
linhas.push("");
|
|
1123
|
+
linhas.push("## Modulos");
|
|
1124
|
+
linhas.push("");
|
|
1125
|
+
for (const modulo of modulos) {
|
|
1126
|
+
linhas.push(`### ${modulo.modulo}`);
|
|
1127
|
+
linhas.push(`- Faz: ${modulo.faz}`);
|
|
1128
|
+
linhas.push(`- Publico: ${resumirListaTexto(modulo.superficiesPublicas, 4)}`);
|
|
1129
|
+
linhas.push(`- Tocar: ${resumirListaTexto(modulo.arquivosProvaveis, 4)}`);
|
|
1130
|
+
linhas.push(`- Score: ${modulo.scoreSemantico} | Confianca: ${modulo.confiancaGeral} | Risco: ${modulo.riscoOperacional}`);
|
|
1131
|
+
linhas.push(`- Lacunas: ${resumirListaTexto(modulo.lacunas, 4)}`);
|
|
1132
|
+
linhas.push("");
|
|
1133
|
+
}
|
|
1134
|
+
return `${linhas.join("\n").trim()}\n`;
|
|
1135
|
+
}
|
|
1136
|
+
function criarEntradaCanonicaProjeto(guiaPorCapacidade) {
|
|
1137
|
+
return {
|
|
1138
|
+
descricao: "Entrada canonica do repositorio para IA. O repo nao e human-first; a IA deve começar por esses artefatos antes de abrir codigo cru.",
|
|
1139
|
+
ordemLeitura: [...ARQUIVOS_CANONICOS_IA_RAIZ],
|
|
1140
|
+
porCapacidade: {
|
|
1141
|
+
pequena: ["llms.txt", "SEMA_BRIEF.micro.txt", "SEMA_INDEX.json", "AGENTS.md"],
|
|
1142
|
+
media: ["llms.txt", "SEMA_BRIEF.curto.txt", "SEMA_INDEX.json", "AGENTS.md", "README.md"],
|
|
1143
|
+
grande: ["llms-full.txt", "SEMA_BRIEF.md", "SEMA_INDEX.json", "AGENTS.md", "README.md"],
|
|
1144
|
+
},
|
|
1145
|
+
docsSuporte: [...DOCUMENTOS_SUPORTE_IA],
|
|
1146
|
+
guiaPorCapacidade,
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
661
1149
|
function falharContextoIa(mensagem) {
|
|
662
1150
|
throw new Error(mensagem);
|
|
663
1151
|
}
|
|
@@ -691,6 +1179,41 @@ function resumirDriftPorModulo(modulo, caminho, resultadoDrift) {
|
|
|
691
1179
|
const recursosDivergentes = modulo
|
|
692
1180
|
? resultadoDrift.recursos_divergentes.filter((recurso) => recurso.modulo === modulo)
|
|
693
1181
|
: [];
|
|
1182
|
+
const vinculosModulo = modulo
|
|
1183
|
+
? [
|
|
1184
|
+
...resultadoDrift.vinculos_validos.filter((vinculo) => vinculo.modulo === modulo),
|
|
1185
|
+
...resultadoDrift.vinculos_quebrados.filter((vinculo) => vinculo.modulo === modulo),
|
|
1186
|
+
]
|
|
1187
|
+
: [];
|
|
1188
|
+
const rotasConsumerModulo = new Set(vinculosModulo
|
|
1189
|
+
.filter((vinculo) => vinculo.tipo === "superficie")
|
|
1190
|
+
.map((vinculo) => vinculo.valor));
|
|
1191
|
+
const arquivosRelacionados = [...new Set([
|
|
1192
|
+
...tasks.flatMap((task) => task.arquivosReferenciados),
|
|
1193
|
+
...tasks.flatMap((task) => task.arquivosProvaveisEditar),
|
|
1194
|
+
...implsValidos.map((impl) => impl.arquivo).filter((item) => Boolean(item)),
|
|
1195
|
+
...implsQuebrados.flatMap((impl) => impl.candidatos?.map((candidato) => candidato.arquivo) ?? []),
|
|
1196
|
+
...vinculosValidos.map((vinculo) => vinculo.arquivo).filter((item) => Boolean(item)),
|
|
1197
|
+
...recursosValidos.map((recurso) => recurso.arquivo).filter(Boolean),
|
|
1198
|
+
...recursosDivergentes.map((recurso) => recurso.arquivo).filter(Boolean),
|
|
1199
|
+
])].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1200
|
+
const consumerSurfaces = resultadoDrift.consumerSurfaces
|
|
1201
|
+
.filter((surface) => arquivosRelacionados.includes(surface.arquivo)
|
|
1202
|
+
|| rotasConsumerModulo.has(surface.rota))
|
|
1203
|
+
.map((surface) => `${surface.tipoArquivo}:${surface.rota} -> ${surface.arquivo}`)
|
|
1204
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1205
|
+
const consumerBridges = resultadoDrift.consumerBridges
|
|
1206
|
+
.filter((bridge) => arquivosRelacionados.includes(bridge.arquivo))
|
|
1207
|
+
.map((bridge) => bridge.caminho)
|
|
1208
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1209
|
+
const appRoutes = [...new Set(resultadoDrift.consumerSurfaces
|
|
1210
|
+
.filter((surface) => arquivosRelacionados.includes(surface.arquivo)
|
|
1211
|
+
|| rotasConsumerModulo.has(surface.rota))
|
|
1212
|
+
.map((surface) => surface.rota))]
|
|
1213
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1214
|
+
const consumerFramework = appRoutes.length > 0 || consumerBridges.length > 0
|
|
1215
|
+
? resultadoDrift.consumerFramework
|
|
1216
|
+
: null;
|
|
694
1217
|
return {
|
|
695
1218
|
caminho,
|
|
696
1219
|
modulo,
|
|
@@ -707,15 +1230,12 @@ function resumirDriftPorModulo(modulo, caminho, resultadoDrift) {
|
|
|
707
1230
|
: tasks.some((task) => task.confiancaVinculo === "media")
|
|
708
1231
|
? "media"
|
|
709
1232
|
: "baixa",
|
|
710
|
-
arquivosRelacionados
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
...recursosValidos.map((recurso) => recurso.arquivo).filter(Boolean),
|
|
717
|
-
...recursosDivergentes.map((recurso) => recurso.arquivo).filter(Boolean),
|
|
718
|
-
])].sort((a, b) => a.localeCompare(b, "pt-BR")),
|
|
1233
|
+
arquivosRelacionados,
|
|
1234
|
+
arquivosProvaveisEditar: arquivosRelacionados,
|
|
1235
|
+
consumerFramework,
|
|
1236
|
+
appRoutes,
|
|
1237
|
+
consumerSurfaces,
|
|
1238
|
+
consumerBridges,
|
|
719
1239
|
checksSugeridos: [...new Set(tasks.flatMap((task) => task.checksSugeridos))],
|
|
720
1240
|
lacunas: [...new Set(tasks.flatMap((task) => task.lacunas))],
|
|
721
1241
|
tasks,
|
|
@@ -737,6 +1257,7 @@ function criarBriefingAgente(arquivo, modulo, ir, resumoDrift, resultadoDrift) {
|
|
|
737
1257
|
...(ir?.resumoAgente.riscos ?? []),
|
|
738
1258
|
])],
|
|
739
1259
|
oQueTocar: resumoDrift.arquivosRelacionados,
|
|
1260
|
+
arquivosProvaveisEditar: resumoDrift.arquivosProvaveisEditar,
|
|
740
1261
|
oQueValidar: [...new Set([
|
|
741
1262
|
...resumoDrift.checksSugeridos,
|
|
742
1263
|
...resultadoDrift.resumo_operacional.oQueValidar,
|
|
@@ -764,20 +1285,20 @@ function criarBriefingAgente(arquivo, modulo, ir, resumoDrift, resultadoDrift) {
|
|
|
764
1285
|
...(ir?.routes.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`) ?? []),
|
|
765
1286
|
...(ir?.superficies.map((superficie) => `${superficie.tipo}:${superficie.nome}`) ?? []),
|
|
766
1287
|
],
|
|
1288
|
+
consumerFramework: resumoDrift.consumerFramework,
|
|
1289
|
+
appRoutes: resumoDrift.appRoutes,
|
|
1290
|
+
consumerSurfaces: resumoDrift.consumerSurfaces,
|
|
1291
|
+
consumerBridges: resumoDrift.consumerBridges,
|
|
767
1292
|
testesMinimos: [
|
|
768
1293
|
"sema validar <arquivo> --json",
|
|
769
1294
|
"sema drift <arquivo> --json",
|
|
770
|
-
"sema verificar
|
|
1295
|
+
"sema verificar <arquivo-ou-pasta> --json",
|
|
771
1296
|
],
|
|
772
1297
|
};
|
|
773
1298
|
}
|
|
774
|
-
async function
|
|
1299
|
+
async function carregarContextoModuloIa(arquivoEntrada) {
|
|
775
1300
|
const arquivo = path.resolve(arquivoEntrada);
|
|
776
1301
|
garantirArquivoSema(arquivo);
|
|
777
|
-
const pastaBase = pastaSaidaOpcional
|
|
778
|
-
? path.resolve(pastaSaidaOpcional)
|
|
779
|
-
: path.resolve(process.cwd(), ".tmp", "contexto-ia", path.basename(arquivo, ".sema"));
|
|
780
|
-
await mkdir(pastaBase, { recursive: true });
|
|
781
1302
|
const contextoProjeto = await carregarProjeto(arquivo, process.cwd());
|
|
782
1303
|
const resultadoModulo = contextoProjeto.modulosSelecionados.find((item) => path.resolve(item.caminho) === arquivo)?.resultado;
|
|
783
1304
|
if (!resultadoModulo) {
|
|
@@ -785,6 +1306,7 @@ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
|
|
|
785
1306
|
}
|
|
786
1307
|
const sucesso = !temErros(resultadoModulo.diagnosticos);
|
|
787
1308
|
const modulo = resultadoModulo.modulo?.nome ?? path.basename(arquivo, ".sema");
|
|
1309
|
+
const geradoEm = new Date().toISOString();
|
|
788
1310
|
const resultadoDrift = await analisarDriftLegado(contextoProjeto);
|
|
789
1311
|
const drift = {
|
|
790
1312
|
comando: "drift",
|
|
@@ -829,21 +1351,146 @@ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
|
|
|
829
1351
|
ir: resultadoModulo.ir ?? null,
|
|
830
1352
|
};
|
|
831
1353
|
const briefing = criarBriefingAgente(arquivo, modulo, resultadoModulo.ir ?? null, drift.resumo, resultadoDrift);
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
1354
|
+
return {
|
|
1355
|
+
arquivo,
|
|
1356
|
+
modulo,
|
|
1357
|
+
sucesso,
|
|
1358
|
+
geradoEm,
|
|
1359
|
+
diagnosticos: resultadoModulo.diagnosticos,
|
|
1360
|
+
ir: resultadoModulo.ir ?? null,
|
|
1361
|
+
validar,
|
|
1362
|
+
diagnosticosJson: diagnosticos,
|
|
1363
|
+
ast,
|
|
1364
|
+
irJson: ir,
|
|
1365
|
+
drift,
|
|
1366
|
+
briefing,
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
async function gerarArquivosResumoModuloIa(contexto, pastaBase) {
|
|
1370
|
+
const guiaPorCapacidade = criarGuiaCapacidadeIa();
|
|
1371
|
+
const resumoSemantico = coletarResumoSemanticoModulo(contexto);
|
|
1372
|
+
const resumoMicro = renderizarResumoModuloTexto(resumoSemantico, "micro", "resumo");
|
|
1373
|
+
const resumoCurto = renderizarResumoModuloTexto(resumoSemantico, "curto", "resumo");
|
|
1374
|
+
const resumoMarkdown = renderizarResumoModuloMarkdown(resumoSemantico, "resumo", guiaPorCapacidade);
|
|
1375
|
+
const briefingMinimo = criarBriefingMinimo(resumoSemantico, "resumo", "curto");
|
|
1376
|
+
const promptCurto = criarPromptCurtoModulo(resumoSemantico, "mudanca", "curto", "pequena");
|
|
1377
|
+
await writeFile(path.join(pastaBase, "resumo.micro.txt"), resumoMicro, "utf8");
|
|
1378
|
+
await writeFile(path.join(pastaBase, "resumo.curto.txt"), resumoCurto, "utf8");
|
|
1379
|
+
await writeFile(path.join(pastaBase, "resumo.md"), resumoMarkdown, "utf8");
|
|
1380
|
+
await writeFile(path.join(pastaBase, "briefing.min.json"), `${JSON.stringify(briefingMinimo, null, 2)}\n`, "utf8");
|
|
1381
|
+
await writeFile(path.join(pastaBase, "prompt-curto.txt"), promptCurto, "utf8");
|
|
1382
|
+
return {
|
|
1383
|
+
artefatosCompactos: ["resumo.micro.txt", "resumo.curto.txt", "resumo.md", "briefing.min.json", "prompt-curto.txt"],
|
|
1384
|
+
guiaPorCapacidade,
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
async function gerarResumoProjetoIa(entrada, pastaSaidaOpcional, escreverNaRaiz = false) {
|
|
1388
|
+
const contextoProjeto = await carregarProjeto(entrada, process.cwd());
|
|
1389
|
+
const geradoEm = new Date().toISOString();
|
|
1390
|
+
const guiaPorCapacidade = criarGuiaCapacidadeIa();
|
|
1391
|
+
const entradaCanonica = criarEntradaCanonicaProjeto(guiaPorCapacidade);
|
|
1392
|
+
const resultadoDrift = await analisarDriftLegado(contextoProjeto);
|
|
1393
|
+
const modulos = contextoProjeto.modulosSelecionados.map((item) => {
|
|
1394
|
+
const modulo = item.resultado.modulo?.nome ?? path.basename(item.caminho, ".sema");
|
|
1395
|
+
const driftResumo = resumirDriftPorModulo(modulo, item.caminho, resultadoDrift);
|
|
1396
|
+
const briefing = criarBriefingAgente(item.caminho, modulo, item.resultado.ir ?? null, driftResumo, resultadoDrift);
|
|
1397
|
+
return coletarResumoSemanticoModulo({
|
|
1398
|
+
arquivo: item.caminho,
|
|
1399
|
+
modulo,
|
|
1400
|
+
geradoEm,
|
|
1401
|
+
ir: item.resultado.ir ?? null,
|
|
1402
|
+
briefing,
|
|
1403
|
+
drift: {
|
|
1404
|
+
comando: "drift",
|
|
1405
|
+
caminho: item.caminho,
|
|
1406
|
+
modulo,
|
|
1407
|
+
sucesso: resultadoDrift.sucesso,
|
|
1408
|
+
resumo: driftResumo,
|
|
1409
|
+
drift: resultadoDrift,
|
|
1410
|
+
},
|
|
1411
|
+
});
|
|
1412
|
+
});
|
|
1413
|
+
const baseProjeto = contextoProjeto.baseProjeto;
|
|
1414
|
+
const pastaSaida = escreverNaRaiz
|
|
1415
|
+
? baseProjeto
|
|
1416
|
+
: pastaSaidaOpcional
|
|
1417
|
+
? path.resolve(pastaSaidaOpcional)
|
|
1418
|
+
: path.resolve(baseProjeto, ".tmp", "sema-resumo");
|
|
1419
|
+
await mkdir(pastaSaida, { recursive: true });
|
|
1420
|
+
const semaBrief = renderizarResumoProjetoMarkdown(geradoEm, modulos, guiaPorCapacidade);
|
|
1421
|
+
const indexJson = {
|
|
1422
|
+
comando: "resumo-projeto",
|
|
1423
|
+
geradoEm,
|
|
1424
|
+
cliVersao: VERSAO_CLI,
|
|
1425
|
+
baseProjeto,
|
|
1426
|
+
totalModulos: modulos.length,
|
|
1427
|
+
entradaCanonica,
|
|
1428
|
+
guiaPorCapacidade,
|
|
1429
|
+
modulos,
|
|
1430
|
+
};
|
|
1431
|
+
const micro = [
|
|
1432
|
+
`PROJETO: ${path.basename(baseProjeto)}`,
|
|
1433
|
+
`MODULOS: ${modulos.length}`,
|
|
1434
|
+
`ENTRADA_IA: ${entradaCanonica.porCapacidade.pequena.join(" -> ")}`,
|
|
1435
|
+
`TOP_MODULOS: ${resumirListaTexto(modulos.map((modulo) => modulo.modulo), 3)}`,
|
|
1436
|
+
`TOP_RISCOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.riscosPrincipais)), 3)}`,
|
|
1437
|
+
`TOP_LACUNAS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.lacunas)), 3)}`,
|
|
1438
|
+
`GERADO_EM: ${geradoEm}`,
|
|
1439
|
+
"",
|
|
1440
|
+
].join("\n");
|
|
1441
|
+
const curto = [
|
|
1442
|
+
`PROJETO: ${path.basename(baseProjeto)}`,
|
|
1443
|
+
`BASE: ${baseProjeto}`,
|
|
1444
|
+
`MODULOS: ${modulos.length}`,
|
|
1445
|
+
`ENTRADA_IA: ${entradaCanonica.porCapacidade.media.join(" -> ")}`,
|
|
1446
|
+
`TOP_MODULOS: ${resumirListaTexto(modulos.map((modulo) => modulo.modulo), 6)}`,
|
|
1447
|
+
`TOP_RISCOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.riscosPrincipais)), 6)}`,
|
|
1448
|
+
`TOP_LACUNAS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.lacunas)), 6)}`,
|
|
1449
|
+
`TOP_ARQUIVOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.arquivosProvaveis)), 6)}`,
|
|
1450
|
+
`GERADO_EM: ${geradoEm}`,
|
|
1451
|
+
"",
|
|
1452
|
+
].join("\n");
|
|
1453
|
+
await writeFile(path.join(pastaSaida, "SEMA_BRIEF.md"), semaBrief, "utf8");
|
|
1454
|
+
await writeFile(path.join(pastaSaida, "SEMA_BRIEF.micro.txt"), micro, "utf8");
|
|
1455
|
+
await writeFile(path.join(pastaSaida, "SEMA_BRIEF.curto.txt"), curto, "utf8");
|
|
1456
|
+
await writeFile(path.join(pastaSaida, "SEMA_INDEX.json"), `${JSON.stringify(indexJson, null, 2)}\n`, "utf8");
|
|
1457
|
+
return {
|
|
1458
|
+
geradoEm,
|
|
1459
|
+
baseProjeto,
|
|
1460
|
+
pastaSaida,
|
|
1461
|
+
artefatos: ["SEMA_BRIEF.md", "SEMA_BRIEF.micro.txt", "SEMA_BRIEF.curto.txt", "SEMA_INDEX.json"],
|
|
1462
|
+
modulos,
|
|
1463
|
+
guiaPorCapacidade,
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
|
|
1467
|
+
const contexto = await carregarContextoModuloIa(arquivoEntrada);
|
|
1468
|
+
const pastaBase = pastaSaidaOpcional
|
|
1469
|
+
? path.resolve(pastaSaidaOpcional)
|
|
1470
|
+
: path.resolve(process.cwd(), ".tmp", "contexto-ia", path.basename(contexto.arquivo, ".sema"));
|
|
1471
|
+
await mkdir(pastaBase, { recursive: true });
|
|
1472
|
+
await writeFile(path.join(pastaBase, "validar.json"), `${JSON.stringify(contexto.validar, null, 2)}\n`, "utf8");
|
|
1473
|
+
await writeFile(path.join(pastaBase, "diagnosticos.json"), `${JSON.stringify(contexto.diagnosticosJson, null, 2)}\n`, "utf8");
|
|
1474
|
+
await writeFile(path.join(pastaBase, "ast.json"), `${JSON.stringify(contexto.ast, null, 2)}\n`, "utf8");
|
|
1475
|
+
await writeFile(path.join(pastaBase, "ir.json"), `${JSON.stringify(contexto.irJson, null, 2)}\n`, "utf8");
|
|
1476
|
+
await writeFile(path.join(pastaBase, "drift.json"), `${JSON.stringify(contexto.drift, null, 2)}\n`, "utf8");
|
|
1477
|
+
await writeFile(path.join(pastaBase, "briefing.json"), `${JSON.stringify(contexto.briefing, null, 2)}\n`, "utf8");
|
|
1478
|
+
const resumoGerado = await gerarArquivosResumoModuloIa(contexto, pastaBase);
|
|
1479
|
+
const resumo = `# Contexto de IA para ${contexto.modulo}
|
|
1480
|
+
|
|
1481
|
+
- Arquivo alvo: \`${contexto.arquivo}\`
|
|
1482
|
+
- Modulo: \`${contexto.modulo}\`
|
|
1483
|
+
- Sucesso em validar: \`${contexto.sucesso}\`
|
|
1484
|
+
- Quantidade de diagnosticos: \`${contexto.diagnosticos.length}\`
|
|
1485
|
+
- Gerado em: \`${contexto.geradoEm}\`
|
|
844
1486
|
|
|
845
1487
|
## Arquivos gerados neste pacote
|
|
846
1488
|
|
|
1489
|
+
- \`resumo.micro.txt\`
|
|
1490
|
+
- \`resumo.curto.txt\`
|
|
1491
|
+
- \`resumo.md\`
|
|
1492
|
+
- \`briefing.min.json\`
|
|
1493
|
+
- \`prompt-curto.txt\`
|
|
847
1494
|
- \`validar.json\`
|
|
848
1495
|
- \`diagnosticos.json\`
|
|
849
1496
|
- \`ast.json\`
|
|
@@ -853,28 +1500,61 @@ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
|
|
|
853
1500
|
|
|
854
1501
|
## Fluxo recomendado para o agente
|
|
855
1502
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1503
|
+
### IA pequena ou gratuita
|
|
1504
|
+
|
|
1505
|
+
1. Ler \`resumo.micro.txt\`.
|
|
1506
|
+
2. Ler \`briefing.min.json\`.
|
|
1507
|
+
3. Se ainda couber contexto, ler \`resumo.curto.txt\`.
|
|
1508
|
+
|
|
1509
|
+
### IA media
|
|
1510
|
+
|
|
1511
|
+
1. Ler \`resumo.curto.txt\`.
|
|
1512
|
+
2. Ler \`briefing.min.json\`.
|
|
1513
|
+
3. Ler \`drift.json\`.
|
|
1514
|
+
4. Se precisar, subir para \`resumo.md\`.
|
|
1515
|
+
|
|
1516
|
+
### IA grande ou com tool use
|
|
1517
|
+
|
|
1518
|
+
1. Ler \`README.md\`.
|
|
1519
|
+
2. Ler \`resumo.md\`.
|
|
1520
|
+
3. Ler \`briefing.json\`.
|
|
1521
|
+
4. Ler \`drift.json\`.
|
|
1522
|
+
5. So depois abrir \`ir.json\` e \`ast.json\`.
|
|
1523
|
+
|
|
1524
|
+
## Fechamento
|
|
1525
|
+
|
|
1526
|
+
1. Editar o arquivo \`.sema\`.
|
|
1527
|
+
2. Rodar \`sema formatar "${contexto.arquivo}"\`.
|
|
1528
|
+
3. Rodar \`sema validar "${contexto.arquivo}" --json\`.
|
|
1529
|
+
4. Rodar \`sema drift "${contexto.arquivo}" --json\`.
|
|
1530
|
+
5. Fechar com \`sema verificar <arquivo-ou-pasta> --json --saida ./.tmp/verificacao-ia\`.
|
|
865
1531
|
|
|
866
1532
|
## Textos base para onboarding do agente
|
|
867
1533
|
|
|
868
1534
|
- \`sema starter-ia\`
|
|
1535
|
+
- \`sema resumo "${contexto.arquivo}" --micro --para onboarding\`
|
|
1536
|
+
- \`sema prompt-curto "${contexto.arquivo}" --para mudanca\`
|
|
869
1537
|
- \`sema prompt-ia\`
|
|
870
1538
|
`;
|
|
871
1539
|
await writeFile(path.join(pastaBase, "README.md"), resumo, "utf8");
|
|
872
1540
|
return {
|
|
873
|
-
sucesso:
|
|
874
|
-
arquivo,
|
|
875
|
-
modulo,
|
|
1541
|
+
sucesso: contexto.sucesso,
|
|
1542
|
+
arquivo: contexto.arquivo,
|
|
1543
|
+
modulo: contexto.modulo,
|
|
876
1544
|
pastaSaida: pastaBase,
|
|
877
|
-
artefatos: [
|
|
1545
|
+
artefatos: [
|
|
1546
|
+
"validar.json",
|
|
1547
|
+
"diagnosticos.json",
|
|
1548
|
+
"ast.json",
|
|
1549
|
+
"ir.json",
|
|
1550
|
+
"drift.json",
|
|
1551
|
+
"briefing.json",
|
|
1552
|
+
"README.md",
|
|
1553
|
+
...resumoGerado.artefatosCompactos,
|
|
1554
|
+
],
|
|
1555
|
+
artefatosCompactos: resumoGerado.artefatosCompactos,
|
|
1556
|
+
geradoEm: contexto.geradoEm,
|
|
1557
|
+
guiaPorCapacidade: resumoGerado.guiaPorCapacidade,
|
|
878
1558
|
};
|
|
879
1559
|
}
|
|
880
1560
|
async function comandoIniciar(cwd, template) {
|
|
@@ -1044,6 +1724,596 @@ async function comandoIniciar(cwd, template) {
|
|
|
1044
1724
|
- Contratos em \`contratos/\`
|
|
1045
1725
|
- Handlers App Router em \`src/app/api/\`
|
|
1046
1726
|
- Rota de exemplo validada por \`drift\`
|
|
1727
|
+
`,
|
|
1728
|
+
},
|
|
1729
|
+
];
|
|
1730
|
+
}
|
|
1731
|
+
else if (template === "nextjs-consumer") {
|
|
1732
|
+
arquivos = [
|
|
1733
|
+
{
|
|
1734
|
+
caminhoRelativo: "sema.config.json",
|
|
1735
|
+
conteudo: `{
|
|
1736
|
+
"origens": ["./contratos"],
|
|
1737
|
+
"saida": "./generated",
|
|
1738
|
+
"alvos": ["typescript"],
|
|
1739
|
+
"alvoPadrao": "typescript",
|
|
1740
|
+
"estruturaSaida": "modulos",
|
|
1741
|
+
"framework": "base",
|
|
1742
|
+
"modoEstrito": true,
|
|
1743
|
+
"diretoriosCodigo": ["./src"],
|
|
1744
|
+
"fontesLegado": ["nextjs-consumer", "typescript"],
|
|
1745
|
+
"diretoriosSaidaPorAlvo": {
|
|
1746
|
+
"typescript": "./generated/typescript"
|
|
1747
|
+
},
|
|
1748
|
+
"convencoesGeracaoPorProjeto": "base"
|
|
1749
|
+
}
|
|
1750
|
+
`,
|
|
1751
|
+
},
|
|
1752
|
+
{
|
|
1753
|
+
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
1754
|
+
conteudo: `module showroom.consumer {
|
|
1755
|
+
task fetch_showroom_ranking {
|
|
1756
|
+
input {
|
|
1757
|
+
}
|
|
1758
|
+
output {
|
|
1759
|
+
ranking: Json
|
|
1760
|
+
}
|
|
1761
|
+
impl {
|
|
1762
|
+
ts: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
1763
|
+
}
|
|
1764
|
+
vinculos {
|
|
1765
|
+
arquivo: "src/lib/sema_consumer_bridge.ts"
|
|
1766
|
+
simbolo: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
1767
|
+
superficie: "/ranking"
|
|
1768
|
+
arquivo: "src/app/ranking/page.tsx"
|
|
1769
|
+
arquivo: "src/app/ranking/loading.tsx"
|
|
1770
|
+
arquivo: "src/app/ranking/error.tsx"
|
|
1771
|
+
}
|
|
1772
|
+
guarantees {
|
|
1773
|
+
ranking existe
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
`,
|
|
1778
|
+
},
|
|
1779
|
+
{
|
|
1780
|
+
caminhoRelativo: "src/lib/sema_consumer_bridge.ts",
|
|
1781
|
+
conteudo: `export async function semaFetchShowroomRanking() {
|
|
1782
|
+
return {
|
|
1783
|
+
ranking: [
|
|
1784
|
+
{ clube: "Tigres do Norte", pontos: 33 },
|
|
1785
|
+
{ clube: "Porto Azul", pontos: 31 },
|
|
1786
|
+
{ clube: "Galo de Ouro", pontos: 28 },
|
|
1787
|
+
],
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
`,
|
|
1791
|
+
},
|
|
1792
|
+
{
|
|
1793
|
+
caminhoRelativo: "src/app/ranking/page.tsx",
|
|
1794
|
+
conteudo: `import { semaFetchShowroomRanking } from "../../lib/sema_consumer_bridge";
|
|
1795
|
+
|
|
1796
|
+
export default async function RankingPage() {
|
|
1797
|
+
const { ranking } = await semaFetchShowroomRanking();
|
|
1798
|
+
|
|
1799
|
+
return (
|
|
1800
|
+
<main>
|
|
1801
|
+
<h1>Ranking showroom</h1>
|
|
1802
|
+
<ul>
|
|
1803
|
+
{ranking.map((item) => (
|
|
1804
|
+
<li key={item.clube}>
|
|
1805
|
+
{item.clube} - {item.pontos} pts
|
|
1806
|
+
</li>
|
|
1807
|
+
))}
|
|
1808
|
+
</ul>
|
|
1809
|
+
</main>
|
|
1810
|
+
);
|
|
1811
|
+
}
|
|
1812
|
+
`,
|
|
1813
|
+
},
|
|
1814
|
+
{
|
|
1815
|
+
caminhoRelativo: "src/app/ranking/loading.tsx",
|
|
1816
|
+
conteudo: `export default function Loading() {
|
|
1817
|
+
return <p>Carregando ranking...</p>;
|
|
1818
|
+
}
|
|
1819
|
+
`,
|
|
1820
|
+
},
|
|
1821
|
+
{
|
|
1822
|
+
caminhoRelativo: "src/app/ranking/error.tsx",
|
|
1823
|
+
conteudo: `"use client";
|
|
1824
|
+
|
|
1825
|
+
export default function Error({
|
|
1826
|
+
error,
|
|
1827
|
+
reset,
|
|
1828
|
+
}: {
|
|
1829
|
+
error: Error;
|
|
1830
|
+
reset: () => void;
|
|
1831
|
+
}) {
|
|
1832
|
+
return (
|
|
1833
|
+
<main>
|
|
1834
|
+
<h1>Falha ao carregar ranking</h1>
|
|
1835
|
+
<p>{error.message}</p>
|
|
1836
|
+
<button type="button" onClick={reset}>Tentar novamente</button>
|
|
1837
|
+
</main>
|
|
1838
|
+
);
|
|
1839
|
+
}
|
|
1840
|
+
`,
|
|
1841
|
+
},
|
|
1842
|
+
{
|
|
1843
|
+
caminhoRelativo: "README.md",
|
|
1844
|
+
conteudo: `# Starter Next.js Consumer + Sema
|
|
1845
|
+
|
|
1846
|
+
- Contratos em \`contratos/\`
|
|
1847
|
+
- Bridge consumer canonico em \`src/lib/sema_consumer_bridge.ts\`
|
|
1848
|
+
- Superficies App Router em \`src/app/\`
|
|
1849
|
+
- O slice oficial desta fase e \`consumer bridge + App Router surfaces\`
|
|
1850
|
+
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual drift
|
|
1851
|
+
`,
|
|
1852
|
+
},
|
|
1853
|
+
];
|
|
1854
|
+
}
|
|
1855
|
+
else if (template === "react-vite-consumer") {
|
|
1856
|
+
arquivos = [
|
|
1857
|
+
{
|
|
1858
|
+
caminhoRelativo: "sema.config.json",
|
|
1859
|
+
conteudo: `{
|
|
1860
|
+
"origens": ["./contratos"],
|
|
1861
|
+
"saida": "./generated",
|
|
1862
|
+
"alvos": ["typescript"],
|
|
1863
|
+
"alvoPadrao": "typescript",
|
|
1864
|
+
"estruturaSaida": "modulos",
|
|
1865
|
+
"framework": "base",
|
|
1866
|
+
"modoEstrito": true,
|
|
1867
|
+
"diretoriosCodigo": ["./src"],
|
|
1868
|
+
"fontesLegado": ["react-vite-consumer", "typescript"],
|
|
1869
|
+
"diretoriosSaidaPorAlvo": {
|
|
1870
|
+
"typescript": "./generated/typescript"
|
|
1871
|
+
},
|
|
1872
|
+
"convencoesGeracaoPorProjeto": "base"
|
|
1873
|
+
}
|
|
1874
|
+
`,
|
|
1875
|
+
},
|
|
1876
|
+
{
|
|
1877
|
+
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
1878
|
+
conteudo: `module showroom.consumer {
|
|
1879
|
+
task fetch_showroom_ranking {
|
|
1880
|
+
input {
|
|
1881
|
+
}
|
|
1882
|
+
output {
|
|
1883
|
+
ranking: Json
|
|
1884
|
+
}
|
|
1885
|
+
impl {
|
|
1886
|
+
ts: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
1887
|
+
}
|
|
1888
|
+
vinculos {
|
|
1889
|
+
arquivo: "src/lib/sema_consumer_bridge.ts"
|
|
1890
|
+
simbolo: src.lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
1891
|
+
superficie: "/ranking"
|
|
1892
|
+
arquivo: "src/router.tsx"
|
|
1893
|
+
arquivo: "src/pages/ranking.tsx"
|
|
1894
|
+
}
|
|
1895
|
+
guarantees {
|
|
1896
|
+
ranking existe
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
`,
|
|
1901
|
+
},
|
|
1902
|
+
{
|
|
1903
|
+
caminhoRelativo: "src/lib/sema_consumer_bridge.ts",
|
|
1904
|
+
conteudo: `export async function semaFetchShowroomRanking() {
|
|
1905
|
+
return {
|
|
1906
|
+
ranking: [
|
|
1907
|
+
{ clube: "Tigres do Norte", pontos: 33 },
|
|
1908
|
+
{ clube: "Porto Azul", pontos: 31 },
|
|
1909
|
+
{ clube: "Galo de Ouro", pontos: 28 },
|
|
1910
|
+
],
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
`,
|
|
1914
|
+
},
|
|
1915
|
+
{
|
|
1916
|
+
caminhoRelativo: "src/pages/ranking.tsx",
|
|
1917
|
+
conteudo: `import { useEffect, useState } from "react";
|
|
1918
|
+
import { semaFetchShowroomRanking } from "../lib/sema_consumer_bridge";
|
|
1919
|
+
|
|
1920
|
+
export function RankingPage() {
|
|
1921
|
+
const [ranking, setRanking] = useState<Array<{ clube: string; pontos: number }>>([]);
|
|
1922
|
+
|
|
1923
|
+
useEffect(() => {
|
|
1924
|
+
void semaFetchShowroomRanking().then((payload) => setRanking(payload.ranking ?? []));
|
|
1925
|
+
}, []);
|
|
1926
|
+
|
|
1927
|
+
return (
|
|
1928
|
+
<main>
|
|
1929
|
+
<h1>Ranking showroom</h1>
|
|
1930
|
+
<ul>
|
|
1931
|
+
{ranking.map((item) => (
|
|
1932
|
+
<li key={item.clube}>
|
|
1933
|
+
{item.clube} - {item.pontos} pts
|
|
1934
|
+
</li>
|
|
1935
|
+
))}
|
|
1936
|
+
</ul>
|
|
1937
|
+
</main>
|
|
1938
|
+
);
|
|
1939
|
+
}
|
|
1940
|
+
`,
|
|
1941
|
+
},
|
|
1942
|
+
{
|
|
1943
|
+
caminhoRelativo: "src/router.tsx",
|
|
1944
|
+
conteudo: `import { createBrowserRouter } from "react-router-dom";
|
|
1945
|
+
import { RankingPage } from "./pages/ranking";
|
|
1946
|
+
|
|
1947
|
+
export const appRouter = createBrowserRouter([
|
|
1948
|
+
{
|
|
1949
|
+
path: "/ranking",
|
|
1950
|
+
Component: RankingPage,
|
|
1951
|
+
},
|
|
1952
|
+
]);
|
|
1953
|
+
`,
|
|
1954
|
+
},
|
|
1955
|
+
{
|
|
1956
|
+
caminhoRelativo: "src/App.tsx",
|
|
1957
|
+
conteudo: `import { RouterProvider } from "react-router-dom";
|
|
1958
|
+
import { appRouter } from "./router";
|
|
1959
|
+
|
|
1960
|
+
export default function App() {
|
|
1961
|
+
return <RouterProvider router={appRouter} />;
|
|
1962
|
+
}
|
|
1963
|
+
`,
|
|
1964
|
+
},
|
|
1965
|
+
{
|
|
1966
|
+
caminhoRelativo: "src/main.tsx",
|
|
1967
|
+
conteudo: `import React from "react";
|
|
1968
|
+
import ReactDOM from "react-dom/client";
|
|
1969
|
+
import App from "./App";
|
|
1970
|
+
|
|
1971
|
+
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
|
1972
|
+
<React.StrictMode>
|
|
1973
|
+
<App />
|
|
1974
|
+
</React.StrictMode>,
|
|
1975
|
+
);
|
|
1976
|
+
`,
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
caminhoRelativo: "README.md",
|
|
1980
|
+
conteudo: `# Starter React Vite Consumer + Sema
|
|
1981
|
+
|
|
1982
|
+
- Contratos em \`contratos/\`
|
|
1983
|
+
- Bridge consumer canonico em \`src/lib/sema_consumer_bridge.ts\`
|
|
1984
|
+
- Rotas explicitas em \`src/router.tsx\`
|
|
1985
|
+
- Superficies consumer em \`src/pages/\`
|
|
1986
|
+
- O slice oficial desta fase e \`consumer bridge + react-router surfaces\`
|
|
1987
|
+
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual drift
|
|
1988
|
+
`,
|
|
1989
|
+
},
|
|
1990
|
+
];
|
|
1991
|
+
}
|
|
1992
|
+
else if (template === "angular-consumer") {
|
|
1993
|
+
arquivos = [
|
|
1994
|
+
{
|
|
1995
|
+
caminhoRelativo: "sema.config.json",
|
|
1996
|
+
conteudo: `{
|
|
1997
|
+
"origens": ["./contratos"],
|
|
1998
|
+
"saida": "./generated",
|
|
1999
|
+
"alvos": ["typescript"],
|
|
2000
|
+
"alvoPadrao": "typescript",
|
|
2001
|
+
"estruturaSaida": "modulos",
|
|
2002
|
+
"framework": "base",
|
|
2003
|
+
"modoEstrito": true,
|
|
2004
|
+
"diretoriosCodigo": ["./src"],
|
|
2005
|
+
"fontesLegado": ["angular-consumer", "typescript"],
|
|
2006
|
+
"diretoriosSaidaPorAlvo": {
|
|
2007
|
+
"typescript": "./generated/typescript"
|
|
2008
|
+
},
|
|
2009
|
+
"convencoesGeracaoPorProjeto": "base"
|
|
2010
|
+
}
|
|
2011
|
+
`,
|
|
2012
|
+
},
|
|
2013
|
+
{
|
|
2014
|
+
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
2015
|
+
conteudo: `module showroom.consumer {
|
|
2016
|
+
task fetch_showroom_ranking {
|
|
2017
|
+
input {
|
|
2018
|
+
}
|
|
2019
|
+
output {
|
|
2020
|
+
ranking: Json
|
|
2021
|
+
}
|
|
2022
|
+
impl {
|
|
2023
|
+
ts: src.app.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2024
|
+
}
|
|
2025
|
+
vinculos {
|
|
2026
|
+
arquivo: "src/app/sema_consumer_bridge.ts"
|
|
2027
|
+
simbolo: src.app.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2028
|
+
superficie: "/ranking"
|
|
2029
|
+
arquivo: "src/app/app.routes.ts"
|
|
2030
|
+
arquivo: "src/app/features/ranking/ranking.routes.ts"
|
|
2031
|
+
arquivo: "src/app/features/ranking/ranking-page.component.ts"
|
|
2032
|
+
}
|
|
2033
|
+
guarantees {
|
|
2034
|
+
ranking existe
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
`,
|
|
2039
|
+
},
|
|
2040
|
+
{
|
|
2041
|
+
caminhoRelativo: "src/app/sema_consumer_bridge.ts",
|
|
2042
|
+
conteudo: `export async function semaFetchShowroomRanking() {
|
|
2043
|
+
return {
|
|
2044
|
+
ranking: [
|
|
2045
|
+
{ clube: "Tigres do Norte", pontos: 33 },
|
|
2046
|
+
{ clube: "Porto Azul", pontos: 31 },
|
|
2047
|
+
{ clube: "Galo de Ouro", pontos: 28 },
|
|
2048
|
+
],
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
`,
|
|
2052
|
+
},
|
|
2053
|
+
{
|
|
2054
|
+
caminhoRelativo: "src/app/app.routes.ts",
|
|
2055
|
+
conteudo: `import { Routes } from "@angular/router";
|
|
2056
|
+
|
|
2057
|
+
export const routes: Routes = [
|
|
2058
|
+
{
|
|
2059
|
+
path: "ranking",
|
|
2060
|
+
loadChildren: () => import("./features/ranking/ranking.routes").then((m) => m.RANKING_ROUTES),
|
|
2061
|
+
},
|
|
2062
|
+
];
|
|
2063
|
+
`,
|
|
2064
|
+
},
|
|
2065
|
+
{
|
|
2066
|
+
caminhoRelativo: "src/app/features/ranking/ranking.routes.ts",
|
|
2067
|
+
conteudo: `import { Routes } from "@angular/router";
|
|
2068
|
+
|
|
2069
|
+
export const RANKING_ROUTES: Routes = [
|
|
2070
|
+
{
|
|
2071
|
+
path: "",
|
|
2072
|
+
loadComponent: () => import("./ranking-page.component").then((m) => m.RankingPageComponent),
|
|
2073
|
+
},
|
|
2074
|
+
];
|
|
2075
|
+
`,
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
caminhoRelativo: "src/app/features/ranking/ranking-page.component.ts",
|
|
2079
|
+
conteudo: `import { Component, OnInit } from "@angular/core";
|
|
2080
|
+
import { CommonModule } from "@angular/common";
|
|
2081
|
+
import { semaFetchShowroomRanking } from "../../sema_consumer_bridge";
|
|
2082
|
+
|
|
2083
|
+
@Component({
|
|
2084
|
+
selector: "app-ranking-page",
|
|
2085
|
+
standalone: true,
|
|
2086
|
+
imports: [CommonModule],
|
|
2087
|
+
template: \`
|
|
2088
|
+
<main>
|
|
2089
|
+
<h1>Ranking showroom</h1>
|
|
2090
|
+
<ul>
|
|
2091
|
+
<li *ngFor="let item of ranking">
|
|
2092
|
+
{{ item.clube }} - {{ item.pontos }} pts
|
|
2093
|
+
</li>
|
|
2094
|
+
</ul>
|
|
2095
|
+
</main>
|
|
2096
|
+
\`,
|
|
2097
|
+
})
|
|
2098
|
+
export class RankingPageComponent implements OnInit {
|
|
2099
|
+
ranking: Array<{ clube: string; pontos: number }> = [];
|
|
2100
|
+
|
|
2101
|
+
async ngOnInit() {
|
|
2102
|
+
const payload = await semaFetchShowroomRanking();
|
|
2103
|
+
this.ranking = payload.ranking ?? [];
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
`,
|
|
2107
|
+
},
|
|
2108
|
+
{
|
|
2109
|
+
caminhoRelativo: "src/app/app.component.ts",
|
|
2110
|
+
conteudo: `import { Component } from "@angular/core";
|
|
2111
|
+
import { RouterOutlet } from "@angular/router";
|
|
2112
|
+
|
|
2113
|
+
@Component({
|
|
2114
|
+
selector: "app-root",
|
|
2115
|
+
standalone: true,
|
|
2116
|
+
imports: [RouterOutlet],
|
|
2117
|
+
template: "<router-outlet />",
|
|
2118
|
+
})
|
|
2119
|
+
export class AppComponent {}
|
|
2120
|
+
`,
|
|
2121
|
+
},
|
|
2122
|
+
{
|
|
2123
|
+
caminhoRelativo: "src/main.ts",
|
|
2124
|
+
conteudo: `import { bootstrapApplication } from "@angular/platform-browser";
|
|
2125
|
+
import { provideRouter } from "@angular/router";
|
|
2126
|
+
import { AppComponent } from "./app/app.component";
|
|
2127
|
+
import { routes } from "./app/app.routes";
|
|
2128
|
+
|
|
2129
|
+
void bootstrapApplication(AppComponent, {
|
|
2130
|
+
providers: [provideRouter(routes)],
|
|
2131
|
+
});
|
|
2132
|
+
`,
|
|
2133
|
+
},
|
|
2134
|
+
{
|
|
2135
|
+
caminhoRelativo: "README.md",
|
|
2136
|
+
conteudo: `# Starter Angular Consumer + Sema
|
|
2137
|
+
|
|
2138
|
+
- Contratos em \`contratos/\`
|
|
2139
|
+
- Bridge consumer canonico em \`src/app/sema_consumer_bridge.ts\`
|
|
2140
|
+
- Rotas lazy em \`src/app/app.routes.ts\`
|
|
2141
|
+
- Feature folders em \`src/app/features/\`
|
|
2142
|
+
- O slice oficial desta fase e \`consumer bridge + route config surfaces\`
|
|
2143
|
+
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual drift
|
|
2144
|
+
`,
|
|
2145
|
+
},
|
|
2146
|
+
];
|
|
2147
|
+
}
|
|
2148
|
+
else if (template === "flutter-consumer") {
|
|
2149
|
+
arquivos = [
|
|
2150
|
+
{
|
|
2151
|
+
caminhoRelativo: "sema.config.json",
|
|
2152
|
+
conteudo: `{
|
|
2153
|
+
"origens": ["./contratos"],
|
|
2154
|
+
"saida": "./generated",
|
|
2155
|
+
"alvos": ["dart"],
|
|
2156
|
+
"alvoPadrao": "dart",
|
|
2157
|
+
"estruturaSaida": "modulos",
|
|
2158
|
+
"framework": "base",
|
|
2159
|
+
"modoEstrito": true,
|
|
2160
|
+
"diretoriosCodigo": ["./lib"],
|
|
2161
|
+
"fontesLegado": ["flutter-consumer", "dart"],
|
|
2162
|
+
"diretoriosSaidaPorAlvo": {
|
|
2163
|
+
"dart": "./generated/dart"
|
|
2164
|
+
},
|
|
2165
|
+
"convencoesGeracaoPorProjeto": "base"
|
|
2166
|
+
}
|
|
2167
|
+
`,
|
|
2168
|
+
},
|
|
2169
|
+
{
|
|
2170
|
+
caminhoRelativo: "pubspec.yaml",
|
|
2171
|
+
conteudo: `name: sema_flutter_consumer
|
|
2172
|
+
description: Starter Flutter consumer IA-first com Sema
|
|
2173
|
+
publish_to: "none"
|
|
2174
|
+
|
|
2175
|
+
environment:
|
|
2176
|
+
sdk: ">=3.3.0 <4.0.0"
|
|
2177
|
+
|
|
2178
|
+
dependencies:
|
|
2179
|
+
flutter:
|
|
2180
|
+
sdk: flutter
|
|
2181
|
+
go_router: ^14.0.0
|
|
2182
|
+
`,
|
|
2183
|
+
},
|
|
2184
|
+
{
|
|
2185
|
+
caminhoRelativo: "contratos/showroom_consumer.sema",
|
|
2186
|
+
conteudo: `module showroom.consumer {
|
|
2187
|
+
task fetch_showroom_ranking {
|
|
2188
|
+
input {
|
|
2189
|
+
}
|
|
2190
|
+
output {
|
|
2191
|
+
resultado: Json
|
|
2192
|
+
}
|
|
2193
|
+
impl {
|
|
2194
|
+
dart: lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2195
|
+
}
|
|
2196
|
+
vinculos {
|
|
2197
|
+
arquivo: "lib/sema_consumer_bridge.dart"
|
|
2198
|
+
simbolo: lib.sema_consumer_bridge.semaFetchShowroomRanking
|
|
2199
|
+
superficie: "/ranking"
|
|
2200
|
+
arquivo: "lib/router.dart"
|
|
2201
|
+
arquivo: "lib/screens/ranking_screen.dart"
|
|
2202
|
+
}
|
|
2203
|
+
guarantees {
|
|
2204
|
+
resultado existe
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
`,
|
|
2209
|
+
},
|
|
2210
|
+
{
|
|
2211
|
+
caminhoRelativo: "lib/sema_consumer_bridge.dart",
|
|
2212
|
+
conteudo: `Future<Map<String, dynamic>> semaFetchShowroomRanking() async {
|
|
2213
|
+
return {
|
|
2214
|
+
"ranking": [
|
|
2215
|
+
{"clube": "Tigres do Norte", "pontos": 33},
|
|
2216
|
+
{"clube": "Porto Azul", "pontos": 31},
|
|
2217
|
+
{"clube": "Galo de Ouro", "pontos": 28},
|
|
2218
|
+
],
|
|
2219
|
+
};
|
|
2220
|
+
}
|
|
2221
|
+
`,
|
|
2222
|
+
},
|
|
2223
|
+
{
|
|
2224
|
+
caminhoRelativo: "lib/router.dart",
|
|
2225
|
+
conteudo: `import "package:go_router/go_router.dart";
|
|
2226
|
+
import "package:flutter/widgets.dart";
|
|
2227
|
+
import "screens/ranking_screen.dart";
|
|
2228
|
+
|
|
2229
|
+
final appRouter = GoRouter(
|
|
2230
|
+
routes: [
|
|
2231
|
+
GoRoute(
|
|
2232
|
+
path: "/ranking",
|
|
2233
|
+
builder: (BuildContext context, GoRouterState state) => const RankingScreen(),
|
|
2234
|
+
),
|
|
2235
|
+
],
|
|
2236
|
+
);
|
|
2237
|
+
`,
|
|
2238
|
+
},
|
|
2239
|
+
{
|
|
2240
|
+
caminhoRelativo: "lib/screens/ranking_screen.dart",
|
|
2241
|
+
conteudo: `import "package:flutter/widgets.dart";
|
|
2242
|
+
import "../sema_consumer_bridge.dart";
|
|
2243
|
+
|
|
2244
|
+
class RankingScreen extends StatefulWidget {
|
|
2245
|
+
const RankingScreen({super.key});
|
|
2246
|
+
|
|
2247
|
+
@override
|
|
2248
|
+
State<RankingScreen> createState() => _RankingScreenState();
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
class _RankingScreenState extends State<RankingScreen> {
|
|
2252
|
+
List<Map<String, dynamic>> ranking = const [];
|
|
2253
|
+
|
|
2254
|
+
@override
|
|
2255
|
+
void initState() {
|
|
2256
|
+
super.initState();
|
|
2257
|
+
semaFetchShowroomRanking().then((payload) {
|
|
2258
|
+
final itens = (payload["ranking"] as List<dynamic>? ?? const [])
|
|
2259
|
+
.whereType<Map<String, dynamic>>()
|
|
2260
|
+
.toList();
|
|
2261
|
+
if (!mounted) return;
|
|
2262
|
+
setState(() {
|
|
2263
|
+
ranking = itens;
|
|
2264
|
+
});
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
@override
|
|
2269
|
+
Widget build(BuildContext context) {
|
|
2270
|
+
return ListView(
|
|
2271
|
+
children: [
|
|
2272
|
+
const Padding(
|
|
2273
|
+
padding: EdgeInsets.all(16),
|
|
2274
|
+
child: Text("Ranking showroom"),
|
|
2275
|
+
),
|
|
2276
|
+
...ranking.map((item) => Padding(
|
|
2277
|
+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
2278
|
+
child: Text("\${item["clube"]} - \${item["pontos"]} pts"),
|
|
2279
|
+
)),
|
|
2280
|
+
],
|
|
2281
|
+
);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
`,
|
|
2285
|
+
},
|
|
2286
|
+
{
|
|
2287
|
+
caminhoRelativo: "lib/main.dart",
|
|
2288
|
+
conteudo: `import "package:flutter/material.dart";
|
|
2289
|
+
import "router.dart";
|
|
2290
|
+
|
|
2291
|
+
void main() {
|
|
2292
|
+
runApp(const ShowroomApp());
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
class ShowroomApp extends StatelessWidget {
|
|
2296
|
+
const ShowroomApp({super.key});
|
|
2297
|
+
|
|
2298
|
+
@override
|
|
2299
|
+
Widget build(BuildContext context) {
|
|
2300
|
+
return MaterialApp.router(
|
|
2301
|
+
routerConfig: appRouter,
|
|
2302
|
+
);
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
`,
|
|
2306
|
+
},
|
|
2307
|
+
{
|
|
2308
|
+
caminhoRelativo: "README.md",
|
|
2309
|
+
conteudo: `# Starter Flutter Consumer + Sema
|
|
2310
|
+
|
|
2311
|
+
- Contratos em \`contratos/\`
|
|
2312
|
+
- Bridge consumer canonico em \`lib/sema_consumer_bridge.dart\`
|
|
2313
|
+
- Rotas consumer em \`lib/router.dart\`
|
|
2314
|
+
- Superficies consumer em \`lib/screens/\`
|
|
2315
|
+
- O slice oficial desta fase e \`consumer bridge + router/screen surfaces\`
|
|
2316
|
+
- \`drift\` valida \`impl\`, \`vinculos\`, bridge e superficies, sem prometer visual diff
|
|
1047
2317
|
`,
|
|
1048
2318
|
},
|
|
1049
2319
|
];
|
|
@@ -1602,6 +2872,10 @@ async function comandoInspecionar(entrada, emJson, cwd = process.cwd()) {
|
|
|
1602
2872
|
modoAdocao: contextoProjeto.modoAdocao,
|
|
1603
2873
|
scoreDrift: resultadoDrift.resumo_operacional.scoreMedio,
|
|
1604
2874
|
confiancaGeral: resultadoDrift.resumo_operacional.confiancaGeral,
|
|
2875
|
+
consumerFramework: resultadoDrift.consumerFramework,
|
|
2876
|
+
appRoutes: resultadoDrift.appRoutes,
|
|
2877
|
+
consumerSurfaces: resultadoDrift.consumerSurfaces,
|
|
2878
|
+
consumerBridges: resultadoDrift.consumerBridges,
|
|
1605
2879
|
},
|
|
1606
2880
|
projeto: {
|
|
1607
2881
|
arquivos: contextoProjeto.arquivosProjeto,
|
|
@@ -1936,44 +3210,80 @@ async function comandoStarterIa() {
|
|
|
1936
3210
|
console.log(STARTER_IA);
|
|
1937
3211
|
return 0;
|
|
1938
3212
|
}
|
|
3213
|
+
async function comandoSyncAiEntrypoints(emJson) {
|
|
3214
|
+
const resumoProjeto = await gerarResumoProjetoIa(process.cwd(), undefined, true);
|
|
3215
|
+
const indexJson = JSON.parse(await readFile(path.join(resumoProjeto.pastaSaida, "SEMA_INDEX.json"), "utf8"));
|
|
3216
|
+
const artefatos = [...new Set([
|
|
3217
|
+
...ARQUIVOS_CANONICOS_IA_RAIZ,
|
|
3218
|
+
...resumoProjeto.artefatos,
|
|
3219
|
+
])];
|
|
3220
|
+
if (emJson) {
|
|
3221
|
+
console.log(JSON.stringify({
|
|
3222
|
+
comando: "sync-ai-entrypoints",
|
|
3223
|
+
sucesso: true,
|
|
3224
|
+
baseProjeto: resumoProjeto.baseProjeto,
|
|
3225
|
+
pastaSaida: resumoProjeto.pastaSaida,
|
|
3226
|
+
artefatos,
|
|
3227
|
+
entradaCanonica: indexJson.entradaCanonica,
|
|
3228
|
+
}, null, 2));
|
|
3229
|
+
return 0;
|
|
3230
|
+
}
|
|
3231
|
+
console.log("Entrypoints IA-first sincronizados");
|
|
3232
|
+
console.log("");
|
|
3233
|
+
console.log(`Base do projeto: ${resumoProjeto.baseProjeto}`);
|
|
3234
|
+
console.log(`Ordem canonica: ${indexJson.entradaCanonica.ordemLeitura.join(" -> ")}`);
|
|
3235
|
+
console.log(`IA pequena: ${indexJson.entradaCanonica.porCapacidade.pequena.join(" -> ")}`);
|
|
3236
|
+
console.log(`IA media: ${indexJson.entradaCanonica.porCapacidade.media.join(" -> ")}`);
|
|
3237
|
+
console.log(`IA grande: ${indexJson.entradaCanonica.porCapacidade.grande.join(" -> ")}`);
|
|
3238
|
+
return 0;
|
|
3239
|
+
}
|
|
1939
3240
|
async function comandoAjudaIa() {
|
|
1940
3241
|
const descoberta = await descobrirDocsIa();
|
|
1941
3242
|
console.log("Ajuda de IA da Sema");
|
|
1942
3243
|
console.log("");
|
|
3244
|
+
console.log(renderizarCaixaAscii([
|
|
3245
|
+
"IA-first para greenfield, edicao guiada e legado sem contrato inicial",
|
|
3246
|
+
"use o menor artefato semantico que resolva a tarefa",
|
|
3247
|
+
]));
|
|
3248
|
+
console.log("");
|
|
1943
3249
|
console.log(renderizarCabecalhoDocsIa(descoberta));
|
|
1944
3250
|
console.log("");
|
|
1945
|
-
console.log("
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
console.log("- Usa `execucao` para explicitar timeout, retry, compensacao e criticidade.");
|
|
1951
|
-
console.log("- Usa `drift` para medir divergencia entre contrato e codigo vivo com score, confianca e lacunas.");
|
|
1952
|
-
console.log("- Usa `contexto-ia` para preparar AST, IR, diagnosticos, drift e `briefing.json` antes da edicao.");
|
|
3251
|
+
console.log(renderizarSecaoAscii("Tres jeitos de usar a Sema", [
|
|
3252
|
+
"[1] Producao inicial: modele, valide, compile e verifique antes de subir codigo derivado.",
|
|
3253
|
+
"[2] Edicao em projeto com Sema: inspecione, leia resumo, rode drift e gere contexto antes de editar codigo vivo.",
|
|
3254
|
+
"[3] Projeto sem Sema ainda: importe, revise o rascunho, formate, valide e use drift como juiz da adocao incremental.",
|
|
3255
|
+
]));
|
|
1953
3256
|
console.log("");
|
|
1954
|
-
console.log("
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
3257
|
+
console.log(renderizarSecaoAscii("Capacidade de IA", [
|
|
3258
|
+
"pequena: `sema resumo --micro`, `briefing.min.json`, `prompt-curto.txt`",
|
|
3259
|
+
"media: `sema resumo --curto`, `drift.json`, `briefing.min.json`",
|
|
3260
|
+
"grande: `sema contexto-ia`, `briefing.json`, `ir.json`, `ast.json`",
|
|
3261
|
+
]));
|
|
1958
3262
|
console.log("");
|
|
1959
|
-
console.log("Fluxo recomendado"
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
3263
|
+
console.log(renderizarSecaoAscii("Fluxo recomendado", [
|
|
3264
|
+
"Use `sema starter-ia` para um texto curto de onboarding.",
|
|
3265
|
+
"Use `sema sync-ai-entrypoints` para regenerar `SEMA_BRIEF.*` e `SEMA_INDEX.json` na raiz.",
|
|
3266
|
+
"Use `sema resumo <arquivo> --micro --para onboarding` para IA pequena.",
|
|
3267
|
+
"Use `sema prompt-curto <arquivo> --curto --para mudanca` para colar contexto em modelo gratuito.",
|
|
3268
|
+
"Use `sema prompt-ia`, `sema prompt-ia-ui`, `sema prompt-ia-react` e `sema prompt-ia-sema-primeiro` conforme a tarefa.",
|
|
3269
|
+
"Use `sema exemplos-prompt-ia` para pegar modelos prontos de prompt.",
|
|
3270
|
+
"Use `sema inspecionar` para descobrir base, codigo vivo e fontes legado.",
|
|
3271
|
+
"Use `sema drift` para medir impls, vinculos, rotas, score e lacunas.",
|
|
3272
|
+
"Use `sema contexto-ia <arquivo.sema>` para gerar AST, IR, drift, `briefing.json` e `briefing.min.json`.",
|
|
3273
|
+
"Use `sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>` quando a tarefa pedir codigo derivado.",
|
|
3274
|
+
]));
|
|
1970
3275
|
console.log("");
|
|
1971
|
-
console.log("
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
3276
|
+
console.log(renderizarSecaoAscii("Regras praticas", [
|
|
3277
|
+
"Foi feita para IA operar melhor; leitura humana e consequencia, nao centro de produto.",
|
|
3278
|
+
"Governa contrato, intencao, erro, efeito, garantia, fluxo, vinculos e execucao.",
|
|
3279
|
+
"Nao escreve contrato final sozinho nem substitui decisao arquitetural.",
|
|
3280
|
+
"Se voce quer testar a Sema de verdade, nao peca so HTML solto.",
|
|
3281
|
+
"Peca `.sema` + arquitetura + React + TypeScript, ou use o modo `Sema primeiro`.",
|
|
3282
|
+
"Se o projeto ja existe, trate `importar` como rascunho e `drift` como juiz.",
|
|
3283
|
+
"IA pequena comeca no menor artefato que resolve a tarefa; nao enfie `ast.json` inteiro nela de bobeira.",
|
|
3284
|
+
"Antes de editar software vivo, leia `briefing.min.json` ou `briefing.json` em vez de sair cavando arquivo na fe.",
|
|
3285
|
+
"Trate `route`, `worker`, `evento`, `fila`, `cron`, `webhook`, `cache`, `storage` e `policy` como superficies de primeira classe.",
|
|
3286
|
+
]));
|
|
1977
3287
|
return 0;
|
|
1978
3288
|
}
|
|
1979
3289
|
async function comandoPromptIa() {
|
|
@@ -2021,6 +3331,142 @@ async function comandoExemplosPromptIa() {
|
|
|
2021
3331
|
console.log(EXEMPLOS_PROMPT_IA);
|
|
2022
3332
|
return 0;
|
|
2023
3333
|
}
|
|
3334
|
+
async function comandoResumo(entrada, args, emJson) {
|
|
3335
|
+
const tamanho = normalizarTamanhoResumo(args);
|
|
3336
|
+
const modo = normalizarModoResumo(obterOpcao(args, "--para"));
|
|
3337
|
+
const pastaSaida = obterOpcao(args, "--saida");
|
|
3338
|
+
const escreverNaRaiz = possuiFlag(args, "--raiz");
|
|
3339
|
+
const alvo = entrada ? path.resolve(process.cwd(), entrada) : process.cwd();
|
|
3340
|
+
if (entrada && entrada.toLowerCase().endsWith(".sema")) {
|
|
3341
|
+
const contexto = await carregarContextoModuloIa(alvo);
|
|
3342
|
+
const resumoSemantico = coletarResumoSemanticoModulo(contexto);
|
|
3343
|
+
const guiaPorCapacidade = criarGuiaCapacidadeIa();
|
|
3344
|
+
const texto = tamanho === "medio"
|
|
3345
|
+
? renderizarResumoModuloMarkdown(resumoSemantico, modo, guiaPorCapacidade)
|
|
3346
|
+
: renderizarResumoModuloTexto(resumoSemantico, tamanho, modo);
|
|
3347
|
+
let pastaResumo;
|
|
3348
|
+
let artefatosCompactos = [];
|
|
3349
|
+
if (pastaSaida) {
|
|
3350
|
+
pastaResumo = path.resolve(pastaSaida);
|
|
3351
|
+
await mkdir(pastaResumo, { recursive: true });
|
|
3352
|
+
const gerado = await gerarArquivosResumoModuloIa(contexto, pastaResumo);
|
|
3353
|
+
artefatosCompactos = gerado.artefatosCompactos;
|
|
3354
|
+
}
|
|
3355
|
+
if (emJson) {
|
|
3356
|
+
console.log(JSON.stringify({
|
|
3357
|
+
comando: "resumo",
|
|
3358
|
+
modo,
|
|
3359
|
+
tamanho,
|
|
3360
|
+
geradoEm: contexto.geradoEm,
|
|
3361
|
+
arquivo: contexto.arquivo,
|
|
3362
|
+
modulo: contexto.modulo,
|
|
3363
|
+
pastaSaida: pastaResumo ?? null,
|
|
3364
|
+
artefatosCompactos,
|
|
3365
|
+
guiaPorCapacidade,
|
|
3366
|
+
resumo: resumoSemantico,
|
|
3367
|
+
texto,
|
|
3368
|
+
}, null, 2));
|
|
3369
|
+
return 0;
|
|
3370
|
+
}
|
|
3371
|
+
if (pastaResumo) {
|
|
3372
|
+
console.log(`Resumo IA-first gerado em ${pastaResumo}`);
|
|
3373
|
+
console.log("");
|
|
3374
|
+
}
|
|
3375
|
+
console.log(texto);
|
|
3376
|
+
return 0;
|
|
3377
|
+
}
|
|
3378
|
+
const resumoProjeto = await gerarResumoProjetoIa(alvo, pastaSaida, escreverNaRaiz);
|
|
3379
|
+
const arquivoResumo = tamanho === "micro"
|
|
3380
|
+
? "SEMA_BRIEF.micro.txt"
|
|
3381
|
+
: tamanho === "curto"
|
|
3382
|
+
? "SEMA_BRIEF.curto.txt"
|
|
3383
|
+
: "SEMA_BRIEF.md";
|
|
3384
|
+
const texto = await readFile(path.join(resumoProjeto.pastaSaida, arquivoResumo), "utf8");
|
|
3385
|
+
if (emJson) {
|
|
3386
|
+
console.log(JSON.stringify({
|
|
3387
|
+
comando: "resumo",
|
|
3388
|
+
modo,
|
|
3389
|
+
tamanho,
|
|
3390
|
+
geradoEm: resumoProjeto.geradoEm,
|
|
3391
|
+
baseProjeto: resumoProjeto.baseProjeto,
|
|
3392
|
+
pastaSaida: resumoProjeto.pastaSaida,
|
|
3393
|
+
artefatos: resumoProjeto.artefatos,
|
|
3394
|
+
guiaPorCapacidade: resumoProjeto.guiaPorCapacidade,
|
|
3395
|
+
modulos: resumoProjeto.modulos,
|
|
3396
|
+
texto,
|
|
3397
|
+
}, null, 2));
|
|
3398
|
+
return 0;
|
|
3399
|
+
}
|
|
3400
|
+
console.log(`Resumo IA-first do projeto gerado em ${resumoProjeto.pastaSaida}`);
|
|
3401
|
+
console.log("");
|
|
3402
|
+
console.log(texto);
|
|
3403
|
+
return 0;
|
|
3404
|
+
}
|
|
3405
|
+
async function comandoPromptCurto(entrada, args, emJson) {
|
|
3406
|
+
const tamanho = normalizarTamanhoResumo(args);
|
|
3407
|
+
const modo = normalizarModoResumo(obterOpcao(args, "--para"));
|
|
3408
|
+
const alvo = entrada ? path.resolve(process.cwd(), entrada) : process.cwd();
|
|
3409
|
+
if (entrada && entrada.toLowerCase().endsWith(".sema")) {
|
|
3410
|
+
const contexto = await carregarContextoModuloIa(alvo);
|
|
3411
|
+
const resumoSemantico = coletarResumoSemanticoModulo(contexto);
|
|
3412
|
+
const capacidade = tamanho === "micro" ? "pequena" : tamanho === "curto" ? "media" : "grande";
|
|
3413
|
+
const prompt = criarPromptCurtoModulo(resumoSemantico, modo, tamanho, capacidade);
|
|
3414
|
+
if (emJson) {
|
|
3415
|
+
console.log(JSON.stringify({
|
|
3416
|
+
comando: "prompt-curto",
|
|
3417
|
+
modo,
|
|
3418
|
+
tamanho,
|
|
3419
|
+
capacidade,
|
|
3420
|
+
geradoEm: contexto.geradoEm,
|
|
3421
|
+
arquivo: contexto.arquivo,
|
|
3422
|
+
modulo: contexto.modulo,
|
|
3423
|
+
prompt,
|
|
3424
|
+
}, null, 2));
|
|
3425
|
+
return 0;
|
|
3426
|
+
}
|
|
3427
|
+
console.log(prompt);
|
|
3428
|
+
return 0;
|
|
3429
|
+
}
|
|
3430
|
+
const resumoProjeto = await gerarResumoProjetoIa(alvo);
|
|
3431
|
+
const arquivoResumo = tamanho === "micro"
|
|
3432
|
+
? "SEMA_BRIEF.micro.txt"
|
|
3433
|
+
: tamanho === "curto"
|
|
3434
|
+
? "SEMA_BRIEF.curto.txt"
|
|
3435
|
+
: "SEMA_BRIEF.md";
|
|
3436
|
+
const contextoProjeto = await readFile(path.join(resumoProjeto.pastaSaida, arquivoResumo), "utf8");
|
|
3437
|
+
const capacidade = tamanho === "micro" ? "pequena" : tamanho === "curto" ? "media" : "grande";
|
|
3438
|
+
const prompt = `Voce esta operando Sema em modo IA-first.
|
|
3439
|
+
|
|
3440
|
+
Isto nao e material feito para humano; e contexto comprimido para IA.
|
|
3441
|
+
|
|
3442
|
+
Capacidade alvo: ${capacidade}
|
|
3443
|
+
Modo da tarefa: ${modo}
|
|
3444
|
+
|
|
3445
|
+
Regras:
|
|
3446
|
+
- comece pelo resumo compacto abaixo
|
|
3447
|
+
- se a tarefa pedir mais contexto, abra \`SEMA_INDEX.json\`
|
|
3448
|
+
- nao tente ler o repo inteiro se o resumo ja disser onde tocar
|
|
3449
|
+
- preserve contrato, risco, lacuna e checks sugeridos
|
|
3450
|
+
|
|
3451
|
+
Contexto do projeto:
|
|
3452
|
+
${contextoProjeto.trim()}
|
|
3453
|
+
`;
|
|
3454
|
+
if (emJson) {
|
|
3455
|
+
console.log(JSON.stringify({
|
|
3456
|
+
comando: "prompt-curto",
|
|
3457
|
+
modo,
|
|
3458
|
+
tamanho,
|
|
3459
|
+
capacidade,
|
|
3460
|
+
geradoEm: resumoProjeto.geradoEm,
|
|
3461
|
+
baseProjeto: resumoProjeto.baseProjeto,
|
|
3462
|
+
pastaSaida: resumoProjeto.pastaSaida,
|
|
3463
|
+
prompt,
|
|
3464
|
+
}, null, 2));
|
|
3465
|
+
return 0;
|
|
3466
|
+
}
|
|
3467
|
+
console.log(prompt);
|
|
3468
|
+
return 0;
|
|
3469
|
+
}
|
|
2024
3470
|
async function comandoContextoIa(arquivo, pastaSaida, emJson) {
|
|
2025
3471
|
const resultado = await gerarContextoIa(arquivo, pastaSaida);
|
|
2026
3472
|
if (emJson) {
|
|
@@ -2252,7 +3698,7 @@ async function principal() {
|
|
|
2252
3698
|
{
|
|
2253
3699
|
const fonte = normalizarFonteImportacao(posicionais[0]);
|
|
2254
3700
|
if (!fonte || !posicionais[1]) {
|
|
2255
|
-
console.error("Uso: sema importar <nestjs|fastapi|flask|nextjs|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]");
|
|
3701
|
+
console.error("Uso: sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]");
|
|
2256
3702
|
codigoSaida = 1;
|
|
2257
3703
|
break;
|
|
2258
3704
|
}
|
|
@@ -2271,6 +3717,15 @@ async function principal() {
|
|
|
2271
3717
|
case "starter-ia":
|
|
2272
3718
|
codigoSaida = await comandoStarterIa();
|
|
2273
3719
|
break;
|
|
3720
|
+
case "sync-ai-entrypoints":
|
|
3721
|
+
codigoSaida = await comandoSyncAiEntrypoints(possuiFlag(resto, "--json"));
|
|
3722
|
+
break;
|
|
3723
|
+
case "resumo":
|
|
3724
|
+
codigoSaida = await comandoResumo(posicionais[0], resto, possuiFlag(resto, "--json"));
|
|
3725
|
+
break;
|
|
3726
|
+
case "prompt-curto":
|
|
3727
|
+
codigoSaida = await comandoPromptCurto(posicionais[0], resto, possuiFlag(resto, "--json"));
|
|
3728
|
+
break;
|
|
2274
3729
|
case "prompt-ia":
|
|
2275
3730
|
codigoSaida = await comandoPromptIa();
|
|
2276
3731
|
break;
|