@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.
Files changed (260) hide show
  1. package/adapters/claude-code/README.md +158 -0
  2. package/adapters/claude-code/agents/ork-master.md +2 -0
  3. package/adapters/claude-code/commands/master.md +8 -0
  4. package/adapters/claude-code/commands/ork.md +9 -0
  5. package/adapters/claude-code/mods/autoridade.json +56 -0
  6. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  7. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  8. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  9. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  10. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  11. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  12. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  13. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  14. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  15. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  16. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  17. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  18. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  19. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  20. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  21. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  22. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  23. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  24. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  25. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  27. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  28. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  29. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  30. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  31. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  32. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
  33. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  34. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  35. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  36. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  37. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  38. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  39. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  40. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  41. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  42. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  43. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  44. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  45. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  46. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  47. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  48. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  49. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  50. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  51. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  52. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  53. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  54. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  55. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  56. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  57. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  58. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  59. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  60. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  61. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  62. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  63. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  64. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  65. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  66. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  67. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  68. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  69. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  70. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  71. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  72. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  73. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  74. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  75. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  76. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  77. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  78. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  79. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  80. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  81. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  82. package/adapters/codex/skills/ork/SKILL.md +18 -3
  83. package/adapters/hermes/README.md +1 -0
  84. package/adapters/hermes/bin/ork-network-status.sh +10 -0
  85. package/adapters/hermes/hermes.plugin.json +1 -0
  86. package/adapters/hermes/hitl-ingress/__init__.py +2 -2
  87. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +7 -6
  88. package/adapters/openclaw/README.md +26 -5
  89. package/adapters/openclaw/dist/hitl-ingress.js +2 -2
  90. package/adapters/openclaw/dist/index.js +46 -11
  91. package/adapters/openclaw/openclaw.plugin.json +5 -1
  92. package/adapters/openclaw/package.json +2 -2
  93. package/adapters/openclaw/src/hitl-ingress.ts +2 -2
  94. package/adapters/openclaw/src/index.ts +49 -11
  95. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  96. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  97. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  98. package/assets/docs-en/produto/README.md +14 -0
  99. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  100. package/assets/docs-en/roadmap/README.md +14 -0
  101. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  102. package/assets/orkmind_bridge.py +117 -9
  103. package/dist/adapters/claude-bg.js +116 -18
  104. package/dist/adapters/codex.js +14 -4
  105. package/dist/agents-md.js +24 -14
  106. package/dist/auditrun.js +22 -3
  107. package/dist/board.js +20 -17
  108. package/dist/branch-de-estado.js +88 -10
  109. package/dist/busca-semantica.js +52 -12
  110. package/dist/canarios-rm057.js +149 -0
  111. package/dist/canarios.js +2 -0
  112. package/dist/catalogo.js +33 -0
  113. package/dist/ci.js +21 -8
  114. package/dist/claims-conferir.js +342 -0
  115. package/dist/claims.js +41 -1
  116. package/dist/company-brain-client.js +36 -1
  117. package/dist/company-brain-context.js +158 -22
  118. package/dist/company-brain-journal.js +2 -1
  119. package/dist/company-brain-migration.js +36 -1
  120. package/dist/conducao-sentinela.js +388 -0
  121. package/dist/conducao-texto.js +12 -18
  122. package/dist/conducao.js +122 -30
  123. package/dist/conhecimento.js +490 -0
  124. package/dist/docs.js +70 -17
  125. package/dist/doctor-pulse-cron.js +349 -0
  126. package/dist/doctor-rede.js +150 -0
  127. package/dist/doctor.js +195 -111
  128. package/dist/entrega-pr.js +42 -29
  129. package/dist/escopo-escrita.js +10 -1
  130. package/dist/esgotamentos.js +181 -0
  131. package/dist/estado-thread.js +23 -1
  132. package/dist/experiencia-instalacao.js +45 -25
  133. package/dist/experiencia.js +12 -2
  134. package/dist/fabrica-batida.js +310 -0
  135. package/dist/fabrica-estado.js +52 -14
  136. package/dist/fabrica-publicar.js +9 -1
  137. package/dist/fechamento.js +20 -66
  138. package/dist/fila-pesada.js +444 -0
  139. package/dist/fix.js +3 -2
  140. package/dist/forja.js +31 -7
  141. package/dist/gates.js +3 -24
  142. package/dist/handoff.js +10 -6
  143. package/dist/hitl-contract.js +59 -4
  144. package/dist/hitl-curto.js +11 -6
  145. package/dist/hitl-gates.js +5 -0
  146. package/dist/hitl-local-receipt.js +2 -0
  147. package/dist/hitl-lote.js +5 -2
  148. package/dist/hitl-resumo.js +38 -3
  149. package/dist/hitl-tempo-parado.js +201 -0
  150. package/dist/hitl-texto-livre.js +5 -5
  151. package/dist/hitl.js +29 -33
  152. package/dist/horario.js +41 -7
  153. package/dist/hosts.js +104 -11
  154. package/dist/impedimento.js +299 -0
  155. package/dist/index.js +961 -542
  156. package/dist/indice-vetorial.js +87 -10
  157. package/dist/indice.js +9 -1
  158. package/dist/init.js +56 -43
  159. package/dist/instabilidade.js +144 -0
  160. package/dist/integracoes-locais.js +4 -0
  161. package/dist/intelligence-graph-cli.js +170 -16
  162. package/dist/intelligence-graph-contexto.js +254 -0
  163. package/dist/intelligence-graph-contract.js +2 -1
  164. package/dist/intelligence-graph-extract-md.js +56 -4
  165. package/dist/intelligence-graph-extract-ts.js +71 -3
  166. package/dist/intelligence-graph-parsers.js +6 -4
  167. package/dist/intelligence-graph-query.js +66 -19
  168. package/dist/leases.js +664 -87
  169. package/dist/ledger-stats.js +15 -1
  170. package/dist/ledger.js +18 -1
  171. package/dist/licoes.js +1 -0
  172. package/dist/liveness.js +6 -3
  173. package/dist/locale-ajuda.js +761 -0
  174. package/dist/locale-gerados.js +160 -0
  175. package/dist/locale-master.js +99 -0
  176. package/dist/locale-onboarding.js +92 -0
  177. package/dist/locale-phase.js +151 -0
  178. package/dist/locale-pulse.js +211 -0
  179. package/dist/locale-retry.js +385 -0
  180. package/dist/locale-roadmap.js +102 -0
  181. package/dist/locale-ship.js +494 -0
  182. package/dist/locale-thread.js +277 -0
  183. package/dist/locale-verify.js +125 -0
  184. package/dist/locale.js +714 -0
  185. package/dist/maestro-runtime.js +4 -1
  186. package/dist/manifest.js +149 -4
  187. package/dist/maquina.js +23 -4
  188. package/dist/master-digest.js +6 -1
  189. package/dist/master-nota.js +18 -11
  190. package/dist/master.js +145 -31
  191. package/dist/mcp-artifacts.js +43 -3
  192. package/dist/mcp-git.js +42 -8
  193. package/dist/mcp-grafo-worker.js +5 -3
  194. package/dist/mcp-grafo.js +55 -6
  195. package/dist/mcp-server.js +22 -3
  196. package/dist/mcp-ship.js +3 -1
  197. package/dist/mcp-verify.js +6 -1
  198. package/dist/memoria.js +48 -6
  199. package/dist/modos.js +3 -6
  200. package/dist/network-roadmap.js +196 -18
  201. package/dist/noctum-arco.js +911 -0
  202. package/dist/noctum-capacidade.js +141 -0
  203. package/dist/noctum-envelope.js +810 -0
  204. package/dist/noctum-execucao.js +304 -0
  205. package/dist/noctum-fila.js +280 -0
  206. package/dist/ocupacao.js +40 -5
  207. package/dist/onboarding.js +40 -21
  208. package/dist/orkmind.js +99 -7
  209. package/dist/orquestracao.js +24 -21
  210. package/dist/parado-no-condutor.js +219 -38
  211. package/dist/phase.js +160 -52
  212. package/dist/policies.js +56 -5
  213. package/dist/portfolio.js +8 -3
  214. package/dist/postura-local.js +234 -0
  215. package/dist/preflight.js +11 -10
  216. package/dist/procedencia.js +225 -0
  217. package/dist/projeto-alvo.js +132 -5
  218. package/dist/prompts.js +40 -1
  219. package/dist/prova-ativacao.js +75 -6
  220. package/dist/pulse-delivery.js +47 -4
  221. package/dist/pulse.js +98 -19
  222. package/dist/ratelimit.js +24 -6
  223. package/dist/recall.js +3 -1
  224. package/dist/redacao-saida.js +63 -0
  225. package/dist/rede-adesao.js +399 -0
  226. package/dist/rede-forja.js +289 -0
  227. package/dist/rede-projetos.js +239 -0
  228. package/dist/rede-status.js +337 -0
  229. package/dist/rede.js +980 -0
  230. package/dist/retry.js +291 -140
  231. package/dist/roadmap-reservas.js +20 -3
  232. package/dist/roadmap-status.js +150 -34
  233. package/dist/runtime-context.js +181 -3
  234. package/dist/runtime-profiles.js +22 -1
  235. package/dist/runtimes.js +2 -1
  236. package/dist/saida-segura.js +58 -0
  237. package/dist/session-events.js +7 -3
  238. package/dist/session-watcher-claude.js +120 -24
  239. package/dist/session-watcher.js +185 -33
  240. package/dist/sessoes-contas.js +187 -0
  241. package/dist/sessoes-inventario.js +6 -18
  242. package/dist/sessoes.js +83 -2
  243. package/dist/ship-publicar.js +800 -0
  244. package/dist/ship.js +157 -88
  245. package/dist/steal.js +77 -0
  246. package/dist/thread-close.js +3 -2
  247. package/dist/thread.js +299 -49
  248. package/dist/util.js +8 -1
  249. package/dist/verify.js +141 -52
  250. package/dist/vida-da-thread.js +254 -0
  251. package/dist/worktree-local.js +165 -0
  252. package/dist/worktree.js +25 -2
  253. package/dist/yaml.js +27 -8
  254. package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
  255. package/package.json +7 -3
  256. package/references/definition-of-done.md +1 -1
  257. package/schemas/code-artifact-graph.v1.schema.json +2 -1
  258. package/skills/README.md +1 -1
  259. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  260. 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
- * Monta o pacote dos ids pedidos mais a cadeia de pais. A fonte canônica é o portfólio local;
32
- * o Brain é projeção, e a diferença entre os dois sai como frescor e lacuna, nunca é corrigida aqui.
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 buildContext(c, ids, transport, thread) {
35
- const tenant = c.manifesto.memory.tenant;
36
- const pedido = [...new Set(ids)].sort(comparar);
37
- if (!pedido.length)
38
- throw Error('brain.context.ids-required');
39
- if (pedido.some(id => !ID.test(id)))
40
- throw Error('brain.context.id-invalid');
41
- if (pedido.length > LIMITE)
42
- throw Error('brain.context.too-many');
43
- 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]));
44
- const base = { schema: exports.CONTEXT_SCHEMA, tenant, contrato: company_brain_contract_1.CONTRACT_HASH, thread, pedido };
45
- const encerrar = (r) => ({ ...base, state: r.state, ...(r.error ? { error: r.error } : {}), itens: [], lacunas: [], digest: null, consultadoEm: new Date().toISOString() });
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 encerrar(r);
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 encerrar({ state: 'unavailable', error: 'brain.context.get-limit' });
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 encerrar(g);
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
- const entidade = b ?? f, citacao = citacaoDe(entidade.source);
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
- const fd = fs.openSync(file, 'a', 0o600);
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
- const r = (0, node_child_process_1.spawnSync)(config.cli, ['brain', 'migration'], { cwd: c.raiz, shell: false, encoding: 'utf8', timeout: Math.min(config.timeout_ms, 15000), maxBuffer: 2 * 1024 * 1024,
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 {