@semacode/cli 4.1.2 → 4.2.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 (39) hide show
  1. package/dist/agentBootstrap.d.ts +4 -0
  2. package/dist/agentBootstrap.js +44 -0
  3. package/dist/agentContext.d.ts +1 -1
  4. package/dist/agentContext.js +5 -5
  5. package/dist/agentContextPack.js +22 -31
  6. package/dist/agentEntryPoints.d.ts +1 -3
  7. package/dist/agentEntryPoints.js +16 -262
  8. package/dist/cliArgs.js +1 -0
  9. package/dist/cliGrammar.js +8 -4
  10. package/dist/cliHelpTexto.js +5 -4
  11. package/dist/comandoSessao.d.ts +0 -33
  12. package/dist/comandoSessao.js +71 -70
  13. package/dist/contextBudget.d.ts +15 -0
  14. package/dist/contextBudget.js +64 -0
  15. package/dist/docs.part01.js +0 -1
  16. package/dist/docs.part02.js +11 -23
  17. package/dist/docsRelations.d.ts +2 -0
  18. package/dist/docsRelations.js +83 -0
  19. package/dist/geracaoCore.d.ts +1 -1
  20. package/dist/index.part07.d.ts +1 -0
  21. package/dist/index.part07.js +54 -31
  22. package/dist/index.part08.js +3 -3
  23. package/dist/indexPack.d.ts +1 -0
  24. package/dist/indexPack.js +1 -1
  25. package/dist/initCommand.d.ts +1 -0
  26. package/dist/initCommand.js +10 -1
  27. package/dist/sessionContext.d.ts +13 -0
  28. package/dist/sessionContext.js +41 -0
  29. package/dist/verificacaoPythonLocal.d.ts +17 -0
  30. package/dist/verificacaoPythonLocal.js +46 -0
  31. package/docs/ai-integration.md +5 -13
  32. package/docs/ai-workflow.md +8 -6
  33. package/docs/commands.md +1 -1
  34. package/docs/documentation.md +33 -0
  35. package/docs/testing.md +18 -0
  36. package/exemplos/python_verificacao.sema +68 -68
  37. package/node_modules/@sema/gerador-python/dist/runtime.js +65 -65
  38. package/package.json +1 -1
  39. package/skills/sema/SKILL.md +82 -169
@@ -6,6 +6,7 @@ import pacoteCli from "../package.json" with { type: "json" };
6
6
  import { compilarCodigo, formatarDiagnosticos, lerArquivoTexto, temErros, } from "@sema/nucleo";
7
7
  import { carregarProjeto, resolverAlvosVerificacao, } from "./projeto.js";
8
8
  import { SCHEMA_CACHE_VERIFICACAO, calcularChaveVerificacao, carregarCacheVerificacao, gravarCacheVerificacao, } from "./verificacaoCache.js";
9
+ import { erroModoPreservacao, prepararImplementacaoPythonLocal, evidenciaPython } from "./verificacaoPythonLocal.js";
9
10
  const FONTES_POR_ALVO_SUPORTADO = {
10
11
  typescript: ["typescript", "javascript"],
11
12
  javascript: ["typescript", "javascript"],
@@ -210,7 +211,7 @@ export function imprimirResumoVerificacao(resumos) {
210
211
  totalArquivos += alvo.arquivosGerados;
211
212
  totalTestes += alvo.quantidadeTestes;
212
213
  totalAlvos += 1;
213
- console.log(` alvo=${alvo.alvo} framework=${alvo.framework} estrutura=${alvo.estrutura} status=${alvo.sucesso ? "ok" : "falhou"} arquivos=${alvo.arquivosGerados} testes=${alvo.quantidadeTestes}${alvo.testesExecutados ? "" : " (skip)"} saida=${alvo.pastaSaida}`);
214
+ console.log(` alvo=${alvo.alvo} framework=${alvo.framework} estrutura=${alvo.estrutura} status=${alvo.sucesso ? "ok" : "falhou"} arquivos=${alvo.arquivosGerados} testes=${alvo.quantidadeTestes}${alvo.testesExecutados ? "" : " (skip)"}${alvo.tipoEvidencia ? ` evidencia=${alvo.tipoEvidencia} (não comprova produção)` : ""} saida=${alvo.pastaSaida}`);
214
215
  }
215
216
  }
216
217
  console.log(`Totais: modulos=${resumos.length} alvos=${totalAlvos} arquivos=${totalArquivos} testes=${totalTestes}`);
@@ -240,6 +241,11 @@ export async function comandoVerificar(entrada, baseSaida, cwd = process.cwd(),
240
241
  ...resolverConfiguracaoVerificacaoPorAlvo(alvo, contextoProjeto.configCarregada),
241
242
  }));
242
243
  const incompatibilidade = configuracoesAlvo.find((item) => item.incompatibilidade);
244
+ const erroPreservacao = erroModoPreservacao(opcoes.preservarImplementacao, configuracoesAlvo);
245
+ if (erroPreservacao) {
246
+ console.error(erroPreservacao);
247
+ return 1;
248
+ }
243
249
  if (incompatibilidade?.incompatibilidade) {
244
250
  console.error(incompatibilidade.incompatibilidade);
245
251
  return 1;
@@ -272,7 +278,7 @@ export async function comandoVerificar(entrada, baseSaida, cwd = process.cwd(),
272
278
  estrutura,
273
279
  conteudoContrato,
274
280
  });
275
- const emCache = opcoes.semCache ? undefined : await carregarCacheVerificacao(chave, pastaAlvo);
281
+ const emCache = opcoes.semCache || opcoes.preservarImplementacao ? undefined : await carregarCacheVerificacao(chave, pastaAlvo);
276
282
  if (emCache) {
277
283
  resumoModulo.alvos.push({
278
284
  alvo,
@@ -294,21 +300,27 @@ export async function comandoVerificar(entrada, baseSaida, cwd = process.cwd(),
294
300
  continue;
295
301
  }
296
302
  const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
297
- const escrita = await escreverArquivos(pastaAlvo, arquivos, { artefatoGerado: true });
303
+ const preparacao = opcoes.preservarImplementacao ? await prepararImplementacaoPythonLocal(pastaAlvo, arquivos) : { arquivosParaEscrita: arquivos };
304
+ if (preparacao.erro) {
305
+ console.error(preparacao.erro);
306
+ return 1;
307
+ }
308
+ const escrita = await escreverArquivos(pastaAlvo, preparacao.arquivosParaEscrita, { artefatoGerado: true });
298
309
  artefatosGeradosAcimaDoLimite.push(...escrita.artefatosGeradosAcimaDoLimite);
299
310
  const { execucao, testesExecutados } = executarTestesParaVerificacao(alvo, pastaAlvo, arquivos, framework);
300
- await gravarCacheVerificacao({
301
- schemaVersion: SCHEMA_CACHE_VERIFICACAO,
302
- chave,
303
- versaoCli: pacoteCli.version,
304
- alvo,
305
- modulo: ir.nome,
306
- sucesso: execucao.codigoSaida === 0,
307
- quantidadeTestes: execucao.quantidadeTestes,
308
- testesExecutados,
309
- arquivosGerados: arquivos.map((arquivo) => arquivo.caminhoRelativo),
310
- geradoEm: new Date().toISOString(),
311
- });
311
+ if (!opcoes.preservarImplementacao)
312
+ await gravarCacheVerificacao({
313
+ schemaVersion: SCHEMA_CACHE_VERIFICACAO,
314
+ chave,
315
+ versaoCli: pacoteCli.version,
316
+ alvo,
317
+ modulo: ir.nome,
318
+ sucesso: execucao.codigoSaida === 0,
319
+ quantidadeTestes: execucao.quantidadeTestes,
320
+ testesExecutados,
321
+ arquivosGerados: arquivos.map((arquivo) => arquivo.caminhoRelativo),
322
+ geradoEm: new Date().toISOString(),
323
+ });
312
324
  resumoModulo.alvos.push({
313
325
  alvo,
314
326
  arquivosGerados: arquivos.length,
@@ -319,7 +331,7 @@ export async function comandoVerificar(entrada, baseSaida, cwd = process.cwd(),
319
331
  estrutura,
320
332
  testesExecutados,
321
333
  origem: "executado",
322
- ...(alvo === "python" ? { tipoEvidencia: "andaime_demonstrativo", implementacaoExternaExecutada: false } : {}),
334
+ ...(alvo === "python" ? evidenciaPython(opcoes.preservarImplementacao) : {}),
323
335
  });
324
336
  if (execucao.codigoSaida !== 0) {
325
337
  imprimirResumoVerificacao([...resumos, resumoModulo]);
@@ -372,6 +384,11 @@ export async function comandoVerificarJson(entrada, baseSaida, cwd = process.cwd
372
384
  ...resolverConfiguracaoVerificacaoPorAlvo(alvo, contextoProjeto.configCarregada),
373
385
  }));
374
386
  const incompatibilidade = configuracoesAlvo.find((item) => item.incompatibilidade);
387
+ const erroPreservacao = erroModoPreservacao(opcoes.preservarImplementacao, configuracoesAlvo);
388
+ if (erroPreservacao) {
389
+ console.log(JSON.stringify({ comando: "verificar", sucesso: false, erro: erroPreservacao, modulos: [], totais: { modulos: 0, alvos: 0, arquivos: 0, testes: 0 } }));
390
+ return 1;
391
+ }
375
392
  if (incompatibilidade?.incompatibilidade) {
376
393
  console.log(JSON.stringify({
377
394
  comando: "verificar",
@@ -418,7 +435,7 @@ export async function comandoVerificarJson(entrada, baseSaida, cwd = process.cwd
418
435
  estrutura,
419
436
  conteudoContrato,
420
437
  });
421
- const emCache = opcoes.semCache ? undefined : await carregarCacheVerificacao(chave, pastaAlvo);
438
+ const emCache = opcoes.semCache || opcoes.preservarImplementacao ? undefined : await carregarCacheVerificacao(chave, pastaAlvo);
422
439
  if (emCache) {
423
440
  resumoModulo.alvos.push({
424
441
  alvo,
@@ -439,21 +456,27 @@ export async function comandoVerificarJson(entrada, baseSaida, cwd = process.cwd
439
456
  continue;
440
457
  }
441
458
  const arquivos = aplicarEstruturaSaida(gerarArquivosPorAlvo(ir, alvo, framework), ir, estrutura);
442
- const escrita = await escreverArquivos(pastaAlvo, arquivos, { artefatoGerado: true });
459
+ const preparacao = opcoes.preservarImplementacao ? await prepararImplementacaoPythonLocal(pastaAlvo, arquivos) : { arquivosParaEscrita: arquivos };
460
+ if (preparacao.erro) {
461
+ console.log(JSON.stringify({ comando: "verificar", sucesso: false, erro: preparacao.erro, modulos: resumos, totais: { modulos: resumos.length, alvos: 0, arquivos: 0, testes: 0 } }));
462
+ return 1;
463
+ }
464
+ const escrita = await escreverArquivos(pastaAlvo, preparacao.arquivosParaEscrita, { artefatoGerado: true });
443
465
  artefatosGeradosAcimaDoLimite.push(...escrita.artefatosGeradosAcimaDoLimite);
444
466
  const { execucao, testesExecutados } = executarTestesParaVerificacao(alvo, pastaAlvo, arquivos, framework, true);
445
- await gravarCacheVerificacao({
446
- schemaVersion: SCHEMA_CACHE_VERIFICACAO,
447
- chave,
448
- versaoCli: pacoteCli.version,
449
- alvo,
450
- modulo: ir.nome,
451
- sucesso: execucao.codigoSaida === 0,
452
- quantidadeTestes: execucao.quantidadeTestes,
453
- testesExecutados,
454
- arquivosGerados: arquivos.map((arquivo) => arquivo.caminhoRelativo),
455
- geradoEm: new Date().toISOString(),
456
- });
467
+ if (!opcoes.preservarImplementacao)
468
+ await gravarCacheVerificacao({
469
+ schemaVersion: SCHEMA_CACHE_VERIFICACAO,
470
+ chave,
471
+ versaoCli: pacoteCli.version,
472
+ alvo,
473
+ modulo: ir.nome,
474
+ sucesso: execucao.codigoSaida === 0,
475
+ quantidadeTestes: execucao.quantidadeTestes,
476
+ testesExecutados,
477
+ arquivosGerados: arquivos.map((arquivo) => arquivo.caminhoRelativo),
478
+ geradoEm: new Date().toISOString(),
479
+ });
457
480
  resumoModulo.alvos.push({
458
481
  alvo,
459
482
  arquivosGerados: arquivos.length,
@@ -464,7 +487,7 @@ export async function comandoVerificarJson(entrada, baseSaida, cwd = process.cwd
464
487
  estrutura,
465
488
  testesExecutados,
466
489
  origem: "executado",
467
- ...(alvo === "python" ? { tipoEvidencia: "andaime_demonstrativo", implementacaoExternaExecutada: false } : {}),
490
+ ...(alvo === "python" ? evidenciaPython(opcoes.preservarImplementacao) : {}),
468
491
  });
469
492
  resumoModulo.saidaTestes.push({ alvo, stdout: execucao.saidaPadrao, stderr: execucao.saidaErro });
470
493
  if (execucao.codigoSaida !== 0) {
@@ -34,7 +34,7 @@ export async function principal() {
34
34
  let codigoSaida = 0;
35
35
  switch (comando) {
36
36
  case "iniciar":
37
- codigoSaida = await comandoIniciar(cwd, normalizarTemplateIniciar(obterOpcao(resto, "--template")), { force: possuiFlag(resto, "--force"), exemplosCompletos: possuiFlag(resto, "--com-exemplos") });
37
+ codigoSaida = await comandoIniciar(cwd, normalizarTemplateIniciar(obterOpcao(resto, "--template")), { force: possuiFlag(resto, "--force"), exemplosCompletos: possuiFlag(resto, "--com-exemplos"), contextoArgs: resto });
38
38
  break;
39
39
  case "sessao": {
40
40
  const { comandoSessao } = await import("./comandoSessao.js");
@@ -105,8 +105,8 @@ export async function principal() {
105
105
  break;
106
106
  case "verificar":
107
107
  codigoSaida = possuiFlag(resto, "--json")
108
- ? await comandoVerificarJson(posicionais[0], resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)), cwd, { alvo: obterOpcao(resto, "--alvo"), semCache: possuiFlag(resto, "--sem-cache") })
109
- : await comandoVerificar(posicionais[0], resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)), cwd, { alvo: obterOpcao(resto, "--alvo"), semCache: possuiFlag(resto, "--sem-cache") });
108
+ ? await comandoVerificarJson(posicionais[0], resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)), cwd, { alvo: obterOpcao(resto, "--alvo"), semCache: possuiFlag(resto, "--sem-cache"), preservarImplementacao: possuiFlag(resto, "--preservar-implementacao") })
109
+ : await comandoVerificar(posicionais[0], resolverSaidaPadrao(obterOpcao(resto, "--saida", "./.tmp/sema-verificar"), "typescript", await carregarConfiguracaoProjeto(posicionais[0] ? path.resolve(cwd, posicionais[0]) : cwd)), cwd, { alvo: obterOpcao(resto, "--alvo"), semCache: possuiFlag(resto, "--sem-cache"), preservarImplementacao: possuiFlag(resto, "--preservar-implementacao") });
110
110
  break;
111
111
  case "inspecionar":
112
112
  codigoSaida = await comandoInspecionar(posicionais[0], possuiFlag(resto, "--json"), cwd, resto);
@@ -50,5 +50,6 @@ export declare function selecionarIndiceContexto(input: {
50
50
  mode?: string;
51
51
  drift?: string;
52
52
  sourceIndexChars?: number;
53
+ maximoModulos?: number;
53
54
  }): IndexPack;
54
55
  export {};
package/dist/indexPack.js CHANGED
@@ -84,7 +84,7 @@ export function selecionarIndiceContexto(input) {
84
84
  .map((modulo) => compactarModulo(modulo, requestTokens, projetarResumoInteiro))
85
85
  .filter((item) => item !== null)
86
86
  .sort((a, b) => b.relevanceScore - a.relevanceScore || a.module.localeCompare(b.module, "pt-BR"))
87
- .slice(0, projetarResumoInteiro ? input.modulos.length : 8);
87
+ .slice(0, input.maximoModulos ?? (projetarResumoInteiro ? input.modulos.length : 8));
88
88
  const base = {
89
89
  schema: "sema.ai.index-pack/v1",
90
90
  selection,
@@ -2,5 +2,6 @@ import { type TemplateIniciar } from "./initTemplatesBase.js";
2
2
  export declare function comandoIniciar(cwd: string, template: TemplateIniciar, opcoes?: {
3
3
  force?: boolean;
4
4
  exemplosCompletos?: boolean;
5
+ contextoArgs?: string[];
5
6
  }): Promise<number>;
6
7
  export declare function comandoInstalarExemplos(emJson: boolean): Promise<number>;
@@ -1,5 +1,6 @@
1
1
  // SEMA-GOVERNED: sema.produto.cli_init_templates, sema.produto.escrita_segura_workspace
2
2
  // Descrição: inicializa projetos preservando arquivos existentes e bloqueando escapes do workspace.
3
+ import { resolverPerfilContexto, salvarPerfilContexto, ARQUIVO_PERFIL_CONTEXTO, PERGUNTA_CONTEXTO } from "./contextBudget.js";
3
4
  import * as fs from "node:fs";
4
5
  import { readFile } from "node:fs/promises";
5
6
  import path from "node:path";
@@ -57,8 +58,14 @@ const EXEMPLOS_STARTER_INICIAR = new Set([
57
58
  "exemplos/autenticacao.sema",
58
59
  ]);
59
60
  export async function comandoIniciar(cwd, template, opcoes = {}) {
60
- const arquivosCompletos = arquivosTemplateIniciar(template);
61
61
  const configAncestral = await carregarConfiguracaoProjeto(cwd);
62
+ const basePerfil = configAncestral?.baseDiretorio ?? cwd;
63
+ const perfilContexto = await resolverPerfilContexto(basePerfil, opcoes.contextoArgs ?? []);
64
+ if (!perfilContexto) {
65
+ console.log(JSON.stringify({ comando: "iniciar", sucesso: false, status: "configuracao_necessaria", pergunta: PERGUNTA_CONTEXTO, proximoPasso: "Repita iniciar com --janela-contexto <tokens>; nenhum arquivo foi criado." }));
66
+ return 1;
67
+ }
68
+ const arquivosCompletos = arquivosTemplateIniciar(template);
62
69
  const subpastaGovernada = Boolean(configAncestral
63
70
  && path.resolve(configAncestral.baseDiretorio) !== path.resolve(cwd));
64
71
  // Em subpasta de workspace ja governado o config do template e omitido: a
@@ -84,6 +91,7 @@ export async function comandoIniciar(cwd, template, opcoes = {}) {
84
91
  ]);
85
92
  const caminhosTemplate = new Set(arquivos.map((arquivo) => arquivo.caminhoRelativo));
86
93
  const destinos = await validarDestinosEscritaWorkspace(cwd, [
94
+ ...(basePerfil === cwd ? [ARQUIVO_PERFIL_CONTEXTO] : []),
87
95
  ...caminhosTemplate,
88
96
  ...exemplosIniciar.map((arquivo) => arquivo.caminhoRelativo),
89
97
  ...ARQUIVOS_RESUMO_PROJETO_IA,
@@ -95,6 +103,7 @@ export async function comandoIniciar(cwd, template, opcoes = {}) {
95
103
  const arquivosParaEscrever = opcoes.force
96
104
  ? arquivos
97
105
  : arquivos.filter((arquivo) => !existentes.has(arquivo.caminhoRelativo));
106
+ await salvarPerfilContexto(basePerfil, perfilContexto);
98
107
  await escreverArquivos(cwd, arquivosParaEscrever, { inserirCabecalhoGovernado: true });
99
108
  const exemplos = await materializarExemplosOficiais(cwd, true, opcoes.exemplosCompletos ? undefined : EXEMPLOS_STARTER_INICIAR);
100
109
  if (!exemplos.sucesso) {
@@ -0,0 +1,13 @@
1
+ export declare function navegarContextoSessao(base: string, pedido: string, arquivo?: string): Promise<{
2
+ totalModulos: number;
3
+ indiceCaracteres: number;
4
+ candidatos: {
5
+ modulo: any;
6
+ contrato: string;
7
+ motivo: string;
8
+ resumo: any;
9
+ arquivos: any;
10
+ }[];
11
+ status: string;
12
+ execucaoAutorizada: boolean;
13
+ }>;
@@ -0,0 +1,41 @@
1
+ // SEMA-GOVERNED: sema.produto.cli_sessao
2
+ // Descrição: consulta o índice local internamente e retorna candidatos rastreáveis, sem autorização de edição.
3
+ import { readFile } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { selecionarIndiceContexto } from "./indexPack.js";
6
+ import { validarDestinosEscritaWorkspace } from "./workspaceWrite.js";
7
+ export async function navegarContextoSessao(base, pedido, arquivo) {
8
+ await validarDestinosEscritaWorkspace(base, ["SEMA_INDEX.json"]);
9
+ const texto = await readFile(path.join(base, "SEMA_INDEX.json"), "utf8");
10
+ const indice = JSON.parse(texto);
11
+ if (!Array.isArray(indice.modulos))
12
+ throw new Error("Índice sem módulos; rode sema sync-codex --json.");
13
+ const relativo = (valor) => {
14
+ const absoluto = path.resolve(base, valor);
15
+ const rel = path.relative(base, absoluto);
16
+ if (rel === ".." || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel))
17
+ throw new Error("Referência de contexto fora do workspace.");
18
+ return rel.replace(/\\/g, "/");
19
+ };
20
+ const alvo = arquivo ? relativo(arquivo) : undefined;
21
+ const exatos = alvo ? indice.modulos.filter((m) => relativo(m.arquivo) === alvo
22
+ || m.arquivosProvaveis?.some((p) => relativo(p) === alvo)) : [];
23
+ const pack = selecionarIndiceContexto({ modulos: indice.modulos, request: pedido, baseProject: base, sourceIndexChars: texto.length, maximoModulos: indice.modulos.length });
24
+ const encontrados = alvo ? exatos.map((m) => ({
25
+ module: m.modulo, contract: m.arquivo, purpose: m.faz, likelyFiles: m.arquivosProvaveis,
26
+ })) : pack.matches;
27
+ return {
28
+ totalModulos: indice.modulos.length,
29
+ indiceCaracteres: texto.length,
30
+ candidatos: encontrados.map((m) => ({
31
+ modulo: m.module,
32
+ contrato: relativo(m.contract),
33
+ motivo: alvo ? `Referência exata: ${alvo}` : "Correspondência de intenção; confirme no contrato antes de editar.",
34
+ resumo: m.purpose,
35
+ arquivos: (m.likelyFiles ?? []).map(relativo),
36
+ })),
37
+ status: encontrados.length === 0 ? "sem_correspondencia" : encontrados.length === 1 ? "contrato_localizado" : "selecionar_contrato",
38
+ execucaoAutorizada: false,
39
+ };
40
+ }
41
+ //# sourceMappingURL=sessionContext.js.map
@@ -0,0 +1,17 @@
1
+ type Arquivo = {
2
+ caminhoRelativo: string;
3
+ conteudo: string;
4
+ };
5
+ export declare function erroModoPreservacao(preservar: boolean | undefined, configuracoes: Array<{
6
+ alvo: string;
7
+ framework: string;
8
+ }>): string | undefined;
9
+ export declare function prepararImplementacaoPythonLocal(base: string, arquivos: Arquivo[]): Promise<{
10
+ arquivosParaEscrita: Arquivo[];
11
+ erro?: string;
12
+ }>;
13
+ export declare function evidenciaPython(preservar: boolean | undefined): {
14
+ tipoEvidencia: "andaime_demonstrativo" | "implementacao_local_preservada";
15
+ implementacaoExternaExecutada: boolean;
16
+ };
17
+ export {};
@@ -0,0 +1,46 @@
1
+ // SEMA-GOVERNED: sema.produto.cli_verificacao
2
+ // Contrato: contratos/sema/cli_verificacao.sema
3
+ // Descrição: preserva Python local explicitamente; testes continuam derivados do contrato, sem cache.
4
+ import { lstat } from "node:fs/promises";
5
+ import path from "node:path";
6
+ export function erroModoPreservacao(preservar, configuracoes) {
7
+ if (preservar && (configuracoes.length !== 1 || configuracoes[0].alvo !== "python" || configuracoes[0].framework !== "base")) {
8
+ return "--preservar-implementacao exige --alvo python e framework base.";
9
+ }
10
+ return undefined;
11
+ }
12
+ export async function prepararImplementacaoPythonLocal(base, arquivos) {
13
+ const implementacoes = arquivos.filter(arquivo => arquivo.caminhoRelativo.endsWith(".py") && !path.basename(arquivo.caminhoRelativo).startsWith("test_"));
14
+ if (implementacoes.length === 0)
15
+ return { arquivosParaEscrita: [], erro: "Nenhuma implementação Python local prevista pelo contrato." };
16
+ try {
17
+ for (const arquivo of implementacoes) {
18
+ const destino = path.resolve(base, arquivo.caminhoRelativo);
19
+ const relativo = path.relative(path.resolve(base), destino);
20
+ if (path.isAbsolute(relativo) || relativo.split(path.sep).includes(".."))
21
+ throw new Error("escape");
22
+ let atual = destino;
23
+ while (true) {
24
+ const info = await lstat(atual);
25
+ if (info.isSymbolicLink() || (atual === destino ? !info.isFile() || info.nlink > 1 : !info.isDirectory()))
26
+ throw new Error("link ou tipo inválido");
27
+ const pai = path.dirname(atual);
28
+ if (pai === atual)
29
+ break;
30
+ atual = pai;
31
+ }
32
+ }
33
+ const preservados = new Set(implementacoes.map(arquivo => arquivo.caminhoRelativo));
34
+ return { arquivosParaEscrita: arquivos.filter(arquivo => !preservados.has(arquivo.caminhoRelativo)) };
35
+ }
36
+ catch {
37
+ return { arquivosParaEscrita: [], erro: "Implementação Python local ausente ou caminho não seguro. Gere e preencha a implementação antes de usar --preservar-implementacao." };
38
+ }
39
+ }
40
+ export function evidenciaPython(preservar) {
41
+ return {
42
+ tipoEvidencia: preservar ? "implementacao_local_preservada" : "andaime_demonstrativo",
43
+ implementacaoExternaExecutada: false,
44
+ };
45
+ }
46
+ //# sourceMappingURL=verificacaoPythonLocal.js.map
@@ -60,19 +60,11 @@ while contract-only queries keep unobserved implementation fields null inside th
60
60
 
61
61
  ## Codex Context Tiers
62
62
 
63
- Codex with a small context budget should start with `SEMA_BOOT.md`,
64
- `SEMA_SMALL_MODEL.md`, `SEMA_BRIEF.micro.txt`,
65
- `AGENT_CONTEXT_PACK.json`, and `SEMA_INDEX.json`. They should stop early
66
- when a gate is unclear.
67
-
68
- Codex with a medium context budget should start with `SEMA_BOOT.md`,
69
- `AGENT_CONTEXT_PACK.json`, `SEMA_BRIEF.curto.txt`,
70
- `SEMA_INDEX.json`, and `AGENTS.md`. They must run docs-impact, drift, and
71
- impact before edits.
72
-
73
- Codex with a large context budget may consume `AGENT_CONTEXT_PACK.json`, `SEMA_BRIEF.md`,
74
- `SEMA_INDEX.json`, AST, IR, drift, and impact outputs, but larger context does
75
- not remove the contract-first rule.
63
+ All context capacities start with AGENTS.md, SEMA_BOOT.md and sema sessao.
64
+ The first session asks for the effective window in tokens. Declare --janela-contexto
65
+ and use --salvar-perfil to remember it; --orcamento-contexto and --reserva-saida are adjustable.
66
+ SEMA_INDEX.json and AGENT_CONTEXT_PACK.json are internal CLI data, never mandatory full reads.
67
+ Read the selected contract and its declared dependencies, then the linked code. Ambiguity requires refinement.
76
68
 
77
69
  ## Governed Code
78
70
 
@@ -5,10 +5,10 @@ This is the minimum workflow for Codex in a local workspace.
5
5
 
6
6
  1. Read `SEMA_BOOT.md`.
7
7
  2. Run `sema --version`. If the shell cannot find it, use `$HOME/.sema/bin/sema` on macOS/Linux. On Windows, PowerShell resolves `sema.ps1` from PATH and cmd.exe resolves `sema.cmd`; use `& "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$HOME\.sema\bin\sema-managed.ps1" --version` as the absolute fallback. Only then declare the CLI unavailable.
8
- 3. Run `sema resumo --drift none` for contract-only orientation; request `--drift cache` or `--drift fresh` only when code evidence is needed.
9
- 4. Run `sema docs-impacto --intencao "<change>" --json`.
8
+ 3. Run `sema sessao "<intenção>" --json`; then `sema resumo <contrato> --micro --drift none --json` only for the selected contract.
9
+ 4. Run `sema docs-impacto --intencao "<change>" --arquivo <contract> --json`.
10
10
  5. Read every required document returned by the command.
11
- 6. Read `docs/commands.md` before selecting a command or interpreting `--saida`.
11
+ 6. Consult command help or the relevant section of `docs/commands.md` when syntax, a gate or `--saida` is unclear.
12
12
  7. If the right capability is unclear, run `sema descobrir recomendar --intencao "<goal>" --json`; do not auto-run ambiguous recommendations.
13
13
  8. Use `exemplos/` and `docs/syntax.md` before creating or editing a contract.
14
14
  9. Run `sema drift --cache fresh` and `sema impacto` before editing existing code.
@@ -30,9 +30,11 @@ UI rule: if the task involves an interface, minimum evidence includes desktop an
30
30
 
31
31
  ## Codex Context Capacity
32
32
 
33
- - Small context: `SEMA_SMALL_MODEL.md`, `SEMA_BRIEF.micro.txt`, `AGENT_CONTEXT_PACK.json`, `SEMA_INDEX.json`.
34
- - Medium context: `SEMA_BOOT.md`, `AGENT_CONTEXT_PACK.json`, `SEMA_BRIEF.curto.txt`, `SEMA_INDEX.json`, `AGENTS.md`.
35
- - Large context: `SEMA_BOOT.md`, `AGENT_CONTEXT_PACK.json`, `SEMA_BRIEF.md`, `SEMA_INDEX.json`, AST, IR, drift, and impact.
33
+ All capacities use AGENTS.md -> SEMA_BOOT.md -> the contract returned by `sema sessao`.
34
+ The first session asks for the configured token window; declare `--janela-contexto <tokens> --salvar-perfil`.
35
+ Use `--orcamento-contexto` and `--reserva-saida` to allocate space. Counts use characters / 4, not the model tokenizer.
36
+ The CLI reads SEMA_INDEX.json internally. Do not load the full index, global pack, or unrelated modules.
37
+ An explicit `--arquivo` selects its contract and declared dependencies. Word matches are optional references.
36
38
 
37
39
  ## When to Generate Code
38
40
 
package/docs/commands.md CHANGED
@@ -18,7 +18,7 @@ Then read every required doc returned by `docs-impacto`.
18
18
 
19
19
  ## Session Opening
20
20
 
21
- - `sema sessao "<intencao>" --json`: opens a governed session with one compact envelope. It returns workspace identity (`baseProjeto`, `hashContratos`, CLI version), artifact freshness (`frescor.fresco` plus the exact recovery command when stale), the project's contract count and modules, the declared intent's categories with blocking and recommended docs, the four gate commands for the full loop, and concrete next steps. Treat `frescor.fresco:false` as a pre-action blocker: run the suggested `sema sync-codex --json` before editing, because gates protect the consistency that stale artifacts break.
21
+ - `sema sessao "<intencao>" [--arquivo <contrato-ou-codigo>] [--janela-contexto <tokens>] [--orcamento-contexto <tokens>] [--reserva-saida <tokens>] [--salvar-perfil] --json`: asks for the effective window when absent and stores the profile only on explicit request. The compact response contains workspace identity, artifact freshness, matching contracts and linked files, mandatory document paths, scoped gates and next steps. The index stays inside the CLI. The budget estimates the public JSON size using characters/4; it does not measure the conversation or the model's exact tokenizer. Omitted candidates are counted and require scope refinement; mandatory readings are never silently waived. Treat `frescor.fresco:false` as a pre-action blocker and run the suggested `sema sync-codex --json`. Navigation never authorizes execution.
22
22
 
23
23
  ## Public JSON output
24
24
 
@@ -47,3 +47,36 @@ same rule applies to drift and semantic-budget governance: keep a cohesive
47
47
  primary capability in the root contract and move secondary responsibilities to
48
48
  named children. Preserve task names, guarantees, implementations, and
49
49
  `vinculos`; never create numbered part files.
50
+
51
+
52
+ ## Progressive AI Context
53
+
54
+ The mandatory entry is AGENTS.md and SEMA_BOOT.md. SEMA_INDEX.json and
55
+ AGENT_CONTEXT_PACK.json are internal CLI sources, not required full readings.
56
+ The session asks for the effective context window when it is unknown. The local
57
+ `.sema/contexto-ia.json` profile is saved only by `--salvar-perfil` or by `iniciar`
58
+ with a declared window. Reconfigure it after switching models.
59
+
60
+ `sema sessao "<intent>" --janela-contexto 32768 --salvar-perfil --json`
61
+ configures a 32K window. Defaults allocate 4096 estimated tokens to the session
62
+ response and reserve 4096 for output. Other instructions, tools, conversation
63
+ and code need the remaining space. `--orcamento-contexto` and `--reserva-saida`
64
+ adjust this split. The characters/4 estimate includes the public envelope and
65
+ a margin; it is not an exact tokenizer or a measurement of the client's used
66
+ context. The limit applies to the session response, not every legacy command
67
+ or the cumulative conversation. The output reserve does not configure the model.
68
+
69
+ In docs-impacto and finalizar-mudanca, `--arquivo` fixes the target. Explicit
70
+ contracts are included even beyond the 80th catalog entry. Source files resolve
71
+ through `vinculos.arquivo`. Required expansion follows declared `use` dependencies,
72
+ with reasons and originating contracts. Missing or ambiguous dependencies block.
73
+ `docs.arquivo` references are recommendations and do not expand the dependency
74
+ graph. Intent suggestions stay in `leituraRecomendada`, distinct from
75
+ `leituraObrigatoria`, and do not block closure. Pass the same target at closure
76
+ and confirm the selected contracts before editing code.
77
+
78
+ The context-budget and docs-relevancia tests measure actual CLI output, prove
79
+ that the raw index is absent, verify hash invalidation and configuration before
80
+ writes, and cover WhatsApp alongside 85 unrelated contracts. Drift, contract
81
+ and behavioral gates remain required. To roll back, restore the prior generators
82
+ and resolvers and run sync-codex; preserve manual blocks and the local profile.
package/docs/testing.md CHANGED
@@ -169,3 +169,21 @@ this scaffold: its tests and guarantees cannot establish production behavior.
169
169
  Use the application's real tests and drift evidence for that claim. Generated
170
170
  failure cases currently retain the explicit synthetic error context and are
171
171
  not evidence that the real implementation produces those errors.
172
+
173
+ To execute an explicitly filled local Python implementation without overwriting
174
+ it, use the same verification output base that contains the generated module:
175
+
176
+ ```bash
177
+ sema verificar contratos/app.sema --alvo python --saida .tmp/check --preservar-implementacao --json
178
+ ```
179
+
180
+ This opt-in mode supports only Python with the base framework. All expected
181
+ implementation files must already exist as regular files, without symlinks,
182
+ junctions or hardlinks. It preserves those files byte for byte, regenerates the
183
+ contract tests and support artifacts, and always runs the tests without reading
184
+ or writing the verification cache. Missing implementations fail before writes;
185
+ new expectations and incorrect implementation results still fail. The output
186
+ reports `tipoEvidencia: implementacao_local_preservada` and
187
+ `implementacaoExternaExecutada: false`: it proves execution of those local files,
188
+ not automatic execution of a linked `impl`, a remote deployment or production.
189
+ Normal verification retains the demonstration scaffold behavior.
@@ -1,68 +1,68 @@
1
- module exemplos.python_verificacao {
2
- docs {
3
- resumo: "Regressao executavel Python para garantias numericas, formulario tipado, status e metadados aninhados."
4
- }
5
- entity FormularioEntrega {
6
- fields {
7
- tipo: Texto
8
- }
9
- }
10
- entity MetaTemplate {
11
- fields {
12
- original_campaign_id: Texto
13
- }
14
- }
15
- entity Template {
16
- fields {
17
- _template_meta: MetaTemplate
18
- }
19
- }
20
- entity Status {
21
- fields {
22
- desired_action: Texto
23
- }
24
- }
25
- task preparar {
26
- input {
27
- formulario: FormularioEntrega required
28
- }
29
- output {
30
- poolSize: Inteiro
31
- workersAplicados: Inteiro
32
- template: Template
33
- status: Status
34
- }
35
- rules {
36
- formulario.tipo existe
37
- }
38
- guarantees {
39
- poolSize > 0
40
- workersAplicados >= 2
41
- template._template_meta existe
42
- template._template_meta.original_campaign_id em ["campanha_1"]
43
- status.desired_action em ["iniciar", "parar"]
44
- }
45
- tests {
46
- caso "verifica cada saida" {
47
- given {
48
- formulario {
49
- tipo: "entrega"
50
- }
51
- }
52
- expect {
53
- sucesso: verdadeiro
54
- poolSize: 1
55
- workersAplicados: 2
56
- template {
57
- _template_meta {
58
- original_campaign_id: "campanha_1"
59
- }
60
- }
61
- status {
62
- desired_action: "iniciar"
63
- }
64
- }
65
- }
66
- }
67
- }
68
- }
1
+ module exemplos.python_verificacao {
2
+ docs {
3
+ resumo: "Regressao executavel Python para garantias numericas, formulario tipado, status e metadados aninhados."
4
+ }
5
+ entity FormularioEntrega {
6
+ fields {
7
+ tipo: Texto
8
+ }
9
+ }
10
+ entity MetaTemplate {
11
+ fields {
12
+ original_campaign_id: Texto
13
+ }
14
+ }
15
+ entity Template {
16
+ fields {
17
+ _template_meta: MetaTemplate
18
+ }
19
+ }
20
+ entity Status {
21
+ fields {
22
+ desired_action: Texto
23
+ }
24
+ }
25
+ task preparar {
26
+ input {
27
+ formulario: FormularioEntrega required
28
+ }
29
+ output {
30
+ poolSize: Inteiro
31
+ workersAplicados: Inteiro
32
+ template: Template
33
+ status: Status
34
+ }
35
+ rules {
36
+ formulario.tipo existe
37
+ }
38
+ guarantees {
39
+ poolSize > 0
40
+ workersAplicados >= 2
41
+ template._template_meta existe
42
+ template._template_meta.original_campaign_id em ["campanha_1"]
43
+ status.desired_action em ["iniciar", "parar"]
44
+ }
45
+ tests {
46
+ caso "verifica cada saida" {
47
+ given {
48
+ formulario {
49
+ tipo: "entrega"
50
+ }
51
+ }
52
+ expect {
53
+ sucesso: verdadeiro
54
+ poolSize: 1
55
+ workersAplicados: 2
56
+ template {
57
+ _template_meta {
58
+ original_campaign_id: "campanha_1"
59
+ }
60
+ }
61
+ status {
62
+ desired_action: "iniciar"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }