@orkastery/cli 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/adapters/README.md +11 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +3 -1
  3. package/adapters/claude-code/agents/ork-check.md +1 -1
  4. package/adapters/claude-code/agents/ork-go.md +2 -2
  5. package/adapters/claude-code/agents/ork-goal.md +1 -1
  6. package/adapters/claude-code/agents/ork-master.md +1 -1
  7. package/adapters/claude-code/agents/ork-plan.md +1 -1
  8. package/adapters/claude-code/agents/ork-ship.md +1 -1
  9. package/adapters/claude-code/commands/master.md +11 -8
  10. package/adapters/claude-code/commands/ork.md +8 -0
  11. package/adapters/claude-code/commands/ship.md +2 -2
  12. package/adapters/codex/skills/ork/SKILL.md +12 -1
  13. package/adapters/hermes/README.md +3 -0
  14. package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
  15. package/adapters/hermes/bin/ork-brain.sh +3 -0
  16. package/adapters/hermes/bin/ork-maestro.sh +4 -1
  17. package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
  18. package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
  19. package/adapters/hermes/hermes.plugin.json +2 -0
  20. package/adapters/hermes/hitl-ingress/__init__.py +36 -3
  21. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
  22. package/adapters/openclaw/README.md +34 -3
  23. package/adapters/openclaw/dist/hitl-ingress.js +37 -3
  24. package/adapters/openclaw/dist/index.js +92 -39
  25. package/adapters/openclaw/openclaw.plugin.json +10 -3
  26. package/adapters/openclaw/package.json +2 -2
  27. package/adapters/openclaw/src/hitl-ingress.ts +32 -3
  28. package/adapters/openclaw/src/index.ts +108 -41
  29. package/assets/docs/padroes/documentacao-de-produto.md +2 -2
  30. package/assets/docs/padroes/roadmap-de-produto.md +1 -1
  31. package/assets/docs/produto/_modelo-feature.md +2 -0
  32. package/assets/orkmind_bridge.py +214 -1
  33. package/dist/adapters/claude-bg.js +88 -9
  34. package/dist/adapters/codex-events.js +3 -1
  35. package/dist/board.js +74 -0
  36. package/dist/branch-de-estado.js +5 -4
  37. package/dist/busca-semantica.js +161 -0
  38. package/dist/ci.js +141 -10
  39. package/dist/company-brain-cli.js +27 -2
  40. package/dist/company-brain-context.js +132 -0
  41. package/dist/company-brain-dossie.js +376 -0
  42. package/dist/company-brain-mcp.js +4 -1
  43. package/dist/conducao.js +117 -31
  44. package/dist/decisao-autonoma.js +42 -0
  45. package/dist/docs.js +64 -22
  46. package/dist/doctor.js +33 -0
  47. package/dist/entrega-pr.js +109 -5
  48. package/dist/experiencia-instalacao.js +256 -0
  49. package/dist/experiencia.js +72 -0
  50. package/dist/fabrica-estado.js +43 -10
  51. package/dist/fechamento.js +105 -0
  52. package/dist/fix.js +1 -1
  53. package/dist/forja.js +435 -0
  54. package/dist/gates.js +10 -1
  55. package/dist/hitl-classificacao.js +11 -1
  56. package/dist/hitl-contract.js +50 -7
  57. package/dist/hitl-curto.js +158 -0
  58. package/dist/hitl-gates.js +67 -1
  59. package/dist/hitl-lote.js +30 -15
  60. package/dist/hitl-presentation.js +10 -7
  61. package/dist/hitl-resumo.js +33 -12
  62. package/dist/hitl-texto-livre.js +150 -0
  63. package/dist/hosts.js +86 -1
  64. package/dist/index.js +605 -41
  65. package/dist/indice-vetorial.js +317 -0
  66. package/dist/init.js +13 -0
  67. package/dist/integracoes-locais.js +1 -1
  68. package/dist/intelligence-benchmark-contract.js +570 -0
  69. package/dist/intelligence-graph-cli.js +430 -0
  70. package/dist/intelligence-graph-contract.js +577 -0
  71. package/dist/intelligence-graph-extract-md.js +469 -0
  72. package/dist/intelligence-graph-extract-ts.js +810 -0
  73. package/dist/intelligence-graph-extract.js +369 -0
  74. package/dist/intelligence-graph-index.js +512 -0
  75. package/dist/intelligence-graph-parsers.js +327 -0
  76. package/dist/intelligence-graph-query.js +344 -0
  77. package/dist/intelligence-graph-repo.js +187 -0
  78. package/dist/leases.js +84 -0
  79. package/dist/ledger.js +14 -0
  80. package/dist/maestro-cli.js +10 -1
  81. package/dist/maestro-contract.js +5 -1
  82. package/dist/maestro-discovery.js +16 -2
  83. package/dist/maestro-snapshot.js +6 -2
  84. package/dist/manifest.js +142 -5
  85. package/dist/master-batch.js +3 -2
  86. package/dist/master-digest.js +2 -2
  87. package/dist/master-nota.js +203 -0
  88. package/dist/master.js +4 -0
  89. package/dist/mcp-experiencia.js +164 -0
  90. package/dist/mcp-git.js +36 -10
  91. package/dist/mcp-install.js +3 -1
  92. package/dist/mcp-maestro.js +3 -2
  93. package/dist/mcp-server.js +84 -5
  94. package/dist/memoria.js +147 -1
  95. package/dist/network-roadmap.js +907 -0
  96. package/dist/ocupacao.js +38 -2
  97. package/dist/onboarding.js +113 -7
  98. package/dist/orkmind.js +165 -9
  99. package/dist/phase.js +166 -13
  100. package/dist/policies.js +2 -0
  101. package/dist/projeto-alvo.js +551 -0
  102. package/dist/prompts.js +1 -1
  103. package/dist/pulse-consentimento.js +4 -2
  104. package/dist/pulse-delivery.js +5 -0
  105. package/dist/pulse-resposta.js +674 -49
  106. package/dist/pulse.js +21 -0
  107. package/dist/ratelimit.js +3 -2
  108. package/dist/retry.js +230 -9
  109. package/dist/roadmap-reservas.js +262 -20
  110. package/dist/roadmap-status.js +213 -0
  111. package/dist/runtime-ambiente.js +12 -1
  112. package/dist/session-watcher-claude.js +26 -0
  113. package/dist/sessoes.js +49 -15
  114. package/dist/thread-close.js +3 -0
  115. package/dist/verify.js +5 -4
  116. package/dist/worktree.js +77 -0
  117. package/eval/casos/orchestration-experience-pt-br.json +48 -0
  118. package/eval/casos/orchestration-experience.json +48 -0
  119. package/package.json +1 -1
  120. package/schemas/code-artifact-graph.v1.schema.json +581 -0
  121. package/schemas/graph-benchmark.v1.schema.json +2240 -0
  122. package/schemas/maestro-snapshot.schema.json +23 -0
  123. package/skills/README.md +7 -5
  124. package/skills/core/onboarding/SKILL.md +7 -0
  125. package/skills/core/orchestration-experience/SKILL.md +113 -0
  126. package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
  127. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  128. package/skills/phases/go-implementation/SKILL.md +2 -0
@@ -56,6 +56,8 @@ const leases_1 = require("./leases");
56
56
  const hitl_gates_1 = require("./hitl-gates");
57
57
  const hitl_contract_1 = require("./hitl-contract");
58
58
  const hitl_presentation_1 = require("./hitl-presentation");
59
+ const roadmap_status_1 = require("./roadmap-status");
60
+ const network_roadmap_1 = require("./network-roadmap");
59
61
  const hitl_sessions_1 = require("./hitl-sessions");
60
62
  const hitl_local_1 = require("./hitl-local");
61
63
  const mcp_artifacts_1 = require("./mcp-artifacts");
@@ -65,6 +67,7 @@ const modos_1 = require("./modos");
65
67
  const versao_1 = require("./versao");
66
68
  const mcp_verify_1 = require("./mcp-verify");
67
69
  const conducao_1 = require("./conducao");
70
+ const decisao_autonoma_1 = require("./decisao-autonoma");
68
71
  const conducao_texto_1 = require("./conducao-texto");
69
72
  const mcp_ship_1 = require("./mcp-ship");
70
73
  const company_brain_mcp_1 = require("./company-brain-mcp");
@@ -72,6 +75,8 @@ const claude_bg_1 = require("./adapters/claude-bg");
72
75
  const session_watcher_claude_1 = require("./session-watcher-claude");
73
76
  const runtime_profiles_1 = require("./runtime-profiles");
74
77
  const mcp_maestro_1 = require("./mcp-maestro");
78
+ const projeto_alvo_1 = require("./projeto-alvo");
79
+ const mcp_experiencia_1 = require("./mcp-experiencia");
75
80
  const identidade = zod_1.z.string().min(1).max(80).regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/);
76
81
  const daThread = zod_1.z.object({ threadId: identidade }).strict();
77
82
  const daDecisao = daThread.extend({ pedidoId: identidade }).strict();
@@ -297,15 +302,33 @@ function criarServidorMcp(opcoes) {
297
302
  throw Error('lease.busy: ' + conflitos.map(l => l.nome + ' (' + l.thread + ')').join(', '));
298
303
  }
299
304
  };
300
- const server = new index_js_1.Server({ name: 'orkastery', version: versao_1.VERSAO_DO_ORK }, { capabilities: { tools: {} }, instructions: 'Opere somente este projeto pelas ferramentas do nucleo. Decisoes humanas usam ork_request_decision e o dialogo do host; argumentos de ferramenta nunca sao respostas.' });
305
+ const server = new index_js_1.Server({ name: 'orkastery', version: versao_1.VERSAO_DO_ORK }, { capabilities: { tools: {} }, instructions: 'Opere somente este projeto pelas ferramentas do nucleo. O parametro opcional projeto so confere o projeto servido; nunca troca a raiz. O status do roadmap vem de ork_network_roadmap, transportado como vem. Decisoes humanas usam ork_request_decision e o dialogo do host; argumentos de ferramenta nunca sao respostas.' });
306
+ /**
307
+ * RM-052 (D5): toda tool aceita `projeto`, e ele so CONFERE o projeto fixado no startup. Pedido de
308
+ * outro projeto recusa tipado, com o projeto servido como unico candidato; a raiz nunca muda aqui.
309
+ */
310
+ const conferirProjeto = (pedido) => {
311
+ const c = carregar(), nome = c.manifesto.project.name, abbrev = c.manifesto.project.abbrev, v = pedido.toLowerCase();
312
+ if (nome.toLowerCase() === v || (!!abbrev && abbrev.toLowerCase() === v))
313
+ return;
314
+ throw new projeto_alvo_1.ErroDeProjeto('projeto.fora-do-servidor', `este servidor MCP atende somente o projeto ${nome}; "${pedido}" nao e ele`, [{ nome, abbrev, raiz: (0, projeto_alvo_1.raizParaExibir)(raiz), remoto: (0, projeto_alvo_1.remotoDoProjeto)(raiz, c.manifesto.fabrica?.remoto ?? 'origin'), presente: true }], 'Use o servidor MCP instalado no outro projeto (ork mcp install --project <raiz>), ou o CLI com --projeto <nome>.');
315
+ };
316
+ const campoProjeto = zod_1.z.string().regex(projeto_alvo_1.PADRAO_DO_NOME_DE_PROJETO)
317
+ .describe('Nome ou abbrev do projeto pedido; este servidor atende somente o projeto fixado na instalacao');
301
318
  const ferramentas = new Map();
302
319
  function registrarTool(nome, config, executar) {
303
320
  if (opcoes.threadId && ['ork_thread_new', 'ork_phase_run', 'ork_request_decision', 'ork_preflight'].includes(nome))
304
321
  return;
305
- const schema = converterSchema(config.inputSchema, { $refStrategy: 'none' });
322
+ const entrada = config.inputSchema.extend({ projeto: campoProjeto.optional() });
323
+ const schema = converterSchema(entrada, { $refStrategy: 'none' });
306
324
  ferramentas.set(nome, { tool: { name: nome, description: config.description, annotations: config.annotations,
307
325
  inputSchema: schema },
308
- executar: async (raw, extra) => executar(config.inputSchema.parse(raw), extra) });
326
+ executar: async (raw, extra) => {
327
+ const { projeto, ...args } = entrada.parse(raw);
328
+ if (projeto !== undefined)
329
+ conferirProjeto(projeto);
330
+ return executar(args, extra);
331
+ } });
309
332
  }
310
333
  server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: [...ferramentas.values()].map(f => f.tool) }));
311
334
  server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request, extra) => {
@@ -316,6 +339,8 @@ function criarServidorMcp(opcoes) {
316
339
  return await f.executar(request.params.arguments ?? {}, extra);
317
340
  }
318
341
  catch (e) {
342
+ if (e instanceof projeto_alvo_1.ErroDeProjeto)
343
+ return { ...resposta(e.recusa), isError: true };
319
344
  return { ...resposta({ erro: e.message }), isError: true };
320
345
  }
321
346
  });
@@ -344,6 +369,7 @@ function criarServidorMcp(opcoes) {
344
369
  });
345
370
  server.onclose = () => ingresso.fechar();
346
371
  (0, company_brain_mcp_1.registerBrainTools)(registrarTool, carregar, thread, opcoes.brainWrites ?? []);
372
+ (0, mcp_experiencia_1.registrarConsultasExperiencia)(registrarTool, { raiz, carregar, transporte: opcoes.transporteShip ?? 'github-ssh' });
347
373
  (0, mcp_maestro_1.registerMaestro)(registrarTool, { root: raiz, threadId: opcoes.threadId, load: carregar, checkThread: thread, tools: () => [...ferramentas.keys()] });
348
374
  registrarTool('ork_preflight', { description: 'Preflight contextual por modo e bloco, sem inventário global/modelos. Não autoriza despacho nem comprova entrega.',
349
375
  inputSchema: zod_1.z.object({ modo: modoDeConducao }).strict(), annotations: { readOnlyHint: true } }, async ({ modo }) => {
@@ -402,6 +428,35 @@ function criarServidorMcp(opcoes) {
402
428
  livre(threadId);
403
429
  return resposta((0, mcp_artifacts_1.escreverArtefatoMcp)(raiz, threadId, tipo, conteudo, expectedSha256));
404
430
  });
431
+ // RM-037 (rm037defeito, defeito 1): a decisao que a sessao toma sem perguntar ao dono. O sandbox do
432
+ // codex nao grava o ledger e o `ork decisao registrar` morria em EROFS. Mesma `registrarDecisao` do CLI:
433
+ // contrato v2, criterio que resolve e rastro no mesmo evento. Nao pergunta ao dono e nao toca gate.
434
+ const campoDaDecisao = zod_1.z.string().min(1).max(4096);
435
+ registrarTool('ork_decision_record', { description: 'Registra decisao ja tomada pela sessao sem perguntar ao dono (classe decidido), com criterio que resolve e rastro. Nao pergunta, nao responde nem aprova gate.',
436
+ inputSchema: daThread.extend({ decidido: campoDaDecisao, porque: campoDaDecisao, comoMudar: campoDaDecisao,
437
+ custoAgora: campoDaDecisao, custoDepois: campoDaDecisao,
438
+ criterio: zod_1.z.object({ tipo: zod_1.z.enum(['manifesto', 'ledger', 'medicao']), referencia: campoDaDecisao }).strict(),
439
+ quemDecidiu: zod_1.z.string().min(1).max(200), evidencia: campoDaDecisao, razao: campoDaDecisao.optional(),
440
+ reverte: zod_1.z.string().min(1).max(80).optional() }).strict(),
441
+ annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, ...e }) => {
442
+ thread(threadId);
443
+ livre(threadId);
444
+ // A sessao decide por ela: o rastro nao pode nascer assinado em nome do dono.
445
+ if (/^\s*(?:o\s+|a\s+)?(?:dono|owner|builder|maestro)\b/i.test(e.quemDecidiu))
446
+ throw Error('mcp.decision.author: quemDecidiu e a sessao que decidiu, nunca o dono');
447
+ let registro;
448
+ try {
449
+ registro = (0, decisao_autonoma_1.registrarDecisao)(raiz, threadId, { decidido: e.decidido, porque: e.porque, comoMudar: e.comoMudar,
450
+ custoDeReverter: { agora: e.custoAgora, depois: e.custoDepois }, criterio: e.criterio, quemDecidiu: e.quemDecidiu,
451
+ evidencia: e.evidencia, ...(e.razao ? { razao: e.razao } : {}), ...(e.reverte ? { reverte: e.reverte } : {}), origem: 'mcp', host: opcoes.host,
452
+ despacho: opcoes.dispatchId ?? null });
453
+ }
454
+ catch (erro) {
455
+ throw Error((0, hitl_contract_1.recusaNaSuperficie)(erro.message, hitl_contract_1.CAMPOS_DA_DECISAO_NO_MCP));
456
+ }
457
+ const { pedido, evento } = registro;
458
+ return resposta({ ok: true, pedidoId: pedido.id, eventId: evento.eventId, fase: pedido.fase, reciboOficial: false });
459
+ });
405
460
  registrarTool('ork_claims_list', { description: 'Lista alegacoes e seu estado de verificacao registrado pelo nucleo.',
406
461
  inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
407
462
  thread(threadId);
@@ -423,6 +478,25 @@ function criarServidorMcp(opcoes) {
423
478
  });
424
479
  registrarTool('ork_hitl_pending', { description: 'Pedidos HITL atuais da thread, incluindo prazo; nao aprova nem abre pedido.',
425
480
  inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => resposta({ threadId, pendencias: pendencias(threadId) }));
481
+ registrarTool('ork_roadmap_status', { description: 'Status report do roadmap SO desta maquina (o checkout local), no formato aprovado pelo dono: grupos com icones, #HITL no que espera o dono e o fecho. Somente leitura; transporte o texto como vem. O cabecalho diz o projeto consultado e o que nao foi lido (reservas, outras maquinas). Para o status do roadmap com as threads de todas as maquinas, as reservas, as fontes e as lacunas, use ork_network_roadmap; nunca conclua sobre ele a partir de ork_maestro ou de threads.',
482
+ inputSchema: zod_1.z.object({}).strict(), annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false } }, async () => {
483
+ const c = carregar();
484
+ // RM-052: origem `instalacao`; o servidor fixado nao revela os outros projetos da maquina.
485
+ const consulta = (0, projeto_alvo_1.consultaDoProjeto)(c, { origem: 'instalacao', outrosProjetos: false,
486
+ lido: ['roadmap (docs/roadmap)', projeto_alvo_1.FORA_DA_CONSULTA.threadsDaMaquina], naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.reservas, 'threads de outras máquinas (ork network roadmap)'] });
487
+ const status = (0, roadmap_status_1.montarStatusDoRoadmap)(raiz, { projeto: c.manifesto.project.name, consulta });
488
+ return resposta({ texto: (0, roadmap_status_1.textoDoStatusDoRoadmap)(status), status });
489
+ });
490
+ /**
491
+ * RM-054 (fatia 2, D-G5): o roadmap da rede do projeto servido, em todas as maquinas dele. O servidor
492
+ * fixado nao le o registro nem revela os outros projetos (D5 da RM-052); o texto e o do CLI.
493
+ */
494
+ registrarTool('ork_network_roadmap', { description: 'Roadmap da rede do projeto servido, somente leitura: o status report do roadmap (RM-048) com as threads de TODAS as maquinas, as reservas, as threads por maquina com a idade da batida, a fonte e a hora de cada parte e as lacunas tipadas. E a fonte do status do roadmap: transporte o texto como vem, sem reescrever nem resumir. Lacuna e "Nao consultado" sao o que nao foi lido: nunca conclua "roadmap vazio" nem "nenhuma maquina publicou" a partir deles. Este servidor le so o projeto fixado; os outros projetos vem do CLI ork network roadmap.',
495
+ inputSchema: zod_1.z.object({}).strict(), annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true } }, async () => {
496
+ carregar();
497
+ const panorama = (0, network_roadmap_1.montarPanoramaDaRede)({ fixado: raiz });
498
+ return resposta({ texto: (0, network_roadmap_1.textoDoPanoramaDaRede)(panorama), panorama });
499
+ });
426
500
  registrarTool('ork_observe', { description: 'Observa uma vez o progresso canonico e pedidos da thread. Nao cria monitor ou despacho.',
427
501
  inputSchema: daThread, annotations: { readOnlyHint: true } }, async ({ threadId }) => {
428
502
  return resposta(observar(threadId));
@@ -439,14 +513,19 @@ function criarServidorMcp(opcoes) {
439
513
  while (!fs.existsSync(existente))
440
514
  existente = path.dirname(existente);
441
515
  confinado(existente);
442
- return resposta((0, thread_1.novaThread)(c, { nome, modo: modo ?? c.manifesto.conduction.default_mode, criarWorktree: true }));
516
+ const criada = (0, thread_1.novaThread)(c, { nome, modo: modo ?? c.manifesto.conduction.default_mode, criarWorktree: true });
517
+ // RM-052 (D7): thread nova, projeto conhecido pelo nome nesta maquina; o registro nunca derruba a criacao.
518
+ if (criada.gravada)
519
+ (0, projeto_alvo_1.registrarProjetoEmSilencio)(raiz, 'mcp thread new');
520
+ return resposta(criada);
443
521
  });
444
522
  registrarTool('ork_phase_run', { description: 'Despacha fase autorizada pelo nucleo, preservando policies, estado e runtime/modelo. dryRun nao inicia modelo, mas pode registrar prompt/eventos.',
445
523
  inputSchema: fase, annotations: { readOnlyHint: false, destructiveHint: false } }, async (args) => {
446
524
  const t = thread(args.threadId);
447
525
  livre(t.id);
448
526
  const { threadId, fase: f, ...op } = args;
449
- return resposta((0, phase_1.rodarFase)(carregar(), threadId, { ...op, fase: (0, thread_1.exigirFase)(t, f), canal: conducao.canal }));
527
+ // RM-037 (A3): o MCP nao roda a suite para a baseline do despacho; a falta dela volta como pendencia.
528
+ return resposta((0, phase_1.rodarFase)(carregar(), threadId, { ...op, fase: (0, thread_1.exigirFase)(t, f), canal: conducao.canal, baselinePeloDespacho: false }));
450
529
  });
451
530
  registrarTool('ork_gate_request', { description: 'Abre pedido de gate somente quando pausa ou escalacao tipada esta comprovada no nucleo; nao aprova.',
452
531
  inputSchema: daThread.extend({ motivo: zod_1.z.enum(['human.pending', 'policy.violation', 'cost.violation',
package/dist/memoria.js CHANGED
@@ -35,6 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.sincronizarOnboarding = sincronizarOnboarding;
37
37
  exports.abrirMemoria = abrirMemoria;
38
+ exports.estadoDeEmbeddings = estadoDeEmbeddings;
39
+ exports.sondarEmbeddings = sondarEmbeddings;
38
40
  exports.tagsDoProjeto = tagsDoProjeto;
39
41
  exports.situacaoDaThread = situacaoDaThread;
40
42
  exports.situacaoDaFase = situacaoDaFase;
@@ -64,6 +66,7 @@ exports.sincronizarMemoria = sincronizarMemoria;
64
66
  exports.publicar = publicar;
65
67
  exports.publicarPropostas = publicarPropostas;
66
68
  exports.textoDoEstado = textoDoEstado;
69
+ exports.textoDosEmbeddings = textoDosEmbeddings;
67
70
  exports.textoDoSync = textoDoSync;
68
71
  exports.parsePrioridade = parsePrioridade;
69
72
  const write_activation_1 = require("./write-activation");
@@ -97,6 +100,7 @@ const memoria_humana_1 = require("./memoria-humana");
97
100
  const master_1 = require("./master");
98
101
  const modos_1 = require("./modos");
99
102
  const orkmind_1 = require("./orkmind");
103
+ const indice_vetorial_1 = require("./indice-vetorial");
100
104
  const ledger_1 = require("./ledger");
101
105
  const thread_1 = require("./thread");
102
106
  const util_1 = require("./util");
@@ -167,6 +171,10 @@ function abrirMemoria(carregado, opcoes = {}) {
167
171
  const leituraRestrita = resolverLeituraRestrita(carregado.manifesto, opcoes.leituraRestrita);
168
172
  const { estado, driver } = (0, orkmind_1.resolverRegime)(carregado.manifesto, opcoes.driver ?? null);
169
173
  const ativo = estado.efetivo === 'orkmind' && driver !== null;
174
+ const config = (0, orkmind_1.configDoManifesto)(carregado.manifesto);
175
+ const embeddings = (universo) => estadoDeEmbeddings(carregado.manifesto, ativo ? driver?.disponivel().saude ?? null : null, carregado.raiz, estado.tenant, config.dsn, { universo });
176
+ if (estado.pedido === 'orkmind')
177
+ estado.embeddings = embeddings();
170
178
  const consultarRestrito = (collection, tags) => {
171
179
  if (!leituraRestrita)
172
180
  throw Error('memory.query.invalid');
@@ -178,7 +186,7 @@ function abrirMemoria(carregado, opcoes = {}) {
178
186
  throw Error('memory.query.unsupported');
179
187
  return (0, orkmind_1.concluirConsultaDelimitada)(driver.consultar(q), q);
180
188
  };
181
- return {
189
+ const memoria = {
182
190
  configSource: context.source,
183
191
  configDivergent: context.divergent,
184
192
  get leituraRestrita() { return leituraRestrita; },
@@ -243,6 +251,114 @@ function abrirMemoria(carregado, opcoes = {}) {
243
251
  return driver.exportar(colecao).find((e) => e.id === id) ?? null;
244
252
  },
245
253
  };
254
+ // A cobertura precisa do universo do tenant (um export por colecao): so quando pedida.
255
+ if (opcoes.embeddings === 'detalhado' && ativo && !leituraRestrita) {
256
+ estado.embeddings = embeddings((0, indice_vetorial_1.universoDoTenant)(memoria, estado.tenant));
257
+ }
258
+ return memoria;
259
+ }
260
+ // ---------------------------------------------------------------------------
261
+ // I-38 (T4, D6): estado sondado dos embeddings. Nunca derruba o regime.
262
+ // ---------------------------------------------------------------------------
263
+ /** Os indices locais do tenant nesta base, por modelo e dimensao. */
264
+ function indicesDoTenant(raiz, tenant, base, universo) {
265
+ const dir = (0, indice_vetorial_1.dirDosIndices)(raiz, tenant);
266
+ if (!fs.existsSync(dir))
267
+ return [];
268
+ const indices = [];
269
+ for (const nome of fs.readdirSync(dir).filter(n => n.endsWith('.json')).sort()) {
270
+ try {
271
+ const bruto = JSON.parse(fs.readFileSync(path.join(dir, nome), 'utf8'));
272
+ if (bruto.contrato !== indice_vetorial_1.CONTRATO_INDICE || bruto.tenant !== tenant || bruto.base !== base)
273
+ continue;
274
+ const { indice } = (0, indice_vetorial_1.lerIndice)(path.join(dir, nome), { tenant, base, modelo: bruto.modelo, dim: bruto.dim });
275
+ const vetores = Object.keys(indice.entradas).length;
276
+ const coerentes = (0, indice_vetorial_1.vetoresCoerentes)(indice, universo).size;
277
+ indices.push({ modelo: indice.modelo, dim: indice.dim, vetores, coerentes, desatualizados: vetores - coerentes });
278
+ }
279
+ catch { /* arquivo ilegivel nao e indice: `ork memory index` o reconstroi */ }
280
+ }
281
+ return indices;
282
+ }
283
+ /**
284
+ * Estado de embeddings: configuracao, presenca da chave (nome, nunca valor), a sonda `health`
285
+ * da ponte e os arquivos de indice. `saude` null quer dizer que a ponte nao foi sondada.
286
+ */
287
+ function estadoDeEmbeddings(manifesto, saude, raiz, tenant, dsn, opcoes = {}) {
288
+ const config = (0, manifest_1.configDeEmbedding)(manifesto);
289
+ const env = opcoes.env ?? process.env;
290
+ const configurado = config.provider !== 'none';
291
+ const variavel = config.api_key_env;
292
+ const bruto = variavel ? (env[variavel] ?? '').trim() : '';
293
+ const chavePresente = !!variavel && (0, orkmind_1.chaveDeEmbeddingAceita)(bruto, dsn);
294
+ const recusada = bruto !== '' && !chavePresente;
295
+ const dimLocal = configurado && config.fallback_model ? (0, indice_vetorial_1.dimDoModeloLocal)(config.fallback_model, env) : null;
296
+ const dependencias = saude?.fallback.dependencias ?? false;
297
+ const fallback = { modelo: config.fallback_model || null, presente: dimLocal !== null, dependencias, dim: dimLocal };
298
+ const base = (0, indice_vetorial_1.impressaoDaBase)(dsn);
299
+ const existe = (modelo, dim) => dim !== null && fs.existsSync((0, indice_vetorial_1.arquivoDoIndice)(raiz, tenant, modelo, dim));
300
+ const estado = {
301
+ configurado, provider: config.provider, modelo: configurado ? config.model : null, dim: configurado ? config.dim : null,
302
+ variavelDaChave: variavel, chavePresente, fallback, indices: [], entradas: null, cobertura: null,
303
+ ativo: 'nenhum', sondado: saude !== null, motivo: null, detalhe: '', correcao: '',
304
+ };
305
+ if (!configurado) {
306
+ return { ...estado, motivo: 'embeddings.nao-configurado',
307
+ detalhe: 'memory.embedding ausente ou provider none: busca por significado desligada; o recall por tag segue identico',
308
+ correcao: 'declare memory.embedding no manifesto (provider openrouter e api_key_env com o NOME da variavel da chave)' };
309
+ }
310
+ const fallbackUsavel = saude !== null && fallback.presente && dependencias;
311
+ if (chavePresente) {
312
+ estado.ativo = 'primario';
313
+ if (!existe(config.model, config.dim)) {
314
+ estado.motivo = 'embeddings.indice-ausente';
315
+ estado.detalhe = `chave presente em ${variavel}; o indice local de ${config.model} ainda nao existe`;
316
+ estado.correcao = 'rode ork memory index (use --dry-run antes para ver tokens e custo)';
317
+ }
318
+ else
319
+ estado.detalhe = `primario ${config.model} (${config.dim} dim) pela chave em ${variavel}`;
320
+ }
321
+ else {
322
+ estado.ativo = fallbackUsavel ? 'fallback' : 'nenhum';
323
+ estado.motivo = 'embeddings.chave-ausente';
324
+ const local = !fallback.modelo ? 'sem fallback local declarado: a busca por significado cai para FTS'
325
+ : !fallback.presente ? `fallback ${fallback.modelo} ausente do cache local: a busca cai para FTS`
326
+ : !saude ? 'ponte nao sondada: fallback local nao conferido'
327
+ : !dependencias ? `fallback ${fallback.modelo} sem torch/transformers no interpretador da ponte: a busca cai para FTS`
328
+ : `busca usa o fallback local ${fallback.modelo} (${fallback.dim} dim)` +
329
+ (existe(fallback.modelo, fallback.dim) ? '' : '; indice local ausente: rode ork memory index --modelo fallback');
330
+ estado.detalhe = `${variavel} ${recusada ? 'tem valor recusado (parece URL, DSN ou texto com espaco; nunca impresso)' : 'nao esta no ambiente (valor nunca impresso)'}; ${local}`;
331
+ estado.correcao = `exporte ${variavel} com a chave dedicada ao Orkastery; o valor nunca vai ao manifesto`;
332
+ }
333
+ if (opcoes.universo) {
334
+ const universo = opcoes.universo.filter(e => (e.tags.project ?? []).includes(tenant));
335
+ estado.indices = indicesDoTenant(raiz, tenant, base, universo);
336
+ estado.entradas = universo.length;
337
+ const referencia = estado.ativo === 'fallback' ? { modelo: fallback.modelo, dim: fallback.dim } : { modelo: config.model, dim: config.dim };
338
+ const indice = estado.indices.find(i => i.modelo === referencia.modelo && i.dim === referencia.dim);
339
+ estado.cobertura = universo.length === 0 ? 0 : Math.round(((indice?.coerentes ?? 0) / universo.length) * 10_000) / 10_000;
340
+ }
341
+ return estado;
342
+ }
343
+ /**
344
+ * `ork memory status --sondar`: UMA chamada real com texto fixo curto pelo caminho ativo, com
345
+ * a latencia medida (primario custa cerca de US$ 0,00000005; fallback local, so CPU).
346
+ */
347
+ function sondarEmbeddings(manifesto, estado, embeddar, timeoutMs) {
348
+ if (estado.ativo === 'nenhum')
349
+ return { ok: false, alvo: null, latenciaMs: null, motivo: estado.motivo };
350
+ const config = (0, manifest_1.configDeEmbedding)(manifesto);
351
+ const primario = estado.ativo === 'primario';
352
+ const modelo = primario ? config.model : estado.fallback.modelo;
353
+ const dim = primario ? config.dim : estado.fallback.dim;
354
+ const inicio = Date.now();
355
+ try {
356
+ embeddar({ papel: 'consulta', alvo: estado.ativo, modelo, dim, textos: ['sonda de saude do ork'] }, { timeoutMs });
357
+ return { ok: true, alvo: estado.ativo, latenciaMs: Date.now() - inicio, motivo: null };
358
+ }
359
+ catch (erro) {
360
+ return { ok: false, alvo: estado.ativo, latenciaMs: Date.now() - inicio, motivo: (0, indice_vetorial_1.codigoDeEmbedding)(erro) };
361
+ }
246
362
  }
247
363
  // ---------------------------------------------------------------------------
248
364
  // Tags: as 5 dimensoes, montadas em um lugar so.
@@ -968,8 +1084,38 @@ function textoDoEstado(estado) {
968
1084
  linhas.push(` colecoes gravadas: ${orkmind_1.COLECOES_DO_ORK.join(', ')}`);
969
1085
  linhas.push(' governanca: source=agent; decision/human exige human_gate comprovado; mandatory=false e regra nunca critical.');
970
1086
  }
1087
+ if (estado.embeddings)
1088
+ linhas.push('', ...textoDosEmbeddings(estado.embeddings));
971
1089
  return linhas.join('\n');
972
1090
  }
1091
+ /** Secao de embeddings do `ork memory status` (I-38 D6): nome da variavel, nunca o valor. */
1092
+ function textoDosEmbeddings(e) {
1093
+ const linhas = ['Busca por significado (embeddings, nao deterministica; o recall por tag nao muda)', ''];
1094
+ linhas.push(` provider ${e.configurado ? `${e.provider} ${e.modelo} (${e.dim} dim)` : 'none (desligada)'}`);
1095
+ if (e.configurado) {
1096
+ linhas.push(` chave ${e.variavelDaChave} ${e.chavePresente ? 'presente' : 'ausente'} no ambiente (valor nunca impresso)`);
1097
+ linhas.push(` fallback local ${e.fallback.modelo ? `${e.fallback.modelo}: ${e.fallback.presente ? `no cache (${e.fallback.dim} dim)` : 'ausente do cache'}, ` +
1098
+ `dependencias ${e.fallback.dependencias ? 'ok' : e.sondado ? 'ausentes' : 'nao sondadas'}` : '(nao declarado)'}`);
1099
+ linhas.push(` caminho ativo ${e.ativo}${e.sondado ? '' : ' (ponte nao sondada)'}`);
1100
+ }
1101
+ for (const i of e.indices) {
1102
+ linhas.push(` indice ${i.modelo} / ${i.dim} dim: ${i.vetores} vetor(es), ${i.coerentes ?? '?'} coerente(s), ${i.desatualizados ?? '?'} desatualizado(s)`);
1103
+ }
1104
+ if (e.entradas !== null) {
1105
+ linhas.push(` cobertura ${e.cobertura === null ? '-' : `${Math.round(e.cobertura * 1000) / 10}%`} de ${e.entradas} entrada(s) do tenant`);
1106
+ }
1107
+ if (e.sonda) {
1108
+ linhas.push(` sonda ${e.sonda.ok ? `${e.sonda.alvo} respondeu em ${e.sonda.latenciaMs} ms` : `sem resposta (${e.sonda.motivo ?? 'sem caminho ativo'})`}`);
1109
+ }
1110
+ if (e.motivo) {
1111
+ linhas.push(` motivo ${e.motivo}`);
1112
+ linhas.push(` ${e.detalhe}`);
1113
+ linhas.push(` correcao: ${e.correcao}`);
1114
+ }
1115
+ else
1116
+ linhas.push(` ${e.detalhe}`);
1117
+ return linhas;
1118
+ }
973
1119
  /** Texto de `ork memory sync`. */
974
1120
  function textoDoSync(r) {
975
1121
  const linhas = [];