@orkastery/cli 0.2.0 → 0.4.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/LICENSE +1 -1
- package/README.md +86 -65
- package/adapters/README.md +30 -15
- package/adapters/claude-code/.claude-plugin/plugin.json +11 -5
- package/adapters/claude-code/README.md +110 -8
- package/adapters/claude-code/commands/check.md +4 -3
- package/adapters/claude-code/commands/goal.md +3 -2
- package/adapters/claude-code/commands/master.md +3 -2
- package/adapters/claude-code/commands/onboarding.md +21 -0
- package/adapters/claude-code/commands/ork.md +99 -27
- package/adapters/claude-code/hooks/hooks.json +6 -1
- package/adapters/claude-code/hooks/ork-guard.js +1 -1
- package/adapters/claude-code/hooks/ork-sensor.js +66 -0
- package/adapters/codex/skills/ork/SKILL.md +57 -0
- package/adapters/hermes/README.md +161 -0
- package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
- package/adapters/hermes/bin/ork-brain.sh +4 -0
- package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
- package/adapters/hermes/bin/ork-maestro.sh +6 -0
- package/adapters/hermes/bin/ork-master-enviar.py +84 -0
- package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
- package/adapters/hermes/hermes.plugin.json +24 -4
- package/adapters/hermes/hitl-ingress/__init__.py +356 -0
- package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
- package/adapters/openclaw/README.md +136 -27
- package/adapters/openclaw/bin/ork-brain.sh +4 -0
- package/adapters/openclaw/construir.sh +19 -0
- package/adapters/openclaw/dist/hitl-ingress.js +199 -0
- package/adapters/openclaw/dist/index.js +437 -0
- package/adapters/openclaw/openclaw.plugin.json +39 -134
- package/adapters/openclaw/package.json +26 -0
- package/adapters/openclaw/src/hitl-ingress.ts +180 -0
- package/adapters/openclaw/src/index.ts +460 -0
- package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
- package/adapters/openclaw/tsconfig.json +15 -0
- package/assets/docs/markdownlint-cli2.jsonc +22 -0
- package/assets/docs/padroes/documentacao-de-produto.md +133 -0
- package/assets/docs/padroes/roadmap-de-produto.md +98 -0
- package/assets/docs/produto/README.md +14 -0
- package/assets/docs/produto/_modelo-feature.md +59 -0
- package/assets/docs/roadmap/README.md +14 -0
- package/assets/docs/roadmap/_modelo-item.md +73 -0
- package/assets/orkmind-native-schema.json +32 -0
- package/assets/orkmind_bridge.py +357 -0
- package/assets/orkmind_fixture.py +67 -0
- package/assets/orkmind_prospective.py +138 -0
- package/assets/reference-tariffs-i07.json +23 -0
- package/dist/adapters/claude-bg.js +488 -39
- package/dist/adapters/codex-controller-sensor.js +449 -0
- package/dist/adapters/codex-controller-worker.js +361 -0
- package/dist/adapters/codex-controller.js +252 -0
- package/dist/adapters/codex-events.js +205 -0
- package/dist/adapters/codex-question.js +26 -0
- package/dist/adapters/codex-runner.js +133 -0
- package/dist/adapters/codex.js +394 -0
- package/dist/agents-md.js +84 -0
- package/dist/auditoria.js +12 -9
- package/dist/auditrun.js +5 -4
- package/dist/board.js +174 -23
- package/dist/branch-de-estado.js +136 -0
- package/dist/canarios-hitl.js +177 -0
- package/dist/canarios-i43.js +543 -0
- package/dist/canarios-pulse.js +147 -0
- package/dist/canarios-sensores.js +129 -0
- package/dist/canarios.js +111 -2
- package/dist/catalogo.js +9 -0
- package/dist/ci.js +223 -0
- package/dist/ciclos.js +2 -1
- package/dist/claim-lint.js +64 -0
- package/dist/claims.js +60 -0
- package/dist/company-brain-capture.js +195 -0
- package/dist/company-brain-cli.js +123 -0
- package/dist/company-brain-client.js +61 -0
- package/dist/company-brain-contract.js +166 -0
- package/dist/company-brain-journal.js +192 -0
- package/dist/company-brain-mcp.js +33 -0
- package/dist/company-brain-migration.js +60 -0
- package/dist/company-brain-source.js +177 -0
- package/dist/company-brain-worker.js +18 -0
- package/dist/conducao-texto.js +61 -0
- package/dist/conducao.js +876 -0
- package/dist/contrato-publico.js +39 -0
- package/dist/creation-operation-store.js +251 -0
- package/dist/creation-operation.js +148 -0
- package/dist/decisao-autonoma.js +183 -0
- package/dist/delegation.js +79 -0
- package/dist/demo.js +120 -0
- package/dist/docs.js +828 -0
- package/dist/doctor.js +184 -25
- package/dist/entrega-pr.js +117 -0
- package/dist/escopo-escrita.js +71 -0
- package/dist/estado-thread.js +222 -0
- package/dist/evalrunner.js +12 -0
- package/dist/fabrica-estado.js +329 -0
- package/dist/fabrica-publicar.js +76 -0
- package/dist/fix.js +22 -1
- package/dist/gates.js +59 -11
- package/dist/handoff.js +39 -23
- package/dist/hitl-canais.js +333 -0
- package/dist/hitl-classificacao.js +131 -0
- package/dist/hitl-contract.js +465 -0
- package/dist/hitl-estado.js +136 -0
- package/dist/hitl-gates.js +554 -0
- package/dist/hitl-ingress-receipt.js +382 -0
- package/dist/hitl-local-atestado.js +57 -0
- package/dist/hitl-local-receipt.js +328 -0
- package/dist/hitl-local.js +143 -0
- package/dist/hitl-lock.js +139 -0
- package/dist/hitl-lote.js +223 -0
- package/dist/hitl-native-offer.js +97 -0
- package/dist/hitl-native.js +65 -0
- package/dist/hitl-presentation.js +209 -0
- package/dist/hitl-public-receipt.js +176 -0
- package/dist/hitl-resumo.js +209 -0
- package/dist/hitl-sessions.js +475 -0
- package/dist/hitl.js +711 -0
- package/dist/horario.js +269 -0
- package/dist/hosts.js +198 -22
- package/dist/index.js +1741 -94
- package/dist/indice.js +99 -0
- package/dist/init.js +28 -3
- package/dist/integracoes-locais.js +17 -0
- package/dist/leases.js +65 -21
- package/dist/ledger-stats.js +272 -0
- package/dist/ledger.js +109 -2
- package/dist/licoes.js +221 -0
- package/dist/liveness.js +218 -0
- package/dist/maestro-actions.js +51 -0
- package/dist/maestro-authority.js +152 -0
- package/dist/maestro-cli.js +97 -0
- package/dist/maestro-contract.js +55 -0
- package/dist/maestro-discovery.js +132 -0
- package/dist/maestro-runtime.js +268 -0
- package/dist/maestro-snapshot.js +86 -0
- package/dist/maestro-sources.js +224 -0
- package/dist/manifest.js +165 -6
- package/dist/maquina.js +102 -0
- package/dist/master-audit.js +101 -0
- package/dist/master-batch.js +43 -0
- package/dist/master-digest.js +149 -0
- package/dist/master-migracao.js +155 -0
- package/dist/master.js +361 -77
- package/dist/mcp-artifacts.js +234 -0
- package/dist/mcp-git.js +433 -0
- package/dist/mcp-install.js +310 -0
- package/dist/mcp-maestro.js +25 -0
- package/dist/mcp-server.js +469 -0
- package/dist/mcp-ship.js +436 -0
- package/dist/mcp-verify.js +173 -0
- package/dist/memoria-humana.js +207 -0
- package/dist/memoria.js +314 -78
- package/dist/memory-migration.js +279 -0
- package/dist/memory-prospective.js +148 -0
- package/dist/modos-migracao.js +191 -0
- package/dist/modos.js +151 -15
- package/dist/monitor-lock.js +110 -0
- package/dist/objective.js +449 -0
- package/dist/ocupacao.js +267 -0
- package/dist/onboarding.js +303 -0
- package/dist/orkmind.js +389 -90
- package/dist/orquestracao.js +96 -69
- package/dist/phase.js +612 -151
- package/dist/playbook-capabilities.js +150 -0
- package/dist/playbook-contracts.js +188 -0
- package/dist/policies.js +72 -0
- package/dist/portfolio-context.js +61 -0
- package/dist/portfolio.js +180 -0
- package/dist/preflight.js +207 -0
- package/dist/process-audit.js +112 -0
- package/dist/project-state.js +93 -0
- package/dist/prompts.js +25 -5
- package/dist/prova-minima.js +112 -0
- package/dist/pulse-cadencia.js +163 -0
- package/dist/pulse-consentimento.js +260 -0
- package/dist/pulse-delivery.js +323 -0
- package/dist/pulse-resposta.js +542 -0
- package/dist/pulse.js +262 -0
- package/dist/ratelimit.js +35 -2
- package/dist/recall.js +80 -3
- package/dist/redacao-saida.js +45 -0
- package/dist/redacao-url.js +66 -0
- package/dist/retry.js +640 -118
- package/dist/roadmap-reservas.js +243 -0
- package/dist/runtime-ambiente.js +38 -0
- package/dist/runtime-context.js +215 -0
- package/dist/runtime-profiles.js +869 -0
- package/dist/runtimes.js +103 -0
- package/dist/sandbox.js +9 -0
- package/dist/session-events.js +203 -0
- package/dist/session-watcher-claude.js +637 -0
- package/dist/session-watcher.js +700 -0
- package/dist/sessoes-adopt.js +154 -0
- package/dist/sessoes-inventario.js +159 -0
- package/dist/sessoes.js +16 -35
- package/dist/setup.js +691 -0
- package/dist/ship.js +168 -19
- package/dist/slug.js +1 -1
- package/dist/thread-close.js +115 -0
- package/dist/thread.js +142 -28
- package/dist/tokens.js +1 -1
- package/dist/util.js +4 -2
- package/dist/verify-sandbox.js +265 -0
- package/dist/verify.js +270 -25
- package/dist/versao.js +60 -0
- package/dist/worktree.js +31 -2
- package/dist/write-activation.js +291 -0
- package/dist/yaml.js +5 -1
- package/eval/casos/master-metrics.json +1 -1
- package/eval/casos/onboarding.json +102 -0
- package/eval/casos/orkastery-bootstrap.json +37 -3
- package/eval/casos/scope-check-capability-map.json +45 -7
- package/eval/casos/ship-release.json +3 -3
- package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
- package/eval/fixtures/b2-master-log/caso.json +1 -1
- package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
- package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
- package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
- package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
- package/eval/fixtures/fx-codex-dry/caso.json +18 -0
- package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
- package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
- package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
- package/eval/fixtures/fx-happy/caso.json +6 -4
- package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
- package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
- package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
- package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
- package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
- package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
- package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
- package/eval/fixtures/fx-omnicanal/caso.json +17 -0
- package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
- package/monitor/company-brain.cjs +17 -0
- package/monitor/pulse-scope.cjs +45 -0
- package/monitor/pulse.cron +18 -0
- package/monitor/varredura-pulse.sh +27 -0
- package/package.json +28 -7
- package/references/definition-of-done.md +2 -2
- package/schemas/claims.schema.json +25 -0
- package/schemas/company-brain.schema.json +1158 -0
- package/schemas/creation-operation.schema.json +365 -0
- package/schemas/maestro-snapshot.schema.json +2716 -0
- package/skills/README.md +3 -3
- package/skills/core/onboarding/SKILL.md +50 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
- package/skills/core/thread-state/SKILL.md +3 -1
- package/skills/governance/decision-triage/SKILL.md +4 -4
- package/skills/governance/narrative-guardian/SKILL.md +1 -1
- package/skills/governance/roadmap-keeper/SKILL.md +1 -1
- package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
- package/skills/observability/thread-tracing/SKILL.md +1 -1
- package/skills/phases/check-quality/SKILL.md +2 -2
- package/skills/phases/goal-definition/SKILL.md +1 -1
- package/skills/phases/master-metrics/SKILL.md +9 -7
- package/skills/phases/plan-specification/SKILL.md +1 -1
- package/skills/phases/ship-release/SKILL.md +1 -1
package/dist/master.js
CHANGED
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* contrato e nao mudam. "Uma entrega sem MASTER log nao aconteceu."
|
|
12
12
|
*
|
|
13
13
|
* O score e humano, de 0 a 5, com JUSTIFICATIVA OBRIGATORIA: o `ork` recusa score sem
|
|
14
|
-
* justificativa, em qualquer modo. Nos modos que nao pausam no MASTER (`#
|
|
14
|
+
* justificativa, em qualquer modo. Nos modos que nao pausam no MASTER (`#Classic`,
|
|
15
15
|
* `#Maestro`, `#Auto`) o score nao desaparece: a thread cai na fila de batch scoring,
|
|
16
|
-
* que `ork master
|
|
16
|
+
* que `ork master` lista com o indice ja derivado do ledger (I-43: a fila saiu).
|
|
17
17
|
*/
|
|
18
18
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
19
|
if (k2 === undefined) k2 = k;
|
|
@@ -49,28 +49,45 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
49
49
|
};
|
|
50
50
|
})();
|
|
51
51
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
-
exports.ORDEM_DAS_CLASSES = exports.CLASSES_DE_FALHA = exports.VERSAO_MASTER_LOG = exports.CONTRATO_MASTER_LOG = void 0;
|
|
52
|
+
exports.AUTOR_DA_OMISSAO = exports.CONTRATO_MASTER_PENDENTE = exports.ORDEM_DAS_CLASSES = exports.CLASSES_DE_FALHA = exports.VERSAO_MASTER_LOG = exports.CONTRATO_MASTER_LOG = void 0;
|
|
53
53
|
exports.parseClasse = parseClasse;
|
|
54
54
|
exports.caminhoPostmortem = caminhoPostmortem;
|
|
55
55
|
exports.caminhoMasterLog = caminhoMasterLog;
|
|
56
56
|
exports.fasesPercorridas = fasesPercorridas;
|
|
57
57
|
exports.regimeDoScore = regimeDoScore;
|
|
58
58
|
exports.entregou = entregou;
|
|
59
|
+
exports.indiceDaThread = indiceDaThread;
|
|
59
60
|
exports.exigirScoreValido = exigirScoreValido;
|
|
61
|
+
exports.autoriaHumana = autoriaHumana;
|
|
62
|
+
exports.exigirAutoriaHumana = exigirAutoriaHumana;
|
|
63
|
+
exports.masterRatificado = masterRatificado;
|
|
64
|
+
exports.preflightMaster = preflightMaster;
|
|
60
65
|
exports.registrarMaster = registrarMaster;
|
|
66
|
+
exports.proporMaster = proporMaster;
|
|
61
67
|
exports.validarMasterLog = validarMasterLog;
|
|
68
|
+
exports.validarMasterPendente = validarMasterPendente;
|
|
62
69
|
exports.lerMasterLog = lerMasterLog;
|
|
70
|
+
exports.aceitarPorOmissao = aceitarPorOmissao;
|
|
71
|
+
exports.aceitosPorOmissao = aceitosPorOmissao;
|
|
63
72
|
exports.pendentesDeScore = pendentesDeScore;
|
|
64
|
-
exports.
|
|
73
|
+
exports.tabelaDeEntregas = tabelaDeEntregas;
|
|
74
|
+
exports.aceitarPendentesPorOmissao = aceitarPendentesPorOmissao;
|
|
65
75
|
exports.textoDoMaster = textoDoMaster;
|
|
66
76
|
exports.tabelaDeClasses = tabelaDeClasses;
|
|
67
77
|
const path = __importStar(require("node:path"));
|
|
78
|
+
const node_crypto_1 = require("node:crypto");
|
|
79
|
+
const thread_close_1 = require("./thread-close");
|
|
80
|
+
const estado_thread_1 = require("./estado-thread");
|
|
68
81
|
const ledger_1 = require("./ledger");
|
|
69
82
|
const modos_1 = require("./modos");
|
|
70
83
|
const thread_1 = require("./thread");
|
|
71
84
|
const types_1 = require("./types");
|
|
72
85
|
const util_1 = require("./util");
|
|
73
86
|
const fs = __importStar(require("node:fs"));
|
|
87
|
+
const horario_1 = require("./horario");
|
|
88
|
+
const indice_1 = require("./indice");
|
|
89
|
+
const ship_1 = require("./ship");
|
|
90
|
+
const fabrica_publicar_1 = require("./fabrica-publicar");
|
|
74
91
|
/** Identificador do contrato congelado do MASTER log. */
|
|
75
92
|
exports.CONTRATO_MASTER_LOG = 'ork.master-log/v1';
|
|
76
93
|
/** Versao do contrato. Uma mudanca de contrato exige uma versao nova, nao um campo novo. */
|
|
@@ -151,11 +168,48 @@ function fasesPercorridas(raiz, id) {
|
|
|
151
168
|
}
|
|
152
169
|
/** Regime do score: `pausa` nos modos que param no MASTER, `batch` nos demais. */
|
|
153
170
|
function regimeDoScore(thread) {
|
|
171
|
+
// Ciclo sem MASTER (o `#Fast`, I-42) nao pausa no MASTER: o score, quando vier, e de lote.
|
|
172
|
+
// Sem esta guarda, uma thread #Fast entregue derrubava `ork master`, o aceite por omissao
|
|
173
|
+
// e o pulse, que listam as pendentes de score (27/09/2026).
|
|
174
|
+
if (!thread.blocos?.some((b) => b.fases.includes('MASTER')))
|
|
175
|
+
return 'batch';
|
|
154
176
|
return (0, thread_1.pausaNaThread)(thread, 'MASTER') ? 'pausa' : 'batch';
|
|
155
177
|
}
|
|
156
178
|
/** A thread ja entregou (o ledger tem `ship_done`)? */
|
|
157
179
|
function entregou(raiz, id) {
|
|
158
|
-
return (0,
|
|
180
|
+
return (0, thread_close_1.provaDeEntrega)(raiz, id) !== null;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Pergunta ao git se a entrega desta thread foi desfeita, e grava se foi. Nunca lanca.
|
|
184
|
+
*
|
|
185
|
+
* Idempotente por `revertSha` (`registrarReversaoDaEntrega`), entao pode rodar em toda
|
|
186
|
+
* consulta: a mesma reversao nao rebaixa a thread duas vezes. Git indisponivel nao
|
|
187
|
+
* derruba o MASTER; no pior caso o indice continua sendo o que o ledger ja sabia.
|
|
188
|
+
*/
|
|
189
|
+
function sincronizarReversao(raiz, id) {
|
|
190
|
+
try {
|
|
191
|
+
(0, ship_1.registrarReversaoDaEntrega)(raiz, (0, thread_1.lerThread)(raiz, id));
|
|
192
|
+
}
|
|
193
|
+
catch { /* git indisponivel nao barra o MASTER */ }
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* O indice da thread, DEPOIS de perguntar ao git se a entrega ainda esta de pe.
|
|
197
|
+
*
|
|
198
|
+
* ESTE E O PONTO UNICO por onde o MASTER calcula indice, e ele existe por causa do que
|
|
199
|
+
* o CHECK de 20/09/2026 provou com `git revert` real: o unico escritor de
|
|
200
|
+
* `rollback_done` rodava no COMECO de um `ork ship` SEGUINTE da mesma thread, e depois
|
|
201
|
+
* do MASTER nao ha ship seguinte. Uma entrega desfeita na base saia daqui como 5 de 5
|
|
202
|
+
* "sem tropeco", e `ork master --aceitar-omissao` gravava score 5 com a justificativa
|
|
203
|
+
* "sem reversao" sobre ela. Em 20 das 27 threads entregues do projeto a janela do ship
|
|
204
|
+
* seguinte nunca chegou a abrir.
|
|
205
|
+
*
|
|
206
|
+
* A regra que ficou: quem AFIRMA o numero e quem tem de conferir o fato. Por isso a
|
|
207
|
+
* deteccao roda no momento em que o indice e calculado e no momento em que a omissao e
|
|
208
|
+
* aceita, e nao so num ship futuro que quase nunca acontece.
|
|
209
|
+
*/
|
|
210
|
+
function indiceDaThread(raiz, id) {
|
|
211
|
+
sincronizarReversao(raiz, id);
|
|
212
|
+
return (0, indice_1.calcularIndice)((0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id)));
|
|
159
213
|
}
|
|
160
214
|
/**
|
|
161
215
|
* Valida o score humano ANTES de gravar qualquer coisa.
|
|
@@ -176,13 +230,17 @@ function exigirScoreValido(score, justificativa) {
|
|
|
176
230
|
* Registra o MASTER da thread: POSTMORTEM tipado, MASTER log no contrato e o score.
|
|
177
231
|
* Ao fim, a thread fecha (`status: fechada`) e o ledger ganha `master_done`.
|
|
178
232
|
*/
|
|
179
|
-
function
|
|
233
|
+
function prepararDocumentos(raiz, id, opcoes) {
|
|
180
234
|
const thread = (0, thread_1.lerThread)(raiz, id);
|
|
181
235
|
exigirScoreValido(opcoes.score, opcoes.justificativa);
|
|
182
236
|
if (thread.score && !opcoes.refazer) {
|
|
183
237
|
throw new Error(`a thread ${id} ja tem score ${thread.score.valor}/5 dado por ${thread.score.avaliadoPor} ` +
|
|
184
|
-
`em ${thread.score.avaliadoEm}; use --refazer para regravar o MASTER`);
|
|
238
|
+
`em ${(0, horario_1.formatarDataHoraRotulada)(thread.score.avaliadoEm)}; use --refazer para regravar o MASTER`);
|
|
185
239
|
}
|
|
240
|
+
(0, thread_close_1.exigirEntrega)(raiz, id);
|
|
241
|
+
// A1: o indice gravado ao lado do score sai do ledger, e o ledger so sabe da reversao
|
|
242
|
+
// se alguem perguntar ao git. Aqui e o momento em que o numero e congelado.
|
|
243
|
+
sincronizarReversao(raiz, id);
|
|
186
244
|
const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id));
|
|
187
245
|
const gatesBloqueados = eventos
|
|
188
246
|
.filter((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.gateBloqueado)
|
|
@@ -211,12 +269,17 @@ function registrarMaster(raiz, id, opcoes) {
|
|
|
211
269
|
'informada: o `ork` gravou "outra". Corrija com --classe <classe> --refazer.'
|
|
212
270
|
: 'nenhuma --classe informada e nenhum gate reprovou: o `ork` gravou "sem-falha".');
|
|
213
271
|
}
|
|
272
|
+
// I-43 (D3): o indice e DERIVADO do ledger no momento do registro, e acompanha o
|
|
273
|
+
// score como o que a maquina achava antes de o dono falar. Quando as duas existem,
|
|
274
|
+
// a nota humana e a que vale; o indice fica ao lado dela, nao no lugar.
|
|
275
|
+
const indice = (0, indice_1.calcularIndice)(eventos);
|
|
214
276
|
const score = {
|
|
215
277
|
valor: opcoes.score,
|
|
216
278
|
justificativa: opcoes.justificativa.trim(),
|
|
217
|
-
avaliadoPor:
|
|
279
|
+
avaliadoPor: opcoes.por?.trim() ?? '',
|
|
218
280
|
avaliadoEm: (0, util_1.agora)(),
|
|
219
|
-
regime: regimeDoScore(thread),
|
|
281
|
+
regime: opcoes.regime ?? regimeDoScore(thread),
|
|
282
|
+
indice: indice.valor,
|
|
220
283
|
};
|
|
221
284
|
const percorridas = fasesPercorridas(raiz, id);
|
|
222
285
|
const resumo = opcoes.resumo?.trim() ||
|
|
@@ -257,6 +320,12 @@ function registrarMaster(raiz, id, opcoes) {
|
|
|
257
320
|
avaliadoEm: score.avaliadoEm,
|
|
258
321
|
classesDeFalha: classes,
|
|
259
322
|
resumo,
|
|
323
|
+
regime: score.regime,
|
|
324
|
+
indice: {
|
|
325
|
+
valor: indice.valor,
|
|
326
|
+
base: indice.base,
|
|
327
|
+
parcelas: indice.parcelas.map((p) => ({ evento: p.evento, ocorrencias: p.ocorrencias, desconto: p.desconto })),
|
|
328
|
+
},
|
|
260
329
|
base: thread.base,
|
|
261
330
|
worktree: thread.worktree,
|
|
262
331
|
evidencia: {
|
|
@@ -267,72 +336,140 @@ function registrarMaster(raiz, id, opcoes) {
|
|
|
267
336
|
claims: thread.claims.length,
|
|
268
337
|
},
|
|
269
338
|
};
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
339
|
+
if (classes.some(c => !exports.ORDEM_DAS_CLASSES.includes(c)))
|
|
340
|
+
throw new Error('classe fora do catálogo fixo');
|
|
341
|
+
return { thread, postmortem, masterLog, caminhoPostmortem: caminhoPostmortem(raiz, id),
|
|
342
|
+
caminhoMasterLog: caminhoMasterLog(raiz, id), classesInferidas, avisos };
|
|
343
|
+
}
|
|
344
|
+
/** Identidade declarada explicitamente. Não é autenticação de host. */
|
|
345
|
+
function autoriaHumana(por) {
|
|
346
|
+
const genericos = ['humano', 'humana', 'operador', 'usuario', 'user', 'anonimo', 'ninguem', 'host', 'admin', 'root', 'equipe', 'time'];
|
|
347
|
+
return typeof por === 'string' && por.trim().length >= 2 && !por.trim().startsWith('-') &&
|
|
348
|
+
!genericos.includes(semAcento(por.trim().toLowerCase())) &&
|
|
349
|
+
!/(?:^|[^a-z0-9])(codex|claude|gpt(?:[0-9-]*)?|openai|agente?|agent|runtime|auto|ia|llm|bot|pendente|pending|batch)(?:$|[^a-z0-9])/i.test(semAcento(por));
|
|
350
|
+
}
|
|
351
|
+
function exigirAutoriaHumana(por) {
|
|
352
|
+
if (!autoriaHumana(por))
|
|
353
|
+
throw new Error('ratificação exige --por humano explícito; agente ou autoria pendente não pode pontuar');
|
|
354
|
+
}
|
|
355
|
+
function masterRatificado(raiz, id) {
|
|
356
|
+
const t = (0, thread_1.lerThread)(raiz, id);
|
|
357
|
+
if (!t.score || !autoriaHumana(t.score.avaliadoPor) || t.fechamentoAdmin)
|
|
358
|
+
return false;
|
|
359
|
+
const e = [...(0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id))].reverse().find(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido);
|
|
360
|
+
return !!e && e.por === t.score.avaliadoPor && e.score === t.score.valor && e.justificativa === t.score.justificativa;
|
|
361
|
+
}
|
|
362
|
+
/** Preflight reutilizado pelo lote, sem escrita. */
|
|
363
|
+
function preflightMaster(raiz, id, opcoes) {
|
|
364
|
+
// Mantém erros de valor e duplicação anteriores ao erro de autoria.
|
|
365
|
+
const r = prepararDocumentos(raiz, id, opcoes);
|
|
366
|
+
exigirAutoriaHumana(opcoes.por);
|
|
367
|
+
const erros = validarMasterLog(r.masterLog);
|
|
368
|
+
if (erros.length)
|
|
369
|
+
throw new Error(erros.join('; '));
|
|
370
|
+
return r;
|
|
371
|
+
}
|
|
372
|
+
function registrarMaster(raiz, id, opcoes) {
|
|
373
|
+
const r = preflightMaster(raiz, id, opcoes);
|
|
374
|
+
const { thread, postmortem, masterLog } = r;
|
|
375
|
+
(0, util_1.gravarJson)(r.caminhoPostmortem, postmortem);
|
|
376
|
+
(0, util_1.gravarJson)(r.caminhoMasterLog, masterLog);
|
|
377
|
+
thread.score = postmortem.score;
|
|
378
|
+
thread.score_proposto = null;
|
|
379
|
+
// I-42: ciclo sem MASTER (o `#Fast`) fecha sem trocar de fase; `faseAtual` fica dentro do ciclo.
|
|
380
|
+
if (!thread.fases?.length || thread.fases.includes('MASTER'))
|
|
381
|
+
thread.faseAtual = 'MASTER';
|
|
280
382
|
thread.status = 'fechada';
|
|
281
383
|
(0, thread_1.gravarThread)(raiz, thread);
|
|
384
|
+
(0, fabrica_publicar_1.publicarEmSegundoPlano)(raiz);
|
|
282
385
|
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.postmortemGravado, {
|
|
283
|
-
fase: 'MASTER',
|
|
284
|
-
|
|
285
|
-
classesInferidas,
|
|
286
|
-
gatesBloqueados: gatesBloqueados.length,
|
|
287
|
-
arquivo: path.relative(raiz, caminhoP),
|
|
386
|
+
fase: 'MASTER', classesDeFalha: postmortem.classesDeFalha, classesInferidas: r.classesInferidas,
|
|
387
|
+
gatesBloqueados: postmortem.gatesBloqueados.length, arquivo: path.relative((0, estado_thread_1.raizDoEstado)(raiz), r.caminhoPostmortem),
|
|
288
388
|
});
|
|
289
389
|
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.masterConcluido, {
|
|
290
|
-
fase: 'MASTER',
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
autorizadoPor: score.avaliadoPor,
|
|
296
|
-
regime: score.regime,
|
|
297
|
-
contrato: exports.CONTRATO_MASTER_LOG,
|
|
298
|
-
arquivo: path.relative(raiz, caminhoM),
|
|
299
|
-
estado: 'thread fechada',
|
|
390
|
+
fase: 'MASTER', modo: thread.modo, tag: (0, modos_1.tagDoModo)(thread.modo), score: masterLog.score,
|
|
391
|
+
justificativa: masterLog.justificativa, por: masterLog.avaliadoPor, autorizadoPor: masterLog.avaliadoPor,
|
|
392
|
+
classesDeFalha: masterLog.classesDeFalha, regime: postmortem.score.regime,
|
|
393
|
+
contrato: exports.CONTRATO_MASTER_LOG, arquivo: path.relative((0, estado_thread_1.raizDoEstado)(raiz), r.caminhoMasterLog), estado: 'thread fechada',
|
|
394
|
+
masterLogSha256: hashDocumento(r.caminhoMasterLog), postmortemSha256: hashDocumento(r.caminhoPostmortem),
|
|
300
395
|
});
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
396
|
+
return r;
|
|
397
|
+
}
|
|
398
|
+
exports.CONTRATO_MASTER_PENDENTE = 'ork.master-pending/v1';
|
|
399
|
+
function proporMaster(raiz, id, opcoes) {
|
|
400
|
+
if (!opcoes.por?.trim())
|
|
401
|
+
throw new Error('proposta exige autoria explícita');
|
|
402
|
+
if ((0, thread_1.lerThread)(raiz, id).score)
|
|
403
|
+
throw new Error('thread já pontuada; proposta não sobrescreve score');
|
|
404
|
+
const r = prepararDocumentos(raiz, id, opcoes);
|
|
405
|
+
const proposta = { valor: opcoes.score, justificativa: opcoes.justificativa.trim(),
|
|
406
|
+
classes: r.postmortem.classesDeFalha, propostoPor: opcoes.por.trim(), propostoEm: (0, util_1.agora)(), resumo: r.postmortem.resumo };
|
|
407
|
+
// O contrato pendente não contém avaliadoPor nem avaliadoEm.
|
|
408
|
+
const { avaliadoPor: _por, avaliadoEm: _em, ...base } = r.masterLog;
|
|
409
|
+
const log = { ...base, contrato: exports.CONTRATO_MASTER_PENDENTE, score: null,
|
|
410
|
+
estado: 'ratificacao-pendente', score_proposto: proposta };
|
|
411
|
+
const post = { ...r.postmortem, score: null, score_proposto: proposta };
|
|
412
|
+
(0, util_1.gravarJson)(r.caminhoPostmortem, post);
|
|
413
|
+
(0, util_1.gravarJson)(r.caminhoMasterLog, log);
|
|
414
|
+
r.thread.score_proposto = proposta;
|
|
415
|
+
if (!r.thread.fases?.length || r.thread.fases.includes('MASTER'))
|
|
416
|
+
r.thread.faseAtual = 'MASTER';
|
|
417
|
+
r.thread.status = 'aberta';
|
|
418
|
+
(0, thread_1.gravarThread)(raiz, r.thread);
|
|
419
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.scoreProposto, { fase: 'MASTER', ...proposta, arquivo: path.relative((0, estado_thread_1.raizDoEstado)(raiz), r.caminhoMasterLog) });
|
|
420
|
+
return log;
|
|
310
421
|
}
|
|
311
422
|
/**
|
|
312
423
|
* Valida um MASTER log contra o contrato congelado. Devolve a lista de erros (vazia = valido).
|
|
313
424
|
* E o mesmo validador que a suite roda: o contrato e executavel, nao prosa.
|
|
314
425
|
*/
|
|
315
426
|
function validarMasterLog(bruto) {
|
|
316
|
-
const erros =
|
|
427
|
+
const erros = validarBaseMaster(bruto);
|
|
317
428
|
if (!bruto || typeof bruto !== 'object')
|
|
318
429
|
return ['o MASTER log nao e um objeto'];
|
|
319
430
|
const log = bruto;
|
|
320
431
|
if (log.contrato !== exports.CONTRATO_MASTER_LOG) {
|
|
321
432
|
erros.push(`campo "contrato" deve ser "${exports.CONTRATO_MASTER_LOG}"`);
|
|
322
433
|
}
|
|
323
|
-
if (log.versao !== exports.VERSAO_MASTER_LOG)
|
|
324
|
-
erros.push(`campo "versao" deve ser ${exports.VERSAO_MASTER_LOG}`);
|
|
325
|
-
for (const campo of ['thread', 'slug', 'modo', 'tag', 'justificativa', 'resumo', 'avaliadoPor']) {
|
|
326
|
-
const v = log[campo];
|
|
327
|
-
if (typeof v !== 'string' || v.trim() === '')
|
|
328
|
-
erros.push(`campo "${campo}" ausente ou vazio`);
|
|
329
|
-
}
|
|
330
434
|
if (typeof log.score !== 'number' || !Number.isInteger(log.score) || log.score < 0 || log.score > 5) {
|
|
331
435
|
erros.push('campo "score" deve ser um inteiro de 0 a 5');
|
|
332
436
|
}
|
|
333
437
|
if (typeof log.avaliadoEm !== 'string' || Number.isNaN(Date.parse(log.avaliadoEm))) {
|
|
334
438
|
erros.push('campo "avaliadoEm" deve ser um carimbo ISO valido');
|
|
335
439
|
}
|
|
440
|
+
if (!autoriaHumana(log.avaliadoPor))
|
|
441
|
+
erros.push('avaliadoPor precisa de autoria humana explícita');
|
|
442
|
+
return erros;
|
|
443
|
+
}
|
|
444
|
+
/** Valida a proposta sem convertê-la em avaliação humana. */
|
|
445
|
+
function validarMasterPendente(bruto) {
|
|
446
|
+
const erros = validarBaseMaster(bruto);
|
|
447
|
+
if (!bruto || typeof bruto !== 'object')
|
|
448
|
+
return erros;
|
|
449
|
+
const log = bruto;
|
|
450
|
+
if (log.contrato !== exports.CONTRATO_MASTER_PENDENTE || log.estado !== 'ratificacao-pendente' || log.score !== null ||
|
|
451
|
+
Object.hasOwn(log, 'avaliadoPor') || Object.hasOwn(log, 'avaliadoEm'))
|
|
452
|
+
erros.push('MASTER pendente exige ratificação sem score humano');
|
|
453
|
+
const p = log.score_proposto;
|
|
454
|
+
if (!p || !Number.isInteger(p.valor) || p.valor < 0 || p.valor > 5 ||
|
|
455
|
+
typeof p.propostoPor !== 'string' || !p.propostoPor.trim() ||
|
|
456
|
+
typeof p.propostoEm !== 'string' || !Number.isFinite(Date.parse(p.propostoEm)) ||
|
|
457
|
+
p.justificativa !== log.justificativa || p.resumo !== log.resumo ||
|
|
458
|
+
JSON.stringify(p.classes) !== JSON.stringify(log.classesDeFalha))
|
|
459
|
+
erros.push('proposta de score inválida');
|
|
460
|
+
return erros;
|
|
461
|
+
}
|
|
462
|
+
function validarBaseMaster(bruto) {
|
|
463
|
+
if (!bruto || typeof bruto !== 'object')
|
|
464
|
+
return ['o MASTER log nao e um objeto'];
|
|
465
|
+
const erros = [], log = bruto;
|
|
466
|
+
if (log.versao !== exports.VERSAO_MASTER_LOG)
|
|
467
|
+
erros.push(`campo "versao" deve ser ${exports.VERSAO_MASTER_LOG}`);
|
|
468
|
+
for (const campo of ['thread', 'slug', 'modo', 'tag', 'justificativa', 'resumo']) {
|
|
469
|
+
const v = log[campo];
|
|
470
|
+
if (typeof v !== 'string' || v.trim() === '')
|
|
471
|
+
erros.push(`campo "${campo}" ausente ou vazio`);
|
|
472
|
+
}
|
|
336
473
|
if (!Array.isArray(log.fases) || log.fases.length === 0) {
|
|
337
474
|
erros.push('campo "fases" deve listar as fases percorridas');
|
|
338
475
|
}
|
|
@@ -361,22 +498,120 @@ function validarMasterLog(bruto) {
|
|
|
361
498
|
}
|
|
362
499
|
return erros;
|
|
363
500
|
}
|
|
364
|
-
|
|
501
|
+
function hashDocumento(arquivo) {
|
|
502
|
+
return (0, node_crypto_1.createHash)('sha256').update(fs.readFileSync(arquivo)).digest('hex');
|
|
503
|
+
}
|
|
504
|
+
/** Leitura fail-closed: documento divergente não vira aprendizado ratificado. */
|
|
365
505
|
function lerMasterLog(raiz, id) {
|
|
366
506
|
const caminho = caminhoMasterLog(raiz, id);
|
|
367
507
|
if (!fs.existsSync(caminho))
|
|
368
508
|
return null;
|
|
369
|
-
|
|
509
|
+
let log;
|
|
510
|
+
try {
|
|
511
|
+
log = (0, util_1.lerJson)(caminho);
|
|
512
|
+
}
|
|
513
|
+
catch {
|
|
514
|
+
return null; /* JSON inválido não é MASTER */
|
|
515
|
+
}
|
|
516
|
+
if (validarMasterLog(log).length || !masterRatificado(raiz, id))
|
|
517
|
+
return null;
|
|
518
|
+
const score = (0, thread_1.lerThread)(raiz, id).score;
|
|
519
|
+
const evento = [...(0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id))].reverse().find(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido);
|
|
520
|
+
if (log.thread !== id || log.score !== score.valor || log.justificativa !== score.justificativa ||
|
|
521
|
+
log.avaliadoPor !== score.avaliadoPor || log.avaliadoEm !== score.avaliadoEm)
|
|
522
|
+
return null;
|
|
523
|
+
if (Array.isArray(evento.classesDeFalha) && JSON.stringify(log.classesDeFalha) !== JSON.stringify(evento.classesDeFalha))
|
|
524
|
+
return null;
|
|
525
|
+
// Hashes são evidência adicional no evento, sem mudar o contrato congelado v1.
|
|
526
|
+
if (evento.masterLogSha256 && hashDocumento(caminho) !== evento.masterLogSha256)
|
|
527
|
+
return null;
|
|
528
|
+
if (evento.postmortemSha256 && (!fs.existsSync(caminhoPostmortem(raiz, id)) ||
|
|
529
|
+
hashDocumento(caminhoPostmortem(raiz, id)) !== evento.postmortemSha256))
|
|
530
|
+
return null;
|
|
531
|
+
return log;
|
|
532
|
+
}
|
|
533
|
+
/** Quem decide quando ninguem decide. Literal unico, para o leitor reconhecer. */
|
|
534
|
+
exports.AUTOR_DA_OMISSAO = 'nucleo ork (omissao)';
|
|
535
|
+
/**
|
|
536
|
+
* Aceita a entrega por OMISSAO e registra que foi por omissao (I-43, D3).
|
|
537
|
+
*
|
|
538
|
+
* Este e o coracao da remocao da fila de ratificacao, e a parte que nao pode dar
|
|
539
|
+
* errado. Aceitacao por default sem registro seria pior que a fila: a fila ao menos
|
|
540
|
+
* deixava 13 threads visiveis esperando; uma entrega ruim aceita em silencio some, e
|
|
541
|
+
* some sem deixar rastro de que sumiu (R4 do GOAL).
|
|
542
|
+
*
|
|
543
|
+
* Entao a aceitacao produz TRES rastros independentes:
|
|
544
|
+
* 1. o evento `aceite_por_omissao` no ledger, append-only, com o indice e os
|
|
545
|
+
* insumos que o produziram;
|
|
546
|
+
* 2. o `score` gravado com `regime: 'omissao'` e `avaliadoPor` do nucleo,
|
|
547
|
+
* distinguivel de nota humana a olho e por codigo;
|
|
548
|
+
* 3. a visao de `ork master`, que lista o que passou sem o dono olhar.
|
|
549
|
+
*
|
|
550
|
+
* E ela NAO e irreversivel: reclamar continua possivel para sempre. O dono pontua a
|
|
551
|
+
* thread quando quiser, o score vira `regime: 'pausa'` com o nome dele, e o evento de
|
|
552
|
+
* omissao PERMANECE no ledger, porque o ledger e append-only e a historia de que a
|
|
553
|
+
* entrega passou sem revisao continua sendo verdade.
|
|
554
|
+
*/
|
|
555
|
+
function aceitarPorOmissao(raiz, id) {
|
|
556
|
+
const thread = (0, thread_1.lerThread)(raiz, id);
|
|
557
|
+
const dir = (0, thread_1.dirThread)(raiz, id);
|
|
558
|
+
// A1: aceitar por default so pode carimbar nota depois de perguntar ao git se a
|
|
559
|
+
// entrega ainda esta de pe. Era aqui que uma entrega revertida virava score 5.
|
|
560
|
+
const indice = indiceDaThread(raiz, id);
|
|
561
|
+
const aceitoEm = (0, util_1.agora)();
|
|
562
|
+
(0, ledger_1.registrar)(dir, id, ledger_1.TIPOS_DE_EVENTO.aceitePorOmissao, {
|
|
563
|
+
fase: 'MASTER',
|
|
564
|
+
indice: indice.valor,
|
|
565
|
+
base: indice.base,
|
|
566
|
+
// Os INSUMOS vao junto: um numero sem origem no ledger e um numero inventado.
|
|
567
|
+
insumos: indice.parcelas.map((p) => ({ evento: p.evento, ocorrencias: p.ocorrencias, desconto: p.desconto })),
|
|
568
|
+
decididoPor: exports.AUTOR_DA_OMISSAO,
|
|
569
|
+
razao: 'entrega aceita por default: ninguem pontuou. Nota humana posterior sobrescreve, e este evento permanece',
|
|
570
|
+
});
|
|
571
|
+
registrarMaster(raiz, id, {
|
|
572
|
+
score: Math.round(indice.valor),
|
|
573
|
+
justificativa: `Aceita por omissao: ninguem pontuou esta entrega. Indice derivado do ledger = ` +
|
|
574
|
+
`${indice.valor} de ${indice.base}` +
|
|
575
|
+
(indice.parcelas.length === 0
|
|
576
|
+
? ', sem reversao, GO-FIX, CHECK refeito nem ship barrado.'
|
|
577
|
+
: `, descontando ${indice.parcelas.map((p) => `${p.evento} x${p.ocorrencias}`).join(', ')}.`) +
|
|
578
|
+
' O dono pode pontuar quando quiser; a nota humana sobrescreve e o registro da omissao permanece.',
|
|
579
|
+
por: exports.AUTOR_DA_OMISSAO,
|
|
580
|
+
regime: 'omissao',
|
|
581
|
+
refazer: thread.status === 'fechada',
|
|
582
|
+
});
|
|
583
|
+
return { thread: id, indice, decididoPor: exports.AUTOR_DA_OMISSAO, aceitoEm };
|
|
584
|
+
}
|
|
585
|
+
/** As entregas aceitas por omissao: o que passou sem o dono olhar. */
|
|
586
|
+
function aceitosPorOmissao(raiz) {
|
|
587
|
+
const saida = [];
|
|
588
|
+
for (const id of (0, thread_1.listarIds)(raiz)) {
|
|
589
|
+
const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id));
|
|
590
|
+
const aceite = [...eventos].reverse().find((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.aceitePorOmissao);
|
|
591
|
+
if (!aceite)
|
|
592
|
+
continue;
|
|
593
|
+
// A1: a reversao pode ter vindo DEPOIS do aceite. O indice aqui e recalculado ao
|
|
594
|
+
// vivo, e `scoreGravado` fica ao lado para a divergencia aparecer em vez de sumir:
|
|
595
|
+
// o MASTER log e contrato congelado e nao se reescreve sozinho.
|
|
596
|
+
saida.push({
|
|
597
|
+
thread: id,
|
|
598
|
+
indice: indiceDaThread(raiz, id),
|
|
599
|
+
decididoPor: String(aceite.decididoPor ?? exports.AUTOR_DA_OMISSAO),
|
|
600
|
+
aceitoEm: String(aceite.ts ?? ''),
|
|
601
|
+
scoreGravado: (0, thread_1.lerThread)(raiz, id).score?.valor ?? null,
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
return saida;
|
|
370
605
|
}
|
|
371
606
|
/**
|
|
372
607
|
* A fila de batch scoring: threads que entregaram (ou chegaram ao MASTER) e ainda nao
|
|
373
|
-
* tem score. E a fila que `#
|
|
608
|
+
* tem score. E a fila que `#Classic`, `#Maestro` e `#Auto` alimentam ao entregar sem pausa.
|
|
374
609
|
*/
|
|
375
610
|
function pendentesDeScore(raiz, todas = false) {
|
|
376
611
|
const saida = [];
|
|
377
612
|
for (const id of (0, thread_1.listarIds)(raiz)) {
|
|
378
613
|
const thread = (0, thread_1.lerThread)(raiz, id);
|
|
379
|
-
if (thread.
|
|
614
|
+
if (thread.fechamentoAdmin || masterRatificado(raiz, id))
|
|
380
615
|
continue;
|
|
381
616
|
const jaEntregou = entregou(raiz, id);
|
|
382
617
|
const noMaster = thread.faseAtual === 'MASTER';
|
|
@@ -392,44 +627,93 @@ function pendentesDeScore(raiz, todas = false) {
|
|
|
392
627
|
}
|
|
393
628
|
return saida;
|
|
394
629
|
}
|
|
395
|
-
/**
|
|
396
|
-
|
|
630
|
+
/**
|
|
631
|
+
* A visao de entregas de `ork master` (I-43, T8): o que a FILA deixou de ser.
|
|
632
|
+
*
|
|
633
|
+
* O que saiu foi a FILA, e o que ela era: uma lista que acumulava "entregou e nao tem
|
|
634
|
+
* score" esperando o humano. Ela tinha 13 entradas em 20/09/2026, e nao por falta de
|
|
635
|
+
* lembrete: lembrete nao converte em nota. Enquanto ela existia, a unica informacao
|
|
636
|
+
* sobre a qualidade de uma entrega era uma nota que ninguem dava.
|
|
637
|
+
*
|
|
638
|
+
* No lugar dela, cada entrega chega com um INDICE ja calculado do ledger, e o comando
|
|
639
|
+
* oferece UM caminho para drenar o que sobrou: aceitar por omissao, com registro.
|
|
640
|
+
*
|
|
641
|
+
* O que NAO saiu, e nao podia sair: pontuar. `ork master <thread> --score` continua
|
|
642
|
+
* inteiro, e a nota humana continua sobrescrevendo o indice quando o dono reclama.
|
|
643
|
+
*/
|
|
644
|
+
function tabelaDeEntregas(raiz, todas = false) {
|
|
397
645
|
const pendentes = pendentesDeScore(raiz, todas);
|
|
646
|
+
const omissoes = aceitosPorOmissao(raiz);
|
|
647
|
+
// A1: o indice da coluna e o de AGORA; `SCORE GRAVADO` e o que o MASTER log congelou.
|
|
648
|
+
// Quando o segundo e maior, a entrega caiu depois de aceita e isso precisa aparecer.
|
|
649
|
+
const caiuDepoisDeAceita = omissoes.filter((o) => typeof o.scoreGravado === 'number' && o.indice.valor < o.scoreGravado);
|
|
650
|
+
const secaoOmissao = omissoes.length === 0
|
|
651
|
+
? []
|
|
652
|
+
: ['', `Aceitas por omissao (${omissoes.length}): o que passou sem voce olhar.`, '',
|
|
653
|
+
(0, util_1.tabela)(['ID', 'INDICE', 'SCORE GRAVADO', 'ACEITA EM'], omissoes.map((o) => [o.thread, `${o.indice.valor}/${o.indice.base}`,
|
|
654
|
+
typeof o.scoreGravado === 'number' ? `${o.scoreGravado}/5` : '-',
|
|
655
|
+
(0, horario_1.formatarDataHora)(o.aceitoEm)])),
|
|
656
|
+
(0, horario_1.legendaDoFuso)(),
|
|
657
|
+
...(caiuDepoisDeAceita.length === 0 ? [] : ['',
|
|
658
|
+
`ATENCAO: ${caiuDepoisDeAceita.length} entrega(s) cairam DEPOIS de aceitas: ` +
|
|
659
|
+
caiuDepoisDeAceita.map((o) => o.thread).join(', ') + '.',
|
|
660
|
+
' O MASTER log e contrato congelado e nao se reescreve sozinho. Pontue para o',
|
|
661
|
+
' registro humano alcancar o fato; o registro da omissao permanece no ledger.']),
|
|
662
|
+
'', 'Discordou de alguma? A nota humana sobrescreve, e o registro da omissao permanece:',
|
|
663
|
+
' ork master <thread-id> --score <0-5> --justificativa "<por que>" --por <humano>'];
|
|
398
664
|
if (pendentes.length === 0) {
|
|
399
|
-
return
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
'Para ver tambem as
|
|
665
|
+
return [
|
|
666
|
+
todas
|
|
667
|
+
? 'Nenhuma thread aberta sem score.'
|
|
668
|
+
: 'Nenhuma entrega esperando decisao. Para ver tambem as que ainda nao entregaram: ork master --todas',
|
|
669
|
+
...secaoOmissao,
|
|
670
|
+
].join('\n');
|
|
403
671
|
}
|
|
404
|
-
const linhas = pendentes.map((p) =>
|
|
405
|
-
p.thread.id
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
672
|
+
const linhas = pendentes.map((p) => {
|
|
673
|
+
const indice = indiceDaThread(raiz, p.thread.id);
|
|
674
|
+
return [
|
|
675
|
+
p.thread.id,
|
|
676
|
+
p.thread.slug,
|
|
677
|
+
(0, modos_1.tagDoModo)(p.thread.modo),
|
|
678
|
+
p.thread.faseAtual,
|
|
679
|
+
p.thread.status,
|
|
680
|
+
p.entregou ? 'sim' : 'nao',
|
|
681
|
+
`${indice.valor}/${indice.base}`,
|
|
682
|
+
indice.parcelas.length === 0 ? 'sem tropeco' : indice.parcelas.map((x) => `${x.evento} x${x.ocorrencias}`).join(', '),
|
|
683
|
+
];
|
|
684
|
+
});
|
|
415
685
|
return [
|
|
416
|
-
`
|
|
686
|
+
`Entregas (${pendentes.length}) com o indice ja derivado do ledger. O numero nao foi digitado por ninguem.`,
|
|
417
687
|
'',
|
|
418
|
-
|
|
688
|
+
(0, util_1.tabela)(['ID', 'SLUG', 'MODO', 'FASE', 'STATUS', 'ENTREGOU', 'INDICE', 'DE ONDE VEIO'], linhas),
|
|
419
689
|
'',
|
|
420
|
-
'
|
|
421
|
-
|
|
690
|
+
'ENTREGUE E ACEITO, a menos que voce diga o contrario.',
|
|
691
|
+
' ork master --aceitar-omissao aceita as entregues, com o indice e os insumos no ledger',
|
|
692
|
+
' ork master <id> --score <0-5> --justificativa "<por que>" --por <humano> se quiser reclamar',
|
|
422
693
|
'',
|
|
423
694
|
`Classes fixas: ${exports.ORDEM_DAS_CLASSES.join(', ')}`,
|
|
695
|
+
...secaoOmissao,
|
|
424
696
|
].join('\n');
|
|
425
697
|
}
|
|
698
|
+
/**
|
|
699
|
+
* Aceita por omissao TODAS as entregas que ainda esperam decisao.
|
|
700
|
+
*
|
|
701
|
+
* E o comando que drena a fila de uma vez, e por isso ele so alcanca o que de fato
|
|
702
|
+
* ENTREGOU: uma thread que nunca chegou ao ship nao tem entrega para aceitar, e
|
|
703
|
+
* aceita-la seria inventar um fato.
|
|
704
|
+
*/
|
|
705
|
+
function aceitarPendentesPorOmissao(raiz) {
|
|
706
|
+
return pendentesDeScore(raiz)
|
|
707
|
+
.filter((p) => p.entregou)
|
|
708
|
+
.map((p) => aceitarPorOmissao(raiz, p.thread.id));
|
|
709
|
+
}
|
|
426
710
|
/** Texto de `ork master <thread-id> --score`. */
|
|
427
711
|
function textoDoMaster(r) {
|
|
428
712
|
const linhas = [];
|
|
429
713
|
linhas.push(`MASTER registrado: thread ${r.thread.id} fechada.`);
|
|
430
714
|
linhas.push(` score ${r.masterLog.score}/5 (${r.postmortem.score.regime})`);
|
|
431
715
|
linhas.push(` justificativa ${r.masterLog.justificativa}`);
|
|
432
|
-
linhas.push(` avaliado por ${r.masterLog.avaliadoPor} em ${r.masterLog.avaliadoEm}`);
|
|
716
|
+
linhas.push(` avaliado por ${r.masterLog.avaliadoPor} em ${(0, horario_1.formatarDataHoraRotulada)(r.masterLog.avaliadoEm)}`);
|
|
433
717
|
linhas.push(` classes ${r.masterLog.classesDeFalha.join(', ')}`);
|
|
434
718
|
linhas.push(` fases ${r.masterLog.fases.join(' -> ')}`);
|
|
435
719
|
linhas.push(` entregas ${r.postmortem.entregas.length} ship(s) concluido(s) no ledger`);
|