@orkastery/cli 0.6.5 → 0.6.7
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/agents/ork-check.md +4 -0
- package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +1 -1
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -1
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/assets/adapters-en/claude-code/agents/ork-check.md +4 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +14 -0
- package/dist/adapters/claude-bg.js +1 -1
- package/dist/agendador-cpu.js +27 -4
- package/dist/ambiente-funcional.js +72 -0
- package/dist/cenarios-sensores.js +3 -7
- package/dist/check-agil.js +204 -60
- package/dist/check-paralelo.js +101 -36
- package/dist/claim-lint.js +19 -0
- package/dist/claims.js +77 -11
- package/dist/fila-pesada.js +8 -6
- package/dist/fix.js +152 -6
- package/dist/hitl-gates.js +1 -1
- package/dist/index.js +53 -4
- package/dist/locale-ajuda.js +10 -4
- package/dist/locale-claims.js +22 -6
- package/dist/locale-operacao-restante.js +12 -0
- package/dist/locale-prompts.js +4 -2
- package/dist/locale-pulse.js +2 -0
- package/dist/locale-retry.js +8 -0
- package/dist/locale-verify.js +8 -0
- package/dist/mcp-artifacts.js +24 -0
- package/dist/mcp-install.js +1 -1
- package/dist/mcp-server.js +11 -1
- package/dist/mcp-verify-async.js +2 -1
- package/dist/noctum-provas.js +56 -30
- package/dist/recibo-prova.js +87 -0
- package/dist/retry.js +6 -0
- package/dist/security-scan/executor.js +9 -3
- package/dist/security-scan/guard.js +5 -2
- package/dist/session-watcher.js +94 -23
- package/dist/ship.js +1 -1
- package/dist/temporario-das-lanes.js +94 -0
- package/dist/verify.js +662 -410
- package/eval/fixtures/fx-sensores-runtime/caso.json +1 -1
- package/package.json +1 -1
- package/skills/phases/check-quality/SKILL.md +14 -0
|
@@ -156,12 +156,15 @@ function launch(pgidFile, timeoutMs, bin, args) {
|
|
|
156
156
|
child.on('error', e => { process.stderr.write(`${e.message}\n`); process.exit(127); });
|
|
157
157
|
if (child.pid)
|
|
158
158
|
fs.writeFileSync(pgidFile, String(child.pid));
|
|
159
|
-
const timer =
|
|
159
|
+
const timer = Number.isFinite(timeoutMs)
|
|
160
|
+
? setTimeout(() => { fs.writeFileSync(`${pgidFile}${exports.LAUNCH_TIMEOUT_SUFFIX}`, ''); kill(); }, timeoutMs)
|
|
161
|
+
: undefined;
|
|
160
162
|
for (const s of ['SIGTERM', 'SIGINT', 'SIGHUP']) {
|
|
161
163
|
process.on(s, () => { kill(); process.exit(128 + (os.constants.signals[s] ?? 15)); });
|
|
162
164
|
}
|
|
163
165
|
child.on('exit', (code, signal) => {
|
|
164
|
-
|
|
166
|
+
if (timer)
|
|
167
|
+
clearTimeout(timer);
|
|
165
168
|
kill(); // background processes the tool left in its group
|
|
166
169
|
fs.rmSync(pgidFile, { force: true });
|
|
167
170
|
process.exit(code ?? 128 + (signal ? os.constants.signals[signal] ?? 9 : 9));
|
package/dist/session-watcher.js
CHANGED
|
@@ -39,6 +39,8 @@ exports.reconciliarSessaoSemWatcher = reconciliarSessaoSemWatcher;
|
|
|
39
39
|
exports.validarRegistroWatcher = validarRegistroWatcher;
|
|
40
40
|
exports.validarFonteWatcher = validarFonteWatcher;
|
|
41
41
|
exports.prepararFonteWatcher = prepararFonteWatcher;
|
|
42
|
+
exports.esperarProntidaoWatcher = esperarProntidaoWatcher;
|
|
43
|
+
exports.esperarConfirmacaoDoPaiWatcher = esperarConfirmacaoDoPaiWatcher;
|
|
42
44
|
exports.iniciarWatcher = iniciarWatcher;
|
|
43
45
|
exports.acompanharSessao = acompanharSessao;
|
|
44
46
|
/** D6: observador restrito a uma sessão, cursor canônico e resultados idempotentes. */
|
|
@@ -906,6 +908,61 @@ function prepararFonteWatcher(raiz, sessionId, fonte) {
|
|
|
906
908
|
throw e;
|
|
907
909
|
}
|
|
908
910
|
}
|
|
911
|
+
class ErroDoApertoWatcher extends Error {
|
|
912
|
+
encerrarOutro;
|
|
913
|
+
constructor(message, encerrarOutro) {
|
|
914
|
+
super(message);
|
|
915
|
+
this.encerrarOutro = encerrarOutro;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
const TETO_ABSOLUTO_APERTO_WATCHER_MS = 60000;
|
|
919
|
+
const PAUSA_APERTO_WATCHER = new Int32Array(new SharedArrayBuffer(4));
|
|
920
|
+
function conferirTetoDoAperto(tetoMs) {
|
|
921
|
+
if (!Number.isFinite(tetoMs) || tetoMs <= 0)
|
|
922
|
+
throw new Error('teto invalido para o aperto de mao do watcher');
|
|
923
|
+
}
|
|
924
|
+
/** Lado do dispatcher: lentidao nao encerra um watcher cuja identidade continua viva. */
|
|
925
|
+
function esperarProntidaoWatcher(lerSinal, identidade, opcoes = {}) {
|
|
926
|
+
const agora = opcoes.agora ?? Date.now;
|
|
927
|
+
const estado = opcoes.estado ?? codex_runner_1.estadoProcesso;
|
|
928
|
+
const pausar = opcoes.pausar ?? ((ms) => { Atomics.wait(PAUSA_APERTO_WATCHER, 0, 0, ms); });
|
|
929
|
+
const tetoProntidaoMs = opcoes.tetoMs ?? TETO_ABSOLUTO_APERTO_WATCHER_MS;
|
|
930
|
+
conferirTetoDoAperto(tetoProntidaoMs);
|
|
931
|
+
const inicio = agora();
|
|
932
|
+
for (;;) {
|
|
933
|
+
if (agora() - inicio >= tetoProntidaoMs)
|
|
934
|
+
throw new ErroDoApertoWatcher('watcher sem prontidao confirmada', true);
|
|
935
|
+
const sinal = lerSinal();
|
|
936
|
+
if (sinal === 'confirmado')
|
|
937
|
+
return;
|
|
938
|
+
if (sinal === 'invalido')
|
|
939
|
+
throw new ErroDoApertoWatcher('watcher com prontidao invalida', true);
|
|
940
|
+
if (estado(identidade) === 'ausente')
|
|
941
|
+
throw new ErroDoApertoWatcher('watcher sem prontidao confirmada', false);
|
|
942
|
+
const restante = tetoProntidaoMs - (agora() - inicio);
|
|
943
|
+
pausar(Math.min(10, Math.max(1, restante)));
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
/** Lado do watcher: o ack continua pendente somente enquanto o pai capturado na partida nao saiu. */
|
|
947
|
+
async function esperarConfirmacaoDoPaiWatcher(lerSinal, identidadePai, opcoes = {}) {
|
|
948
|
+
const agora = opcoes.agora ?? Date.now;
|
|
949
|
+
const estado = opcoes.estado ?? codex_runner_1.estadoProcesso;
|
|
950
|
+
const pausar = opcoes.pausar ?? ((ms) => new Promise(resolve => setTimeout(resolve, ms)));
|
|
951
|
+
const tetoConfirmacaoMs = opcoes.tetoMs ?? TETO_ABSOLUTO_APERTO_WATCHER_MS;
|
|
952
|
+
conferirTetoDoAperto(tetoConfirmacaoMs);
|
|
953
|
+
const inicio = agora();
|
|
954
|
+
for (;;) {
|
|
955
|
+
if (agora() - inicio >= tetoConfirmacaoMs)
|
|
956
|
+
throw new ErroDoApertoWatcher('watcher sem confirmacao do pai', false);
|
|
957
|
+
const sinal = lerSinal();
|
|
958
|
+
if (sinal === 'confirmado')
|
|
959
|
+
return;
|
|
960
|
+
if (sinal === 'invalido' || estado(identidadePai) === 'ausente')
|
|
961
|
+
throw new ErroDoApertoWatcher('watcher sem confirmacao do pai', false);
|
|
962
|
+
const restante = tetoConfirmacaoMs - (agora() - inicio);
|
|
963
|
+
await pausar(Math.min(10, Math.max(1, restante)));
|
|
964
|
+
}
|
|
965
|
+
}
|
|
909
966
|
function iniciarWatcher(raiz, sessionId) {
|
|
910
967
|
const { thread, sessao: registrada } = (0, session_events_1.resolverSessao)(raiz, sessionId);
|
|
911
968
|
const sessao = (0, session_events_1.exigirSessaoDespachada)(registrada, sessionId);
|
|
@@ -947,27 +1004,29 @@ function iniciarWatcher(raiz, sessionId) {
|
|
|
947
1004
|
try {
|
|
948
1005
|
if (!identidade)
|
|
949
1006
|
throw new Error('watcher sem identidade de processo');
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
(0, ledger_1.registrar)(dir, thread.id, 'session_watcher_started', { fase: sessao.fase, sessionId,
|
|
957
|
-
despachoEm: sessao.despachadaEm, pid: identidade.pid, identidade, readyPath, token });
|
|
958
|
-
(0, codex_runner_1.gravarAtomico)(ackPath, { token });
|
|
959
|
-
return identidade.pid;
|
|
1007
|
+
esperarProntidaoWatcher(() => {
|
|
1008
|
+
if (!fs.existsSync(readyPath))
|
|
1009
|
+
return 'pendente';
|
|
1010
|
+
let ready;
|
|
1011
|
+
try {
|
|
1012
|
+
ready = lerJson(readyPath);
|
|
960
1013
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1014
|
+
catch {
|
|
1015
|
+
return 'invalido';
|
|
1016
|
+
}
|
|
1017
|
+
return ready && ready.token === token && ready.sessionId === sessionId && ready.despachoEm === sessao.despachadaEm &&
|
|
1018
|
+
JSON.stringify(ready.identidade) === JSON.stringify(identidade) && (0, codex_runner_1.estadoProcesso)(identidade) === 'vivo'
|
|
1019
|
+
? 'confirmado' : 'invalido';
|
|
1020
|
+
}, identidade);
|
|
1021
|
+
(0, ledger_1.registrar)(dir, thread.id, 'session_watcher_started', { fase: sessao.fase, sessionId,
|
|
1022
|
+
despachoEm: sessao.despachadaEm, pid: identidade.pid, identidade, readyPath, token });
|
|
1023
|
+
(0, codex_runner_1.gravarAtomico)(ackPath, { token });
|
|
1024
|
+
return identidade.pid;
|
|
966
1025
|
}
|
|
967
1026
|
catch (e) {
|
|
968
1027
|
falha();
|
|
969
|
-
//
|
|
970
|
-
if (identidade && (0, codex_runner_1.estadoProcesso)(identidade) === 'vivo')
|
|
1028
|
+
// Lentidao dentro do teto nao encerra o filho; so teto ou prontidao invalida autorizam o sinal.
|
|
1029
|
+
if (e instanceof ErroDoApertoWatcher && e.encerrarOutro && identidade && (0, codex_runner_1.estadoProcesso)(identidade) === 'vivo')
|
|
971
1030
|
child.kill('SIGTERM');
|
|
972
1031
|
throw e;
|
|
973
1032
|
}
|
|
@@ -978,18 +1037,30 @@ async function acompanhar() {
|
|
|
978
1037
|
try {
|
|
979
1038
|
const readyPath = process.argv[5], token = process.argv[6];
|
|
980
1039
|
if (readyPath && token) {
|
|
1040
|
+
const identidadePai = (0, codex_runner_1.identidadeProcesso)(process.ppid);
|
|
1041
|
+
if (!identidadePai)
|
|
1042
|
+
throw new Error('watcher sem confirmacao do pai');
|
|
981
1043
|
validarRegistroWatcher(carregado.raiz, sessionId);
|
|
982
1044
|
const sessao = (0, session_events_1.exigirSessaoDespachada)((0, session_events_1.resolverSessao)(carregado.raiz, sessionId, threadId).sessao, sessionId);
|
|
983
1045
|
const identidade = (0, codex_runner_1.identidadeProcesso)(process.pid);
|
|
984
1046
|
if (!identidade)
|
|
985
1047
|
throw new Error('watcher sem identidade propria');
|
|
986
1048
|
(0, codex_runner_1.gravarAtomico)(readyPath, { token, sessionId, despachoEm: sessao.despachadaEm, identidade });
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1049
|
+
await esperarConfirmacaoDoPaiWatcher(() => {
|
|
1050
|
+
if (!(0, ledger_1.threadPresente)((0, thread_1.dirThread)(carregado.raiz, threadId)))
|
|
1051
|
+
return 'invalido';
|
|
1052
|
+
const ackPath = readyPath + '.ack';
|
|
1053
|
+
if (!fs.existsSync(ackPath))
|
|
1054
|
+
return 'pendente';
|
|
1055
|
+
let ack;
|
|
1056
|
+
try {
|
|
1057
|
+
ack = lerJson(ackPath);
|
|
1058
|
+
}
|
|
1059
|
+
catch {
|
|
1060
|
+
return 'invalido';
|
|
1061
|
+
}
|
|
1062
|
+
return ack?.token === token ? 'confirmado' : 'invalido';
|
|
1063
|
+
}, identidadePai);
|
|
993
1064
|
}
|
|
994
1065
|
await acompanharSessao(carregado, sessionId, { threadId });
|
|
995
1066
|
}
|
package/dist/ship.js
CHANGED
|
@@ -560,7 +560,7 @@ function ship(carregado, threadId, opcoes) {
|
|
|
560
560
|
// 3. Verificacao independente: reexecuta claims e comandos no HEAD real da thread.
|
|
561
561
|
const verificacao = (0, verify_1.verificar)(carregado, threadId, { executor: opcoes.executorVerify,
|
|
562
562
|
conducao: { filaPesada: { ...opcoes.avisoDaFilaPesada, esperarMs: opcoes.esperarFilaPesadaMs } } });
|
|
563
|
-
r.verificacao = verificacao;
|
|
563
|
+
r.verificacao = (0, verify_1.resultadoVerifyRedigido)(verificacao);
|
|
564
564
|
if (!verificacaoCompletaParaShip(verificacao)) {
|
|
565
565
|
const motivo = (verificacao.parcial ? 'verify.failed'
|
|
566
566
|
: verificacao.motivos.find((m) => m !== 'claims.unverifiable'));
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ENV_TMPDIR_DA_RODADA = exports.ENV_TMPFS = void 0;
|
|
37
|
+
exports.sondarTmpfs = sondarTmpfs;
|
|
38
|
+
exports.selecionarTemporario = selecionarTemporario;
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const os = __importStar(require("node:os"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
exports.ENV_TMPFS = 'ORK_CHECK_TMPFS';
|
|
43
|
+
/** Marca de transporte: o verify, e nao a lane, e o dono do ciclo de vida de TMPDIR. */
|
|
44
|
+
exports.ENV_TMPDIR_DA_RODADA = 'ORK_CHECK_TMPDIR_DA_RODADA';
|
|
45
|
+
const TMPFS_MAGIC = 0x01021994;
|
|
46
|
+
/** Confere filesystem em memoria, espaco e escrita sem depender do nome ou do tamanho de uma maquina. */
|
|
47
|
+
function sondarTmpfs(dir) {
|
|
48
|
+
try {
|
|
49
|
+
if (!path.isAbsolute(dir) || !fs.statSync(dir).isDirectory())
|
|
50
|
+
return { ok: false, motivo: 'candidato-ausente' };
|
|
51
|
+
const s = fs.statfsSync(dir, { bigint: true });
|
|
52
|
+
if (Number(s.type) !== TMPFS_MAGIC)
|
|
53
|
+
return { ok: false, motivo: 'filesystem-nao-e-tmpfs' };
|
|
54
|
+
const teste = fs.mkdtempSync(path.join(dir, 'ork-check-sonda-'));
|
|
55
|
+
try {
|
|
56
|
+
fs.writeFileSync(path.join(teste, 'gravavel'), 'ok', { mode: 0o600 });
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
fs.rmSync(teste, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
return { ok: true, livres: Number(s.bavail * s.bsize) };
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
const erro = e;
|
|
65
|
+
return { ok: false, motivo: `sonda-falhou:${String(erro.code || erro.message)}` };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* O tmpfs e opt-in ate a bancada provar ganho. `auto` exige folga proporcional de memoria e espaco; qualquer duvida
|
|
70
|
+
* usa o temporario em disco. Verify e lanes chamam esta mesma funcao para nao criarem politicas diferentes.
|
|
71
|
+
*/
|
|
72
|
+
function selecionarTemporario(opcoes = {}) {
|
|
73
|
+
const chave = opcoes.chave ?? process.env[exports.ENV_TMPFS];
|
|
74
|
+
const disco = opcoes.disco ?? os.tmpdir();
|
|
75
|
+
const candidatos = opcoes.candidatos ?? [process.env.XDG_RUNTIME_DIR, '/dev/shm']
|
|
76
|
+
.filter((x) => !!x);
|
|
77
|
+
const memoriaLivre = opcoes.memoriaLivre ?? os.freemem();
|
|
78
|
+
const memoriaTotal = opcoes.memoriaTotal ?? os.totalmem();
|
|
79
|
+
const sondar = opcoes.sondar ?? sondarTmpfs;
|
|
80
|
+
if (chave !== 'auto')
|
|
81
|
+
return { diretorio: disco, estado: 'fallback', motivo: chave ? `chave-${chave}` : 'desligado-por-padrao' };
|
|
82
|
+
if (!(memoriaTotal > 0) || memoriaLivre / memoriaTotal < 0.25) {
|
|
83
|
+
return { diretorio: disco, estado: 'fallback', motivo: 'memoria-livre-sem-folga' };
|
|
84
|
+
}
|
|
85
|
+
const necessario = Math.min(memoriaLivre / 4, memoriaTotal / 10);
|
|
86
|
+
const motivos = [];
|
|
87
|
+
for (const candidato of [...new Set(candidatos)]) {
|
|
88
|
+
const r = sondar(candidato);
|
|
89
|
+
if (r.ok && r.livres >= necessario)
|
|
90
|
+
return { diretorio: candidato, estado: 'agile', motivo: 'tmpfs-gravavel-com-folga' };
|
|
91
|
+
motivos.push(`${candidato}:${r.ok ? 'espaco-sem-folga' : r.motivo}`);
|
|
92
|
+
}
|
|
93
|
+
return { diretorio: disco, estado: 'fallback', motivo: motivos.length ? motivos.join(';') : 'sem-candidato-tmpfs' };
|
|
94
|
+
}
|