@semacode/cli 1.5.17 → 1.5.19

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 (111) hide show
  1. package/AGENTS.md +268 -260
  2. package/LICENSE +22 -22
  3. package/README.md +93 -61
  4. package/SEMA_BRIEF.curto.txt +8 -6
  5. package/SEMA_BRIEF.md +71 -22
  6. package/SEMA_BRIEF.micro.txt +7 -5
  7. package/SEMA_INDEX.json +931 -193
  8. package/dist/controleComercialSupabase.d.ts +326 -0
  9. package/dist/controleComercialSupabase.js +310 -0
  10. package/dist/controleComercialSupabase.js.map +1 -0
  11. package/dist/docs.js +48 -20
  12. package/dist/docs.js.map +1 -1
  13. package/dist/drift.d.ts +5 -3
  14. package/dist/drift.js +119 -116
  15. package/dist/drift.js.map +1 -1
  16. package/dist/importador.d.ts +1 -1
  17. package/dist/importador.js +1 -200
  18. package/dist/importador.js.map +1 -1
  19. package/dist/index.js +1924 -493
  20. package/dist/index.js.map +1 -1
  21. package/dist/mcpRemoto.d.ts +32 -0
  22. package/dist/mcpRemoto.js +61 -0
  23. package/dist/mcpRemoto.js.map +1 -0
  24. package/dist/projeto.js +3 -21
  25. package/dist/projeto.js.map +1 -1
  26. package/dist/tipos.d.ts +1 -1
  27. package/docs/AGENT_STARTER.md +109 -102
  28. package/docs/cli.md +89 -33
  29. package/docs/como-ensinar-a-sema-para-ia.md +42 -36
  30. package/docs/deploy.md +231 -43
  31. package/docs/documentacao.md +61 -36
  32. package/docs/env.md +63 -14
  33. package/docs/extensao-vscode.md +12 -4
  34. package/docs/fluxo-pratico-ia-sema.md +45 -35
  35. package/docs/instalacao-e-primeiro-uso.md +52 -30
  36. package/docs/integracao-com-ia.md +44 -35
  37. package/docs/mcp.md +270 -31
  38. package/docs/pagamento-ponta-a-ponta.md +40 -24
  39. package/docs/persistencia-vendor-first.md +11 -5
  40. package/docs/prompt-base-ia-sema.md +18 -11
  41. package/docs/rollback.md +17 -15
  42. package/docs/sintaxe.md +37 -229
  43. package/exemplos/agendamento.sema +105 -106
  44. package/exemplos/assinatura.sema +133 -136
  45. package/exemplos/auditoria.sema +89 -88
  46. package/exemplos/autenticacao.sema +125 -125
  47. package/exemplos/author_obra_comum.sema +294 -0
  48. package/exemplos/author_tema_sensivel.sema +264 -0
  49. package/exemplos/automacao.sema +107 -107
  50. package/exemplos/cadastro_usuario.sema +54 -54
  51. package/exemplos/calculadora.sema +78 -78
  52. package/exemplos/crud_simples.sema +89 -89
  53. package/exemplos/estoque.sema +127 -126
  54. package/exemplos/exportacao.sema +94 -94
  55. package/exemplos/fila.sema +130 -131
  56. package/exemplos/integracao_externa.sema +94 -94
  57. package/exemplos/multi_tenant.sema +140 -140
  58. package/exemplos/notificacao.sema +149 -98
  59. package/exemplos/operacao_estrategia.sema +633 -402
  60. package/exemplos/pagamento.sema +434 -222
  61. package/exemplos/pagamento_dominio.sema +35 -35
  62. package/exemplos/pedido.sema +255 -119
  63. package/exemplos/permissao.sema +121 -121
  64. package/exemplos/persistencia_vendor_first.sema +86 -86
  65. package/exemplos/profile_game.sema +114 -0
  66. package/exemplos/profile_legal.sema +105 -0
  67. package/exemplos/profile_ops.sema +110 -0
  68. package/exemplos/profile_research.sema +104 -0
  69. package/exemplos/profile_software.sema +123 -0
  70. package/exemplos/profile_workflow_n8n.sema +99 -0
  71. package/exemplos/relatorio.sema +93 -93
  72. package/exemplos/replica_analitica_erp.sema +160 -0
  73. package/exemplos/testes_embutidos.sema +45 -45
  74. package/exemplos/tratamento_erro.sema +157 -157
  75. package/exemplos/upload_arquivo.sema +93 -93
  76. package/exemplos/webhook.sema +94 -96
  77. package/llms-full.txt +34 -34
  78. package/llms.txt +17 -17
  79. package/node_modules/@sema/gerador-css/dist/index.js +563 -563
  80. package/node_modules/@sema/gerador-css/package.json +1 -1
  81. package/node_modules/@sema/gerador-dart/package.json +1 -1
  82. package/node_modules/@sema/gerador-html/dist/index.js +90 -90
  83. package/node_modules/@sema/gerador-html/package.json +1 -1
  84. package/node_modules/@sema/gerador-javascript/dist/index.js +92 -92
  85. package/node_modules/@sema/gerador-javascript/package.json +1 -1
  86. package/node_modules/@sema/gerador-lua/dist/index.js +53 -53
  87. package/node_modules/@sema/gerador-lua/package.json +1 -1
  88. package/node_modules/@sema/gerador-python/dist/index.js +122 -96
  89. package/node_modules/@sema/gerador-python/dist/index.js.map +1 -1
  90. package/node_modules/@sema/gerador-python/package.json +1 -1
  91. package/node_modules/@sema/gerador-typescript/dist/index.js +153 -153
  92. package/node_modules/@sema/gerador-typescript/package.json +1 -1
  93. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +2 -4
  94. package/node_modules/@sema/nucleo/dist/formatador/index.js +26 -46
  95. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -1
  96. package/node_modules/@sema/nucleo/dist/ir/conversor.js +9 -204
  97. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
  98. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +3 -35
  99. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +0 -21
  100. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -1
  101. package/node_modules/@sema/nucleo/dist/parser/parser.js +0 -40
  102. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
  103. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +6 -5
  104. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +76 -307
  105. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
  106. package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +2 -0
  107. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +32 -2
  108. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +1 -1
  109. package/node_modules/@sema/nucleo/package.json +1 -1
  110. package/node_modules/@sema/padroes/package.json +1 -1
  111. package/package.json +15 -15
@@ -13,10 +13,12 @@ const TIPOS_PRIMITIVOS = new Set([
13
13
  "Booleano",
14
14
  "Data",
15
15
  "DataHora",
16
+ "Timestamp",
16
17
  "Id",
17
18
  "Email",
18
19
  "Url",
19
20
  "Json",
21
+ "Objeto",
20
22
  "Vazio",
21
23
  ]);
22
24
  const TIPOS_COMPOSTOS_SUPORTADOS = new Set(["Lista", "Mapa", "Opcional", "Ou"]);
@@ -90,54 +92,6 @@ const CAMPOS_ERRO_OPERACIONAL = new Set([
90
92
  "requer_compensacao",
91
93
  ]);
92
94
  const CRITICIDADES_OPERACIONAIS = new Set(["baixa", "media", "alta", "critica"]);
93
- const TIPOS_AUTHOR_PROFILE = new Set([
94
- "book",
95
- "work",
96
- "part",
97
- "chapter",
98
- "section",
99
- "scene",
100
- "character",
101
- "arc",
102
- "audience",
103
- "thesis",
104
- "argument",
105
- "claim",
106
- "source",
107
- "concept",
108
- "example",
109
- "voice",
110
- "style_rule",
111
- "lexicon",
112
- "motif",
113
- "canon",
114
- ]);
115
- const TERMOS_AUTHOR_SENSIVEIS = [
116
- "autismo",
117
- "autista",
118
- "autistas",
119
- "tea",
120
- "neurodiversidade",
121
- "neurodivergencia",
122
- "neurodivergente",
123
- "saude",
124
- "clinico",
125
- "clinica",
126
- "medico",
127
- "medica",
128
- "diagnostico",
129
- "diagnosticar",
130
- "terapia",
131
- "tratamento",
132
- "medicamento",
133
- "psicologia",
134
- "psiquiatria",
135
- "educacao inclusiva",
136
- "inclusao escolar",
137
- "juridico",
138
- "legal",
139
- "financeiro",
140
- ];
141
95
  const PADRAO_CAMINHO_INTEROP = /^[A-Za-z_][A-Za-z0-9_-]*(\.[A-Za-z_][A-Za-z0-9_-]*)*$/;
142
96
  function normalizarOrigemImplementacao(valor) {
143
97
  switch (valor.toLowerCase()) {
@@ -149,10 +103,6 @@ function normalizarOrigemImplementacao(valor) {
149
103
  return "py";
150
104
  case "dart":
151
105
  return "dart";
152
- case "lua":
153
- return "lua";
154
- case "php":
155
- return "php";
156
106
  case "cs":
157
107
  case "csharp":
158
108
  case "dotnet":
@@ -203,17 +153,6 @@ function localizarBloco(corpo, nome) {
203
153
  }
204
154
  return corpo.blocos.find((bloco) => bloco.tipo === "bloco_generico" && (bloco.palavraChave === nome || bloco.nome === nome));
205
155
  }
206
- function nomeBlocoDeclarativo(bloco) {
207
- return bloco.palavraChave === "desconhecido"
208
- ? (bloco.nome ?? "desconhecido")
209
- : bloco.palavraChave;
210
- }
211
- function blocoTemNome(bloco, nomes) {
212
- return nomes.includes(nomeBlocoDeclarativo(bloco).toLowerCase());
213
- }
214
- function localizarBlocoPorNomes(corpo, ...nomes) {
215
- return corpo?.blocos.find((bloco) => bloco.tipo === "bloco_generico" && blocoTemNome(bloco, nomes));
216
- }
217
156
  function localizarCampo(bloco, ...nomes) {
218
157
  if (!bloco) {
219
158
  return undefined;
@@ -313,7 +252,7 @@ function validarImplementacoesTask(task, diagnosticos) {
313
252
  for (const campo of task.impl.campos) {
314
253
  const origem = normalizarOrigemImplementacao(campo.nome);
315
254
  if (!origem) {
316
- diagnosticos.push(criarDiagnostico("SEM059", `Task "${task.nome}" declarou implementacao externa invalida em impl: "${campo.nome}".`, "erro", campo.intervalo, "Use apenas ts, py, dart, lua, php, cs, java, go, rust ou cpp dentro do bloco impl."));
255
+ diagnosticos.push(criarDiagnostico("SEM059", `Task "${task.nome}" declarou implementacao externa invalida em impl: "${campo.nome}".`, "erro", campo.intervalo, "Use apenas ts, py, dart, cs, java, go, rust ou cpp dentro do bloco impl."));
317
256
  continue;
318
257
  }
319
258
  if (origens.has(origem)) {
@@ -500,6 +439,11 @@ function validarExecucaoBloco(execucao, diagnosticos, contexto) {
500
439
  }
501
440
  }
502
441
  }
442
+ const criticidade = valorCampoCompleto(localizarCampo(execucao, "criticidade_operacional"));
443
+ const idempotencia = localizarCampo(execucao, "idempotencia");
444
+ if ((criticidade === "alta" || criticidade === "critica") && !idempotencia) {
445
+ diagnosticos.push(criarDiagnostico("SEM101", `Execucao critica em ${contexto} deveria declarar idempotencia explicita.`, "aviso", execucao.intervalo, "Declare idempotencia: verdadeiro ou idempotencia: falso para a IA nao assumir retry seguro no escuro."));
446
+ }
503
447
  }
504
448
  function validarExecucao(task, diagnosticos) {
505
449
  validarExecucaoBloco(task.execucao, diagnosticos, `task "${task.nome}"`);
@@ -943,16 +887,7 @@ function validarInvariantesDeCampos(bloco, nomeBloco, diagnosticos) {
943
887
  dicaReferencia: "Referencie apenas campos declarados no proprio bloco ao escrever invariantes de dominio.",
944
888
  });
945
889
  }
946
- function referenciaAgentConhecida(referencia, agentsConhecidos) {
947
- if (agentsConhecidos.has(referencia)) {
948
- return true;
949
- }
950
- return referencia.startsWith("agent.") && agentsConhecidos.has(referencia.slice("agent.".length));
951
- }
952
- function referenciaOperadorFlowConhecida(referencia, tasksConhecidas, agentsConhecidos) {
953
- return tasksConhecidas.has(referencia) || referenciaAgentConhecida(referencia, agentsConhecidos);
954
- }
955
- function validarFlow(flow, tasksConhecidas, agentsConhecidos, tarefasDetalhadas, diagnosticos) {
890
+ function validarFlow(flow, tasksConhecidas, tarefasDetalhadas, diagnosticos) {
956
891
  const possuiEtapas = flow.corpo.linhas.length > 0 || flow.corpo.campos.length > 0 || flow.corpo.blocos.length > 0;
957
892
  if (!possuiEtapas) {
958
893
  diagnosticos.push(criarDiagnostico("SEM012", `Flow "${flow.nome}" precisa declarar ao menos uma etapa.`, "erro", flow.intervalo, "Adicione linhas declarativas, campos ou subblocos dentro de flow."));
@@ -966,8 +901,8 @@ function validarFlow(flow, tasksConhecidas, agentsConhecidos, tarefasDetalhadas,
966
901
  .filter((campo) => campo.nome === "task" || campo.nome === "tarefa")
967
902
  .map((campo) => campo.valor);
968
903
  for (const tarefa of tarefasReferenciadas) {
969
- if (!referenciaOperadorFlowConhecida(tarefa, tasksConhecidas, agentsConhecidos)) {
970
- diagnosticos.push(criarDiagnostico("SEM013", `Flow "${flow.nome}" referencia operador "${tarefa}" que nao existe.`, "erro", flow.intervalo, "Declare a task ou agent no mesmo modulo, ou ajuste a referencia do flow."));
904
+ if (!tasksConhecidas.has(tarefa)) {
905
+ diagnosticos.push(criarDiagnostico("SEM013", `Flow "${flow.nome}" referencia task "${tarefa}" que nao existe.`, "erro", flow.intervalo, "Declare a task no mesmo modulo ou ajuste a referencia do flow."));
971
906
  }
972
907
  }
973
908
  const etapas = flow.corpo.linhas
@@ -987,16 +922,11 @@ function validarFlow(flow, tasksConhecidas, agentsConhecidos, tarefasDetalhadas,
987
922
  }
988
923
  nomesEtapas.add(item.etapa.nome);
989
924
  etapasValidas.set(item.etapa.nome, item.etapa);
990
- const etapaUsaTask = Boolean(item.etapa.task && tasksConhecidas.has(item.etapa.task));
991
- const etapaUsaAgent = Boolean(item.etapa.task && referenciaAgentConhecida(item.etapa.task, agentsConhecidos));
992
- if (item.etapa.task && !etapaUsaTask && !etapaUsaAgent) {
993
- const sugestoesOperadores = [
994
- descreverSugestoes(tasksConhecidas, "Tasks conhecidas no contexto"),
995
- descreverSugestoes(agentsConhecidos, "Agents conhecidos no contexto"),
996
- ].filter(Boolean).join(" ");
997
- diagnosticos.push(criarDiagnostico("SEM034", `Etapa "${item.etapa.nome}" do flow "${flow.nome}" usa operador "${item.etapa.task}" que nao existe.`, "erro", item.linha.intervalo, sugestoesOperadores || "Ajuste a etapa para apontar para uma task ou agent declarado/importado."));
998
- }
999
- if (item.etapa.task && etapaUsaTask) {
925
+ if (item.etapa.task && !tasksConhecidas.has(item.etapa.task)) {
926
+ const sugestoesTasks = descreverSugestoes(tasksConhecidas, "Tasks conhecidas no contexto");
927
+ diagnosticos.push(criarDiagnostico("SEM034", `Etapa "${item.etapa.nome}" do flow "${flow.nome}" usa task "${item.etapa.task}" que nao existe.`, "erro", item.linha.intervalo, sugestoesTasks ?? "Ajuste a task da etapa para apontar para uma task declarada ou importada."));
928
+ }
929
+ if (item.etapa.task) {
1000
930
  const detalhesTask = tarefasDetalhadas.get(item.etapa.task);
1001
931
  if (detalhesTask) {
1002
932
  const indiceInput = indicesCampos(detalhesTask.input);
@@ -1036,12 +966,8 @@ function validarFlow(flow, tasksConhecidas, agentsConhecidos, tarefasDetalhadas,
1036
966
  if (item.etapa.condicao) {
1037
967
  const referencias = extrairReferenciasDaExpressao(item.etapa.condicao).map((referencia) => extrairRaiz(referencia));
1038
968
  for (const referencia of referencias) {
1039
- if (!ehMarcadorSemantico(referencia)
1040
- && !tasksConhecidas.has(referencia)
1041
- && !referenciaAgentConhecida(referencia, agentsConhecidos)
1042
- && !nomesEtapas.has(referencia)
1043
- && !contextoFlow.has(referencia)) {
1044
- diagnosticos.push(criarDiagnostico("SEM035", `Condicao da etapa "${item.etapa.nome}" em flow "${flow.nome}" referencia "${referencia}" fora do contexto atual.`, "erro", item.linha.intervalo, "Condicoes de flow devem apontar para marcadores semanticos, campos do flow, tasks, agents ou etapas anteriores."));
969
+ if (!ehMarcadorSemantico(referencia) && !tasksConhecidas.has(referencia) && !nomesEtapas.has(referencia) && !contextoFlow.has(referencia)) {
970
+ diagnosticos.push(criarDiagnostico("SEM035", `Condicao da etapa "${item.etapa.nome}" em flow "${flow.nome}" referencia "${referencia}" fora do contexto atual.`, "erro", item.linha.intervalo, "No MVP atual, condicoes de flow devem apontar para marcadores semanticos, campos do flow, tasks conhecidas ou etapas anteriores."));
1045
971
  }
1046
972
  }
1047
973
  }
@@ -1062,7 +988,7 @@ function validarFlow(flow, tasksConhecidas, agentsConhecidos, tarefasDetalhadas,
1062
988
  diagnosticos.push(criarDiagnostico("SEM045", `Etapa "${item.etapa.nome}" do flow "${flow.nome}" aponta para "${destino}" em ramificacao, mas essa etapa nao foi declarada.`, "erro", item.linha.intervalo, sugestoesEtapas ?? "Declare a etapa de destino no mesmo flow antes de usa-la em em_sucesso ou em_erro."));
1063
989
  }
1064
990
  }
1065
- if (item.etapa.task && tasksConhecidas.has(item.etapa.task)) {
991
+ if (item.etapa.task) {
1066
992
  const detalhesTask = tarefasDetalhadas.get(item.etapa.task);
1067
993
  const indiceErrors = indiceErros(detalhesTask?.errors ?? []);
1068
994
  for (const rotaErro of item.etapa.porErro) {
@@ -1087,13 +1013,18 @@ function validarVinculoEstadoDaTask(task, statesConhecidos, diagnosticos) {
1087
1013
  diagnosticos.push(criarDiagnostico("SEM037", `Task "${task.nome}" declarou state sem indicar qual estado ela governa.`, "erro", task.state.intervalo, "Use \"state nome_do_estado { ... }\" ou declare \"estado: nome_do_estado\" dentro do bloco state da task."));
1088
1014
  return;
1089
1015
  }
1090
- const estadoConhecido = statesConhecidos.get(nomeEstado);
1016
+ const blocoTransitions = localizarBloco(task.state, "transitions");
1017
+ const linhasTransicao = blocoTransitions?.linhas ?? task.state.linhas;
1018
+ const transicoesLocais = new Set(linhasTransicao
1019
+ .map((linha) => parsearTransicaoEstado(linha.conteudo))
1020
+ .filter((transicao) => Boolean(transicao))
1021
+ .map((transicao) => serializarTransicao(transicao.origem, transicao.destino)));
1022
+ const estadoConhecido = statesConhecidos.get(nomeEstado)
1023
+ ?? (transicoesLocais.size > 0 ? { transicoes: transicoesLocais } : undefined);
1091
1024
  if (!estadoConhecido) {
1092
1025
  diagnosticos.push(criarDiagnostico("SEM038", `Task "${task.nome}" referencia state "${nomeEstado}", mas esse state nao foi encontrado.`, "erro", task.state.intervalo, "Declare o state no mesmo modulo ou importe um modulo que exponha esse state."));
1093
1026
  return;
1094
1027
  }
1095
- const blocoTransitions = localizarBloco(task.state, "transitions");
1096
- const linhasTransicao = blocoTransitions?.linhas ?? task.state.linhas;
1097
1028
  if (linhasTransicao.length === 0) {
1098
1029
  diagnosticos.push(criarDiagnostico("SEM039", `Task "${task.nome}" referencia state "${nomeEstado}" sem declarar transicoes.`, "erro", task.state.intervalo, "Declare ao menos uma transicao para explicitar como a task altera o estado."));
1099
1030
  return;
@@ -1266,187 +1197,30 @@ function validarGuardrailsSeguranca(modulo, diagnosticos) {
1266
1197
  }
1267
1198
  }
1268
1199
  }
1269
- function valoresDeclarativos(bloco) {
1270
- if (!bloco) {
1271
- return [];
1272
- }
1273
- return [
1274
- ...bloco.linhas.map((linha) => linha.conteudo),
1275
- ...bloco.campos.map((campo) => valorCampoCompleto(campo) ?? campo.nome),
1276
- ].filter((valor) => valor.trim().length > 0);
1200
+ function campoStatusTexto(campo) {
1201
+ return (campo.nome === "status" || campo.nome === "estado") && campo.valor === "Texto";
1277
1202
  }
1278
- function valoresDeclarativosProfundos(bloco) {
1279
- if (!bloco) {
1280
- return [];
1281
- }
1282
- return [
1283
- nomeBlocoDeclarativo(bloco),
1284
- bloco.nome ?? "",
1285
- ...valoresDeclarativos(bloco),
1286
- ...bloco.campos.flatMap((campo) => [campo.nome, campo.valor, ...campo.modificadores]),
1287
- ...bloco.blocos.flatMap((filho) => filho.tipo === "bloco_generico" ? valoresDeclarativosProfundos(filho) : []),
1288
- ].filter((valor) => valor.trim().length > 0);
1289
- }
1290
- function normalizarTextoAuthorSensivel(valor) {
1291
- return valor
1292
- .normalize("NFD")
1293
- .replace(/[\u0300-\u036f]/g, "")
1294
- .toLowerCase()
1295
- .replace(/[_\W]+/g, " ")
1296
- .replace(/\s+/g, " ")
1297
- .trim();
1203
+ function moduloTemStateComTransicao(modulo) {
1204
+ return modulo.states.some((state) => (localizarBloco(state.corpo, "transitions")?.linhas.length ?? 0) > 0);
1298
1205
  }
1299
- function textoContemTermoAuthorSensivel(valor) {
1300
- const texto = ` ${normalizarTextoAuthorSensivel(valor)} `;
1301
- return TERMOS_AUTHOR_SENSIVEIS.some((termo) => {
1302
- const termoNormalizado = normalizarTextoAuthorSensivel(termo);
1303
- if (termoNormalizado.length <= 3) {
1304
- return texto.includes(` ${termoNormalizado} `);
1305
- }
1306
- return texto.includes(termoNormalizado);
1307
- });
1308
- }
1309
- function blocoAuthorMarcaSensivel(bloco) {
1310
- const campoSensivel = localizarCampo(bloco, "sensivel", "sensitive", "tema_sensivel");
1311
- const valorSensivel = normalizarTextoAuthorSensivel(valorCampoCompleto(campoSensivel) ?? "");
1312
- if (["verdadeiro", "true", "sim", "alto", "alta", "critico", "critica"].includes(valorSensivel)) {
1313
- return true;
1314
- }
1315
- return valoresDeclarativosProfundos(bloco).some(textoContemTermoAuthorSensivel);
1316
- }
1317
- function coletarAuthorBlocksPorTipo(modulo, tipos) {
1318
- return modulo.authorBlocks.filter((bloco) => tipos.includes(nomeBlocoDeclarativo(bloco)));
1319
- }
1320
- function coletarSubblocosPorNomes(bloco, nomes) {
1321
- return bloco.blocos.filter((item) => item.tipo === "bloco_generico" && blocoTemNome(item, nomes));
1322
- }
1323
- function validarSubblocoNaoVazio(bloco, diagnosticos, codigo, contexto) {
1324
- if (bloco.campos.length > 0 || bloco.linhas.length > 0 || bloco.blocos.length > 0) {
1206
+ function validarStatusTextoComState(modulo, diagnosticos) {
1207
+ if (!moduloTemStateComTransicao(modulo)) {
1325
1208
  return;
1326
1209
  }
1327
- diagnosticos.push(criarDiagnostico(codigo, `${contexto} declarou "${nomeBlocoDeclarativo(bloco)}" vazio.`, "erro", bloco.intervalo, "Declare ao menos uma linha ou campo para que o guardrail seja verificavel por IA."));
1328
- }
1329
- function validarAuthorBlock(bloco, diagnosticos) {
1330
- const tipo = nomeBlocoDeclarativo(bloco);
1331
- const contexto = `${tipo} "${bloco.nome ?? tipo}"`;
1332
- if (["book", "work"].includes(tipo) && !localizarCampo(bloco, "titulo", "title", "proposito", "purpose")) {
1333
- diagnosticos.push(criarDiagnostico("SEM120", `${contexto} deveria declarar titulo ou proposito para ancorar a obra autoral.`, "aviso", bloco.intervalo, "Use titulo/title para nome editorial ou proposito/purpose para livro tecnico, ensaio, manual ou obra nao ficcional."));
1334
- }
1335
- if (["chapter", "section"].includes(tipo) && !localizarCampo(bloco, "intent", "intencao", "objetivo", "purpose")) {
1336
- diagnosticos.push(criarDiagnostico("SEM121", `${contexto} deveria declarar intencao ou objetivo.`, "aviso", bloco.intervalo, "Declare intent/intencao/objetivo para que a IA nao preencha a secao com texto generico."));
1337
- }
1338
- if (tipo === "scene" && !localizarCampo(bloco, "pov", "ponto_de_vista")) {
1339
- diagnosticos.push(criarDiagnostico("SEM122", `${contexto} deveria declarar pov para preservar continuidade narrativa.`, "aviso", bloco.intervalo, "Use pov ou ponto_de_vista quando a obra tiver cenas narrativas."));
1340
- }
1341
- if (tipo === "voice" && !localizarCampo(bloco, "tom", "tone", "registro", "ritmo")) {
1342
- diagnosticos.push(criarDiagnostico("SEM123", `${contexto} deveria declarar tom, registro ou ritmo.`, "aviso", bloco.intervalo, "Declare a voz da obra para reduzir texto raso, repetitivo ou com cara de IA."));
1343
- }
1344
- if (tipo === "claim" && !localizarCampo(bloco, "source", "fonte", "evidencia", "confidence", "confianca")) {
1345
- diagnosticos.push(criarDiagnostico("SEM124", `${contexto} deveria declarar fonte, evidencia ou confianca.`, "aviso", bloco.intervalo, "Claims de nao-ficcao precisam de rastreio para diferenciar argumento, opiniao e evidencia."));
1346
- }
1347
- if (tipo === "style_rule") {
1348
- const guardrails = coletarSubblocosPorNomes(bloco, ["forbidden", "proibido", "avoid", "evitar", "echo", "ecos"]);
1349
- const tolerancia = localizarBlocoPorNomes(bloco, "tolerancia", "tolerance");
1350
- if (guardrails.length === 0 && !tolerancia && bloco.campos.length === 0 && bloco.linhas.length === 0) {
1351
- diagnosticos.push(criarDiagnostico("SEM125", `${contexto} precisa declarar proibicoes, ecos, tolerancia ou preferencias.`, "erro", bloco.intervalo, "Use proibido/forbidden para cliches, echo/ecos para repeticao, evitar/avoid para muletas ou tolerancia para limites."));
1352
- }
1353
- for (const guardrail of guardrails) {
1354
- validarSubblocoNaoVazio(guardrail, diagnosticos, "SEM126", contexto);
1355
- }
1356
- const vistos = new Set();
1357
- for (const guardrail of guardrails) {
1358
- for (const valor of valoresDeclarativos(guardrail)) {
1359
- const chave = valor.toLowerCase();
1360
- if (vistos.has(chave)) {
1361
- diagnosticos.push(criarDiagnostico("SEM127", `${contexto} repetiu o guardrail de estilo "${valor}".`, "aviso", guardrail.intervalo, "Remova duplicatas para manter a regra de estilo enxuta."));
1362
- }
1363
- vistos.add(chave);
1210
+ for (const entity of modulo.entities) {
1211
+ const fields = localizarBloco(entity.corpo, "fields");
1212
+ for (const campo of fields?.campos ?? []) {
1213
+ if (!campoStatusTexto(campo)) {
1214
+ continue;
1364
1215
  }
1216
+ diagnosticos.push(criarDiagnostico("SEM100", `Entity "${entity.nome}" declara "${campo.nome}: Texto" enquanto o modulo tem state com transitions.`, "aviso", campo.intervalo, "Prefira enum/status de dominio para impedir que a IA invente estados fora do ciclo declarado."));
1365
1217
  }
1366
1218
  }
1367
1219
  }
1368
- function styleRuleTemProibicoes(bloco) {
1369
- return coletarSubblocosPorNomes(bloco, ["forbidden", "proibido", "avoid", "evitar"]).some((guardrail) => valoresDeclarativos(guardrail).length > 0);
1370
- }
1371
- function flowReferenciaAgent(flow, agentsConhecidos) {
1372
- for (const linha of flow.corpo.linhas) {
1373
- const etapa = parsearEtapaFlow(linha.conteudo);
1374
- if (etapa?.task && referenciaAgentConhecida(etapa.task, agentsConhecidos)) {
1375
- return true;
1376
- }
1377
- }
1378
- const task = localizarCampo(flow.corpo, "task")?.valor;
1379
- return Boolean(task && referenciaAgentConhecida(task, agentsConhecidos));
1380
- }
1381
- function validarAuthorSensivel(modulo, agentsConhecidos, diagnosticos) {
1382
- if (modulo.authorBlocks.length === 0 || !modulo.authorBlocks.some(blocoAuthorMarcaSensivel)) {
1383
- return;
1384
- }
1385
- const obras = coletarAuthorBlocksPorTipo(modulo, ["book", "work"]);
1386
- const audiences = coletarAuthorBlocksPorTipo(modulo, ["audience"]);
1387
- const claims = coletarAuthorBlocksPorTipo(modulo, ["claim"]);
1388
- const sources = coletarAuthorBlocksPorTipo(modulo, ["source"]);
1389
- const styleRules = coletarAuthorBlocksPorTipo(modulo, ["style_rule"]);
1390
- const primeiroBlocoSensivel = modulo.authorBlocks.find(blocoAuthorMarcaSensivel) ?? modulo.authorBlocks[0];
1391
- const intervaloBase = primeiroBlocoSensivel?.intervalo;
1392
- if (obras.length === 0) {
1393
- diagnosticos.push(criarDiagnostico("SEM132", "Author sensivel precisa declarar book/work para ancorar proposito, tipo, publico e limites da obra.", "erro", intervaloBase, "Declare book ou work antes de pedir para a IA criar ou editar material sensivel."));
1394
- }
1395
- if (audiences.length === 0) {
1396
- diagnosticos.push(criarDiagnostico("SEM133", "Author sensivel precisa declarar audience/publico antes da IA escrever ou editar.", "erro", intervaloBase, "Declare se o livro fala com pais, educadores, pessoas autistas, profissionais, publico geral ou outro grupo."));
1397
- }
1398
- if (claims.length === 0) {
1399
- diagnosticos.push(criarDiagnostico("SEM134", "Author sensivel precisa declarar claim para separar fato, argumento, opiniao e promessa editorial.", "erro", intervaloBase, "Declare ao menos um claim para qualquer tese factual que a IA deva sustentar ou revisar."));
1400
- }
1401
- if (sources.length === 0) {
1402
- diagnosticos.push(criarDiagnostico("SEM135", "Author sensivel precisa declarar source/fonte rastreavel.", "erro", intervaloBase, "Declare source para DSM, CID, artigo, livro, guia clinico, entrevista, experiencia autoral ou outra fonte aceita."));
1403
- }
1404
- if (styleRules.length === 0) {
1405
- diagnosticos.push(criarDiagnostico("SEM136", "Author sensivel precisa declarar style_rule para bloquear cliche, infantilizacao, generalizacao e linguagem ruim.", "erro", intervaloBase, "Declare style_rule com proibido/evitar/ecos/tolerancia antes da IA gerar texto."));
1406
- }
1407
- if (modulo.agents.length === 0) {
1408
- diagnosticos.push(criarDiagnostico("SEM137", "Author sensivel precisa declarar agent governado para revisao, fonte, sensibilidade ou estilo.", "erro", intervaloBase, "Declare ao menos um agent com role, goal, tools, memory e policy."));
1409
- }
1410
- if (!modulo.flows.some((flow) => flowReferenciaAgent(flow, agentsConhecidos))) {
1411
- diagnosticos.push(criarDiagnostico("SEM138", "Author sensivel precisa declarar flow chamando agent governado.", "erro", intervaloBase, "Modele etapas como escrever, checar fonte, revisar linguagem, validar sensibilidade e preservar canon."));
1412
- }
1413
- for (const claim of claims) {
1414
- if (!localizarCampo(claim, "source", "fonte", "evidencia")) {
1415
- diagnosticos.push(criarDiagnostico("SEM139", `Claim sensivel "${claim.nome ?? "claim"}" precisa declarar source/fonte/evidencia.`, "erro", claim.intervalo, "Toda afirmacao factual sensivel precisa apontar fonte ou evidencia antes da IA usar no texto."));
1416
- }
1417
- if (!localizarCampo(claim, "confidence", "confianca")) {
1418
- diagnosticos.push(criarDiagnostico("SEM140", `Claim sensivel "${claim.nome ?? "claim"}" precisa declarar confidence/confianca.`, "erro", claim.intervalo, "Declare o nivel de confianca para a IA diferenciar fato forte, consenso limitado e hipotese."));
1419
- }
1420
- }
1421
- for (const styleRule of styleRules) {
1422
- if (!styleRuleTemProibicoes(styleRule)) {
1423
- diagnosticos.push(criarDiagnostico("SEM141", `Style_rule sensivel "${styleRule.nome ?? "style_rule"}" precisa declarar proibido/evitar verificavel.`, "erro", styleRule.intervalo, "Inclua termos, frases ou abordagens proibidas, como infantilizacao, generalizacao, promessa clinica ou cliche."));
1424
- }
1425
- }
1426
- }
1427
- function validarAgent(agent, diagnosticos) {
1428
- const nome = agent.nome ?? "agent";
1429
- if (!localizarCampo(agent, "role", "papel") && !localizarCampo(agent, "goal", "objetivo")) {
1430
- diagnosticos.push(criarDiagnostico("SEM128", `Agent "${nome}" precisa declarar role/papel ou goal/objetivo.`, "erro", agent.intervalo, "Agente sem objetivo vira prompt solto. Declare role ou goal."));
1431
- }
1432
- const tools = localizarBlocoPorNomes(agent, "tools", "ferramentas");
1433
- if (!tools || valoresDeclarativos(tools).length === 0) {
1434
- diagnosticos.push(criarDiagnostico("SEM129", `Agent "${nome}" precisa declarar tools/ferramentas.`, "erro", agent.intervalo, "Declare as ferramentas que o agente pode usar para limitar acao e dar rastreabilidade."));
1435
- }
1436
- const policy = localizarBlocoPorNomes(agent, "policy", "politica");
1437
- if (!policy || valoresDeclarativos(policy).length === 0) {
1438
- diagnosticos.push(criarDiagnostico("SEM130", `Agent "${nome}" precisa declarar policy/politica.`, "erro", agent.intervalo, "Declare limites como nao_reescrever_sem_aprovacao, citar_trechos_afetados ou atualizar_docs_apos_edicao."));
1439
- }
1440
- const memory = localizarBlocoPorNomes(agent, "memory", "memoria");
1441
- if (!memory || valoresDeclarativos(memory).length === 0) {
1442
- diagnosticos.push(criarDiagnostico("SEM131", `Agent "${nome}" deveria declarar memory/memoria para evitar contexto improvisado.`, "aviso", agent.intervalo, "Declare quais memorias, docs ou contratos o agente deve consultar antes de agir."));
1443
- }
1444
- }
1445
1220
  export function criarContextoLocal(modulo) {
1446
1221
  const simbolos = new Map();
1447
1222
  const tiposConhecidos = new Set(TIPOS_PRIMITIVOS);
1448
1223
  const tasksConhecidas = new Set();
1449
- const agentsConhecidos = new Set();
1450
1224
  const tarefasDetalhadas = new Map();
1451
1225
  const statesConhecidos = new Map();
1452
1226
  const enumsConhecidos = new Map();
@@ -1459,10 +1233,6 @@ export function criarContextoLocal(modulo) {
1459
1233
  tasksConhecidas.add(nome);
1460
1234
  return;
1461
1235
  }
1462
- if (categoria === "agent") {
1463
- agentsConhecidos.add(nome);
1464
- return;
1465
- }
1466
1236
  if (categoria !== "database") {
1467
1237
  tiposConhecidos.add(nome);
1468
1238
  }
@@ -1487,16 +1257,6 @@ export function criarContextoLocal(modulo) {
1487
1257
  for (const route of modulo.routes) {
1488
1258
  registrar(route.nome, "route");
1489
1259
  }
1490
- for (const authorBlock of modulo.authorBlocks) {
1491
- if (authorBlock.nome && TIPOS_AUTHOR_PROFILE.has(authorBlock.palavraChave)) {
1492
- registrar(authorBlock.nome, authorBlock.palavraChave);
1493
- }
1494
- }
1495
- for (const agent of modulo.agents) {
1496
- if (agent.nome) {
1497
- registrar(agent.nome, "agent");
1498
- }
1499
- }
1500
1260
  for (const worker of modulo.workers) {
1501
1261
  if (worker.nome) {
1502
1262
  registrar(worker.nome, "worker");
@@ -1557,7 +1317,6 @@ export function criarContextoLocal(modulo) {
1557
1317
  simbolos,
1558
1318
  tiposConhecidos,
1559
1319
  tasksConhecidas,
1560
- agentsConhecidos,
1561
1320
  tarefasDetalhadas,
1562
1321
  statesConhecidos,
1563
1322
  modulosImportados: [],
@@ -1585,6 +1344,14 @@ function validarTask(task, tiposConhecidos, statesConhecidos, diagnosticos) {
1585
1344
  }
1586
1345
  const entradasConhecidas = new Set(task.input?.campos.map((campo) => campo.nome) ?? []);
1587
1346
  const saidasConhecidas = new Set(task.output?.campos.map((campo) => campo.nome) ?? []);
1347
+ if (task.state) {
1348
+ for (const campo of task.output?.campos ?? []) {
1349
+ if (!campoStatusTexto(campo)) {
1350
+ continue;
1351
+ }
1352
+ diagnosticos.push(criarDiagnostico("SEM100", `Task "${task.nome}" declara output "${campo.nome}: Texto" enquanto governa state.`, "aviso", campo.intervalo, "Use um enum/status de dominio no output para manter a transicao rastreavel para IA."));
1353
+ }
1354
+ }
1588
1355
  if (task.rules) {
1589
1356
  validarExpressoesDeclaradas(task.rules.linhas, diagnosticos, {
1590
1357
  codigoErroSintaxe: "SEM021",
@@ -1615,6 +1382,7 @@ function validarTask(task, tiposConhecidos, statesConhecidos, diagnosticos) {
1615
1382
  continue;
1616
1383
  }
1617
1384
  validarCasoTeste(task, bloco, diagnosticos);
1385
+ validarTesteSemanticoForte(task, bloco, diagnosticos);
1618
1386
  }
1619
1387
  }
1620
1388
  if (task.guarantees && task.output) {
@@ -1638,6 +1406,32 @@ function validarTask(task, tiposConhecidos, statesConhecidos, diagnosticos) {
1638
1406
  }
1639
1407
  validarVinculoEstadoDaTask(task, statesConhecidos, diagnosticos);
1640
1408
  }
1409
+ export function validarTesteSemanticoForte(task, caso, diagnosticos) {
1410
+ if (!taskEhSensivel(task) || !caso.expect) {
1411
+ return;
1412
+ }
1413
+ const possuiErroEsperado = Boolean(caso.error
1414
+ && (caso.error.campos.length > 0 || caso.error.linhas.length > 0 || caso.error.blocos.length > 0));
1415
+ if (possuiErroEsperado) {
1416
+ return;
1417
+ }
1418
+ const camposExpect = caso.expect.campos.filter((campo) => campo.nome !== "");
1419
+ const somenteSucesso = camposExpect.length === 1
1420
+ && camposExpect[0]?.nome === "sucesso"
1421
+ && caso.expect.linhas.length === 0
1422
+ && caso.expect.blocos.length === 0;
1423
+ if (!somenteSucesso) {
1424
+ return;
1425
+ }
1426
+ diagnosticos.push(criarDiagnostico("SEM102", `Caso de teste "${caso.nome}" da task sensivel "${task.nome}" valida apenas sucesso.`, "aviso", caso.expect.intervalo, "Inclua algum output, erro esperado ou garantia observavel para a IA nao tratar 'sucesso' como contrato completo."));
1427
+ }
1428
+ export function emitirDiagnosticosContratoFrouxo(task, diagnosticos) {
1429
+ for (const bloco of task.tests?.blocos ?? []) {
1430
+ if (bloco.tipo === "caso_teste") {
1431
+ validarTesteSemanticoForte(task, bloco, diagnosticos);
1432
+ }
1433
+ }
1434
+ }
1641
1435
  function validarCasoTeste(task, caso, diagnosticos) {
1642
1436
  if (!caso.given) {
1643
1437
  diagnosticos.push(criarDiagnostico("SEM008", `Caso de teste "${caso.nome}" da task "${task.nome}" precisa declarar given.`, "erro", caso.intervalo));
@@ -1651,7 +1445,6 @@ export function analisarSemantica(modulo, opcoes = {}) {
1651
1445
  const simbolos = new Map();
1652
1446
  const tiposConhecidos = new Set(TIPOS_PRIMITIVOS);
1653
1447
  const tasksConhecidas = new Set();
1654
- const agentsConhecidos = new Set();
1655
1448
  const tarefasDetalhadas = new Map();
1656
1449
  const statesConhecidos = new Map();
1657
1450
  const modulosImportados = [];
@@ -1687,9 +1480,6 @@ export function analisarSemantica(modulo, opcoes = {}) {
1687
1480
  for (const task of contextoImportado.tasksConhecidas) {
1688
1481
  tasksConhecidas.add(task);
1689
1482
  }
1690
- for (const agent of contextoImportado.agentsConhecidos) {
1691
- agentsConhecidos.add(agent);
1692
- }
1693
1483
  for (const [nomeTask, detalhesTask] of contextoImportado.tarefasDetalhadas) {
1694
1484
  tarefasDetalhadas.set(nomeTask, {
1695
1485
  input: detalhesTask.input.map((campo) => ({ ...campo, modificadores: [...campo.modificadores] })),
@@ -1719,10 +1509,6 @@ export function analisarSemantica(modulo, opcoes = {}) {
1719
1509
  tasksConhecidas.add(nome);
1720
1510
  return;
1721
1511
  }
1722
- if (categoria === "agent") {
1723
- agentsConhecidos.add(nome);
1724
- return;
1725
- }
1726
1512
  if (categoria !== "database") {
1727
1513
  tiposConhecidos.add(nome);
1728
1514
  }
@@ -1747,16 +1533,6 @@ export function analisarSemantica(modulo, opcoes = {}) {
1747
1533
  for (const route of modulo.routes) {
1748
1534
  registrar(route.nome, "route", route.intervalo);
1749
1535
  }
1750
- for (const authorBlock of modulo.authorBlocks) {
1751
- if (authorBlock.nome && TIPOS_AUTHOR_PROFILE.has(authorBlock.palavraChave)) {
1752
- registrar(authorBlock.nome, authorBlock.palavraChave, authorBlock.intervalo);
1753
- }
1754
- }
1755
- for (const agent of modulo.agents) {
1756
- if (agent.nome) {
1757
- registrar(agent.nome, "agent", agent.intervalo);
1758
- }
1759
- }
1760
1536
  for (const worker of modulo.workers) {
1761
1537
  if (worker.nome) {
1762
1538
  registrar(worker.nome, "worker", worker.intervalo);
@@ -1834,7 +1610,7 @@ export function analisarSemantica(modulo, opcoes = {}) {
1834
1610
  validarTask(task, tiposConhecidos, statesConhecidos, diagnosticos);
1835
1611
  }
1836
1612
  for (const flow of modulo.flows) {
1837
- validarFlow(flow, tasksConhecidas, agentsConhecidos, tarefasDetalhadas, diagnosticos);
1613
+ validarFlow(flow, tasksConhecidas, tarefasDetalhadas, diagnosticos);
1838
1614
  }
1839
1615
  for (const route of modulo.routes) {
1840
1616
  validarRoute(route, tasksConhecidas, tarefasDetalhadas, diagnosticos);
@@ -1864,13 +1640,6 @@ export function analisarSemantica(modulo, opcoes = {}) {
1864
1640
  for (const policy of modulo.policies) {
1865
1641
  validarSuperficie(policy, "policy", tasksConhecidas, tiposConhecidos, diagnosticos);
1866
1642
  }
1867
- for (const authorBlock of modulo.authorBlocks) {
1868
- validarAuthorBlock(authorBlock, diagnosticos);
1869
- }
1870
- for (const agent of modulo.agents) {
1871
- validarAgent(agent, diagnosticos);
1872
- }
1873
- validarAuthorSensivel(modulo, agentsConhecidos, diagnosticos);
1874
1643
  for (const database of modulo.databases) {
1875
1644
  validarDatabase(database, diagnosticos);
1876
1645
  }
@@ -1893,13 +1662,13 @@ export function analisarSemantica(modulo, opcoes = {}) {
1893
1662
  for (const state of modulo.states) {
1894
1663
  validarState(state, tiposConhecidos, enumsConhecidos, diagnosticos);
1895
1664
  }
1665
+ validarStatusTextoComState(modulo, diagnosticos);
1896
1666
  return {
1897
1667
  contexto: {
1898
1668
  modulo: modulo.nome,
1899
1669
  simbolos,
1900
1670
  tiposConhecidos,
1901
1671
  tasksConhecidas,
1902
- agentsConhecidos,
1903
1672
  tarefasDetalhadas,
1904
1673
  statesConhecidos,
1905
1674
  modulosImportados,