@orkastery/cli 0.6.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/claude-code/README.md +1 -1
- package/adapters/claude-code/agents/ork-check.md +1 -1
- package/adapters/claude-code/agents/ork-go.md +1 -1
- package/adapters/claude-code/agents/ork-goal.md +1 -1
- package/adapters/claude-code/agents/ork-master.md +1 -1
- package/adapters/claude-code/agents/ork-plan.md +1 -1
- package/adapters/claude-code/agents/ork-ship.md +1 -1
- package/adapters/claude-code/commands/ork.md +1 -1
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -0
- package/adapters/codex/skills/ork/SKILL.md +1 -1
- package/adapters/hermes/README.md +1 -1
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/assets/adapters-en/claude-code/README.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-check.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-go.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-goal.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-master.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-plan.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-ship.md +1 -1
- package/assets/adapters-en/claude-code/commands/ork.md +1 -1
- package/assets/adapters-en/codex/skills/ork/SKILL.md +1 -1
- package/assets/adapters-en/hermes/README.md +1 -1
- package/assets/docs/padroes/roadmap-de-produto.md +1 -1
- package/assets/docs-en/padroes/roadmap-de-produto.md +1 -1
- package/assets/orkmind_fixture.py +4 -1
- package/assets/references-en/testing-patterns.md +1 -1
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +1 -1
- package/assets/skills-en/phases/check-quality/SKILL.md +1 -1
- package/assets/skills-en/phases/go-implementation/SKILL.md +1 -1
- package/dist/adapters/claude-bg.js +3 -1
- package/dist/adapters/grok-mcp-servidor.js +22 -12
- package/dist/adapters/grok.js +1 -1
- package/dist/agendador-cpu.js +10 -2
- package/dist/catalogo.js +3 -3
- package/dist/{canarios-hitl.js → cenarios-hitl.js} +7 -7
- package/dist/{canarios-i43.js → cenarios-i43.js} +16 -16
- package/dist/{canarios-pulse.js → cenarios-pulse.js} +3 -3
- package/dist/{canarios-rm057.js → cenarios-rm057.js} +3 -3
- package/dist/{canarios-sensores.js → cenarios-sensores.js} +5 -5
- package/dist/{canarios.js → cenarios.js} +22 -22
- package/dist/changelog-check.js +217 -0
- package/dist/check-agil.js +242 -5
- package/dist/check-paralelo.js +17 -4
- package/dist/ci.js +3 -2
- package/dist/claim-lint.js +29 -0
- package/dist/claims.js +5 -1
- package/dist/docs.js +8 -1
- package/dist/evalrunner.js +37 -37
- package/dist/fila-pesada.js +121 -11
- package/dist/hitl-canais.js +1 -1
- package/dist/hitl-classificacao.js +1 -0
- package/dist/hitl-presentation.js +1 -1
- package/dist/hitl-tempo-parado.js +1 -1
- package/dist/index.js +47 -29
- package/dist/init.js +1 -1
- package/dist/intelligence-graph-cli.js +27 -9
- package/dist/locale-ajuda.js +6 -6
- package/dist/locale-claims.js +16 -2
- package/dist/locale-grafo.js +56 -1
- package/dist/locale-maestro.js +38 -0
- package/dist/locale-network.js +8 -6
- package/dist/locale-onboarding.js +14 -0
- package/dist/locale-operacao-restante.js +18 -18
- package/dist/locale-preflight.js +80 -0
- package/dist/locale-projetos.js +6 -0
- package/dist/locale-prompts.js +8 -8
- package/dist/locale-pulse.js +4 -0
- package/dist/locale-retry.js +16 -0
- package/dist/locale-security-scan.js +35 -1
- package/dist/locale-verify.js +15 -0
- package/dist/locale.js +24 -7
- package/dist/maestro-cli.js +12 -17
- package/dist/mcp-install.js +2 -1
- package/dist/mcp-server.js +20 -17
- package/dist/mcp-verify-async.js +353 -0
- package/dist/mcp-verify-worker.js +17 -0
- package/dist/mcp-verify.js +10 -1
- package/dist/pedido-conducao.js +51 -0
- package/dist/preflight.js +25 -26
- package/dist/prompts.js +4 -2
- package/dist/pulse.js +4 -2
- package/dist/rede.js +24 -12
- package/dist/retry.js +12 -0
- package/dist/sandbox.js +11 -11
- package/dist/security-scan/cli.js +2 -2
- package/dist/security-scan/report.js +1 -1
- package/dist/session-watcher.js +33 -7
- package/dist/verify.js +166 -34
- package/eval/README.md +8 -8
- package/eval/fixtures/fx-codex-dry/caso.json +1 -1
- package/eval/fixtures/fx-happy/caso.json +1 -1
- package/eval/fixtures/fx-indice-reversao/caso.json +1 -1
- package/eval/fixtures/fx-listagem-abertas/caso.json +1 -1
- package/eval/fixtures/fx-omnicanal/caso.json +1 -1
- package/eval/fixtures/fx-pedido-colado/caso.json +1 -1
- package/eval/fixtures/fx-schema-drift/caso.json +1 -1
- package/package.json +1 -1
- package/references/testing-patterns.md +1 -1
- package/skills/core/orkastery-bootstrap/SKILL.md +1 -1
- package/skills/phases/check-quality/SKILL.md +1 -1
- package/skills/phases/go-implementation/SKILL.md +1 -1
package/dist/mcp-verify.js
CHANGED
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.ESPERA_DA_FILA_PESADA_MCP_MS = void 0;
|
|
37
|
+
exports.diagnosticoDoVerifyMcp = diagnosticoDoVerifyMcp;
|
|
37
38
|
exports.verificarMcp = verificarMcp;
|
|
38
39
|
/** Operação estruturada: argumentos só identificam a thread; execução sempre confinada. */
|
|
39
40
|
const fs = __importStar(require("node:fs"));
|
|
@@ -68,6 +69,14 @@ function mesmoLease(a, b) {
|
|
|
68
69
|
return !!a && a.nome === b.nome && a.thread === b.thread && a.pid === b.pid &&
|
|
69
70
|
a.adquiridoEm === b.adquiridoEm && a.expiraEm === b.expiraEm && a.motivo === b.motivo;
|
|
70
71
|
}
|
|
72
|
+
/** Parte pura do retorno MCP: permite provar o contrato mesmo quando o sandbox nao abre outro sandbox. */
|
|
73
|
+
function diagnosticoDoVerifyMcp(r) {
|
|
74
|
+
return {
|
|
75
|
+
regressoes: r.regressoes.map(c => c.nome),
|
|
76
|
+
preExistentes: r.preExistentes.map(c => c.nome),
|
|
77
|
+
comparacoes: r.comparacoes,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
71
80
|
/** Síncrono: prazo total/per-command, não cancelamento reativo do event loop. */
|
|
72
81
|
function verificarMcp(raizEntrada, threadId, conducao = {}) {
|
|
73
82
|
const deadline = Date.now() + PRAZO_TOTAL_MS;
|
|
@@ -167,7 +176,7 @@ function verificarMcp(raizEntrada, threadId, conducao = {}) {
|
|
|
167
176
|
execucoes: execucoes.slice(0, LIMITE_RETORNO).map(c => ({ nome: c.nome, ok: c.ok, code: c.code,
|
|
168
177
|
executado: c.executado === true, resumo: c.resumo })),
|
|
169
178
|
totalExecucoes: execucoes.length, omitidas: Math.max(0, execucoes.length - LIMITE_RETORNO),
|
|
170
|
-
|
|
179
|
+
...diagnosticoDoVerifyMcp(r),
|
|
171
180
|
executor: 'codex-sandbox', prazoTotalMs: PRAZO_TOTAL_MS, limitePorComandoMs: COMANDO_MAX_MS,
|
|
172
181
|
};
|
|
173
182
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MOTIVOS_DE_PEDIDO_A_CONDUCAO = void 0;
|
|
4
|
+
exports.registrarPedidoAConducao = registrarPedidoAConducao;
|
|
5
|
+
/**
|
|
6
|
+
* Pedido estreito da sessao de fase para a conducao. A sessao nao executa o comando,
|
|
7
|
+
* nao aprova gate e nao assume o dono: ela apenas registra por que parou e o passo exato.
|
|
8
|
+
*/
|
|
9
|
+
const gates_1 = require("./gates");
|
|
10
|
+
const ledger_1 = require("./ledger");
|
|
11
|
+
const thread_1 = require("./thread");
|
|
12
|
+
exports.MOTIVOS_DE_PEDIDO_A_CONDUCAO = [
|
|
13
|
+
'concurrency.lease-indeterminado',
|
|
14
|
+
'conducao.acao-necessaria',
|
|
15
|
+
];
|
|
16
|
+
function comandoSeguro(comando) {
|
|
17
|
+
return comando.length <= 1000 && /^ork [^\s]/u.test(comando) && !/[\p{Cc}\p{Cf};|&<>`$\\()]/u.test(comando) &&
|
|
18
|
+
!/\s{2,}/.test(comando) && comando.trim() === comando;
|
|
19
|
+
}
|
|
20
|
+
/** Registra uma vez, sempre correlacionado ao despacho que originou o servidor MCP filho. */
|
|
21
|
+
function registrarPedidoAConducao(raiz, threadId, entrada) {
|
|
22
|
+
if (!exports.MOTIVOS_DE_PEDIDO_A_CONDUCAO.includes(entrada.motivo))
|
|
23
|
+
throw Error('conducao.request.reason.invalid');
|
|
24
|
+
if (!comandoSeguro(entrada.comando)) {
|
|
25
|
+
throw Error('conducao.request.command.invalid: informe um comando ork de uma linha, sem operadores de shell');
|
|
26
|
+
}
|
|
27
|
+
const thread = (0, thread_1.lerThread)(raiz, threadId), dir = (0, thread_1.dirThread)(raiz, threadId), eventos = (0, ledger_1.lerLedger)(dir);
|
|
28
|
+
const despacho = eventos.filter(e => e.tipo === 'phase_dispatch' &&
|
|
29
|
+
e.identidade?.dispatchId === entrada.despacho).at(-1);
|
|
30
|
+
if (!despacho || despacho.thread !== threadId || typeof despacho.sessionId !== 'string' || typeof despacho.fase !== 'string') {
|
|
31
|
+
throw Error('conducao.request.dispatch.invalid: o servidor nao corresponde a um despacho provado desta thread');
|
|
32
|
+
}
|
|
33
|
+
const sessao = thread.sessoes.find(s => s.sessionId === despacho.sessionId && s.fase === despacho.fase);
|
|
34
|
+
if (!sessao)
|
|
35
|
+
throw Error('conducao.request.session.invalid: o despacho nao esta vinculado a sessao ativa da thread');
|
|
36
|
+
const existente = eventos.filter(e => e.tipo === 'gate_blocked' && e.origem === 'mcp.request_conduction' &&
|
|
37
|
+
e.despacho === entrada.despacho && e.motivo === entrada.motivo && e.comando === entrada.comando).at(-1);
|
|
38
|
+
if (existente)
|
|
39
|
+
return { ok: true, criado: false, eventId: existente.eventId, motivo: entrada.motivo,
|
|
40
|
+
comando: entrada.comando, fase: despacho.fase, sessionId: despacho.sessionId, despacho: entrada.despacho };
|
|
41
|
+
const evento = (0, gates_1.registrarGateBloqueado)(dir, threadId, {
|
|
42
|
+
gate: 'phase.dispatch', motivo: entrada.motivo, modo: thread.modo,
|
|
43
|
+
detalhe: entrada.detalhe, correcao: entrada.comando,
|
|
44
|
+
evidencia: `despacho ${entrada.despacho} da sessao ${despacho.sessionId}`,
|
|
45
|
+
fase: despacho.fase, sessionId: despacho.sessionId, despachoEm: sessao.despachadaEm,
|
|
46
|
+
despacho: entrada.despacho, comando: entrada.comando, origem: 'mcp.request_conduction',
|
|
47
|
+
pedidoConducao: { contrato: 'ork.pedido-conducao/v1', host: entrada.host, estado: 'aberto' },
|
|
48
|
+
});
|
|
49
|
+
return { ok: true, criado: true, eventId: evento.eventId, motivo: entrada.motivo,
|
|
50
|
+
comando: entrada.comando, fase: despacho.fase, sessionId: despacho.sessionId, despacho: entrada.despacho };
|
|
51
|
+
}
|
package/dist/preflight.js
CHANGED
|
@@ -126,49 +126,46 @@ function sondasDeAmbiente(raiz, umask = umaskDoProcesso()) {
|
|
|
126
126
|
* com login conferido pelo proprio CLI. A sonda nao marca o store: quem marca e o despacho.
|
|
127
127
|
*/
|
|
128
128
|
function checkDeContas(raiz, runtime, auth = authPadrao) {
|
|
129
|
+
const m = (0, locale_1.msg)().preflight;
|
|
129
130
|
let perfis;
|
|
130
131
|
try {
|
|
131
132
|
perfis = (0, runtime_profiles_1.perfisDoRuntime)((0, runtime_profiles_1.lerPerfisComContas)(raiz), runtime).filter(p => p.estado !== 'desativado');
|
|
132
133
|
}
|
|
133
134
|
catch (e) {
|
|
134
|
-
return { nome: 'contas', nivel: 'fail', detalhe:
|
|
135
|
+
return { nome: 'contas', nivel: 'fail', detalhe: m.storeInvalido(e.message) };
|
|
135
136
|
}
|
|
136
137
|
if (!perfis.length)
|
|
137
|
-
return { nome: 'contas', nivel: 'ok', detalhe:
|
|
138
|
+
return { nome: 'contas', nivel: 'ok', detalhe: m.semPerfil(runtime) };
|
|
138
139
|
const estados = perfis.map(p => {
|
|
139
140
|
const a = auth((0, runtime_profiles_1.perfilDeDespacho)(p));
|
|
140
141
|
return { id: p.id, pronto: a.ok && (0, runtime_profiles_1.perfilDisponivel)(p),
|
|
141
|
-
texto: !a.ok ? `${a.pago ?
|
|
142
|
+
texto: !a.ok ? `${a.pago ? m.estadoConta.providerPago : a.transitorio ? m.estadoConta.loginInconclusivo : m.estadoConta.semLogin} (${a.detalhe})`
|
|
143
|
+
: (0, runtime_profiles_1.perfilDisponivel)(p) ? m.estadoConta.pronto : m.estadoConta.esgotadoAte(p.estado, p.esgotadoAte ?? '') };
|
|
142
144
|
});
|
|
143
145
|
const prontos = estados.filter(e => e.pronto).length;
|
|
144
146
|
return { nome: 'contas', nivel: prontos === 0 ? 'fail' : prontos < estados.length ? 'warn' : 'ok',
|
|
145
|
-
detalhe:
|
|
146
|
-
...(prontos < estados.length ? { correcao:
|
|
147
|
+
detalhe: m.contas(runtime, estados.map(e => `${e.id} ${e.texto}`).join('; ')),
|
|
148
|
+
...(prontos < estados.length ? { correcao: m.contasCorrecao } : {}) };
|
|
147
149
|
}
|
|
148
|
-
const limites = [
|
|
149
|
-
'Sonda contextual local: não inventaria sessões, não inicia modelo e não autoriza despacho.',
|
|
150
|
-
'Aceitação do modelo, instalação do adaptador/MCP, contexto da thread, gates e policies do pedido são revalidados no despacho; com perfis, o login de cada conta é conferido aqui e de novo no despacho.',
|
|
151
|
-
'Trio sem override; um override posterior exige resolver e verificar novamente o despacho.',
|
|
152
|
-
'VERIFY/SHIP MCP exigem executor Codex isolado próprio e transporte SHIP válido; a sonda de despacho não comprova entrega.',
|
|
153
|
-
];
|
|
154
150
|
function preflight(raiz, modo, nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), sensores = sensoresPadrao) {
|
|
151
|
+
const t = (0, locale_1.msg)().preflight;
|
|
155
152
|
// I-43: a matriz tem os cinco (para LER thread antiga); quem entra aqui e ESCRITA.
|
|
156
153
|
if (!modos_1.ORDEM_DOS_MODOS.includes(modo))
|
|
157
154
|
throw Error('preflight.mode.invalid');
|
|
158
155
|
const checks = [];
|
|
159
|
-
checks.push({ nome: 'node', nivel: Number(process.versions.node.split('.')[0]) >= 20 ? 'ok' : 'fail', detalhe:
|
|
156
|
+
checks.push({ nome: 'node', nivel: Number(process.versions.node.split('.')[0]) >= 20 ? 'ok' : 'fail', detalhe: t.node });
|
|
160
157
|
const git = !!(0, util_1.noPath)('git');
|
|
161
|
-
checks.push({ nome: 'git', nivel: git ? 'ok' : 'fail', detalhe: git ?
|
|
158
|
+
checks.push({ nome: 'git', nivel: git ? 'ok' : 'fail', detalhe: git ? t.gitOk : t.gitAusente });
|
|
162
159
|
const repo = git ? (0, util_1.exec)('git', ['rev-parse', '--is-inside-work-tree'], raiz, 10000) : null;
|
|
163
|
-
checks.push({ nome: 'repositorio', nivel: repo?.ok && repo.stdout.trim() === 'true' ? 'ok' : 'fail', detalhe:
|
|
160
|
+
checks.push({ nome: 'repositorio', nivel: repo?.ok && repo.stdout.trim() === 'true' ? 'ok' : 'fail', detalhe: t.repo });
|
|
164
161
|
checks.push(...sondasDeAmbiente(raiz));
|
|
165
162
|
const carregado = (0, manifest_1.carregarManifesto)(raiz);
|
|
166
163
|
const blocos = [];
|
|
167
|
-
checks.push({ nome: 'manifesto', nivel: !carregado || carregado.erros.length ? 'fail' : 'ok', detalhe: !carregado ?
|
|
164
|
+
checks.push({ nome: 'manifesto', nivel: !carregado || carregado.erros.length ? 'fail' : 'ok', detalhe: !carregado ? t.manifestoAusente : carregado.erros.length ? t.manifestoInvalido : t.manifestoValido });
|
|
168
165
|
if (carregado && !carregado.erros.length) {
|
|
169
166
|
const m = carregado.manifesto;
|
|
170
|
-
checks.push({ nome: 'modo', nivel: m.conduction.allowed_modes.includes(modo) ? 'ok' : 'fail', detalhe:
|
|
171
|
-
checks.push({ nome: 'abbrev', nivel: (0, slug_1.validarAbbrev)(m.project.abbrev).ok ? 'ok' : 'fail', detalhe:
|
|
167
|
+
checks.push({ nome: 'modo', nivel: m.conduction.allowed_modes.includes(modo) ? 'ok' : 'fail', detalhe: t.modo(modo) });
|
|
168
|
+
checks.push({ nome: 'abbrev', nivel: (0, slug_1.validarAbbrev)(m.project.abbrev).ok ? 'ok' : 'fail', detalhe: t.abbrev });
|
|
172
169
|
const setup = (0, setup_1.lerSetup)(carregado.raiz), observados = new Map(), contas = new Map();
|
|
173
170
|
let sandbox;
|
|
174
171
|
for (const [i, bloco] of modos_1.MODOS[modo].blocos.entries()) {
|
|
@@ -177,11 +174,11 @@ function preflight(raiz, modo, nomesHerdados = (0, runtime_ambiente_1.nomesDePro
|
|
|
177
174
|
try {
|
|
178
175
|
trio = (0, phase_1.resolverDespacho)(m, {}, (0, setup_1.configDoBloco)(setup, modo, bloco.fases[0]));
|
|
179
176
|
(0, runtimes_1.resolverRuntime)(trio.runtime);
|
|
180
|
-
locais.push({ nome: 'trio', nivel: 'ok', detalhe:
|
|
177
|
+
locais.push({ nome: 'trio', nivel: 'ok', detalhe: t.trio });
|
|
181
178
|
if (!observados.has(trio.runtime))
|
|
182
179
|
observados.set(trio.runtime, sensores.runtime(trio.runtime));
|
|
183
180
|
const presente = observados.get(trio.runtime);
|
|
184
|
-
locais.push({ nome: 'runtime', nivel: presente ? 'ok' : 'fail', detalhe: presente ?
|
|
181
|
+
locais.push({ nome: 'runtime', nivel: presente ? 'ok' : 'fail', detalhe: presente ? t.runtimeOk(trio.runtime) : t.runtimeAusente(trio.runtime) });
|
|
185
182
|
if (presente) {
|
|
186
183
|
if (!contas.has(trio.runtime))
|
|
187
184
|
contas.set(trio.runtime, checkDeContas(carregado.raiz, trio.runtime, sensores.auth ?? authPadrao));
|
|
@@ -189,14 +186,15 @@ function preflight(raiz, modo, nomesHerdados = (0, runtime_ambiente_1.nomesDePro
|
|
|
189
186
|
}
|
|
190
187
|
if (trio.runtime === 'codex' && presente) {
|
|
191
188
|
sandbox ??= sensores.sandboxCodex();
|
|
192
|
-
locais.push({ nome: 'sandbox de despacho', nivel: sandbox ? 'ok' : m.runtime.sandbox === 'danger-full-access' ? 'warn' : 'fail', detalhe: sandbox ?
|
|
189
|
+
locais.push({ nome: 'sandbox de despacho', nivel: sandbox ? 'ok' : m.runtime.sandbox === 'danger-full-access' ? 'warn' : 'fail', detalhe: sandbox ? t.sandboxOk : t.sandboxFalhou });
|
|
193
190
|
}
|
|
194
191
|
const ativos = nomesHerdados.filter(n => runtime_ambiente_1.ENVS_DE_PROVIDER_PAGO.includes(n));
|
|
195
192
|
const relevantes = ativos.filter(n => trio.runtime === 'claude-bg' ? /^(ANTHROPIC_|CLAUDE_CODE_USE_)/.test(n) : /^(OPENAI_|OPENROUTER_)/.test(n));
|
|
196
|
-
locais.push({ nome: 'provider', nivel: m.runtime.provider_policy === 'subscription-only' && relevantes.length ? 'fail' : ativos.length ? 'warn' : 'ok',
|
|
193
|
+
locais.push({ nome: 'provider', nivel: m.runtime.provider_policy === 'subscription-only' && relevantes.length ? 'fail' : ativos.length ? 'warn' : 'ok',
|
|
194
|
+
detalhe: relevantes.length ? t.providerIncompativel(relevantes.join(', ')) : ativos.length ? t.providerAlheio : t.providerNenhum });
|
|
197
195
|
}
|
|
198
196
|
catch {
|
|
199
|
-
locais.push({ nome: 'trio', nivel: 'fail', detalhe:
|
|
197
|
+
locais.push({ nome: 'trio', nivel: 'fail', detalhe: t.trioInvalido });
|
|
200
198
|
}
|
|
201
199
|
blocos.push({ numero: i + 1, fases: [...bloco.fases], trio, checks: locais, pronto: locais.every(c => c.nivel !== 'fail') });
|
|
202
200
|
}
|
|
@@ -205,16 +203,17 @@ function preflight(raiz, modo, nomesHerdados = (0, runtime_ambiente_1.nomesDePro
|
|
|
205
203
|
return { modo, scope: 'dispatch-local', checks, blocos,
|
|
206
204
|
prontoPrimeiroBloco: basePronta && !!blocos[0]?.pronto,
|
|
207
205
|
prontoTodosBlocos: basePronta && blocos.length > 0 && blocos.every(b => b.pronto),
|
|
208
|
-
entrega: { verificada: false, dependencias: ['executor Codex isolado', 'transporte SHIP instalado', 'gates e HEADs correntes'] }, limites: [...limites] };
|
|
206
|
+
entrega: { verificada: false, dependencias: ['executor Codex isolado', 'transporte SHIP instalado', 'gates e HEADs correntes'] }, limites: [...t.limites] };
|
|
209
207
|
}
|
|
210
208
|
function textoPreflight(r) {
|
|
211
209
|
// I-35: o Check guarda o ISO (dado de maquina); quem imprime para o dono localiza.
|
|
212
210
|
let localizou = false;
|
|
213
211
|
const local = (t) => { const l = (0, horario_1.localizarTexto)(t); if (l !== t)
|
|
214
212
|
localizou = true; return l; };
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
213
|
+
const m = (0, locale_1.msg)().preflight, nome = (v) => m.nomes[v] ?? v;
|
|
214
|
+
const linhas = [m.titulo(r.modo), ...r.checks.map(c => m.check(c.nivel, nome(c.nome), local(c.detalhe))),
|
|
215
|
+
...r.blocos.flatMap(b => [m.bloco(b.numero, b.fases.join('→'), b.trio ? `${b.trio.runtime}/${b.trio.model}/${b.trio.effort}` : null),
|
|
216
|
+
...b.checks.map(c => m.checkDoBloco(c.nivel, nome(c.nome), local(c.detalhe)))]), m.resumo(r.prontoPrimeiroBloco, r.prontoTodosBlocos), ...r.limites];
|
|
218
217
|
// O fuso sai uma vez por mensagem, depois dos limites.
|
|
219
218
|
if (localizou)
|
|
220
219
|
linhas.push((0, horario_1.legendaDoFuso)());
|
package/dist/prompts.js
CHANGED
|
@@ -292,7 +292,7 @@ function lintTemplate(t, contrato) {
|
|
|
292
292
|
*/
|
|
293
293
|
exports.TEMPLATE_FASE_PADRAO = `---
|
|
294
294
|
id: fase-padrao
|
|
295
|
-
versao:
|
|
295
|
+
versao: 5
|
|
296
296
|
descricao: Prompt canonico de uma fase do ciclo GOAL..MASTER, com nomenclatura, modo de conducao, contexto da thread, memoria injetada e regras de evidencia.
|
|
297
297
|
fases: [GOAL, PLAN, GO, CHECK, SHIP, MASTER]
|
|
298
298
|
variaveis: [fase, thread, bloco, nome, ciclo_canonico, tag, blocos, pausas, linha_variante, regra_de_pausa, invariantes, slug, projeto_nome, projeto_abbrev, base_branch, base_commit, diretorio, trabalho, pedido, fecho_go, memoria_injetada, regras_de_evidencia]
|
|
@@ -307,6 +307,7 @@ Quando disponiveis, use ork_artifact_read/write para objetivo, plano e parecer,
|
|
|
307
307
|
Decisao que voce tomar sem perguntar ao dono vai ao ledger por \`ork decisao registrar <thread>\` (no MCP, \`ork_decision_record\`, pois o sandbox do codex nao grava o ledger), com o que foi decidido, o porque, como mudar, o custo de reverter agora e depois, o criterio escrito, quem decidiu e a evidencia; e assim que ela chega ao dono no resumo, em vez de sumir na conversa.
|
|
308
308
|
Artefato de autoria do agente nao e recibo oficial; cadastrar claim nao significa verifica-la.
|
|
309
309
|
Para registrar produto, prefira ork_git_commit com HEAD atual e paths com claims; use ork_verify para verificacao real e ork_ship com HEADs fonte/destino conferidos para entrega. Commit local nao e SHIP; retorno incomplete exige reconciliar estado e remoto antes de repetir. Permissao para consultar nao concede essas operacoes: respeite a autorizacao nativa e os gates.
|
|
310
|
+
Quando o MCP expuser \`ork_verify_status\`, chame \`ork_verify\` uma vez, guarde o \`rodadaId\` e consulte a mesma rodada a cada 30–60 s. Enquanto ela estiver na fila ou rodando, retenha apenas estado e lane atuais no contexto; nao repita o pedido nem copie payloads intermediarios. So avance com o veredito terminal verde; falha tipada ou veredito vermelho bloqueia o ciclo.
|
|
310
311
|
Decisao do dono deve ser apresentada pela sessao condutora ao host; a sessao filha nao responde nem assume a identidade do dono.
|
|
311
312
|
Preserve o perfil filho configurado: \`interactive\` concede consultas; \`worktree\` exige opt-in da instalacao e autoriza ferramentas exatas na WT validada, sem aprovar gates ou assumir o dono. Nao mude configuracao para contornar bloqueio.
|
|
312
313
|
Consulte \`ork_git_status\` para HEADs reais e estado Git; use \`ork_git_commit\`, \`ork_verify\` e \`ork_ship\` pelos contratos do nucleo, sem Bash Git nem inventar SHAs. Use \`source.head\` como \`expectedHead\` do commit; consulte novamente apos commit e use \`source.head\`/\`destination.head\` como \`expectedSource\`/\`expectedDestination\` do SHIP. Base historica nao substitui a consulta atual. As regras Edit/deny sao permissoes nativas de ferramentas, nao sandbox de processos.
|
|
@@ -351,7 +352,7 @@ Falha de autenticação permanece impedimento; não troque provider, sandbox ou
|
|
|
351
352
|
/** English counterpart of the canonical phase prompt. The pt-BR template above remains the source contract. */
|
|
352
353
|
exports.TEMPLATE_FASE_PADRAO_EN = `---
|
|
353
354
|
id: fase-padrao.en
|
|
354
|
-
versao:
|
|
355
|
+
versao: 5
|
|
355
356
|
descricao: Canonical prompt for a GOAL..MASTER cycle phase, with naming, conduction mode, thread context, injected memory, and evidence rules.
|
|
356
357
|
fases: [GOAL, PLAN, GO, CHECK, SHIP, MASTER]
|
|
357
358
|
variaveis: [fase, thread, bloco, nome, ciclo_canonico, tag, blocos, pausas, linha_variante, regra_de_pausa, invariantes, slug, projeto_nome, projeto_abbrev, base_branch, base_commit, diretorio, trabalho, pedido, fecho_go, memoria_injetada, regras_de_evidencia]
|
|
@@ -366,6 +367,7 @@ When available, use ork_artifact_read/write for the goal, plan, and review, and
|
|
|
366
367
|
Record every decision you make without asking the owner in the ledger with \`ork decisao registrar <thread>\` (or \`ork_decision_record\` in MCP because the Codex sandbox cannot write the ledger), including what was decided, why, how to change it, reversal cost now and later, the written criterion, who decided, and the evidence. This is how it reaches the owner in the summary instead of disappearing in the conversation.
|
|
367
368
|
An agent-authored artifact is not an official receipt; registering a claim does not verify it.
|
|
368
369
|
To record product changes, prefer ork_git_commit with the current HEAD and paths with claims; use ork_verify for real verification and ork_ship with checked source/destination HEADs for delivery. A local commit is not SHIP; an incomplete result requires reconciling state and remote before retrying. Permission to query does not grant those operations: respect native authorization and gates.
|
|
370
|
+
When MCP exposes \`ork_verify_status\`, call \`ork_verify\` once, keep its \`rodadaId\`, and query that same round every 30–60 seconds. While queued or running, retain only the current state and lane in context; do not repeat the request or copy intermediate payloads. Continue only after a terminal green verdict; a typed failure or red verdict blocks the cycle.
|
|
369
371
|
The conducting session presents an owner decision to the host; a child session neither answers nor assumes the owner's identity.
|
|
370
372
|
Preserve the configured child profile: \`interactive\` grants queries; \`worktree\` requires installation opt-in and authorizes exact tools in the validated worktree, without approving gates or assuming the owner. Do not change configuration to bypass a block.
|
|
371
373
|
Query \`ork_git_status\` for real HEADs and Git state; use \`ork_git_commit\`, \`ork_verify\`, and \`ork_ship\` through the core contracts, without Bash Git or invented SHAs. Use \`source.head\` as the commit \`expectedHead\`; query again after the commit and use \`source.head\`/\`destination.head\` as SHIP \`expectedSource\`/\`expectedDestination\`. A historical base does not replace the current query. Edit/deny rules are native tool permissions, not process sandbox rules.
|
package/dist/pulse.js
CHANGED
|
@@ -157,7 +157,8 @@ function comporPulse(carregado, entrada) {
|
|
|
157
157
|
if (p.motivo === 'human.pending' && p.fonte === 'ledger' && entregas?.doCondutor.gates.has(`${l.thread}|${p.fase}`))
|
|
158
158
|
continue;
|
|
159
159
|
if (ehRegistro(l.thread)) {
|
|
160
|
-
if (p.fonte === 'escalonador' || ['lease.busy', 'conducao.em-andamento', 'concurrency.limite', 'vaga.stale',
|
|
160
|
+
if (p.fonte === 'escalonador' || ['lease.busy', 'conducao.em-andamento', 'concurrency.limite', 'vaga.stale',
|
|
161
|
+
'runtime.silencio', 'concurrency.lease-indeterminado', 'conducao.acao-necessaria'].includes(p.motivo))
|
|
161
162
|
continue;
|
|
162
163
|
const sessoes = radar.sessoes.filter(s => s.thread?.id === l.thread && s.thread.fase === p.fase);
|
|
163
164
|
// Escalada explícita de ledger não é apagada pela conclusão de uma sessão.
|
|
@@ -213,7 +214,8 @@ function comporPulse(carregado, entrada) {
|
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
// I-45: vaga parada e sinal do escalonador (`ork board reap` devolve a vaga), nao pergunta ao dono.
|
|
216
|
-
const esperaAutomatica = ['lease.busy', 'conducao.em-andamento', 'concurrency.limite', 'runtime.rate-limited', 'vaga.stale'
|
|
217
|
+
const esperaAutomatica = ['lease.busy', 'conducao.em-andamento', 'concurrency.limite', 'runtime.rate-limited', 'vaga.stale',
|
|
218
|
+
'concurrency.lease-indeterminado', 'conducao.acao-necessaria'].includes(p.motivo);
|
|
217
219
|
(esperaAutomatica ? automaticas : humanos).push(item);
|
|
218
220
|
}
|
|
219
221
|
// RM-063 (F5): o MASTER por omissao da varredura nao vira item do dono (I-45: a entrega sem nota fica na faixa
|
package/dist/rede.js
CHANGED
|
@@ -73,7 +73,7 @@ exports.painelDaRede = painelDaRede;
|
|
|
73
73
|
* fora de qualquer clone de projeto.
|
|
74
74
|
*
|
|
75
75
|
* D3: publicar exige o repositorio privado, conferido na forja antes de cada publicacao.
|
|
76
|
-
* D5: o retrato e uma LISTA DE PERMISSAO (maquina,
|
|
76
|
+
* D5: o retrato e uma LISTA DE PERMISSAO (maquina, alias legado, forjas, runtimes, hosts, projetos,
|
|
77
77
|
* versao do `ork`, batida) e passa por uma varredura de segredo antes do push: um achado recusa a
|
|
78
78
|
* publicacao inteira, e o erro diz o padrao e o campo, nunca o valor.
|
|
79
79
|
* D6: cada maquina so escreve o proprio retrato; o `REDE.md` e indice derivado que quem publica
|
|
@@ -191,6 +191,17 @@ function hostnameSeguro() {
|
|
|
191
191
|
const bruto = os.hostname().trim();
|
|
192
192
|
return /^[A-Za-z0-9][A-Za-z0-9._-]{0,252}$/.test(bruto) ? bruto : bruto.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 253) || 'desconhecido';
|
|
193
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* RM-062 F3: o nome que sai da maquina precisa ter sido escolhido localmente. O fallback historico
|
|
196
|
+
* para `os.hostname()` transformava um detalhe privado em nome de arquivo e em JSON. A configuracao
|
|
197
|
+
* fica em `~/.orkastery/maquina.json`; `--maquina` e `ORK_MAQUINA` cobrem a primeira entrada.
|
|
198
|
+
*/
|
|
199
|
+
function nomeGenericoDaRede(explicito) {
|
|
200
|
+
const nome = (explicito ?? '').trim() || (0, maquina_1.lerConfigDaMaquina)()?.nome || (process.env.ORK_MAQUINA ?? '').trim();
|
|
201
|
+
if (!nome)
|
|
202
|
+
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeGenericoAusente);
|
|
203
|
+
return nomeSeguro(nome);
|
|
204
|
+
}
|
|
194
205
|
/** O retrato desta maquina, montado so com os campos da lista de permissao (D5). */
|
|
195
206
|
function retratoDaMaquina(opcoes = {}) {
|
|
196
207
|
return retratoComDescartes(opcoes).retrato;
|
|
@@ -199,7 +210,7 @@ function retratoDaMaquina(opcoes = {}) {
|
|
|
199
210
|
* O retrato e os projetos que ficaram fora dele. Projeto vem de fora do nucleo (o registro da
|
|
200
211
|
* RM-052, o cwd, o ultimo retrato): um valor dele com cara de segredo tira SO aquele projeto, com
|
|
201
212
|
* aviso, em vez de travar a publicacao da maquina para sempre (A1 do CHECK 1). O que o nucleo monta
|
|
202
|
-
* (maquina,
|
|
213
|
+
* (maquina, alias legado, forjas, runtimes, hosts) continua falhando fechado em `exigirRetratoSeguro`.
|
|
203
214
|
*/
|
|
204
215
|
function retratoComDescartes(opcoes = {}) {
|
|
205
216
|
const amb = opcoes.amb ?? {};
|
|
@@ -248,11 +259,12 @@ function retratoComDescartes(opcoes = {}) {
|
|
|
248
259
|
descartados.push({ campo: `projetos[${exports.MAXIMO_DE_ITENS}..]`, padrao: `limite de ${exports.MAXIMO_DE_ITENS} projetos` });
|
|
249
260
|
limpos.length = exports.MAXIMO_DE_ITENS;
|
|
250
261
|
}
|
|
262
|
+
const maquina = nomeGenericoDaRede(opcoes.maquina);
|
|
251
263
|
const retrato = {
|
|
252
264
|
contrato: exports.CONTRATO_DO_RETRATO,
|
|
253
|
-
maquina
|
|
265
|
+
maquina,
|
|
254
266
|
...(opcoes.id ? { id: opcoes.id } : {}),
|
|
255
|
-
hostname:
|
|
267
|
+
hostname: maquina,
|
|
256
268
|
adesao: opcoes.adesao ?? (0, rede_adesao_1.adesaoDaRede)().adesao ?? 'rede',
|
|
257
269
|
forjas: identidades.map((i) => ({ forja: i.forja, host: i.host, cli: i.cli, versao: i.versao, usuario: i.usuario })),
|
|
258
270
|
runtimes,
|
|
@@ -785,10 +797,9 @@ function gravarNaCasa(conferida, retrato, descartados, opcoes) {
|
|
|
785
797
|
const idDoOutro = atual ? atual.id ?? null : idNoArquivo(cache, ponta, arquivoDoRetrato(maquina));
|
|
786
798
|
const alheio = !!idDoOutro && idDoOutro !== retrato.id;
|
|
787
799
|
if (alheio && !opcoes.tomarNome) {
|
|
788
|
-
//
|
|
789
|
-
const mesmoHostname = atual?.hostname === hostnameSeguro();
|
|
800
|
+
// O campo legado `hostname` agora repete o alias generico e nao distingue instalacoes.
|
|
790
801
|
const outro = atual ? { hostname: atual.hostname, publicadoEm: atual.publicadoEm } : null;
|
|
791
|
-
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeEmUso(maquina, outro ? m.network.quemHostname(String(outro.hostname), (0, horario_1.formatarDataHora)(outro.publicadoEm)) : m.network.quemIlegivel,
|
|
802
|
+
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeEmUso(maquina, outro ? m.network.quemHostname(String(outro.hostname), (0, horario_1.formatarDataHora)(outro.publicadoEm)) : m.network.quemIlegivel, m.network.dicaNomeEmUso));
|
|
792
803
|
}
|
|
793
804
|
const mudancas = [
|
|
794
805
|
{ caminho: arquivoDoRetrato(maquina), conteudo: JSON.stringify(retrato, null, 2) + '\n' },
|
|
@@ -819,7 +830,7 @@ function publicarRede(opcoes = {}) {
|
|
|
819
830
|
if (!adesao.membro)
|
|
820
831
|
throw new locale_1.ErroDoCatalogo((m) => m.network.foraDaRede);
|
|
821
832
|
const amb = opcoes.amb ?? {};
|
|
822
|
-
const maquina =
|
|
833
|
+
const maquina = nomeGenericoDaRede(opcoes.maquina);
|
|
823
834
|
const id = (0, rede_adesao_1.idDaMaquina)();
|
|
824
835
|
const agora = opcoes.agora ?? new Date().toISOString();
|
|
825
836
|
const marca = lerMarcaDaRede();
|
|
@@ -860,12 +871,13 @@ const NOME_DE_MAQUINA = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
|
860
871
|
* `ork network entrar`. M2 do CHECK 1: atomico do ponto de vista da maquina. Confere (e cria,
|
|
861
872
|
* privada) a casa, publica o primeiro retrato e SO ENTAO grava o nome e a adesao; se a publicacao
|
|
862
873
|
* falha, nada muda aqui. M3: o nome que vale e gravado, como no `ork fabrica entrar`: `--maquina`,
|
|
863
|
-
* senao o ja gravado, senao `ORK_MAQUINA
|
|
874
|
+
* senao o ja gravado, senao `ORK_MAQUINA`; assim o cron publica com o mesmo nome. RM-062 F3:
|
|
875
|
+
* hostname nunca e fallback, porque nome de arquivo e JSON sao evidencia publicada.
|
|
864
876
|
*/
|
|
865
877
|
function entrarNaRede(opcoes = {}) {
|
|
866
|
-
// O nome explicito tem de ser valido; o que vem do arquivo
|
|
878
|
+
// O nome explicito tem de ser valido; o que vem do arquivo ou de ORK_MAQUINA e saneado.
|
|
867
879
|
const explicito = (opcoes.maquina ?? '').trim();
|
|
868
|
-
const maquina = explicito ||
|
|
880
|
+
const maquina = explicito || nomeGenericoDaRede();
|
|
869
881
|
if (!NOME_DE_MAQUINA.test(maquina)) {
|
|
870
882
|
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeInvalido(maquina));
|
|
871
883
|
}
|
|
@@ -896,7 +908,7 @@ function entrarNaRede(opcoes = {}) {
|
|
|
896
908
|
function sairDaRede(opcoes = {}) {
|
|
897
909
|
// U3 da revisao 3: a saida local vem primeiro; nada depois dela pode deixar a maquina membro.
|
|
898
910
|
(0, rede_adesao_1.gravarConfigDaRede)({ membro: false });
|
|
899
|
-
const maquina =
|
|
911
|
+
const maquina = nomeGenericoDaRede(opcoes.maquina);
|
|
900
912
|
const r = resolverCasa(opcoes);
|
|
901
913
|
if (r.casa)
|
|
902
914
|
(0, rede_adesao_1.gravarConfigDaRede)({ forja: r.casa.forja, host: r.casa.host, dono: r.casa.dono, repositorio: r.casa.repositorio });
|
package/dist/retry.js
CHANGED
|
@@ -288,6 +288,12 @@ exports.POLITICA_DE_RETRY = {
|
|
|
288
288
|
automatica: true,
|
|
289
289
|
...TEXTOS_DA_POLITICA['lease.busy'],
|
|
290
290
|
},
|
|
291
|
+
'concurrency.lease-indeterminado': {
|
|
292
|
+
motivo: 'concurrency.lease-indeterminado',
|
|
293
|
+
acao: 'esperar-janela',
|
|
294
|
+
automatica: false,
|
|
295
|
+
...TEXTOS_DA_POLITICA['concurrency.lease-indeterminado'],
|
|
296
|
+
},
|
|
291
297
|
// I-36 (T6): a vez chega quando a conducao atual terminar. Redespachar agora so recebe a mesma recusa,
|
|
292
298
|
// e passar na frente de quem conduz e exatamente o incidente de 19/09/2026.
|
|
293
299
|
'conducao.em-andamento': {
|
|
@@ -296,6 +302,12 @@ exports.POLITICA_DE_RETRY = {
|
|
|
296
302
|
automatica: true,
|
|
297
303
|
...TEXTOS_DA_POLITICA['conducao.em-andamento'],
|
|
298
304
|
},
|
|
305
|
+
'conducao.acao-necessaria': {
|
|
306
|
+
motivo: 'conducao.acao-necessaria',
|
|
307
|
+
acao: 'esperar-janela',
|
|
308
|
+
automatica: false,
|
|
309
|
+
...TEXTOS_DA_POLITICA['conducao.acao-necessaria'],
|
|
310
|
+
},
|
|
299
311
|
// I-41 (D10): formato e defeito de quem escreveu o pedido, e a spec dirigida conserta.
|
|
300
312
|
// Escalar isto para o dono seria pedir que ele revise a sintaxe do robo.
|
|
301
313
|
'hitl.formato': {
|
package/dist/sandbox.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Sandbox deterministica para os
|
|
3
|
+
* Sandbox deterministica para os cenarios de `ork eval` (bloco B4).
|
|
4
4
|
*
|
|
5
|
-
* Um
|
|
5
|
+
* Um cenario precisa exercitar o comportamento REAL do nucleo: git de verdade, worktree de
|
|
6
6
|
* verdade, lease de verdade. Fazer isso no repositorio do usuario seria inaceitavel, e
|
|
7
7
|
* simular git com dublê seria testar o dublê. A saida e um repositorio git temporario,
|
|
8
8
|
* criado, usado e apagado dentro da mesma execucao.
|
|
9
9
|
*
|
|
10
10
|
* Regras que esta sandbox respeita, e por isso ela pode rodar em `ork eval` na maquina de
|
|
11
11
|
* qualquer builder: nada de rede, nada de credencial, nada fora de um diretorio temporario,
|
|
12
|
-
* e limpeza garantida mesmo quando o
|
|
12
|
+
* e limpeza garantida mesmo quando o cenario falha.
|
|
13
13
|
*/
|
|
14
14
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
15
15
|
if (k2 === undefined) k2 = k;
|
|
@@ -55,7 +55,7 @@ const path = __importStar(require("node:path"));
|
|
|
55
55
|
const init_1 = require("./init");
|
|
56
56
|
const manifest_1 = require("./manifest");
|
|
57
57
|
const util_1 = require("./util");
|
|
58
|
-
/** `git` existe nesta maquina? Sem ele os
|
|
58
|
+
/** `git` existe nesta maquina? Sem ele os cenarios saem `unavailable`, nunca `passing`. */
|
|
59
59
|
function gitDisponivel() {
|
|
60
60
|
return (0, util_1.noPath)('git') !== null;
|
|
61
61
|
}
|
|
@@ -75,15 +75,15 @@ function commitar(dir, arquivo, conteudo, mensagem) {
|
|
|
75
75
|
/**
|
|
76
76
|
* Repositorio git temporario com manifesto gerado pelo proprio `ork init`.
|
|
77
77
|
*
|
|
78
|
-
* O manifesto vem do `init` de verdade e nao de um objeto escrito a mao:
|
|
79
|
-
* proprio manifesto testa o
|
|
78
|
+
* O manifesto vem do `init` de verdade e nao de um objeto escrito a mao: cenario que monta o
|
|
79
|
+
* proprio manifesto testa o cenario, nao o produto.
|
|
80
80
|
*/
|
|
81
81
|
function sandboxGit(nome, abbrev = 'evl') {
|
|
82
|
-
// I-49:
|
|
82
|
+
// I-49: cenario nunca escreve no registro compartilhado de contas do usuario.
|
|
83
83
|
if (!process.env.ORK_CONTAS_DIR) {
|
|
84
84
|
process.env.ORK_CONTAS_DIR = path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'ork-contas-eval-')), 'private');
|
|
85
85
|
}
|
|
86
|
-
// I-51:
|
|
86
|
+
// I-51: cenario nunca publica o estado da fabrica.
|
|
87
87
|
if (process.env.ORK_FABRICA_PUBLICAR === undefined)
|
|
88
88
|
process.env.ORK_FABRICA_PUBLICAR = '0';
|
|
89
89
|
if (!process.env.ORK_USUARIO_DIR)
|
|
@@ -91,10 +91,10 @@ function sandboxGit(nome, abbrev = 'evl') {
|
|
|
91
91
|
const dir = dirTemporario(nome);
|
|
92
92
|
(0, util_1.exec)('git', ['init', '-b', 'main'], dir);
|
|
93
93
|
(0, util_1.exec)('git', ['config', 'user.email', 'eval@orkastery.local'], dir);
|
|
94
|
-
(0, util_1.exec)('git', ['config', 'user.name', '
|
|
94
|
+
(0, util_1.exec)('git', ['config', 'user.name', 'Cenario do ork eval'], dir);
|
|
95
95
|
(0, util_1.exec)('git', ['config', 'commit.gpgsign', 'false'], dir);
|
|
96
|
-
commitar(dir, 'README.md', '# projeto do
|
|
97
|
-
(0, init_1.init)(dir, { nome: '
|
|
96
|
+
commitar(dir, 'README.md', '# projeto do cenario\n', 'inicial');
|
|
97
|
+
(0, init_1.init)(dir, { nome: 'cenario', abbrev });
|
|
98
98
|
return {
|
|
99
99
|
dir,
|
|
100
100
|
carregado: (0, manifest_1.exigirManifesto)(dir),
|
|
@@ -55,7 +55,7 @@ function executarSecurityScan(argv, ctx) {
|
|
|
55
55
|
const message = e.message;
|
|
56
56
|
if (!/^security-scan\.(config-invalid|dismissal-invalid)/.test(message))
|
|
57
57
|
throw e;
|
|
58
|
-
console.error(message);
|
|
58
|
+
console.error(json ? message : m.error(message));
|
|
59
59
|
return 1;
|
|
60
60
|
}
|
|
61
61
|
const files = (0, report_1.writeReport)(ctx.estado, report);
|
|
@@ -68,7 +68,7 @@ function executarSecurityScan(argv, ctx) {
|
|
|
68
68
|
if (notRun.length) {
|
|
69
69
|
ctx.escrever(m.notRunHeading);
|
|
70
70
|
for (const r of notRun)
|
|
71
|
-
ctx.escrever(m.notRun(r.name, m.states[r.state] ?? r.state, r.reason ?? ''));
|
|
71
|
+
ctx.escrever(m.notRun(r.name, m.states[r.state] ?? r.state, m.reason(r.reason ?? '')));
|
|
72
72
|
}
|
|
73
73
|
ctx.escrever(files.md);
|
|
74
74
|
}
|
|
@@ -143,7 +143,7 @@ function renderMarkdown(report) {
|
|
|
143
143
|
else {
|
|
144
144
|
out.push(`| ${m.tableTool} | ${m.tableExecutor} | ${m.tableState} | ${m.tableReason} |`, '| --- | --- | --- | --- |');
|
|
145
145
|
for (const r of report.tools) {
|
|
146
|
-
out.push(`| ${cell(r.name)} | ${r.executor ?? m.noExecutor} | ${m.states[r.state] ?? r.state} | ${cell(r.reason ?? '')} |`);
|
|
146
|
+
out.push(`| ${cell(r.name)} | ${r.executor ?? m.noExecutor} | ${m.states[r.state] ?? r.state} | ${cell(m.reason(r.reason ?? ''))} |`);
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
const news = report.findings.filter(f => f.status === 'new');
|
package/dist/session-watcher.js
CHANGED
|
@@ -61,6 +61,17 @@ const session_watcher_claude_1 = require("./session-watcher-claude");
|
|
|
61
61
|
const session_watcher_grok_1 = require("./session-watcher-grok");
|
|
62
62
|
const conta_esgotada_1 = require("./conta-esgotada");
|
|
63
63
|
const trabalho_thread_1 = require("./trabalho-thread");
|
|
64
|
+
const pedido_conducao_1 = require("./pedido-conducao");
|
|
65
|
+
/** O gate estreito da própria sessão vence diagnósticos genéricos do watcher. */
|
|
66
|
+
function pedidoDaConducao(eventos, sessionId, despachoEm) {
|
|
67
|
+
const evento = eventos.filter(e => e.tipo === 'gate_blocked' && e.origem === 'mcp.request_conduction' &&
|
|
68
|
+
e.sessionId === sessionId && e.despachoEm === despachoEm && typeof e.motivo === 'string' &&
|
|
69
|
+
pedido_conducao_1.MOTIVOS_DE_PEDIDO_A_CONDUCAO.includes(e.motivo) &&
|
|
70
|
+
typeof e.comando === 'string' && typeof e.despacho === 'string').at(-1);
|
|
71
|
+
return evento ? { motivo: evento.motivo, comando: evento.comando,
|
|
72
|
+
detalhe: typeof evento.detalhe === 'string' ? evento.detalhe : 'sessão solicitou ação da condução',
|
|
73
|
+
despacho: evento.despacho } : null;
|
|
74
|
+
}
|
|
64
75
|
/** Falhas operacionais e bloqueios sem retry automático não alegam conclusão do produto. */
|
|
65
76
|
function bloqueioPreservado(terminal) {
|
|
66
77
|
return terminal.classificacao === 'gate_blocked' && terminal.motivo !== null &&
|
|
@@ -474,18 +485,25 @@ function reconciliarSessaoSemWatcher(carregado, threadId, agoraMs = Date.now())
|
|
|
474
485
|
if (atuais.some(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
|
|
475
486
|
e.despachoEm === sessao.despachadaEm))
|
|
476
487
|
return;
|
|
488
|
+
const pedido = pedidoDaConducao(atuais, sessao.sessionId, sessao.despachadaEm);
|
|
477
489
|
const dados = { fase: sessao.fase, sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm,
|
|
478
|
-
sensorResultId, classificacao: 'gate_blocked', motivo: 'runtime.unavailable', runtime: sessao.runtime,
|
|
479
|
-
fonte: '
|
|
490
|
+
sensorResultId, classificacao: 'gate_blocked', motivo: pedido?.motivo ?? 'runtime.unavailable', runtime: sessao.runtime,
|
|
491
|
+
fonte: pedido ? 'mcp.request_conduction: parada intencional tipada pela sessão'
|
|
492
|
+
: 'conducao.batida: sessão verificada sem watcher e sem evento útil', fonteVencedora: null,
|
|
480
493
|
ok: false, conclusaoNativa: false, conclusaoNativaAusente: 'watcher ausente e fonte indisponível além do limite',
|
|
481
494
|
estado: 'bloqueada', observadoEm: new Date(agoraMs).toISOString(), gate: 'phase.dispatch',
|
|
482
|
-
origem: 'conducao.batida', morteLatenciaMs: agoraMs - ultimoUtil
|
|
483
|
-
|
|
495
|
+
origem: 'conducao.batida', morteLatenciaMs: agoraMs - ultimoUtil,
|
|
496
|
+
...(pedido ? { detalhe: pedido.detalhe, correcao: pedido.comando, comando: pedido.comando,
|
|
497
|
+
pedidoConducao: { contrato: 'ork.pedido-conducao/v1', despacho: pedido.despacho, estado: 'aberto' } } : {}) };
|
|
498
|
+
if (!pedido)
|
|
499
|
+
(0, ledger_1.registrar)(dir, threadId, 'sessao_morta', dados);
|
|
484
500
|
(0, ledger_1.registrar)(dir, threadId, 'gate_blocked', dados);
|
|
485
501
|
(0, ledger_1.registrar)(dir, threadId, 'phase_result', dados);
|
|
486
502
|
});
|
|
487
503
|
return { thread: threadId, sessionId: sessao.sessionId, estado: 'parada',
|
|
488
|
-
detalhe:
|
|
504
|
+
detalhe: pedidoDaConducao((0, ledger_1.lerLedger)(dir), sessao.sessionId, sessao.despachadaEm)
|
|
505
|
+
? 'sessão parou com pedido tipado para a condução'
|
|
506
|
+
: 'sessão verificada sem watcher e sem evento útil além do limite' };
|
|
489
507
|
}
|
|
490
508
|
}
|
|
491
509
|
function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registrada }, opcoes) {
|
|
@@ -714,6 +732,7 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
714
732
|
}
|
|
715
733
|
if (!podeTerminar)
|
|
716
734
|
return { ...base, bytesLidos };
|
|
735
|
+
const pedido = pedidoDaConducao(atuais, sessionId, sessao.despachadaEm);
|
|
717
736
|
const semTerminal = !terminal;
|
|
718
737
|
// Fato registrado para a autoridade de revisão: `null` só com terminal nativo correlacionado.
|
|
719
738
|
const conclusaoNativa = incompleto || invalido || aberto || descorrelacionado
|
|
@@ -726,6 +745,11 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
726
745
|
terminal = { classificacao: 'gate_blocked', motivo: 'runtime.silencio',
|
|
727
746
|
timestamp: new Date(now).toISOString(), turnId: null, fonte: 'processo ausente e arquivos estáveis',
|
|
728
747
|
tokens: new codex_events_1.ParserCodex().estado.tokens, duracaoMs: null };
|
|
748
|
+
if (pedido && (terminal.classificacao === 'fase_concluida' ||
|
|
749
|
+
terminal.classificacao === 'gate_blocked' && ['runtime.unavailable', 'runtime.silencio'].includes(terminal.motivo ?? ''))) {
|
|
750
|
+
terminal = { ...terminal, classificacao: 'gate_blocked', motivo: pedido.motivo,
|
|
751
|
+
fonte: `mcp.request_conduction: ${pedido.detalhe}` };
|
|
752
|
+
}
|
|
729
753
|
if (fechamento && (fechamento.exitCode !== 0 || fechamento.signal || fechamento.erro) &&
|
|
730
754
|
terminal.classificacao !== 'human.pending' && !bloqueioPreservado(terminal)) {
|
|
731
755
|
terminal = { ...terminal, classificacao: 'gate_blocked', motivo: 'runtime.unavailable' };
|
|
@@ -739,7 +763,7 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
739
763
|
? (0, trabalho_thread_1.gravarRespostaFinalDaSessao)(carregado.raiz, thread.id, sessionId, terminal.respostaFinal) : null;
|
|
740
764
|
const dados = { fase: sessao.fase, sessionId, despachoEm: sessao.despachadaEm, sensorResultId: resultadoId,
|
|
741
765
|
classificacao: terminal.classificacao, motivo: terminal.motivo, runtime: 'codex', fonte: terminal.fonte,
|
|
742
|
-
fonteVencedora: incompleto || invalido || aberto || descorrelacionado ? null : terminais[0]?.nome ?? null,
|
|
766
|
+
fonteVencedora: pedido || incompleto || invalido || aberto || descorrelacionado ? null : terminais[0]?.nome ?? null,
|
|
743
767
|
turnId: terminal.turnId, numeroTurno: terminal.numeroTurno ?? null,
|
|
744
768
|
tokens: terminal.tokens, exitCode: fechamento?.exitCode ?? null, exitCodeFonte: fechamento?.fonte ?? 'unavailable',
|
|
745
769
|
signal: fechamento?.signal ?? null, duracaoMs: fechamento?.duracaoMs ?? terminal.duracaoMs,
|
|
@@ -750,11 +774,13 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
750
774
|
estado: terminal.classificacao === 'fase_concluida' ? 'concluida' : 'bloqueada',
|
|
751
775
|
observadoEm: terminal.timestamp, gate: 'phase.dispatch', origem: 'sessions.watch',
|
|
752
776
|
morteLatenciaMs: morte ? now - cursor.progressoEm : null, ...(perfil ? { perfil } : {}),
|
|
777
|
+
...(pedido ? { detalhe: pedido.detalhe, correcao: pedido.comando, comando: pedido.comando,
|
|
778
|
+
pedidoConducao: { contrato: 'ork.pedido-conducao/v1', despacho: pedido.despacho, estado: 'aberto' } } : {}),
|
|
753
779
|
...(respostaFinal ? { respostaFinal: { arquivo: (0, trabalho_thread_1.caminhoDoTrabalho)(thread.id) + respostaFinal.arquivo,
|
|
754
780
|
sha256: respostaFinal.sha256, bytes: respostaFinal.bytes, truncada: respostaFinal.truncada } } : {}),
|
|
755
781
|
...(conta ? { falhaDeConta: { motivo: conta.falha.motivo, resetEm: conta.falha.resetEm, fonte: conta.falha.fonte,
|
|
756
782
|
trecho: conta.falha.trecho } } : {}) };
|
|
757
|
-
const tipo = semTerminal && morte && !incompleto && !conta ? 'sessao_morta' : terminal.classificacao;
|
|
783
|
+
const tipo = semTerminal && morte && !incompleto && !conta && !pedido ? 'sessao_morta' : terminal.classificacao;
|
|
758
784
|
// I-33 (D12): o perfil sai do rodizio na primeira gravacao do resultado, onde a evidencia esta.
|
|
759
785
|
if (conta && perfil && !atuais.some(e => e.tipo === 'phase_result' && e.sensorResultId === resultadoId)) {
|
|
760
786
|
try {
|