@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/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);
|
|
@@ -269,8 +560,23 @@ function rodarFase(carregado, threadId, opcoes) {
|
|
|
269
560
|
// Gate tipado do bloco B1: as policies do manifesto valem ANTES do despacho, em
|
|
270
561
|
// qualquer modo. Prompt reprovado nem chega a ser gravado em disco: gravar um prompt
|
|
271
562
|
// com credencial e criar um segundo vazamento no proprio repositorio.
|
|
272
|
-
|
|
563
|
+
// RM-008 (fatia 3): as licoes que viraram policy recebem os fatos da thread, calculados aqui.
|
|
564
|
+
const blocoDespachado = (0, thread_1.blocoDaThread)(thread, fase);
|
|
565
|
+
const violacoes = (0, policies_1.avaliarPolicies)(manifesto, {
|
|
566
|
+
gate: 'phase.dispatch', prompt, threadId: thread.id, modo: thread.modo, fase,
|
|
567
|
+
bloco: thread.blocos.indexOf(blocoDespachado) + 1,
|
|
568
|
+
blocoComGo: blocoDespachado.fases.includes('GO'),
|
|
569
|
+
temBaseline: (0, ledger_1.lerLedger)(dir).some((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.baselineGravada),
|
|
570
|
+
fallbackDoBloco: (0, setup_1.fallbackDoBloco)(setup, thread.modo, fase),
|
|
571
|
+
});
|
|
273
572
|
const bloqueiam = (0, policies_1.bloqueantes)(violacoes);
|
|
573
|
+
// Warn registra e segue: o aviso vai ao ledger (fora do ensaio) e o despacho continua.
|
|
574
|
+
if (!opcoes.dryRun) {
|
|
575
|
+
for (const v of (0, policies_1.avisos)(violacoes)) {
|
|
576
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.politicaAviso, { gate: 'phase.dispatch', fase, slug,
|
|
577
|
+
policy: v.policy, detalhe: v.detalhe, correcao: v.correcao, modo: thread.modo });
|
|
578
|
+
}
|
|
579
|
+
}
|
|
274
580
|
if (bloqueiam.length > 0) {
|
|
275
581
|
const detalhe = bloqueiam.map((v) => `${v.policy}: ${v.detalhe}`).join('; ');
|
|
276
582
|
// Bloco B3: violacao de CUSTO sai tipada como tal. E o que permite a politica de
|
|
@@ -296,6 +602,7 @@ function rodarFase(carregado, threadId, opcoes) {
|
|
|
296
602
|
verificada: false,
|
|
297
603
|
pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase),
|
|
298
604
|
dryRun: opcoes.dryRun === true,
|
|
605
|
+
runtime,
|
|
299
606
|
model,
|
|
300
607
|
effort,
|
|
301
608
|
bloqueado: true,
|
|
@@ -304,173 +611,327 @@ function rodarFase(carregado, threadId, opcoes) {
|
|
|
304
611
|
erro: detalhe,
|
|
305
612
|
};
|
|
306
613
|
}
|
|
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
|
-
});
|
|
614
|
+
// I-43 (D4, viga a): a validacao por runtime diferente e cobrada no MESMO portao
|
|
615
|
+
// por onde todo despacho ja passa. Trocar um portao por outro no mesmo lugar e a
|
|
616
|
+
// mudanca que o CHECK consegue conferir lendo um diff.
|
|
617
|
+
const erroDeRuntime = runtimeCruzadoParaDespacho(thread, fase, runtime);
|
|
618
|
+
if (erroDeRuntime) {
|
|
619
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.autoconferencia',
|
|
620
|
+
modo: thread.modo, detalhe: erroDeRuntime, fase, slug,
|
|
621
|
+
correcao: `ork phase run ${thread.id} CHECK --runtime <outro> --prompt "<pedido>"` });
|
|
622
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
623
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
624
|
+
runtime, model, effort, bloqueado: true, motivo: 'runtime.autoconferencia', violacoes, erro: erroDeRuntime };
|
|
321
625
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
slug
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
motivo:
|
|
329
|
-
detalhe: memoria.estado.detalhe,
|
|
330
|
-
correcao: memoria.estado.correcao,
|
|
331
|
-
});
|
|
626
|
+
const erroDeEstado = estadoParaDespacho(raiz, thread, opcoes.dryRun);
|
|
627
|
+
if (erroDeEstado) {
|
|
628
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'tree.blocked',
|
|
629
|
+
modo: thread.modo, detalhe: erroDeEstado, correcao: `ork worktree sync ${thread.id}`, fase, slug });
|
|
630
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
631
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
632
|
+
runtime, model, effort, bloqueado: true, motivo: 'tree.blocked', violacoes, erro: erroDeEstado };
|
|
332
633
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
634
|
+
// I-36 (T7, T14): validado o pedido, a conducao da thread, antes de tocar a worktree. A mesma fase com o
|
|
635
|
+
// mesmo prompt de quem conduz devolve a sessao em andamento sem chamar o adapter; outro pedido recebe a recusa.
|
|
636
|
+
const identidade = (0, runtime_context_1.novaIdentidadeDeDespacho)(thread.id, fase);
|
|
637
|
+
const canal = opcoes.canal ?? (0, conducao_1.canalDoProcesso)();
|
|
638
|
+
const pedidoDeConducao = { canal, correlacao: opcoes.correlacao ?? null, operacao: 'phase.run', fase,
|
|
639
|
+
promptSha256: sha, identidade: identidade.dispatchId, prazoMs: prazoDaSessao(limites) };
|
|
640
|
+
const ocupadaPor = (ocupada, gravarNoLedger) => {
|
|
641
|
+
const base = { thread, slug, promptPath, promptSha256: sha, comando: [], verificada: false,
|
|
642
|
+
pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true, runtime, model, effort, violacoes: [] };
|
|
643
|
+
const atual = ocupada.atual;
|
|
644
|
+
if (ocupada.idempotente && atual) {
|
|
645
|
+
if (gravarNoLedger)
|
|
646
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoIdempotente, { fase, promptSha256: sha, canal,
|
|
647
|
+
sessionId: atual.sessao, conducao: { canal: atual.canal, desde: atual.desde },
|
|
648
|
+
razao: 'mesma fase e mesmo prompt de quem ja conduz: a sessao em andamento atende o pedido, sem sessao nova e sem cota' });
|
|
649
|
+
return { ...base, sessionId: atual.sessao, bloqueado: false, motivo: null, idempotente: true, conducao: atual };
|
|
650
|
+
}
|
|
651
|
+
const recusa = (0, conducao_1.recusaDeConducao)(thread.id, atual, pedidoDeConducao);
|
|
652
|
+
if (gravarNoLedger)
|
|
653
|
+
(0, conducao_1.registrarRecusa)(raiz, recusa);
|
|
654
|
+
return { ...base, sessionId: null, bloqueado: true, motivo: 'conducao.em-andamento', erro: recusa.texto, recusa,
|
|
655
|
+
...(atual ? { conducao: atual } : {}) };
|
|
355
656
|
};
|
|
356
|
-
|
|
657
|
+
let conducao = null;
|
|
357
658
|
if (opcoes.dryRun) {
|
|
358
|
-
|
|
659
|
+
// O ensaio nao toma nada, mas diz a verdade: com conducao em andamento, o despacho real seria recusado.
|
|
660
|
+
const atual = (0, conducao_1.conducaoDaThread)(raiz, thread.id);
|
|
661
|
+
if (atual)
|
|
662
|
+
return ocupadaPor({ ok: false, idempotente: atual.fase === fase && atual.promptSha256 === sha, atual }, false);
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
const tomada = (0, conducao_1.tomarConducao)(raiz, thread.id, pedidoDeConducao);
|
|
666
|
+
if (!tomada.ok)
|
|
667
|
+
return ocupadaPor(tomada, true);
|
|
668
|
+
conducao = tomada;
|
|
669
|
+
}
|
|
670
|
+
try {
|
|
671
|
+
const cwd = thread.worktree ?? raiz;
|
|
672
|
+
let contextoRuntime;
|
|
673
|
+
try {
|
|
674
|
+
contextoRuntime = (0, runtime_context_1.contextoDoProjeto)(raiz, runtime, cwd, thread.id);
|
|
675
|
+
}
|
|
676
|
+
catch (e) {
|
|
677
|
+
const erro = `runtime.unavailable: ${e.message}`;
|
|
678
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.unavailable',
|
|
679
|
+
modo: thread.modo, detalhe: erro, fase, slug });
|
|
680
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
681
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
682
|
+
runtime, model, effort, bloqueado: true, motivo: 'runtime.unavailable', violacoes, erro };
|
|
683
|
+
}
|
|
684
|
+
if (contextoRuntime)
|
|
685
|
+
contextoRuntime.identidade = identidade;
|
|
686
|
+
(0, util_1.gravar)(promptPath, prompt);
|
|
687
|
+
// I-33 (D2, D4, D7): o perfil sai do store com o login conferido. Sem perfil disponivel, o
|
|
688
|
+
// despacho nao sai pela conta errada: o prompt ja gravado fica registrado para a rotacao do
|
|
689
|
+
// retry (outro runtime da ordem de fallback, ou a fila), com o motivo tipado.
|
|
690
|
+
let escolha;
|
|
691
|
+
try {
|
|
692
|
+
escolha = perfilParaDespacho(carregado, thread, fase, runtime, { perfil: opcoes.perfil, dryRun: opcoes.dryRun, origem: 'phase.run' });
|
|
693
|
+
}
|
|
694
|
+
catch (e) {
|
|
695
|
+
escolha = { perfil: null, configurados: 0, erro: e.message };
|
|
696
|
+
}
|
|
697
|
+
if (escolha.erro) {
|
|
698
|
+
const motivo = escolha.motivo ?? 'runtime.unavailable';
|
|
699
|
+
const erro = `${motivo}: ${escolha.erro}`;
|
|
700
|
+
if (!opcoes.dryRun) {
|
|
701
|
+
const semPerfil = { identidade, raiz, thread, fase, slug, promptPath, promptSha256: sha, runtime, cwd, model, effort,
|
|
702
|
+
origem: 'phase.run', canal, correlacao: opcoes.correlacao ?? null };
|
|
703
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoFalhou, { ...dadosDoDespacho(semPerfil, []), erro });
|
|
704
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo, modo: thread.modo, detalhe: erro,
|
|
705
|
+
correcao: motivo === 'cost.violation'
|
|
706
|
+
? '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'
|
|
707
|
+
: 'ork accounts list mostra o estado de cada perfil; ork retry run segue pela ordem de fallback ou pela fila',
|
|
708
|
+
fase, slug, runtime, origem: 'phase.run' });
|
|
709
|
+
}
|
|
710
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
|
|
711
|
+
verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
|
|
712
|
+
runtime, model, effort, bloqueado: true, motivo, violacoes, erro };
|
|
713
|
+
}
|
|
714
|
+
const perfil = escolha.perfil ?? undefined;
|
|
715
|
+
// A injecao e evidencia: o ledger diz quantos itens entraram, de que colecao e de onde,
|
|
716
|
+
// para que "o prompt tinha a decisao D2" seja verificavel depois sem reler o prompt.
|
|
717
|
+
if (injecao.itens.length > 0) {
|
|
718
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.memoriaInjetada, {
|
|
719
|
+
fase,
|
|
720
|
+
slug,
|
|
721
|
+
regime: injecao.regime,
|
|
722
|
+
decisoes: injecao.decisoes,
|
|
723
|
+
licoes: injecao.licoes,
|
|
724
|
+
regras: injecao.regras,
|
|
725
|
+
itens: injecao.itens.map((i) => `${i.id}:${i.colecao}:${i.location}`),
|
|
726
|
+
promptSha256: sha,
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
if (memoria.estado.motivo && memoria.estado.pedido === 'orkmind') {
|
|
730
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.memoriaDegradada, {
|
|
731
|
+
fase,
|
|
732
|
+
slug,
|
|
733
|
+
pedido: memoria.estado.pedido,
|
|
734
|
+
efetivo: memoria.estado.efetivo,
|
|
735
|
+
motivo: memoria.estado.motivo,
|
|
736
|
+
detalhe: memoria.estado.detalhe,
|
|
737
|
+
correcao: memoria.estado.correcao,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
const pausaAoFim = (0, thread_1.pausaNaThread)(thread, fase);
|
|
741
|
+
const claimsSchema = fase === 'GO' && runtime === 'codex'
|
|
742
|
+
? schemaDeClaimsDoPacote()
|
|
743
|
+
: undefined;
|
|
744
|
+
// I-33 (N1): lido antes de a sessao existir; depois dela, um commit rapido ja estaria no HEAD.
|
|
745
|
+
const headNoDespacho = fase === 'GO' && runtime === 'codex' && !opcoes.dryRun ? (0, session_watcher_claude_1.headDaWorktree)(cwd) : undefined;
|
|
746
|
+
const resultado = rt.despachar({
|
|
747
|
+
prompt,
|
|
748
|
+
nome: slug,
|
|
749
|
+
cwd,
|
|
750
|
+
model,
|
|
751
|
+
effort,
|
|
752
|
+
dryRun: opcoes.dryRun,
|
|
753
|
+
sandbox: manifesto.runtime.sandbox,
|
|
754
|
+
logDir: path.join(dir, 'sessoes'),
|
|
755
|
+
vinculo: { thread: thread.id, fase, promptSha256: sha },
|
|
756
|
+
contextoRuntime,
|
|
757
|
+
...(perfil ? { perfil } : {}),
|
|
758
|
+
...(fase === 'PLAN' ? { colaboracao: 'plan' } : {}),
|
|
759
|
+
...(claimsSchema ? { outputSchema: claimsSchema } : {}),
|
|
760
|
+
// `thread.base.branch` vira a branch fonte quando a thread ganha worktree
|
|
761
|
+
// (`ork/<slug>`). O review nativo precisa comparar essa fonte com a base de
|
|
762
|
+
// integração do projeto; usar a própria fonte produz um diff vazio.
|
|
763
|
+
...(fase === 'CHECK' && runtime === 'codex' ? { reviewBaseBranch: manifesto.worktree.base_branch } : {}),
|
|
764
|
+
...(limites ? { duracaoMaximaMs: limites.duracaoMs } : {}),
|
|
765
|
+
// I-36 (D4): a sessao filha herda a identidade do despacho e o canal; e assim que ela reentra.
|
|
766
|
+
ambienteExtra: (0, conducao_1.ambienteDaConducao)(identidade.dispatchId, thread.id, canal),
|
|
767
|
+
});
|
|
768
|
+
const ctx = {
|
|
769
|
+
identidade,
|
|
770
|
+
canal,
|
|
771
|
+
correlacao: opcoes.correlacao ?? null,
|
|
772
|
+
...(conducao ? { conducao } : {}),
|
|
773
|
+
prazoDaSessaoMs: pedidoDeConducao.prazoMs,
|
|
774
|
+
raiz,
|
|
359
775
|
thread,
|
|
776
|
+
fase,
|
|
360
777
|
slug,
|
|
361
778
|
promptPath,
|
|
362
779
|
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.
|
|
780
|
+
runtime,
|
|
781
|
+
cwd,
|
|
370
782
|
model,
|
|
371
783
|
effort,
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
784
|
+
origem: 'phase.run',
|
|
785
|
+
...(perfil ? { perfil } : {}),
|
|
786
|
+
...(headNoDespacho !== undefined ? { headNoDespacho } : {}),
|
|
375
787
|
};
|
|
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,
|
|
788
|
+
const comum = dadosDoDespacho(ctx, resultado.comando);
|
|
789
|
+
if (opcoes.dryRun) {
|
|
790
|
+
return {
|
|
791
|
+
thread,
|
|
400
792
|
slug,
|
|
401
793
|
promptPath,
|
|
402
794
|
promptSha256: sha,
|
|
403
|
-
|
|
795
|
+
comando: resultado.comando,
|
|
796
|
+
sessionId: null,
|
|
797
|
+
verificada: false,
|
|
798
|
+
pausaAoFim,
|
|
799
|
+
dryRun: true,
|
|
800
|
+
// O ensaio NAO toca no ledger (a garantia do B0 continua de pe), mas devolve o
|
|
801
|
+
// par resolvido: e assim que o `--dry-run` mostra o modelo que seria despachado.
|
|
802
|
+
runtime,
|
|
404
803
|
model,
|
|
405
804
|
effort,
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
805
|
+
bloqueado: false,
|
|
806
|
+
motivo: null,
|
|
807
|
+
violacoes,
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
if (!resultado.ok || !resultado.sessionId) {
|
|
811
|
+
const erro = resultado.erro ?? 'sem sessionId na saida do runtime';
|
|
812
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoFalhou, {
|
|
813
|
+
...comum,
|
|
814
|
+
controlador: resultado.controlador,
|
|
815
|
+
erro,
|
|
816
|
+
stderr: resultado.stderr.slice(0, 500),
|
|
418
817
|
});
|
|
818
|
+
// I-33 (D1, D5): a CONTA recusou o despacho. Nada rodou, entao nada foi produzido: o perfil
|
|
819
|
+
// sai do rodizio e o gate tipado fica para a rotacao do retry, que redespacha o mesmo prompt.
|
|
820
|
+
const falha = resultado.falhaDeConta ?? null;
|
|
821
|
+
if (falha) {
|
|
822
|
+
try {
|
|
823
|
+
(0, ratelimit_1.marcarContaDaFalha)(carregado, perfil, falha);
|
|
824
|
+
}
|
|
825
|
+
catch { /* o gate abaixo continua registrando a falha */ }
|
|
826
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: falha.motivo, modo: thread.modo, detalhe: erro,
|
|
827
|
+
correcao: 'ork retry run rotaciona para o proximo perfil, para o runtime de fallback ou para a fila', fase, slug,
|
|
828
|
+
runtime, origem: 'phase.run', falhaDeConta: falha, ...(perfil ? { perfil } : {}),
|
|
829
|
+
evidencia: 'saida real do runtime adapter no despacho, nao relato do agente' });
|
|
830
|
+
return { thread, slug, promptPath, promptSha256: sha, comando: resultado.comando, controlador: resultado.controlador,
|
|
831
|
+
sessionId: null, verificada: false, pausaAoFim, dryRun: false, runtime, model, effort, bloqueado: false,
|
|
832
|
+
motivo: falha.motivo, violacoes, naFila: null, erro };
|
|
833
|
+
}
|
|
834
|
+
// Bloco B3: rate limit nao e falha seca. A fase morreu com HORA de volta, entao ela
|
|
835
|
+
// vira pedido na fila duravel em vez de virar tarefa da memoria de alguem. O prompt
|
|
836
|
+
// ja esta gravado em disco com o sha256 acima, e e ele que sera redespachado.
|
|
837
|
+
const sinal = resultado.rateLimit ?? null;
|
|
838
|
+
if (sinal) {
|
|
839
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rateLimitDetectado, {
|
|
840
|
+
fase,
|
|
841
|
+
slug,
|
|
842
|
+
fonte: sinal.fonte,
|
|
843
|
+
resetEm: sinal.resetEm,
|
|
844
|
+
trecho: sinal.trecho,
|
|
845
|
+
evidencia: 'stderr real do runtime adapter, nao relato do agente',
|
|
846
|
+
});
|
|
847
|
+
const pedido = (0, ratelimit_1.enfileirar)(carregado, {
|
|
848
|
+
thread: thread.id,
|
|
849
|
+
fase,
|
|
850
|
+
slug,
|
|
851
|
+
promptPath,
|
|
852
|
+
promptSha256: sha,
|
|
853
|
+
cwd,
|
|
854
|
+
model,
|
|
855
|
+
effort,
|
|
856
|
+
sinal,
|
|
857
|
+
detalhe: erro,
|
|
858
|
+
});
|
|
859
|
+
(0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rateLimitEnfileirado, {
|
|
860
|
+
fase,
|
|
861
|
+
slug,
|
|
862
|
+
pedido: pedido.id,
|
|
863
|
+
liberaEm: pedido.liberaEm,
|
|
864
|
+
janelaEstimada: pedido.janelaEstimada,
|
|
865
|
+
fonte: sinal.fonte,
|
|
866
|
+
promptSha256: sha,
|
|
867
|
+
correcao: `ork retry resume (ou aguarde ate ${pedido.liberaEm})`,
|
|
868
|
+
});
|
|
869
|
+
return {
|
|
870
|
+
thread,
|
|
871
|
+
slug,
|
|
872
|
+
promptPath,
|
|
873
|
+
promptSha256: sha,
|
|
874
|
+
comando: resultado.comando,
|
|
875
|
+
controlador: resultado.controlador,
|
|
876
|
+
sessionId: null,
|
|
877
|
+
verificada: false,
|
|
878
|
+
pausaAoFim,
|
|
879
|
+
dryRun: false,
|
|
880
|
+
runtime,
|
|
881
|
+
model,
|
|
882
|
+
effort,
|
|
883
|
+
bloqueado: false,
|
|
884
|
+
motivo: 'runtime.rate-limited',
|
|
885
|
+
violacoes,
|
|
886
|
+
naFila: pedido,
|
|
887
|
+
erro,
|
|
888
|
+
};
|
|
889
|
+
}
|
|
419
890
|
return {
|
|
420
891
|
thread,
|
|
421
892
|
slug,
|
|
422
893
|
promptPath,
|
|
423
894
|
promptSha256: sha,
|
|
424
895
|
comando: resultado.comando,
|
|
896
|
+
controlador: resultado.controlador,
|
|
425
897
|
sessionId: null,
|
|
426
898
|
verificada: false,
|
|
427
899
|
pausaAoFim,
|
|
428
900
|
dryRun: false,
|
|
901
|
+
runtime,
|
|
429
902
|
model,
|
|
430
903
|
effort,
|
|
431
904
|
bloqueado: false,
|
|
432
|
-
motivo: 'runtime.
|
|
905
|
+
motivo: 'runtime.unavailable',
|
|
433
906
|
violacoes,
|
|
434
|
-
naFila:
|
|
907
|
+
naFila: null,
|
|
435
908
|
erro,
|
|
436
909
|
};
|
|
437
910
|
}
|
|
911
|
+
concluirDespacho(ctx, resultado.sessionId, resultado.verificada, resultado.comando, rt.fonteVerificacao, resultado.controlador, { logPath: resultado.logPath, processoPath: resultado.processoPath, reciboPath: resultado.reciboPath });
|
|
438
912
|
return {
|
|
439
913
|
thread,
|
|
440
914
|
slug,
|
|
441
915
|
promptPath,
|
|
442
916
|
promptSha256: sha,
|
|
443
917
|
comando: resultado.comando,
|
|
444
|
-
sessionId:
|
|
445
|
-
|
|
918
|
+
sessionId: resultado.sessionId,
|
|
919
|
+
controlador: resultado.controlador,
|
|
920
|
+
verificada: resultado.verificada,
|
|
446
921
|
pausaAoFim,
|
|
447
922
|
dryRun: false,
|
|
923
|
+
runtime,
|
|
448
924
|
model,
|
|
449
925
|
effort,
|
|
450
926
|
bloqueado: false,
|
|
451
|
-
motivo:
|
|
927
|
+
motivo: null,
|
|
452
928
|
violacoes,
|
|
453
|
-
naFila: null,
|
|
454
|
-
erro,
|
|
455
929
|
};
|
|
456
930
|
}
|
|
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
|
-
};
|
|
931
|
+
finally {
|
|
932
|
+
// Despacho que nao virou sessao devolve a conducao; o que virou ja a entregou a sessao.
|
|
933
|
+
conducao?.liberar();
|
|
934
|
+
}
|
|
474
935
|
}
|
|
475
936
|
/** Tabela de `ork phase list`: o historico do ledger da thread. */
|
|
476
937
|
function tabelaDoLedger(raiz, threadId) {
|
|
@@ -523,7 +984,7 @@ function tabelaDoLedger(raiz, threadId) {
|
|
|
523
984
|
if (e.cobertura)
|
|
524
985
|
detalhe.push(`cobertura ${String(e.cobertura)}`);
|
|
525
986
|
if (e.liberaEm)
|
|
526
|
-
detalhe.push(`libera em ${String(e.liberaEm)}`);
|
|
987
|
+
detalhe.push(`libera em ${(0, horario_1.formatarDataHora)(String(e.liberaEm))}`);
|
|
527
988
|
if (e.tentativa !== undefined && e.limite !== undefined) {
|
|
528
989
|
detalhe.push(`tentativa ${String(e.tentativa)}/${String(e.limite)}`);
|
|
529
990
|
}
|
|
@@ -555,12 +1016,12 @@ function tabelaDoLedger(raiz, threadId) {
|
|
|
555
1016
|
if (e.erro)
|
|
556
1017
|
detalhe.push(`erro: ${String(e.erro)}`);
|
|
557
1018
|
if (e.detalhe && !e.decisao)
|
|
558
|
-
detalhe.push(String(e.detalhe).slice(0, 90));
|
|
1019
|
+
detalhe.push((0, horario_1.localizarTexto)(String(e.detalhe)).slice(0, 90));
|
|
559
1020
|
if (e.modo && !e.fase)
|
|
560
1021
|
detalhe.push(`modo ${String(e.modo)}`);
|
|
561
|
-
return [
|
|
1022
|
+
return [(0, horario_1.formatarDataHora)(e.ts, { segundos: true }), e.tipo, detalhe.join(' | ')];
|
|
562
1023
|
});
|
|
563
|
-
return (0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas)
|
|
1024
|
+
return `${(0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas)}\n${(0, horario_1.legendaDoFuso)()}`;
|
|
564
1025
|
}
|
|
565
1026
|
/** Slug legivel por humano de uma sessao (usado nas mensagens do CLI). */
|
|
566
1027
|
function descreverSlug(slug) {
|