@orkastery/cli 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/dist/adapters/claude-bg.js +6 -6
- package/dist/adapters/grok-events.js +227 -0
- package/dist/adapters/grok-mcp-servidor.js +612 -0
- package/dist/adapters/grok-mcp.js +178 -0
- package/dist/adapters/grok.js +686 -0
- package/dist/agendador-cpu.js +92 -0
- package/dist/branch-de-estado.js +7 -2
- package/dist/check-agil.js +48 -20
- package/dist/check-paralelo.js +73 -18
- package/dist/conducao.js +5 -0
- package/dist/docs.js +9 -16
- package/dist/doctor-forja.js +1 -3
- package/dist/doctor.js +1 -1
- package/dist/entrega-pr.js +10 -10
- package/dist/fabrica-estado.js +20 -11
- package/dist/horario.js +4 -1
- package/dist/index.js +20 -10
- package/dist/integracoes-locais.js +2 -0
- package/dist/locale-accounts.js +11 -3
- package/dist/locale-ajuda.js +10 -6
- package/dist/locale-forja.js +2 -4
- package/dist/locale-operacao-restante.js +2 -2
- package/dist/locale-retry.js +40 -2
- package/dist/locale-ship.js +10 -2
- package/dist/manifest.js +6 -1
- package/dist/mcp-install.js +22 -12
- package/dist/mcp-server.js +42 -16
- package/dist/merge-da-entrega.js +85 -0
- package/dist/network-roadmap.js +18 -14
- package/dist/noctum-aceite.js +154 -14
- package/dist/noctum-cli.js +69 -12
- package/dist/noctum-entrega.js +55 -7
- package/dist/noctum-envelope.js +1 -1
- package/dist/noctum-execucao.js +5 -1
- package/dist/noctum-fechamento.js +18 -7
- package/dist/noctum-fila.js +6 -1
- package/dist/noctum-guarda.js +81 -4
- package/dist/noctum-maquinas.js +5 -1
- package/dist/noctum-modo.js +35 -7
- package/dist/noctum-reconciliacao.js +4 -1
- package/dist/noctum-rede.js +102 -0
- package/dist/noctum-relatorio.js +44 -10
- package/dist/noctum-retomada-rede.js +71 -0
- package/dist/noctum-vigia.js +49 -9
- package/dist/parado-no-condutor.js +14 -15
- package/dist/phase.js +43 -15
- package/dist/postura-local.js +7 -3
- package/dist/preflight.js +2 -1
- package/dist/ratelimit.js +1 -0
- package/dist/retry.js +103 -10
- package/dist/runtime-context.js +165 -45
- package/dist/runtime-escada.js +7 -1
- package/dist/runtime-profiles.js +27 -17
- package/dist/runtimes.js +42 -5
- package/dist/security-scan/agil.js +18 -7
- package/dist/security-scan/executor.js +8 -0
- package/dist/session-watcher-grok.js +425 -0
- package/dist/session-watcher.js +19 -4
- package/dist/sessoes-contas.js +33 -5
- package/dist/setup.js +11 -11
- package/dist/varredura-acoes.js +8 -15
- package/dist/verify.js +26 -10
- package/package.json +2 -2
package/dist/mcp-server.js
CHANGED
|
@@ -76,6 +76,7 @@ const fila_pesada_1 = require("./fila-pesada");
|
|
|
76
76
|
const decisao_autonoma_1 = require("./decisao-autonoma");
|
|
77
77
|
const conducao_texto_1 = require("./conducao-texto");
|
|
78
78
|
const mcp_ship_1 = require("./mcp-ship");
|
|
79
|
+
const grok_1 = require("./adapters/grok");
|
|
79
80
|
const company_brain_mcp_1 = require("./company-brain-mcp");
|
|
80
81
|
const claude_bg_1 = require("./adapters/claude-bg");
|
|
81
82
|
const session_watcher_claude_1 = require("./session-watcher-claude");
|
|
@@ -113,7 +114,8 @@ const modoDeConducao = zod_1.z.string().trim().min(1).max(40)
|
|
|
113
114
|
const nova = zod_1.z.object({ nome: zod_1.z.string().trim().min(1).max(200),
|
|
114
115
|
modo: modoDeConducao.optional() }).strict();
|
|
115
116
|
const fase = daThread.extend({ fase: zod_1.z.enum(['GOAL', 'PLAN', 'GO', 'CHECK', 'SHIP', 'MASTER']),
|
|
116
|
-
|
|
117
|
+
// RM-067 (F4b): o grok tambem, como o --runtime do CLI, sempre com o model dele.
|
|
118
|
+
prompt: zod_1.z.string().min(1).max(65536), runtime: zod_1.z.enum(['claude-bg', 'codex', 'grok']).optional(),
|
|
117
119
|
model: zod_1.z.string().trim().min(1).max(200).optional(),
|
|
118
120
|
effort: zod_1.z.enum(['low', 'medium', 'high', 'xhigh', 'max']).optional(),
|
|
119
121
|
// RM-056 (D1): o perfil pedido, validado contra o store pelo mesmo caminho do CLI.
|
|
@@ -125,8 +127,11 @@ const resposta = (valor) => ({ content: [{ type: 'text', text: JSON.stringify(va
|
|
|
125
127
|
function criarServidorMcp(opcoes) {
|
|
126
128
|
if (!path.isAbsolute(opcoes.projeto))
|
|
127
129
|
throw Error('mcp.project.invalid: raiz absoluta obrigatoria');
|
|
128
|
-
if (!['claude-code', 'codex'].includes(opcoes.host))
|
|
130
|
+
if (!['claude-code', 'codex', 'grok'].includes(opcoes.host))
|
|
129
131
|
throw Error('mcp.host.invalid');
|
|
132
|
+
// RM-067 (F4b, G1): o servidor do grok so serve a sessao filha; o despacho grava --thread na config da worktree.
|
|
133
|
+
if (opcoes.host === 'grok' && opcoes.threadId === undefined)
|
|
134
|
+
throw Error('mcp.host.child-only: --host grok serve so a sessao filha vinculada a uma thread (--thread), que o despacho do ork grava na config da worktree');
|
|
130
135
|
if (opcoes.permissoesFilho !== undefined && !['interactive', 'worktree'].includes(opcoes.permissoesFilho))
|
|
131
136
|
throw Error('mcp.child-permissions.invalid');
|
|
132
137
|
if (opcoes.threadId !== undefined)
|
|
@@ -187,6 +192,18 @@ function criarServidorMcp(opcoes) {
|
|
|
187
192
|
};
|
|
188
193
|
if (opcoes.threadId)
|
|
189
194
|
thread(opcoes.threadId);
|
|
195
|
+
// RM-067 (F4b, G1): o servidor do grok lista so as ferramentas do perfil filho; o headless nao aprova outra em dialogo.
|
|
196
|
+
const doGrok = opcoes.host === 'grok'
|
|
197
|
+
? new Set((0, grok_1.ferramentasServidasAoGrok)(opcoes.permissoesFilho ?? 'interactive', (0, mcp_grafo_1.grafoLigado)((0, manifest_1.exigirManifesto)(raiz).manifesto))) : null;
|
|
198
|
+
// RM-067 (F4c, D4): a lista do despacho e um subconjunto da uniao do perfil filho; fora dela, ou sem o host grok, recusa.
|
|
199
|
+
if (opcoes.ferramentas !== undefined) {
|
|
200
|
+
const pedidas = opcoes.ferramentas;
|
|
201
|
+
if (!doGrok || pedidas.some(n => !doGrok.has(n)) || new Set(pedidas).size !== pedidas.length)
|
|
202
|
+
throw Error('mcp.tools.invalid: a lista do despacho sai do perfil filho do grok');
|
|
203
|
+
for (const nome of [...doGrok])
|
|
204
|
+
if (!pedidas.includes(nome))
|
|
205
|
+
doGrok.delete(nome);
|
|
206
|
+
}
|
|
190
207
|
const pendencias = (id) => {
|
|
191
208
|
const t = thread(id), eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id)), contexto = (0, hitl_gates_1.contextoHitl)(raiz, id);
|
|
192
209
|
const pedidos = [(0, hitl_presentation_1.pedidoHitlAberto)(raiz, id, t.faseAtual, null),
|
|
@@ -195,7 +212,7 @@ function criarServidorMcp(opcoes) {
|
|
|
195
212
|
// e so ele. Nenhum outro canal mcp-local sai `disponivel` daqui por suposicao.
|
|
196
213
|
return pedidos.filter(p => p && eventos.some(e => e.tipo === 'hitl_requested' && e.contexto === contexto &&
|
|
197
214
|
e.pedido?.id === p.id)).map(p => ({ pedido: p, estado: (0, hitl_contract_1.estadoDoPedido)(p),
|
|
198
|
-
canais: (0, hitl_presentation_1.ofertaDoPedido)(p, [opcoes.host]), prazoLocal: (0, hitl_presentation_1.prazoLocalDoPedido)(p) }));
|
|
215
|
+
canais: (0, hitl_presentation_1.ofertaDoPedido)(p, opcoes.host === 'grok' ? [] : [opcoes.host]), prazoLocal: (0, hitl_presentation_1.prazoLocalDoPedido)(p) }));
|
|
199
216
|
};
|
|
200
217
|
const fases = (id) => {
|
|
201
218
|
thread(id);
|
|
@@ -334,6 +351,8 @@ function criarServidorMcp(opcoes) {
|
|
|
334
351
|
function registrarTool(nome, config, executar) {
|
|
335
352
|
if (opcoes.threadId && ['ork_thread_new', 'ork_phase_run', 'ork_request_decision', 'ork_request_master_note', 'ork_preflight'].includes(nome))
|
|
336
353
|
return;
|
|
354
|
+
if (doGrok && !doGrok.has(nome))
|
|
355
|
+
return;
|
|
337
356
|
const entrada = config.inputSchema.extend({ projeto: campoProjeto.optional() });
|
|
338
357
|
const schema = converterSchema(entrada, { $refStrategy: 'none' });
|
|
339
358
|
ferramentas.set(nome, { tool: { name: nome, description: config.description, annotations: config.annotations,
|
|
@@ -347,6 +366,7 @@ function criarServidorMcp(opcoes) {
|
|
|
347
366
|
}
|
|
348
367
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: [...ferramentas.values()].map(f => f.tool) }));
|
|
349
368
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request, extra) => {
|
|
369
|
+
opcoes.emCurso?.(1);
|
|
350
370
|
try {
|
|
351
371
|
const f = ferramentas.get(request.params.name);
|
|
352
372
|
if (!f)
|
|
@@ -358,12 +378,16 @@ function criarServidorMcp(opcoes) {
|
|
|
358
378
|
return { ...resposta(e.recusa), isError: true };
|
|
359
379
|
return { ...resposta({ erro: e.message }), isError: true };
|
|
360
380
|
}
|
|
381
|
+
finally {
|
|
382
|
+
opcoes.emCurso?.(-1);
|
|
383
|
+
}
|
|
361
384
|
});
|
|
362
385
|
const conexaoLocal = (0, node_crypto_1.randomUUID)();
|
|
363
386
|
// RM-059 (F9, G3): a caixa de saida do Mensageiro de Sessoes so existe no servidor do dono do Claude Code, na memoria:
|
|
364
387
|
// a resposta a uma sessao claude-bg que entra pelo dialogo deste servidor sai por ela, e o texto nunca vai a disco.
|
|
365
388
|
const caixa = opcoes.host === 'claude-code' && !opcoes.threadId ? (0, entrega_por_mod_1.novaCaixaDeSaida)() : null;
|
|
366
|
-
|
|
389
|
+
// RM-067 (F4b, G5): o headless do grok nao tem dialogo, e a sessao filha nao pede decisao nem nota: sem ingresso local.
|
|
390
|
+
const ingresso = opcoes.host === 'grok' ? null : (0, hitl_local_1.criarIngressoLocal)(raiz, { host: opcoes.host, connectionId: conexaoLocal }, async (pedido, signal) => {
|
|
367
391
|
carregar();
|
|
368
392
|
thread(pedido.thread);
|
|
369
393
|
// D12: pergunta nativa que aceita texto NAO vira menu. Um menu sobre pergunta aberta
|
|
@@ -388,14 +412,14 @@ function criarServidorMcp(opcoes) {
|
|
|
388
412
|
}, { caixa });
|
|
389
413
|
// RM-059 (fatia F8, T8.1): a nota do MASTER pelo mesmo ingresso local. O formulario e fixo (a nota de 0 a 5 e o
|
|
390
414
|
// porque); sem a capacidade de formulario no cliente, a recusa vem antes de qualquer escrita.
|
|
391
|
-
const ingressoDaNota = (0, master_nota_local_1.criarIngressoDaNota)(raiz, { host: opcoes.host, connectionId: conexaoLocal }, async (apresentacao, signal) => {
|
|
415
|
+
const ingressoDaNota = opcoes.host === 'grok' ? null : (0, master_nota_local_1.criarIngressoDaNota)(raiz, { host: opcoes.host, connectionId: conexaoLocal }, async (apresentacao, signal) => {
|
|
392
416
|
carregar();
|
|
393
417
|
thread(apresentacao.thread);
|
|
394
418
|
const r = await server.elicitInput({ mode: 'form', message: apresentacao.mensagem,
|
|
395
419
|
requestedSchema: apresentacao.esquema }, { signal, timeout: 300000 });
|
|
396
420
|
return r.action === 'accept' ? { action: 'accept', content: r.content } : { action: r.action };
|
|
397
421
|
}, () => Boolean(server.getClientCapabilities()?.elicitation?.form));
|
|
398
|
-
server.onclose = () => { ingresso
|
|
422
|
+
server.onclose = () => { ingresso?.fechar(); ingressoDaNota?.fechar(); };
|
|
399
423
|
(0, company_brain_mcp_1.registerBrainTools)(registrarTool, carregar, thread, opcoes.brainWrites ?? []);
|
|
400
424
|
(0, mcp_experiencia_1.registrarConsultasExperiencia)(registrarTool, { raiz, carregar, transporte: opcoes.transporteShip ?? 'github-ssh' });
|
|
401
425
|
// RM-026 K7 (fatia 2): o conhecimento escrito, só leitura, do projeto fixado; também na sessão filha vinculada.
|
|
@@ -595,16 +619,18 @@ function criarServidorMcp(opcoes) {
|
|
|
595
619
|
livre(threadId);
|
|
596
620
|
return resposta((0, hitl_gates_1.abrirPedidoGate)(raiz, threadId, motivo));
|
|
597
621
|
});
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
622
|
+
if (ingresso)
|
|
623
|
+
registrarTool('ork_request_decision', { description: 'Apresenta pedido existente ao dono por dialogo nativo. Somente IDs; nunca forneca resposta nos argumentos.',
|
|
624
|
+
inputSchema: daDecisao, annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, pedidoId }, extra) => {
|
|
625
|
+
thread(threadId);
|
|
626
|
+
return resposta(await ingresso.solicitar(threadId, pedidoId, extra.signal));
|
|
627
|
+
});
|
|
628
|
+
if (ingressoDaNota)
|
|
629
|
+
registrarTool('ork_request_master_note', { description: 'Pede ao dono, pelo dialogo nativo do host, a nota de 0 a 5 e o porque de uma entrega. Somente o threadId; nunca forneca nota nem porque nos argumentos.',
|
|
630
|
+
inputSchema: daThread, annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId }, extra) => {
|
|
631
|
+
thread(threadId);
|
|
632
|
+
return resposta(await ingressoDaNota.solicitar(threadId, extra.signal));
|
|
633
|
+
});
|
|
608
634
|
// RM-059 (F9, T9.1): o Mensageiro de Sessoes nas duas pontas. Nenhuma das duas entra no --allowedTools do modelo (D8):
|
|
609
635
|
// quem chama e o mod ork-mensageiro, e nenhuma responde, aprova ou abre pedido.
|
|
610
636
|
if (caixa)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.branchRegistradaDaEntrega = branchRegistradaDaEntrega;
|
|
4
|
+
exports.mergesDasEntregasNaBase = mergesDasEntregasNaBase;
|
|
5
|
+
/**
|
|
6
|
+
* Reconhecimento unico do merge que entrega uma thread na linha de primeiro pai da base.
|
|
7
|
+
*
|
|
8
|
+
* A forja pode preservar o titulo `ship(<thread>)` no assunto ou usar sua mensagem padrao.
|
|
9
|
+
* Nos formatos padrao, a branch e o vinculo: ela precisa ser exatamente a branch registrada
|
|
10
|
+
* para a thread. O fallback pela convencao existe para o `docs verificar` no CI, que nao tem
|
|
11
|
+
* `.orkastery/`, e fecha o id antes de aceitar o sufixo da fase (`ork-abc` nao casa `ork-abcd`).
|
|
12
|
+
*/
|
|
13
|
+
const branch_de_estado_1 = require("./branch-de-estado");
|
|
14
|
+
const ledger_1 = require("./ledger");
|
|
15
|
+
const thread_1 = require("./thread");
|
|
16
|
+
const util_1 = require("./util");
|
|
17
|
+
/** A branch da thread como foi registrada, preferindo o evento especifico da worktree. */
|
|
18
|
+
function branchRegistradaDaEntrega(raiz, thread) {
|
|
19
|
+
try {
|
|
20
|
+
const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread));
|
|
21
|
+
const worktree = [...eventos].reverse().find((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.worktreeCriada && (0, branch_de_estado_1.branchValida)(e.branch));
|
|
22
|
+
if (worktree)
|
|
23
|
+
return String(worktree.branch);
|
|
24
|
+
const criada = [...eventos].reverse().find((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.threadCriada);
|
|
25
|
+
const base = criada?.base;
|
|
26
|
+
if (base && typeof base === 'object' && !Array.isArray(base)) {
|
|
27
|
+
const branch = base.branch;
|
|
28
|
+
if ((0, branch_de_estado_1.branchValida)(branch))
|
|
29
|
+
return branch;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch { /* checkout de CI ou thread sem estado local */ }
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const branchConvencionalDaThread = (branch, thread) => {
|
|
36
|
+
const prefixo = `ork/${thread}`;
|
|
37
|
+
return branch === prefixo || branch.startsWith(`${prefixo}-`);
|
|
38
|
+
};
|
|
39
|
+
function threadDoAssunto(assunto, entregas, base) {
|
|
40
|
+
const ship = /^ship\(([^)]+)\)/.exec(assunto);
|
|
41
|
+
if (ship?.[1])
|
|
42
|
+
return ship[1];
|
|
43
|
+
const github = /^Merge pull request #[1-9][0-9]* from [^/\s]+\/(\S+)$/.exec(assunto);
|
|
44
|
+
const gitlab = /^Merge branch '(.+)' into '(.+)'$/.exec(assunto);
|
|
45
|
+
const branch = github?.[1] ?? (gitlab?.[2] === base ? gitlab[1] : null);
|
|
46
|
+
if (!branch)
|
|
47
|
+
return null;
|
|
48
|
+
return entregas.find((entrega) => entrega.branch === null
|
|
49
|
+
? branchConvencionalDaThread(branch, entrega.thread)
|
|
50
|
+
: branch === entrega.branch)?.thread ?? null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Merges das entregas na base, em ordem do git log (mais novo primeiro por omissao).
|
|
54
|
+
*
|
|
55
|
+
* O assunto e lido por `%s`, portanto uma citacao somente no corpo nao entra. `--first-parent`
|
|
56
|
+
* tira commits da branch lateral. O segundo pai continua opcional no retorno para preservar a
|
|
57
|
+
* recusa tipada `entrega.sem-vinculo` de squash/rebase quando a CI e obrigatoria.
|
|
58
|
+
*/
|
|
59
|
+
function mergesDasEntregasNaBase(raiz, refBase, base, entregas, reverse = false) {
|
|
60
|
+
const saida = new Map(entregas.map((e) => [e.thread, []]));
|
|
61
|
+
if (!(0, branch_de_estado_1.branchValida)(refBase) || !(0, branch_de_estado_1.branchValida)(base))
|
|
62
|
+
return saida;
|
|
63
|
+
const args = ['log', refBase, '--first-parent', '--format=%H%x09%P%x09%cI%x09%s', ...(reverse ? ['--reverse'] : []), '--'];
|
|
64
|
+
const r = (0, util_1.exec)('git', args, raiz, 60000);
|
|
65
|
+
if (!r.ok)
|
|
66
|
+
return saida;
|
|
67
|
+
for (const linha of r.stdout.split('\n')) {
|
|
68
|
+
const [sha, pais, em, assunto] = linha.split('\t');
|
|
69
|
+
if (!(0, branch_de_estado_1.shaValido)(sha) || typeof assunto !== 'string')
|
|
70
|
+
continue;
|
|
71
|
+
const thread = threadDoAssunto(assunto, entregas, base);
|
|
72
|
+
if (!thread)
|
|
73
|
+
continue;
|
|
74
|
+
const segundo = (pais ?? '').split(' ')[1] ?? null;
|
|
75
|
+
const ms = Date.parse(em ?? '');
|
|
76
|
+
const merges = saida.get(thread) ?? [];
|
|
77
|
+
merges.push({
|
|
78
|
+
mergeSha: sha,
|
|
79
|
+
headSha: segundo && (0, branch_de_estado_1.shaValido)(segundo) ? segundo : null,
|
|
80
|
+
em: Number.isFinite(ms) ? new Date(ms).toISOString() : null,
|
|
81
|
+
});
|
|
82
|
+
saida.set(thread, merges);
|
|
83
|
+
}
|
|
84
|
+
return saida;
|
|
85
|
+
}
|
package/dist/network-roadmap.js
CHANGED
|
@@ -454,7 +454,7 @@ function maquinasDoPanorama(retratos, local, ctx, lacunas) {
|
|
|
454
454
|
const idadeMs = Math.max(0, agora - Date.parse(m.publicadoEm));
|
|
455
455
|
const semBatida = idadeMs > fabrica_estado_1.LIMIAR_SEM_BATIDA_MS;
|
|
456
456
|
if (semBatida) {
|
|
457
|
-
lacunas.push(lacuna('maquina.sem-batida', 'fabrica', m.maquina, `${m.maquina} sem retrato novo há ${(0, horario_1.duracaoCurta)(Math.floor(idadeMs / 60000))} (último em ${(0, horario_1.formatarDataHora)(m.publicadoEm, { fuso: ctx.fuso })}): ` +
|
|
457
|
+
lacunas.push(lacuna('maquina.sem-batida', 'fabrica', m.maquina, `${m.maquina} sem retrato novo há ${(0, horario_1.duracaoCurta)(Math.floor(idadeMs / 60000))} (último em ${(0, horario_1.formatarDataHora)(m.publicadoEm, { fuso: ctx.fuso, agora: ctx.quando })}): ` +
|
|
458
458
|
'as threads dela podem ter andado', `confira a ${m.maquina}: ela publica ao criar thread, despachar fase, entregar e a cada batida do pulse`));
|
|
459
459
|
}
|
|
460
460
|
saida.push({ maquina: m.maquina, por: m.por, publicadoEm: m.publicadoEm, idadeMin: Math.floor(idadeMs / 60000), semBatida,
|
|
@@ -632,7 +632,7 @@ function lerProjetoDoClone(p, geral) {
|
|
|
632
632
|
fontes.push({ parte, origem: 'clone', onde, ref: nome, commit: r.ponta, dataDoCommit, lidoEm: ctx.quando, atualizado: r.atualizado, existe: true });
|
|
633
633
|
if (!r.atualizado) {
|
|
634
634
|
lacunas.push(lacuna(`${parte}.sem-leitura`, parte, onde, `sem leitura nova de ${onde}${porque(r.tentou)}; ` +
|
|
635
|
-
`vale a última cópia desta máquina, commit ${r.ponta.slice(0, 7)} de ${(0, horario_1.formatarDataHora)(dataDoCommit, { fuso: ctx.fuso })}`, correcao()));
|
|
635
|
+
`vale a última cópia desta máquina, commit ${r.ponta.slice(0, 7)} de ${(0, horario_1.formatarDataHora)(dataDoCommit, { fuso: ctx.fuso, agora: ctx.quando })}`, correcao()));
|
|
636
636
|
}
|
|
637
637
|
return r.ponta;
|
|
638
638
|
}
|
|
@@ -1033,15 +1033,15 @@ function descreverProjeto(x) {
|
|
|
1033
1033
|
function linhaDaFonte(f, quando, fuso) {
|
|
1034
1034
|
const m = (0, locale_1.msg)().network.roadmap;
|
|
1035
1035
|
const parte = m.fonteParte(f.parte);
|
|
1036
|
-
const lido = f.lidoEm === quando ? m.lidoAgora : m.lidoEm((0, horario_1.formatarDataHora)(f.lidoEm, { fuso }));
|
|
1036
|
+
const lido = f.lidoEm === quando ? m.lidoAgora : m.lidoEm((0, horario_1.formatarDataHora)(f.lidoEm, { fuso, agora: quando }));
|
|
1037
1037
|
if (f.origem === 'estado-local')
|
|
1038
1038
|
return m.fonteLocal(parte, f.onde, lido);
|
|
1039
1039
|
if (!f.existe)
|
|
1040
1040
|
return m.fonteInexistente(parte, f.onde, lido);
|
|
1041
1041
|
const alvo = f.parte === 'roadmap' ? m.alvoDoRoadmap(f.onde) : f.onde;
|
|
1042
|
-
return m.fonteCommit(parte, alvo, (f.commit ?? '').slice(0, 7), (0, horario_1.formatarDataHora)(f.dataDoCommit, { fuso }), f.atualizado ? lido : m.ultimaCopia);
|
|
1042
|
+
return m.fonteCommit(parte, alvo, (f.commit ?? '').slice(0, 7), (0, horario_1.formatarDataHora)(f.dataDoCommit, { fuso, agora: quando }), f.atualizado ? lido : m.ultimaCopia);
|
|
1043
1043
|
}
|
|
1044
|
-
function linhasDasMaquinas(x, fuso) {
|
|
1044
|
+
function linhasDasMaquinas(x, quando, fuso) {
|
|
1045
1045
|
const m = (0, locale_1.msg)().network.roadmap;
|
|
1046
1046
|
if (x.maquinas === null)
|
|
1047
1047
|
return [m.maquinasNaoLidas];
|
|
@@ -1051,11 +1051,11 @@ function linhasDasMaquinas(x, fuso) {
|
|
|
1051
1051
|
const quem = `${m.maquina}${m.estaMaquina ? (0, locale_1.msg)().network.roadmap.estaMaquina : ''}`;
|
|
1052
1052
|
// Fatia 3: a maquina so da rede por pessoa; as threads dela neste projeto nao foram lidas.
|
|
1053
1053
|
if (m.origem === 'rede') {
|
|
1054
|
-
return [(0, locale_1.msg)().network.roadmap.maquinaSoNaRede(quem, (0, horario_1.formatarDataHora)(m.publicadoEm, { fuso }), (0, horario_1.duracaoCurta)(m.idadeMin), m.semBatida, fabrica_estado_1.BRANCH_DA_FABRICA)];
|
|
1054
|
+
return [(0, locale_1.msg)().network.roadmap.maquinaSoNaRede(quem, (0, horario_1.formatarDataHora)(m.publicadoEm, { fuso, agora: quando }), (0, horario_1.duracaoCurta)(m.idadeMin), m.semBatida, fabrica_estado_1.BRANCH_DA_FABRICA)];
|
|
1055
1055
|
}
|
|
1056
1056
|
const rm = (0, locale_1.msg)().network.roadmap;
|
|
1057
1057
|
const batida = m.origem === 'estado-local' ? rm.estadoLocalAgora
|
|
1058
|
-
: rm.retrato((0, horario_1.formatarDataHora)(m.publicadoEm, { fuso }), (0, horario_1.duracaoCurta)(m.idadeMin), m.semBatida);
|
|
1058
|
+
: rm.retrato((0, horario_1.formatarDataHora)(m.publicadoEm, { fuso, agora: quando }), (0, horario_1.duracaoCurta)(m.idadeMin), m.semBatida);
|
|
1059
1059
|
const cabeca = rm.resumoMaquina(quem, m.ativas.length, m.entreguesSemMaster, batida);
|
|
1060
1060
|
// RM-037 (rm037noite, defeito 4): o runtime e o modelo de cada thread, quando o retrato os traz.
|
|
1061
1061
|
return [cabeca, ...m.ativas.map((t) => ` ${t.id} · ${t.modo} · ${t.fase} · ${t.roadmap ?? rm.semItem}` +
|
|
@@ -1063,30 +1063,34 @@ function linhasDasMaquinas(x, fuso) {
|
|
|
1063
1063
|
(t.esperaVoce ? rm.esperaVoce(t.pergunta ?? rm.veredito) : ''))];
|
|
1064
1064
|
});
|
|
1065
1065
|
}
|
|
1066
|
-
function linhasDasReservas(x, fuso) {
|
|
1066
|
+
function linhasDasReservas(x, quando, fuso) {
|
|
1067
1067
|
const m = (0, locale_1.msg)().network.roadmap;
|
|
1068
1068
|
if (x.reservas === null)
|
|
1069
1069
|
return [m.reservasNaoLidas];
|
|
1070
1070
|
if (x.reservas.length === 0)
|
|
1071
1071
|
return [m.nenhumaReserva];
|
|
1072
|
-
return x.reservas.map((r) => m.reserva(r.item, r.maquina, r.thread ?? m.semThread, (0, horario_1.formatarDataHora)(r.desdeEm, { fuso })));
|
|
1072
|
+
return x.reservas.map((r) => m.reserva(r.item, r.maquina, r.thread ?? m.semThread, (0, horario_1.formatarDataHora)(r.desdeEm, { fuso, agora: quando })));
|
|
1073
1073
|
}
|
|
1074
1074
|
/** Fatia 3: a casa da rede por pessoa e as maquinas dela, com a batida e os projetos que declaram. */
|
|
1075
1075
|
function linhasDaRede(r, quando, fuso) {
|
|
1076
1076
|
const x = (0, locale_1.msg)().network.roadmap;
|
|
1077
|
-
const lido = r.lidoEm === quando ? x.redeLidaAgora : x.redeLidaEm((0, horario_1.formatarDataHora)(r.lidoEm, { fuso }));
|
|
1077
|
+
const lido = r.lidoEm === quando ? x.redeLidaAgora : x.redeLidaEm((0, horario_1.formatarDataHora)(r.lidoEm, { fuso, agora: quando }));
|
|
1078
1078
|
const casa = !r.casa ? x.casaAusente
|
|
1079
1079
|
: r.atualizado === null ? x.casaNaoLida(r.casa)
|
|
1080
1080
|
: x.casaLida(r.casa, r.ponta ? r.ponta.slice(0, 7) : x.semCommit, r.atualizado ? lido : x.casaUltimaCopia);
|
|
1081
1081
|
if (r.membros.length === 0)
|
|
1082
1082
|
return [casa, x.nenhumRetrato];
|
|
1083
|
-
return [casa, ...r.membros.map((m) => x.membro(m.maquina, m.estaMaquina ? x.estaMaquina : '', (0, horario_1.formatarDataHora)(m.publicadoEm, { fuso }), m.idadeMin === null ? x.batidaIlegivel : x.idade((0, horario_1.duracaoCurta)(m.idadeMin)), m.semBatida, m.versaoOrk ? x.versao(m.versaoOrk) : '', m.projetos.length ? x.projetos(m.projetos.join(', ')) : x.nenhumProjeto))];
|
|
1083
|
+
return [casa, ...r.membros.map((m) => x.membro(m.maquina, m.estaMaquina ? x.estaMaquina : '', (0, horario_1.formatarDataHora)(m.publicadoEm, { fuso, agora: quando }), m.idadeMin === null ? x.batidaIlegivel : x.idade((0, horario_1.duracaoCurta)(m.idadeMin)), m.semBatida, m.versaoOrk ? x.versao(m.versaoOrk) : '', m.projetos.length ? x.projetos(m.projetos.join(', ')) : x.nenhumProjeto))];
|
|
1084
1084
|
}
|
|
1085
1085
|
const linhaDaLacuna = (l) => {
|
|
1086
1086
|
const m = (0, locale_1.msg)().network.roadmap;
|
|
1087
1087
|
return m.lacuna(l.tipo, l.alvo ? ` (${l.alvo})` : '', m.lacunaDetalhe(l.tipo, l.parte, l.alvo, l.detalhe), m.lacunaCorrecao(l.tipo, l.correcao));
|
|
1088
1088
|
};
|
|
1089
|
-
/**
|
|
1089
|
+
/**
|
|
1090
|
+
* O texto de `ork network roadmap`: o consultado e o nao consultado no alto, e cada parte com a fonte e a hora. RM-074 (F4):
|
|
1091
|
+
* as datas omitem o ano pelo ano da leitura (`consultadoEm`), nao pelo relogio de quem le o texto: o mesmo panorama da o
|
|
1092
|
+
* mesmo texto em qualquer dia, e o retrato pt-BR F3c nao fica vermelho na virada do ano.
|
|
1093
|
+
*/
|
|
1090
1094
|
function textoDoPanoramaDaRede(p) {
|
|
1091
1095
|
const m = (0, locale_1.msg)().network.roadmap;
|
|
1092
1096
|
if (p.contrato !== exports.CONTRATO_PANORAMA_DA_REDE)
|
|
@@ -1108,8 +1112,8 @@ function textoDoPanoramaDaRede(p) {
|
|
|
1108
1112
|
// Fatia 2 do ensaio (P7): o fuso ja sai no fim do panorama (e no bloco, quando difere): sem a legenda do status.
|
|
1109
1113
|
linhas.push(x.roadmap ? (0, roadmap_status_1.textoDoStatusDoRoadmap)(x.roadmap, fuso, { legenda: false })
|
|
1110
1114
|
: m.roadmapNaoLido(x.projeto.nome, x.lacunas.map((l) => l.tipo).filter((t) => t !== 'projeto.sem-clone').join(', ') || m.semFonte));
|
|
1111
|
-
linhas.push('', m.threadsPorMaquina, ...linhasDasMaquinas(x, fuso));
|
|
1112
|
-
linhas.push('', m.reservas, ...linhasDasReservas(x, fuso));
|
|
1115
|
+
linhas.push('', m.threadsPorMaquina, ...linhasDasMaquinas(x, p.consultadoEm, fuso));
|
|
1116
|
+
linhas.push('', m.reservas, ...linhasDasReservas(x, p.consultadoEm, fuso));
|
|
1113
1117
|
linhas.push('', m.fontes, ...(x.fontes.length ? x.fontes.map((f) => linhaDaFonte(f, p.consultadoEm, fuso)) : [m.nenhumaFonte]));
|
|
1114
1118
|
linhas.push('', m.lacunas, ...(x.lacunas.length ? x.lacunas.map(linhaDaLacuna) : [m.nenhumaLacuna]));
|
|
1115
1119
|
// A legenda e a da hora da leitura, como os horarios do panorama: com a de agora, o horario de verao mudava o texto.
|