@orkastery/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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-sensor.js +66 -0
- package/adapters/codex/skills/ork/SKILL.md +57 -0
- package/adapters/hermes/README.md +163 -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-objective-message.sh +17 -0
- package/adapters/hermes/bin/ork-objective-status.sh +12 -0
- package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
- package/adapters/hermes/hermes.plugin.json +26 -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 +135 -26
- 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 +458 -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 +11 -8
- package/dist/auditrun.js +5 -4
- package/dist/board.js +173 -22
- 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 +216 -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 +183 -24
- 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 +21 -0
- package/dist/gates.js +55 -9
- 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 +1736 -93
- 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 +107 -2
- package/dist/licoes.js +215 -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 +596 -150
- package/dist/playbook-capabilities.js +150 -0
- package/dist/playbook-contracts.js +188 -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 +637 -115
- 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 +683 -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 +150 -15
- 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 +2 -0
- package/eval/casos/onboarding.json +102 -0
- package/eval/casos/orkastery-bootstrap.json +35 -1
- package/eval/casos/scope-check-capability-map.json +45 -7
- package/eval/casos/ship-release.json +2 -2
- 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 +25 -4
- 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/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/scope-check-capability-map/SKILL.md +17 -7
package/dist/phase.js
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* `ork phase run|list`: despacho de fase pelo runtime adapter e leitura do ledger.
|
|
4
|
-
*
|
|
5
|
-
* O prompt e montado pelo `ork` (nomenclatura das fases + modo de conducao + contexto da
|
|
6
|
-
* thread + pedido do builder), gravado com hash sha256 no diretorio da thread e so entao
|
|
7
|
-
* despachado. Depois do despacho o `ork` RE-VERIFICA no runtime que a sessao existe:
|
|
8
|
-
* self-report de despacho nao vale como evidencia.
|
|
9
|
-
*/
|
|
10
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
3
|
if (k2 === undefined) k2 = k;
|
|
12
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -42,6 +34,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
42
34
|
})();
|
|
43
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
36
|
exports.REGRAS_DE_EVIDENCIA = exports.CONTRATO_DAS_FASES = void 0;
|
|
37
|
+
exports.escolherPerfil = escolherPerfil;
|
|
38
|
+
exports.perfilParaDespacho = perfilParaDespacho;
|
|
39
|
+
exports.runtimeCruzadoParaDespacho = runtimeCruzadoParaDespacho;
|
|
40
|
+
exports.estadoParaDespacho = estadoParaDespacho;
|
|
41
|
+
exports.fasesDoCicloNoPrompt = fasesDoCicloNoPrompt;
|
|
45
42
|
exports.valoresDoPrompt = valoresDoPrompt;
|
|
46
43
|
exports.montarPrompt = montarPrompt;
|
|
47
44
|
exports.montarPromptComMemoria = montarPromptComMemoria;
|
|
@@ -50,16 +47,33 @@ exports.slugDaSessao = slugDaSessao;
|
|
|
50
47
|
exports.resolverDespacho = resolverDespacho;
|
|
51
48
|
exports.dadosDoDespacho = dadosDoDespacho;
|
|
52
49
|
exports.concluirDespacho = concluirDespacho;
|
|
50
|
+
exports.prazoDaSessao = prazoDaSessao;
|
|
53
51
|
exports.rodarFase = rodarFase;
|
|
54
52
|
exports.tabelaDoLedger = tabelaDoLedger;
|
|
55
53
|
exports.descreverSlug = descreverSlug;
|
|
54
|
+
const hitl_gates_1 = require("./hitl-gates");
|
|
55
|
+
const runtime_context_1 = require("./runtime-context");
|
|
56
|
+
/**
|
|
57
|
+
* `ork phase run|list`: despacho de fase pelo runtime adapter e leitura do ledger.
|
|
58
|
+
*
|
|
59
|
+
* O prompt e montado pelo `ork` (nomenclatura das fases + modo de conducao + contexto da
|
|
60
|
+
* thread + pedido do builder), gravado com hash sha256 no diretorio da thread e so entao
|
|
61
|
+
* despachado. Depois do despacho o `ork` RE-VERIFICA no runtime que a sessao existe:
|
|
62
|
+
* self-report de despacho nao vale como evidencia.
|
|
63
|
+
*/
|
|
56
64
|
const node_crypto_1 = require("node:crypto");
|
|
65
|
+
const fs = __importStar(require("node:fs"));
|
|
57
66
|
const path = __importStar(require("node:path"));
|
|
58
|
-
const
|
|
67
|
+
const session_watcher_1 = require("./session-watcher");
|
|
68
|
+
const session_watcher_claude_1 = require("./session-watcher-claude");
|
|
69
|
+
const runtimes_1 = require("./runtimes");
|
|
70
|
+
const setup_1 = require("./setup");
|
|
59
71
|
const modos_1 = require("./modos");
|
|
60
72
|
const gates_1 = require("./gates");
|
|
61
73
|
const policies_1 = require("./policies");
|
|
62
74
|
const ratelimit_1 = require("./ratelimit");
|
|
75
|
+
const claude_bg_1 = require("./adapters/claude-bg");
|
|
76
|
+
const codex_1 = require("./adapters/codex");
|
|
63
77
|
const memoria_1 = require("./memoria");
|
|
64
78
|
const prompts_1 = require("./prompts");
|
|
65
79
|
const slug_1 = require("./slug");
|
|
@@ -67,6 +81,145 @@ const thread_1 = require("./thread");
|
|
|
67
81
|
const types_1 = require("./types");
|
|
68
82
|
const util_1 = require("./util");
|
|
69
83
|
const ledger_1 = require("./ledger");
|
|
84
|
+
const estado_thread_1 = require("./estado-thread");
|
|
85
|
+
const horario_1 = require("./horario");
|
|
86
|
+
const runtime_profiles_1 = require("./runtime-profiles");
|
|
87
|
+
const maquina_1 = require("./maquina");
|
|
88
|
+
const fabrica_publicar_1 = require("./fabrica-publicar");
|
|
89
|
+
const conducao_1 = require("./conducao");
|
|
90
|
+
/**
|
|
91
|
+
* I-33 (D2, D4, D14): o perfil do despacho. Sem perfis do runtime no store, nenhum (P8). Com
|
|
92
|
+
* perfis, o pedido explicito ou o perfil da vez na ordem do store pela politica de rotacao do
|
|
93
|
+
* manifesto (sem ela, a padrao da D16); perfil esgotado, sem auth, pago ou desativado nunca
|
|
94
|
+
* recebe despacho.
|
|
95
|
+
*/
|
|
96
|
+
function escolherPerfil(raiz, runtime, opcoes = {}) {
|
|
97
|
+
// I-49: o despacho enxerga o estado que as outras fabricas viram na mesma conta.
|
|
98
|
+
const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz, opcoes.agoraMs);
|
|
99
|
+
const doRuntime = (0, runtime_profiles_1.perfisDoRuntime)(store, runtime);
|
|
100
|
+
if (opcoes.perfil !== undefined) {
|
|
101
|
+
const pedido = doRuntime.find(p => p.id === opcoes.perfil);
|
|
102
|
+
if (!pedido)
|
|
103
|
+
return { perfil: null, configurados: doRuntime.length, erro: `perfil "${opcoes.perfil}" nao existe para o runtime ${runtime}` };
|
|
104
|
+
if (!(0, runtime_profiles_1.perfilDisponivel)(pedido, opcoes.agoraMs))
|
|
105
|
+
return { perfil: null, configurados: doRuntime.length,
|
|
106
|
+
erro: `perfil "${pedido.id}" esta ${pedido.estado}${pedido.esgotadoAte ? ` ate ${pedido.esgotadoAte}` : ''}` };
|
|
107
|
+
return { perfil: (0, runtime_profiles_1.perfilDeDespacho)(pedido), configurados: doRuntime.length };
|
|
108
|
+
}
|
|
109
|
+
if (doRuntime.length === 0)
|
|
110
|
+
return { perfil: null, configurados: 0 };
|
|
111
|
+
const proximo = (0, runtime_profiles_1.proximoPerfilDisponivel)(store, runtime, opcoes.politica ?? runtime_profiles_1.POLITICA_PADRAO, opcoes);
|
|
112
|
+
if (proximo)
|
|
113
|
+
return { perfil: (0, runtime_profiles_1.perfilDeDespacho)(proximo), configurados: doRuntime.length };
|
|
114
|
+
const agoraMs = opcoes.agoraMs ?? Date.now();
|
|
115
|
+
// Motivo do bloqueio pelo estado dos perfis: com algum esgotado ha prazo (fila); so sem-auth, login;
|
|
116
|
+
// so provider pago (D13), custo: `cost.violation` nunca recebe retry automatico.
|
|
117
|
+
const motivo = doRuntime.some(p => p.estado === 'esgotado' && p.esgotadoAte !== null && Date.parse(p.esgotadoAte) > agoraMs)
|
|
118
|
+
? 'runtime.quota-exhausted' : doRuntime.some(p => p.estado === 'sem-auth') ? 'runtime.auth-missing'
|
|
119
|
+
: doRuntime.some(p => p.estado === 'provider-pago') ? 'cost.violation' : 'runtime.unavailable';
|
|
120
|
+
return { perfil: null, configurados: doRuntime.length, motivo,
|
|
121
|
+
erro: `nenhum perfil disponivel do runtime ${runtime} (${doRuntime.map(p => `${p.id}: ${p.estado}`).join(', ')})` };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* I-33 (D7, D13): preflight de auth antes do despacho. O perfil escolhido tem o login conferido
|
|
125
|
+
* pelo proprio CLI com o env dele; reprovado, vira `sem-auth` no store (ou `provider-pago`, quando
|
|
126
|
+
* o login e por API key, helper, Console ou nuvem), a troca vai ao ledger (`runtime_profile_rotated`)
|
|
127
|
+
* e o proximo perfil do mesmo runtime e conferido. Perfil sem login de assinatura nunca recebe
|
|
128
|
+
* despacho. Sem perfil (ambiente do processo) ou em ensaio, nada e conferido.
|
|
129
|
+
*/
|
|
130
|
+
function perfilParaDespacho(carregado, thread, fase, runtime, opcoes) {
|
|
131
|
+
const { raiz } = carregado;
|
|
132
|
+
const excluir = [...(opcoes.excluir ?? [])];
|
|
133
|
+
const politica = (0, runtime_profiles_1.politicaDeRotacao)(carregado.manifesto);
|
|
134
|
+
for (;;) {
|
|
135
|
+
const escolha = escolherPerfil(raiz, runtime, { perfil: opcoes.perfil, excluir, politica });
|
|
136
|
+
if (escolha.erro || !escolha.perfil || opcoes.dryRun)
|
|
137
|
+
return escolha;
|
|
138
|
+
const auth = runtime === 'claude-bg' ? (0, claude_bg_1.conferirAuth)(escolha.perfil) : runtime === 'codex' ? (0, codex_1.conferirAuth)(escolha.perfil)
|
|
139
|
+
: { ok: false, detalhe: `runtime ${runtime} sem conferencia de login` };
|
|
140
|
+
if (auth.ok)
|
|
141
|
+
return escolha;
|
|
142
|
+
let motivo, razao;
|
|
143
|
+
if (auth.transitorio) {
|
|
144
|
+
// A14: conferencia inconclusiva nao marca sem-auth: o perfil fica fora so deste despacho.
|
|
145
|
+
(0, runtime_profiles_1.registrarConferenciaInconclusiva)(raiz, escolha.perfil.id, auth.detalhe);
|
|
146
|
+
motivo = 'runtime.unavailable';
|
|
147
|
+
razao = 'a conferencia de login nao concluiu (A14): o perfil fica fora so deste despacho e e conferido de novo no proximo';
|
|
148
|
+
}
|
|
149
|
+
else if (auth.pago) {
|
|
150
|
+
// D13: login valido, mas cobrado por token. O perfil sai do rodizio com estado proprio e nunca despacha.
|
|
151
|
+
(0, runtime_profiles_1.marcarFalhaDePerfil)(raiz, escolha.perfil.id, { estado: 'provider-pago', esgotadoAte: null, motivo: 'cost.violation', detalhe: auth.detalhe });
|
|
152
|
+
motivo = 'cost.violation';
|
|
153
|
+
razao = 'o preflight achou login por provider pago (D13): perfil de API key, helper, Console ou nuvem nunca recebe despacho';
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const falha = { motivo: 'runtime.auth-missing', resetEm: null, fonte: 'sem-horario', trecho: auth.detalhe };
|
|
157
|
+
(0, ratelimit_1.marcarContaDaFalha)(carregado, escolha.perfil, falha);
|
|
158
|
+
motivo = falha.motivo;
|
|
159
|
+
razao = 'o preflight de auth reprovou o perfil antes do despacho (D7): perfil sem login nunca recebe despacho';
|
|
160
|
+
}
|
|
161
|
+
excluir.push(escolha.perfil.id);
|
|
162
|
+
const proximo = opcoes.perfil === undefined ? escolherPerfil(raiz, runtime, { excluir, politica }).perfil : null;
|
|
163
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread.id), thread.id, ledger_1.TIPOS_DE_EVENTO.perfilRotacionado, {
|
|
164
|
+
fase, motivo, origem: `${opcoes.origem}.preflight`,
|
|
165
|
+
de: { runtime, perfil: escolha.perfil.id }, para: proximo ? { runtime, perfil: proximo.id } : null,
|
|
166
|
+
evidencia: auth.detalhe, razao,
|
|
167
|
+
autorizadoPor: 'politica de rotacao da I-33 (D5, D7, D13), igual em todos os modos',
|
|
168
|
+
});
|
|
169
|
+
if (opcoes.perfil !== undefined)
|
|
170
|
+
return { perfil: null, configurados: escolha.configurados, motivo,
|
|
171
|
+
erro: `perfil "${opcoes.perfil}" ${auth.transitorio ? 'com conferencia de login inconclusiva' : auth.pago ? 'autenticado por provider pago' : 'sem login conferido'}: ${auth.detalhe}` };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* O CHECK desta thread pode rodar neste runtime? (I-43, D4, viga a)
|
|
176
|
+
*
|
|
177
|
+
* A regra: quem VALIDA nao pode ser quem EXECUTOU. Ela vinha do Objective Envelope,
|
|
178
|
+
* onde valia so na criacao e para tres threads que nunca rodaram nada; aqui ela passa
|
|
179
|
+
* a valer no despacho de qualquer thread que a exija.
|
|
180
|
+
*
|
|
181
|
+
* Compara o runtime do CHECK com os runtimes das sessoes de GO JA REGISTRADAS em
|
|
182
|
+
* `thread.sessoes`, que ja carregam `runtime` e ja aparecem em `ork thread status`.
|
|
183
|
+
* Nenhum dado novo precisa ser coletado: o que faltava era a regra, nao o dado.
|
|
184
|
+
*
|
|
185
|
+
* Sem sessao de GO registrada nao ha o que cruzar, e o despacho passa: inventar
|
|
186
|
+
* impedimento sobre um GO que nao aconteceu seria barrar por suposicao.
|
|
187
|
+
*/
|
|
188
|
+
function runtimeCruzadoParaDespacho(thread, fase, runtime) {
|
|
189
|
+
if (thread.exigeRuntimeDiferente !== true || fase !== 'CHECK')
|
|
190
|
+
return null;
|
|
191
|
+
const doGo = [...new Set(thread.sessoes.filter((s) => s.fase === 'GO').map((s) => s.runtime))];
|
|
192
|
+
if (doGo.length === 0)
|
|
193
|
+
return null;
|
|
194
|
+
if (!doGo.includes(runtime))
|
|
195
|
+
return null;
|
|
196
|
+
return `runtime.autoconferencia: o CHECK precisa de runtime diferente do GO, e "${runtime}" `
|
|
197
|
+
+ `foi o runtime do GO desta thread (${doGo.join(', ')}). `
|
|
198
|
+
+ `Despache o CHECK em outro runtime, ou tire a exigencia da thread.`;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* I-43 (T11): o ramo do Objective Envelope saiu daqui.
|
|
202
|
+
*
|
|
203
|
+
* Ele era a UNICA consulta do produto ao envelope, e dependia de `thread.creationOrigin`.
|
|
204
|
+
* A medida: das 137 threads do projeto, ZERO tinham `creationOrigin`. O ramo nunca
|
|
205
|
+
* disparou para thread nenhuma, e a "unica pausa planejada do #Maestro" nao bloqueava
|
|
206
|
+
* o despacho nem das tres threads que o proprio envelope criou.
|
|
207
|
+
*
|
|
208
|
+
* O que ele PRETENDIA garantir (que ninguem despacha sem validacao combinada) continua
|
|
209
|
+
* garantido, e agora de verdade, por `runtimeCruzadoParaDespacho` logo acima e pelos
|
|
210
|
+
* criterios de pronto executaveis que `ork verify` cobra.
|
|
211
|
+
*/
|
|
212
|
+
function estadoParaDespacho(raiz, thread, dryRun = false) {
|
|
213
|
+
if (!thread.worktree)
|
|
214
|
+
return null;
|
|
215
|
+
try {
|
|
216
|
+
(0, estado_thread_1.vincularEstado)(raiz, thread.id, thread.worktree, dryRun);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
return e.message;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
70
223
|
/** O que cada fase canonica entrega. Vai no cabecalho do prompt de toda sessao. */
|
|
71
224
|
exports.CONTRATO_DAS_FASES = {
|
|
72
225
|
GOAL: 'GOAL (F1): objetivo verificavel, impact map, criterios de sucesso e claims com comando de verificacao. Nao implementa.',
|
|
@@ -82,6 +235,21 @@ exports.REGRAS_DE_EVIDENCIA = [
|
|
|
82
235
|
'Trabalhe apenas no diretorio de trabalho indicado acima.',
|
|
83
236
|
'Passos irreversiveis (push, merge, delecao) so acontecem quando o modo autoriza.',
|
|
84
237
|
];
|
|
238
|
+
/**
|
|
239
|
+
* I-42 (D11): as fases que o cabecalho do prompt descreve.
|
|
240
|
+
*
|
|
241
|
+
* Regra por desenho de bloco, nunca por nome de modo: quando o ciclo e um bloco so e esse bloco
|
|
242
|
+
* nao percorre as seis fases, o prompt descreve so as fases dele. As outras cinco linhas seriam
|
|
243
|
+
* cerimonia de um ciclo que a sessao nao vai percorrer. Bloco unico com as seis fases e ciclo de
|
|
244
|
+
* varios blocos continuam com as seis linhas, byte a byte.
|
|
245
|
+
*/
|
|
246
|
+
function fasesDoCicloNoPrompt(thread) {
|
|
247
|
+
const [unico, ...resto] = thread.blocos;
|
|
248
|
+
if (unico && resto.length === 0 && unico.fases.length < types_1.FASES.length) {
|
|
249
|
+
return types_1.FASES.filter((f) => unico.fases.includes(f));
|
|
250
|
+
}
|
|
251
|
+
return types_1.FASES;
|
|
252
|
+
}
|
|
85
253
|
/**
|
|
86
254
|
* Os valores que o template de fase recebe.
|
|
87
255
|
*
|
|
@@ -98,7 +266,7 @@ function valoresDoPrompt(thread, fase, pedido, memoriaInjetada = '') {
|
|
|
98
266
|
thread: thread.id,
|
|
99
267
|
bloco: bloco.fases.join('-'),
|
|
100
268
|
nome: thread.nome,
|
|
101
|
-
ciclo_canonico:
|
|
269
|
+
ciclo_canonico: fasesDoCicloNoPrompt(thread).map((f) => `${bloco.fases.includes(f) ? '>' : ' '} ${exports.CONTRATO_DAS_FASES[f]}`).join('\n'),
|
|
102
270
|
tag: def.tag,
|
|
103
271
|
blocos: thread.blocos.map((b) => b.fases.join('-')).join(' / '),
|
|
104
272
|
pausas: String(thread.blocos.filter((b) => b.pausa).length),
|
|
@@ -150,6 +318,16 @@ function montarPromptComMemoria(carregado, thread, fase, pedido, memoria) {
|
|
|
150
318
|
function hashDoPrompt(prompt) {
|
|
151
319
|
return (0, node_crypto_1.createHash)('sha256').update(prompt, 'utf8').digest('hex');
|
|
152
320
|
}
|
|
321
|
+
function schemaDeClaimsDoPacote() {
|
|
322
|
+
const candidatos = [
|
|
323
|
+
path.join(__dirname, '..', 'schemas', 'claims.schema.json'),
|
|
324
|
+
path.join(__dirname, '..', '..', 'schemas', 'claims.schema.json'),
|
|
325
|
+
];
|
|
326
|
+
const arquivo = candidatos.find(c => fs.existsSync(c));
|
|
327
|
+
if (!arquivo)
|
|
328
|
+
throw new Error('runtime.unavailable: schema de claims nao encontrado no pacote');
|
|
329
|
+
return JSON.parse(fs.readFileSync(arquivo, 'utf8'));
|
|
330
|
+
}
|
|
153
331
|
/** Slug da sessao que conduz esta fase, rotacionando quando o slug ja foi usado na thread. */
|
|
154
332
|
function slugDaSessao(thread, fase) {
|
|
155
333
|
const bloco = (0, thread_1.blocoDaThread)(thread, fase);
|
|
@@ -160,18 +338,28 @@ function slugDaSessao(thread, fase) {
|
|
|
160
338
|
return (0, slug_1.proximaRotacao)(base, usados);
|
|
161
339
|
}
|
|
162
340
|
/**
|
|
163
|
-
*
|
|
341
|
+
* Runtime, modelo e esforco EFETIVAMENTE usados num despacho, resolvidos numa funcao so.
|
|
342
|
+
*
|
|
343
|
+
* Precedencia (decisao D4 da thread ork-homologarcod): opcao explicita do CLI > setup do
|
|
344
|
+
* bloco (feature #setup, `.orkastery/setup.json`) > runtime do manifesto.
|
|
164
345
|
*
|
|
165
346
|
* Regra do esforco: quem informa SO o modelo esta pedindo o despacho mais capaz que
|
|
166
|
-
* existe, entao o esforco assume `high` em vez de herdar o do
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
347
|
+
* existe, entao o esforco assume `high` em vez de herdar o do setup ou do manifesto.
|
|
348
|
+
* Quem informa o esforco manda. Resolver isso aqui, e nao no ponto de chamada, e o que
|
|
349
|
+
* permite gravar o trio no ledger como FATO: o mesmo valor que foi para o runtime
|
|
350
|
+
* adapter e o que fica carimbado no evento.
|
|
170
351
|
*/
|
|
171
|
-
function resolverDespacho(manifesto, opcoes) {
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
352
|
+
function resolverDespacho(manifesto, opcoes, doBloco) {
|
|
353
|
+
const origem = doBloco?.runtime ?? manifesto.runtime.adapter;
|
|
354
|
+
const runtime = opcoes.runtime ?? origem;
|
|
355
|
+
if ((0, runtimes_1.runtimeConhecido)(runtime) && runtime !== origem && !opcoes.model?.trim())
|
|
356
|
+
throw new Error(`setup.model.required: ao trocar runtime de ${origem} para ${runtime}, informe --runtime ${runtime} --model <modelo> para este despacho; o setup do projeto permanece intacto.`);
|
|
357
|
+
const model = opcoes.model ?? doBloco?.model ?? manifesto.runtime.model;
|
|
358
|
+
if (!model.trim())
|
|
359
|
+
throw new Error(`setup.model.required: modelo pendente para ${runtime}; informe --model <modelo> neste despacho ou complete o bloco em ork setup.`);
|
|
360
|
+
const effort = opcoes.effort ??
|
|
361
|
+
(opcoes.model !== undefined ? 'high' : doBloco?.effort ?? manifesto.runtime.effort);
|
|
362
|
+
return { runtime, model, effort };
|
|
175
363
|
}
|
|
176
364
|
/** O comando com o prompt mascarado pelo hash: o ledger nao guarda o texto inteiro. */
|
|
177
365
|
function comandoMascarado(comando, sha) {
|
|
@@ -194,6 +382,12 @@ function dadosDoDespacho(ctx, comando) {
|
|
|
194
382
|
promptPath: path.relative(ctx.raiz, ctx.promptPath),
|
|
195
383
|
promptSha256: ctx.promptSha256,
|
|
196
384
|
origem: ctx.origem,
|
|
385
|
+
// I-36 (T10): a porta por onde o dono chegou. `runtime` e o motor; `canal` e a porta.
|
|
386
|
+
...(ctx.canal ? { canal: ctx.canal } : {}),
|
|
387
|
+
...(ctx.correlacao ? { correlacao: ctx.correlacao } : {}),
|
|
388
|
+
...(ctx.identidade ? { identidade: ctx.identidade } : {}),
|
|
389
|
+
// I-33 (D4): so identidade e diretorio do perfil; o store guarda o resto e nada e segredo.
|
|
390
|
+
...(ctx.perfil ? { perfil: ctx.perfil } : {}),
|
|
197
391
|
comando: comandoMascarado(comando, ctx.promptSha256),
|
|
198
392
|
};
|
|
199
393
|
}
|
|
@@ -201,27 +395,36 @@ function dadosDoDespacho(ctx, comando) {
|
|
|
201
395
|
* Fecha um despacho BEM SUCEDIDO: ledger, decisao autonoma ou pausa prevista, e a
|
|
202
396
|
* sessao gravada no `thread.json`. Usada pelo `ork phase run` e pela retomada do B3.
|
|
203
397
|
*/
|
|
204
|
-
function concluirDespacho(ctx, sessionId, verificada, comando
|
|
398
|
+
function concluirDespacho(ctx, sessionId, verificada, comando, fonteVerificacao, controlador,
|
|
399
|
+
/** Variante histórica do supervisor; a variante do controller não tem log próprio. */
|
|
400
|
+
sensores) {
|
|
205
401
|
const dir = (0, thread_1.dirThread)(ctx.raiz, ctx.thread.id);
|
|
206
402
|
const comum = dadosDoDespacho(ctx, comando);
|
|
207
403
|
const bloco = (0, thread_1.blocoDaThread)(ctx.thread, ctx.fase);
|
|
208
404
|
const pausaAoFim = (0, thread_1.pausaNaThread)(ctx.thread, ctx.fase);
|
|
209
|
-
(
|
|
405
|
+
// I-51 (RM-047): a maquina que despachou. So o evento de conducao; os de HITL nao mudam.
|
|
406
|
+
(0, ledger_1.registrar)(dir, ctx.thread.id, ledger_1.TIPOS_DE_EVENTO.faseDespachada, { ...comum, sessionId, ...(controlador ? { controlador } : {}),
|
|
407
|
+
maquina: (0, maquina_1.nomeDaMaquina)() });
|
|
210
408
|
(0, ledger_1.registrar)(dir, ctx.thread.id, ledger_1.TIPOS_DE_EVENTO.despachoVerificado, {
|
|
211
409
|
fase: ctx.fase,
|
|
212
410
|
slug: ctx.slug,
|
|
213
411
|
sessionId,
|
|
214
|
-
fonte:
|
|
412
|
+
// A fonte e do runtime que despachou: e ela que diz ONDE conferir a sessao depois.
|
|
413
|
+
fonte: fonteVerificacao ?? (0, runtimes_1.resolverRuntime)(ctx.runtime).fonteVerificacao,
|
|
215
414
|
encontrada: verificada,
|
|
216
415
|
});
|
|
217
416
|
if (!pausaAoFim) {
|
|
417
|
+
const tag = (0, modos_1.definicaoDoModo)(ctx.thread.modo).tag;
|
|
218
418
|
(0, ledger_1.registrar)(dir, ctx.thread.id, ledger_1.TIPOS_DE_EVENTO.decisaoAutonoma, {
|
|
219
419
|
fase: ctx.fase,
|
|
220
420
|
slug: ctx.slug,
|
|
221
421
|
sessionId,
|
|
222
422
|
decisao: `bloco ${bloco.fases.join('-')} segue sem pausa humana`,
|
|
223
|
-
|
|
423
|
+
// I-41 (GO-FIX 1, D11): o rastro tipado. `autorizadoPor` fica pelo que ja o lia.
|
|
424
|
+
quemDecidiu: `o builder, pela #TAG ${tag} no pedido`,
|
|
425
|
+
autorizadoPor: `#TAG ${tag} no pedido do builder`,
|
|
224
426
|
evidencia: `prompt sha256 ${ctx.promptSha256}`,
|
|
427
|
+
razao: `o modo ${tag} não prevê pausa humana ao fim do bloco ${bloco.fases.join('-')}`,
|
|
225
428
|
});
|
|
226
429
|
}
|
|
227
430
|
else {
|
|
@@ -234,6 +437,7 @@ function concluirDespacho(ctx, sessionId, verificada, comando) {
|
|
|
234
437
|
});
|
|
235
438
|
}
|
|
236
439
|
const sessao = {
|
|
440
|
+
...(controlador ? { controlador } : {}),
|
|
237
441
|
slug: ctx.slug,
|
|
238
442
|
fase: ctx.fase,
|
|
239
443
|
bloco: bloco.fases.join('-'),
|
|
@@ -243,23 +447,110 @@ function concluirDespacho(ctx, sessionId, verificada, comando) {
|
|
|
243
447
|
promptPath: path.relative(ctx.raiz, ctx.promptPath),
|
|
244
448
|
promptSha256: ctx.promptSha256,
|
|
245
449
|
verificada,
|
|
450
|
+
...(ctx.perfil ? { perfil: ctx.perfil } : {}),
|
|
451
|
+
...(ctx.canal ? { canal: ctx.canal } : {}),
|
|
452
|
+
...(ctx.correlacao ? { correlacao: ctx.correlacao } : {}),
|
|
246
453
|
};
|
|
247
454
|
ctx.thread.sessoes.push(sessao);
|
|
455
|
+
// `ultimoUso` e informativo: store indisponivel nao desfaz um despacho ja provado.
|
|
456
|
+
if (ctx.perfil) {
|
|
457
|
+
try {
|
|
458
|
+
(0, runtime_profiles_1.registrarUsoDePerfil)(ctx.raiz, ctx.perfil.id, sessao.despachadaEm);
|
|
459
|
+
}
|
|
460
|
+
catch { /* informativo */ }
|
|
461
|
+
}
|
|
248
462
|
ctx.thread.faseAtual = ctx.fase;
|
|
249
463
|
(0, thread_1.gravarThread)(ctx.raiz, ctx.thread);
|
|
464
|
+
// I-36 (T7): a conducao deixa de ser do ato de despachar e passa a ser da janela da sessao.
|
|
465
|
+
vincularConducaoDaSessao(ctx, sessionId);
|
|
466
|
+
// I-51 (RM-047): as outras maquinas veem a fase nova; so com a fabrica compartilhada.
|
|
467
|
+
(0, fabrica_publicar_1.publicarEmSegundoPlano)(ctx.raiz);
|
|
468
|
+
if (ctx.runtime === 'codex' || ctx.runtime === 'claude-bg')
|
|
469
|
+
registrarObservacao(ctx, sessao, dir, controlador, sensores);
|
|
250
470
|
return sessao;
|
|
251
471
|
}
|
|
472
|
+
/**
|
|
473
|
+
* I-36 (T7): o lease de execucao sobrevive ao `ork phase run`, porque quem executa e a sessao. Ele
|
|
474
|
+
* so sai quando a fase termina (a prova da I-34 no ledger) ou com prova de abandono (D7).
|
|
475
|
+
*/
|
|
476
|
+
function vincularConducaoDaSessao(ctx, sessionId) {
|
|
477
|
+
const sessao = { sessionId, runtime: ctx.runtime, perfil: ctx.perfil?.id ?? null };
|
|
478
|
+
const prazoMs = ctx.prazoDaSessaoMs ?? conducao_1.PRAZO_DE_SESSAO_PADRAO_MS;
|
|
479
|
+
if (ctx.conducao) {
|
|
480
|
+
ctx.conducao.converterEmSessao({ ...sessao, prazoMs });
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
try {
|
|
484
|
+
(0, conducao_1.registrarConducaoDaSessao)(ctx.raiz, ctx.thread.id, { canal: ctx.canal ?? 'cli', correlacao: ctx.correlacao ?? null,
|
|
485
|
+
operacao: ctx.origem.startsWith('retry') ? 'retry.run' : 'phase.run', fase: ctx.fase, promptSha256: ctx.promptSha256,
|
|
486
|
+
identidade: ctx.identidade?.dispatchId ?? null, prazoMs }, sessao);
|
|
487
|
+
}
|
|
488
|
+
catch { /* a conducao protege a worktree; um despacho ja provado nao se desfaz por falta dela */ }
|
|
489
|
+
}
|
|
490
|
+
/** I-36: o prazo do lease de uma sessao do bloco: o limite de duracao dele, ou o padrao. */
|
|
491
|
+
function prazoDaSessao(limites) {
|
|
492
|
+
return limites?.duracaoMs ? limites.duracaoMs + conducao_1.MARGEM_DO_PRAZO_MS : conducao_1.PRAZO_DE_SESSAO_PADRAO_MS;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* D4: registro da fonte e arranque do observador no ponto comum a `phase` e `retry`.
|
|
496
|
+
* Sem CLI manual e sem segundo runtime: quem despacha e prova a sessao inicia a observacao.
|
|
497
|
+
*/
|
|
498
|
+
function registrarObservacao(ctx, sessao, dir, controlador, sensores) {
|
|
499
|
+
const mesmoDespacho = (e) => e.sessionId === sessao.sessionId && e.despachoEm === sessao.despachadaEm;
|
|
500
|
+
try {
|
|
501
|
+
// I-34: claude-bg observa pela fonte nativa; no PLAN o registro guarda o sha de base do artefato.
|
|
502
|
+
// I-33 (N1): o GO codex registra o HEAD do despacho, como a fonte claude-bg; sem ele a D11c nao ve commit pelo shell.
|
|
503
|
+
const head = ctx.runtime === 'codex' && ctx.fase === 'GO' ? { head: ctx.headNoDespacho ?? null } : {};
|
|
504
|
+
const fonte = ctx.runtime === 'claude-bg' ? (0, session_watcher_claude_1.fonteClaudeDoDespacho)(ctx.raiz, ctx.thread.id, ctx.fase, ctx.cwd)
|
|
505
|
+
: sensores?.logPath ? { logPath: sensores.logPath, processoPath: sensores.processoPath, reciboPath: sensores.reciboPath, ...head }
|
|
506
|
+
: controlador ? { controlador, cwd: ctx.cwd, ...head } : null;
|
|
507
|
+
if (!fonte)
|
|
508
|
+
return;
|
|
509
|
+
(0, session_watcher_1.validarFonteWatcher)(ctx.raiz, sessao.sessionId, fonte);
|
|
510
|
+
const eventos = (0, ledger_1.lerLedger)(dir);
|
|
511
|
+
if (!eventos.some(e => e.tipo === 'session_sensor_registered' && mesmoDespacho(e))) {
|
|
512
|
+
(0, ledger_1.registrar)(dir, ctx.thread.id, 'session_sensor_registered', { fase: ctx.fase,
|
|
513
|
+
sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm, ...fonte, ...(ctx.perfil ? { perfil: ctx.perfil } : {}) });
|
|
514
|
+
}
|
|
515
|
+
// A primitiva verifica identidade/prontidao e ignora registros antigos sem prova.
|
|
516
|
+
(0, session_watcher_1.iniciarWatcher)(ctx.raiz, sessao.sessionId);
|
|
517
|
+
}
|
|
518
|
+
catch {
|
|
519
|
+
(0, ledger_1.registrar)(dir, ctx.thread.id, 'session_watcher_error', { fase: ctx.fase, sessionId: sessao.sessionId,
|
|
520
|
+
despachoEm: sessao.despachadaEm, motivo: 'runtime.unavailable', erro: 'fonte ou prontidao do watcher invalida',
|
|
521
|
+
origem: 'phase.dispatch', ...(controlador ? { controlador } : {}) });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
252
524
|
/** Despacha a fase pelo runtime adapter e registra tudo no ledger da thread. */
|
|
253
525
|
function rodarFase(carregado, threadId, opcoes) {
|
|
526
|
+
const rodar = () => opcoes.dryRun ? rodarFaseSobLock(carregado, threadId, opcoes) :
|
|
527
|
+
(0, hitl_gates_1.comLockHitl)(carregado.raiz, threadId, () => rodarFaseSobLock(carregado, threadId, opcoes));
|
|
528
|
+
// I-36 (D2): `--esperar` espera a vez FORA do lock HITL (que serializa respostas do dono) e so
|
|
529
|
+
// depois repete o pedido. Sem ele, a recusa sai na hora.
|
|
530
|
+
const prazo = opcoes.esperarMs && opcoes.esperarMs > 0 && !opcoes.dryRun ? Date.now() + opcoes.esperarMs : null;
|
|
531
|
+
for (;;) {
|
|
532
|
+
if (prazo)
|
|
533
|
+
(0, conducao_1.esperarConducaoLivre)(carregado.raiz, threadId, Math.max(0, prazo - Date.now()));
|
|
534
|
+
const r = rodar();
|
|
535
|
+
if (r.motivo !== 'conducao.em-andamento' || !prazo || Date.now() >= prazo)
|
|
536
|
+
return r;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
function rodarFaseSobLock(carregado, threadId, opcoes) {
|
|
254
540
|
const { raiz, manifesto } = carregado;
|
|
255
541
|
const thread = (0, thread_1.lerThread)(raiz, threadId);
|
|
256
542
|
const fase = opcoes.fase;
|
|
257
543
|
const dir = (0, thread_1.dirThread)(raiz, thread.id);
|
|
258
544
|
const slug = slugDaSessao(thread, fase);
|
|
259
|
-
// Resolve UMA vez o
|
|
260
|
-
// ledger e a resposta do CLI. Resolver duas vezes e o caminho curto para o ledger
|
|
261
|
-
// dizer um modelo e o
|
|
262
|
-
|
|
545
|
+
// Resolve UMA vez o trio runtime/modelo/esforco: o mesmo objeto vai ao runtime adapter,
|
|
546
|
+
// ao ledger e a resposta do CLI. Resolver duas vezes e o caminho curto para o ledger
|
|
547
|
+
// dizer um modelo e o runtime receber outro. O setup do bloco (feature #setup) entra
|
|
548
|
+
// aqui: cada bloco de cada modo pode abrir a sessao com runtime/modelo/esforco proprios.
|
|
549
|
+
const setup = (0, setup_1.lerSetup)(raiz);
|
|
550
|
+
const doBloco = (0, setup_1.configDoBloco)(setup, thread.modo, fase);
|
|
551
|
+
const { runtime, model, effort } = resolverDespacho(manifesto, opcoes, doBloco);
|
|
552
|
+
const limites = (0, setup_1.limitesDoBloco)(manifesto, setup, thread.modo, fase);
|
|
553
|
+
const rt = (0, runtimes_1.resolverRuntime)(runtime);
|
|
263
554
|
// Bloco B6: a memoria entra ANTES do hash. O prompt que o ledger carimba e o mesmo que
|
|
264
555
|
// o agente recebe, memoria injetada inclusa.
|
|
265
556
|
const memoria = opcoes.memoria ?? (0, memoria_1.abrirMemoria)(carregado);
|
|
@@ -296,6 +587,7 @@ function rodarFase(carregado, threadId, opcoes) {
|
|
|
296
587
|
verificada: false,
|
|
297
588
|
pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase),
|
|
298
589
|
dryRun: opcoes.dryRun === true,
|
|
590
|
+
runtime,
|
|
299
591
|
model,
|
|
300
592
|
effort,
|
|
301
593
|
bloqueado: true,
|
|
@@ -304,173 +596,327 @@ function rodarFase(carregado, threadId, opcoes) {
|
|
|
304
596
|
erro: detalhe,
|
|
305
597
|
};
|
|
306
598
|
}
|
|
307
|
-
(
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
slug,
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
itens: injecao.itens.map((i) => `${i.id}:${i.colecao}:${i.location}`),
|
|
319
|
-
promptSha256: sha,
|
|
320
|
-
});
|
|
599
|
+
// I-43 (D4, viga a): a validacao por runtime diferente e cobrada no MESMO portao
|
|
600
|
+
// por onde todo despacho ja passa. Trocar um portao por outro no mesmo lugar e a
|
|
601
|
+
// mudanca que o CHECK consegue conferir lendo um diff.
|
|
602
|
+
const erroDeRuntime = runtimeCruzadoParaDespacho(thread, fase, runtime);
|
|
603
|
+
if (erroDeRuntime) {
|
|
604
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.autoconferencia',
|
|
605
|
+
modo: thread.modo, detalhe: erroDeRuntime, fase, slug,
|
|
606
|
+
correcao: `ork phase run ${thread.id} CHECK --runtime <outro> --prompt "<pedido>"` });
|
|
607
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
608
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
609
|
+
runtime, model, effort, bloqueado: true, motivo: 'runtime.autoconferencia', violacoes, erro: erroDeRuntime };
|
|
321
610
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
slug
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
motivo:
|
|
329
|
-
detalhe: memoria.estado.detalhe,
|
|
330
|
-
correcao: memoria.estado.correcao,
|
|
331
|
-
});
|
|
611
|
+
const erroDeEstado = estadoParaDespacho(raiz, thread, opcoes.dryRun);
|
|
612
|
+
if (erroDeEstado) {
|
|
613
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'tree.blocked',
|
|
614
|
+
modo: thread.modo, detalhe: erroDeEstado, correcao: `ork worktree sync ${thread.id}`, fase, slug });
|
|
615
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
616
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
617
|
+
runtime, model, effort, bloqueado: true, motivo: 'tree.blocked', violacoes, erro: erroDeEstado };
|
|
332
618
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
619
|
+
// I-36 (T7, T14): validado o pedido, a conducao da thread, antes de tocar a worktree. A mesma fase com o
|
|
620
|
+
// mesmo prompt de quem conduz devolve a sessao em andamento sem chamar o adapter; outro pedido recebe a recusa.
|
|
621
|
+
const identidade = (0, runtime_context_1.novaIdentidadeDeDespacho)(thread.id, fase);
|
|
622
|
+
const canal = opcoes.canal ?? (0, conducao_1.canalDoProcesso)();
|
|
623
|
+
const pedidoDeConducao = { canal, correlacao: opcoes.correlacao ?? null, operacao: 'phase.run', fase,
|
|
624
|
+
promptSha256: sha, identidade: identidade.dispatchId, prazoMs: prazoDaSessao(limites) };
|
|
625
|
+
const ocupadaPor = (ocupada, gravarNoLedger) => {
|
|
626
|
+
const base = { thread, slug, promptPath, promptSha256: sha, comando: [], verificada: false,
|
|
627
|
+
pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true, runtime, model, effort, violacoes: [] };
|
|
628
|
+
const atual = ocupada.atual;
|
|
629
|
+
if (ocupada.idempotente && atual) {
|
|
630
|
+
if (gravarNoLedger)
|
|
631
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoIdempotente, { fase, promptSha256: sha, canal,
|
|
632
|
+
sessionId: atual.sessao, conducao: { canal: atual.canal, desde: atual.desde },
|
|
633
|
+
razao: 'mesma fase e mesmo prompt de quem ja conduz: a sessao em andamento atende o pedido, sem sessao nova e sem cota' });
|
|
634
|
+
return { ...base, sessionId: atual.sessao, bloqueado: false, motivo: null, idempotente: true, conducao: atual };
|
|
635
|
+
}
|
|
636
|
+
const recusa = (0, conducao_1.recusaDeConducao)(thread.id, atual, pedidoDeConducao);
|
|
637
|
+
if (gravarNoLedger)
|
|
638
|
+
(0, conducao_1.registrarRecusa)(raiz, recusa);
|
|
639
|
+
return { ...base, sessionId: null, bloqueado: true, motivo: 'conducao.em-andamento', erro: recusa.texto, recusa,
|
|
640
|
+
...(atual ? { conducao: atual } : {}) };
|
|
355
641
|
};
|
|
356
|
-
|
|
642
|
+
let conducao = null;
|
|
357
643
|
if (opcoes.dryRun) {
|
|
358
|
-
|
|
644
|
+
// O ensaio nao toma nada, mas diz a verdade: com conducao em andamento, o despacho real seria recusado.
|
|
645
|
+
const atual = (0, conducao_1.conducaoDaThread)(raiz, thread.id);
|
|
646
|
+
if (atual)
|
|
647
|
+
return ocupadaPor({ ok: false, idempotente: atual.fase === fase && atual.promptSha256 === sha, atual }, false);
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
const tomada = (0, conducao_1.tomarConducao)(raiz, thread.id, pedidoDeConducao);
|
|
651
|
+
if (!tomada.ok)
|
|
652
|
+
return ocupadaPor(tomada, true);
|
|
653
|
+
conducao = tomada;
|
|
654
|
+
}
|
|
655
|
+
try {
|
|
656
|
+
const cwd = thread.worktree ?? raiz;
|
|
657
|
+
let contextoRuntime;
|
|
658
|
+
try {
|
|
659
|
+
contextoRuntime = (0, runtime_context_1.contextoDoProjeto)(raiz, runtime, cwd, thread.id);
|
|
660
|
+
}
|
|
661
|
+
catch (e) {
|
|
662
|
+
const erro = `runtime.unavailable: ${e.message}`;
|
|
663
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.unavailable',
|
|
664
|
+
modo: thread.modo, detalhe: erro, fase, slug });
|
|
665
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
666
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
667
|
+
runtime, model, effort, bloqueado: true, motivo: 'runtime.unavailable', violacoes, erro };
|
|
668
|
+
}
|
|
669
|
+
if (contextoRuntime)
|
|
670
|
+
contextoRuntime.identidade = identidade;
|
|
671
|
+
(0, util_1.gravar)(promptPath, prompt);
|
|
672
|
+
// I-33 (D2, D4, D7): o perfil sai do store com o login conferido. Sem perfil disponivel, o
|
|
673
|
+
// despacho nao sai pela conta errada: o prompt ja gravado fica registrado para a rotacao do
|
|
674
|
+
// retry (outro runtime da ordem de fallback, ou a fila), com o motivo tipado.
|
|
675
|
+
let escolha;
|
|
676
|
+
try {
|
|
677
|
+
escolha = perfilParaDespacho(carregado, thread, fase, runtime, { perfil: opcoes.perfil, dryRun: opcoes.dryRun, origem: 'phase.run' });
|
|
678
|
+
}
|
|
679
|
+
catch (e) {
|
|
680
|
+
escolha = { perfil: null, configurados: 0, erro: e.message };
|
|
681
|
+
}
|
|
682
|
+
if (escolha.erro) {
|
|
683
|
+
const motivo = escolha.motivo ?? 'runtime.unavailable';
|
|
684
|
+
const erro = `${motivo}: ${escolha.erro}`;
|
|
685
|
+
if (!opcoes.dryRun) {
|
|
686
|
+
const semPerfil = { identidade, raiz, thread, fase, slug, promptPath, promptSha256: sha, runtime, cwd, model, effort,
|
|
687
|
+
origem: 'phase.run', canal, correlacao: opcoes.correlacao ?? null };
|
|
688
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoFalhou, { ...dadosDoDespacho(semPerfil, []), erro });
|
|
689
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo, modo: thread.modo, detalhe: erro,
|
|
690
|
+
correcao: motivo === 'cost.violation'
|
|
691
|
+
? 'refaca o login do perfil pela assinatura (claude auth login --claudeai ou codex login com ChatGPT) e rode ork accounts check; perfil de provider pago nunca despacha'
|
|
692
|
+
: 'ork accounts list mostra o estado de cada perfil; ork retry run segue pela ordem de fallback ou pela fila',
|
|
693
|
+
fase, slug, runtime, origem: 'phase.run' });
|
|
694
|
+
}
|
|
695
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
696
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
697
|
+
runtime, model, effort, bloqueado: true, motivo, violacoes, erro };
|
|
698
|
+
}
|
|
699
|
+
const perfil = escolha.perfil ?? undefined;
|
|
700
|
+
// A injecao e evidencia: o ledger diz quantos itens entraram, de que colecao e de onde,
|
|
701
|
+
// para que "o prompt tinha a decisao D2" seja verificavel depois sem reler o prompt.
|
|
702
|
+
if (injecao.itens.length > 0) {
|
|
703
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.memoriaInjetada, {
|
|
704
|
+
fase,
|
|
705
|
+
slug,
|
|
706
|
+
regime: injecao.regime,
|
|
707
|
+
decisoes: injecao.decisoes,
|
|
708
|
+
licoes: injecao.licoes,
|
|
709
|
+
regras: injecao.regras,
|
|
710
|
+
itens: injecao.itens.map((i) => `${i.id}:${i.colecao}:${i.location}`),
|
|
711
|
+
promptSha256: sha,
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
if (memoria.estado.motivo && memoria.estado.pedido === 'orkmind') {
|
|
715
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.memoriaDegradada, {
|
|
716
|
+
fase,
|
|
717
|
+
slug,
|
|
718
|
+
pedido: memoria.estado.pedido,
|
|
719
|
+
efetivo: memoria.estado.efetivo,
|
|
720
|
+
motivo: memoria.estado.motivo,
|
|
721
|
+
detalhe: memoria.estado.detalhe,
|
|
722
|
+
correcao: memoria.estado.correcao,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
const pausaAoFim = (0, thread_1.pausaNaThread)(thread, fase);
|
|
726
|
+
const claimsSchema = fase === 'GO' && runtime === 'codex'
|
|
727
|
+
? schemaDeClaimsDoPacote()
|
|
728
|
+
: undefined;
|
|
729
|
+
// I-33 (N1): lido antes de a sessao existir; depois dela, um commit rapido ja estaria no HEAD.
|
|
730
|
+
const headNoDespacho = fase === 'GO' && runtime === 'codex' && !opcoes.dryRun ? (0, session_watcher_claude_1.headDaWorktree)(cwd) : undefined;
|
|
731
|
+
const resultado = rt.despachar({
|
|
732
|
+
prompt,
|
|
733
|
+
nome: slug,
|
|
734
|
+
cwd,
|
|
735
|
+
model,
|
|
736
|
+
effort,
|
|
737
|
+
dryRun: opcoes.dryRun,
|
|
738
|
+
sandbox: manifesto.runtime.sandbox,
|
|
739
|
+
logDir: path.join(dir, 'sessoes'),
|
|
740
|
+
vinculo: { thread: thread.id, fase, promptSha256: sha },
|
|
741
|
+
contextoRuntime,
|
|
742
|
+
...(perfil ? { perfil } : {}),
|
|
743
|
+
...(fase === 'PLAN' ? { colaboracao: 'plan' } : {}),
|
|
744
|
+
...(claimsSchema ? { outputSchema: claimsSchema } : {}),
|
|
745
|
+
// `thread.base.branch` vira a branch fonte quando a thread ganha worktree
|
|
746
|
+
// (`ork/<slug>`). O review nativo precisa comparar essa fonte com a base de
|
|
747
|
+
// integração do projeto; usar a própria fonte produz um diff vazio.
|
|
748
|
+
...(fase === 'CHECK' && runtime === 'codex' ? { reviewBaseBranch: manifesto.worktree.base_branch } : {}),
|
|
749
|
+
...(limites ? { duracaoMaximaMs: limites.duracaoMs } : {}),
|
|
750
|
+
// I-36 (D4): a sessao filha herda a identidade do despacho e o canal; e assim que ela reentra.
|
|
751
|
+
ambienteExtra: (0, conducao_1.ambienteDaConducao)(identidade.dispatchId, thread.id, canal),
|
|
752
|
+
});
|
|
753
|
+
const ctx = {
|
|
754
|
+
identidade,
|
|
755
|
+
canal,
|
|
756
|
+
correlacao: opcoes.correlacao ?? null,
|
|
757
|
+
...(conducao ? { conducao } : {}),
|
|
758
|
+
prazoDaSessaoMs: pedidoDeConducao.prazoMs,
|
|
759
|
+
raiz,
|
|
359
760
|
thread,
|
|
761
|
+
fase,
|
|
360
762
|
slug,
|
|
361
763
|
promptPath,
|
|
362
764
|
promptSha256: sha,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
verificada: false,
|
|
366
|
-
pausaAoFim,
|
|
367
|
-
dryRun: true,
|
|
368
|
-
// O ensaio NAO toca no ledger (a garantia do B0 continua de pe), mas devolve o
|
|
369
|
-
// par resolvido: e assim que o `--dry-run` mostra o modelo que seria despachado.
|
|
765
|
+
runtime,
|
|
766
|
+
cwd,
|
|
370
767
|
model,
|
|
371
768
|
effort,
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
769
|
+
origem: 'phase.run',
|
|
770
|
+
...(perfil ? { perfil } : {}),
|
|
771
|
+
...(headNoDespacho !== undefined ? { headNoDespacho } : {}),
|
|
375
772
|
};
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
...comum,
|
|
381
|
-
erro,
|
|
382
|
-
stderr: resultado.stderr.slice(0, 500),
|
|
383
|
-
});
|
|
384
|
-
// Bloco B3: rate limit nao e falha seca. A fase morreu com HORA de volta, entao ela
|
|
385
|
-
// vira pedido na fila duravel em vez de virar tarefa da memoria de alguem. O prompt
|
|
386
|
-
// ja esta gravado em disco com o sha256 acima, e e ele que sera redespachado.
|
|
387
|
-
const sinal = resultado.rateLimit ?? null;
|
|
388
|
-
if (sinal) {
|
|
389
|
-
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rateLimitDetectado, {
|
|
390
|
-
fase,
|
|
391
|
-
slug,
|
|
392
|
-
fonte: sinal.fonte,
|
|
393
|
-
resetEm: sinal.resetEm,
|
|
394
|
-
trecho: sinal.trecho,
|
|
395
|
-
evidencia: 'stderr real do runtime adapter, nao relato do agente',
|
|
396
|
-
});
|
|
397
|
-
const pedido = (0, ratelimit_1.enfileirar)(carregado, {
|
|
398
|
-
thread: thread.id,
|
|
399
|
-
fase,
|
|
773
|
+
const comum = dadosDoDespacho(ctx, resultado.comando);
|
|
774
|
+
if (opcoes.dryRun) {
|
|
775
|
+
return {
|
|
776
|
+
thread,
|
|
400
777
|
slug,
|
|
401
778
|
promptPath,
|
|
402
779
|
promptSha256: sha,
|
|
403
|
-
|
|
780
|
+
comando: resultado.comando,
|
|
781
|
+
sessionId: null,
|
|
782
|
+
verificada: false,
|
|
783
|
+
pausaAoFim,
|
|
784
|
+
dryRun: true,
|
|
785
|
+
// O ensaio NAO toca no ledger (a garantia do B0 continua de pe), mas devolve o
|
|
786
|
+
// par resolvido: e assim que o `--dry-run` mostra o modelo que seria despachado.
|
|
787
|
+
runtime,
|
|
404
788
|
model,
|
|
405
789
|
effort,
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
790
|
+
bloqueado: false,
|
|
791
|
+
motivo: null,
|
|
792
|
+
violacoes,
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
if (!resultado.ok || !resultado.sessionId) {
|
|
796
|
+
const erro = resultado.erro ?? 'sem sessionId na saida do runtime';
|
|
797
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoFalhou, {
|
|
798
|
+
...comum,
|
|
799
|
+
controlador: resultado.controlador,
|
|
800
|
+
erro,
|
|
801
|
+
stderr: resultado.stderr.slice(0, 500),
|
|
418
802
|
});
|
|
803
|
+
// I-33 (D1, D5): a CONTA recusou o despacho. Nada rodou, entao nada foi produzido: o perfil
|
|
804
|
+
// sai do rodizio e o gate tipado fica para a rotacao do retry, que redespacha o mesmo prompt.
|
|
805
|
+
const falha = resultado.falhaDeConta ?? null;
|
|
806
|
+
if (falha) {
|
|
807
|
+
try {
|
|
808
|
+
(0, ratelimit_1.marcarContaDaFalha)(carregado, perfil, falha);
|
|
809
|
+
}
|
|
810
|
+
catch { /* o gate abaixo continua registrando a falha */ }
|
|
811
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: falha.motivo, modo: thread.modo, detalhe: erro,
|
|
812
|
+
correcao: 'ork retry run rotaciona para o proximo perfil, para o runtime de fallback ou para a fila', fase, slug,
|
|
813
|
+
runtime, origem: 'phase.run', falhaDeConta: falha, ...(perfil ? { perfil } : {}),
|
|
814
|
+
evidencia: 'saida real do runtime adapter no despacho, nao relato do agente' });
|
|
815
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: resultado.comando, controlador: resultado.controlador,
|
|
816
|
+
sessionId: null, verificada: false, pausaAoFim, dryRun: false, runtime, model, effort, bloqueado: false,
|
|
817
|
+
motivo: falha.motivo, violacoes, naFila: null, erro };
|
|
818
|
+
}
|
|
819
|
+
// Bloco B3: rate limit nao e falha seca. A fase morreu com HORA de volta, entao ela
|
|
820
|
+
// vira pedido na fila duravel em vez de virar tarefa da memoria de alguem. O prompt
|
|
821
|
+
// ja esta gravado em disco com o sha256 acima, e e ele que sera redespachado.
|
|
822
|
+
const sinal = resultado.rateLimit ?? null;
|
|
823
|
+
if (sinal) {
|
|
824
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rateLimitDetectado, {
|
|
825
|
+
fase,
|
|
826
|
+
slug,
|
|
827
|
+
fonte: sinal.fonte,
|
|
828
|
+
resetEm: sinal.resetEm,
|
|
829
|
+
trecho: sinal.trecho,
|
|
830
|
+
evidencia: 'stderr real do runtime adapter, nao relato do agente',
|
|
831
|
+
});
|
|
832
|
+
const pedido = (0, ratelimit_1.enfileirar)(carregado, {
|
|
833
|
+
thread: thread.id,
|
|
834
|
+
fase,
|
|
835
|
+
slug,
|
|
836
|
+
promptPath,
|
|
837
|
+
promptSha256: sha,
|
|
838
|
+
cwd,
|
|
839
|
+
model,
|
|
840
|
+
effort,
|
|
841
|
+
sinal,
|
|
842
|
+
detalhe: erro,
|
|
843
|
+
});
|
|
844
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rateLimitEnfileirado, {
|
|
845
|
+
fase,
|
|
846
|
+
slug,
|
|
847
|
+
pedido: pedido.id,
|
|
848
|
+
liberaEm: pedido.liberaEm,
|
|
849
|
+
janelaEstimada: pedido.janelaEstimada,
|
|
850
|
+
fonte: sinal.fonte,
|
|
851
|
+
promptSha256: sha,
|
|
852
|
+
correcao: `ork retry resume (ou aguarde ate ${pedido.liberaEm})`,
|
|
853
|
+
});
|
|
854
|
+
return {
|
|
855
|
+
thread,
|
|
856
|
+
slug,
|
|
857
|
+
promptPath,
|
|
858
|
+
promptSha256: sha,
|
|
859
|
+
comando: resultado.comando,
|
|
860
|
+
controlador: resultado.controlador,
|
|
861
|
+
sessionId: null,
|
|
862
|
+
verificada: false,
|
|
863
|
+
pausaAoFim,
|
|
864
|
+
dryRun: false,
|
|
865
|
+
runtime,
|
|
866
|
+
model,
|
|
867
|
+
effort,
|
|
868
|
+
bloqueado: false,
|
|
869
|
+
motivo: 'runtime.rate-limited',
|
|
870
|
+
violacoes,
|
|
871
|
+
naFila: pedido,
|
|
872
|
+
erro,
|
|
873
|
+
};
|
|
874
|
+
}
|
|
419
875
|
return {
|
|
420
876
|
thread,
|
|
421
877
|
slug,
|
|
422
878
|
promptPath,
|
|
423
879
|
promptSha256: sha,
|
|
424
880
|
comando: resultado.comando,
|
|
881
|
+
controlador: resultado.controlador,
|
|
425
882
|
sessionId: null,
|
|
426
883
|
verificada: false,
|
|
427
884
|
pausaAoFim,
|
|
428
885
|
dryRun: false,
|
|
886
|
+
runtime,
|
|
429
887
|
model,
|
|
430
888
|
effort,
|
|
431
889
|
bloqueado: false,
|
|
432
|
-
motivo: 'runtime.
|
|
890
|
+
motivo: 'runtime.unavailable',
|
|
433
891
|
violacoes,
|
|
434
|
-
naFila:
|
|
892
|
+
naFila: null,
|
|
435
893
|
erro,
|
|
436
894
|
};
|
|
437
895
|
}
|
|
896
|
+
concluirDespacho(ctx, resultado.sessionId, resultado.verificada, resultado.comando, rt.fonteVerificacao, resultado.controlador, { logPath: resultado.logPath, processoPath: resultado.processoPath, reciboPath: resultado.reciboPath });
|
|
438
897
|
return {
|
|
439
898
|
thread,
|
|
440
899
|
slug,
|
|
441
900
|
promptPath,
|
|
442
901
|
promptSha256: sha,
|
|
443
902
|
comando: resultado.comando,
|
|
444
|
-
sessionId:
|
|
445
|
-
|
|
903
|
+
sessionId: resultado.sessionId,
|
|
904
|
+
controlador: resultado.controlador,
|
|
905
|
+
verificada: resultado.verificada,
|
|
446
906
|
pausaAoFim,
|
|
447
907
|
dryRun: false,
|
|
908
|
+
runtime,
|
|
448
909
|
model,
|
|
449
910
|
effort,
|
|
450
911
|
bloqueado: false,
|
|
451
|
-
motivo:
|
|
912
|
+
motivo: null,
|
|
452
913
|
violacoes,
|
|
453
|
-
naFila: null,
|
|
454
|
-
erro,
|
|
455
914
|
};
|
|
456
915
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
promptPath,
|
|
462
|
-
promptSha256: sha,
|
|
463
|
-
comando: resultado.comando,
|
|
464
|
-
sessionId: resultado.sessionId,
|
|
465
|
-
verificada: resultado.verificada,
|
|
466
|
-
pausaAoFim,
|
|
467
|
-
dryRun: false,
|
|
468
|
-
model,
|
|
469
|
-
effort,
|
|
470
|
-
bloqueado: false,
|
|
471
|
-
motivo: null,
|
|
472
|
-
violacoes,
|
|
473
|
-
};
|
|
916
|
+
finally {
|
|
917
|
+
// Despacho que nao virou sessao devolve a conducao; o que virou ja a entregou a sessao.
|
|
918
|
+
conducao?.liberar();
|
|
919
|
+
}
|
|
474
920
|
}
|
|
475
921
|
/** Tabela de `ork phase list`: o historico do ledger da thread. */
|
|
476
922
|
function tabelaDoLedger(raiz, threadId) {
|
|
@@ -523,7 +969,7 @@ function tabelaDoLedger(raiz, threadId) {
|
|
|
523
969
|
if (e.cobertura)
|
|
524
970
|
detalhe.push(`cobertura ${String(e.cobertura)}`);
|
|
525
971
|
if (e.liberaEm)
|
|
526
|
-
detalhe.push(`libera em ${String(e.liberaEm)}`);
|
|
972
|
+
detalhe.push(`libera em ${(0, horario_1.formatarDataHora)(String(e.liberaEm))}`);
|
|
527
973
|
if (e.tentativa !== undefined && e.limite !== undefined) {
|
|
528
974
|
detalhe.push(`tentativa ${String(e.tentativa)}/${String(e.limite)}`);
|
|
529
975
|
}
|
|
@@ -555,12 +1001,12 @@ function tabelaDoLedger(raiz, threadId) {
|
|
|
555
1001
|
if (e.erro)
|
|
556
1002
|
detalhe.push(`erro: ${String(e.erro)}`);
|
|
557
1003
|
if (e.detalhe && !e.decisao)
|
|
558
|
-
detalhe.push(String(e.detalhe).slice(0, 90));
|
|
1004
|
+
detalhe.push((0, horario_1.localizarTexto)(String(e.detalhe)).slice(0, 90));
|
|
559
1005
|
if (e.modo && !e.fase)
|
|
560
1006
|
detalhe.push(`modo ${String(e.modo)}`);
|
|
561
|
-
return [
|
|
1007
|
+
return [(0, horario_1.formatarDataHora)(e.ts, { segundos: true }), e.tipo, detalhe.join(' | ')];
|
|
562
1008
|
});
|
|
563
|
-
return (0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas)
|
|
1009
|
+
return `${(0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas)}\n${(0, horario_1.legendaDoFuso)()}`;
|
|
564
1010
|
}
|
|
565
1011
|
/** Slug legivel por humano de uma sessao (usado nas mensagens do CLI). */
|
|
566
1012
|
function descreverSlug(slug) {
|