@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
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONTEXT_SCHEMA = void 0;
|
|
3
|
+
exports.SERVER_CONTEXT_SCHEMA = exports.CONTEXT_SCHEMA = void 0;
|
|
4
4
|
exports.buildContext = buildContext;
|
|
5
5
|
const portfolio_1 = require("./portfolio");
|
|
6
6
|
const company_brain_client_1 = require("./company-brain-client");
|
|
7
7
|
const company_brain_contract_1 = require("./company-brain-contract");
|
|
8
8
|
const company_brain_source_1 = require("./company-brain-source");
|
|
9
9
|
exports.CONTEXT_SCHEMA = 'ork.brain-context/v1';
|
|
10
|
+
exports.SERVER_CONTEXT_SCHEMA = 'orkmind.company-brain-context/v1';
|
|
11
|
+
const SEM_MODO_CONTEXT = 'brain.selection.context-unsupported';
|
|
12
|
+
const SERVIDOR_INVALIDO = 'brain.context.server-invalid';
|
|
10
13
|
const ID = /^(prod|proj|init)-[a-z0-9][a-z0-9-]{2,47}$/;
|
|
11
14
|
const ORDEM = { prod: 0, proj: 1, init: 2 };
|
|
12
15
|
const LIMITE = 1000;
|
|
@@ -27,25 +30,122 @@ function citacaoDe(source) {
|
|
|
27
30
|
return null;
|
|
28
31
|
return { instance, source_ref, source_hash, source_version, location };
|
|
29
32
|
}
|
|
33
|
+
/** O servidor exige também `authority`: o pacote dele só traz item com a citação inteira; a consulta exige o mesmo. */
|
|
34
|
+
const citadoPeloServidor = (source) => citacaoDe(source) !== null && typeof source.authority === 'string' && source.authority !== '';
|
|
30
35
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
36
|
+
* Confere um pacote `orkmind.company-brain-context/v1` contra o lote pedido: schema, tenant, pedido,
|
|
37
|
+
* digest recalculado, citação inteira, ordem, fecho de pais e destino de cada id pedido.
|
|
33
38
|
*/
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
function conferirPacoteDoServidor(r, tenant, lote) {
|
|
40
|
+
const ctx = r.context;
|
|
41
|
+
if (!['ok', 'empty'].includes(r.state) || !ctx || typeof ctx !== 'object' || Array.isArray(ctx))
|
|
42
|
+
return false;
|
|
43
|
+
if (Object.keys(ctx).sort().join(',') !== 'digest,gaps,items,requested,schema,tenant_id')
|
|
44
|
+
return false;
|
|
45
|
+
const { digest: recebido, ...corpo } = ctx;
|
|
46
|
+
if (ctx.schema !== exports.SERVER_CONTEXT_SCHEMA || ctx.tenant_id !== tenant || (0, company_brain_contract_1.canonical)(ctx.requested) !== (0, company_brain_contract_1.canonical)(lote) ||
|
|
47
|
+
!Array.isArray(ctx.items) || !Array.isArray(ctx.gaps) || typeof recebido !== 'string' || (0, company_brain_contract_1.digest)(corpo) !== recebido)
|
|
48
|
+
return false;
|
|
49
|
+
if (r.state !== (ctx.items.length ? 'ok' : 'empty'))
|
|
50
|
+
return false;
|
|
51
|
+
const pedidos = new Set(lote), vistos = new Map(), codigos = new Map();
|
|
52
|
+
for (const g of ctx.gaps) {
|
|
53
|
+
if (!g || typeof g.id !== 'string' || typeof g.code !== 'string' || !ID.test(g.id))
|
|
54
|
+
return false;
|
|
55
|
+
if (!codigos.has(g.id))
|
|
56
|
+
codigos.set(g.id, new Set());
|
|
57
|
+
codigos.get(g.id).add(g.code);
|
|
58
|
+
}
|
|
59
|
+
for (const item of ctx.items) {
|
|
60
|
+
if (!item || typeof item.id !== 'string' || !ID.test(item.id) || vistos.has(item.id))
|
|
61
|
+
return false;
|
|
62
|
+
if (item.state === 'withheld') {
|
|
63
|
+
if (Object.keys(item).length !== 2)
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
else if (item.state !== 'ok' || !item.entity || typeof item.entity !== 'object' || item.entity.kind !== kindDe(item.id) ||
|
|
67
|
+
!Number.isInteger(item.entity.version) || !citadoPeloServidor(item.entity.source))
|
|
68
|
+
return false;
|
|
69
|
+
vistos.set(item.id, item);
|
|
70
|
+
}
|
|
71
|
+
const ordem = ctx.items.map((i) => i.id);
|
|
72
|
+
const ordenado = [...ordem].sort((a, b) => ORDEM[kindDe(a)] - ORDEM[kindDe(b)] || comparar(a, b));
|
|
73
|
+
if ((0, company_brain_contract_1.canonical)(ordem) !== (0, company_brain_contract_1.canonical)(ordenado))
|
|
74
|
+
return false;
|
|
75
|
+
// Fecho: todo item fora do pedido é pai, um kind acima, de um item citado do pacote.
|
|
76
|
+
const paisCitados = new Set();
|
|
77
|
+
for (const item of ctx.items)
|
|
78
|
+
if (item.state === 'ok') {
|
|
79
|
+
const parent = item.entity.parent_id;
|
|
80
|
+
if (typeof parent === 'string' && ID.test(parent) && ORDEM[kindDe(parent)] < ORDEM[kindDe(item.id)])
|
|
81
|
+
paisCitados.add(parent);
|
|
82
|
+
}
|
|
83
|
+
for (const id of vistos.keys())
|
|
84
|
+
if (!pedidos.has(id) && !paisCitados.has(id))
|
|
85
|
+
return false;
|
|
86
|
+
// Destino: todo id pedido sai como item ou como lacuna de desconhecido ou de citação incompleta.
|
|
87
|
+
for (const id of lote) {
|
|
88
|
+
const c = codigos.get(id);
|
|
89
|
+
if (!vistos.has(id) && !(c?.has('entity.unknown') || c?.has('citation.incomplete')))
|
|
90
|
+
return false;
|
|
91
|
+
if (vistos.has(id) && (c?.has('entity.unknown') || c?.has('citation.incomplete')))
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* B4.2: resolve o escopo pelo modo `context` do servidor. Devolve null quando o OrkMind não tem o modo
|
|
98
|
+
* (o chamador usa a consulta), ou a resposta que encerra o pacote.
|
|
99
|
+
*/
|
|
100
|
+
function resolverPeloServidor(transport, tenant, pedido, fonte, pai) {
|
|
101
|
+
const escopo = new Set(pedido), brain = new Map(), retidos = new Set(), semCitacao = new Set();
|
|
102
|
+
let primeiro = true;
|
|
103
|
+
for (let pendentes = pedido; pendentes.length;) {
|
|
104
|
+
const resolvidosNaVolta = [];
|
|
105
|
+
for (let inicio = 0; inicio < pendentes.length; inicio += LIMITE) {
|
|
106
|
+
const lote = pendentes.slice(inicio, inicio + LIMITE);
|
|
107
|
+
const r = transport({ schema: company_brain_client_1.BRAIN_API, operation: 'query', payload: (0, company_brain_contract_1.validateContract)({ schema: 'orkmind.company-brain-selection/v1',
|
|
108
|
+
tenant_id: tenant, facets: { ids: lote, kinds: [], workspace_ids: [], source_instances: [] }, mode: 'context',
|
|
109
|
+
limit: lote.length, offset: 0 }) });
|
|
110
|
+
if (r.state === 'unavailable' && r.error === SEM_MODO_CONTEXT)
|
|
111
|
+
return primeiro ? null : { state: 'conflict', error: SERVIDOR_INVALIDO };
|
|
112
|
+
primeiro = false;
|
|
113
|
+
if (falha(r.state))
|
|
114
|
+
return r;
|
|
115
|
+
if (!conferirPacoteDoServidor(r, tenant, lote))
|
|
116
|
+
return { state: 'conflict', error: SERVIDOR_INVALIDO };
|
|
117
|
+
const ctx = r.context;
|
|
118
|
+
for (const g of ctx.gaps)
|
|
119
|
+
if (g.code === 'citation.incomplete')
|
|
120
|
+
semCitacao.add(g.id);
|
|
121
|
+
for (const item of ctx.items) {
|
|
122
|
+
// Pai que outro lote ou volta já resolveu vale uma vez só: a primeira resposta fica.
|
|
123
|
+
if (escopo.has(item.id) && !lote.includes(item.id))
|
|
124
|
+
continue;
|
|
125
|
+
escopo.add(item.id);
|
|
126
|
+
resolvidosNaVolta.push(item.id);
|
|
127
|
+
if (item.state === 'withheld')
|
|
128
|
+
retidos.add(item.id);
|
|
129
|
+
else
|
|
130
|
+
brain.set(item.id, { ...item.entity, id: item.id });
|
|
131
|
+
}
|
|
132
|
+
resolvidosNaVolta.push(...lote);
|
|
133
|
+
}
|
|
134
|
+
// O servidor fecha os pais que o Brain conhece; os que só a fonte local conhece vão na próxima volta.
|
|
135
|
+
const novos = new Set();
|
|
136
|
+
for (const id of resolvidosNaVolta)
|
|
137
|
+
if (!retidos.has(id))
|
|
138
|
+
for (const parent of [pai(id, fonte.get(id)?.parent_id), pai(id, brain.get(id)?.parent_id)])
|
|
139
|
+
if (parent && !escopo.has(parent))
|
|
140
|
+
novos.add(parent);
|
|
141
|
+
novos.forEach(id => escopo.add(id));
|
|
142
|
+
pendentes = [...novos].sort(comparar);
|
|
143
|
+
}
|
|
144
|
+
return { brain, retidos, semCitacao, escopo };
|
|
145
|
+
}
|
|
146
|
+
/** B4.1: o caminho anterior ao modo `context`, por `query` e `get`, para um OrkMind sem o modo. */
|
|
147
|
+
function resolverPelaConsulta(transport, tenant, pedido, fonte, pai) {
|
|
46
148
|
const escopo = new Set(pedido), brain = new Map(), retidos = new Set();
|
|
47
|
-
// O pai só entra por um filho visível e tem kind acima dele: init, proj e prod fecham em três voltas.
|
|
48
|
-
const pai = (id, parent) => typeof parent === 'string' && ID.test(parent) && ORDEM[kindDe(parent)] < ORDEM[kindDe(id)] ? parent : null;
|
|
49
149
|
let gets = 0;
|
|
50
150
|
for (let pendentes = pedido; pendentes.length;) {
|
|
51
151
|
for (let inicio = 0; inicio < pendentes.length; inicio += LIMITE) {
|
|
@@ -54,7 +154,7 @@ function buildContext(c, ids, transport, thread) {
|
|
|
54
154
|
tenant_id: tenant, facets: { ids: lote, kinds: [], workspace_ids: [], source_instances: [] }, mode: 'selection',
|
|
55
155
|
limit: lote.length, offset: 0 }) });
|
|
56
156
|
if (falha(r.state))
|
|
57
|
-
return
|
|
157
|
+
return r;
|
|
58
158
|
const itens = Array.isArray(r.items) ? r.items : [];
|
|
59
159
|
for (const item of itens)
|
|
60
160
|
if (item?.state === 'ok' && doLote.has(item.entity?.id))
|
|
@@ -67,10 +167,10 @@ function buildContext(c, ids, transport, thread) {
|
|
|
67
167
|
else if (retidosNoLote)
|
|
68
168
|
for (const id of faltantes) {
|
|
69
169
|
if (++gets > LIMITE_DE_GET)
|
|
70
|
-
return
|
|
170
|
+
return { state: 'unavailable', error: 'brain.context.get-limit' };
|
|
71
171
|
const g = transport({ schema: company_brain_client_1.BRAIN_API, operation: 'get', payload: { tenant_id: tenant, id } });
|
|
72
172
|
if (falha(g.state))
|
|
73
|
-
return
|
|
173
|
+
return g;
|
|
74
174
|
if (g.state === 'withheld')
|
|
75
175
|
retidos.add(id);
|
|
76
176
|
else if (g.state === 'ok' && g.entity?.id === id)
|
|
@@ -87,6 +187,35 @@ function buildContext(c, ids, transport, thread) {
|
|
|
87
187
|
}
|
|
88
188
|
pendentes = novos.sort(comparar);
|
|
89
189
|
}
|
|
190
|
+
return { brain, retidos, semCitacao: new Set(), escopo };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Monta o pacote dos ids pedidos mais a cadeia de pais. A fonte canônica é o portfólio local;
|
|
194
|
+
* o Brain é projeção, e a diferença entre os dois sai como frescor e lacuna, nunca é corrigida aqui.
|
|
195
|
+
*/
|
|
196
|
+
function buildContext(c, ids, transport, thread) {
|
|
197
|
+
const tenant = c.manifesto.memory.tenant;
|
|
198
|
+
const pedido = [...new Set(ids)].sort(comparar);
|
|
199
|
+
if (!pedido.length)
|
|
200
|
+
throw Error('brain.context.ids-required');
|
|
201
|
+
if (pedido.some(id => !ID.test(id)))
|
|
202
|
+
throw Error('brain.context.id-invalid');
|
|
203
|
+
if (pedido.length > LIMITE)
|
|
204
|
+
throw Error('brain.context.too-many');
|
|
205
|
+
const fonte = new Map((0, company_brain_source_1.portfolioEntities)((0, portfolio_1.readPortfolio)(c.raiz), { tenant, instance: c.manifesto.project.name, thread, aclRef: 'ork-factory' }).map(e => [e.id, e]));
|
|
206
|
+
const base = { schema: exports.CONTEXT_SCHEMA, tenant, contrato: company_brain_contract_1.CONTRACT_HASH, thread, pedido };
|
|
207
|
+
// O pai só entra por um filho visível e tem kind acima dele: init, proj e prod fecham em três voltas.
|
|
208
|
+
const pai = (id, parent) => typeof parent === 'string' && ID.test(parent) && ORDEM[kindDe(parent)] < ORDEM[kindDe(id)] ? parent : null;
|
|
209
|
+
const doServidor = resolverPeloServidor(transport, tenant, pedido, fonte, pai);
|
|
210
|
+
const caminho = doServidor === null ? 'consulta' : 'servidor';
|
|
211
|
+
const encerrar = (r) => ({ ...base, state: r.state, ...(r.error ? { error: r.error } : {}), itens: [], lacunas: [],
|
|
212
|
+
digest: null, consultadoEm: new Date().toISOString(), caminho });
|
|
213
|
+
if (doServidor && 'state' in doServidor)
|
|
214
|
+
return encerrar(doServidor);
|
|
215
|
+
const resolvido = doServidor ?? resolverPelaConsulta(transport, tenant, pedido, fonte, pai);
|
|
216
|
+
if ('state' in resolvido)
|
|
217
|
+
return encerrar(resolvido);
|
|
218
|
+
const { escopo, brain, retidos, semCitacao } = resolvido;
|
|
90
219
|
const itens = [], lacunas = [];
|
|
91
220
|
const lacuna = (id, codigo) => lacunas.push({ id, codigo });
|
|
92
221
|
for (const id of escopo) {
|
|
@@ -95,12 +224,19 @@ function buildContext(c, ids, transport, thread) {
|
|
|
95
224
|
lacuna(id, 'brain.retido');
|
|
96
225
|
continue;
|
|
97
226
|
}
|
|
227
|
+
// Sem citação no Brain vale como no caminho da consulta: o Brain tem a entidade, mas ela não é citável.
|
|
228
|
+
if (semCitacao.has(id)) {
|
|
229
|
+
lacuna(id, 'citacao.incompleta');
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
98
232
|
const b = brain.get(id), f = fonte.get(id);
|
|
99
233
|
if (!b && !f) {
|
|
100
234
|
lacuna(id, 'entidade.desconhecida');
|
|
101
235
|
continue;
|
|
102
236
|
}
|
|
103
|
-
|
|
237
|
+
// Suspeitas da revisao de 03/10: a citacao exige `authority` nos dois caminhos, como o servidor (o
|
|
238
|
+
// schema do Source a exige); sem isso, um Brain fora do contrato dava pacote e digest diferentes por caminho.
|
|
239
|
+
const entidade = b ?? f, citacao = citadoPeloServidor(entidade.source) ? citacaoDe(entidade.source) : null;
|
|
104
240
|
if (!citacao) {
|
|
105
241
|
lacuna(id, 'citacao.incompleta');
|
|
106
242
|
continue;
|
|
@@ -128,5 +264,5 @@ function buildContext(c, ids, transport, thread) {
|
|
|
128
264
|
lacunas.sort((a, b) => comparar(a.id, b.id) || comparar(a.codigo, b.codigo));
|
|
129
265
|
// O digest cobre o que foi dito e de onde veio; o horário da consulta fica fora para o pacote ser reproduzível.
|
|
130
266
|
const corpo = { ...base, state: (itens.length ? 'ok' : 'empty'), itens, lacunas };
|
|
131
|
-
return { ...corpo, digest: (0, company_brain_contract_1.digest)(corpo), consultadoEm: new Date().toISOString() };
|
|
267
|
+
return { ...corpo, digest: (0, company_brain_contract_1.digest)(corpo), consultadoEm: new Date().toISOString(), caminho };
|
|
132
268
|
}
|
|
@@ -118,7 +118,8 @@ function withProcessLock(dir, busy, run) {
|
|
|
118
118
|
}
|
|
119
119
|
function durableAppend(file, value) {
|
|
120
120
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
121
|
-
|
|
121
|
+
// RM-047: O_NOFOLLOW; um ledger versionado como link não leva o append para fora da raiz.
|
|
122
|
+
const fd = fs.openSync(file, fs.constants.O_WRONLY | fs.constants.O_APPEND | fs.constants.O_CREAT | fs.constants.O_NOFOLLOW, 0o600);
|
|
122
123
|
try {
|
|
123
124
|
fs.writeFileSync(fd, JSON.stringify(value) + '\n');
|
|
124
125
|
fs.fsyncSync(fd);
|
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.brainAdmin = brainAdmin;
|
|
4
37
|
exports.reconcileBrain = reconcileBrain;
|
|
5
38
|
exports.applyBrain = applyBrain;
|
|
39
|
+
const os = __importStar(require("node:os"));
|
|
6
40
|
const node_child_process_1 = require("node:child_process");
|
|
7
41
|
const project_state_1 = require("./project-state");
|
|
8
42
|
const portfolio_1 = require("./portfolio");
|
|
@@ -15,7 +49,8 @@ function brainAdmin(c) {
|
|
|
15
49
|
const dsn = config.database_url_env ? process.env[config.database_url_env] : undefined;
|
|
16
50
|
if (config.mode !== 'orkmind' || !dsn)
|
|
17
51
|
throw Error('brain.configuration.missing');
|
|
18
|
-
|
|
52
|
+
// RM-047: cwd fora do clone; um nome de interpretador em memory.cli não acha arquivo do repositório.
|
|
53
|
+
const r = (0, node_child_process_1.spawnSync)(config.cli, ['brain', 'migration'], { cwd: os.homedir(), shell: false, encoding: 'utf8', timeout: Math.min(config.timeout_ms, 15000), maxBuffer: 2 * 1024 * 1024,
|
|
19
54
|
input: JSON.stringify({ schema: 'orkmind.company-brain-admin/v1', operation, payload }),
|
|
20
55
|
env: { PATH: process.env.PATH ?? '/usr/bin:/bin', PYTHONDONTWRITEBYTECODE: '1', ORKMIND_DATABASE_URL: dsn, ORKMIND_BRAIN_TENANT: config.tenant } });
|
|
21
56
|
try {
|