@orkastery/cli 0.6.0 → 0.6.2

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 (118) hide show
  1. package/adapters/claude-code/agents/ork-check.md +1 -1
  2. package/adapters/claude-code/agents/ork-go.md +1 -1
  3. package/adapters/claude-code/agents/ork-goal.md +1 -1
  4. package/adapters/claude-code/agents/ork-master.md +1 -1
  5. package/adapters/claude-code/agents/ork-plan.md +1 -1
  6. package/adapters/claude-code/agents/ork-ship.md +1 -1
  7. package/adapters/claude-code/commands/ork.md +1 -1
  8. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -0
  9. package/adapters/codex/skills/ork/SKILL.md +1 -1
  10. package/adapters/openclaw/openclaw.plugin.json +1 -1
  11. package/adapters/openclaw/package.json +1 -1
  12. package/assets/adapters-en/claude-code/agents/ork-check.md +1 -1
  13. package/assets/adapters-en/claude-code/agents/ork-go.md +1 -1
  14. package/assets/adapters-en/claude-code/agents/ork-goal.md +1 -1
  15. package/assets/adapters-en/claude-code/agents/ork-master.md +1 -1
  16. package/assets/adapters-en/claude-code/agents/ork-plan.md +1 -1
  17. package/assets/adapters-en/claude-code/agents/ork-ship.md +1 -1
  18. package/assets/adapters-en/claude-code/commands/ork.md +1 -1
  19. package/assets/adapters-en/codex/skills/ork/SKILL.md +1 -1
  20. package/assets/orkmind_fixture.py +4 -1
  21. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +1 -1
  22. package/assets/skills-en/phases/check-quality/SKILL.md +1 -1
  23. package/assets/skills-en/phases/go-implementation/SKILL.md +1 -1
  24. package/dist/adapters/claude-bg.js +9 -7
  25. package/dist/adapters/grok-events.js +227 -0
  26. package/dist/adapters/grok-mcp-servidor.js +622 -0
  27. package/dist/adapters/grok-mcp.js +178 -0
  28. package/dist/adapters/grok.js +686 -0
  29. package/dist/agendador-cpu.js +92 -0
  30. package/dist/branch-de-estado.js +7 -2
  31. package/dist/changelog-check.js +217 -0
  32. package/dist/check-agil.js +289 -25
  33. package/dist/check-paralelo.js +73 -18
  34. package/dist/ci.js +3 -2
  35. package/dist/claim-lint.js +29 -0
  36. package/dist/claims.js +4 -0
  37. package/dist/conducao.js +5 -0
  38. package/dist/docs.js +16 -16
  39. package/dist/doctor-forja.js +1 -3
  40. package/dist/doctor.js +1 -1
  41. package/dist/entrega-pr.js +10 -10
  42. package/dist/fabrica-estado.js +20 -11
  43. package/dist/fila-pesada.js +121 -11
  44. package/dist/hitl-classificacao.js +1 -0
  45. package/dist/horario.js +4 -1
  46. package/dist/index.js +63 -35
  47. package/dist/integracoes-locais.js +2 -0
  48. package/dist/intelligence-graph-cli.js +27 -9
  49. package/dist/locale-accounts.js +11 -3
  50. package/dist/locale-ajuda.js +10 -6
  51. package/dist/locale-claims.js +16 -2
  52. package/dist/locale-forja.js +2 -4
  53. package/dist/locale-grafo.js +56 -1
  54. package/dist/locale-maestro.js +38 -0
  55. package/dist/locale-network.js +8 -6
  56. package/dist/locale-onboarding.js +14 -0
  57. package/dist/locale-operacao-restante.js +2 -2
  58. package/dist/locale-preflight.js +80 -0
  59. package/dist/locale-projetos.js +6 -0
  60. package/dist/locale-prompts.js +8 -8
  61. package/dist/locale-pulse.js +4 -0
  62. package/dist/locale-retry.js +56 -2
  63. package/dist/locale-security-scan.js +35 -1
  64. package/dist/locale-ship.js +10 -2
  65. package/dist/locale-verify.js +15 -0
  66. package/dist/locale.js +24 -7
  67. package/dist/maestro-cli.js +12 -17
  68. package/dist/manifest.js +6 -1
  69. package/dist/mcp-install.js +24 -13
  70. package/dist/mcp-server.js +62 -33
  71. package/dist/mcp-verify-async.js +353 -0
  72. package/dist/mcp-verify-worker.js +17 -0
  73. package/dist/mcp-verify.js +10 -1
  74. package/dist/merge-da-entrega.js +85 -0
  75. package/dist/network-roadmap.js +18 -14
  76. package/dist/noctum-aceite.js +154 -14
  77. package/dist/noctum-cli.js +69 -12
  78. package/dist/noctum-entrega.js +55 -7
  79. package/dist/noctum-envelope.js +1 -1
  80. package/dist/noctum-execucao.js +5 -1
  81. package/dist/noctum-fechamento.js +18 -7
  82. package/dist/noctum-fila.js +6 -1
  83. package/dist/noctum-guarda.js +81 -4
  84. package/dist/noctum-maquinas.js +5 -1
  85. package/dist/noctum-modo.js +35 -7
  86. package/dist/noctum-reconciliacao.js +4 -1
  87. package/dist/noctum-rede.js +102 -0
  88. package/dist/noctum-relatorio.js +44 -10
  89. package/dist/noctum-retomada-rede.js +71 -0
  90. package/dist/noctum-vigia.js +49 -9
  91. package/dist/parado-no-condutor.js +14 -15
  92. package/dist/pedido-conducao.js +51 -0
  93. package/dist/phase.js +43 -15
  94. package/dist/postura-local.js +7 -3
  95. package/dist/preflight.js +27 -27
  96. package/dist/prompts.js +4 -2
  97. package/dist/pulse.js +4 -2
  98. package/dist/ratelimit.js +1 -0
  99. package/dist/rede.js +24 -12
  100. package/dist/retry.js +115 -10
  101. package/dist/runtime-context.js +165 -45
  102. package/dist/runtime-escada.js +7 -1
  103. package/dist/runtime-profiles.js +27 -17
  104. package/dist/runtimes.js +42 -5
  105. package/dist/security-scan/agil.js +18 -7
  106. package/dist/security-scan/cli.js +2 -2
  107. package/dist/security-scan/executor.js +8 -0
  108. package/dist/security-scan/report.js +1 -1
  109. package/dist/session-watcher-grok.js +425 -0
  110. package/dist/session-watcher.js +52 -11
  111. package/dist/sessoes-contas.js +33 -5
  112. package/dist/setup.js +11 -11
  113. package/dist/varredura-acoes.js +8 -15
  114. package/dist/verify.js +191 -43
  115. package/package.json +2 -2
  116. package/skills/core/orkastery-bootstrap/SKILL.md +1 -1
  117. package/skills/phases/check-quality/SKILL.md +1 -1
  118. package/skills/phases/go-implementation/SKILL.md +1 -1
@@ -48,6 +48,7 @@ const master_1 = require("./master");
48
48
  const noctum_arco_1 = require("./noctum-arco");
49
49
  const noctum_envelope_1 = require("./noctum-envelope");
50
50
  const noctum_fila_1 = require("./noctum-fila");
51
+ const noctum_rede_1 = require("./noctum-rede");
51
52
  const noctum_medicao_1 = require("./noctum-medicao");
52
53
  const noctum_registro_1 = require("./noctum-registro");
53
54
  const noctum_supervisao_1 = require("./noctum-supervisao");
@@ -115,8 +116,6 @@ function condicaoDeFechamento(estado, fila, medicao, quando, emVoo = 0, parada =
115
116
  * a thread aberta e sem MASTER ratificado. A thread que não se lê não segura o fechamento: a fila já a mostra.
116
117
  */
117
118
  function mastersDevidos(raiz, estado, fila, sup) {
118
- if (estado.conteudo?.contrato !== noctum_envelope_1.CONTRATO_ENVELOPE_V2)
119
- return [];
120
119
  const devidos = [];
121
120
  for (const t of fila.trabalhos) {
122
121
  if (t.estado !== 'entregue' || !t.thread || sup.isolados.has(t.id))
@@ -219,7 +218,10 @@ function gravarRetrato(carregado, arco, estado, encerramento, quando, o) {
219
218
  const { raiz } = carregado;
220
219
  let trabalhosDaFila = null;
221
220
  try {
222
- trabalhosDaFila = trabalhosDoArco((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: o.maquina, lerReservas: o.lerReservas }));
221
+ const rede = estado.conteudo && (0, noctum_envelope_1.envelopeMultimaquina)(estado.conteudo)
222
+ ? o.projecaoDaRede ?? (0, noctum_rede_1.lerRede)(carregado, arco, { quando, maquina: o.maquina, remoto: o.remoto, rede: o.redeDaCoordenacao }) : null;
223
+ const coordenacao = rede ? (0, noctum_rede_1.coordenacaoDaFila)(rede) : null;
224
+ trabalhosDaFila = rede?.lacuna ? null : trabalhosDoArco((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: o.maquina, lerReservas: o.lerReservas, ...(coordenacao ? { coordenacao } : {}) }));
223
225
  }
224
226
  catch (e) {
225
227
  if (!(e instanceof noctum_envelope_1.RecusaDoArco))
@@ -286,6 +288,14 @@ function fecharSeDevido(carregado, arco, opcoes = {}) {
286
288
  let agora = false;
287
289
  if (!estado.encerramento) {
288
290
  const emVooAgora = (0, noctum_sessoes_em_voo_1.sessoesEmVooDoArco)(raiz, estado).length;
291
+ const multimaquina = (0, noctum_envelope_1.envelopeMultimaquina)(estado.conteudo);
292
+ const rede = multimaquina
293
+ ? opcoes.projecaoDaRede ?? (0, noctum_rede_1.lerRede)(carregado, arco, { quando, maquina: opcoes.maquina, remoto: opcoes.remoto, rede: opcoes.redeDaCoordenacao })
294
+ : null;
295
+ // Com rede íntegra, o teto em sessões é global. Sem leitura, o consumo local ainda pode provar sozinho que o teto caiu.
296
+ const estadoDoCusto = rede && !rede.lacuna
297
+ ? { ...estado, consumo: { ...estado.consumo, arco: rede.consumo.arco } }
298
+ : estado;
289
299
  // RM-058, integração (D7): a parada da supervisão; o log dela que não se lê não segura o fechamento pelas outras condições.
290
300
  let sup = null;
291
301
  try {
@@ -297,19 +307,20 @@ function fecharSeDevido(carregado, arco, opcoes = {}) {
297
307
  }
298
308
  const parada = sup?.parada ?? null;
299
309
  // Revogado, hora, a parada e o teto em sessões vêm primeiro e sem a fila nem a medição: nenhuma falha delas segura esse fechamento.
300
- let condicao = condicaoDeFechamento(estado, null, null, quando, emVooAgora, parada);
310
+ let condicao = condicaoDeFechamento(estadoDoCusto, null, null, quando, emVooAgora, parada);
301
311
  let falhaDaMedicao = '';
302
312
  if (!condicao) {
303
313
  let fila = null;
304
314
  try {
305
- fila = (0, noctum_fila_1.montarFila)((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas }));
315
+ const coordenacao = rede ? (0, noctum_rede_1.coordenacaoDaFila)(rede) : null;
316
+ fila = rede?.lacuna ? null : (0, noctum_fila_1.montarFila)((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas, ...(coordenacao ? { coordenacao } : {}) }));
306
317
  }
307
318
  catch (e) {
308
319
  if (!(e instanceof noctum_envelope_1.RecusaDoArco))
309
320
  throw e;
310
321
  }
311
322
  let medicao = null;
312
- if (estado.conteudo.orcamento.arco.unidade !== 'sessoes') {
323
+ if (estado.conteudo.orcamento.arco.unidade !== 'sessoes' && !rede?.lacuna) {
313
324
  // A medição que falha não prova o teto alcançado: o custo não fecha, e a fila vazia ainda pode fechar.
314
325
  try {
315
326
  medicao = medir(raiz, estado, quando);
@@ -318,7 +329,7 @@ function fecharSeDevido(carregado, arco, opcoes = {}) {
318
329
  falhaDaMedicao = `; a medição falhou (${e.message.slice(0, 200)})`;
319
330
  }
320
331
  }
321
- condicao = condicaoDeFechamento(estado, fila, medicao, quando, emVooAgora, parada);
332
+ condicao = condicaoDeFechamento(estadoDoCusto, fila, medicao, quando, emVooAgora, parada);
322
333
  // RM-058, integração (T4, D8): a fila vazia não fecha o arco por cima do MASTER por omissão que a entrega dele ainda
323
334
  // deve; o passo seguinte o faz, e o fechamento vem depois. A hora, a parada e o teto fecharam antes, sem esperar.
324
335
  const devidos = condicao?.motivo === 'fila-vazia' && fila && sup ? mastersDevidos(raiz, estado, fila, sup) : [];
@@ -81,6 +81,9 @@ function classificar(t, posicao, f, fatos, entregues, semSaida, estado) {
81
81
  if (fatos.coordenacao?.encerrados?.has(t.id)) {
82
82
  return { ...base, thread: f?.threads[0]?.id ?? null, estado: 'encerrado-sem-entrega', detalhe: 'encerrado sem entrega em outra máquina do arco' };
83
83
  }
84
+ if ((0, noctum_envelope_1.envelopeMultimaquina)(estado.conteudo) && fatos.coordenacao?.emOutraMaquina?.has(t.id)) {
85
+ return bloqueado('em-outra-maquina', 'o trabalho tem ordem viva em outra máquina do arco');
86
+ }
84
87
  if (!f)
85
88
  return bloqueado('thread-ilegivel', 'o trabalho não foi lido');
86
89
  if (f.ilegivel)
@@ -278,7 +281,9 @@ function fatosDaFila(carregado, arco, opcoes = {}) {
278
281
  }
279
282
  else {
280
283
  const alvo = (0, noctum_envelope_1.shaDoPedido)(t.pedido);
281
- casam = threads.filter(x => x.roadmap === t.item && x.pedido?.sha256 === alvo);
284
+ const ordem = opcoes.coordenacao?.ordens?.get(t.id);
285
+ casam = threads.filter(x => x.roadmap === t.item && x.pedido?.sha256 === alvo &&
286
+ (!ordem || x.assunto.endsWith(`o${ordem.numero}`)));
282
287
  // Sem casar e com thread ilegível, ela pode ser a do trabalho: abrir outra duplicaria a thread.
283
288
  if (!casam.length && fatos.threadsIlegiveis.length)
284
289
  ilegivel = fatos.threadsIlegiveis[0];
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.pedidoDoArco = exports.linhaDoArco = exports.MOTIVO_DO_ARCO_ILEGIVEL = exports.MOTIVO_DA_GUARDA = void 0;
36
+ exports.pedidoDoArco = exports.linhaDoArco = exports.MOTIVO_DA_REDE_ILEGIVEL = exports.MOTIVO_DO_ARCO_ILEGIVEL = exports.MOTIVO_DA_GUARDA = void 0;
37
37
  exports.lerArcosDaRaiz = lerArcosDaRaiz;
38
38
  exports.arcoDosEventos = arcoDosEventos;
39
39
  exports.arcoDoUltimoDespacho = arcoDoUltimoDespacho;
@@ -70,12 +70,14 @@ const path = __importStar(require("node:path"));
70
70
  const estado_thread_1 = require("./estado-thread");
71
71
  const ledger_1 = require("./ledger");
72
72
  const locale_1 = require("./locale");
73
+ const manifest_1 = require("./manifest");
73
74
  const noctum_arco_1 = require("./noctum-arco");
74
75
  const noctum_sessoes_em_voo_1 = require("./noctum-sessoes-em-voo");
75
76
  const noctum_envelope_1 = require("./noctum-envelope");
76
77
  const thread_1 = require("./thread");
77
78
  exports.MOTIVO_DA_GUARDA = 'noctum.guarda.thread-do-arco';
78
79
  exports.MOTIVO_DO_ARCO_ILEGIVEL = 'noctum.guarda.arco-ilegivel';
80
+ exports.MOTIVO_DA_REDE_ILEGIVEL = 'noctum.guarda.rede-ilegivel';
79
81
  /** A recusa com os três textos do catálogo, cada um remontável no locale de quem imprime. */
80
82
  function recusa(motivo, thread, arco, situacao, origem, detalhe, correcao) {
81
83
  return { motivo, thread, arco, situacao, origem, detalhe: (0, locale_1.textoDoCatalogo)(detalhe), correcao: (0, locale_1.textoDoCatalogo)(correcao),
@@ -92,7 +94,7 @@ function nomesDosArcos(raiz) {
92
94
  }
93
95
  /** Lê cada arco desta raiz uma vez. O arco que não se lê fica com o motivo, e os outros seguem. */
94
96
  function lerArcosDaRaiz(raiz, quando = new Date().toISOString()) {
95
- const arcos = { quando, lidos: new Map(), ilegiveis: new Map() };
97
+ const arcos = { quando, lidos: new Map(), ilegiveis: new Map(), redes: new Map(), redesIlegiveis: new Map() };
96
98
  for (const arco of nomesDosArcos(raiz)) {
97
99
  try {
98
100
  const lido = (0, noctum_arco_1.lerArcoComProposta)(raiz, arco, quando);
@@ -127,8 +129,51 @@ function arcoDoUltimoDespacho(raiz, thread) {
127
129
  }
128
130
  /** A thread está na lista? A fixada no trabalho, ou a que casa com o item e o sha256 do pedido dele. */
129
131
  function naLista(conteudo, thread, dados) {
130
- return !!conteudo?.trabalhos?.some(w => w.thread !== undefined ? w.thread === thread
131
- : w.pedido !== undefined && dados().roadmap === w.item && dados().pedido === (0, noctum_envelope_1.shaDoPedido)(w.pedido));
132
+ return !!trabalhoNaLista(conteudo, thread, dados);
133
+ }
134
+ /** O trabalho da thread na lista, pela fixação ou pelo pedido, quando existe. */
135
+ function trabalhoNaLista(conteudo, thread, dados) {
136
+ return conteudo?.trabalhos?.find(w => w.thread !== undefined ? w.thread === thread
137
+ : w.pedido !== undefined && dados().roadmap === w.item && dados().pedido === (0, noctum_envelope_1.shaDoPedido)(w.pedido)) ?? null;
138
+ }
139
+ /** O id do trabalho que liga esta thread ao arco, na lista vigente ou no despacho mais recente. */
140
+ function trabalhoDaThread(estado, thread, dados) {
141
+ const listado = trabalhoNaLista(estado.conteudo, thread, dados);
142
+ if (listado)
143
+ return listado.id;
144
+ for (let i = estado.despachos.length - 1; i >= 0; i--) {
145
+ const d = estado.despachos[i];
146
+ if (d.thread === thread || d.threadDespachada === thread)
147
+ return d.trabalho;
148
+ }
149
+ return null;
150
+ }
151
+ /** A rede do arco, uma vez por `ArcosDaRaiz`; falha inesperada também fica cacheada e falha fechada. */
152
+ function redeDoArco(arco, arcos, ler) {
153
+ const pronta = arcos.redes.get(arco);
154
+ if (pronta)
155
+ return pronta;
156
+ const falha = arcos.redesIlegiveis.get(arco);
157
+ if (falha !== undefined)
158
+ return falha;
159
+ try {
160
+ const rede = ler(arco);
161
+ arcos.redes.set(arco, rede);
162
+ return rede;
163
+ }
164
+ catch (e) {
165
+ const detalhe = (e instanceof Error ? e.message : String(e)).split('\n')[0].slice(0, 200);
166
+ arcos.redesIlegiveis.set(arco, detalhe);
167
+ return detalhe;
168
+ }
169
+ }
170
+ /**
171
+ * A fila carrega a Sentinela, que carrega esta guarda. Resolver a projeção só quando uma thread de arco v3 encerrado
172
+ * realmente precisar dela evita o ciclo de inicialização fila -> guarda -> rede -> coordenação -> fila.
173
+ */
174
+ function lerRedePadrao(raiz, arco, quando) {
175
+ const { lerRede } = require('./noctum-rede');
176
+ return lerRede((0, manifest_1.exigirManifesto)(raiz), arco, { quando });
132
177
  }
133
178
  /**
134
179
  * Os vínculos da thread com os arcos lidos, um por arco, na ordem das origens: a lista do envelope vigente, a da proposta
@@ -183,6 +228,38 @@ function guardaDaThread(raiz, thread, quando = new Date().toISOString(), opcoes
183
228
  const vinculos = vinculosDaThread(raiz, arcos, thread, ultimo);
184
229
  const v = vinculos.find(x => x.arco !== opcoes.doArco && guardaOsCaminhosManuais(x));
185
230
  if (!v) {
231
+ let dadosLidos = null;
232
+ const dados = () => {
233
+ if (dadosLidos)
234
+ return dadosLidos;
235
+ try {
236
+ const t = (0, thread_1.lerThread)(raiz, thread);
237
+ dadosLidos = { roadmap: t.roadmap ?? null, pedido: t.pedido?.sha256 ?? null };
238
+ }
239
+ catch {
240
+ dadosLidos = { roadmap: null, pedido: null };
241
+ }
242
+ return dadosLidos;
243
+ };
244
+ // Num v3 encerrado localmente, o trabalho pode seguir em outra máquina. A rede só é lida depois de provar o vínculo,
245
+ // e a leitura fica no `ArcosDaRaiz` para o registrar-pr --todas não consultar o mesmo arco de novo.
246
+ for (const t of vinculos.filter(x => x.arco !== opcoes.doArco && x.situacao === 'encerrado')) {
247
+ const lido = arcos.lidos.get(t.arco);
248
+ if (!lido?.estado.conteudo || !(0, noctum_envelope_1.envelopeMultimaquina)(lido.estado.conteudo))
249
+ continue;
250
+ const trabalho = trabalhoDaThread(lido.estado, thread, dados);
251
+ if (!trabalho)
252
+ continue;
253
+ const rede = redeDoArco(t.arco, arcos, opcoes.lerRede ?? ((arco) => lerRedePadrao(raiz, arco, arcos.quando)));
254
+ if (typeof rede === 'string' || rede.lacuna) {
255
+ const falha = typeof rede === 'string' ? rede : `${rede.lacuna.motivo}: ${rede.lacuna.detalhe}`;
256
+ return recusa(exports.MOTIVO_DA_REDE_ILEGIVEL, thread, t.arco, t.situacao, 'rede', (m) => m.ship.guarda.redeIlegivel(thread, t.arco, falha), (m) => m.ship.guarda.redeIlegivelCorrecao(t.arco));
257
+ }
258
+ const naRede = rede.trabalhos.find(x => x.id === trabalho);
259
+ if (!rede.revogada && naRede && naRede.estado !== 'entregue' && naRede.estado !== 'encerrado') {
260
+ return recusa(exports.MOTIVO_DA_GUARDA, thread, t.arco, t.situacao, 'rede', (m) => m.ship.guarda.redeDoArco(thread, t.arco, naRede.estado, trabalho), (m) => m.ship.guarda.redeDoArcoCorrecao(t.arco));
261
+ }
262
+ }
186
263
  // A2 do CHECK: no arco que terminou (revogado, expirado ou encerrado), a sessão que ele despachou e que ainda conduz a
187
264
  // thread não entrega fora dele; sem sessão dele em voo, a thread se entrega à mão, como antes.
188
265
  for (const t of vinculos.filter(x => x.arco !== opcoes.doArco && TERMINAIS.includes(x.situacao))) {
@@ -351,6 +351,9 @@ function passoDaMaquina(carregado, arco, opcoes = {}) {
351
351
  const perfisDaN2 = opcoes.n2?.perfis ?? (() => perfisDoStore(raiz, Date.parse(quando)));
352
352
  // 4. O passo da N2, só com o que o ramo deu a esta máquina, e a vaga global no gancho da reserva da coordenação.
353
353
  const ordemDoTrabalho = new Map(minhas.filter(o => permitidos.has(o.trabalho)).map(o => [o.trabalho, o.ordem]));
354
+ const ordensDaFila = new Map(minhas.filter(o => permitidos.has(o.trabalho)).map(o => [o.trabalho, { ordem: o.ordem, numero: o.n }]));
355
+ const emOutraMaquina = new Set([...estado.ordens.values()]
356
+ .filter(o => o.maquina !== eu && (0, noctum_coordenacao_1.ordemViva)(o)).map(o => o.trabalho));
354
357
  const reservar = (raizDoPasso, pedido, q) => {
355
358
  const ordem = ordemDoTrabalho.get(pedido.trabalho);
356
359
  if (!ordem)
@@ -369,7 +372,8 @@ function passoDaMaquina(carregado, arco, opcoes = {}) {
369
372
  const passo = (0, noctum_execucao_1.passoDoArco)(carregado, arco, { ...opcoes.n2, quando, maquina: opcoes.maquina,
370
373
  perfis: () => perfisDaN2().filter(p => !semVaga.has(p.id)),
371
374
  lerReservas: () => ({ leitura: 'copia-local', reservas: reservadas.map(x => ({ item: x.item, maquina: eu, thread: x.thread })) }),
372
- coordenacao: { trabalhos: permitidos, entregues: (0, noctum_coordenacao_1.entreguesNaRede)(estado), encerrados: (0, noctum_coordenacao_1.encerradosNaRede)(estado), reservar } });
375
+ coordenacao: { trabalhos: permitidos, entregues: (0, noctum_coordenacao_1.entreguesNaRede)(estado), encerrados: (0, noctum_coordenacao_1.encerradosNaRede)(estado),
376
+ emOutraMaquina, ordens: ordensDaFila, reservar } });
373
377
  return { acao: 'passo', passo, relatorio };
374
378
  }
375
379
  catch (e) {
@@ -79,6 +79,7 @@ const noctum_relatorio_1 = require("./noctum-relatorio");
79
79
  const noctum_registro_1 = require("./noctum-registro");
80
80
  const noctum_supervisao_1 = require("./noctum-supervisao");
81
81
  const noctum_vigia_1 = require("./noctum-vigia");
82
+ const noctum_rede_1 = require("./noctum-rede");
82
83
  exports.CONTRATO_INGRESSO_DO_ARCO = 'ork.noctum-ingresso/v1';
83
84
  exports.CONTRATO_RETRATO_DO_ARCO = 'ork.noctum-retrato/v1';
84
85
  exports.CONTRATO_TIQUE = 'ork.noctum-tique/v1';
@@ -175,18 +176,25 @@ function retratoDoArco(carregado, arco, opcoes = {}) {
175
176
  return null;
176
177
  const lacunas = [];
177
178
  const conteudo = estado.conteudo;
179
+ const rede = conteudo && (0, noctum_envelope_1.envelopeMultimaquina)(conteudo) ? opcoes.projecaoDaRede ?? (0, noctum_rede_1.lerRede)(carregado, arco, { quando, maquina: opcoes.maquina, remoto: opcoes.remoto, rede: opcoes.redeDaCoordenacao }) : null;
180
+ if (rede?.lacuna)
181
+ lacunas.push(`a rede do arco não pôde ser lida (${rede.lacuna.motivo}: ${rede.lacuna.detalhe})`);
178
182
  let consumo = [];
179
183
  let fila = null;
180
184
  if (conteudo && estado.autorizadoPor) {
181
185
  // As unidades dos tetos só: com todos em sessões, nenhuma transcrição nem rollout é lido para o retrato.
182
- const medicao = (0, noctum_relatorio_1.medidorDoRelatorio)(opcoes, conteudo)(raiz, estado, quando);
186
+ const estadoDoCusto = rede && !rede.lacuna ? { ...estado, consumo: { ...estado.consumo, arco: rede.consumo.arco } } : estado;
187
+ const medicao = (0, noctum_relatorio_1.medidorDoRelatorio)(opcoes, conteudo)(raiz, estadoDoCusto, quando);
183
188
  const o = conteudo.orcamento;
184
189
  const linha = (escopo, unidade, teto, c) => ({ escopo, unidade, teto, texto: (0, noctum_medicao_1.textoDoConsumo)(c), valor: c.valor });
185
190
  consumo = [linha('do arco', o.arco.unidade, o.arco.valor, (0, noctum_medicao_1.consumoDoEscopoNaUnidade)(medicao, 'arco', o.arco.unidade)),
186
191
  ...o.porConta.map(s => linha(`da conta ${s.conta}`, s.teto.unidade, s.teto.valor, (0, noctum_medicao_1.consumoDoEscopoNaUnidade)(medicao, { conta: s.conta }, s.teto.unidade))),
187
192
  ...o.porRuntime.map(s => linha(`do runtime ${s.runtime}`, s.teto.unidade, s.teto.valor, (0, noctum_medicao_1.consumoDoEscopoNaUnidade)(medicao, { runtime: s.runtime }, s.teto.unidade)))];
188
193
  try {
189
- const f = (0, noctum_fechamento_1.trabalhosDoArco)((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas }));
194
+ const coordenacao = rede ? (0, noctum_rede_1.coordenacaoDaFila)(rede) : null;
195
+ if (rede?.lacuna)
196
+ throw new noctum_envelope_1.RecusaDoArco(rede.lacuna.motivo, rede.lacuna.detalhe);
197
+ const f = (0, noctum_fechamento_1.trabalhosDoArco)((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas, ...(coordenacao ? { coordenacao } : {}) }));
190
198
  fila = { situacao: f.situacao, trabalhos: f.trabalhos.map(t => ({ id: t.id, item: t.item, thread: t.thread, estado: t.estado, fase: t.fase,
191
199
  motivo: t.motivo })) };
192
200
  lacunas.push(...f.lacunas);
@@ -224,7 +232,8 @@ function retratoDoArco(carregado, arco, opcoes = {}) {
224
232
  }
225
233
  return { contrato: exports.CONTRATO_RETRATO_DO_ARCO, arco, quando, situacao: estado.situacao, versao: estado.versao, envelopeSha256: estado.envelopeSha256,
226
234
  janela: conteudo ? { inicio: conteudo.janela.inicio, fim: conteudo.janela.fim, fuso: conteudo.janela.fuso } : null,
227
- propostaPendente: estado.propostaPendente, consumo, fila, fechamento, relatorio, supervisao, decisoesPendentes: estado.decisoes.length, lacunas };
235
+ propostaPendente: estado.propostaPendente, consumo, fila, ...(rede ? { rede } : {}), fechamento, relatorio, supervisao,
236
+ decisoesPendentes: estado.decisoes.length, lacunas };
228
237
  }
229
238
  /** O retrato em texto para pessoa, em pt-BR, com os horários no fuso da janela. */
230
239
  function textoDoRetrato(r) {
@@ -243,6 +252,13 @@ function textoDoRetrato(r) {
243
252
  l.push(`Fila: ${r.fila.situacao}`, ...r.fila.trabalhos.map(t => ` • ${t.id} (${t.item}): ${t.estado}${t.fase ? `, fase ${t.fase}` : ''}` +
244
253
  `${t.thread ? `, thread ${t.thread}` : ''}${t.motivo ? ` (${t.motivo})` : ''}`));
245
254
  }
255
+ if (r.rede) {
256
+ if (r.rede.lacuna)
257
+ l.push(`Rede: sem leitura (${r.rede.lacuna.motivo}: ${r.rede.lacuna.detalhe})`);
258
+ else
259
+ l.push(`Rede: autoridade ${r.rede.autoridade?.maquina ?? 'ainda não assumida'}; máquina desta composição ${r.rede.maquina}`, ...r.rede.maquinas.map(m => ` • ${m.nome}: último sinal ${m.ultimoSinal ? formatarNoFuso(m.ultimoSinal) : 'ausente'}, ` +
260
+ `${m.ordensVivas.length} ordem(ns), ${m.vagasAtivas.length} vaga(s), consumo ${m.consumo}`));
261
+ }
246
262
  if (r.fechamento) {
247
263
  l.push(`Fechamento: ${r.fechamento.motivo} em ${formatarNoFuso(r.fechamento.em)}: ${r.fechamento.detalhe}`, ...r.fechamento.paradas.map(p => ` • ${p}`));
248
264
  }
@@ -267,11 +283,17 @@ function textoDoRetrato(r) {
267
283
  * vencimento) acabada, quando o relatório não tenta mais (A3 do CHECK: o canal sem transporte, o terminal nunca mostrado).
268
284
  * O vigia não roda mais, e o log dele não cresce.
269
285
  */
270
- function terminalQuieto(carregado, arco, estado, quando) {
286
+ function terminalQuieto(carregado, arco, estado, quando, rede) {
271
287
  if (!['expirado', 'revogado', 'encerrado'].includes(estado.situacao))
272
288
  return false;
273
289
  if (estado.despachos.some(d => d.desfecho === 'pendente'))
274
290
  return false;
291
+ if (estado.conteudo && (0, noctum_envelope_1.envelopeMultimaquina)(estado.conteudo)) {
292
+ if (!rede || rede.lacuna)
293
+ return false;
294
+ if (rede.obrigacoes.ordens.length || rede.obrigacoes.vagas.length || rede.obrigacoes.vezes.length)
295
+ return false;
296
+ }
275
297
  try {
276
298
  const r = (0, noctum_relatorio_1.retratoDoRelatorio)(carregado.raiz, arco, estado.conteudo, quando);
277
299
  if (r.versoes.at(-1)?.entregue === true)
@@ -299,8 +321,11 @@ function tiqueDoArco(carregado, arco, opcoes = {}) {
299
321
  if (!estado?.autorizadoPor) {
300
322
  throw new noctum_envelope_1.RecusaDoArco('noctum.modo.sem-envelope', `o arco ${arco} nunca foi autorizado pelo dono: o #Noctum não vale; ${COMO_ABRIR}`);
301
323
  }
324
+ const rede = estado.conteudo && (0, noctum_envelope_1.envelopeMultimaquina)(estado.conteudo)
325
+ ? opcoes.projecaoDaRede ?? (0, noctum_rede_1.lerRede)(carregado, arco, { quando, maquina: opcoes.maquina, remoto: opcoes.remoto, rede: opcoes.redeDaCoordenacao }) : null;
302
326
  const deFechamento = { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas, medir: opcoes.medir,
303
- parar: opcoes.parar, listarSessoes: opcoes.listarSessoes, git: opcoes.git };
327
+ parar: opcoes.parar, listarSessoes: opcoes.listarSessoes, git: opcoes.git, projecaoDaRede: rede ?? undefined,
328
+ remoto: opcoes.remoto, redeDaCoordenacao: opcoes.redeDaCoordenacao };
304
329
  const falhas = [];
305
330
  let erro = null;
306
331
  const isolada = (etapa, fn) => {
@@ -338,8 +363,10 @@ function tiqueDoArco(carregado, arco, opcoes = {}) {
338
363
  fechamento = isolada('fechamento', () => (0, noctum_fechamento_1.fecharSeDevido)(carregado, arco, deFechamento)) ?? queFalhou();
339
364
  }
340
365
  }
341
- else if (agora && agora.situacao !== 'agendado' && !terminalQuieto(carregado, arco, agora, quando)) {
366
+ else if (agora && agora.situacao !== 'agendado' && !terminalQuieto(carregado, arco, agora, quando, rede)) {
342
367
  const deVigia = { ...opcoes.opcoesDoVigia, quando, maquina: opcoes.maquina ?? opcoes.opcoesDoVigia?.maquina,
368
+ coordenacao: { remoto: opcoes.remoto ?? opcoes.opcoesDoVigia?.coordenacao?.remoto,
369
+ rede: opcoes.redeDaCoordenacao ?? opcoes.opcoesDoVigia?.coordenacao?.rede },
343
370
  passo: { maquina: opcoes.maquina, lerReservas: opcoes.lerReservas, ...opcoes.opcoesDoPasso, ...opcoes.opcoesDoVigia?.passo } };
344
371
  vigia = isolada('vigia', () => (opcoes.vigia ?? noctum_vigia_1.vigiarArco)(carregado, arco, deVigia));
345
372
  const doVigia = vigia?.acao === 'tique' ? vigia.passo : null;
@@ -351,7 +378,8 @@ function tiqueDoArco(carregado, arco, opcoes = {}) {
351
378
  let relatorio;
352
379
  try {
353
380
  relatorio = (0, noctum_relatorio_1.entregarRelatorioSeDevido)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas,
354
- medir: opcoes.medir, supervisao: opcoes.supervisao, enviar: opcoes.enviar });
381
+ medir: opcoes.medir, supervisao: opcoes.supervisao, enviar: opcoes.enviar, projecaoDaRede: rede ?? undefined,
382
+ remoto: opcoes.remoto, redeDaCoordenacao: opcoes.redeDaCoordenacao });
355
383
  }
356
384
  catch (e) {
357
385
  throw erro ?? e;
@@ -335,7 +335,7 @@ const recusaDoNucleo = (motivo) => !!motivo && !motivo.startsWith('noctum.') &&
335
335
  * isolamento. Trabalho isolado, entregue, fechado, esperando o dono, com reserva pendente ou com retomada autorizada e
336
336
  * ainda não atendida (B1) fica de fora.
337
337
  */
338
- function decidirSessoes(raiz, arco, conteudo, estado, sup, leitura, quando) {
338
+ function decidirSessoes(raiz, arco, conteudo, estado, sup, leitura, quando, ordensCanceladas = new Set()) {
339
339
  const parametros = sup.parametros;
340
340
  if (!parametros)
341
341
  return [];
@@ -346,6 +346,9 @@ function decidirSessoes(raiz, arco, conteudo, estado, sup, leitura, quando) {
346
346
  const decisoes = [];
347
347
  const aposReserva = (0, exports.ultimaReservaDoArco)(estado);
348
348
  for (const [trabalho, thread] of (0, noctum_supervisao_1.threadsDoArco)(raiz, conteudo, estado)) {
349
+ // A sessão da ordem cancelada na rede é encerrada pelo vigia, mas nunca autorizada a retomar nesta máquina.
350
+ if (ordensCanceladas.has(trabalho))
351
+ continue;
349
352
  if (sup.isolados.has(trabalho) || pendentes.has(trabalho))
350
353
  continue;
351
354
  let t, eventos;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONTRATO_REDE_DO_ARCO = void 0;
4
+ exports.lerRede = lerRede;
5
+ exports.coordenacaoDaFila = coordenacaoDaFila;
6
+ const maquina_1 = require("./maquina");
7
+ const noctum_arco_1 = require("./noctum-arco");
8
+ const noctum_coordenacao_1 = require("./noctum-coordenacao");
9
+ const noctum_envelope_1 = require("./noctum-envelope");
10
+ exports.CONTRATO_REDE_DO_ARCO = 'ork.noctum-rede/v1';
11
+ const consumoVazio = () => ({ arco: 0, porConta: {}, porRuntime: {} });
12
+ function vazia(arco, maquina, multimaquina, envelopeSha256, lidaEm, lacuna) {
13
+ return { contrato: exports.CONTRATO_REDE_DO_ARCO, arco, multimaquina, maquina, envelopeSha256, lidaEm, autoridade: null, revogada: null,
14
+ maquinas: [], trabalhos: [], consumo: consumoVazio(), obrigacoes: { ordens: [], vagas: [], vezes: [] }, lacuna };
15
+ }
16
+ function ordemProjetada(o) {
17
+ return { ordem: o.ordem, numero: o.n, maquina: o.maquina, estado: o.estado, emitidaEm: o.emitidaEm };
18
+ }
19
+ function projetar(estado, maquina, quando) {
20
+ const conteudo = estado.vigente.conteudo;
21
+ if (!(0, noctum_envelope_1.envelopeMultimaquina)(conteudo))
22
+ return vazia(estado.arco, maquina, false, estado.vigente.envelopeSha256, estado.lidoEm, null);
23
+ const vezes = [...estado.vezes.values()].flat();
24
+ const maquinas = conteudo.maquinas.map(({ nome }) => ({
25
+ nome,
26
+ ultimoSinal: estado.sinais.get(nome) ?? null,
27
+ sinalRecente: (0, noctum_coordenacao_1.batidaRecente)(estado, nome, maquina, quando),
28
+ ordensVivas: [...estado.ordens.values()].filter(o => o.maquina === nome && (0, noctum_coordenacao_1.ordemViva)(o)).map(o => o.ordem).sort(),
29
+ vagasAtivas: estado.vagas.filter(v => v.maquina === nome && !v.solta).map(v => v.vaga).sort(),
30
+ vezesAtivas: vezes.filter(v => v.maquina === nome && !v.fim).map(v => `${v.chave}/${v.n}`).sort(),
31
+ consumo: estado.vagas.filter(v => v.maquina === nome && (!v.solta || v.solta.consumiu)).length,
32
+ }));
33
+ const trabalhos = conteudo.trabalhos.map(t => {
34
+ const situacao = estado.trabalhos.get(t.id);
35
+ const ordem = situacao.ordem ? ordemProjetada(situacao.ordem) : null;
36
+ const registro = estado.entregas.get(t.id);
37
+ const entrega = registro ? { em: registro.em, maquina: registro.por, merge: String(registro.merge) } : null;
38
+ return { id: t.id, estado: situacao.estado, maquina: ordem?.maquina ?? null, ordem, maquinaPresa: t.maquina ?? null, entrega };
39
+ });
40
+ return {
41
+ contrato: exports.CONTRATO_REDE_DO_ARCO,
42
+ arco: estado.arco,
43
+ multimaquina: true,
44
+ maquina,
45
+ envelopeSha256: estado.vigente.envelopeSha256,
46
+ lidaEm: estado.lidoEm,
47
+ autoridade: estado.autoridade ? { maquina: estado.autoridade.maquina, geracao: estado.autoridade.geracao, desde: estado.autoridade.desde } : null,
48
+ revogada: estado.revogada,
49
+ maquinas,
50
+ trabalhos,
51
+ consumo: estado.consumo,
52
+ obrigacoes: {
53
+ ordens: [...estado.ordens.values()].filter(o => o.maquina === maquina && (0, noctum_coordenacao_1.ordemViva)(o)).map(o => o.ordem).sort(),
54
+ vagas: estado.vagas.filter(v => v.maquina === maquina && !v.solta).map(v => v.vaga).sort(),
55
+ vezes: vezes.filter(v => v.maquina === maquina && !v.fim).map(v => `${v.chave}/${v.n}`).sort(),
56
+ },
57
+ lacuna: null,
58
+ };
59
+ }
60
+ /** Lê a rede de um v3. Em v1/v2 não toca o remoto; recusa tipada vira lacuna, sem inventar estado. */
61
+ function lerRede(carregado, arco, opcoes = {}) {
62
+ const quando = opcoes.quando ?? new Date().toISOString();
63
+ const maquina = (0, maquina_1.nomeDaMaquina)(opcoes.maquina);
64
+ const local = (0, noctum_arco_1.lerArco)(carregado.raiz, arco, quando);
65
+ if (!local?.conteudo || !(0, noctum_envelope_1.envelopeMultimaquina)(local.conteudo)) {
66
+ return vazia(arco, maquina, false, local?.envelopeSha256 ?? null, quando, null);
67
+ }
68
+ try {
69
+ return projetar((0, noctum_coordenacao_1.lerCoordenacao)(carregado, arco, { ...opcoes, quando }), maquina, quando);
70
+ }
71
+ catch (e) {
72
+ if (!(e instanceof noctum_envelope_1.RecusaDoArco))
73
+ throw e;
74
+ return vazia(arco, maquina, true, local.envelopeSha256, quando, { motivo: e.motivo, detalhe: e.message });
75
+ }
76
+ }
77
+ /** Adapta a projeção íntegra para a fila. Rede local ou ilegível não vira coordenação vazia. */
78
+ function coordenacaoDaFila(rede) {
79
+ if (!rede.multimaquina || rede.lacuna)
80
+ return null;
81
+ const trabalhos = new Set();
82
+ const entregues = new Map();
83
+ const encerrados = new Set();
84
+ const emOutraMaquina = new Set();
85
+ const ordens = new Map();
86
+ for (const t of rede.trabalhos) {
87
+ if (t.entrega)
88
+ entregues.set(t.id, t.entrega.em);
89
+ else if (t.estado === 'entregue')
90
+ entregues.set(t.id, t.ordem?.emitidaEm ?? rede.lidaEm);
91
+ if (t.estado === 'encerrado')
92
+ encerrados.add(t.id);
93
+ if (t.ordem?.maquina === rede.maquina && t.ordem.estado === 'aceita') {
94
+ trabalhos.add(t.id);
95
+ ordens.set(t.id, { ordem: t.ordem.ordem, numero: t.ordem.numero });
96
+ }
97
+ else if (t.ordem && ['emitida', 'aceita', 'isolada'].includes(t.ordem.estado) && t.ordem.maquina !== rede.maquina) {
98
+ emOutraMaquina.add(t.id);
99
+ }
100
+ }
101
+ return { trabalhos, entregues, encerrados, emOutraMaquina, ordens };
102
+ }
@@ -98,6 +98,7 @@ const noctum_registro_1 = require("./noctum-registro");
98
98
  const noctum_supervisao_1 = require("./noctum-supervisao");
99
99
  const procedencia_1 = require("./procedencia");
100
100
  const thread_1 = require("./thread");
101
+ const noctum_rede_1 = require("./noctum-rede");
101
102
  exports.CONTRATO_RELATORIO = 'ork.noctum-relatorio/v1';
102
103
  /** O teto de uma mensagem do Telegram é 4.096; a página fica abaixo, com folga, como o digest do MASTER. */
103
104
  exports.TETO_DA_PAGINA = 3900;
@@ -231,9 +232,14 @@ function fatosDoRelatorio(carregado, arco, opcoes = {}, modo = {}) {
231
232
  const conteudo = estado.conteudo;
232
233
  const fuso = conteudo.janela.fuso;
233
234
  const lacunas = [];
235
+ const multimaquina = (0, noctum_envelope_1.envelopeMultimaquina)(conteudo);
236
+ const rede = multimaquina ? opcoes.projecaoDaRede ?? (0, noctum_rede_1.lerRede)(carregado, arco, { quando, maquina: opcoes.maquina, remoto: opcoes.remoto, rede: opcoes.redeDaCoordenacao }) : null;
237
+ if (rede?.lacuna)
238
+ lacunas.push(`a rede do arco não pôde ser lida (${rede.lacuna.motivo}: ${rede.lacuna.detalhe})`);
234
239
  let fila = null;
235
240
  try {
236
- fila = (0, noctum_fechamento_1.trabalhosDoArco)((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas }));
241
+ const coordenacao = rede ? (0, noctum_rede_1.coordenacaoDaFila)(rede) : null;
242
+ fila = rede?.lacuna ? null : (0, noctum_fechamento_1.trabalhosDoArco)((0, noctum_fila_1.fatosDaFila)(carregado, arco, { quando, maquina: opcoes.maquina, lerReservas: opcoes.lerReservas, ...(coordenacao ? { coordenacao } : {}) }));
237
243
  }
238
244
  catch (e) {
239
245
  if (!(e instanceof noctum_envelope_1.RecusaDoArco))
@@ -274,7 +280,22 @@ function fatosDoRelatorio(carregado, arco, opcoes = {}, modo = {}) {
274
280
  const pendente = estado.despachos.find(d => d.trabalho === t.id && d.desfecho === 'pendente');
275
281
  const base = { trabalho: t.id, item: t.item, thread: t.thread };
276
282
  const isolado = supervisao?.isolados.find(i => i.trabalho === t.id);
277
- if (t.estado === 'entregue' && t.thread && eventos) {
283
+ const naRede = rede?.trabalhos.find(x => x.id === t.id);
284
+ if (multimaquina && naRede?.entrega) {
285
+ const master = eventos ? [...eventos].reverse().find(x => x.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido) : null;
286
+ entregues.push({ ...base, pr: null, merge: naRede.entrega.merge, maquina: naRede.entrega.maquina,
287
+ push: `registro de entrega da N3 na máquina ${naRede.entrega.maquina}`,
288
+ master: master && typeof master.score === 'number' ? `MASTER ${master.score}/5` : 'MASTER pendente' });
289
+ continue;
290
+ }
291
+ if (multimaquina && naRede?.ordem && naRede.ordem.maquina !== rede?.maquina &&
292
+ ['emitida', 'aceita', 'isolada'].includes(naRede.ordem.estado)) {
293
+ emCurso.push({ ...base, estado: naRede.estado, maquina: naRede.ordem.maquina,
294
+ checkpoint: `ordem ${naRede.ordem.ordem} viva na máquina ${naRede.ordem.maquina}`,
295
+ retomada: `na máquina ${naRede.ordem.maquina}`, proximo: 'acompanhar a ordem e seus recibos na rede', reserva: null });
296
+ continue;
297
+ }
298
+ if (!multimaquina && t.estado === 'entregue' && t.thread && eventos) {
278
299
  const e = entregaDaThread(eventos);
279
300
  if (e.provada && e.ship) {
280
301
  const master = [...eventos].reverse().find(x => x.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido);
@@ -293,6 +314,12 @@ function fatosDoRelatorio(carregado, arco, opcoes = {}, modo = {}) {
293
314
  retomada: 'a entrega (N5), com a prova no SHA exato', proximo: 'provar o push e o merge', reserva: null });
294
315
  continue;
295
316
  }
317
+ if (multimaquina && t.estado === 'entregue') {
318
+ emCurso.push({ ...base, estado: t.estado, maquina: naRede?.maquina ?? null,
319
+ checkpoint: 'a entrega local ainda não tem registro de entrega na rede', retomada: 'a reconciliação da máquina',
320
+ proximo: 'publicar ou reconciliar o recibo da N3', reserva: null });
321
+ continue;
322
+ }
296
323
  if (isolado || t.estado === 'bloqueado' || t.estado === 'encerrado-sem-entrega') {
297
324
  const doDono = t.motivo === 'decisao-no-lote' || t.motivo === 'dono';
298
325
  const lote = doDono && t.thread ? estado.decisoes.find(d => d.thread === t.thread || d.dependentes.includes(t.thread))?.id ?? null : null;
@@ -330,11 +357,13 @@ function fatosDoRelatorio(carregado, arco, opcoes = {}, modo = {}) {
330
357
  }
331
358
  }
332
359
  decisoes.sort((a, b) => a.em.localeCompare(b.em));
333
- const custo = modo.semCusto ? [] : linhasDeCusto(conteudo, medidorDoRelatorio(opcoes, conteudo)(raiz, estado, quando));
360
+ const estadoDoCusto = rede && !rede.lacuna ? { ...estado, consumo: { ...estado.consumo, arco: rede.consumo.arco } } : estado;
361
+ const custo = modo.semCusto ? [] : linhasDeCusto(conteudo, medidorDoRelatorio(opcoes, conteudo)(raiz, estadoDoCusto, quando));
334
362
  const candidato = fila?.candidatos[0];
335
363
  return {
336
364
  arco, quando, fuso, vencimentoEm: vencimentoDoRelatorio(conteudo), janela: { inicio: conteudo.janela.inicio, fim: conteudo.janela.fim },
337
365
  situacao: estado.situacao, envelopeSha256: estado.envelopeSha256,
366
+ ...(multimaquina ? { maquina: rede?.maquina ?? opcoes.maquina ?? 'desconhecida', ...(rede ? { rede } : {}) } : {}),
338
367
  encerramento: estado.encerramento ? { motivo: estado.encerramento.motivo, detalhe: estado.encerramento.detalhe, em: estado.encerramento.em } : null,
339
368
  entregues, emCurso, impedidos, decisoes, custo,
340
369
  sessoesDespachadas: estado.despachos.filter(d => d.desfecho === 'concluido' && !d.idempotente).length,
@@ -371,15 +400,20 @@ function linhasDoRelatorio(f, versao) {
371
400
  l.push(`O arco segue até ${hora(f.janela.fim)}.`);
372
401
  else
373
402
  l.push(`O arco está ${f.situacao}.`);
403
+ if (f.rede && !f.rede.lacuna) {
404
+ l.push(`Rede: autoridade ${f.rede.autoridade?.maquina ?? 'ainda não assumida'}; composta na máquina ${f.maquina}.`, ...f.rede.maquinas.map(m => `• Máquina ${m.nome}: último sinal ${m.ultimoSinal ? hora(m.ultimoSinal) : 'ausente'}; ` +
405
+ `${m.ordensVivas.length} ordem(ns), ${m.vagasAtivas.length} vaga(s), consumo ${m.consumo}.`));
406
+ }
374
407
  if (f.lacunas.length)
375
408
  l.push(`Não lido: ${f.lacunas.join('; ')}.`);
376
- l.push('', '✅ Entregue', ...(f.entregues.length ? f.entregues.map(e => `• ${e.trabalho} (${e.item}): thread ${e.thread}` +
409
+ l.push('', '✅ Entregue', ...(f.entregues.length ? f.entregues.map(e => `• ${e.trabalho} (${e.item}): ` +
410
+ `${e.thread ? `thread ${e.thread}` : 'sem thread local'}${e.maquina ? `, máquina ${e.maquina}` : ''}` +
377
411
  `${e.pr !== null ? `, PR #${e.pr}` : ''}${e.merge ? `, merge ${e.merge.slice(0, 8)}` : ''}, push provado (${e.push}), ${e.master}`) : nada));
378
412
  const daSupervisao = [...f.retomadas.map(r => `• retomada autorizada pela supervisão: ${r}`),
379
413
  ...f.sessoesParadas.map(s => `• pela supervisão, ${s}`)];
380
414
  l.push('', '🔄 Em curso', ...(f.emCurso.length || f.paradas.length || daSupervisao.length ? [...f.emCurso.map(e => `• ${e.trabalho} (${e.item}): ` +
381
415
  `${e.thread ? `thread ${e.thread}, ` : ''}checkpoint: ${e.checkpoint}; retoma: ${e.retomada}; próximo passo: ${e.proximo}` +
382
- `${e.reserva ? `; ${e.reserva}` : ''}`), ...f.paradas.map(p => `• no fechamento, ${p}`), ...daSupervisao] : nada));
416
+ `${e.maquina ? `; máquina ${e.maquina}` : ''}${e.reserva ? `; ${e.reserva}` : ''}`), ...f.paradas.map(p => `• no fechamento, ${p}`), ...daSupervisao] : nada));
383
417
  // A parada da supervisão que ainda não fechou o arco (o fechamento a lê no tique seguinte) vai ao Impedido, com alcance do arco.
384
418
  const parada = f.paradaDaSupervisao && f.encerramento?.motivo !== 'supervisao'
385
419
  ? [`• o arco: parado pela supervisão (${f.paradaDaSupervisao}); alcance: arco`] : [];
@@ -440,8 +474,8 @@ function linhasDoRelatorio(f, versao) {
440
474
  return l.map(x => (0, hitl_1.redigirSegredos)(x));
441
475
  }
442
476
  /** As páginas de até `TETO_DA_PAGINA` caracteres, cada uma com o arco, a versão e a página no cabeçalho. */
443
- function paginar(arco, versao, linhas) {
444
- const cabecalho = (i, n) => `Arco ${arco}, relatório v${versao}, página ${i}/${n}`;
477
+ function paginar(arco, versao, linhas, maquina) {
478
+ const cabecalho = (i, n) => `Arco ${arco}, relatório v${versao}, página ${i}/${n}${maquina ? `, máquina ${maquina}` : ''}`;
445
479
  const espaco = exports.TETO_DA_PAGINA - cabecalho(99, 99).length - 1;
446
480
  const blocos = [[]];
447
481
  let tamanho = 0;
@@ -583,7 +617,7 @@ function correcoesDoRelatorio(linhas, fatos) {
583
617
  return correcoes;
584
618
  }
585
619
  function compor(fatos, versao, motivo, canal, corrigidos) {
586
- const paginas = paginar(fatos.arco, versao, linhasDoRelatorio(fatos, versao));
620
+ const paginas = paginar(fatos.arco, versao, linhasDoRelatorio(fatos, versao), fatos.maquina);
587
621
  return { tipo: 'composto', versao, motivo, vencimentoEm: fatos.vencimentoEm, canal, sha256: sha(paginas.join('\n')), paginas,
588
622
  informados: { entregues: fatos.entregues.map(e => ({ trabalho: e.trabalho, thread: e.thread, merge: e.merge })), corrigidos } };
589
623
  }
@@ -619,7 +653,7 @@ function entregarRelatorioSeDevido(carregado, arco, opcoes = {}) {
619
653
  const fatos = fatosDoRelatorio(carregado, arco, { ...opcoes, quando }, { semCusto: true });
620
654
  if (!fatos)
621
655
  return sem('sem-relatorio', `o arco ${arco} não tem envelope autorizado`);
622
- const comCusto = (f) => ({ ...f, custo: linhasDeCusto(conteudo, medidorDoRelatorio(opcoes, conteudo)(raiz, estado, quando)) });
656
+ const comCusto = (f) => ({ ...f, custo: linhasDeCusto(conteudo, medidorDoRelatorio(opcoes, conteudo)(raiz, f.rede && !f.rede.lacuna ? { ...estado, consumo: { ...estado.consumo, arco: f.rede.consumo.arco } } : estado, quando)) });
623
657
  try {
624
658
  return (0, noctum_registro_1.comRegistro)(raiz, arco, 'relatorio', (linhas, anexar) => {
625
659
  const todas = [...linhas];
@@ -755,7 +789,7 @@ function relatorioNoTerminal(carregado, arco, opcoes = {}) {
755
789
  if (!fatos)
756
790
  return null;
757
791
  return { versao: null, previa: true, paginas: paginar(arco, 0, ['Prévia: nenhuma versão foi composta ainda; isto não é a entrega.',
758
- ...linhasDoRelatorio(fatos, 0)]) };
792
+ ...linhasDoRelatorio(fatos, 0)], fatos.maquina) };
759
793
  }
760
794
  if (opcoes.interativo) {
761
795
  // Com a trava ocupada (o tique enviando), o dono vê as páginas assim mesmo; o recibo do terminal fica para a vez seguinte.