@orkastery/cli 0.4.3 → 0.5.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.
- package/adapters/README.md +11 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +3 -1
- package/adapters/claude-code/agents/ork-check.md +1 -1
- package/adapters/claude-code/agents/ork-go.md +2 -2
- package/adapters/claude-code/agents/ork-goal.md +1 -1
- package/adapters/claude-code/agents/ork-master.md +1 -1
- package/adapters/claude-code/agents/ork-plan.md +1 -1
- package/adapters/claude-code/agents/ork-ship.md +1 -1
- package/adapters/claude-code/commands/master.md +11 -8
- package/adapters/claude-code/commands/ork.md +8 -0
- package/adapters/claude-code/commands/ship.md +2 -2
- package/adapters/codex/skills/ork/SKILL.md +12 -1
- package/adapters/hermes/README.md +3 -0
- package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
- package/adapters/hermes/bin/ork-brain.sh +3 -0
- package/adapters/hermes/bin/ork-maestro.sh +4 -1
- package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
- package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
- package/adapters/hermes/hermes.plugin.json +2 -0
- package/adapters/hermes/hitl-ingress/__init__.py +36 -3
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
- package/adapters/openclaw/README.md +34 -2
- package/adapters/openclaw/dist/hitl-ingress.js +37 -3
- package/adapters/openclaw/dist/index.js +92 -20
- package/adapters/openclaw/openclaw.plugin.json +10 -1
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +32 -3
- package/adapters/openclaw/src/index.ts +108 -20
- package/assets/docs/padroes/documentacao-de-produto.md +2 -2
- package/assets/docs/padroes/roadmap-de-produto.md +1 -1
- package/assets/docs/produto/_modelo-feature.md +2 -0
- package/assets/orkmind_bridge.py +214 -1
- package/dist/adapters/claude-bg.js +6 -3
- package/dist/board.js +74 -0
- package/dist/branch-de-estado.js +5 -4
- package/dist/busca-semantica.js +161 -0
- package/dist/ci.js +141 -10
- package/dist/company-brain-cli.js +27 -2
- package/dist/company-brain-context.js +132 -0
- package/dist/company-brain-dossie.js +376 -0
- package/dist/company-brain-mcp.js +4 -1
- package/dist/conducao.js +71 -18
- package/dist/decisao-autonoma.js +42 -0
- package/dist/docs.js +64 -22
- package/dist/doctor.js +33 -0
- package/dist/entrega-pr.js +109 -5
- package/dist/experiencia-instalacao.js +256 -0
- package/dist/experiencia.js +72 -0
- package/dist/fabrica-estado.js +43 -10
- package/dist/fechamento.js +105 -0
- package/dist/forja.js +435 -0
- package/dist/gates.js +9 -1
- package/dist/hitl-classificacao.js +11 -1
- package/dist/hitl-contract.js +50 -7
- package/dist/hitl-curto.js +158 -0
- package/dist/hitl-gates.js +67 -1
- package/dist/hitl-lote.js +30 -15
- package/dist/hitl-presentation.js +10 -7
- package/dist/hitl-resumo.js +33 -12
- package/dist/hitl-texto-livre.js +150 -0
- package/dist/hosts.js +86 -1
- package/dist/index.js +602 -38
- package/dist/indice-vetorial.js +317 -0
- package/dist/init.js +13 -0
- package/dist/integracoes-locais.js +1 -1
- package/dist/intelligence-benchmark-contract.js +570 -0
- package/dist/intelligence-graph-cli.js +430 -0
- package/dist/intelligence-graph-contract.js +577 -0
- package/dist/intelligence-graph-extract-md.js +469 -0
- package/dist/intelligence-graph-extract-ts.js +810 -0
- package/dist/intelligence-graph-extract.js +369 -0
- package/dist/intelligence-graph-index.js +512 -0
- package/dist/intelligence-graph-parsers.js +327 -0
- package/dist/intelligence-graph-query.js +344 -0
- package/dist/intelligence-graph-repo.js +187 -0
- package/dist/leases.js +84 -0
- package/dist/ledger.js +14 -0
- package/dist/maestro-cli.js +10 -1
- package/dist/maestro-contract.js +5 -1
- package/dist/maestro-discovery.js +16 -2
- package/dist/maestro-snapshot.js +6 -2
- package/dist/manifest.js +142 -5
- package/dist/master-batch.js +3 -2
- package/dist/master-digest.js +2 -2
- package/dist/master-nota.js +203 -0
- package/dist/master.js +4 -0
- package/dist/mcp-experiencia.js +164 -0
- package/dist/mcp-git.js +4 -0
- package/dist/mcp-install.js +3 -1
- package/dist/mcp-maestro.js +3 -2
- package/dist/mcp-server.js +84 -5
- package/dist/memoria.js +147 -1
- package/dist/network-roadmap.js +907 -0
- package/dist/ocupacao.js +38 -2
- package/dist/onboarding.js +113 -7
- package/dist/orkmind.js +165 -9
- package/dist/phase.js +166 -13
- package/dist/policies.js +2 -0
- package/dist/projeto-alvo.js +551 -0
- package/dist/prompts.js +1 -1
- package/dist/pulse-consentimento.js +4 -2
- package/dist/pulse-delivery.js +5 -0
- package/dist/pulse-resposta.js +674 -49
- package/dist/pulse.js +21 -0
- package/dist/retry.js +51 -8
- package/dist/roadmap-reservas.js +262 -20
- package/dist/roadmap-status.js +213 -0
- package/dist/thread-close.js +3 -0
- package/dist/verify.js +4 -3
- package/eval/casos/orchestration-experience-pt-br.json +48 -0
- package/eval/casos/orchestration-experience.json +48 -0
- package/package.json +1 -1
- package/schemas/code-artifact-graph.v1.schema.json +581 -0
- package/schemas/graph-benchmark.v1.schema.json +2240 -0
- package/schemas/maestro-snapshot.schema.json +23 -0
- package/skills/README.md +7 -5
- package/skills/core/onboarding/SKILL.md +7 -0
- package/skills/core/orchestration-experience/SKILL.md +113 -0
- package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/go-implementation/SKILL.md +2 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.textoAceito = exports.LACUNAS_SO_CONTAGEM = exports.EXTENSOES_MD = exports.EXTENSOES_TS = exports.CONFIG_SCHEMA = exports.RELATORIO_SCHEMA = exports.VERSAO_KG2 = exports.EXTRATOR_ARQUIVOS = exports.EXTRATOR_ID = exports.EXTRATOR_MD = exports.EXTRATOR_TS = void 0;
|
|
4
|
+
exports.textoCurto = textoCurto;
|
|
5
|
+
exports.extensaoDe = extensaoDe;
|
|
6
|
+
exports.idDeBlob = idDeBlob;
|
|
7
|
+
exports.decodificarUtf8 = decodificarUtf8;
|
|
8
|
+
exports.extrairGrafo = extrairGrafo;
|
|
9
|
+
/**
|
|
10
|
+
* RM-031 KG2 (D1, D7 a D10): extracao deterministica do grafo `ork.code-artifact-graph/v1`.
|
|
11
|
+
*
|
|
12
|
+
* Modulo puro: recebe os bytes das fontes e o compilador TypeScript por parametro (D1), sem abrir
|
|
13
|
+
* arquivo, rede ou processo. As fontes sao ordenadas antes de tudo e os IDs saem do contrato
|
|
14
|
+
* (`derivarIds`), entao a ordem de leitura nao muda o grafo nem o relatorio. O que nenhum extrator
|
|
15
|
+
* prova vira diagnostico do contrato ou lacuna do relatorio (D7), nunca aresta nem no fabricado.
|
|
16
|
+
*/
|
|
17
|
+
const node_crypto_1 = require("node:crypto");
|
|
18
|
+
const intelligence_graph_contract_1 = require("./intelligence-graph-contract");
|
|
19
|
+
const intelligence_graph_extract_md_1 = require("./intelligence-graph-extract-md");
|
|
20
|
+
const intelligence_graph_extract_ts_1 = require("./intelligence-graph-extract-ts");
|
|
21
|
+
exports.EXTRATOR_TS = 'ork.ts-ast';
|
|
22
|
+
exports.EXTRATOR_MD = 'ork.md-structure';
|
|
23
|
+
exports.EXTRATOR_ID = 'ork.id-mention';
|
|
24
|
+
/** D9: declara o arquivo do manifesto que nenhum extrator leu. */
|
|
25
|
+
exports.EXTRATOR_ARQUIVOS = 'ork.repo-files';
|
|
26
|
+
/** Versao da regra de extracao; a do compilador entra no `extractor_version` do `ork.ts-ast`. */
|
|
27
|
+
exports.VERSAO_KG2 = '1.0.0';
|
|
28
|
+
exports.RELATORIO_SCHEMA = 'ork.graph-extraction-report/v0';
|
|
29
|
+
exports.CONFIG_SCHEMA = 'ork.graph-extraction-config/v0';
|
|
30
|
+
exports.EXTENSOES_TS = ['.cjs', '.cts', '.js', '.jsx', '.mjs', '.mts', '.ts', '.tsx'];
|
|
31
|
+
exports.EXTENSOES_MD = ['.markdown', '.md'];
|
|
32
|
+
/** D7: categorias de lacuna volumosas saem so na contagem; as demais saem tambem listadas. */
|
|
33
|
+
exports.LACUNAS_SO_CONTAGEM = new Set([
|
|
34
|
+
'chamada-fora-de-simbolo', 'chamada-nao-resolvida', 'chamada-alvo-fora-do-grafo', 'chamada-por-tipo', 'import-sem-simbolo',
|
|
35
|
+
'id-sem-artefato', 'link-externo',
|
|
36
|
+
]);
|
|
37
|
+
function falha(codigo, onde) {
|
|
38
|
+
throw new Error(onde ? `${codigo} em ${onde}` : codigo);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Aninhamento extremo estoura a pilha do compilador ou do analisador (o binder do TypeScript e
|
|
42
|
+
* recursivo): a extracao falha inteira com erro tipado, nunca com grafo parcial (D10).
|
|
43
|
+
*/
|
|
44
|
+
function semEstouro(extrator, f) {
|
|
45
|
+
try {
|
|
46
|
+
return f();
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
if (e instanceof RangeError && /call stack/i.test(e.message))
|
|
50
|
+
falha('extracao.limite.pilha', extrator);
|
|
51
|
+
throw e;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Replica da regra de texto do contrato (controles, marcas invisiveis, surrogate isolado), para o
|
|
56
|
+
* produtor descartar referencia que o contrato recusaria. O corpus do KG1 e a autoridade.
|
|
57
|
+
*/
|
|
58
|
+
const CONTROLE = /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u180e\u200b\u200e\u200f\u2028\u2029\u202a-\u202e\u2060-\u206f\ufeff\ufff9-\ufffb]/;
|
|
59
|
+
const SURROGATE_ISOLADO = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
60
|
+
const textoAceito = (t) => !CONTROLE.test(t) && !SURROGATE_ISOLADO.test(t);
|
|
61
|
+
exports.textoAceito = textoAceito;
|
|
62
|
+
/** Texto curto que cabe em `reference` ou `fragment`; fora disso, `null` (nunca truncado). */
|
|
63
|
+
function textoCurto(t) {
|
|
64
|
+
const limpo = t.trim();
|
|
65
|
+
return limpo.length >= 1 && limpo.length <= intelligence_graph_contract_1.GRAFO_LIMITES.fragmento && (0, exports.textoAceito)(limpo) ? limpo : null;
|
|
66
|
+
}
|
|
67
|
+
/** Extensao do nome do arquivo em minusculas (`.ts`); arquivo oculto sem ponto no meio nao tem. */
|
|
68
|
+
function extensaoDe(caminho) {
|
|
69
|
+
const nome = caminho.slice(caminho.lastIndexOf('/') + 1), i = nome.lastIndexOf('.');
|
|
70
|
+
return i <= 0 ? '' : nome.slice(i).toLowerCase();
|
|
71
|
+
}
|
|
72
|
+
/** D8: id de blob do Git, calculado dos bytes; igual ao `git hash-object --no-filters` do arquivo. */
|
|
73
|
+
function idDeBlob(bytes) {
|
|
74
|
+
return (0, node_crypto_1.createHash)('sha1').update(`blob ${bytes.length}\0`).update(bytes).digest('hex');
|
|
75
|
+
}
|
|
76
|
+
const sha256 = (b) => (0, node_crypto_1.createHash)('sha256').update(b).digest('hex');
|
|
77
|
+
/** UTF-8 estrito, com o BOM preservado para os offsets baterem com os bytes. */
|
|
78
|
+
function decodificarUtf8(bytes) {
|
|
79
|
+
try {
|
|
80
|
+
return new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Converte offset UTF-16 do texto em offset de byte UTF-8 e em linha (1-based). */
|
|
87
|
+
class MapaDoTexto {
|
|
88
|
+
texto;
|
|
89
|
+
tamanho;
|
|
90
|
+
bytes = null;
|
|
91
|
+
quebras = null;
|
|
92
|
+
constructor(texto, tamanho) {
|
|
93
|
+
this.texto = texto;
|
|
94
|
+
this.tamanho = tamanho;
|
|
95
|
+
}
|
|
96
|
+
byte(i) {
|
|
97
|
+
if (this.tamanho === this.texto.length)
|
|
98
|
+
return i;
|
|
99
|
+
if (!this.bytes) {
|
|
100
|
+
const t = this.texto, acc = new Uint32Array(t.length + 1);
|
|
101
|
+
for (let j = 0; j < t.length; j++) {
|
|
102
|
+
const c = t.charCodeAt(j);
|
|
103
|
+
// Par de surrogates e um code point de 4 bytes; o texto veio de UTF-8 valido, sem surrogate isolado.
|
|
104
|
+
if (c >= 0xd800 && c <= 0xdbff && j + 1 < t.length) {
|
|
105
|
+
acc[j + 1] = acc[j] + 4;
|
|
106
|
+
acc[j + 2] = acc[j + 1];
|
|
107
|
+
j++;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
acc[j + 1] = acc[j] + (c < 0x80 ? 1 : c < 0x800 ? 2 : 3);
|
|
111
|
+
}
|
|
112
|
+
this.bytes = acc;
|
|
113
|
+
}
|
|
114
|
+
return this.bytes[i];
|
|
115
|
+
}
|
|
116
|
+
linha(i) {
|
|
117
|
+
if (!this.quebras) {
|
|
118
|
+
const q = [];
|
|
119
|
+
for (let j = this.texto.indexOf('\n'); j >= 0; j = this.texto.indexOf('\n', j + 1))
|
|
120
|
+
q.push(j);
|
|
121
|
+
this.quebras = q;
|
|
122
|
+
}
|
|
123
|
+
let baixo = 0, alto = this.quebras.length;
|
|
124
|
+
while (baixo < alto) {
|
|
125
|
+
const meio = (baixo + alto) >> 1;
|
|
126
|
+
if (this.quebras[meio] < i)
|
|
127
|
+
baixo = meio + 1;
|
|
128
|
+
else
|
|
129
|
+
alto = meio;
|
|
130
|
+
}
|
|
131
|
+
return baixo + 1;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const chaveDoNo = (r) => (0, intelligence_graph_contract_1.canonico)([r.kind, r.path, r.fragment]);
|
|
135
|
+
const zeros = '0'.repeat(64);
|
|
136
|
+
function contagemVazia(chaves) {
|
|
137
|
+
return Object.fromEntries(chaves.map((k) => [k, 0]));
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Extrai o grafo das fontes fornecidas. Lanca `extracao.*` para entrada invalida ou teto do
|
|
141
|
+
* contrato estourado (D10), e `grafo.*` se o resultado violar o contrato (defeito do extrator).
|
|
142
|
+
*/
|
|
143
|
+
function extrairGrafo(entrada, parser) {
|
|
144
|
+
const { ts, unicode, markdown, javascript } = parser;
|
|
145
|
+
if (!/^[0-9]+(\.[0-9]+)*$/.test(unicode))
|
|
146
|
+
falha('extracao.entrada.unicode-invalido');
|
|
147
|
+
if (!/^[0-9A-Za-z][0-9A-Za-z.-]{0,40}$/.test(markdown.versao) || typeof markdown.analisar !== 'function'
|
|
148
|
+
|| typeof markdown.referencia !== 'function')
|
|
149
|
+
falha('extracao.entrada.markdown-invalido');
|
|
150
|
+
if (!javascript || !/^node\.[0-9]+(\.[0-9]+)*$/.test(javascript.versao) || typeof javascript.sintaxe !== 'function') {
|
|
151
|
+
falha('extracao.entrada.javascript-invalido');
|
|
152
|
+
}
|
|
153
|
+
const acl = [...new Set(entrada.acl_refs)].sort(intelligence_graph_contract_1.compararUtf8);
|
|
154
|
+
const access = { tenant_id: entrada.tenant_id, acl_refs: acl };
|
|
155
|
+
const authority = `git:${entrada.repository_id}`;
|
|
156
|
+
const fontes = [...entrada.fontes].sort((a, b) => (0, intelligence_graph_contract_1.compararUtf8)(a.path, b.path));
|
|
157
|
+
for (let i = 1; i < fontes.length; i++)
|
|
158
|
+
if (fontes[i - 1].path === fontes[i].path)
|
|
159
|
+
falha('extracao.entrada.fonte-duplicada');
|
|
160
|
+
// O contrato recusa o grafo inteiro por um caminho ruim; aqui o caminho sai e fica declarado.
|
|
161
|
+
const excluidas = (entrada.excluidas ?? []).map((e) => ({ path: e.path, motivo: e.motivo }));
|
|
162
|
+
const validas = fontes.filter((f) => {
|
|
163
|
+
const ok = f.path.length <= intelligence_graph_contract_1.GRAFO_LIMITES.caminho && (0, intelligence_graph_contract_1.caminhoValido)(f.path);
|
|
164
|
+
if (!ok)
|
|
165
|
+
excluidas.push({ path: f.path, motivo: 'caminho-recusado' });
|
|
166
|
+
return ok;
|
|
167
|
+
});
|
|
168
|
+
const porNfc = new Map();
|
|
169
|
+
for (const f of validas)
|
|
170
|
+
porNfc.set(f.path.normalize('NFC'), (porNfc.get(f.path.normalize('NFC')) ?? 0) + 1);
|
|
171
|
+
const aceitas = validas.filter((f) => {
|
|
172
|
+
const ok = porNfc.get(f.path.normalize('NFC')) === 1;
|
|
173
|
+
if (!ok)
|
|
174
|
+
excluidas.push({ path: f.path, motivo: 'caminho-ambiguo' });
|
|
175
|
+
return ok;
|
|
176
|
+
});
|
|
177
|
+
if (aceitas.length === 0)
|
|
178
|
+
falha('extracao.entrada.sem-fontes');
|
|
179
|
+
if (aceitas.length > intelligence_graph_contract_1.GRAFO_LIMITES.manifesto)
|
|
180
|
+
falha('extracao.limite.manifesto');
|
|
181
|
+
const manifesto = new Map();
|
|
182
|
+
for (const f of aceitas) {
|
|
183
|
+
manifesto.set(f.path, {
|
|
184
|
+
path: f.path, authority, source_hash: sha256(f.bytes), source_version: idDeBlob(f.bytes), size_bytes: f.bytes.length, access,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const bytesDe = new Map(aceitas.map((f) => [f.path, f.bytes]));
|
|
188
|
+
const textos = new Map();
|
|
189
|
+
const texto = (p) => {
|
|
190
|
+
if (!textos.has(p)) {
|
|
191
|
+
const b = bytesDe.get(p);
|
|
192
|
+
textos.set(p, b ? decodificarUtf8(b) : null);
|
|
193
|
+
}
|
|
194
|
+
return textos.get(p) ?? undefined;
|
|
195
|
+
};
|
|
196
|
+
const achados = { nos: [], arestas: [], diagnosticos: [], lacunas: [] };
|
|
197
|
+
// Laco, nao `push(...lista)`: lista grande estouraria a pilha antes do teto tipado do contrato.
|
|
198
|
+
const juntar = (a) => {
|
|
199
|
+
for (const x of a.nos)
|
|
200
|
+
achados.nos.push(x);
|
|
201
|
+
for (const x of a.arestas)
|
|
202
|
+
achados.arestas.push(x);
|
|
203
|
+
for (const x of a.diagnosticos)
|
|
204
|
+
achados.diagnosticos.push(x);
|
|
205
|
+
for (const x of a.lacunas)
|
|
206
|
+
achados.lacunas.push(x);
|
|
207
|
+
};
|
|
208
|
+
const caminhos = aceitas.map((f) => f.path);
|
|
209
|
+
const fontesTs = [], fontesMd = [];
|
|
210
|
+
for (const p of caminhos) {
|
|
211
|
+
const ext = extensaoDe(p), ehTs = exports.EXTENSOES_TS.includes(ext), ehMd = exports.EXTENSOES_MD.includes(ext);
|
|
212
|
+
if (!ehTs && !ehMd) {
|
|
213
|
+
// D9: o arquivo vira no, e o diagnostico diz que o conteudo dele nao foi lido.
|
|
214
|
+
achados.diagnosticos.push({ kind: 'unsupported-language', path: p, reference: ext || null, extrator: exports.EXTRATOR_ARQUIVOS });
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const t = texto(p);
|
|
218
|
+
if (t === undefined)
|
|
219
|
+
achados.lacunas.push({ categoria: 'utf8-invalido', path: p, inicio: null, detalhe: null });
|
|
220
|
+
else
|
|
221
|
+
(ehTs ? fontesTs : fontesMd).push({ path: p, texto: t });
|
|
222
|
+
}
|
|
223
|
+
const versaoTs = `${exports.VERSAO_KG2}+typescript.${ts.version}+${javascript.versao}`;
|
|
224
|
+
// B1: a raiz virtual do compilador deriva do manifesto; um caminho do repositorio nao a nomeia.
|
|
225
|
+
const raiz = `/ork-${(0, intelligence_graph_contract_1.sha256DoCanonico)([...manifesto.values()].map((m) => [m.path, m.source_hash])).slice(0, 32)}`;
|
|
226
|
+
const aceitaFragmento = (f) => f.length >= 1 && f.length <= intelligence_graph_contract_1.GRAFO_LIMITES.fragmento && (0, exports.textoAceito)(f);
|
|
227
|
+
juntar(semEstouro(exports.EXTRATOR_TS, () => (0, intelligence_graph_extract_ts_1.extrairTypeScript)({
|
|
228
|
+
fontes: fontesTs, arquivos: caminhos, texto, raiz, aceitaFragmento, sintaxe: javascript.sintaxe, extrator: exports.EXTRATOR_TS,
|
|
229
|
+
}, ts)));
|
|
230
|
+
// B4: chave `caminho#fragmento` como o frontmatter a escreve; duas refs na mesma chave ficam ambiguas.
|
|
231
|
+
const simbolos = new Map();
|
|
232
|
+
for (const r of achados.nos.filter((x) => x.kind === 'symbol')) {
|
|
233
|
+
const chave = `${r.path}#${r.fragment}`, antes = simbolos.get(chave);
|
|
234
|
+
simbolos.set(chave, antes === undefined || (antes && antes.path === r.path && antes.fragment === r.fragment) ? r : null);
|
|
235
|
+
}
|
|
236
|
+
juntar(semEstouro(exports.EXTRATOR_MD, () => (0, intelligence_graph_extract_md_1.extrairMarkdown)({
|
|
237
|
+
fontes: fontesMd, codigo: fontesTs, arquivos: caminhos, simbolos, aceitaFragmento, analisar: markdown.analisar,
|
|
238
|
+
referencia: markdown.referencia, extratorMd: exports.EXTRATOR_MD, extratorId: exports.EXTRATOR_ID,
|
|
239
|
+
})));
|
|
240
|
+
const extratores = [
|
|
241
|
+
{ extractor_id: exports.EXTRATOR_ARQUIVOS, extractor_version: exports.VERSAO_KG2 },
|
|
242
|
+
{ extractor_id: exports.EXTRATOR_ID, extractor_version: exports.VERSAO_KG2 },
|
|
243
|
+
{ extractor_id: exports.EXTRATOR_MD, extractor_version: `${exports.VERSAO_KG2}+${markdown.versao}+unicode.${unicode}` },
|
|
244
|
+
{ extractor_id: exports.EXTRATOR_TS, extractor_version: versaoTs },
|
|
245
|
+
];
|
|
246
|
+
const versoes = new Map(extratores.map((e) => [e.extractor_id, e.extractor_version]));
|
|
247
|
+
const versaoDe = (id) => versoes.get(id) ?? falha('extracao.interna.extrator-desconhecido');
|
|
248
|
+
// Nos: todo arquivo do manifesto e os nos que os extratores provaram.
|
|
249
|
+
const nos = new Map();
|
|
250
|
+
for (const p of caminhos)
|
|
251
|
+
nos.set(chaveDoNo({ kind: 'file', path: p, fragment: null }), { kind: 'file', path: p, fragment: null });
|
|
252
|
+
for (const r of achados.nos) {
|
|
253
|
+
if (!manifesto.has(r.path))
|
|
254
|
+
falha('extracao.interna.no-sem-fonte');
|
|
255
|
+
if (r.fragment === null || !(0, exports.textoAceito)(r.fragment) || r.fragment.length > intelligence_graph_contract_1.GRAFO_LIMITES.fragmento)
|
|
256
|
+
falha('extracao.interna.fragmento');
|
|
257
|
+
nos.set(chaveDoNo(r), r);
|
|
258
|
+
}
|
|
259
|
+
if (nos.size > intelligence_graph_contract_1.GRAFO_LIMITES.nos)
|
|
260
|
+
falha('extracao.limite.nos');
|
|
261
|
+
const mapas = new Map();
|
|
262
|
+
const mapaDe = (p) => {
|
|
263
|
+
let m = mapas.get(p);
|
|
264
|
+
if (!m) {
|
|
265
|
+
const t = texto(p);
|
|
266
|
+
if (t === undefined)
|
|
267
|
+
falha('extracao.interna.trecho-sem-texto');
|
|
268
|
+
m = new MapaDoTexto(t, bytesDe.get(p).length);
|
|
269
|
+
mapas.set(p, m);
|
|
270
|
+
}
|
|
271
|
+
return m;
|
|
272
|
+
};
|
|
273
|
+
// D10: uma aresta por (tipo, origem, destino), com as evidencias ordenadas por posicao.
|
|
274
|
+
const arestas = new Map();
|
|
275
|
+
for (const a of achados.arestas) {
|
|
276
|
+
const kf = chaveDoNo(a.from), kt = chaveDoNo(a.to);
|
|
277
|
+
if (!nos.has(kf) || !nos.has(kt))
|
|
278
|
+
falha('extracao.interna.extremidade-ausente');
|
|
279
|
+
if (a.trecho.path !== a.from.path)
|
|
280
|
+
falha('extracao.interna.evidencia-fora-da-origem');
|
|
281
|
+
if (!(a.trecho.inicio < a.trecho.fim))
|
|
282
|
+
falha('extracao.interna.trecho-vazio');
|
|
283
|
+
const m = mapaDe(a.trecho.path), fonte = manifesto.get(a.trecho.path);
|
|
284
|
+
const e = {
|
|
285
|
+
snapshot_id: `snap-${zeros}`, path: fonte.path, source_hash: fonte.source_hash, source_version: fonte.source_version, authority,
|
|
286
|
+
extractor_id: a.extrator, extractor_version: versaoDe(a.extrator), extraction_method: a.metodo, confidence_class: intelligence_graph_contract_1.CLASSE_DE_CONFIANCA,
|
|
287
|
+
span: { type: 'text', byte_start: m.byte(a.trecho.inicio), byte_end: m.byte(a.trecho.fim), line_start: m.linha(a.trecho.inicio), line_end: m.linha(a.trecho.fim - 1) },
|
|
288
|
+
access,
|
|
289
|
+
};
|
|
290
|
+
const chave = `${a.kind}\u0000${kf}\u0000${kt}`;
|
|
291
|
+
let atual = arestas.get(chave);
|
|
292
|
+
if (!atual)
|
|
293
|
+
arestas.set(chave, (atual = { kind: a.kind, from: a.from, to: a.to, evidencias: new Map() }));
|
|
294
|
+
atual.evidencias.set((0, intelligence_graph_contract_1.canonico)(e), e);
|
|
295
|
+
}
|
|
296
|
+
if (arestas.size > intelligence_graph_contract_1.GRAFO_LIMITES.arestas)
|
|
297
|
+
falha('extracao.limite.arestas');
|
|
298
|
+
const idProvisorio = (r) => `node-${(0, intelligence_graph_contract_1.sha256DoCanonico)([r.kind, r.path, r.fragment])}`;
|
|
299
|
+
let excedentes = 0;
|
|
300
|
+
const edges = [...arestas.values()].map((a) => {
|
|
301
|
+
const evidencias = [...a.evidencias.values()].sort((x, y) => (x.span.byte_start - y.span.byte_start) || (x.span.byte_end - y.span.byte_end)
|
|
302
|
+
|| (0, intelligence_graph_contract_1.compararUtf8)(x.extractor_id, y.extractor_id) || (0, intelligence_graph_contract_1.compararUtf8)(x.extraction_method, y.extraction_method));
|
|
303
|
+
excedentes += Math.max(0, evidencias.length - intelligence_graph_contract_1.GRAFO_LIMITES.evidenciasPorAresta);
|
|
304
|
+
return {
|
|
305
|
+
edge_id: `edge-${zeros}`, kind: a.kind, snapshot_id: `snap-${zeros}`, from: idProvisorio(a.from), to: idProvisorio(a.to),
|
|
306
|
+
evidence: evidencias.slice(0, intelligence_graph_contract_1.GRAFO_LIMITES.evidenciasPorAresta), access,
|
|
307
|
+
};
|
|
308
|
+
});
|
|
309
|
+
const diagnosticos = new Map();
|
|
310
|
+
for (const d of achados.diagnosticos) {
|
|
311
|
+
if (!manifesto.has(d.path))
|
|
312
|
+
falha('extracao.interna.diagnostico-sem-fonte');
|
|
313
|
+
const reference = d.reference === null ? null : textoCurto(d.reference);
|
|
314
|
+
const diag = { kind: d.kind, path: d.path, reference, extractor_id: d.extrator, extractor_version: versaoDe(d.extrator), access };
|
|
315
|
+
diagnosticos.set((0, intelligence_graph_contract_1.canonico)(diag), diag);
|
|
316
|
+
}
|
|
317
|
+
if (diagnosticos.size > intelligence_graph_contract_1.GRAFO_LIMITES.diagnosticos)
|
|
318
|
+
falha('extracao.limite.diagnosticos');
|
|
319
|
+
const config = {
|
|
320
|
+
schema: exports.CONFIG_SCHEMA, authority, acl_refs: acl, evidencias_por_aresta: intelligence_graph_contract_1.GRAFO_LIMITES.evidenciasPorAresta,
|
|
321
|
+
typescript: { extensoes: exports.EXTENSOES_TS, opcoes: intelligence_graph_extract_ts_1.OPCOES_TS_DESCRITAS },
|
|
322
|
+
markdown: {
|
|
323
|
+
extensoes: exports.EXTENSOES_MD, ancora: 'github-slug', artefato: intelligence_graph_extract_md_1.PADRAO_DE_ID.source, frontmatter: intelligence_graph_extract_md_1.CHAVES_DO_FRONTMATTER, sem_mencao: intelligence_graph_extract_md_1.TOKENS_SEM_MENCAO,
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
const rascunho = {
|
|
327
|
+
schema: intelligence_graph_contract_1.GRAFO_SCHEMA, tenant_id: entrada.tenant_id, repository_id: entrada.repository_id,
|
|
328
|
+
snapshot: {
|
|
329
|
+
snapshot_id: `snap-${zeros}`, revision: entrada.revision, revision_unavailable_reason: entrada.revision_unavailable_reason,
|
|
330
|
+
source_manifest: [...manifesto.values()], config_hash: (0, intelligence_graph_contract_1.sha256DoCanonico)(config), extractors: extratores, extractors_digest: zeros,
|
|
331
|
+
},
|
|
332
|
+
nodes: [...nos.values()].map((r) => ({
|
|
333
|
+
node_id: idProvisorio(r), kind: r.kind, snapshot_id: `snap-${zeros}`, locator: { path: r.path, fragment: r.fragment },
|
|
334
|
+
source_hash: manifesto.get(r.path).source_hash, access,
|
|
335
|
+
})),
|
|
336
|
+
edges,
|
|
337
|
+
diagnostics: [...diagnosticos.values()],
|
|
338
|
+
};
|
|
339
|
+
const grafo = (0, intelligence_graph_contract_1.validarGrafo)((0, intelligence_graph_contract_1.derivarIds)(rascunho));
|
|
340
|
+
const digest = (0, intelligence_graph_contract_1.sha256DoCanonico)(grafo);
|
|
341
|
+
const contagens = {
|
|
342
|
+
fontes: grafo.snapshot.source_manifest.length, nos: contagemVazia(intelligence_graph_contract_1.TIPOS_DE_NO), arestas: contagemVazia(intelligence_graph_contract_1.TIPOS_DE_ARESTA),
|
|
343
|
+
diagnosticos: contagemVazia(intelligence_graph_contract_1.TIPOS_DE_DIAGNOSTICO), evidencias: 0,
|
|
344
|
+
};
|
|
345
|
+
for (const n of grafo.nodes)
|
|
346
|
+
contagens.nos[n.kind]++;
|
|
347
|
+
for (const a of grafo.edges) {
|
|
348
|
+
contagens.arestas[a.kind]++;
|
|
349
|
+
contagens.evidencias += a.evidence.length;
|
|
350
|
+
}
|
|
351
|
+
for (const d of grafo.diagnostics)
|
|
352
|
+
contagens.diagnosticos[d.kind]++;
|
|
353
|
+
const porCategoria = new Map(), listadas = new Map();
|
|
354
|
+
for (const l of achados.lacunas) {
|
|
355
|
+
porCategoria.set(l.categoria, (porCategoria.get(l.categoria) ?? 0) + 1);
|
|
356
|
+
if (exports.LACUNAS_SO_CONTAGEM.has(l.categoria))
|
|
357
|
+
continue;
|
|
358
|
+
const linha = l.inicio === null || texto(l.path) === undefined ? null : mapaDe(l.path).linha(l.inicio);
|
|
359
|
+
const item = { categoria: l.categoria, path: l.path, linha, detalhe: l.detalhe };
|
|
360
|
+
listadas.set((0, intelligence_graph_contract_1.canonico)(item), item);
|
|
361
|
+
}
|
|
362
|
+
const relatorio = {
|
|
363
|
+
schema: exports.RELATORIO_SCHEMA, snapshot_id: grafo.snapshot.snapshot_id, graph_digest: digest, contagens, evidencias_excedentes: excedentes,
|
|
364
|
+
excluidas: [...new Map(excluidas.map((e) => [(0, intelligence_graph_contract_1.canonico)(e), e])).entries()].sort((a, b) => (0, intelligence_graph_contract_1.compararUtf8)(a[0], b[0])).map(([, e]) => e),
|
|
365
|
+
lacunas_por_categoria: Object.fromEntries([...porCategoria.entries()].sort((a, b) => (0, intelligence_graph_contract_1.compararUtf8)(a[0], b[0]))),
|
|
366
|
+
lacunas: [...listadas.entries()].sort((a, b) => (0, intelligence_graph_contract_1.compararUtf8)(a[0], b[0])).map(([, l]) => l),
|
|
367
|
+
};
|
|
368
|
+
return { grafo, digest, relatorio };
|
|
369
|
+
}
|