@semacode/cli 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +39 -39
- package/README.md +251 -228
- package/dist/agentEntryPoints.js +551 -550
- package/dist/angular-consumer-standalone.d.ts +3 -1
- package/dist/angular-consumer-standalone.js +12 -8
- package/dist/drift.part01.d.ts +32 -2
- package/dist/drift.part01.js +2 -0
- package/dist/drift.part04.d.ts +3 -2
- package/dist/drift.part04.js +6 -3
- package/dist/drift.part05.d.ts +2 -1
- package/dist/drift.part05.js +4 -3
- package/dist/drift.part06.d.ts +2 -1
- package/dist/drift.part06.js +9 -5
- package/dist/drift.part07.d.ts +11 -10
- package/dist/drift.part07.js +40 -30
- package/dist/drift.part08.d.ts +2 -1
- package/dist/drift.part08.js +4 -3
- package/dist/drift.part11.js +71 -6
- package/dist/drift.part12.js +14 -1
- package/dist/drift.part13.d.ts +42 -7
- package/dist/drift.part13.js +660 -36
- package/dist/driftCache.d.ts +49 -0
- package/dist/driftCache.js +311 -0
- package/dist/driftCacheIncremental.d.ts +98 -0
- package/dist/driftCacheIncremental.js +596 -0
- package/dist/driftCatalogo.d.ts +91 -0
- package/dist/driftCatalogo.js +657 -0
- package/dist/driftCatalogoPersistente.d.ts +8 -0
- package/dist/driftCatalogoPersistente.js +77 -0
- package/dist/driftEscopo.d.ts +23 -0
- package/dist/driftEscopo.js +563 -0
- package/dist/driftEscopoReferencias.d.ts +4 -0
- package/dist/driftEscopoReferencias.js +265 -0
- package/dist/driftOrcamento.d.ts +12 -0
- package/dist/driftOrcamento.js +19 -3
- package/dist/execucoesExternas.js +5 -19
- package/dist/iaPrompts.js +310 -310
- package/dist/index.part01.d.ts +16 -1
- package/dist/index.part01.js +80 -4
- package/dist/index.part02.js +21 -21
- package/dist/index.part03.d.ts +2 -2
- package/dist/index.part03.js +14 -3
- package/dist/index.part04.d.ts +2 -2
- package/dist/index.part04.js +113 -101
- package/dist/index.part05.d.ts +1 -1
- package/dist/index.part05.js +99 -22
- package/dist/index.part06.js +3 -2
- package/dist/index.part07.js +24 -24
- package/dist/index.part08.js +1 -1
- package/dist/init/templates.part01.js +393 -393
- package/dist/init/templates.part02.js +189 -189
- package/dist/initTemplatesBackend.js +73 -73
- package/dist/initTemplatesBase.js +81 -81
- package/dist/initTemplatesFlutter.js +137 -137
- package/dist/initTemplatesRuntime.js +350 -350
- package/dist/initTemplatesWeb.js +309 -309
- package/dist/pipelineConteudo/command.js +1 -36
- package/dist/projeto.d.ts +1 -1
- package/dist/projetoCarregar.d.ts +2 -2
- package/dist/projetoCarregar.js +47 -24
- package/dist/projetoCatalogo.d.ts +7 -0
- package/dist/projetoCatalogo.js +125 -0
- package/dist/projetoTipos.d.ts +14 -5
- package/dist/sync/index.js +35 -35
- package/docs/README.md +34 -34
- package/docs/ai-integration.md +1 -7
- package/docs/ai-onboarding.md +62 -62
- package/docs/ai-workflow.md +4 -0
- package/docs/auth.md +26 -26
- package/docs/cli.md +79 -79
- package/docs/commands.md +16 -13
- package/docs/database.md +15 -15
- package/docs/deploy.md +41 -41
- package/docs/descoberta-capacidades.md +106 -106
- package/docs/documentation.md +37 -46
- package/docs/env.md +16 -16
- package/docs/frontend.md +41 -41
- package/docs/getting-started.md +57 -57
- package/docs/i18n.md +15 -15
- package/docs/pipeline-conteudo.md +246 -246
- package/docs/profiles.md +54 -54
- package/docs/repositories.md +43 -43
- package/docs/rollback.md +31 -31
- package/docs/security.md +32 -32
- package/docs/sistemas-interativos.md +373 -378
- package/docs/support.md +8 -8
- package/docs/testing.md +51 -44
- package/docs/vocabulary.md +29 -29
- package/exemplos/agendamento.sema +1 -1
- package/exemplos/assinatura.sema +1 -1
- package/exemplos/auditoria.sema +1 -1
- package/exemplos/autenticacao.sema +1 -1
- package/exemplos/author_obra_comum.sema +1 -1
- package/exemplos/author_tema_sensivel.sema +1 -1
- package/exemplos/automacao.sema +1 -1
- package/exemplos/cadastro_usuario.sema +1 -1
- package/exemplos/calculadora.sema +1 -1
- package/exemplos/crud_simples.sema +1 -1
- package/exemplos/estoque.sema +1 -1
- package/exemplos/exportacao.sema +1 -1
- package/exemplos/fila.sema +1 -1
- package/exemplos/integracao_externa.sema +1 -1
- package/exemplos/multi_tenant.sema +1 -1
- package/exemplos/notificacao.sema +1 -1
- package/exemplos/operacao_estrategia.sema +132 -132
- package/exemplos/operacao_estrategia_discovery.sema +220 -220
- package/exemplos/operacao_estrategia_fluxo.sema +114 -114
- package/exemplos/operacao_estrategia_gates.sema +106 -106
- package/exemplos/operacao_estrategia_quarentena.sema +133 -133
- package/exemplos/operacao_estrategia_rollout.sema +124 -124
- package/exemplos/pagamento.sema +1 -1
- package/exemplos/pagamento_dominio.sema +1 -1
- package/exemplos/pedido.sema +1 -1
- package/exemplos/permissao.sema +1 -1
- package/exemplos/persistencia_vendor_first.sema +1 -1
- package/exemplos/pipeline-conteudo/README.md +44 -44
- package/exemplos/pipeline-conteudo/alvos.json +23 -23
- package/exemplos/pipeline-conteudo/definicao.json +136 -136
- package/exemplos/profile_conversas.sema +165 -165
- package/exemplos/profile_game.sema +1 -1
- package/exemplos/profile_legal.sema +1 -1
- package/exemplos/profile_ops.sema +1 -1
- package/exemplos/profile_research.sema +1 -1
- package/exemplos/profile_simulation.sema +211 -211
- package/exemplos/profile_software.sema +1 -1
- package/exemplos/profile_workflow_n8n.sema +1 -1
- package/exemplos/relatorio.sema +1 -1
- package/exemplos/replica_analitica_erp.sema +1 -1
- package/exemplos/sistemas-interativos/README.md +100 -100
- package/exemplos/sistemas-interativos/advanced/acceptance-context-evaluate-valid.json +5 -5
- package/exemplos/sistemas-interativos/advanced/acceptance-lock-valid.json +16 -16
- package/exemplos/sistemas-interativos/advanced/asset-provenance-valid.json +32 -32
- package/exemplos/sistemas-interativos/advanced/autonomy-repair-valid.json +93 -93
- package/exemplos/sistemas-interativos/advanced/control-run-definition-valid.json +78 -78
- package/exemplos/sistemas-interativos/advanced/control-run-valid.json +27 -27
- package/exemplos/sistemas-interativos/advanced/distributed-workers-valid.json +79 -79
- package/exemplos/sistemas-interativos/advanced/editor-state-valid.json +42 -42
- package/exemplos/sistemas-interativos/advanced/engine-snapshot-after-valid.json +32 -32
- package/exemplos/sistemas-interativos/advanced/engine-snapshot-before-valid.json +23 -23
- package/exemplos/sistemas-interativos/advanced/job-orchestration-valid.json +39 -39
- package/exemplos/sistemas-interativos/advanced/multimodal-evidence-valid.json +46 -46
- package/exemplos/sistemas-interativos/advanced/multiplayer-authority-valid.json +39 -39
- package/exemplos/sistemas-interativos/advanced/playtest-fuzz-valid.json +37 -37
- package/exemplos/sistemas-interativos/advanced/portability-valid.json +104 -104
- package/exemplos/sistemas-interativos/advanced/temporal-evidence-valid.json +27 -27
- package/exemplos/sistemas-interativos/advanced/temporal-valid.json +118 -118
- package/exemplos/sistemas-interativos/experience-ir-valid.json +459 -459
- package/exemplos/sistemas-interativos/game-2d.json +83 -83
- package/exemplos/sistemas-interativos/game-3d-human.json +81 -81
- package/exemplos/sistemas-interativos/game-pixel-16-bit.json +97 -97
- package/exemplos/sistemas-interativos/game-pixel-8-bit.json +94 -94
- package/exemplos/sistemas-interativos/game-xr-human.json +80 -80
- package/exemplos/sistemas-interativos/hybrid-2-5d.json +108 -108
- package/exemplos/sistemas-interativos/protocol-mutating-rollback-valid.json +75 -75
- package/exemplos/sistemas-interativos/protocol-read-only-valid.json +58 -58
- package/exemplos/sistemas-interativos/simulation-2d-controlled.json +97 -97
- package/exemplos/sistemas-interativos/simulation-3d-calibrated-autonomous.json +141 -141
- package/exemplos/sistemas-interativos/simulation-headless-autonomous-batch.json +112 -112
- package/exemplos/sistemas-interativos/simulation-pixel-16-bit.json +103 -103
- package/exemplos/sistemas-interativos/simulation-text-controlled.json +95 -95
- package/exemplos/testes_embutidos.sema +1 -1
- package/exemplos/tratamento_erro.sema +1 -1
- package/exemplos/upload_arquivo.sema +1 -1
- package/exemplos/webhook.sema +1 -1
- package/node_modules/@sema/gerador-cpp/dist/index.js +176 -176
- package/node_modules/@sema/gerador-cpp/package.json +1 -1
- package/node_modules/@sema/gerador-css/dist/index.part01.js +10 -10
- package/node_modules/@sema/gerador-css/dist/index.part02.js +460 -460
- package/node_modules/@sema/gerador-dotnet/dist/index.js +169 -169
- package/node_modules/@sema/gerador-dotnet/package.json +1 -1
- package/node_modules/@sema/gerador-html/dist/index.js +17 -17
- package/node_modules/@sema/gerador-lua/dist/index.js +51 -51
- package/node_modules/@sema/gerador-php/dist/index.js +113 -113
- package/node_modules/@sema/gerador-python/dist/index.part02.js +3 -3
- package/node_modules/@sema/gerador-typescript/dist/index.part02.js +11 -11
- package/node_modules/@sema/nucleo/dist/diagnosticos/melhorador.js +42 -42
- package/package.json +3 -3
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ObservadorOperacaoDrift } from "./driftCatalogo.js";
|
|
2
|
+
export declare const SCHEMA_CACHE_DRIFT: "sema.drift-index-cache/v1";
|
|
3
|
+
export declare const DIRETORIO_CACHE_DRIFT: string;
|
|
4
|
+
export type PoliticaCacheDrift = "auto" | "refresh" | "off";
|
|
5
|
+
export type ValorJson = null | boolean | number | string | ValorJson[] | {
|
|
6
|
+
[chave: string]: ValorJson;
|
|
7
|
+
};
|
|
8
|
+
export interface EntradaCacheAgregadoDrift {
|
|
9
|
+
fingerprintConteudo: string;
|
|
10
|
+
identidade: ValorJson;
|
|
11
|
+
}
|
|
12
|
+
export interface EnvelopeCacheDrift<T> {
|
|
13
|
+
schema: typeof SCHEMA_CACHE_DRIFT;
|
|
14
|
+
key: string;
|
|
15
|
+
payload: T;
|
|
16
|
+
payloadDigest: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ResultadoCacheAgregadoDrift<T> {
|
|
19
|
+
chave: string;
|
|
20
|
+
valor: T;
|
|
21
|
+
origem: "cache" | "calculado";
|
|
22
|
+
politica: PoliticaCacheDrift;
|
|
23
|
+
}
|
|
24
|
+
export interface MetricasCacheDrift {
|
|
25
|
+
hits: number;
|
|
26
|
+
misses: number;
|
|
27
|
+
corruptos: number;
|
|
28
|
+
gravacoes: number;
|
|
29
|
+
errosGravacao: number;
|
|
30
|
+
calculosCompartilhados: number;
|
|
31
|
+
}
|
|
32
|
+
export interface OpcoesCacheDrift {
|
|
33
|
+
baseProjeto: string;
|
|
34
|
+
politica?: PoliticaCacheDrift;
|
|
35
|
+
limiteBytes?: number;
|
|
36
|
+
observador?: ObservadorOperacaoDrift;
|
|
37
|
+
}
|
|
38
|
+
export interface CacheDrift {
|
|
39
|
+
readonly baseProjeto: string;
|
|
40
|
+
readonly politica: PoliticaCacheDrift;
|
|
41
|
+
chave(entrada: EntradaCacheAgregadoDrift): string;
|
|
42
|
+
caminhoRelativo(chave: string): string;
|
|
43
|
+
obterOuCalcular<T>(entrada: EntradaCacheAgregadoDrift, calcular: () => Promise<T>): Promise<ResultadoCacheAgregadoDrift<T>>;
|
|
44
|
+
metricas(): MetricasCacheDrift;
|
|
45
|
+
}
|
|
46
|
+
export declare function serializarJsonCanonicoCacheDrift(valor: unknown): string;
|
|
47
|
+
export declare function digestJsonCanonicoCacheDrift(valor: unknown): string;
|
|
48
|
+
export declare function criarChaveCacheDrift(entrada: EntradaCacheAgregadoDrift): string;
|
|
49
|
+
export declare function criarCacheDrift(opcoes: OpcoesCacheDrift): CacheDrift;
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
// SEMA-GOVERNED: sema.produto.governanca_ia.drift
|
|
2
|
+
// Descrição: persiste resultados agregados de indexação com chave por conteúdo e validação contra corrupção.
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { escreverArquivoWorkspaceSeguro, validarDestinosEscritaWorkspace, } from "./workspaceWrite.js";
|
|
7
|
+
export const SCHEMA_CACHE_DRIFT = "sema.drift-index-cache/v1";
|
|
8
|
+
export const DIRETORIO_CACHE_DRIFT = path.join(".tmp", "sema-cache", "drift-index", "v1");
|
|
9
|
+
const LIMITE_BYTES_PADRAO = 32 * 1024 * 1024;
|
|
10
|
+
const PADRAO_DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
11
|
+
function emitirEvento(observador, evento) {
|
|
12
|
+
try {
|
|
13
|
+
observador?.(evento);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
// Observabilidade nunca altera o resultado funcional do drift.
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function normalizarPolitica(valor) {
|
|
20
|
+
return valor === "refresh" || valor === "off" ? valor : "auto";
|
|
21
|
+
}
|
|
22
|
+
function normalizarLimiteBytes(valor) {
|
|
23
|
+
if (!Number.isSafeInteger(valor) || valor <= 0) {
|
|
24
|
+
return LIMITE_BYTES_PADRAO;
|
|
25
|
+
}
|
|
26
|
+
return valor;
|
|
27
|
+
}
|
|
28
|
+
function falharJsonCanonico(motivo, caminho) {
|
|
29
|
+
throw new TypeError(`json_cache_drift_invalido:${motivo}:${caminho}`);
|
|
30
|
+
}
|
|
31
|
+
function serializarCanonico(valor, caminho, visitados) {
|
|
32
|
+
if (valor === null) {
|
|
33
|
+
return "null";
|
|
34
|
+
}
|
|
35
|
+
if (typeof valor === "string" || typeof valor === "boolean") {
|
|
36
|
+
return JSON.stringify(valor);
|
|
37
|
+
}
|
|
38
|
+
if (typeof valor === "number") {
|
|
39
|
+
if (!Number.isFinite(valor)) {
|
|
40
|
+
return falharJsonCanonico("numero_nao_finito", caminho);
|
|
41
|
+
}
|
|
42
|
+
return Object.is(valor, -0) ? "0" : JSON.stringify(valor);
|
|
43
|
+
}
|
|
44
|
+
if (typeof valor !== "object") {
|
|
45
|
+
return falharJsonCanonico(`tipo_${typeof valor}_nao_suportado`, caminho);
|
|
46
|
+
}
|
|
47
|
+
if (visitados.has(valor)) {
|
|
48
|
+
return falharJsonCanonico("referencia_ciclica", caminho);
|
|
49
|
+
}
|
|
50
|
+
visitados.add(valor);
|
|
51
|
+
try {
|
|
52
|
+
if (Array.isArray(valor)) {
|
|
53
|
+
const itens = [];
|
|
54
|
+
for (let indice = 0; indice < valor.length; indice += 1) {
|
|
55
|
+
if (!Object.hasOwn(valor, indice)) {
|
|
56
|
+
falharJsonCanonico("array_esparso", `${caminho}[${indice}]`);
|
|
57
|
+
}
|
|
58
|
+
itens.push(serializarCanonico(valor[indice], `${caminho}[${indice}]`, visitados));
|
|
59
|
+
}
|
|
60
|
+
return `[${itens.join(",")}]`;
|
|
61
|
+
}
|
|
62
|
+
const prototipo = Object.getPrototypeOf(valor);
|
|
63
|
+
if (prototipo !== Object.prototype && prototipo !== null) {
|
|
64
|
+
return falharJsonCanonico("objeto_nao_plano", caminho);
|
|
65
|
+
}
|
|
66
|
+
const objeto = valor;
|
|
67
|
+
const campos = Object.keys(objeto)
|
|
68
|
+
.sort()
|
|
69
|
+
.map((chave) => (`${JSON.stringify(chave)}:${serializarCanonico(objeto[chave], `${caminho}.${chave}`, visitados)}`));
|
|
70
|
+
return `{${campos.join(",")}}`;
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
visitados.delete(valor);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export function serializarJsonCanonicoCacheDrift(valor) {
|
|
77
|
+
return serializarCanonico(valor, "$", new Set());
|
|
78
|
+
}
|
|
79
|
+
export function digestJsonCanonicoCacheDrift(valor) {
|
|
80
|
+
return `sha256:${createHash("sha256")
|
|
81
|
+
.update(serializarJsonCanonicoCacheDrift(valor))
|
|
82
|
+
.digest("hex")}`;
|
|
83
|
+
}
|
|
84
|
+
export function criarChaveCacheDrift(entrada) {
|
|
85
|
+
if (!entrada.fingerprintConteudo.trim()) {
|
|
86
|
+
throw new TypeError("fingerprint_conteudo_cache_drift_vazio");
|
|
87
|
+
}
|
|
88
|
+
return digestJsonCanonicoCacheDrift({
|
|
89
|
+
schema: SCHEMA_CACHE_DRIFT,
|
|
90
|
+
fingerprintConteudo: entrada.fingerprintConteudo,
|
|
91
|
+
identidade: entrada.identidade,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function nomeArquivoDaChave(chave) {
|
|
95
|
+
if (!PADRAO_DIGEST.test(chave)) {
|
|
96
|
+
throw new TypeError(`chave_cache_drift_invalida:${chave}`);
|
|
97
|
+
}
|
|
98
|
+
return `${chave.slice("sha256:".length)}.json`;
|
|
99
|
+
}
|
|
100
|
+
function registroObjeto(valor) {
|
|
101
|
+
return typeof valor === "object" && valor !== null && !Array.isArray(valor);
|
|
102
|
+
}
|
|
103
|
+
function erroEhAusencia(erro) {
|
|
104
|
+
return ["ENOENT", "ENOTDIR"].includes(erro.code ?? "");
|
|
105
|
+
}
|
|
106
|
+
class CacheDriftImplementacao {
|
|
107
|
+
baseProjeto;
|
|
108
|
+
politica;
|
|
109
|
+
limiteBytes;
|
|
110
|
+
observador;
|
|
111
|
+
emVoo = new Map();
|
|
112
|
+
contadores = {
|
|
113
|
+
hits: 0,
|
|
114
|
+
misses: 0,
|
|
115
|
+
corruptos: 0,
|
|
116
|
+
gravacoes: 0,
|
|
117
|
+
errosGravacao: 0,
|
|
118
|
+
calculosCompartilhados: 0,
|
|
119
|
+
};
|
|
120
|
+
constructor(opcoes) {
|
|
121
|
+
this.baseProjeto = path.resolve(opcoes.baseProjeto);
|
|
122
|
+
this.politica = normalizarPolitica(opcoes.politica);
|
|
123
|
+
this.limiteBytes = normalizarLimiteBytes(opcoes.limiteBytes);
|
|
124
|
+
this.observador = opcoes.observador;
|
|
125
|
+
}
|
|
126
|
+
chave(entrada) {
|
|
127
|
+
return criarChaveCacheDrift(entrada);
|
|
128
|
+
}
|
|
129
|
+
caminhoRelativo(chave) {
|
|
130
|
+
return path.join(DIRETORIO_CACHE_DRIFT, nomeArquivoDaChave(chave));
|
|
131
|
+
}
|
|
132
|
+
obterOuCalcular(entrada, calcular) {
|
|
133
|
+
const chave = this.chave(entrada);
|
|
134
|
+
const existente = this.emVoo.get(chave);
|
|
135
|
+
if (existente) {
|
|
136
|
+
this.contadores.calculosCompartilhados += 1;
|
|
137
|
+
return existente;
|
|
138
|
+
}
|
|
139
|
+
const execucao = this.executar(chave, calcular);
|
|
140
|
+
this.emVoo.set(chave, execucao);
|
|
141
|
+
const limpar = () => {
|
|
142
|
+
if (this.emVoo.get(chave) === execucao) {
|
|
143
|
+
this.emVoo.delete(chave);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
void execucao.then(limpar, limpar);
|
|
147
|
+
return execucao;
|
|
148
|
+
}
|
|
149
|
+
metricas() {
|
|
150
|
+
return { ...this.contadores };
|
|
151
|
+
}
|
|
152
|
+
async executar(chave, calcular) {
|
|
153
|
+
const caminhoRelativo = this.caminhoRelativo(chave);
|
|
154
|
+
if (this.politica === "off") {
|
|
155
|
+
this.registrarMiss(chave, caminhoRelativo, "politica_off");
|
|
156
|
+
return {
|
|
157
|
+
chave,
|
|
158
|
+
valor: await calcular(),
|
|
159
|
+
origem: "calculado",
|
|
160
|
+
politica: this.politica,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (this.politica === "auto") {
|
|
164
|
+
const leitura = await this.lerCache(chave, caminhoRelativo, true);
|
|
165
|
+
if (leitura.estado === "hit") {
|
|
166
|
+
return {
|
|
167
|
+
chave,
|
|
168
|
+
valor: leitura.payload,
|
|
169
|
+
origem: "cache",
|
|
170
|
+
politica: this.politica,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this.registrarMiss(chave, caminhoRelativo, "politica_refresh");
|
|
176
|
+
}
|
|
177
|
+
const valor = await calcular();
|
|
178
|
+
await this.gravarCache(chave, caminhoRelativo, valor);
|
|
179
|
+
return {
|
|
180
|
+
chave,
|
|
181
|
+
valor,
|
|
182
|
+
origem: "calculado",
|
|
183
|
+
politica: this.politica,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async lerCache(chave, caminhoRelativo, registrarEventos) {
|
|
187
|
+
let caminhoAbsoluto = path.resolve(this.baseProjeto, caminhoRelativo);
|
|
188
|
+
try {
|
|
189
|
+
const [destino] = await validarDestinosEscritaWorkspace(this.baseProjeto, [caminhoRelativo]);
|
|
190
|
+
caminhoAbsoluto = destino.caminhoAbsoluto;
|
|
191
|
+
if (!destino.existe) {
|
|
192
|
+
if (registrarEventos) {
|
|
193
|
+
this.registrarMiss(chave, caminhoRelativo, "arquivo_ausente");
|
|
194
|
+
}
|
|
195
|
+
return { estado: "miss" };
|
|
196
|
+
}
|
|
197
|
+
const informacao = await lstat(caminhoAbsoluto);
|
|
198
|
+
if (!informacao.isFile() || informacao.isSymbolicLink()) {
|
|
199
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "nao_eh_arquivo_regular", registrarEventos);
|
|
200
|
+
}
|
|
201
|
+
if (informacao.size > this.limiteBytes) {
|
|
202
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "limite_bytes_excedido", registrarEventos);
|
|
203
|
+
}
|
|
204
|
+
const bytes = await readFile(caminhoAbsoluto);
|
|
205
|
+
if (bytes.byteLength > this.limiteBytes) {
|
|
206
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "limite_bytes_excedido_apos_leitura", registrarEventos);
|
|
207
|
+
}
|
|
208
|
+
let bruto;
|
|
209
|
+
try {
|
|
210
|
+
bruto = JSON.parse(bytes.toString("utf8"));
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "json_invalido", registrarEventos);
|
|
214
|
+
}
|
|
215
|
+
if (!registroObjeto(bruto)) {
|
|
216
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "envelope_invalido", registrarEventos);
|
|
217
|
+
}
|
|
218
|
+
if (bruto.schema !== SCHEMA_CACHE_DRIFT || bruto.key !== chave) {
|
|
219
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "schema_ou_chave_divergente", registrarEventos);
|
|
220
|
+
}
|
|
221
|
+
if (typeof bruto.payloadDigest !== "string" || !PADRAO_DIGEST.test(bruto.payloadDigest)) {
|
|
222
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "payload_digest_invalido", registrarEventos);
|
|
223
|
+
}
|
|
224
|
+
let digestCalculado;
|
|
225
|
+
try {
|
|
226
|
+
digestCalculado = digestJsonCanonicoCacheDrift(bruto.payload);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "payload_nao_canonico", registrarEventos);
|
|
230
|
+
}
|
|
231
|
+
if (digestCalculado !== bruto.payloadDigest) {
|
|
232
|
+
return this.registrarCorrupto(chave, caminhoRelativo, "payload_digest_divergente", registrarEventos);
|
|
233
|
+
}
|
|
234
|
+
if (registrarEventos) {
|
|
235
|
+
this.contadores.hits += 1;
|
|
236
|
+
emitirEvento(this.observador, {
|
|
237
|
+
tipo: "cache.hit",
|
|
238
|
+
chave,
|
|
239
|
+
caminho: caminhoAbsoluto,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return { estado: "hit", payload: bruto.payload };
|
|
243
|
+
}
|
|
244
|
+
catch (erro) {
|
|
245
|
+
if (registrarEventos) {
|
|
246
|
+
this.registrarMiss(chave, caminhoRelativo, erroEhAusencia(erro) ? "arquivo_ausente" : "cache_indisponivel");
|
|
247
|
+
}
|
|
248
|
+
return { estado: "miss" };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
registrarCorrupto(chave, caminhoRelativo, motivo, registrarEventos) {
|
|
252
|
+
if (registrarEventos) {
|
|
253
|
+
this.contadores.misses += 1;
|
|
254
|
+
this.contadores.corruptos += 1;
|
|
255
|
+
emitirEvento(this.observador, {
|
|
256
|
+
tipo: "cache.corrupt",
|
|
257
|
+
chave,
|
|
258
|
+
caminho: path.resolve(this.baseProjeto, caminhoRelativo),
|
|
259
|
+
motivo,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
return { estado: "corrupt" };
|
|
263
|
+
}
|
|
264
|
+
registrarMiss(chave, caminhoRelativo, motivo) {
|
|
265
|
+
this.contadores.misses += 1;
|
|
266
|
+
emitirEvento(this.observador, {
|
|
267
|
+
tipo: "cache.miss",
|
|
268
|
+
chave,
|
|
269
|
+
caminho: path.resolve(this.baseProjeto, caminhoRelativo),
|
|
270
|
+
motivo,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async gravarCache(chave, caminhoRelativo, payload) {
|
|
274
|
+
let envelope;
|
|
275
|
+
let conteudo;
|
|
276
|
+
try {
|
|
277
|
+
envelope = {
|
|
278
|
+
schema: SCHEMA_CACHE_DRIFT,
|
|
279
|
+
key: chave,
|
|
280
|
+
payload,
|
|
281
|
+
payloadDigest: digestJsonCanonicoCacheDrift(payload),
|
|
282
|
+
};
|
|
283
|
+
conteudo = JSON.stringify(envelope);
|
|
284
|
+
if (Buffer.byteLength(conteudo, "utf8") > this.limiteBytes) {
|
|
285
|
+
this.contadores.errosGravacao += 1;
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
// Resultado não serializável continua válido; apenas não é cacheado.
|
|
291
|
+
this.contadores.errosGravacao += 1;
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
try {
|
|
295
|
+
await escreverArquivoWorkspaceSeguro(this.baseProjeto, caminhoRelativo, conteudo, { sobrescrever: true });
|
|
296
|
+
this.contadores.gravacoes += 1;
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
// Outra execução pode ter publicado a mesma chave. Um vencedor válido
|
|
300
|
+
// encerra a corrida; qualquer outra falha permanece apenas perda de cache.
|
|
301
|
+
const vencedor = await this.lerCache(chave, caminhoRelativo, false);
|
|
302
|
+
if (vencedor.estado !== "hit") {
|
|
303
|
+
this.contadores.errosGravacao += 1;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
export function criarCacheDrift(opcoes) {
|
|
309
|
+
return new CacheDriftImplementacao(opcoes);
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=driftCache.js.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { ConteudoArquivoDrift, ObservadorOperacaoDrift } from "./driftCatalogo.js";
|
|
2
|
+
import { type PoliticaCacheDrift, type ValorJson } from "./driftCache.js";
|
|
3
|
+
export declare const FILE_INDEX_SCHEMA: 2;
|
|
4
|
+
export declare const SCHEMA_MANIFESTO_ARQUIVOS_DRIFT: "sema.drift-file-cache/v2";
|
|
5
|
+
export declare const SCHEMA_GRUPO_INDICE_DRIFT: "sema.drift-index-group-cache/v2";
|
|
6
|
+
export declare const DIRETORIO_CACHE_INCREMENTAL_DRIFT: string;
|
|
7
|
+
export declare const DIRETORIO_IDENTIDADES_CACHE_INCREMENTAL_DRIFT: string;
|
|
8
|
+
export declare function caminhoManifestoArquivosDrift(identidadeDigest: string): string;
|
|
9
|
+
export declare function caminhoManifestoGruposDrift(identidadeDigest: string): string;
|
|
10
|
+
export interface AssinaturaArquivoDrift {
|
|
11
|
+
size: string;
|
|
12
|
+
mtimeNs: string;
|
|
13
|
+
ctimeNs: string;
|
|
14
|
+
dev: string;
|
|
15
|
+
ino: string;
|
|
16
|
+
}
|
|
17
|
+
export interface EstadoArquivoCacheDrift<T> {
|
|
18
|
+
caminho: string;
|
|
19
|
+
contentHash: string;
|
|
20
|
+
valor: T;
|
|
21
|
+
origem: "metadata_hit" | "content_hit" | "calculado";
|
|
22
|
+
}
|
|
23
|
+
export interface EstadoGrupoCacheDrift<T> {
|
|
24
|
+
chave: string;
|
|
25
|
+
valor: T;
|
|
26
|
+
origem: "cache" | "calculado";
|
|
27
|
+
}
|
|
28
|
+
export interface MetricasCacheIncrementalDrift {
|
|
29
|
+
metadataHits: number;
|
|
30
|
+
contentHits: number;
|
|
31
|
+
fileMisses: number;
|
|
32
|
+
groupHits: number;
|
|
33
|
+
groupMisses: number;
|
|
34
|
+
corruptos: number;
|
|
35
|
+
extracoesArquivo: number;
|
|
36
|
+
extracoesGrupo: number;
|
|
37
|
+
gravacoes: number;
|
|
38
|
+
errosGravacao: number;
|
|
39
|
+
}
|
|
40
|
+
export interface OpcoesCacheIncrementalDrift {
|
|
41
|
+
baseProjeto: string;
|
|
42
|
+
politica: PoliticaCacheDrift;
|
|
43
|
+
identidade: ValorJson;
|
|
44
|
+
observador?: ObservadorOperacaoDrift;
|
|
45
|
+
}
|
|
46
|
+
export interface ResolverArquivoCacheDrift<T> {
|
|
47
|
+
arquivo: string;
|
|
48
|
+
analise: string;
|
|
49
|
+
assinar?: () => Promise<AssinaturaArquivoDrift>;
|
|
50
|
+
ler: () => Promise<ConteudoArquivoDrift>;
|
|
51
|
+
extrair: (conteudo: ConteudoArquivoDrift) => Promise<T> | T;
|
|
52
|
+
validar: (valor: unknown) => valor is T;
|
|
53
|
+
}
|
|
54
|
+
export interface ResolverGrupoCacheDrift<T> {
|
|
55
|
+
membros: Array<{
|
|
56
|
+
caminho: string;
|
|
57
|
+
contentHash: string;
|
|
58
|
+
}>;
|
|
59
|
+
calcular: () => Promise<T>;
|
|
60
|
+
validar: (valor: unknown) => valor is T;
|
|
61
|
+
}
|
|
62
|
+
export declare function obterAssinaturaArquivoDrift(arquivo: string): Promise<AssinaturaArquivoDrift>;
|
|
63
|
+
export declare class CacheIncrementalDrift {
|
|
64
|
+
readonly identidadeDigest: string;
|
|
65
|
+
readonly politica: PoliticaCacheDrift;
|
|
66
|
+
private readonly baseProjeto;
|
|
67
|
+
private readonly baseProjetoReal;
|
|
68
|
+
private readonly observador?;
|
|
69
|
+
private readonly caminhoManifestoArquivos;
|
|
70
|
+
private readonly caminhoManifestoGrupos;
|
|
71
|
+
private manifesto?;
|
|
72
|
+
private manifestoEmVoo?;
|
|
73
|
+
private manifestoSujo;
|
|
74
|
+
private readonly arquivosSujos;
|
|
75
|
+
private manifestoGrupos?;
|
|
76
|
+
private manifestoGruposEmVoo?;
|
|
77
|
+
private manifestoGruposSujo;
|
|
78
|
+
private readonly gruposSujos;
|
|
79
|
+
private readonly arquivosEmVoo;
|
|
80
|
+
private readonly metricasAtuais;
|
|
81
|
+
constructor(opcoes: OpcoesCacheIncrementalDrift);
|
|
82
|
+
metricas(): MetricasCacheIncrementalDrift;
|
|
83
|
+
resolverArquivo<T>(opcoes: ResolverArquivoCacheDrift<T>): Promise<EstadoArquivoCacheDrift<T>>;
|
|
84
|
+
private resolverArquivoInterno;
|
|
85
|
+
resolverGrupo<T>(opcoes: ResolverGrupoCacheDrift<T>): Promise<EstadoGrupoCacheDrift<T>>;
|
|
86
|
+
finalizar(): Promise<void>;
|
|
87
|
+
private chaveEnvelope;
|
|
88
|
+
private lerManifestoArquivosAtual;
|
|
89
|
+
private lerManifestoGruposAtual;
|
|
90
|
+
private gravarManifestoArquivosComMerge;
|
|
91
|
+
private gravarManifestoGruposComMerge;
|
|
92
|
+
private obterManifesto;
|
|
93
|
+
private carregarManifesto;
|
|
94
|
+
private obterManifestoGrupos;
|
|
95
|
+
private carregarManifestoGrupos;
|
|
96
|
+
private registrarCorrupto;
|
|
97
|
+
private validarArquivoNoWorkspace;
|
|
98
|
+
}
|