@semacode/cli 3.9.4 → 3.10.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.
@@ -10,7 +10,7 @@ const COMANDOS_PUBLICOS = new Set([
10
10
  "impacto", "importar", "iniciar", "init", "inspecionar", "instalar-exemplos",
11
11
  "interativo", "ir", "pipeline", "profile", "prompt-curto", "prompt-ia",
12
12
  "prompt-ia-react", "prompt-ia-sema-primeiro", "prompt-ia-ui", "renomear-semantico",
13
- "resumo", "rule-packs", "skill", "starter-ia", "sync", "sync-codex", "testar",
13
+ "resumo", "rule-packs", "sessao", "skill", "starter-ia", "sync", "sync-codex", "testar",
14
14
  "validar", "verificar", "ast",
15
15
  ]);
16
16
  const TEMPLATES_INICIAR = new Set([
@@ -451,6 +451,7 @@ function validarComandoBasico(comando, args) {
451
451
  return Boolean(alvo && ALVOS_GERACAO.has(alvo)) && (!estrutura || ESTRUTURAS.has(estrutura)) && (!framework || FRAMEWORKS.has(framework));
452
452
  }
453
453
  case "verificar": return parsearArgumentos(args, { opcoes: ["--saida", "--alvo"], flags: ["--sem-cache"], maxPosicionais: 1 }) !== null;
454
+ case "sessao": return parsearArgumentos(args, { flags: ["--json"], maxPosicionais: 2 }) !== null;
454
455
  case "formatar": return parsearArgumentos(args, { flags: ["--check"], maxPosicionais: 1 }) !== null;
455
456
  case "inspecionar": {
456
457
  const parsed = parsearArgumentos(args, { opcoes: ["--drift", "--cache"], flags: ["--com-drift"], maxPosicionais: 1 });
@@ -143,6 +143,7 @@ export function criarAjudaRaiz(versao) {
143
143
  "sema contexto-ia <arquivo.sema> [--saida <diretorio>] [--json]",
144
144
  "sema sync-codex [--json]",
145
145
  "sema instalar-exemplos [--json]",
146
+ "sema sessao [intencao] [entrada] [--json]",
146
147
  "sema docs-impacto --intencao <acao> [--arquivo <caminho>] [--criar-ausentes] [--completo] [--json]",
147
148
  "sema finalizar-mudanca --intencao <acao> [--arquivo <caminho>] [--doc-lida <caminho>] [--json]",
148
149
  "sema author briefing <arquivo.sema> [--json]",
@@ -0,0 +1,34 @@
1
+ export interface SessaoEnvelope {
2
+ comando: "sessao";
3
+ sucesso: boolean;
4
+ workspace: {
5
+ baseProjeto: string;
6
+ nomePasta: string;
7
+ hashContratos: string;
8
+ cliVersao: string;
9
+ };
10
+ frescor: {
11
+ fresco: boolean;
12
+ hashArtefato: string | null;
13
+ hashAtual: string;
14
+ sugestao: string;
15
+ };
16
+ contratos: {
17
+ total: number;
18
+ modulos: string[];
19
+ };
20
+ intencoes: {
21
+ intencao: string;
22
+ categorias: string[];
23
+ docsBloqueantes: string[];
24
+ docsRecomendadas: string[];
25
+ };
26
+ gates: {
27
+ drift: string;
28
+ validar: string;
29
+ verificar: string;
30
+ finalizar: string;
31
+ };
32
+ proximosPassos: string[];
33
+ }
34
+ export declare function comandoSessao(posicionais: string[], args: string[], emJson: boolean, cwd?: string): Promise<number>;
@@ -0,0 +1,86 @@
1
+ // SEMA-GOVERNED: sema.produto.cli_sessao
2
+ // Descricao: comando sessao devolve envelope compacto de abertura governada.
3
+ import path from "node:path";
4
+ import { verificarFrescorArtefatos } from "./index.part04.js";
5
+ import { carregarProjeto } from "./projetoCarregar.js";
6
+ import { resolverDocumentacaoObrigatoria } from "./docs.js";
7
+ export async function comandoSessao(posicionais, args, emJson, cwd = process.cwd()) {
8
+ const intencao = posicionais[0] ?? args.find((arg) => arg.startsWith("--intencao="))?.split("=")[1] ?? "";
9
+ const entrada = posicionais[1];
10
+ const baseProjeto = entrada ? path.resolve(cwd, entrada) : cwd;
11
+ const contextoProjeto = await carregarProjeto(entrada, cwd, {
12
+ escopo: "projeto",
13
+ adiarDescobertaCodigo: true,
14
+ });
15
+ const pacoteCli = (await import("../package.json", { with: { type: "json" } })).default;
16
+ const frescor = await verificarFrescorArtefatos(contextoProjeto.baseProjeto);
17
+ const modulosNomes = contextoProjeto.modulosSelecionados.map((item) => item.resultado.modulo?.nome ?? path.basename(item.caminho, ".sema"));
18
+ let categorias = [];
19
+ let docsBloqueantes = [];
20
+ let docsRecomendadas = [];
21
+ if (intencao.trim()) {
22
+ const impacto = await resolverDocumentacaoObrigatoria({
23
+ baseProjeto: contextoProjeto.baseProjeto,
24
+ intencao,
25
+ arquivosAlvo: [],
26
+ criarAusentes: false,
27
+ });
28
+ categorias = impacto.categorias;
29
+ docsBloqueantes = impacto.leituraObrigatoria
30
+ .filter((doc) => doc.obrigatoriedade !== "recomendada" && doc.existe)
31
+ .map((doc) => doc.relativo);
32
+ docsRecomendadas = impacto.leituraRecomendada.map((doc) => doc.relativo);
33
+ }
34
+ const envelope = {
35
+ comando: "sessao",
36
+ sucesso: true,
37
+ workspace: {
38
+ baseProjeto: contextoProjeto.baseProjeto,
39
+ nomePasta: path.basename(contextoProjeto.baseProjeto),
40
+ hashContratos: frescor.hashAtual,
41
+ cliVersao: pacoteCli.version,
42
+ },
43
+ frescor,
44
+ contratos: {
45
+ total: contextoProjeto.modulosSelecionados.length,
46
+ modulos: modulosNomes.slice(0, 10),
47
+ },
48
+ intencoes: {
49
+ intencao,
50
+ categorias,
51
+ docsBloqueantes,
52
+ docsRecomendadas,
53
+ },
54
+ gates: {
55
+ drift: "sema drift . --escopo projeto --cache fresh --json",
56
+ validar: "sema validar contratos --json",
57
+ verificar: "sema verificar contratos --alvo typescript --json",
58
+ finalizar: 'sema finalizar-mudanca --intencao "<intencao>" --doc-lida <doc> --json',
59
+ },
60
+ proximosPassos: [
61
+ ...(!frescor.fresco ? ["Artefatos stale detectados — rode sema sync-codex --json antes de agir"] : []),
62
+ ...(docsBloqueantes.length > 0 ? [`Leia antes de agir: ${docsBloqueantes.slice(0, 5).join(", ")}`] : []),
63
+ ...(intencao.trim() ? ["Siga o protocolo AGENTS.md passo a passo"] : ["Declare --intencao para receber gates especificos"]),
64
+ ],
65
+ };
66
+ if (emJson) {
67
+ console.log(JSON.stringify(envelope, null, 2));
68
+ return 0;
69
+ }
70
+ console.log(`Sessao Sema — ${envelope.workspace.nomePasta}`);
71
+ console.log(` Hash contratos: ${envelope.workspace.hashContratos}`);
72
+ console.log(` CLI: ${envelope.workspace.cliVersao}`);
73
+ console.log(` Frescor: ${frescor.fresco ? "fresco" : "STALE"} ${!frescor.fresco ? `(${frescor.sugestao})` : ""}`);
74
+ console.log(` Contratos: ${envelope.contratos.total}`);
75
+ if (intencao) {
76
+ console.log(` Intencao: ${intencao}`);
77
+ console.log(` Categorias: ${categorias.join(", ")}`);
78
+ console.log(` Docs bloqueantes: ${docsBloqueantes.length}`);
79
+ console.log(` Docs recomendadas: ${docsRecomendadas.length}`);
80
+ }
81
+ for (const passo of envelope.proximosPassos) {
82
+ console.log(` → ${passo}`);
83
+ }
84
+ return 0;
85
+ }
86
+ //# sourceMappingURL=comandoSessao.js.map
@@ -4,7 +4,7 @@ import { type GuiaCapacidadeIaMap } from './agentContextTipos.js';
4
4
  import { renderizarCaixaAscii, renderizarSecaoAscii } from './cliHelpTexto.js';
5
5
  import { criarBriefingAgente, criarBriefingAgenteContratos, resumirDriftPorModulo } from "./index.part03.js";
6
6
  import { type ComandoConsultaDrift, type ModoCacheDrift, type ResolucaoModoCacheDrift } from "./driftCacheModes.js";
7
- export type Comando = "iniciar" | "init" | "dev" | "sync" | "author" | "profile" | "conteudo" | "interativo" | "descobrir" | "pipeline" | "capabilities" | "validar" | "ast" | "ir" | "compilar" | "gerar" | "testar" | "diagnosticos" | "verificar" | "inspecionar" | "drift" | "impacto" | "renomear-semantico" | "importar" | "doctor" | "formatar" | "ajuda-ia" | "starter-ia" | "sync-codex" | "skill" | "instalar-exemplos" | "rule-packs" | "docs-impacto" | "finalizar-mudanca" | "resumo" | "prompt-curto" | "prompt-ia" | "prompt-ia-ui" | "prompt-ia-react" | "prompt-ia-sema-primeiro" | "exemplos-prompt-ia" | "contexto-ia";
7
+ export type Comando = "iniciar" | "init" | "dev" | "sync" | "author" | "profile" | "conteudo" | "interativo" | "descobrir" | "pipeline" | "capabilities" | "validar" | "ast" | "ir" | "compilar" | "gerar" | "testar" | "diagnosticos" | "verificar" | "inspecionar" | "drift" | "impacto" | "renomear-semantico" | "importar" | "doctor" | "formatar" | "ajuda-ia" | "starter-ia" | "sync-codex" | "skill" | "instalar-exemplos" | "rule-packs" | "docs-impacto" | "finalizar-mudanca" | "resumo" | "sessao" | "prompt-curto" | "prompt-ia" | "prompt-ia-ui" | "prompt-ia-react" | "prompt-ia-sema-primeiro" | "exemplos-prompt-ia" | "contexto-ia";
8
8
  export interface ResultadoFormatacaoArquivo {
9
9
  caminho: string;
10
10
  alterado: boolean;
@@ -2,6 +2,13 @@ import { type GuiaCapacidadeIaMap } from './agentContextTipos.js';
2
2
  import { ContextoIaGerado, ResumoSemanticoModuloIa, type ResultadoDriftIa } from "./index.part01.js";
3
3
  import type { ResolucaoModoCacheDrift } from "./driftCacheModes.js";
4
4
  export declare const ARQUIVOS_RESUMO_PROJETO_IA: readonly ["SEMA_BOOT.md", "SEMA_SMALL_MODEL.md", "SEMA_BRIEF.md", "SEMA_BRIEF.micro.txt", "SEMA_BRIEF.curto.txt", "SEMA_INDEX.json", "AGENT_CONTEXT_PACK.json", "docs/ai-integration.md"];
5
+ export declare function verificarFrescorArtefatos(baseProjeto: string): Promise<{
6
+ fresco: boolean;
7
+ hashArtefato: string | null;
8
+ hashAtual: string;
9
+ contratosMudaram: boolean;
10
+ sugestao: string;
11
+ }>;
5
12
  export declare function gerarResumoProjetoIa(entrada: string | undefined, pastaSaidaOpcional?: string, escreverNaRaiz?: boolean, analiseDrift?: ResolucaoModoCacheDrift): Promise<{
6
13
  geradoEm: string;
7
14
  baseProjeto: string;
@@ -1,6 +1,7 @@
1
1
  // SEMA-GOVERNED: sema.governanca_ia_contexto, sema.produto.escrita_segura_workspace, sema.produto.governanca_ia.drift.cache.modos
2
2
  // Descrição: gera contexto local e grava artefatos somente dentro da base validada.
3
- import { mkdir } from "node:fs/promises";
3
+ import { mkdir, readFile } from "node:fs/promises";
4
+ import { createHash } from "node:crypto";
4
5
  import path from "node:path";
5
6
  import { formatarDiagnosticos, gerarRespostaValidacao, temErros, } from "@sema/nucleo";
6
7
  import { carregarProjeto, } from "./projeto.js";
@@ -53,6 +54,43 @@ function escolherTopArquivosResumo(modulos, arquivosCodigoDetectados) {
53
54
  }
54
55
  return { arquivos: [], fonte: "nenhum" };
55
56
  }
57
+ async function calcularHashContratos(caminhosContratos, baseProjeto) {
58
+ const hash = createHash("sha256");
59
+ const base = baseProjeto ?? (caminhosContratos[0] ? path.dirname(caminhosContratos[0]) : process.cwd());
60
+ const ordenados = [...caminhosContratos].sort();
61
+ for (const caminho of ordenados) {
62
+ const conteudo = await readFile(caminho, "utf8").catch(() => "");
63
+ const relativo = path.relative(base, caminho).replace(/[\\/]/g, "/");
64
+ hash.update(relativo);
65
+ hash.update(":");
66
+ hash.update(conteudo);
67
+ hash.update(String.fromCharCode(0));
68
+ }
69
+ return hash.digest("hex").slice(0, 16);
70
+ }
71
+ export async function verificarFrescorArtefatos(baseProjeto) {
72
+ const caminhoIndex = path.join(baseProjeto, "SEMA_INDEX.json");
73
+ let hashArtefato = null;
74
+ try {
75
+ const index = JSON.parse(await readFile(caminhoIndex, "utf8"));
76
+ hashArtefato = index.hashContratos ?? null;
77
+ }
78
+ catch {
79
+ hashArtefato = null;
80
+ }
81
+ const origens = await (await import("./projetoOrigens.js")).resolverOrigensProjeto(baseProjeto, baseProjeto, undefined);
82
+ const { listarArquivosDeOrigens } = await import("./projetoOrigens.js");
83
+ const contratos = await listarArquivosDeOrigens(origens);
84
+ const hashAtual = await calcularHashContratos(contratos, baseProjeto);
85
+ const fresco = hashArtefato === hashAtual;
86
+ return {
87
+ fresco,
88
+ hashArtefato,
89
+ hashAtual,
90
+ contratosMudaram: !fresco,
91
+ sugestao: fresco ? "" : "Artefatos de contexto estao desatualizados; rode sema sync-codex --json para regenerar.",
92
+ };
93
+ }
56
94
  export async function gerarResumoProjetoIa(entrada, pastaSaidaOpcional, escreverNaRaiz = false, analiseDrift = { modo: "none", executar: false, avisos: [] }) {
57
95
  const contextoProjeto = await carregarProjeto(entrada, process.cwd(), {
58
96
  escopo: "projeto",
@@ -121,10 +159,13 @@ export async function gerarResumoProjetoIa(entrada, pastaSaidaOpcional, escrever
121
159
  const semaBoot = renderizarSemaBoot(agentContextPack);
122
160
  const semaSmallModel = renderizarSemaSmallModel(agentContextPack);
123
161
  const docAgentesCapacidade = renderizarDocumentoAgentesPorCapacidade(agentContextPack);
162
+ const caminhosContratos = contextoProjeto.modulosSelecionados.map((item) => item.caminho);
163
+ const hashContratos = await calcularHashContratos(caminhosContratos, contextoProjeto.baseProjeto);
124
164
  const indexJson = {
125
165
  comando: "resumo-projeto",
126
166
  geradoEm,
127
167
  cliVersao: VERSAO_CLI,
168
+ hashContratos,
128
169
  baseProjeto,
129
170
  modoVerificacaoCodigo,
130
171
  analiseDrift: {
@@ -36,6 +36,11 @@ export async function principal() {
36
36
  case "iniciar":
37
37
  codigoSaida = await comandoIniciar(cwd, normalizarTemplateIniciar(obterOpcao(resto, "--template")), { force: possuiFlag(resto, "--force"), exemplosCompletos: possuiFlag(resto, "--com-exemplos") });
38
38
  break;
39
+ case "sessao": {
40
+ const { comandoSessao } = await import("./comandoSessao.js");
41
+ codigoSaida = await comandoSessao(posicionais, resto, possuiFlag(resto, "--json"), cwd);
42
+ break;
43
+ }
39
44
  case "author":
40
45
  codigoSaida = await comandoAuthor(posicionais, resto, possuiFlag(resto, "--json"));
41
46
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semacode/cli",
3
- "version": "3.9.4",
3
+ "version": "3.10.0",
4
4
  "description": "Local-first semantic governance CLI for AI agents, proven with Claude, Codex, zCode (GLM) and Kimi: contracts, drift, impact, docs gates, and code generation.",
5
5
  "type": "module",
6
6
  "icon": "logo.png",