@semacode/cli 0.8.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +11 -3
  2. package/dist/drift.d.ts +30 -1
  3. package/dist/drift.js +373 -17
  4. package/dist/drift.js.map +1 -1
  5. package/dist/index.js +828 -53
  6. package/dist/index.js.map +1 -1
  7. package/docs/AGENT_STARTER.md +10 -4
  8. package/docs/como-ensinar-a-sema-para-ia.md +17 -11
  9. package/docs/fluxo-pratico-ia-sema.md +42 -38
  10. package/docs/instalacao-e-primeiro-uso.md +189 -0
  11. package/docs/integracao-com-ia.md +228 -0
  12. package/docs/pagamento-ponta-a-ponta.md +155 -0
  13. package/docs/prompt-base-ia-sema.md +10 -3
  14. package/docs/sintaxe.md +267 -0
  15. package/exemplos/automacao.sema +107 -0
  16. package/exemplos/cadastro_usuario.sema +54 -0
  17. package/exemplos/calculadora.sema +78 -0
  18. package/exemplos/crud_simples.sema +89 -0
  19. package/exemplos/operacao_estrategia.sema +402 -0
  20. package/exemplos/pagamento.sema +222 -0
  21. package/exemplos/pagamento_dominio.sema +35 -0
  22. package/exemplos/testes_embutidos.sema +45 -0
  23. package/exemplos/tratamento_erro.sema +157 -0
  24. package/node_modules/@sema/gerador-dart/package.json +1 -1
  25. package/node_modules/@sema/gerador-python/package.json +1 -1
  26. package/node_modules/@sema/gerador-typescript/package.json +1 -1
  27. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +14 -1
  28. package/node_modules/@sema/nucleo/dist/formatador/index.js +131 -22
  29. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -1
  30. package/node_modules/@sema/nucleo/dist/ir/conversor.js +546 -102
  31. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
  32. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +83 -5
  33. package/node_modules/@sema/nucleo/dist/lexer/lexer.js +1 -1
  34. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +1 -1
  35. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +10 -0
  36. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -1
  37. package/node_modules/@sema/nucleo/dist/parser/parser.js +230 -19
  38. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
  39. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +6 -1
  40. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +269 -10
  41. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
  42. package/node_modules/@sema/nucleo/package.json +1 -1
  43. package/node_modules/@sema/padroes/package.json +1 -1
  44. package/package.json +7 -6
package/dist/index.js CHANGED
@@ -16,12 +16,18 @@ const STARTER_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca d
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, nao gerador magico que deveria fazer tudo
20
- - a Sema modela contratos, estados, fluxos, erros, efeitos e garantias
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
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
23
- - a Sema usa \`drift\` para medir diferenca entre contrato e codigo vivo
24
25
  - a Sema usa \`impl\` para ligar task a simbolo real do runtime
26
+ - a Sema usa \`vinculos\` para ligar contrato a arquivo, simbolo, recurso e superficie real
27
+ - a Sema usa \`execucao\` para explicitar timeout, retry, compensacao e criticidade
28
+ - a Sema usa \`drift\` para medir diferenca entre contrato e codigo vivo com score, confianca e lacunas
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
25
31
  - a Sema pode servir de base para interfaces graficas elegantes e coerentes
26
32
  - a Sema nao gera uma interface completa sozinha no estado atual
27
33
  - trate a Sema como cerebro semantico da aplicacao, nao como gerador magico de front-end pronto
@@ -30,13 +36,20 @@ Importante:
30
36
 
31
37
  Regras:
32
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
33
41
  - trate \`ir --json\` como fonte de verdade semantica
42
+ - trate \`briefing.json\` como plano de intervencao antes de editar projeto vivo
34
43
  - trate \`diagnosticos --json\` como fonte de correcao
35
44
  - use \`sema formatar\` como fonte unica de estilo
36
45
  - preserve a intencao do contrato
37
46
  - nao cobre da Sema adivinhacao de negocio que nao esta no contrato nem no codigo
38
47
 
39
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>]\`
51
+ - descoberta do projeto: \`sema inspecionar [arquivo-ou-pasta] --json\`
52
+ - auditoria do contrato vivo: \`sema drift <arquivo-ou-pasta> [--json]\`
40
53
  - contexto completo do modulo: \`sema contexto-ia <arquivo.sema>\`
41
54
  - estrutura sintatica: \`sema ast <arquivo.sema> --json\`
42
55
  - estrutura semantica: \`sema ir <arquivo.sema> --json\`
@@ -44,39 +57,56 @@ Comandos essenciais:
44
57
  - diagnosticos: \`sema diagnosticos <arquivo.sema> --json\`
45
58
  - formatacao: \`sema formatar <arquivo.sema>\`
46
59
  - importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
47
- - auditoria de coerencia contra codigo vivo: \`sema drift <arquivo-ou-pasta> [--json]\`
48
60
  - geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>\`
49
61
  - verificacao final: \`sema verificar <arquivo-ou-pasta> [--json]\`
50
62
 
51
63
  Antes de editar:
52
64
  1. leia README, docs de IA e um exemplo oficial parecido
53
- 2. 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
54
69
 
55
70
  Depois de editar:
56
71
  1. rode \`sema formatar\`
57
72
  2. rode \`sema validar --json\`
58
73
  3. se houver falha, use \`diagnosticos --json\`
59
- 4. se a tarefa partir de legado, rode \`sema drift\`
74
+ 4. rode \`sema drift\` de novo quando mexer em codigo vivo
60
75
  5. se a tarefa pedir codigo derivado, rode \`sema compilar\`
61
- 6. feche com \`sema verificar\` ou \`npm run project:check\`
76
+ 6. feche com \`sema verificar <arquivo-ou-pasta> --json\`
62
77
 
63
78
  Priorize sempre:
64
79
  - exemplos oficiais
65
80
  - JSON da CLI
81
+ - o menor artefato que resolva a tarefa da IA atual
82
+ - score, confianca e lacunas do \`drift\`
83
+ - \`briefing.json\` como guia de mudanca
66
84
  - consistencia semantica
67
85
 
86
+ Superficies que a IA deve enxergar como first-class:
87
+ - \`route\`
88
+ - \`worker\`
89
+ - \`evento\`
90
+ - \`fila\`
91
+ - \`cron\`
92
+ - \`webhook\`
93
+ - \`cache\`
94
+ - \`storage\`
95
+ - \`policy\`
96
+
68
97
  Nao improvise quando faltar contexto.
69
98
  `;
70
- const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para facilitar entendimento e operacao por IA.
99
+ const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para operacao por IA.
71
100
 
72
- 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.
73
102
 
74
103
  Fontes de verdade, em ordem:
75
104
  1. README do projeto
76
105
  2. gramatica e documentacao de sintaxe da Sema
77
106
  3. especificacao semantica da linguagem
78
107
  4. exemplos oficiais, com prioridade para o vertical de pagamento
79
- 5. AST, IR e diagnosticos exportados pela CLI em JSON
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
80
110
 
81
111
  Regras de operacao:
82
112
  - preserve o significado semantico
@@ -84,6 +114,7 @@ Regras de operacao:
84
114
  - use diagnosticos estruturados como contrato de correcao
85
115
  - use a IR como fonte de verdade semantica quando houver duvida
86
116
  - nao conclua uma alteracao sem validar e verificar o modulo
117
+ - comece pelo menor artefato semantico que resolva a tarefa
87
118
 
88
119
  Antes de editar \`.sema\`, entenda:
89
120
  - o module alvo
@@ -271,6 +302,8 @@ Nao transforme isso em um \`index.html\` solto.
271
302
  Comandos uteis da CLI para esse fluxo:
272
303
  - \`sema starter-ia\`
273
304
  - \`sema ajuda-ia\`
305
+ - \`sema resumo <arquivo-ou-pasta>\`
306
+ - \`sema prompt-curto <arquivo-ou-pasta>\`
274
307
  - \`sema prompt-ia\`
275
308
  - \`sema prompt-ia-ui\`
276
309
  - \`sema prompt-ia-react\`
@@ -306,6 +339,8 @@ Comandos:
306
339
  sema formatar <arquivo-ou-pasta> [--check] [--json]
307
340
  sema ajuda-ia
308
341
  sema starter-ia
342
+ sema resumo <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>] [--saida <diretorio>] [--raiz] [--json]
343
+ sema prompt-curto <arquivo-ou-pasta> [--micro|--curto|--medio] [--para <resumo|onboarding|review|mudanca|bug|arquitetura>] [--json]
309
344
  sema prompt-ia
310
345
  sema prompt-ia-ui
311
346
  sema prompt-ia-react
@@ -335,18 +370,51 @@ function obterOpcao(args, nome, padrao) {
335
370
  function possuiFlag(args, nome) {
336
371
  return args.includes(nome);
337
372
  }
373
+ const OPCOES_COM_VALOR = new Set([
374
+ "--template",
375
+ "--alvo",
376
+ "--saida",
377
+ "--estrutura",
378
+ "--framework",
379
+ "--namespace",
380
+ "--para",
381
+ ]);
338
382
  function obterPosicionais(args) {
339
383
  const posicionais = [];
340
384
  for (let indice = 0; indice < args.length; indice += 1) {
341
385
  const atual = args[indice];
342
386
  if (atual.startsWith("--")) {
343
- indice += 1;
387
+ if (OPCOES_COM_VALOR.has(atual)) {
388
+ indice += 1;
389
+ }
344
390
  continue;
345
391
  }
346
392
  posicionais.push(atual);
347
393
  }
348
394
  return posicionais;
349
395
  }
396
+ function normalizarTamanhoResumo(args) {
397
+ const escolhas = [
398
+ possuiFlag(args, "--micro") ? "micro" : null,
399
+ possuiFlag(args, "--curto") ? "curto" : null,
400
+ possuiFlag(args, "--medio") ? "medio" : null,
401
+ ].filter((item) => item !== null);
402
+ if (escolhas.length > 1) {
403
+ throw new Error("Use apenas uma entre as flags --micro, --curto ou --medio.");
404
+ }
405
+ return escolhas[0] ?? "curto";
406
+ }
407
+ function normalizarModoResumo(valor) {
408
+ if (valor === "resumo"
409
+ || valor === "onboarding"
410
+ || valor === "review"
411
+ || valor === "mudanca"
412
+ || valor === "bug"
413
+ || valor === "arquitetura") {
414
+ return valor;
415
+ }
416
+ return "resumo";
417
+ }
350
418
  function comandoDisponivel(comando, argumentos = ["--version"]) {
351
419
  const execucao = spawnSync(comando, argumentos, { stdio: "ignore", shell: process.platform === "win32" });
352
420
  return (execucao.status ?? 1) === 0;
@@ -620,23 +688,329 @@ async function descobrirDocsIa() {
620
688
  };
621
689
  }
622
690
  function renderizarCabecalhoDocsIa(descoberta) {
691
+ const documentos = descoberta.documentos.map((documento) => `\`${documento.nome}\``);
623
692
  const linhas = [
624
- "Informacoes da instalacao atual",
625
- `- Origem da instalacao: ${descoberta.origemInstalacao}`,
626
- `- Base detectada: ${descoberta.baseDetectada ?? "nao encontrada"}`,
693
+ "Modo IA-first da instalacao atual",
694
+ "- Use `sema` como interface publica principal.",
695
+ "- Nao assuma monorepo, `node pacotes/cli/dist/index.js`, `npm run project:check` ou uma pasta `exemplos` externa ao projeto atual.",
696
+ "- Se a IA tiver contexto curto, comece por `sema resumo` e `sema prompt-curto`.",
697
+ "- Se a IA aguentar mais contexto, suba para `sema drift --json` e `sema contexto-ia`.",
698
+ "- So leia `ast.json` e `ir.json` completos quando a capacidade da IA realmente aguentar esse volume.",
627
699
  ];
628
- if (descoberta.documentos.length > 0) {
629
- linhas.push("- Documentos locais encontrados:");
630
- for (const documento of descoberta.documentos) {
631
- linhas.push(` - ${documento.nome}: ${documento.caminho}`);
632
- }
700
+ if (documentos.length > 0) {
701
+ linhas.push(`- Documentos locais empacotados: ${documentos.join(", ")}.`);
633
702
  }
634
703
  else {
635
- linhas.push("- Documentos locais encontrados: nenhum");
636
- linhas.push(" - Esta instalacao da CLI nao conseguiu localizar a pasta docs ao redor do pacote atual.");
704
+ linhas.push("- Documentos locais empacotados: nenhum extra detectado. Siga a CLI, o contrato atual e os artefatos JSON.");
637
705
  }
638
706
  return linhas.join("\n");
639
707
  }
708
+ function unicos(itens) {
709
+ return [...new Set(itens)];
710
+ }
711
+ function unicosOrdenados(itens) {
712
+ return unicos(itens).sort((a, b) => a.localeCompare(b, "pt-BR"));
713
+ }
714
+ function limitarLista(itens, limite) {
715
+ return itens.slice(0, limite);
716
+ }
717
+ function resumirListaTexto(itens, limite, padrao = "nenhum") {
718
+ if (itens.length === 0) {
719
+ return padrao;
720
+ }
721
+ const visiveis = itens.slice(0, limite);
722
+ const restante = itens.length - visiveis.length;
723
+ return restante > 0 ? `${visiveis.join(", ")} (+${restante})` : visiveis.join(", ");
724
+ }
725
+ function normalizarIdentificadorResumo(valor) {
726
+ return valor.replace(/[._]/g, " ").replace(/\s+/g, " ").trim();
727
+ }
728
+ function resumirCamposTask(task, campo, limiteCampos) {
729
+ const campos = (task[campo] ?? []).map((item) => item.nome).slice(0, limiteCampos);
730
+ if (campos.length === 0) {
731
+ return `${task.nome}(-)`;
732
+ }
733
+ return `${task.nome}(${campos.join(", ")})`;
734
+ }
735
+ function formatarEfeitoSemanticoResumido(efeito) {
736
+ if (efeito.textoOriginal) {
737
+ return efeito.textoOriginal;
738
+ }
739
+ const partes = [`${efeito.categoria} ${efeito.alvo}`];
740
+ if (efeito.criticidade) {
741
+ partes.push(`criticidade=${efeito.criticidade}`);
742
+ }
743
+ if (efeito.detalhe) {
744
+ partes.push(efeito.detalhe);
745
+ }
746
+ return partes.join(" ");
747
+ }
748
+ function calcularRiscoOperacionalResumo(resumoDrift) {
749
+ if (resumoDrift.tasks.some((task) => task.riscoOperacional === "alto")) {
750
+ return "alto";
751
+ }
752
+ if (resumoDrift.tasks.some((task) => task.riscoOperacional === "medio")) {
753
+ return "medio";
754
+ }
755
+ return "baixo";
756
+ }
757
+ function descreverFazModulo(ir, modulo) {
758
+ if (!ir) {
759
+ return `governa o modulo ${normalizarIdentificadorResumo(modulo)}`;
760
+ }
761
+ const partes = [];
762
+ if (ir.routes.length > 0) {
763
+ partes.push(`${ir.routes.length} rota(s)`);
764
+ }
765
+ if (ir.superficies.length > 0) {
766
+ partes.push(`${ir.superficies.length} superficie(s)`);
767
+ }
768
+ if (ir.tasks.length > 0) {
769
+ partes.push(`${ir.tasks.length} task(s)`);
770
+ }
771
+ const foco = ir.routes[0]?.nome ?? ir.superficies[0]?.nome ?? ir.tasks[0]?.nome ?? modulo;
772
+ return partes.length > 0
773
+ ? `governa ${partes.join(", ")} com foco em ${normalizarIdentificadorResumo(foco)}`
774
+ : `governa o modulo ${normalizarIdentificadorResumo(modulo)}`;
775
+ }
776
+ function criarGuiaCapacidadeIa() {
777
+ return {
778
+ pequena: {
779
+ descricao: "IA gratuita ou com contexto curto. Leia so o cartao semantico e o briefing minimo.",
780
+ artefatos: ["resumo.micro.txt", "briefing.min.json", "prompt-curto.txt"],
781
+ ordemLeitura: ["resumo.micro.txt", "briefing.min.json", "resumo.curto.txt"],
782
+ evitar: ["ast.json", "ir.json", "diagnosticos.json"],
783
+ },
784
+ media: {
785
+ descricao: "IA com contexto medio. Aguenta resumo expandido, briefing minimo e drift.",
786
+ artefatos: ["resumo.curto.txt", "briefing.min.json", "drift.json", "prompt-curto.txt"],
787
+ ordemLeitura: ["resumo.curto.txt", "briefing.min.json", "drift.json", "resumo.md"],
788
+ evitar: ["ast.json"],
789
+ },
790
+ grande: {
791
+ descricao: "IA com contexto grande ou tool use. Pode consumir o pacote completo.",
792
+ artefatos: ["README.md", "resumo.md", "briefing.json", "drift.json", "ir.json", "ast.json"],
793
+ ordemLeitura: ["README.md", "resumo.md", "briefing.json", "drift.json", "ir.json", "ast.json"],
794
+ evitar: [],
795
+ },
796
+ };
797
+ }
798
+ function coletarResumoSemanticoModulo(contexto) {
799
+ const { arquivo, modulo, geradoEm, ir, briefing, drift } = contexto;
800
+ const tarefas = ir?.tasks ?? [];
801
+ const rotas = ir?.routes ?? [];
802
+ const superficies = ir?.superficies ?? [];
803
+ const regrasCriticas = unicosOrdenados([
804
+ ...tarefas.flatMap((task) => task.rules),
805
+ ...tarefas.flatMap((task) => task.guarantees),
806
+ ]);
807
+ const efeitos = unicosOrdenados([
808
+ ...tarefas.flatMap((task) => task.effects),
809
+ ...rotas.flatMap((route) => route.efeitosPublicos.map((efeito) => formatarEfeitoSemanticoResumido(efeito))),
810
+ ...superficies.flatMap((superficie) => superficie.effects.map((efeito) => formatarEfeitoSemanticoResumido(efeito))),
811
+ ]);
812
+ const erros = unicosOrdenados([
813
+ ...tarefas.flatMap((task) => Object.keys(task.errors)),
814
+ ...tarefas.flatMap((task) => task.errosDetalhados.map((erro) => erro.codigo)),
815
+ ...rotas.flatMap((route) => route.errosPublicos.map((erro) => erro.codigo)),
816
+ ]);
817
+ const entidadesAfetadas = unicosOrdenados([
818
+ ...(ir?.resumoAgente.entidadesAfetadas ?? []),
819
+ ...tarefas.flatMap((task) => task.resumoAgente.entidadesAfetadas),
820
+ ...rotas.flatMap((route) => route.resumoAgente.entidadesAfetadas),
821
+ ...superficies.flatMap((superficie) => superficie.resumoAgente.entidadesAfetadas),
822
+ ]);
823
+ return {
824
+ geradoEm,
825
+ arquivo,
826
+ modulo,
827
+ perfilCompatibilidade: ir?.perfilCompatibilidade ?? briefing.perfilCompatibilidade,
828
+ scoreSemantico: briefing.scoreSemantico,
829
+ confiancaGeral: briefing.confiancaGeral,
830
+ riscoOperacional: calcularRiscoOperacionalResumo(drift.resumo),
831
+ faz: descreverFazModulo(ir, modulo),
832
+ tarefasPrincipais: limitarLista(tarefas.map((task) => task.nome), 6),
833
+ entradasChave: limitarLista(tarefas.map((task) => resumirCamposTask(task, "input", 4)), 4),
834
+ saidasChave: limitarLista(tarefas.map((task) => resumirCamposTask(task, "output", 4)), 4),
835
+ superficiesPublicas: limitarLista(unicosOrdenados([
836
+ ...briefing.superficiesImpactadas,
837
+ ...rotas.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`),
838
+ ]), 8),
839
+ regrasCriticas: limitarLista(regrasCriticas, 8),
840
+ efeitos: limitarLista(efeitos, 8),
841
+ erros: limitarLista(erros, 8),
842
+ entidadesAfetadas: limitarLista(entidadesAfetadas, 8),
843
+ arquivosProvaveis: limitarLista(unicosOrdenados(briefing.oQueTocar), 8),
844
+ simbolosRelacionados: limitarLista(unicosOrdenados(briefing.simbolosRelacionados), 8),
845
+ riscosPrincipais: limitarLista(unicosOrdenados(briefing.riscosPrincipais), 6),
846
+ lacunas: limitarLista(unicosOrdenados(briefing.oQueEstaFrouxo), 6),
847
+ inferido: limitarLista(unicosOrdenados(briefing.oQueFoiInferido), 6),
848
+ checksSugeridos: limitarLista(unicosOrdenados(briefing.oQueValidar), 6),
849
+ testesMinimos: limitarLista(unicosOrdenados(briefing.testesMinimos), 6),
850
+ };
851
+ }
852
+ function renderizarResumoModuloTexto(resumo, tamanho, modo) {
853
+ const limite = tamanho === "micro" ? 2 : tamanho === "curto" ? 4 : 6;
854
+ const linhas = [
855
+ `MODO: ${modo}`,
856
+ `MODULO: ${resumo.modulo}`,
857
+ `FAZ: ${resumo.faz}`,
858
+ `PERFIL: ${resumo.perfilCompatibilidade}`,
859
+ `PUBLICO: ${resumirListaTexto(resumo.superficiesPublicas, limite)}`,
860
+ `TAREFAS: ${resumirListaTexto(resumo.tarefasPrincipais, limite)}`,
861
+ `ENTRADAS: ${resumirListaTexto(resumo.entradasChave, limite)}`,
862
+ `SAIDAS: ${resumirListaTexto(resumo.saidasChave, limite)}`,
863
+ `REGRAS: ${resumirListaTexto(resumo.regrasCriticas, limite)}`,
864
+ `EFEITOS: ${resumirListaTexto(resumo.efeitos, limite)}`,
865
+ `ERROS: ${resumirListaTexto(resumo.erros, limite)}`,
866
+ `TOCAR: ${resumirListaTexto(resumo.arquivosProvaveis, limite)}`,
867
+ `VALIDAR: ${resumirListaTexto(resumo.checksSugeridos, limite)}`,
868
+ `TESTES: ${resumirListaTexto(resumo.testesMinimos, limite)}`,
869
+ `RISCOS: ${resumirListaTexto(resumo.riscosPrincipais, limite)}`,
870
+ `LACUNAS: ${resumirListaTexto(resumo.lacunas, limite)}`,
871
+ `INFERIDO: ${resumirListaTexto(resumo.inferido, limite)}`,
872
+ `CONFIANCA: ${resumo.confiancaGeral}`,
873
+ `RISCO_OPERACIONAL: ${resumo.riscoOperacional}`,
874
+ `SCORE: ${resumo.scoreSemantico}`,
875
+ `GERADO_EM: ${resumo.geradoEm}`,
876
+ ];
877
+ if (tamanho === "micro") {
878
+ return `${linhas.slice(0, 12).join("\n")}\n`;
879
+ }
880
+ return `${linhas.join("\n")}\n`;
881
+ }
882
+ function renderizarResumoModuloMarkdown(resumo, modo, guiaPorCapacidade) {
883
+ const linhas = [
884
+ `# Resumo Sema para ${resumo.modulo}`,
885
+ "",
886
+ `- Modo: \`${modo}\``,
887
+ `- Gerado em: \`${resumo.geradoEm}\``,
888
+ `- Arquivo: \`${resumo.arquivo}\``,
889
+ `- Perfil: \`${resumo.perfilCompatibilidade}\``,
890
+ `- Score: \`${resumo.scoreSemantico}\``,
891
+ `- Confianca: \`${resumo.confiancaGeral}\``,
892
+ `- Risco operacional: \`${resumo.riscoOperacional}\``,
893
+ "",
894
+ "## O que este modulo faz",
895
+ "",
896
+ `- ${resumo.faz}`,
897
+ `- Superficies publicas: ${resumirListaTexto(resumo.superficiesPublicas, 8)}`,
898
+ `- Tarefas principais: ${resumirListaTexto(resumo.tarefasPrincipais, 8)}`,
899
+ "",
900
+ "## Contrato util para IA",
901
+ "",
902
+ `- Entradas chave: ${resumirListaTexto(resumo.entradasChave, 6)}`,
903
+ `- Saidas chave: ${resumirListaTexto(resumo.saidasChave, 6)}`,
904
+ `- Regras criticas: ${resumirListaTexto(resumo.regrasCriticas, 6)}`,
905
+ `- Efeitos: ${resumirListaTexto(resumo.efeitos, 6)}`,
906
+ `- Erros: ${resumirListaTexto(resumo.erros, 6)}`,
907
+ `- Entidades afetadas: ${resumirListaTexto(resumo.entidadesAfetadas, 6)}`,
908
+ "",
909
+ "## Intervencao segura",
910
+ "",
911
+ `- Arquivos provaveis: ${resumirListaTexto(resumo.arquivosProvaveis, 6)}`,
912
+ `- Simbolos relacionados: ${resumirListaTexto(resumo.simbolosRelacionados, 6)}`,
913
+ `- Riscos principais: ${resumirListaTexto(resumo.riscosPrincipais, 6)}`,
914
+ `- Lacunas: ${resumirListaTexto(resumo.lacunas, 6)}`,
915
+ `- O que foi inferido: ${resumirListaTexto(resumo.inferido, 6)}`,
916
+ `- Checks sugeridos: ${resumirListaTexto(resumo.checksSugeridos, 6)}`,
917
+ `- Testes minimos: ${resumirListaTexto(resumo.testesMinimos, 6)}`,
918
+ "",
919
+ "## Guia por capacidade de IA",
920
+ "",
921
+ ];
922
+ for (const capacidade of ["pequena", "media", "grande"]) {
923
+ const guia = guiaPorCapacidade[capacidade];
924
+ linhas.push(`### ${capacidade}`);
925
+ linhas.push("");
926
+ linhas.push(`- ${guia.descricao}`);
927
+ linhas.push(`- Artefatos: ${guia.artefatos.map((item) => `\`${item}\``).join(", ")}`);
928
+ linhas.push(`- Ordem de leitura: ${guia.ordemLeitura.map((item) => `\`${item}\``).join(" -> ")}`);
929
+ linhas.push(`- Evitar: ${guia.evitar.length > 0 ? guia.evitar.map((item) => `\`${item}\``).join(", ") : "nada obrigatorio"}`);
930
+ linhas.push("");
931
+ }
932
+ return `${linhas.join("\n").trim()}\n`;
933
+ }
934
+ function criarBriefingMinimo(resumo, modo, tamanho) {
935
+ return {
936
+ comando: "briefing-minimo",
937
+ geradoEm: resumo.geradoEm,
938
+ cliVersao: VERSAO_CLI,
939
+ modo,
940
+ tamanho,
941
+ arquivo: resumo.arquivo,
942
+ modulo: resumo.modulo,
943
+ perfilCompatibilidade: resumo.perfilCompatibilidade,
944
+ scoreSemantico: resumo.scoreSemantico,
945
+ confiancaGeral: resumo.confiancaGeral,
946
+ riscoOperacional: resumo.riscoOperacional,
947
+ faz: resumo.faz,
948
+ publico: resumo.superficiesPublicas,
949
+ tarefasPrincipais: resumo.tarefasPrincipais,
950
+ entradasChave: resumo.entradasChave,
951
+ saidasChave: resumo.saidasChave,
952
+ regrasCriticas: resumo.regrasCriticas,
953
+ efeitos: resumo.efeitos,
954
+ erros: resumo.erros,
955
+ arquivosProvaveis: resumo.arquivosProvaveis,
956
+ simbolosRelacionados: resumo.simbolosRelacionados,
957
+ riscosPrincipais: resumo.riscosPrincipais,
958
+ lacunas: resumo.lacunas,
959
+ inferido: resumo.inferido,
960
+ checksSugeridos: resumo.checksSugeridos,
961
+ testesMinimos: resumo.testesMinimos,
962
+ };
963
+ }
964
+ function criarPromptCurtoModulo(resumo, modo, tamanho, capacidade) {
965
+ const resumoTexto = renderizarResumoModuloTexto(resumo, tamanho, modo).trim();
966
+ return `Voce esta operando Sema em modo IA-first.
967
+
968
+ Esta linguagem nao foi desenhada para agradar humano; ela existe para reduzir ambiguidade para IA.
969
+
970
+ Capacidade alvo: ${capacidade}
971
+ Modo da tarefa: ${modo}
972
+
973
+ Regras:
974
+ - nao invente sintaxe nem bloco fora da gramatica oficial
975
+ - preserve a intencao do contrato
976
+ - use este resumo como fonte compacta inicial
977
+ - se a tarefa pedir mais contexto, suba para \`briefing.min.json\`, \`drift.json\` e depois \`ir.json\`
978
+ - nao saia editando backend vivo sem olhar risco, lacuna e checks sugeridos
979
+
980
+ Contexto compacto:
981
+ ${resumoTexto}
982
+ `;
983
+ }
984
+ function renderizarResumoProjetoMarkdown(geradoEm, modulos, guiaPorCapacidade) {
985
+ const linhas = [
986
+ "# SEMA_BRIEF",
987
+ "",
988
+ "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.",
989
+ "",
990
+ `- Gerado em: \`${geradoEm}\``,
991
+ `- Modulos: \`${modulos.length}\``,
992
+ "",
993
+ "## Guia por capacidade",
994
+ "",
995
+ ];
996
+ for (const capacidade of ["pequena", "media", "grande"]) {
997
+ const guia = guiaPorCapacidade[capacidade];
998
+ linhas.push(`- ${capacidade}: ${guia.descricao} Artefatos: ${guia.artefatos.join(", ")}.`);
999
+ }
1000
+ linhas.push("");
1001
+ linhas.push("## Modulos");
1002
+ linhas.push("");
1003
+ for (const modulo of modulos) {
1004
+ linhas.push(`### ${modulo.modulo}`);
1005
+ linhas.push(`- Faz: ${modulo.faz}`);
1006
+ linhas.push(`- Publico: ${resumirListaTexto(modulo.superficiesPublicas, 4)}`);
1007
+ linhas.push(`- Tocar: ${resumirListaTexto(modulo.arquivosProvaveis, 4)}`);
1008
+ linhas.push(`- Score: ${modulo.scoreSemantico} | Confianca: ${modulo.confiancaGeral} | Risco: ${modulo.riscoOperacional}`);
1009
+ linhas.push(`- Lacunas: ${resumirListaTexto(modulo.lacunas, 4)}`);
1010
+ linhas.push("");
1011
+ }
1012
+ return `${linhas.join("\n").trim()}\n`;
1013
+ }
640
1014
  function falharContextoIa(mensagem) {
641
1015
  throw new Error(mensagem);
642
1016
  }
@@ -655,6 +1029,12 @@ function resumirDriftPorModulo(modulo, caminho, resultadoDrift) {
655
1029
  const implsQuebrados = modulo
656
1030
  ? resultadoDrift.impls_quebrados.filter((impl) => impl.modulo === modulo)
657
1031
  : [];
1032
+ const vinculosValidos = modulo
1033
+ ? resultadoDrift.vinculos_validos.filter((vinculo) => vinculo.modulo === modulo)
1034
+ : [];
1035
+ const vinculosQuebrados = modulo
1036
+ ? resultadoDrift.vinculos_quebrados.filter((vinculo) => vinculo.modulo === modulo)
1037
+ : [];
658
1038
  const rotasDivergentes = modulo
659
1039
  ? resultadoDrift.rotas_divergentes.filter((rota) => rota.modulo === modulo)
660
1040
  : [];
@@ -669,28 +1049,84 @@ function resumirDriftPorModulo(modulo, caminho, resultadoDrift) {
669
1049
  modulo,
670
1050
  implsValidos: implsValidos.length,
671
1051
  implsQuebrados: implsQuebrados.length,
1052
+ vinculosValidos: vinculosValidos.length,
1053
+ vinculosQuebrados: vinculosQuebrados.length,
672
1054
  recursosValidos: recursosValidos.length,
673
1055
  recursosDivergentesCount: recursosDivergentes.length,
674
1056
  tasksSemImplementacao: tasks.filter((task) => task.semImplementacao).length,
1057
+ scoreMedio: tasks.length > 0 ? Math.round(tasks.reduce((total, task) => total + task.scoreSemantico, 0) / tasks.length) : 0,
1058
+ confiancaGeral: tasks.some((task) => task.confiancaVinculo === "alta")
1059
+ ? "alta"
1060
+ : tasks.some((task) => task.confiancaVinculo === "media")
1061
+ ? "media"
1062
+ : "baixa",
675
1063
  arquivosRelacionados: [...new Set([
676
1064
  ...tasks.flatMap((task) => task.arquivosReferenciados),
1065
+ ...tasks.flatMap((task) => task.arquivosProvaveisEditar),
677
1066
  ...implsValidos.map((impl) => impl.arquivo).filter((item) => Boolean(item)),
678
1067
  ...implsQuebrados.flatMap((impl) => impl.candidatos?.map((candidato) => candidato.arquivo) ?? []),
1068
+ ...vinculosValidos.map((vinculo) => vinculo.arquivo).filter((item) => Boolean(item)),
679
1069
  ...recursosValidos.map((recurso) => recurso.arquivo).filter(Boolean),
680
1070
  ...recursosDivergentes.map((recurso) => recurso.arquivo).filter(Boolean),
681
1071
  ])].sort((a, b) => a.localeCompare(b, "pt-BR")),
1072
+ checksSugeridos: [...new Set(tasks.flatMap((task) => task.checksSugeridos))],
1073
+ lacunas: [...new Set(tasks.flatMap((task) => task.lacunas))],
682
1074
  tasks,
683
1075
  rotasDivergentes,
684
1076
  recursosDivergentes,
1077
+ vinculosQuebradosDetalhes: vinculosQuebrados,
685
1078
  };
686
1079
  }
687
- async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
1080
+ function criarBriefingAgente(arquivo, modulo, ir, resumoDrift, resultadoDrift) {
1081
+ const tarefasModulo = resultadoDrift.tasks.filter((task) => task.modulo === modulo);
1082
+ return {
1083
+ arquivo,
1084
+ modulo,
1085
+ perfilCompatibilidade: ir?.perfilCompatibilidade ?? "interno",
1086
+ scoreSemantico: resumoDrift.scoreMedio,
1087
+ confiancaGeral: resumoDrift.confiancaGeral,
1088
+ riscosPrincipais: [...new Set([
1089
+ ...resultadoDrift.resumo_operacional.riscosPrincipais.filter((item) => item.startsWith(`${modulo}:`) || tarefasModulo.some((task) => item.startsWith(`${task.task}:`))),
1090
+ ...(ir?.resumoAgente.riscos ?? []),
1091
+ ])],
1092
+ oQueTocar: resumoDrift.arquivosRelacionados,
1093
+ oQueValidar: [...new Set([
1094
+ ...resumoDrift.checksSugeridos,
1095
+ ...resultadoDrift.resumo_operacional.oQueValidar,
1096
+ ])],
1097
+ oQueEstaFrouxo: [...new Set([
1098
+ ...resumoDrift.lacunas,
1099
+ ...resultadoDrift.resumo_operacional.oQueEstaFrouxo,
1100
+ ])],
1101
+ oQueFoiInferido: [...new Set([
1102
+ ...resultadoDrift.impls_quebrados
1103
+ .filter((impl) => impl.modulo === modulo)
1104
+ .flatMap((impl) => impl.candidatos?.map((candidato) => candidato.caminho) ?? []),
1105
+ ...resultadoDrift.vinculos_validos
1106
+ .filter((vinculo) => vinculo.modulo === modulo && vinculo.status === "parcial")
1107
+ .map((vinculo) => `${vinculo.dono}:${vinculo.valor}`),
1108
+ ])],
1109
+ simbolosRelacionados: [...new Set([
1110
+ ...tarefasModulo.flatMap((task) => task.simbolosReferenciados),
1111
+ ...resultadoDrift.vinculos_validos
1112
+ .filter((vinculo) => vinculo.modulo === modulo)
1113
+ .map((vinculo) => vinculo.simbolo)
1114
+ .filter((item) => Boolean(item)),
1115
+ ])],
1116
+ superficiesImpactadas: [
1117
+ ...(ir?.routes.map((route) => `${route.metodo ?? "?"} ${route.caminho ?? route.nome}`) ?? []),
1118
+ ...(ir?.superficies.map((superficie) => `${superficie.tipo}:${superficie.nome}`) ?? []),
1119
+ ],
1120
+ testesMinimos: [
1121
+ "sema validar <arquivo> --json",
1122
+ "sema drift <arquivo> --json",
1123
+ "sema verificar <arquivo-ou-pasta> --json",
1124
+ ],
1125
+ };
1126
+ }
1127
+ async function carregarContextoModuloIa(arquivoEntrada) {
688
1128
  const arquivo = path.resolve(arquivoEntrada);
689
1129
  garantirArquivoSema(arquivo);
690
- const pastaBase = pastaSaidaOpcional
691
- ? path.resolve(pastaSaidaOpcional)
692
- : path.resolve(process.cwd(), ".tmp", "contexto-ia", path.basename(arquivo, ".sema"));
693
- await mkdir(pastaBase, { recursive: true });
694
1130
  const contextoProjeto = await carregarProjeto(arquivo, process.cwd());
695
1131
  const resultadoModulo = contextoProjeto.modulosSelecionados.find((item) => path.resolve(item.caminho) === arquivo)?.resultado;
696
1132
  if (!resultadoModulo) {
@@ -698,6 +1134,7 @@ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
698
1134
  }
699
1135
  const sucesso = !temErros(resultadoModulo.diagnosticos);
700
1136
  const modulo = resultadoModulo.modulo?.nome ?? path.basename(arquivo, ".sema");
1137
+ const geradoEm = new Date().toISOString();
701
1138
  const resultadoDrift = await analisarDriftLegado(contextoProjeto);
702
1139
  const drift = {
703
1140
  comando: "drift",
@@ -741,49 +1178,207 @@ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
741
1178
  diagnosticos: resultadoModulo.diagnosticos,
742
1179
  ir: resultadoModulo.ir ?? null,
743
1180
  };
744
- await writeFile(path.join(pastaBase, "validar.json"), `${JSON.stringify(validar, null, 2)}\n`, "utf8");
745
- await writeFile(path.join(pastaBase, "diagnosticos.json"), `${JSON.stringify(diagnosticos, null, 2)}\n`, "utf8");
746
- await writeFile(path.join(pastaBase, "ast.json"), `${JSON.stringify(ast, null, 2)}\n`, "utf8");
747
- await writeFile(path.join(pastaBase, "ir.json"), `${JSON.stringify(ir, null, 2)}\n`, "utf8");
748
- await writeFile(path.join(pastaBase, "drift.json"), `${JSON.stringify(drift, null, 2)}\n`, "utf8");
749
- const resumo = `# Contexto de IA para ${modulo}
750
-
751
- - Arquivo alvo: \`${arquivo}\`
752
- - Modulo: \`${modulo}\`
753
- - Sucesso em validar: \`${sucesso}\`
754
- - Quantidade de diagnosticos: \`${resultadoModulo.diagnosticos.length}\`
1181
+ const briefing = criarBriefingAgente(arquivo, modulo, resultadoModulo.ir ?? null, drift.resumo, resultadoDrift);
1182
+ return {
1183
+ arquivo,
1184
+ modulo,
1185
+ sucesso,
1186
+ geradoEm,
1187
+ diagnosticos: resultadoModulo.diagnosticos,
1188
+ ir: resultadoModulo.ir ?? null,
1189
+ validar,
1190
+ diagnosticosJson: diagnosticos,
1191
+ ast,
1192
+ irJson: ir,
1193
+ drift,
1194
+ briefing,
1195
+ };
1196
+ }
1197
+ async function gerarArquivosResumoModuloIa(contexto, pastaBase) {
1198
+ const guiaPorCapacidade = criarGuiaCapacidadeIa();
1199
+ const resumoSemantico = coletarResumoSemanticoModulo(contexto);
1200
+ const resumoMicro = renderizarResumoModuloTexto(resumoSemantico, "micro", "resumo");
1201
+ const resumoCurto = renderizarResumoModuloTexto(resumoSemantico, "curto", "resumo");
1202
+ const resumoMarkdown = renderizarResumoModuloMarkdown(resumoSemantico, "resumo", guiaPorCapacidade);
1203
+ const briefingMinimo = criarBriefingMinimo(resumoSemantico, "resumo", "curto");
1204
+ const promptCurto = criarPromptCurtoModulo(resumoSemantico, "mudanca", "curto", "pequena");
1205
+ await writeFile(path.join(pastaBase, "resumo.micro.txt"), resumoMicro, "utf8");
1206
+ await writeFile(path.join(pastaBase, "resumo.curto.txt"), resumoCurto, "utf8");
1207
+ await writeFile(path.join(pastaBase, "resumo.md"), resumoMarkdown, "utf8");
1208
+ await writeFile(path.join(pastaBase, "briefing.min.json"), `${JSON.stringify(briefingMinimo, null, 2)}\n`, "utf8");
1209
+ await writeFile(path.join(pastaBase, "prompt-curto.txt"), promptCurto, "utf8");
1210
+ return {
1211
+ artefatosCompactos: ["resumo.micro.txt", "resumo.curto.txt", "resumo.md", "briefing.min.json", "prompt-curto.txt"],
1212
+ guiaPorCapacidade,
1213
+ };
1214
+ }
1215
+ async function gerarResumoProjetoIa(entrada, pastaSaidaOpcional, escreverNaRaiz = false) {
1216
+ const contextoProjeto = await carregarProjeto(entrada, process.cwd());
1217
+ const geradoEm = new Date().toISOString();
1218
+ const guiaPorCapacidade = criarGuiaCapacidadeIa();
1219
+ const resultadoDrift = await analisarDriftLegado(contextoProjeto);
1220
+ const modulos = contextoProjeto.modulosSelecionados.map((item) => {
1221
+ const modulo = item.resultado.modulo?.nome ?? path.basename(item.caminho, ".sema");
1222
+ const driftResumo = resumirDriftPorModulo(modulo, item.caminho, resultadoDrift);
1223
+ const briefing = criarBriefingAgente(item.caminho, modulo, item.resultado.ir ?? null, driftResumo, resultadoDrift);
1224
+ return coletarResumoSemanticoModulo({
1225
+ arquivo: item.caminho,
1226
+ modulo,
1227
+ geradoEm,
1228
+ ir: item.resultado.ir ?? null,
1229
+ briefing,
1230
+ drift: {
1231
+ comando: "drift",
1232
+ caminho: item.caminho,
1233
+ modulo,
1234
+ sucesso: resultadoDrift.sucesso,
1235
+ resumo: driftResumo,
1236
+ drift: resultadoDrift,
1237
+ },
1238
+ });
1239
+ });
1240
+ const baseProjeto = contextoProjeto.baseProjeto;
1241
+ const pastaSaida = escreverNaRaiz
1242
+ ? baseProjeto
1243
+ : pastaSaidaOpcional
1244
+ ? path.resolve(pastaSaidaOpcional)
1245
+ : path.resolve(baseProjeto, ".tmp", "sema-resumo");
1246
+ await mkdir(pastaSaida, { recursive: true });
1247
+ const semaBrief = renderizarResumoProjetoMarkdown(geradoEm, modulos, guiaPorCapacidade);
1248
+ const indexJson = {
1249
+ comando: "resumo-projeto",
1250
+ geradoEm,
1251
+ cliVersao: VERSAO_CLI,
1252
+ baseProjeto,
1253
+ totalModulos: modulos.length,
1254
+ guiaPorCapacidade,
1255
+ modulos,
1256
+ };
1257
+ const micro = [
1258
+ `PROJETO: ${path.basename(baseProjeto)}`,
1259
+ `MODULOS: ${modulos.length}`,
1260
+ `TOP_MODULOS: ${resumirListaTexto(modulos.map((modulo) => modulo.modulo), 3)}`,
1261
+ `TOP_RISCOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.riscosPrincipais)), 3)}`,
1262
+ `TOP_LACUNAS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.lacunas)), 3)}`,
1263
+ `GERADO_EM: ${geradoEm}`,
1264
+ "",
1265
+ ].join("\n");
1266
+ const curto = [
1267
+ `PROJETO: ${path.basename(baseProjeto)}`,
1268
+ `BASE: ${baseProjeto}`,
1269
+ `MODULOS: ${modulos.length}`,
1270
+ `TOP_MODULOS: ${resumirListaTexto(modulos.map((modulo) => modulo.modulo), 6)}`,
1271
+ `TOP_RISCOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.riscosPrincipais)), 6)}`,
1272
+ `TOP_LACUNAS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.lacunas)), 6)}`,
1273
+ `TOP_ARQUIVOS: ${resumirListaTexto(unicosOrdenados(modulos.flatMap((modulo) => modulo.arquivosProvaveis)), 6)}`,
1274
+ `GERADO_EM: ${geradoEm}`,
1275
+ "",
1276
+ ].join("\n");
1277
+ await writeFile(path.join(pastaSaida, "SEMA_BRIEF.md"), semaBrief, "utf8");
1278
+ await writeFile(path.join(pastaSaida, "SEMA_BRIEF.micro.txt"), micro, "utf8");
1279
+ await writeFile(path.join(pastaSaida, "SEMA_BRIEF.curto.txt"), curto, "utf8");
1280
+ await writeFile(path.join(pastaSaida, "SEMA_INDEX.json"), `${JSON.stringify(indexJson, null, 2)}\n`, "utf8");
1281
+ return {
1282
+ geradoEm,
1283
+ baseProjeto,
1284
+ pastaSaida,
1285
+ artefatos: ["SEMA_BRIEF.md", "SEMA_BRIEF.micro.txt", "SEMA_BRIEF.curto.txt", "SEMA_INDEX.json"],
1286
+ modulos,
1287
+ guiaPorCapacidade,
1288
+ };
1289
+ }
1290
+ async function gerarContextoIa(arquivoEntrada, pastaSaidaOpcional) {
1291
+ const contexto = await carregarContextoModuloIa(arquivoEntrada);
1292
+ const pastaBase = pastaSaidaOpcional
1293
+ ? path.resolve(pastaSaidaOpcional)
1294
+ : path.resolve(process.cwd(), ".tmp", "contexto-ia", path.basename(contexto.arquivo, ".sema"));
1295
+ await mkdir(pastaBase, { recursive: true });
1296
+ await writeFile(path.join(pastaBase, "validar.json"), `${JSON.stringify(contexto.validar, null, 2)}\n`, "utf8");
1297
+ await writeFile(path.join(pastaBase, "diagnosticos.json"), `${JSON.stringify(contexto.diagnosticosJson, null, 2)}\n`, "utf8");
1298
+ await writeFile(path.join(pastaBase, "ast.json"), `${JSON.stringify(contexto.ast, null, 2)}\n`, "utf8");
1299
+ await writeFile(path.join(pastaBase, "ir.json"), `${JSON.stringify(contexto.irJson, null, 2)}\n`, "utf8");
1300
+ await writeFile(path.join(pastaBase, "drift.json"), `${JSON.stringify(contexto.drift, null, 2)}\n`, "utf8");
1301
+ await writeFile(path.join(pastaBase, "briefing.json"), `${JSON.stringify(contexto.briefing, null, 2)}\n`, "utf8");
1302
+ const resumoGerado = await gerarArquivosResumoModuloIa(contexto, pastaBase);
1303
+ const resumo = `# Contexto de IA para ${contexto.modulo}
1304
+
1305
+ - Arquivo alvo: \`${contexto.arquivo}\`
1306
+ - Modulo: \`${contexto.modulo}\`
1307
+ - Sucesso em validar: \`${contexto.sucesso}\`
1308
+ - Quantidade de diagnosticos: \`${contexto.diagnosticos.length}\`
1309
+ - Gerado em: \`${contexto.geradoEm}\`
755
1310
 
756
1311
  ## Arquivos gerados neste pacote
757
1312
 
1313
+ - \`resumo.micro.txt\`
1314
+ - \`resumo.curto.txt\`
1315
+ - \`resumo.md\`
1316
+ - \`briefing.min.json\`
1317
+ - \`prompt-curto.txt\`
758
1318
  - \`validar.json\`
759
1319
  - \`diagnosticos.json\`
760
1320
  - \`ast.json\`
761
1321
  - \`ir.json\`
762
1322
  - \`drift.json\`
1323
+ - \`briefing.json\`
763
1324
 
764
1325
  ## Fluxo recomendado para o agente
765
1326
 
766
- 1. Ler \`ast.json\` para entender a forma escrita.
767
- 2. Ler \`ir.json\` para entender a forma semantica resolvida.
768
- 3. Ler \`drift.json\` para ver quais arquivos e simbolos vivos sustentam a implementacao.
769
- 4. Ler \`diagnosticos.json\` se houver falha ou aviso relevante.
770
- 5. Editar o arquivo \`.sema\`.
771
- 6. Rodar \`sema formatar "${arquivo}"\`.
772
- 7. Rodar \`sema validar "${arquivo}" --json\`.
773
- 8. Fechar com \`sema verificar exemplos --json --saida ./.tmp/verificacao-ia\` ou \`npm run project:check\`.
1327
+ ### IA pequena ou gratuita
1328
+
1329
+ 1. Ler \`resumo.micro.txt\`.
1330
+ 2. Ler \`briefing.min.json\`.
1331
+ 3. Se ainda couber contexto, ler \`resumo.curto.txt\`.
1332
+
1333
+ ### IA media
1334
+
1335
+ 1. Ler \`resumo.curto.txt\`.
1336
+ 2. Ler \`briefing.min.json\`.
1337
+ 3. Ler \`drift.json\`.
1338
+ 4. Se precisar, subir para \`resumo.md\`.
1339
+
1340
+ ### IA grande ou com tool use
1341
+
1342
+ 1. Ler \`README.md\`.
1343
+ 2. Ler \`resumo.md\`.
1344
+ 3. Ler \`briefing.json\`.
1345
+ 4. Ler \`drift.json\`.
1346
+ 5. So depois abrir \`ir.json\` e \`ast.json\`.
1347
+
1348
+ ## Fechamento
1349
+
1350
+ 1. Editar o arquivo \`.sema\`.
1351
+ 2. Rodar \`sema formatar "${contexto.arquivo}"\`.
1352
+ 3. Rodar \`sema validar "${contexto.arquivo}" --json\`.
1353
+ 4. Rodar \`sema drift "${contexto.arquivo}" --json\`.
1354
+ 5. Fechar com \`sema verificar <arquivo-ou-pasta> --json --saida ./.tmp/verificacao-ia\`.
774
1355
 
775
1356
  ## Textos base para onboarding do agente
776
1357
 
777
1358
  - \`sema starter-ia\`
1359
+ - \`sema resumo "${contexto.arquivo}" --micro --para onboarding\`
1360
+ - \`sema prompt-curto "${contexto.arquivo}" --para mudanca\`
778
1361
  - \`sema prompt-ia\`
779
1362
  `;
780
1363
  await writeFile(path.join(pastaBase, "README.md"), resumo, "utf8");
781
1364
  return {
782
- sucesso: true,
783
- arquivo,
784
- modulo,
1365
+ sucesso: contexto.sucesso,
1366
+ arquivo: contexto.arquivo,
1367
+ modulo: contexto.modulo,
785
1368
  pastaSaida: pastaBase,
786
- artefatos: ["validar.json", "diagnosticos.json", "ast.json", "ir.json", "drift.json", "README.md"],
1369
+ artefatos: [
1370
+ "validar.json",
1371
+ "diagnosticos.json",
1372
+ "ast.json",
1373
+ "ir.json",
1374
+ "drift.json",
1375
+ "briefing.json",
1376
+ "README.md",
1377
+ ...resumoGerado.artefatosCompactos,
1378
+ ],
1379
+ artefatosCompactos: resumoGerado.artefatosCompactos,
1380
+ geradoEm: contexto.geradoEm,
1381
+ guiaPorCapacidade: resumoGerado.guiaPorCapacidade,
787
1382
  };
788
1383
  }
789
1384
  async function comandoIniciar(cwd, template) {
@@ -1509,6 +2104,8 @@ async function comandoInspecionar(entrada, emJson, cwd = process.cwd()) {
1509
2104
  diretoriosCodigo: contextoProjeto.diretoriosCodigo,
1510
2105
  fontesLegado: contextoProjeto.fontesLegado,
1511
2106
  modoAdocao: contextoProjeto.modoAdocao,
2107
+ scoreDrift: resultadoDrift.resumo_operacional.scoreMedio,
2108
+ confiancaGeral: resultadoDrift.resumo_operacional.confiancaGeral,
1512
2109
  },
1513
2110
  projeto: {
1514
2111
  arquivos: contextoProjeto.arquivosProjeto,
@@ -1517,6 +2114,7 @@ async function comandoInspecionar(entrada, emJson, cwd = process.cwd()) {
1517
2114
  modulo: item.resultado.modulo?.nome ?? null,
1518
2115
  sucesso: !temErros(item.resultado.diagnosticos),
1519
2116
  diagnosticos: item.resultado.diagnosticos.length,
2117
+ superficies: item.resultado.ir?.superficies.map((superficie) => `${superficie.tipo}:${superficie.nome}`) ?? [],
1520
2118
  implementacao: resumirDriftPorModulo(item.resultado.modulo?.nome ?? null, item.caminho, resultadoDrift),
1521
2119
  })),
1522
2120
  },
@@ -1533,6 +2131,8 @@ async function comandoInspecionar(entrada, emJson, cwd = process.cwd()) {
1533
2131
  console.log(`- Estrutura de saida: ${payload.configuracao.estruturaSaida}`);
1534
2132
  console.log(`- Alvos: ${payload.configuracao.alvos.join(", ")}`);
1535
2133
  console.log(`- Modo de adocao: ${payload.configuracao.modoAdocao}`);
2134
+ console.log(`- Score medio de drift: ${payload.configuracao.scoreDrift}`);
2135
+ console.log(`- Confianca geral: ${payload.configuracao.confiancaGeral}`);
1536
2136
  console.log("- Saidas por alvo:");
1537
2137
  for (const [alvo, saida] of Object.entries(payload.configuracao.saidas)) {
1538
2138
  console.log(` - ${alvo}: ${saida}`);
@@ -1568,9 +2168,13 @@ async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
1568
2168
  console.log(`- Tasks analisadas: ${resultado.tasks.length}`);
1569
2169
  console.log(`- Impl validos: ${resultado.impls_validos.length}`);
1570
2170
  console.log(`- Impl quebrados: ${resultado.impls_quebrados.length}`);
2171
+ console.log(`- Vinculos validos: ${resultado.vinculos_validos.length}`);
2172
+ console.log(`- Vinculos quebrados: ${resultado.vinculos_quebrados.length}`);
1571
2173
  console.log(`- Rotas divergentes: ${resultado.rotas_divergentes.length}`);
1572
2174
  console.log(`- Recursos vivos validos: ${resultado.recursos_validos.length}`);
1573
2175
  console.log(`- Recursos vivos divergentes: ${resultado.recursos_divergentes.length}`);
2176
+ console.log(`- Score medio: ${resultado.resumo_operacional.scoreMedio}`);
2177
+ console.log(`- Confianca geral: ${resultado.resumo_operacional.confiancaGeral}`);
1574
2178
  if (resultado.impls_quebrados.length > 0) {
1575
2179
  console.log("- Impl quebrados:");
1576
2180
  for (const impl of resultado.impls_quebrados) {
@@ -1608,6 +2212,24 @@ async function comandoDrift(entrada, emJson, cwd = process.cwd()) {
1608
2212
  }
1609
2213
  }
1610
2214
  }
2215
+ if (resultado.vinculos_quebrados.length > 0) {
2216
+ console.log("- Vinculos quebrados:");
2217
+ for (const vinculo of resultado.vinculos_quebrados) {
2218
+ console.log(` - ${vinculo.modulo}.${vinculo.dono} :: ${vinculo.tipo}=${vinculo.valor}`);
2219
+ }
2220
+ }
2221
+ if (resultado.resumo_operacional.oQueTocar.length > 0) {
2222
+ console.log("- O que tocar primeiro:");
2223
+ for (const alvo of resultado.resumo_operacional.oQueTocar.slice(0, 8)) {
2224
+ console.log(` - ${alvo}`);
2225
+ }
2226
+ }
2227
+ if (resultado.resumo_operacional.oQueValidar.length > 0) {
2228
+ console.log("- O que validar:");
2229
+ for (const check of resultado.resumo_operacional.oQueValidar.slice(0, 8)) {
2230
+ console.log(` - ${check}`);
2231
+ }
2232
+ }
1611
2233
  if (resultado.diagnosticos.length === 0) {
1612
2234
  console.log("Nenhum drift relevante encontrado.");
1613
2235
  }
@@ -1825,11 +2447,15 @@ async function comandoAjudaIa() {
1825
2447
  console.log(renderizarCabecalhoDocsIa(descoberta));
1826
2448
  console.log("");
1827
2449
  console.log("O que a Sema faz de verdade");
1828
- console.log("- Governa contrato, intencao, erro, efeito, garantia, fluxo e vinculo com implementacao viva.");
2450
+ console.log("- Foi feita para IA operar melhor; leitura humana e consequencia, nao centro de produto.");
2451
+ console.log("- Governa contrato, intencao, erro, efeito, garantia, fluxo, vinculos e execucao.");
1829
2452
  console.log("- Usa `importar` para bootstrap revisavel de legado.");
1830
2453
  console.log("- Usa `impl` para ligar contrato a simbolos reais.");
1831
- console.log("- Usa `drift` para medir divergencia entre contrato e codigo vivo.");
1832
- console.log("- Usa `contexto-ia` para preparar AST, IR, diagnosticos e drift antes da edicao.");
2454
+ console.log("- Usa `vinculos` para ligar contrato a arquivo, simbolo, recurso e superficie real.");
2455
+ console.log("- Usa `execucao` para explicitar timeout, retry, compensacao e criticidade.");
2456
+ console.log("- Usa `drift` para medir divergencia entre contrato e codigo vivo com score, confianca e lacunas.");
2457
+ console.log("- Usa `resumo` e `prompt-curto` para IA pequena ou gratuita.");
2458
+ console.log("- Usa `contexto-ia` para preparar AST, IR, diagnosticos, drift, `briefing.json` e artefatos compactos antes da edicao.");
1833
2459
  console.log("");
1834
2460
  console.log("O que a Sema nao promete");
1835
2461
  console.log("- Nao escreve contrato final sozinho.");
@@ -1838,18 +2464,25 @@ async function comandoAjudaIa() {
1838
2464
  console.log("");
1839
2465
  console.log("Fluxo recomendado");
1840
2466
  console.log("- Use `sema starter-ia` para um texto curto de onboarding.");
2467
+ console.log("- Use `sema resumo <arquivo> --micro --para onboarding` para IA pequena.");
2468
+ console.log("- Use `sema prompt-curto <arquivo> --curto --para mudanca` para colar contexto em modelo gratuito.");
1841
2469
  console.log("- Use `sema prompt-ia` para o prompt-base geral.");
1842
2470
  console.log("- Use `sema prompt-ia-ui` para tarefas visuais com Sema + UI.");
1843
2471
  console.log("- Use `sema prompt-ia-react` para projeto com Sema + React + TypeScript.");
1844
2472
  console.log("- Use `sema prompt-ia-sema-primeiro` para forcar modelagem semantica antes da implementacao.");
1845
2473
  console.log("- Use `sema exemplos-prompt-ia` para pegar modelos prontos de prompt.");
1846
- console.log("- Use `sema contexto-ia <arquivo.sema>` para gerar AST, IR e diagnosticos do modulo alvo.");
2474
+ console.log("- Use `sema inspecionar` para descobrir base, codigo vivo e fontes legado.");
2475
+ console.log("- Use `sema drift` para medir impls, vinculos, rotas, score e lacunas.");
2476
+ console.log("- Use `sema contexto-ia <arquivo.sema>` para gerar AST, IR, drift, `briefing.json` e `briefing.min.json` do modulo alvo.");
1847
2477
  console.log("- Use `sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart> --saida <diretorio>` quando a tarefa pedir codigo derivado.");
1848
2478
  console.log("");
1849
2479
  console.log("Regra pratica");
1850
2480
  console.log("- Se voce quer testar a Sema de verdade, nao peca so HTML solto.");
1851
2481
  console.log("- Peca `.sema` + arquitetura + React + TypeScript, ou use o modo `Sema primeiro`.");
1852
2482
  console.log("- Se o projeto ja existe, trate `importar` como rascunho e `drift` como juiz.");
2483
+ console.log("- IA pequena comeca no menor artefato que resolve a tarefa; nao enfie `ast.json` inteiro nela de bobeira.");
2484
+ console.log("- Antes de editar backend vivo, leia `briefing.min.json` ou `briefing.json` em vez de sair cavando arquivo na fe.");
2485
+ console.log("- Trate `route`, `worker`, `evento`, `fila`, `cron`, `webhook`, `cache`, `storage` e `policy` como superficies de primeira classe.");
1853
2486
  return 0;
1854
2487
  }
1855
2488
  async function comandoPromptIa() {
@@ -1897,6 +2530,142 @@ async function comandoExemplosPromptIa() {
1897
2530
  console.log(EXEMPLOS_PROMPT_IA);
1898
2531
  return 0;
1899
2532
  }
2533
+ async function comandoResumo(entrada, args, emJson) {
2534
+ const tamanho = normalizarTamanhoResumo(args);
2535
+ const modo = normalizarModoResumo(obterOpcao(args, "--para"));
2536
+ const pastaSaida = obterOpcao(args, "--saida");
2537
+ const escreverNaRaiz = possuiFlag(args, "--raiz");
2538
+ const alvo = entrada ? path.resolve(process.cwd(), entrada) : process.cwd();
2539
+ if (entrada && entrada.toLowerCase().endsWith(".sema")) {
2540
+ const contexto = await carregarContextoModuloIa(alvo);
2541
+ const resumoSemantico = coletarResumoSemanticoModulo(contexto);
2542
+ const guiaPorCapacidade = criarGuiaCapacidadeIa();
2543
+ const texto = tamanho === "medio"
2544
+ ? renderizarResumoModuloMarkdown(resumoSemantico, modo, guiaPorCapacidade)
2545
+ : renderizarResumoModuloTexto(resumoSemantico, tamanho, modo);
2546
+ let pastaResumo;
2547
+ let artefatosCompactos = [];
2548
+ if (pastaSaida) {
2549
+ pastaResumo = path.resolve(pastaSaida);
2550
+ await mkdir(pastaResumo, { recursive: true });
2551
+ const gerado = await gerarArquivosResumoModuloIa(contexto, pastaResumo);
2552
+ artefatosCompactos = gerado.artefatosCompactos;
2553
+ }
2554
+ if (emJson) {
2555
+ console.log(JSON.stringify({
2556
+ comando: "resumo",
2557
+ modo,
2558
+ tamanho,
2559
+ geradoEm: contexto.geradoEm,
2560
+ arquivo: contexto.arquivo,
2561
+ modulo: contexto.modulo,
2562
+ pastaSaida: pastaResumo ?? null,
2563
+ artefatosCompactos,
2564
+ guiaPorCapacidade,
2565
+ resumo: resumoSemantico,
2566
+ texto,
2567
+ }, null, 2));
2568
+ return 0;
2569
+ }
2570
+ if (pastaResumo) {
2571
+ console.log(`Resumo IA-first gerado em ${pastaResumo}`);
2572
+ console.log("");
2573
+ }
2574
+ console.log(texto);
2575
+ return 0;
2576
+ }
2577
+ const resumoProjeto = await gerarResumoProjetoIa(alvo, pastaSaida, escreverNaRaiz);
2578
+ const arquivoResumo = tamanho === "micro"
2579
+ ? "SEMA_BRIEF.micro.txt"
2580
+ : tamanho === "curto"
2581
+ ? "SEMA_BRIEF.curto.txt"
2582
+ : "SEMA_BRIEF.md";
2583
+ const texto = await readFile(path.join(resumoProjeto.pastaSaida, arquivoResumo), "utf8");
2584
+ if (emJson) {
2585
+ console.log(JSON.stringify({
2586
+ comando: "resumo",
2587
+ modo,
2588
+ tamanho,
2589
+ geradoEm: resumoProjeto.geradoEm,
2590
+ baseProjeto: resumoProjeto.baseProjeto,
2591
+ pastaSaida: resumoProjeto.pastaSaida,
2592
+ artefatos: resumoProjeto.artefatos,
2593
+ guiaPorCapacidade: resumoProjeto.guiaPorCapacidade,
2594
+ modulos: resumoProjeto.modulos,
2595
+ texto,
2596
+ }, null, 2));
2597
+ return 0;
2598
+ }
2599
+ console.log(`Resumo IA-first do projeto gerado em ${resumoProjeto.pastaSaida}`);
2600
+ console.log("");
2601
+ console.log(texto);
2602
+ return 0;
2603
+ }
2604
+ async function comandoPromptCurto(entrada, args, emJson) {
2605
+ const tamanho = normalizarTamanhoResumo(args);
2606
+ const modo = normalizarModoResumo(obterOpcao(args, "--para"));
2607
+ const alvo = entrada ? path.resolve(process.cwd(), entrada) : process.cwd();
2608
+ if (entrada && entrada.toLowerCase().endsWith(".sema")) {
2609
+ const contexto = await carregarContextoModuloIa(alvo);
2610
+ const resumoSemantico = coletarResumoSemanticoModulo(contexto);
2611
+ const capacidade = tamanho === "micro" ? "pequena" : tamanho === "curto" ? "media" : "grande";
2612
+ const prompt = criarPromptCurtoModulo(resumoSemantico, modo, tamanho, capacidade);
2613
+ if (emJson) {
2614
+ console.log(JSON.stringify({
2615
+ comando: "prompt-curto",
2616
+ modo,
2617
+ tamanho,
2618
+ capacidade,
2619
+ geradoEm: contexto.geradoEm,
2620
+ arquivo: contexto.arquivo,
2621
+ modulo: contexto.modulo,
2622
+ prompt,
2623
+ }, null, 2));
2624
+ return 0;
2625
+ }
2626
+ console.log(prompt);
2627
+ return 0;
2628
+ }
2629
+ const resumoProjeto = await gerarResumoProjetoIa(alvo);
2630
+ const arquivoResumo = tamanho === "micro"
2631
+ ? "SEMA_BRIEF.micro.txt"
2632
+ : tamanho === "curto"
2633
+ ? "SEMA_BRIEF.curto.txt"
2634
+ : "SEMA_BRIEF.md";
2635
+ const contextoProjeto = await readFile(path.join(resumoProjeto.pastaSaida, arquivoResumo), "utf8");
2636
+ const capacidade = tamanho === "micro" ? "pequena" : tamanho === "curto" ? "media" : "grande";
2637
+ const prompt = `Voce esta operando Sema em modo IA-first.
2638
+
2639
+ Isto nao e material feito para humano; e contexto comprimido para IA.
2640
+
2641
+ Capacidade alvo: ${capacidade}
2642
+ Modo da tarefa: ${modo}
2643
+
2644
+ Regras:
2645
+ - comece pelo resumo compacto abaixo
2646
+ - se a tarefa pedir mais contexto, abra \`SEMA_INDEX.json\`
2647
+ - nao tente ler o repo inteiro se o resumo ja disser onde tocar
2648
+ - preserve contrato, risco, lacuna e checks sugeridos
2649
+
2650
+ Contexto do projeto:
2651
+ ${contextoProjeto.trim()}
2652
+ `;
2653
+ if (emJson) {
2654
+ console.log(JSON.stringify({
2655
+ comando: "prompt-curto",
2656
+ modo,
2657
+ tamanho,
2658
+ capacidade,
2659
+ geradoEm: resumoProjeto.geradoEm,
2660
+ baseProjeto: resumoProjeto.baseProjeto,
2661
+ pastaSaida: resumoProjeto.pastaSaida,
2662
+ prompt,
2663
+ }, null, 2));
2664
+ return 0;
2665
+ }
2666
+ console.log(prompt);
2667
+ return 0;
2668
+ }
1900
2669
  async function comandoContextoIa(arquivo, pastaSaida, emJson) {
1901
2670
  const resultado = await gerarContextoIa(arquivo, pastaSaida);
1902
2671
  if (emJson) {
@@ -2147,6 +2916,12 @@ async function principal() {
2147
2916
  case "starter-ia":
2148
2917
  codigoSaida = await comandoStarterIa();
2149
2918
  break;
2919
+ case "resumo":
2920
+ codigoSaida = await comandoResumo(posicionais[0], resto, possuiFlag(resto, "--json"));
2921
+ break;
2922
+ case "prompt-curto":
2923
+ codigoSaida = await comandoPromptCurto(posicionais[0], resto, possuiFlag(resto, "--json"));
2924
+ break;
2150
2925
  case "prompt-ia":
2151
2926
  codigoSaida = await comandoPromptIa();
2152
2927
  break;