@orkastery/cli 0.5.1 → 0.5.6
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/claude-code/README.md +158 -0
- package/adapters/claude-code/agents/ork-master.md +2 -0
- package/adapters/claude-code/commands/master.md +8 -0
- package/adapters/claude-code/commands/ork.md +9 -0
- package/adapters/claude-code/mods/autoridade.json +56 -0
- package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
- package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
- package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
- package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
- package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
- package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
- package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
- package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
- package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
- package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
- package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
- package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
- package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
- package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
- package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
- package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
- package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
- package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
- package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
- package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
- package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
- package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
- package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
- package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
- package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
- package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
- package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
- package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
- package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
- package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
- package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
- package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
- package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
- package/adapters/codex/skills/ork/SKILL.md +18 -3
- package/adapters/hermes/README.md +1 -0
- package/adapters/hermes/bin/ork-network-status.sh +10 -0
- package/adapters/hermes/hermes.plugin.json +1 -0
- package/adapters/hermes/hitl-ingress/__init__.py +2 -2
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +7 -6
- package/adapters/openclaw/README.md +26 -5
- package/adapters/openclaw/dist/hitl-ingress.js +2 -2
- package/adapters/openclaw/dist/index.js +46 -11
- package/adapters/openclaw/openclaw.plugin.json +5 -1
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +2 -2
- package/adapters/openclaw/src/index.ts +49 -11
- package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
- package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
- package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
- package/assets/docs-en/produto/README.md +14 -0
- package/assets/docs-en/produto/_modelo-feature.md +62 -0
- package/assets/docs-en/roadmap/README.md +14 -0
- package/assets/docs-en/roadmap/_modelo-item.md +75 -0
- package/assets/orkmind_bridge.py +117 -9
- package/dist/adapters/claude-bg.js +116 -18
- package/dist/adapters/codex.js +14 -4
- package/dist/agents-md.js +24 -14
- package/dist/auditrun.js +22 -3
- package/dist/board.js +20 -17
- package/dist/branch-de-estado.js +88 -10
- package/dist/busca-semantica.js +52 -12
- package/dist/canarios-rm057.js +149 -0
- package/dist/canarios.js +2 -0
- package/dist/catalogo.js +33 -0
- package/dist/ci.js +21 -8
- package/dist/claims-conferir.js +342 -0
- package/dist/claims.js +41 -1
- package/dist/company-brain-client.js +36 -1
- package/dist/company-brain-context.js +158 -22
- package/dist/company-brain-journal.js +2 -1
- package/dist/company-brain-migration.js +36 -1
- package/dist/conducao-sentinela.js +388 -0
- package/dist/conducao-texto.js +12 -18
- package/dist/conducao.js +122 -30
- package/dist/conhecimento.js +490 -0
- package/dist/docs.js +70 -17
- package/dist/doctor-pulse-cron.js +349 -0
- package/dist/doctor-rede.js +150 -0
- package/dist/doctor.js +195 -111
- package/dist/entrega-pr.js +42 -29
- package/dist/escopo-escrita.js +10 -1
- package/dist/esgotamentos.js +181 -0
- package/dist/estado-thread.js +23 -1
- package/dist/experiencia-instalacao.js +45 -25
- package/dist/experiencia.js +12 -2
- package/dist/fabrica-batida.js +310 -0
- package/dist/fabrica-estado.js +52 -14
- package/dist/fabrica-publicar.js +9 -1
- package/dist/fechamento.js +20 -66
- package/dist/fila-pesada.js +444 -0
- package/dist/fix.js +3 -2
- package/dist/forja.js +31 -7
- package/dist/gates.js +3 -24
- package/dist/handoff.js +10 -6
- package/dist/hitl-contract.js +59 -4
- package/dist/hitl-curto.js +11 -6
- package/dist/hitl-gates.js +5 -0
- package/dist/hitl-local-receipt.js +2 -0
- package/dist/hitl-lote.js +5 -2
- package/dist/hitl-resumo.js +38 -3
- package/dist/hitl-tempo-parado.js +201 -0
- package/dist/hitl-texto-livre.js +5 -5
- package/dist/hitl.js +29 -33
- package/dist/horario.js +41 -7
- package/dist/hosts.js +104 -11
- package/dist/impedimento.js +299 -0
- package/dist/index.js +961 -542
- package/dist/indice-vetorial.js +87 -10
- package/dist/indice.js +9 -1
- package/dist/init.js +56 -43
- package/dist/instabilidade.js +144 -0
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +170 -16
- package/dist/intelligence-graph-contexto.js +254 -0
- package/dist/intelligence-graph-contract.js +2 -1
- package/dist/intelligence-graph-extract-md.js +56 -4
- package/dist/intelligence-graph-extract-ts.js +71 -3
- package/dist/intelligence-graph-parsers.js +6 -4
- package/dist/intelligence-graph-query.js +66 -19
- package/dist/leases.js +664 -87
- package/dist/ledger-stats.js +15 -1
- package/dist/ledger.js +18 -1
- package/dist/licoes.js +1 -0
- package/dist/liveness.js +6 -3
- package/dist/locale-ajuda.js +761 -0
- package/dist/locale-gerados.js +160 -0
- package/dist/locale-master.js +99 -0
- package/dist/locale-onboarding.js +92 -0
- package/dist/locale-phase.js +151 -0
- package/dist/locale-pulse.js +211 -0
- package/dist/locale-retry.js +385 -0
- package/dist/locale-roadmap.js +102 -0
- package/dist/locale-ship.js +494 -0
- package/dist/locale-thread.js +277 -0
- package/dist/locale-verify.js +125 -0
- package/dist/locale.js +714 -0
- package/dist/maestro-runtime.js +4 -1
- package/dist/manifest.js +149 -4
- package/dist/maquina.js +23 -4
- package/dist/master-digest.js +6 -1
- package/dist/master-nota.js +18 -11
- package/dist/master.js +145 -31
- package/dist/mcp-artifacts.js +43 -3
- package/dist/mcp-git.js +42 -8
- package/dist/mcp-grafo-worker.js +5 -3
- package/dist/mcp-grafo.js +55 -6
- package/dist/mcp-server.js +22 -3
- package/dist/mcp-ship.js +3 -1
- package/dist/mcp-verify.js +6 -1
- package/dist/memoria.js +48 -6
- package/dist/modos.js +3 -6
- package/dist/network-roadmap.js +196 -18
- package/dist/noctum-arco.js +911 -0
- package/dist/noctum-capacidade.js +141 -0
- package/dist/noctum-envelope.js +810 -0
- package/dist/noctum-execucao.js +304 -0
- package/dist/noctum-fila.js +280 -0
- package/dist/ocupacao.js +40 -5
- package/dist/onboarding.js +40 -21
- package/dist/orkmind.js +99 -7
- package/dist/orquestracao.js +24 -21
- package/dist/parado-no-condutor.js +219 -38
- package/dist/phase.js +160 -52
- package/dist/policies.js +56 -5
- package/dist/portfolio.js +8 -3
- package/dist/postura-local.js +234 -0
- package/dist/preflight.js +11 -10
- package/dist/procedencia.js +225 -0
- package/dist/projeto-alvo.js +132 -5
- package/dist/prompts.js +40 -1
- package/dist/prova-ativacao.js +75 -6
- package/dist/pulse-delivery.js +47 -4
- package/dist/pulse.js +98 -19
- package/dist/ratelimit.js +24 -6
- package/dist/recall.js +3 -1
- package/dist/redacao-saida.js +63 -0
- package/dist/rede-adesao.js +399 -0
- package/dist/rede-forja.js +289 -0
- package/dist/rede-projetos.js +239 -0
- package/dist/rede-status.js +337 -0
- package/dist/rede.js +980 -0
- package/dist/retry.js +291 -140
- package/dist/roadmap-reservas.js +20 -3
- package/dist/roadmap-status.js +150 -34
- package/dist/runtime-context.js +181 -3
- package/dist/runtime-profiles.js +22 -1
- package/dist/runtimes.js +2 -1
- package/dist/saida-segura.js +58 -0
- package/dist/session-events.js +7 -3
- package/dist/session-watcher-claude.js +120 -24
- package/dist/session-watcher.js +185 -33
- package/dist/sessoes-contas.js +187 -0
- package/dist/sessoes-inventario.js +6 -18
- package/dist/sessoes.js +83 -2
- package/dist/ship-publicar.js +800 -0
- package/dist/ship.js +157 -88
- package/dist/steal.js +77 -0
- package/dist/thread-close.js +3 -2
- package/dist/thread.js +299 -49
- package/dist/util.js +8 -1
- package/dist/verify.js +141 -52
- package/dist/vida-da-thread.js +254 -0
- package/dist/worktree-local.js +165 -0
- package/dist/worktree.js +25 -2
- package/dist/yaml.js +27 -8
- package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
- package/package.json +7 -3
- package/references/definition-of-done.md +1 -1
- package/schemas/code-artifact-graph.v1.schema.json +2 -1
- package/skills/README.md +1 -1
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/master-metrics/SKILL.md +8 -3
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TETO_DE_LINHAS_DE_TABELA = exports.TOKENS_SEM_MENCAO = exports.CHAVES_DO_FRONTMATTER = exports.PADRAO_DE_ID = void 0;
|
|
4
4
|
exports.slugDeTexto = slugDeTexto;
|
|
5
|
+
exports.caminhoDaCitacao = caminhoDaCitacao;
|
|
5
6
|
exports.estruturarMarkdown = estruturarMarkdown;
|
|
6
7
|
exports.extrairMarkdown = extrairMarkdown;
|
|
7
8
|
exports.ligarMarkdown = ligarMarkdown;
|
|
@@ -191,9 +192,10 @@ function estruturar(fonte, aceitaFragmento, analisar, referencia) {
|
|
|
191
192
|
comDelimitador = true;
|
|
192
193
|
}
|
|
193
194
|
if (linhasDeTabela > exports.TETO_DE_LINHAS_DE_TABELA) {
|
|
194
|
-
return { fonte, secoes: [], links: [], textoDeMencao: [], frontmatter, frontmatterInvalido, tabelaGrande: true };
|
|
195
|
+
return { fonte, secoes: [], links: [], citacoes: [], textoDeMencao: [], frontmatter, frontmatterInvalido, tabelaGrande: true };
|
|
195
196
|
}
|
|
196
197
|
const secoes = [], links = [], semMencao = [];
|
|
198
|
+
const citacoes = [];
|
|
197
199
|
const slug = contadorDeSlugs(), abertos = [];
|
|
198
200
|
// B5: referencia de caractere pelo decodificador do micromark (as entidades do HTML5); a crua fica.
|
|
199
201
|
const decodificada = (i, f) => referencia(corpo.slice(i + 1, f - 1)) ?? corpo.slice(i, f);
|
|
@@ -239,6 +241,10 @@ function estruturar(fonte, aceitaFragmento, analisar, referencia) {
|
|
|
239
241
|
semMencao.push([e.inicio, e.fim]);
|
|
240
242
|
}
|
|
241
243
|
// Titulo, lido em paralelo: o texto dele junta dado, codigo, escape e entidade.
|
|
244
|
+
if (e.tipo === 'codeTextData' && !emExcesso)
|
|
245
|
+
citacoes.push({
|
|
246
|
+
destino: corpo.slice(e.inicio, e.fim), inicio: no(e.inicio), fim: no(e.fim),
|
|
247
|
+
});
|
|
242
248
|
if (e.tipo === 'atxHeading' || e.tipo === 'setextHeading')
|
|
243
249
|
titulo = { inicio: no(e.inicio), fim: no(e.fim), partes: [], noTexto: 0, foraDoTexto: 0, noCodigo: 0 };
|
|
244
250
|
else if (titulo) {
|
|
@@ -304,7 +310,7 @@ function estruturar(fonte, aceitaFragmento, analisar, referencia) {
|
|
|
304
310
|
}
|
|
305
311
|
}
|
|
306
312
|
const textoDeMencao = linhasDe(apagarTrechos(corpo, semMencao)).map((l) => ({ inicio: no(l.inicio), texto: l.texto }));
|
|
307
|
-
return { fonte, secoes: secoes.sort((a, b) => a.inicio - b.inicio), links, textoDeMencao, frontmatter, frontmatterInvalido, tabelaGrande: false };
|
|
313
|
+
return { fonte, secoes: secoes.sort((a, b) => a.inicio - b.inicio), links, citacoes, textoDeMencao, frontmatter, frontmatterInvalido, tabelaGrande: false };
|
|
308
314
|
}
|
|
309
315
|
/** Caminho relativo a raiz a partir do arquivo do link; `null` se sair do repositorio. */
|
|
310
316
|
function resolverCaminho(base, destino) {
|
|
@@ -323,6 +329,23 @@ function resolverCaminho(base, destino) {
|
|
|
323
329
|
}
|
|
324
330
|
return r.join('/');
|
|
325
331
|
}
|
|
332
|
+
/** Citacao nao e resolucao de runtime: so caminho literal dentro do manifesto. */
|
|
333
|
+
function caminhoDaCitacao(base, literal, modulo = false) {
|
|
334
|
+
if (!literal || /[\s\\:#?%\u0000-\u001f\u007f]/u.test(literal) || literal.startsWith('/') || literal.startsWith('~'))
|
|
335
|
+
return null;
|
|
336
|
+
if (literal.split('/').some((p) => p === '.git' || p === '.orkastery'))
|
|
337
|
+
return null;
|
|
338
|
+
// Argumento sem prefixo de caminho e nome de pacote, nao candidato local.
|
|
339
|
+
if (modulo && !/^\.{1,2}\//.test(literal))
|
|
340
|
+
return null;
|
|
341
|
+
// Palavras e diretorios nao sao citacoes de arquivo. Modulos podem omitir extensao.
|
|
342
|
+
if (!modulo && (!literal.includes('/') || !/\.(?:[cm]?[jt]s|[jt]sx|json|md|markdown|ya?ml|toml|py|rs|go|c|h|css|html|svg|png|jpe?g|gif|webp|pdf|txt|sh|sql)$/i.test(literal)))
|
|
343
|
+
return null;
|
|
344
|
+
if (['', '.', '..'].includes(literal.split('/').at(-1)))
|
|
345
|
+
return null;
|
|
346
|
+
const caminho = literal.startsWith('./') || literal.startsWith('../') ? resolverCaminho(base, literal) : literal;
|
|
347
|
+
return caminho || null;
|
|
348
|
+
}
|
|
326
349
|
const decodificar = (t) => {
|
|
327
350
|
try {
|
|
328
351
|
return decodeURIComponent(t);
|
|
@@ -339,7 +362,7 @@ function estruturarMarkdown(fonte, e) {
|
|
|
339
362
|
mencoes.push({ inicio: l.inicio + m.index, id: m[0] });
|
|
340
363
|
const d = s.frontmatter?.dados;
|
|
341
364
|
return {
|
|
342
|
-
path: fonte.path, secoes: s.secoes, links: s.links, mencoes,
|
|
365
|
+
path: fonte.path, secoes: s.secoes, links: s.links, citacoes: s.citacoes, mencoes,
|
|
343
366
|
frontmatter: s.frontmatter && d
|
|
344
367
|
? { id: typeof d.id === 'string' ? d.id : null, tipo: typeof d.tipo === 'string' && d.tipo !== '', valores: s.frontmatter.valores }
|
|
345
368
|
: null,
|
|
@@ -414,6 +437,13 @@ function ligarMarkdown(e) {
|
|
|
414
437
|
};
|
|
415
438
|
for (const s of estruturas) {
|
|
416
439
|
const path = s.path, arquivo = { kind: 'file', path, fragment: null };
|
|
440
|
+
const citar = (alvo, k, metodo) => {
|
|
441
|
+
if (alvo === null || alvo === path || !arquivos.has(alvo))
|
|
442
|
+
return false;
|
|
443
|
+
aresta('cites', secaoEm(s, arquivo, k.inicio), { kind: 'file', path: alvo, fragment: null }, e.extratorMd, metodo, { path, inicio: k.inicio, fim: k.fim });
|
|
444
|
+
return true;
|
|
445
|
+
};
|
|
446
|
+
const linksReferenciados = [];
|
|
417
447
|
for (const x of s.secoes) {
|
|
418
448
|
if (x.slug === null) {
|
|
419
449
|
lacuna('secao-recusada', path, x.inicio, null);
|
|
@@ -438,7 +468,15 @@ function ligarMarkdown(e) {
|
|
|
438
468
|
lacuna('link-invalido', path, k.inicio, destino);
|
|
439
469
|
continue;
|
|
440
470
|
}
|
|
441
|
-
const
|
|
471
|
+
const relativo = caminhoDecodificado === '' ? path : resolverCaminho(path, caminhoDecodificado);
|
|
472
|
+
// Links seguem o diretorio do documento; a citacao tambem admite caminho desde a raiz.
|
|
473
|
+
const literal = caminhoDaCitacao(path, caminhoDecodificado);
|
|
474
|
+
// Uma referencia ao arquivo ou a uma secao ja representa esta ocorrencia do link.
|
|
475
|
+
if (relativo === null || !arquivos.has(relativo)) {
|
|
476
|
+
if (citar(literal, k, 'explicit-link'))
|
|
477
|
+
linksReferenciados.push(k);
|
|
478
|
+
}
|
|
479
|
+
const alvo = relativo;
|
|
442
480
|
if (alvo === null) {
|
|
443
481
|
lacuna('link-fora-do-repositorio', path, k.inicio, destino);
|
|
444
482
|
continue;
|
|
@@ -450,6 +488,7 @@ function ligarMarkdown(e) {
|
|
|
450
488
|
const secoesDoAlvo = slugs.get(alvo);
|
|
451
489
|
if (ancora && secoesDoAlvo?.has(ancora)) {
|
|
452
490
|
aresta('references', origem, { kind: 'section', path: alvo, fragment: ancora }, e.extratorMd, 'explicit-link', t);
|
|
491
|
+
linksReferenciados.push(k);
|
|
453
492
|
continue;
|
|
454
493
|
}
|
|
455
494
|
// P6: ancora que nao bate fica declarada; o link ainda prova a referencia ao arquivo.
|
|
@@ -458,6 +497,19 @@ function ligarMarkdown(e) {
|
|
|
458
497
|
if (alvo === path)
|
|
459
498
|
continue;
|
|
460
499
|
aresta('references', origem, { kind: 'file', path: alvo, fragment: null }, e.extratorMd, 'explicit-link', t);
|
|
500
|
+
linksReferenciados.push(k);
|
|
501
|
+
}
|
|
502
|
+
// Codigo inline no rotulo pertence a mesma ocorrencia do link ja resolvido.
|
|
503
|
+
// Varredura por spans preserva citacoes independentes, inclusive na mesma linha.
|
|
504
|
+
linksReferenciados.sort((a, b) => a.inicio - b.inicio || b.fim - a.fim);
|
|
505
|
+
let link = 0;
|
|
506
|
+
for (const k of s.citacoes) {
|
|
507
|
+
while (link < linksReferenciados.length && linksReferenciados[link].fim <= k.inicio)
|
|
508
|
+
link++;
|
|
509
|
+
const l = linksReferenciados[link];
|
|
510
|
+
if (l && l.inicio <= k.inicio && k.fim <= l.fim)
|
|
511
|
+
continue;
|
|
512
|
+
citar(caminhoDaCitacao(path, k.destino), k, 'text-location');
|
|
461
513
|
}
|
|
462
514
|
const artefato = s.frontmatter && s.frontmatter.id !== null ? artefatos.get(s.frontmatter.id) : undefined;
|
|
463
515
|
if (artefato && artefato.path === path && s.frontmatter) {
|
|
@@ -3,9 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.OPCOES_TS_DESCRITAS = void 0;
|
|
4
4
|
exports.casaSonda = casaSonda;
|
|
5
5
|
exports.extrairTypeScript = extrairTypeScript;
|
|
6
|
+
const intelligence_graph_extract_md_1 = require("./intelligence-graph-extract-md");
|
|
6
7
|
/** Extensoes que o extrator TS le; as do `extensaoDe` do KG2. */
|
|
7
8
|
const EXTENSOES_DO_PROGRAMA = ['.cjs', '.cts', '.js', '.jsx', '.mjs', '.mts', '.ts', '.tsx'];
|
|
8
9
|
const DECLARACOES_TS = ['.d.ts', '.d.mts', '.d.cts'];
|
|
10
|
+
/** KG5: candidatos literais; dist -> src e uma convencao de citacao, nunca prova de import. */
|
|
11
|
+
function candidatosDaCitacao(base) {
|
|
12
|
+
const formas = (p) => {
|
|
13
|
+
const semJs = p.replace(/\.(?:[cm]?js|jsx)$/, '');
|
|
14
|
+
if (semJs !== p)
|
|
15
|
+
return [semJs + '.ts', semJs + '.tsx', semJs + '.mts', semJs + '.cts'];
|
|
16
|
+
if (/\.[^/]+$/.test(p))
|
|
17
|
+
return [];
|
|
18
|
+
return EXTENSOES_DO_PROGRAMA.flatMap((ext) => [p + ext, p + '/index' + ext]);
|
|
19
|
+
};
|
|
20
|
+
const grupos = [[base], formas(base)];
|
|
21
|
+
const fonte = base.replace(/(^|\/)dist\//, '$1src/');
|
|
22
|
+
if (fonte !== base)
|
|
23
|
+
grupos.push([fonte], formas(fonte));
|
|
24
|
+
return grupos;
|
|
25
|
+
}
|
|
9
26
|
/** A base sem a extensao (o TypeScript troca `.js` por `.ts`, e `.d.ts` conta inteira). */
|
|
10
27
|
function semExtensao(base) {
|
|
11
28
|
const nome = base.slice(base.lastIndexOf('/') + 1);
|
|
@@ -283,12 +300,19 @@ function extrairTypeScript(e, ts) {
|
|
|
283
300
|
/** Fonte TypeScript, que o compilador transforma; JavaScript roda como esta. */
|
|
284
301
|
const compiladoEm = (arquivo) => !EXTENSOES_JS.includes(extensao(arquivo));
|
|
285
302
|
/** Chaves de todos os imports dentro de um no. */
|
|
286
|
-
function especificadoresEm(raiz) {
|
|
303
|
+
function especificadoresEm(raiz, literais) {
|
|
287
304
|
const r = [], compilado = compiladoEm(raiz.getSourceFile().fileName);
|
|
288
305
|
const coletar = (n) => {
|
|
289
306
|
const chave = chaveDoImport(n, compilado);
|
|
290
|
-
if (chave !== null)
|
|
307
|
+
if (chave !== null) {
|
|
291
308
|
r.push(chave);
|
|
309
|
+
const esp = ts.isImportDeclaration(n) || ts.isExportDeclaration(n) ? n.moduleSpecifier
|
|
310
|
+
: ts.isImportEqualsDeclaration(n) && ts.isExternalModuleReference(n.moduleReference) ? n.moduleReference.expression
|
|
311
|
+
: ts.isImportTypeNode(n) && ts.isLiteralTypeNode(n.argument) ? n.argument.literal
|
|
312
|
+
: ts.isCallExpression(n) ? n.arguments[0] : undefined;
|
|
313
|
+
if (esp)
|
|
314
|
+
literais?.set(esp, chave);
|
|
315
|
+
}
|
|
292
316
|
ts.forEachChild(n, coletar);
|
|
293
317
|
};
|
|
294
318
|
coletar(raiz);
|
|
@@ -597,13 +621,15 @@ function extrairTypeScript(e, ts) {
|
|
|
597
621
|
const divergentesGlobais = new Set();
|
|
598
622
|
// KG4 (D3): por fonte, os caminhos a que as referencias de modulo resolvem e as bases das relativas.
|
|
599
623
|
const dependenciasDe = new Map(), sondasDe = new Map();
|
|
624
|
+
const citacoesDe = new Map();
|
|
600
625
|
for (const fonte of e.fontes) {
|
|
601
626
|
const sf = programa.getSourceFile(absoluto(fonte.path));
|
|
602
627
|
if (!sf || sf.fileName !== absoluto(fonte.path))
|
|
603
628
|
continue;
|
|
604
629
|
const ext = extensao(fonte.path), mapa = new Map();
|
|
605
630
|
const dependencias = new Set(), sondas = new Set();
|
|
606
|
-
|
|
631
|
+
const literaisDeModulo = new Map();
|
|
632
|
+
for (const chave of especificadoresEm(sf, literaisDeModulo)) {
|
|
607
633
|
if (mapa.has(chave))
|
|
608
634
|
continue;
|
|
609
635
|
const esp = especificadorDaChave(chave), doCompilador = resolver(esp, fonte.path);
|
|
@@ -632,6 +658,46 @@ function extrairTypeScript(e, ts) {
|
|
|
632
658
|
if (divergente)
|
|
633
659
|
divergentesGlobais.add(`${fonte.path}\u0000${chave}`);
|
|
634
660
|
}
|
|
661
|
+
// Strings so em testes/scripts. Comentarios, interpolacoes e concatenacoes nao sao avaliados.
|
|
662
|
+
const citacoes = [];
|
|
663
|
+
if (/(?:^|\/)(?:tests?|__tests__|scripts?)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/.test(fonte.path)) {
|
|
664
|
+
const citar = (literal, n, modulo = false) => {
|
|
665
|
+
const base = (0, intelligence_graph_extract_md_1.caminhoDaCitacao)(fonte.path, literal, modulo);
|
|
666
|
+
if (base === null)
|
|
667
|
+
return;
|
|
668
|
+
const grupos = candidatosDaCitacao(base);
|
|
669
|
+
// Inclui ausentes e diretorios: a troca para arquivo invalida a unidade incremental.
|
|
670
|
+
// So arquivos presentes podem virar alvo; diretorios conservam apenas a sonda.
|
|
671
|
+
for (const grupo of grupos)
|
|
672
|
+
for (const p of grupo)
|
|
673
|
+
sondas.add(p);
|
|
674
|
+
for (const grupo of grupos) {
|
|
675
|
+
const presentes = grupo.filter((p) => arquivos.has(p));
|
|
676
|
+
if (!presentes.length)
|
|
677
|
+
continue;
|
|
678
|
+
if (presentes.length === 1 && presentes[0] !== fonte.path) {
|
|
679
|
+
dependencias.add(presentes[0]);
|
|
680
|
+
citacoes.push({ alvo: presentes[0], trecho: { path: fonte.path, inicio: n.getStart(sf), fim: n.getEnd() } });
|
|
681
|
+
}
|
|
682
|
+
break; // Ambiguidade nao autoriza escolher uma fonte nem tentar outro grupo.
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
const literais = (n) => {
|
|
686
|
+
if (ts.isStringLiteral(n) || ts.isNoSubstitutionTemplateLiteral(n)) {
|
|
687
|
+
const chave = literaisDeModulo.get(n);
|
|
688
|
+
// O resolver de import ja provou esta ocorrencia; outra string igual ainda pode citar.
|
|
689
|
+
if (chave !== undefined && mapa.get(chave)?.alvo != null)
|
|
690
|
+
return;
|
|
691
|
+
citar(n.text, n, chave !== undefined);
|
|
692
|
+
// Codigo citado por fixture: so argumentos literais de require/import dentro da string.
|
|
693
|
+
for (const m of n.text.matchAll(/\b(?:require|import)\s*\(\s*(['"])([^'"\r\n]+)\1\s*\)/g))
|
|
694
|
+
citar(m[2], n, true);
|
|
695
|
+
}
|
|
696
|
+
ts.forEachChild(n, literais);
|
|
697
|
+
};
|
|
698
|
+
literais(sf);
|
|
699
|
+
}
|
|
700
|
+
citacoesDe.set(fonte.path, citacoes);
|
|
635
701
|
// O que o TypeScript coleta e a varredura nao ve (tipo importado no JSDoc) tambem liga o checker a outro arquivo.
|
|
636
702
|
for (const nome of nomesDeModulo(sf)) {
|
|
637
703
|
sondar(baseDaSonda(fonte.path, nome), sondas);
|
|
@@ -739,6 +805,8 @@ function extrairTypeScript(e, ts) {
|
|
|
739
805
|
const aresta = (kind, from, to, t) => {
|
|
740
806
|
saida.arestas.push({ kind, from, to, extrator: e.extrator, metodo: 'ast', trecho: t });
|
|
741
807
|
};
|
|
808
|
+
for (const c of citacoesDe.get(fonte.path) ?? [])
|
|
809
|
+
aresta('cites', arquivo, { kind: 'file', path: c.alvo, fragment: null }, c.trecho);
|
|
742
810
|
const lacuna = (categoria, n, detalhe = null) => {
|
|
743
811
|
saida.lacunas.push({ categoria, path: fonte.path, inicio: n ? n.getStart(sf) : null, detalhe });
|
|
744
812
|
};
|
|
@@ -46,10 +46,12 @@ exports.carregarAnalisadores = carregarAnalisadores;
|
|
|
46
46
|
* `typescript` e os pacotes do micromark so valem dentro da instalacao do `ork` que roda (o
|
|
47
47
|
* `node_modules` do pacote `@orkastery/cli` que contem este modulo), nunca do diretorio atual, do
|
|
48
48
|
* `NODE_PATH` nem de uma pasta acima, como a do projeto que instalou o `ork` como dependencia: o
|
|
49
|
-
* repositorio lido e dado, e codigo dele nunca e carregado.
|
|
50
|
-
*
|
|
51
|
-
* instalacao
|
|
52
|
-
*
|
|
49
|
+
* repositorio lido e dado, e codigo dele nunca e carregado. Desde a correcao de empacotamento da
|
|
50
|
+
* RM-031 eles sao dependencias de runtime do pacote publicado, com versao exata, e o
|
|
51
|
+
* `npm install -g` os poe dentro da instalacao; onde faltam ou estao fora dela (o `ork` instalado
|
|
52
|
+
* dentro de um projeto ou pelo `npx`, que icam as dependencias), a recusa e
|
|
53
|
+
* `grafo.parser.indisponivel: <pacote>`, e o `ork doctor` diz a correcao. `pacotesDosAnalisadores`
|
|
54
|
+
* lista o fecho de dependencias deles, com versao, para a chave do indice (CHECK rodada 1, A10).
|
|
53
55
|
*
|
|
54
56
|
* O juiz de sintaxe e o V8 do Node que roda a extracao, o mesmo que carregaria o arquivo. CommonJS
|
|
55
57
|
* compila aqui, em funcao com as variaveis do modulo, como o carregador faz. ESM compila num unico
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rotuloDoNo = exports.ErroDeConsulta = exports.AVISO_DE_PARCIALIDADE = exports.CANDIDATOS_LISTADOS = exports.LIMITE_MAXIMO = exports.LIMITE_PADRAO = exports.PROFUNDIDADE_MAXIMA = exports.CONSULTA_SCHEMA = void 0;
|
|
3
|
+
exports.rotuloDoNo = exports.ErroDeConsulta = exports.TUDO_IGUAL = exports.AVISO_DE_PARCIALIDADE = exports.CANDIDATOS_LISTADOS = exports.LIMITE_MAXIMO = exports.LIMITE_PADRAO = exports.PROFUNDIDADE_MAXIMA = exports.CONSULTA_SCHEMA = void 0;
|
|
4
4
|
exports.filtrarGrafo = filtrarGrafo;
|
|
5
5
|
exports.prepararConsulta = prepararConsulta;
|
|
6
6
|
exports.resolverNo = resolverNo;
|
|
@@ -23,6 +23,10 @@ exports.textoDaResposta = textoDaResposta;
|
|
|
23
23
|
*
|
|
24
24
|
* D7: a resposta e a mesma para o mesmo grafo e a mesma pergunta, byte a byte, em texto e em JSON
|
|
25
25
|
* (`ork.code-graph-query/v0`, provisorio e fora do contrato): ordem por code point, sem horario.
|
|
26
|
+
*
|
|
27
|
+
* RM-031 KG5 fatia 5 (D2 a D4, D9, D10): a resposta traz `fontes`, o sha256 e o blob de cada caminho
|
|
28
|
+
* citado, e cada aresta diz se as fontes dela conferem com a arvore. Quem chama passa a situacao de
|
|
29
|
+
* cada caminho (o CLI le os bytes); sem ela, tudo vale `igual`, e a consulta continua sem arquivo.
|
|
26
30
|
*/
|
|
27
31
|
const intelligence_graph_contract_1 = require("./intelligence-graph-contract");
|
|
28
32
|
exports.CONSULTA_SCHEMA = 'ork.code-graph-query/v0';
|
|
@@ -32,6 +36,9 @@ exports.LIMITE_MAXIMO = 10_000;
|
|
|
32
36
|
/** Candidatos listados quando um nome solto e ambiguo. */
|
|
33
37
|
exports.CANDIDATOS_LISTADOS = 20;
|
|
34
38
|
exports.AVISO_DE_PARCIALIDADE = 'parcial: so arestas que o extrator prova; chamada por despacho de tipo, import nao resolvido e as lacunas do relatorio de extracao ficam fora';
|
|
39
|
+
/** Sem saber da arvore, toda fonte vale `igual`: e o que a arvore limpa garante. */
|
|
40
|
+
const TUDO_IGUAL = () => 'igual';
|
|
41
|
+
exports.TUDO_IGUAL = TUDO_IGUAL;
|
|
35
42
|
/** Erro tipado da consulta; `candidatos` so no nome ambiguo, e so com nos visiveis. */
|
|
36
43
|
class ErroDeConsulta extends Error {
|
|
37
44
|
codigo;
|
|
@@ -101,7 +108,11 @@ function prepararConsulta(grafoInteiro, concessao) {
|
|
|
101
108
|
lista.sort(ordem((a) => rotulos.get(a.from)));
|
|
102
109
|
for (const lista of porFragmento.values())
|
|
103
110
|
lista.sort((x, y) => (0, intelligence_graph_contract_1.compararUtf8)((0, exports.rotuloDoNo)(x), (0, exports.rotuloDoNo)(y)));
|
|
104
|
-
|
|
111
|
+
const fontes = new Map();
|
|
112
|
+
for (const m of grafo.snapshot.source_manifest)
|
|
113
|
+
if (visivel(m.access, concessao))
|
|
114
|
+
fontes.set(m.path, { source_hash: m.source_hash, source_version: m.source_version });
|
|
115
|
+
return { repository_id: grafo.repository_id, snapshot_id: grafo.snapshot.snapshot_id, nos, rotulos, porLocalizador, arquivos, porFragmento, saida, entrada, fontes };
|
|
105
116
|
}
|
|
106
117
|
function ambiguo(texto, candidatos) {
|
|
107
118
|
const rotulos = candidatos.map(exports.rotuloDoNo).sort(intelligence_graph_contract_1.compararUtf8);
|
|
@@ -169,6 +180,31 @@ function arestaDaResposta(g, a, distancia) {
|
|
|
169
180
|
|| (0, intelligence_graph_contract_1.compararUtf8)(x.extractor_id, y.extractor_id) || (0, intelligence_graph_contract_1.compararUtf8)(x.extraction_method, y.extraction_method));
|
|
170
181
|
return { kind: a.kind, from: g.rotulos.get(a.from), to: g.rotulos.get(a.to), edge_id: a.edge_id, distancia, evidencias };
|
|
171
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* KG5 fatia 5 (D4): a aresta so e `igual` quando as fontes dela inteiras conferem: o arquivo da origem, o
|
|
185
|
+
* do alvo (calls e imports resolvem o alvo nele) e os das evidencias. So as devolvidas pedem a situacao.
|
|
186
|
+
* Com teto, a busca binaria monta respostas com limites diferentes, e o CLI le os arquivos citados pela
|
|
187
|
+
* maior delas, a do limite pedido, mesmo os que o corte tira (CHECK rodada 1, S4).
|
|
188
|
+
*/
|
|
189
|
+
function comArvore(g, a, r, situacao) {
|
|
190
|
+
const caminhos = [g.nos.get(a.from).locator.path, g.nos.get(a.to).locator.path, ...r.evidencias.map((e) => e.path)];
|
|
191
|
+
const { evidencias, ...resto } = r;
|
|
192
|
+
return { ...resto, arvore: caminhos.every((p) => situacao(p) === 'igual') ? 'igual' : 'modificada', evidencias };
|
|
193
|
+
}
|
|
194
|
+
/** KG5 fatia 5 (D2, D10): uma entrada por caminho dos nos e das evidencias da resposta, em ordem UTF-8. */
|
|
195
|
+
function fontesDaResposta(g, nos, arestas, situacao) {
|
|
196
|
+
const caminhos = new Set(nos.map((n) => n.path));
|
|
197
|
+
for (const a of arestas)
|
|
198
|
+
for (const e of a.evidencias)
|
|
199
|
+
caminhos.add(e.path);
|
|
200
|
+
const fontes = [];
|
|
201
|
+
for (const p of [...caminhos].sort(intelligence_graph_contract_1.compararUtf8)) {
|
|
202
|
+
const f = g.fontes.get(p);
|
|
203
|
+
if (f)
|
|
204
|
+
fontes.push({ path: p, source_hash: f.source_hash, source_version: f.source_version, arvore: situacao(p) });
|
|
205
|
+
}
|
|
206
|
+
return fontes;
|
|
207
|
+
}
|
|
172
208
|
/** CHECK rodada 1 (A2): primeiro as arestas mais perto do alvo, e o limite corta as mais longe. */
|
|
173
209
|
const ordemDasArestas = (x, y) => (x.distancia - y.distancia)
|
|
174
210
|
|| (0, intelligence_graph_contract_1.compararUtf8)(x.kind, y.kind) || (0, intelligence_graph_contract_1.compararUtf8)(x.from, y.from) || (0, intelligence_graph_contract_1.compararUtf8)(x.to, y.to) || (0, intelligence_graph_contract_1.compararUtf8)(x.edge_id, y.edge_id);
|
|
@@ -204,7 +240,7 @@ function tiposValidos(tipos) {
|
|
|
204
240
|
* cada uma com a distancia do no que a explorou. `limite` corta pela distancia e pela ordem fixa, e
|
|
205
241
|
* a lista de nos so traz o alvo e as pontas das arestas devolvidas.
|
|
206
242
|
*/
|
|
207
|
-
function vizinhanca(g, cabecalho, tipo, texto, opcoes) {
|
|
243
|
+
function vizinhanca(g, cabecalho, tipo, texto, opcoes, situacao) {
|
|
208
244
|
const profundidade = inteiroEntre('profundidade', opcoes.profundidade ?? 1, 1, exports.PROFUNDIDADE_MAXIMA);
|
|
209
245
|
const limite = inteiroEntre('limite', opcoes.limite ?? exports.LIMITE_PADRAO, 1, exports.LIMITE_MAXIMO);
|
|
210
246
|
const sentido = opcoes.sentido ?? 'ambos';
|
|
@@ -228,8 +264,8 @@ function vizinhanca(g, cabecalho, tipo, texto, opcoes) {
|
|
|
228
264
|
}
|
|
229
265
|
camada = proxima;
|
|
230
266
|
}
|
|
231
|
-
const todas = [...vistas.values()].map(({ aresta, d }) => arestaDaResposta(g, aresta, d)).sort(ordemDasArestas);
|
|
232
|
-
const devolvidas = todas.slice(0, limite);
|
|
267
|
+
const todas = [...vistas.values()].map(({ aresta, d }) => ({ aresta, r: arestaDaResposta(g, aresta, d) })).sort((x, y) => ordemDasArestas(x.r, y.r));
|
|
268
|
+
const devolvidas = todas.slice(0, limite).map(({ aresta, r }) => comArvore(g, aresta, r, situacao));
|
|
233
269
|
const idPorRotulo = new Map([...distancia.keys()].map((id) => [g.rotulos.get(id), id]));
|
|
234
270
|
const pontas = new Set([alvo.node_id, ...devolvidas.flatMap((a) => [idPorRotulo.get(a.from), idPorRotulo.get(a.to)])]);
|
|
235
271
|
const nos = [...pontas].map((id) => noDaResposta(g, g.nos.get(id), distancia.get(id)))
|
|
@@ -239,31 +275,31 @@ function vizinhanca(g, cabecalho, tipo, texto, opcoes) {
|
|
|
239
275
|
consulta: { tipo, alvo: texto, para: null, profundidade, sentido, tipos, limite },
|
|
240
276
|
indice: cabecalho, alvo: noDaResposta(g, alvo, 0), para: null, nos, total_nos: distancia.size,
|
|
241
277
|
arestas: devolvidas, total_arestas: todas.length, truncado: todas.length > limite,
|
|
242
|
-
caminho: null, nos_explorados: null, parcial: exports.AVISO_DE_PARCIALIDADE,
|
|
278
|
+
caminho: null, nos_explorados: null, fontes: fontesDaResposta(g, nos, devolvidas, situacao), parcial: exports.AVISO_DE_PARCIALIDADE,
|
|
243
279
|
};
|
|
244
280
|
}
|
|
245
|
-
function vizinhos(g, cabecalho, alvo, opcoes = {}) {
|
|
246
|
-
return vizinhanca(g, cabecalho, 'vizinhos', alvo, opcoes);
|
|
281
|
+
function vizinhos(g, cabecalho, alvo, opcoes = {}, situacao = exports.TUDO_IGUAL) {
|
|
282
|
+
return vizinhanca(g, cabecalho, 'vizinhos', alvo, opcoes, situacao);
|
|
247
283
|
}
|
|
248
284
|
/** Quem chama o simbolo: as arestas `calls` que chegam, ate `profundidade` saltos. */
|
|
249
|
-
function chamadores(g, cabecalho, alvo, opcoes = {}) {
|
|
285
|
+
function chamadores(g, cabecalho, alvo, opcoes = {}, situacao = exports.TUDO_IGUAL) {
|
|
250
286
|
if (resolverNo(g, alvo).kind !== 'symbol')
|
|
251
287
|
throw new ErroDeConsulta('grafo.consulta.alvo-invalido', 'chamadores pede um simbolo; para arquivo, use importadores ou vizinhos');
|
|
252
|
-
return vizinhanca(g, cabecalho, 'chamadores', alvo, { ...opcoes, sentido: 'entrada', tipos: ['calls'] });
|
|
288
|
+
return vizinhanca(g, cabecalho, 'chamadores', alvo, { ...opcoes, sentido: 'entrada', tipos: ['calls'] }, situacao);
|
|
253
289
|
}
|
|
254
290
|
/** Quem importa o arquivo ou o simbolo: as arestas `imports` que chegam, ate `profundidade` saltos. */
|
|
255
|
-
function importadores(g, cabecalho, alvo, opcoes = {}) {
|
|
291
|
+
function importadores(g, cabecalho, alvo, opcoes = {}, situacao = exports.TUDO_IGUAL) {
|
|
256
292
|
const kind = resolverNo(g, alvo).kind;
|
|
257
293
|
if (kind !== 'file' && kind !== 'symbol')
|
|
258
294
|
throw new ErroDeConsulta('grafo.consulta.alvo-invalido', 'importadores pede um arquivo ou um simbolo');
|
|
259
|
-
return vizinhanca(g, cabecalho, 'importadores', alvo, { ...opcoes, sentido: 'entrada', tipos: ['imports'] });
|
|
295
|
+
return vizinhanca(g, cabecalho, 'importadores', alvo, { ...opcoes, sentido: 'entrada', tipos: ['imports'] }, situacao);
|
|
260
296
|
}
|
|
261
297
|
/**
|
|
262
298
|
* D5: o menor caminho de `de` a `para`, pelas arestas no sentido pedido (padrao: `saida`, a direcao
|
|
263
299
|
* da aresta). Busca em largura com a expansao na ordem fixa: entre caminhos do mesmo tamanho, sai
|
|
264
300
|
* sempre o mesmo. Sem caminho, `caminho` e `null`, com os nos explorados.
|
|
265
301
|
*/
|
|
266
|
-
function caminho(g, cabecalho, de, para, opcoes = {}) {
|
|
302
|
+
function caminho(g, cabecalho, de, para, opcoes = {}, situacao = exports.TUDO_IGUAL) {
|
|
267
303
|
const sentido = opcoes.sentido ?? 'saida';
|
|
268
304
|
if (!['entrada', 'saida', 'ambos'].includes(sentido))
|
|
269
305
|
throw new ErroDeConsulta('grafo.consulta.uso', `sentido desconhecido: ${sentido}`);
|
|
@@ -284,20 +320,20 @@ function caminho(g, cabecalho, de, para, opcoes = {}) {
|
|
|
284
320
|
if (anterior.has(destino.node_id)) {
|
|
285
321
|
const cadeia = [];
|
|
286
322
|
for (let id = destino.node_id, atual = anterior.get(id); atual; id = atual.de, atual = anterior.get(id)) {
|
|
287
|
-
cadeia.push({ id,
|
|
323
|
+
cadeia.push({ id, sentido: atual.sentido, aresta: atual.aresta });
|
|
288
324
|
}
|
|
289
325
|
cadeia.reverse();
|
|
290
|
-
cadeia.
|
|
291
|
-
passos = cadeia.map((c) => c.passo);
|
|
326
|
+
passos = cadeia.map((c, n) => ({ sentido: c.sentido, aresta: comArvore(g, c.aresta, arestaDaResposta(g, c.aresta, n), situacao) }));
|
|
292
327
|
nos = [origem.node_id, ...cadeia.map((c) => c.id)].map((id, d) => noDaResposta(g, g.nos.get(id), d));
|
|
293
328
|
}
|
|
329
|
+
const arestas = passos ? passos.map((p) => p.aresta) : [];
|
|
294
330
|
return {
|
|
295
331
|
schema: exports.CONSULTA_SCHEMA,
|
|
296
332
|
consulta: { tipo: 'caminho', alvo: de, para, profundidade: null, sentido, tipos, limite: null },
|
|
297
333
|
indice: cabecalho, alvo: noDaResposta(g, origem, 0), para: noDaResposta(g, destino, passos ? passos.length : null),
|
|
298
334
|
nos, total_nos: nos.length,
|
|
299
|
-
arestas
|
|
300
|
-
caminho: passos, nos_explorados: anterior.size, parcial: exports.AVISO_DE_PARCIALIDADE,
|
|
335
|
+
arestas, total_arestas: arestas.length, truncado: false,
|
|
336
|
+
caminho: passos, nos_explorados: anterior.size, fontes: fontesDaResposta(g, nos, arestas, situacao), parcial: exports.AVISO_DE_PARCIALIDADE,
|
|
301
337
|
};
|
|
302
338
|
}
|
|
303
339
|
function jsonDaResposta(r) {
|
|
@@ -310,8 +346,18 @@ function linhasDaEvidencia(e) {
|
|
|
310
346
|
: `${e.path} pagina ${s.page}`;
|
|
311
347
|
return ` ${e.extractor_id} ${e.extraction_method} ${onde} bytes ${s.byte_start}-${s.byte_end}`;
|
|
312
348
|
}
|
|
349
|
+
/** KG5 fatia 5 (D9): a aresta cuja fonte mudou diz isso na propria linha, como o JSON diz no campo `arvore`. */
|
|
313
350
|
function linhasDaAresta(a, prefixo = ' ') {
|
|
314
|
-
|
|
351
|
+
const marca = a.arvore === 'modificada' ? ' [fonte modificada na arvore]' : '';
|
|
352
|
+
return [`${prefixo}${a.kind} ${a.from} -> ${a.to}${marca}`, ...a.evidencias.map(linhasDaEvidencia)];
|
|
353
|
+
}
|
|
354
|
+
/** KG5 fatia 5 (D9): ate cinco fontes que nao tem na arvore os bytes do indice, com a situacao de cada uma. */
|
|
355
|
+
function linhaDasFontesMudadas(fontes) {
|
|
356
|
+
const mudaram = fontes.filter((f) => f.arvore !== 'igual');
|
|
357
|
+
if (!mudaram.length)
|
|
358
|
+
return [];
|
|
359
|
+
const resto = mudaram.length > 5 ? ` e mais ${mudaram.length - 5}` : '';
|
|
360
|
+
return [`fontes que mudaram na arvore: ${mudaram.slice(0, 5).map((f) => `${f.path} (${f.arvore})`).join(', ')}${resto}`];
|
|
315
361
|
}
|
|
316
362
|
function textoDaResposta(r) {
|
|
317
363
|
const c = r.consulta, i = r.indice;
|
|
@@ -320,6 +366,7 @@ function textoDaResposta(r) {
|
|
|
320
366
|
];
|
|
321
367
|
if (i.arvore === 'modificada')
|
|
322
368
|
linhas.push('aviso: a arvore tem mudanca rastreada; a resposta e do HEAD, nao da arvore');
|
|
369
|
+
linhas.push(...linhaDasFontesMudadas(r.fontes));
|
|
323
370
|
linhas.push(`extratores: ${i.extratores.map((e) => `${e.extractor_id} ${e.extractor_version}`).join(', ')}`);
|
|
324
371
|
if (c.tipo === 'caminho') {
|
|
325
372
|
const para = r.para;
|