@orkastery/cli 0.6.0 → 0.6.2
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 +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/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +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/orkmind_fixture.py +4 -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 +9 -7
- package/dist/adapters/grok-events.js +227 -0
- package/dist/adapters/grok-mcp-servidor.js +622 -0
- package/dist/adapters/grok-mcp.js +178 -0
- package/dist/adapters/grok.js +686 -0
- package/dist/agendador-cpu.js +92 -0
- package/dist/branch-de-estado.js +7 -2
- package/dist/changelog-check.js +217 -0
- package/dist/check-agil.js +289 -25
- package/dist/check-paralelo.js +73 -18
- package/dist/ci.js +3 -2
- package/dist/claim-lint.js +29 -0
- package/dist/claims.js +4 -0
- package/dist/conducao.js +5 -0
- package/dist/docs.js +16 -16
- package/dist/doctor-forja.js +1 -3
- package/dist/doctor.js +1 -1
- package/dist/entrega-pr.js +10 -10
- package/dist/fabrica-estado.js +20 -11
- package/dist/fila-pesada.js +121 -11
- package/dist/hitl-classificacao.js +1 -0
- package/dist/horario.js +4 -1
- package/dist/index.js +63 -35
- package/dist/integracoes-locais.js +2 -0
- package/dist/intelligence-graph-cli.js +27 -9
- package/dist/locale-accounts.js +11 -3
- package/dist/locale-ajuda.js +10 -6
- package/dist/locale-claims.js +16 -2
- package/dist/locale-forja.js +2 -4
- 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 +2 -2
- 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 +56 -2
- package/dist/locale-security-scan.js +35 -1
- package/dist/locale-ship.js +10 -2
- package/dist/locale-verify.js +15 -0
- package/dist/locale.js +24 -7
- package/dist/maestro-cli.js +12 -17
- package/dist/manifest.js +6 -1
- package/dist/mcp-install.js +24 -13
- package/dist/mcp-server.js +62 -33
- 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/merge-da-entrega.js +85 -0
- package/dist/network-roadmap.js +18 -14
- package/dist/noctum-aceite.js +154 -14
- package/dist/noctum-cli.js +69 -12
- package/dist/noctum-entrega.js +55 -7
- package/dist/noctum-envelope.js +1 -1
- package/dist/noctum-execucao.js +5 -1
- package/dist/noctum-fechamento.js +18 -7
- package/dist/noctum-fila.js +6 -1
- package/dist/noctum-guarda.js +81 -4
- package/dist/noctum-maquinas.js +5 -1
- package/dist/noctum-modo.js +35 -7
- package/dist/noctum-reconciliacao.js +4 -1
- package/dist/noctum-rede.js +102 -0
- package/dist/noctum-relatorio.js +44 -10
- package/dist/noctum-retomada-rede.js +71 -0
- package/dist/noctum-vigia.js +49 -9
- package/dist/parado-no-condutor.js +14 -15
- package/dist/pedido-conducao.js +51 -0
- package/dist/phase.js +43 -15
- package/dist/postura-local.js +7 -3
- package/dist/preflight.js +27 -27
- package/dist/prompts.js +4 -2
- package/dist/pulse.js +4 -2
- package/dist/ratelimit.js +1 -0
- package/dist/rede.js +24 -12
- package/dist/retry.js +115 -10
- package/dist/runtime-context.js +165 -45
- package/dist/runtime-escada.js +7 -1
- package/dist/runtime-profiles.js +27 -17
- package/dist/runtimes.js +42 -5
- package/dist/security-scan/agil.js +18 -7
- package/dist/security-scan/cli.js +2 -2
- package/dist/security-scan/executor.js +8 -0
- package/dist/security-scan/report.js +1 -1
- package/dist/session-watcher-grok.js +425 -0
- package/dist/session-watcher.js +52 -11
- package/dist/sessoes-contas.js +33 -5
- package/dist/setup.js +11 -11
- package/dist/varredura-acoes.js +8 -15
- package/dist/verify.js +191 -43
- package/package.json +2 -2
- 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/runtime-context.js
CHANGED
|
@@ -33,10 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS = exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS = exports.MOTIVO_SEM_HOST_MCP = exports.RUNTIMES_SEM_HOST_MCP = void 0;
|
|
36
37
|
exports.novaIdentidadeDeDespacho = novaIdentidadeDeDespacho;
|
|
37
38
|
exports.capacidadeDoRuntimeNoProjeto = capacidadeDoRuntimeNoProjeto;
|
|
39
|
+
exports.capacidadeDaRotacao = capacidadeDaRotacao;
|
|
38
40
|
exports.contextoDoProjeto = contextoDoProjeto;
|
|
39
41
|
exports.validarContextoRuntime = validarContextoRuntime;
|
|
42
|
+
exports.validarContextoDoGrok = validarContextoDoGrok;
|
|
40
43
|
exports.lerDeclaracaoDeMod = lerDeclaracaoDeMod;
|
|
41
44
|
exports.modsDeFaseInstalados = modsDeFaseInstalados;
|
|
42
45
|
/** Contexto interno opt-in: configuracao M4 existente + catalogo instalado, nunca args do modelo. */
|
|
@@ -83,48 +86,89 @@ function ler(raiz, file, limite) {
|
|
|
83
86
|
fs.closeSync(fd);
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
/** A entrada `orkastery` de um host, conferida contra o perfil ja achado nos hosts anteriores; sem entrada, o perfil fica. */
|
|
90
|
+
function perfilDoHost(raiz, host, encontrado) {
|
|
91
|
+
const file = (0, mcp_install_1.arquivoDoHostMcp)(raiz, host), toml = host !== 'claude-code';
|
|
92
|
+
if (!fs.existsSync(file))
|
|
93
|
+
return encontrado;
|
|
94
|
+
let config;
|
|
95
|
+
try {
|
|
92
96
|
const text = ler(raiz, file, 262144).toString('utf8');
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
config = objeto(toml ? (0, smol_toml_1.parse)(text) : JSON.parse(text));
|
|
98
|
+
}
|
|
99
|
+
catch (erro) {
|
|
100
|
+
// RM-067 (F4b, GO-FIX A4 e N2): o motivo tipado do grok leva o codigo do erro de sistema ou a primeira linha do parser,
|
|
101
|
+
// sem o trecho do arquivo do time nem o caminho da maquina.
|
|
102
|
+
if (host !== 'grok')
|
|
103
|
+
throw erro;
|
|
104
|
+
const causa = erro.code ?? erro.message.split('\n')[0];
|
|
105
|
+
throw Error(`runtime.context.conflict: .grok/config.toml do projeto ilegivel (${causa}); conserte o arquivo ou tire dele a entrada orkastery`);
|
|
106
|
+
}
|
|
107
|
+
const chave = toml ? 'mcp_servers' : 'mcpServers';
|
|
108
|
+
if (config[chave] === undefined)
|
|
109
|
+
return encontrado;
|
|
110
|
+
const servidores = objeto(config[chave]);
|
|
111
|
+
if (!Object.hasOwn(servidores, 'orkastery'))
|
|
112
|
+
return encontrado;
|
|
113
|
+
const entrada = objeto(servidores.orkastery), padrao = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host);
|
|
114
|
+
const legado = padrao.args.slice(0, -2);
|
|
115
|
+
let transporte = 'github-ssh';
|
|
116
|
+
let argv = entrada.args;
|
|
117
|
+
let permissoesFilho = 'interactive';
|
|
118
|
+
if (Array.isArray(argv) && argv[argv.length - 2] === '--child-permissions') {
|
|
119
|
+
if (!['interactive', 'worktree'].includes(argv[argv.length - 1]))
|
|
120
|
+
throw Error('runtime.context.conflict: perfil de filho invalido');
|
|
121
|
+
permissoesFilho = argv[argv.length - 1];
|
|
122
|
+
argv = argv.slice(0, -2);
|
|
123
|
+
}
|
|
124
|
+
if (JSON.stringify(argv) !== JSON.stringify(legado)) {
|
|
125
|
+
if (!Array.isArray(argv) || argv.length !== padrao.args.length ||
|
|
126
|
+
argv[argv.length - 2] !== '--ship-transport' || !(0, mcp_transportes_1.ehTransporteShipMcp)(argv[argv.length - 1]))
|
|
127
|
+
throw Error('runtime.context.conflict: MCP Orkastery divergente; transporte invalido ou argumentos extras');
|
|
128
|
+
transporte = argv[argv.length - 1];
|
|
129
|
+
}
|
|
130
|
+
const esperado = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host, undefined, transporte);
|
|
131
|
+
if (entrada.command !== esperado.command || (JSON.stringify(argv) !== JSON.stringify(esperado.args) && JSON.stringify(argv) !== JSON.stringify(legado)))
|
|
132
|
+
throw Error('runtime.context.conflict: MCP Orkastery divergente; repare a instalacao do projeto');
|
|
133
|
+
if (encontrado !== undefined && encontrado.transporteShip !== transporte)
|
|
134
|
+
throw Error('runtime.context.conflict: transportes SHIP divergentes entre hosts');
|
|
135
|
+
if (encontrado !== undefined && encontrado.permissoesFilho !== permissoesFilho)
|
|
136
|
+
throw Error('runtime.context.conflict: perfis de filho divergentes entre hosts');
|
|
137
|
+
return { ...encontrado, transporteShip: transporte, permissoesFilho, ...(host === 'codex' ? { politicasCodex: entrada } : {}) };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* O perfil da instalacao MCP do projeto. RM-067 (F4b, GO-FIX A4): o `.grok/config.toml` tambem prepara, em TOML como o do
|
|
141
|
+
* codex, mas ele e a config do proprio grok, que o time pode manter: para quem nao e o grok (`quem`), a falha de leitura,
|
|
142
|
+
* de parse ou de conferencia dele nao derruba a preparacao dos outros hosts, e a entrada dele fica de fora. GO-FIX N1: sem
|
|
143
|
+
* outro host preparado, a entrada `orkastery` do grok e a preparacao do projeto, e engolir a falha dela faria o claude-bg
|
|
144
|
+
* e o codex despacharem como num projeto legado, sem o MCP; a falha volta, e so a config do time sem a entrada fica de fora.
|
|
145
|
+
*/
|
|
146
|
+
function preparado(raiz, quem) {
|
|
147
|
+
let encontrado;
|
|
148
|
+
let falhaDoGrok = null;
|
|
149
|
+
for (const host of mcp_install_1.HOSTS_MCP) {
|
|
150
|
+
try {
|
|
151
|
+
encontrado = perfilDoHost(raiz, host, encontrado);
|
|
110
152
|
}
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
transporte = argv[argv.length - 1];
|
|
153
|
+
catch (erro) {
|
|
154
|
+
if (host !== 'grok' || quem === undefined || quem === 'grok')
|
|
155
|
+
throw erro;
|
|
156
|
+
falhaDoGrok = erro;
|
|
116
157
|
}
|
|
117
|
-
const esperado = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host, undefined, transporte);
|
|
118
|
-
if (entrada.command !== esperado.command || (JSON.stringify(argv) !== JSON.stringify(esperado.args) && JSON.stringify(argv) !== JSON.stringify(legado)))
|
|
119
|
-
throw Error('runtime.context.conflict: MCP Orkastery divergente; repare a instalacao do projeto');
|
|
120
|
-
if (encontrado !== undefined && encontrado.transporteShip !== transporte)
|
|
121
|
-
throw Error('runtime.context.conflict: transportes SHIP divergentes entre hosts');
|
|
122
|
-
if (encontrado !== undefined && encontrado.permissoesFilho !== permissoesFilho)
|
|
123
|
-
throw Error('runtime.context.conflict: perfis de filho divergentes entre hosts');
|
|
124
|
-
encontrado = { ...encontrado, transporteShip: transporte, permissoesFilho, ...(host === 'codex' ? { politicasCodex: entrada } : {}) };
|
|
125
158
|
}
|
|
159
|
+
if (falhaDoGrok !== null && encontrado === undefined && podeTerEntradaDoOrk(raiz))
|
|
160
|
+
throw falhaDoGrok;
|
|
126
161
|
return encontrado;
|
|
127
162
|
}
|
|
163
|
+
/** O `.grok/config.toml` do projeto tem, ou pode ter, a entrada `orkastery`; o que nao se le conta como se tivesse. */
|
|
164
|
+
function podeTerEntradaDoOrk(raiz) {
|
|
165
|
+
try {
|
|
166
|
+
return ler(raiz, (0, mcp_install_1.arquivoDoHostMcp)(raiz, 'grok'), 262144).toString('utf8').includes('orkastery');
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
128
172
|
function raizCanonica(projeto) {
|
|
129
173
|
if (!path.isAbsolute(projeto))
|
|
130
174
|
throw Error('runtime.context.invalid: projeto absoluto obrigatorio');
|
|
@@ -140,6 +184,8 @@ function hostDoRuntime(runtime) {
|
|
|
140
184
|
return 'claude-code';
|
|
141
185
|
if (runtime === 'codex')
|
|
142
186
|
return 'codex';
|
|
187
|
+
if (runtime === 'grok')
|
|
188
|
+
return 'grok';
|
|
143
189
|
throw Error('runtime.context.invalid: runtime desconhecido');
|
|
144
190
|
}
|
|
145
191
|
/** Confere o recibo e todos os bytes do adaptador antes de considerar o runtime um destino. */
|
|
@@ -186,40 +232,88 @@ function capacidadeDoRuntimeNoProjeto(projeto, runtime) {
|
|
|
186
232
|
let host = null;
|
|
187
233
|
try {
|
|
188
234
|
const raiz = raizCanonica(projeto);
|
|
189
|
-
const perfil = preparado(raiz);
|
|
235
|
+
const perfil = preparado(raiz, runtime);
|
|
190
236
|
if (!perfil)
|
|
191
237
|
return { runtime, host: null, preparado: false, capaz: true, motivo: null };
|
|
238
|
+
if (exports.RUNTIMES_SEM_HOST_MCP.includes(runtime))
|
|
239
|
+
return { runtime, host: null, preparado: true, capaz: false, motivo: exports.MOTIVO_SEM_HOST_MCP };
|
|
192
240
|
host = hostDoRuntime(runtime);
|
|
193
|
-
|
|
241
|
+
// RM-067 (F4b, G6): o grok nao tem adaptador instalavel (plugin, skills, mods); o contexto dele e so o MCP.
|
|
242
|
+
if (host !== 'grok')
|
|
243
|
+
conferirInstalacaoDoHost(raiz, host);
|
|
244
|
+
if (exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS.includes(runtime))
|
|
245
|
+
return { runtime, host, preparado: true, capaz: false, motivo: exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS };
|
|
194
246
|
return { runtime, host, preparado: true, capaz: true, motivo: null };
|
|
195
247
|
}
|
|
196
248
|
catch (erro) {
|
|
197
249
|
return { runtime, host, preparado: true, capaz: false, motivo: erro.message };
|
|
198
250
|
}
|
|
199
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* RM-067 (D15 da ork-grokbuild): runtimes homologados que ainda nao tem host MCP do Orkastery. A sessao filha deles
|
|
254
|
+
* despacha sem contexto, como num projeto sem entrada MCP, ate o host existir. A capacidade de rotacao
|
|
255
|
+
* (`capacidadeDoRuntimeNoProjeto`) nao muda: num projeto preparado, eles seguem fora dos destinos automaticos.
|
|
256
|
+
* RM-067 (F4b, G6): o grok saiu daqui com o host `grok`; a lista fica para o proximo runtime sem host.
|
|
257
|
+
*/
|
|
258
|
+
exports.RUNTIMES_SEM_HOST_MCP = [];
|
|
259
|
+
/** RM-067 (F4): o motivo tipado de um runtime sem host MCP num projeto preparado. */
|
|
260
|
+
exports.MOTIVO_SEM_HOST_MCP = 'runtime.context.no-host: runtime sem host MCP do Orkastery; a sessao despacha sem o contexto do projeto';
|
|
261
|
+
/**
|
|
262
|
+
* RM-067 (F4b, GO-FIX A5; F4c, D9): runtimes com o host MCP que, num projeto preparado, ficam fora dos destinos
|
|
263
|
+
* automaticos (o fallback do retry e a escada), porque o servidor MCP do ork nao grava o estado na sessao deles e a fase
|
|
264
|
+
* que chega por fallback pararia sem prova. O grok ficou aqui da F4b a F4c: o sandbox dele vale para o processo inteiro e
|
|
265
|
+
* os filhos (G17 da RM-067), e o servidor stdio era filho dele. Desde a F4c o servidor e um processo do ork, fora do
|
|
266
|
+
* sandbox (`adapters/grok-mcp.ts`), e a fase do grok no piso `workspace` fecha com prova; a lista fica vazia, para o
|
|
267
|
+
* proximo runtime cujo MCP nao grave o estado, como `RUNTIMES_SEM_HOST_MCP`.
|
|
268
|
+
*/
|
|
269
|
+
exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS = [];
|
|
270
|
+
exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS = 'runtime.context.sandbox: o sandbox do runtime vale tambem para o servidor MCP do ' +
|
|
271
|
+
'ork, que nao grava o estado; como destino automatico num projeto preparado, o runtime fica fora';
|
|
272
|
+
/**
|
|
273
|
+
* RM-067 (F4): a capacidade de um runtime para a rotacao do retry. A troca de perfil DENTRO do runtime em que a thread ja
|
|
274
|
+
* despachou (`mesmoRuntime`) vale para o runtime sem host MCP e para o que fica fora dos destinos automaticos: a sessao
|
|
275
|
+
* dele ja roda como rodava, e a outra conta nao muda isso, entao o `ork retry` troca o perfil dele como troca o dos outros
|
|
276
|
+
* runtimes. Como alvo de fallback num projeto preparado, ele segue incapaz. Desde a F4c, nenhum runtime homologado esta
|
|
277
|
+
* nas duas listas, e o grok e capaz nos dois papeis.
|
|
278
|
+
*/
|
|
279
|
+
function capacidadeDaRotacao(projeto, runtime, mesmoRuntime) {
|
|
280
|
+
const capacidade = capacidadeDoRuntimeNoProjeto(projeto, runtime);
|
|
281
|
+
if (capacidade.capaz || !mesmoRuntime)
|
|
282
|
+
return capacidade;
|
|
283
|
+
const soComoDestino = (exports.RUNTIMES_SEM_HOST_MCP.includes(runtime) && capacidade.motivo === exports.MOTIVO_SEM_HOST_MCP) ||
|
|
284
|
+
(exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS.includes(runtime) && capacidade.motivo === exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS);
|
|
285
|
+
return soComoDestino ? { ...capacidade, capaz: true } : capacidade;
|
|
286
|
+
}
|
|
200
287
|
/** Projeto sem entrada MCP Orkastery continua com o contrato legado. Nao instala nem altera arquivos. */
|
|
201
288
|
function contextoDoProjeto(projeto, runtime, cwd, threadId) {
|
|
202
289
|
const raiz = raizCanonica(projeto);
|
|
203
|
-
const perfil = preparado(raiz);
|
|
290
|
+
const perfil = preparado(raiz, runtime);
|
|
204
291
|
if (!perfil)
|
|
205
292
|
return undefined;
|
|
293
|
+
if (exports.RUNTIMES_SEM_HOST_MCP.includes(runtime))
|
|
294
|
+
return undefined;
|
|
206
295
|
const host = hostDoRuntime(runtime);
|
|
207
296
|
if (!threadId)
|
|
208
297
|
throw Error('runtime.context.invalid: thread obrigatoria para sessao filha');
|
|
209
298
|
const contexto = { projeto: raiz, host, threadId, transporteShip: perfil.transporteShip, permissoesFilho: perfil.permissoesFilho };
|
|
210
|
-
|
|
299
|
+
if (host === 'grok')
|
|
300
|
+
validarContextoDoGrok(contexto, cwd);
|
|
301
|
+
else
|
|
302
|
+
validarContextoRuntime(contexto, cwd);
|
|
211
303
|
return contexto;
|
|
212
304
|
}
|
|
213
|
-
/**
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
305
|
+
/**
|
|
306
|
+
* A conferencia do vinculo, comum a todo host: projeto preparado, perfil e transporte iguais aos da instalacao, cwd e
|
|
307
|
+
* thread da sessao filha, identidade do despacho e, no perfil worktree, a worktree propria da thread. RM-067 (F4b, D2):
|
|
308
|
+
* saiu de `validarContextoRuntime` sem mudar a ordem das conferencias, para o contexto do grok usar a mesma.
|
|
309
|
+
*/
|
|
310
|
+
function conferirVinculo(contexto, cwd) {
|
|
217
311
|
if (contexto.transporteShip !== undefined && !(0, mcp_transportes_1.ehTransporteShipMcp)(contexto.transporteShip))
|
|
218
312
|
throw Error('runtime.context.invalid: transporte desconhecido');
|
|
219
313
|
const raiz = raizCanonica(contexto.projeto);
|
|
220
314
|
if (contexto.permissoesFilho !== undefined && !['interactive', 'worktree'].includes(contexto.permissoesFilho))
|
|
221
315
|
throw Error('runtime.context.invalid: perfil de filho desconhecido');
|
|
222
|
-
const perfil = preparado(raiz);
|
|
316
|
+
const perfil = preparado(raiz, contexto.host);
|
|
223
317
|
if (!perfil)
|
|
224
318
|
throw Error('runtime.context.missing: projeto nao preparado pelo instalador MCP');
|
|
225
319
|
const { transporteShip, permissoesFilho } = perfil;
|
|
@@ -246,6 +340,13 @@ function validarContextoRuntime(contexto, cwd) {
|
|
|
246
340
|
if (!(0, worktree_1.worktreesDoGit)(raiz).some(w => w.dir === cwd && w.branch === (0, worktree_1.branchDaWorktree)(thread)))
|
|
247
341
|
throw Error('runtime.context.worktree: worktree nao registrada na branch da thread');
|
|
248
342
|
}
|
|
343
|
+
return { raiz, perfil, transporteShip, permissoesFilho, thread };
|
|
344
|
+
}
|
|
345
|
+
/** Revalida no receptor do despacho, incluindo bytes instalados e escopo real do cwd. */
|
|
346
|
+
function validarContextoRuntime(contexto, cwd) {
|
|
347
|
+
if (!contexto || (contexto.host !== 'claude-code' && contexto.host !== 'codex'))
|
|
348
|
+
throw Error('runtime.context.invalid: host desconhecido');
|
|
349
|
+
const { raiz, perfil, transporteShip, permissoesFilho, thread } = conferirVinculo(contexto, cwd);
|
|
249
350
|
const { instalacao, arquivos, conferidos, bootstrap } = conferirInstalacaoDoHost(raiz, contexto.host);
|
|
250
351
|
const modsDeFase = contexto.host === 'claude-code' ? modsDeFaseInstalados(raiz, instalacao, arquivos, conferidos) : [];
|
|
251
352
|
// Capacidade derivada do bloco atual, nunca aceita como entrada do modelo.
|
|
@@ -265,6 +366,25 @@ function validarContextoRuntime(contexto, cwd) {
|
|
|
265
366
|
...(contexto.host === 'codex' && permissoesFilho === 'worktree' ? (0, mcp_install_1.politicasFilhoCodex)(perfil.politicasCodex ?? {}) : {}) };
|
|
266
367
|
return { projeto: raiz, instalacao, bootstrap, permissoesFilho, permiteEditarProduto, grafoMcp, servidor, modsDeFase, agentTeams };
|
|
267
368
|
}
|
|
369
|
+
/**
|
|
370
|
+
* RM-067 (F4b, D2): o contexto do grok, revalidado no despacho. O vinculo e o mesmo dos outros hosts; nao ha adaptador
|
|
371
|
+
* instalado a conferir (o grok nao tem plugin, skills nem mods do Orkastery). Devolve o que o comando e o despacho usam:
|
|
372
|
+
* o perfil filho, a flag do grafo da raiz e, desde a F4c, a especificacao do servidor externo vinculado a thread e ao despacho.
|
|
373
|
+
*/
|
|
374
|
+
function validarContextoDoGrok(contexto, cwd) {
|
|
375
|
+
if (!contexto || contexto.host !== 'grok')
|
|
376
|
+
throw Error('runtime.context.invalid: host grok esperado');
|
|
377
|
+
const { raiz, transporteShip, permissoesFilho, thread } = conferirVinculo(contexto, cwd);
|
|
378
|
+
// RM-067 (F4b, GO-FIX B1): a config da sessao vai no cwd; na raiz do projeto ela viraria a entrada do host grok.
|
|
379
|
+
if (!thread.worktree || thread.worktree === raiz || cwd === raiz)
|
|
380
|
+
throw Error('runtime.context.worktree: o grok com o MCP do ork exige a worktree propria da thread; a config da sessao nunca vai a raiz do projeto');
|
|
381
|
+
const grafoMcp = (0, mcp_grafo_1.grafoLigado)((0, manifest_1.exigirManifesto)(raiz).manifesto);
|
|
382
|
+
const publicVerifiers = (0, hitl_public_receipt_1.publicHitlVerifiers)();
|
|
383
|
+
const servidor = { projeto: raiz, threadId: contexto.threadId,
|
|
384
|
+
dispatchId: contexto.identidade?.dispatchId ?? null, permissoesFilho, transporteShip,
|
|
385
|
+
...(publicVerifiers ? { env: { [hitl_public_receipt_1.ENV_HITL_VERIFIERS]: publicVerifiers } } : {}) };
|
|
386
|
+
return { projeto: raiz, threadId: contexto.threadId, permissoesFilho, grafoMcp, servidor };
|
|
387
|
+
}
|
|
268
388
|
const DECLARACAO_OU_MANIFESTO_DE_MOD = /^mods\/[^/]+\/(?:orkastery-mod\.json|\.claude-plugin\/plugin\.json)$/;
|
|
269
389
|
const DECLARACAO_DE_MOD = /^mods\/([^/]+)\/orkastery-mod\.json$/;
|
|
270
390
|
const NOME_DE_MOD = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
package/dist/runtime-escada.js
CHANGED
|
@@ -44,6 +44,7 @@ const locale_1 = require("./locale");
|
|
|
44
44
|
const modos_1 = require("./modos");
|
|
45
45
|
const runtime_profiles_1 = require("./runtime-profiles");
|
|
46
46
|
const setup_1 = require("./setup");
|
|
47
|
+
const runtimes_1 = require("./runtimes");
|
|
47
48
|
const runtime_context_1 = require("./runtime-context");
|
|
48
49
|
const thread_1 = require("./thread");
|
|
49
50
|
/** Os degraus, na ordem do pedido do dono de 12/10/2026. */
|
|
@@ -163,6 +164,11 @@ function planoDoDegrau(carregado, thread, fase, n, despacho, tentados, agoraMs =
|
|
|
163
164
|
}
|
|
164
165
|
return { pulo: 'fallback-sem-destino' };
|
|
165
166
|
}
|
|
167
|
+
// RM-067 (F3, F4): o runtime sem cota esgotada tipada (o grok) fica fora do degrau "outra conta": a escada nunca troca a
|
|
168
|
+
// conta dele, ate o formato da cota esgotada ser confirmado no ensaio real. Como alvo de fallback (degrau 2) ele vale no
|
|
169
|
+
// projeto sem o MCP do ork e, desde a F4c (o servidor do ork fora do sandbox dele), tambem no preparado.
|
|
170
|
+
if (runtimes_1.RUNTIMES_SEM_COTA_TIPADA.includes(despacho.runtime))
|
|
171
|
+
return { pulo: 'cota-sem-sinal-tipado' };
|
|
166
172
|
// Degrau 3: outra conta do runtime que falhou. O diretorio de cada conta e o que separa um daemon do outro. Os perfis
|
|
167
173
|
// tentados sao os efetivos (o redespacho sem perfil pedido escolhe um, e e ele que falhou); o despacho que nasceu sem
|
|
168
174
|
// perfil (o runtime caiu antes da escolha) tem como conta de origem a que o degrau 1 de fato usou.
|
|
@@ -187,7 +193,7 @@ function planoDoDegrau(carregado, thread, fase, n, despacho, tentados, agoraMs =
|
|
|
187
193
|
if (p.id === contaDeOrigem?.id || jaTentados.has(p.id))
|
|
188
194
|
return false;
|
|
189
195
|
const d = (0, runtime_profiles_1.perfilDeDespacho)(p);
|
|
190
|
-
return !dirOriginal || (
|
|
196
|
+
return !dirOriginal || (0, runtime_profiles_1.diretorioDoPerfil)(d) !== dirOriginal;
|
|
191
197
|
});
|
|
192
198
|
return outro ? { destino: { ...original, perfil: outro.id } } : { pulo: 'sem-outro-perfil' };
|
|
193
199
|
}
|
package/dist/runtime-profiles.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.COLUNAS_DE_PERFIS = exports.POLITICA_PADRAO = exports.ARQUIVO_CONTAS = exports.CONTRATO_CONTAS = exports.ESTADOS_DE_PERFIL = exports.RUNTIMES_COM_PERFIL = exports.VARIAVEL_DO_PERFIL = exports.ARQUIVO_PERFIS = exports.CONTRATO_PERFIS = void 0;
|
|
36
|
+
exports.COLUNAS_DE_PERFIS = exports.POLITICA_PADRAO = exports.ARQUIVO_CONTAS = exports.CONTRATO_CONTAS = exports.ESTADOS_DE_PERFIL = exports.RUNTIMES_COM_INVENTARIO = exports.CAMPO_DO_PERFIL = exports.RUNTIMES_COM_PERFIL = exports.VARIAVEL_DO_PERFIL = exports.ARQUIVO_PERFIS = exports.CONTRATO_PERFIS = void 0;
|
|
37
37
|
exports.runtimeComPerfil = runtimeComPerfil;
|
|
38
38
|
exports.validarDiretorioDePerfil = validarDiretorioDePerfil;
|
|
39
39
|
exports.validarIdDePerfil = validarIdDePerfil;
|
|
@@ -81,7 +81,7 @@ exports.perfisComHorario = perfisComHorario;
|
|
|
81
81
|
* I-33 (D3): perfis de conta por runtime, contrato `ork.runtime-profiles/v1`.
|
|
82
82
|
*
|
|
83
83
|
* Um perfil aponta o DIRETORIO onde o proprio CLI do runtime guarda configuracao e login
|
|
84
|
-
* (`CLAUDE_CONFIG_DIR` no claude-bg, `CODEX_HOME` no codex). O `ork` nunca le, copia nem
|
|
84
|
+
* (`CLAUDE_CONFIG_DIR` no claude-bg, `CODEX_HOME` no codex, `GROK_HOME` no grok). O `ork` nunca le, copia nem
|
|
85
85
|
* migra o que o CLI grava la dentro: o login e feito pelo proprio CLI com o env do perfil, e
|
|
86
86
|
* o store guarda so identidade, diretorio e estado de uso. Nenhum segredo entra aqui.
|
|
87
87
|
*
|
|
@@ -101,8 +101,19 @@ const locale_1 = require("./locale");
|
|
|
101
101
|
exports.CONTRATO_PERFIS = 'ork.runtime-profiles/v1';
|
|
102
102
|
exports.ARQUIVO_PERFIS = 'runtime-profiles.json';
|
|
103
103
|
/** Runtimes homologados que aceitam perfil, e a variavel que cada um le. */
|
|
104
|
-
exports.VARIAVEL_DO_PERFIL = { 'claude-bg': 'CLAUDE_CONFIG_DIR', codex: 'CODEX_HOME' };
|
|
104
|
+
exports.VARIAVEL_DO_PERFIL = { 'claude-bg': 'CLAUDE_CONFIG_DIR', codex: 'CODEX_HOME', grok: 'GROK_HOME' };
|
|
105
105
|
exports.RUNTIMES_COM_PERFIL = Object.keys(exports.VARIAVEL_DO_PERFIL);
|
|
106
|
+
/** O campo do perfil que guarda o diretorio de cada runtime (o store e o despacho usam o mesmo nome). */
|
|
107
|
+
exports.CAMPO_DO_PERFIL = { 'claude-bg': 'configDir', codex: 'codexHome', grok: 'grokHome' };
|
|
108
|
+
const CAMPOS_DE_DIRETORIO = Object.values(exports.CAMPO_DO_PERFIL);
|
|
109
|
+
/** O diretorio padrao de cada CLI na HOME, quando o processo nao informa a variavel. */
|
|
110
|
+
const PASTA_PADRAO = { 'claude-bg': '.claude', codex: '.codex', grok: '.grok' };
|
|
111
|
+
/**
|
|
112
|
+
* RM-067 (F3, F4): runtimes de assinatura que o #Noctum mede e cuja conta do processo o inventario sempre consulta
|
|
113
|
+
* (`claude agents`, rollouts do codex). Desde a F4, o `ork sessions` e a carga do rodizio leem tambem o `grok`, pela
|
|
114
|
+
* pasta de sessoes que ele grava (`RUNTIMES_DAS_SESSOES` em `sessoes-contas.ts`); a medicao do #Noctum segue sem ele.
|
|
115
|
+
*/
|
|
116
|
+
exports.RUNTIMES_COM_INVENTARIO = ['claude-bg', 'codex'];
|
|
106
117
|
/**
|
|
107
118
|
* I-33 (D13): `provider-pago` e o perfil cujo proprio CLI diz que o login e por API key,
|
|
108
119
|
* `api_key_helper`, Console ou provider de nuvem, e nao pela assinatura. Nunca recebe despacho;
|
|
@@ -135,8 +146,11 @@ function validarIdDePerfil(id) {
|
|
|
135
146
|
}
|
|
136
147
|
/** Diretorio do perfil, pelo campo do seu runtime. */
|
|
137
148
|
function diretorioDoPerfil(p) {
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
return validarDiretorioDePerfil(p[exports.CAMPO_DO_PERFIL[p.runtime]]);
|
|
150
|
+
}
|
|
151
|
+
/** O perfil de despacho com o diretorio no campo do seu runtime. */
|
|
152
|
+
function comDiretorio(id, runtime, dir) {
|
|
153
|
+
return { id, runtime, [exports.CAMPO_DO_PERFIL[runtime]]: dir };
|
|
140
154
|
}
|
|
141
155
|
/** Valida um perfil de despacho vindo do ledger, do thread.json ou do pedido da fila. */
|
|
142
156
|
function validarPerfilDeDespacho(v) {
|
|
@@ -146,16 +160,13 @@ function validarPerfilDeDespacho(v) {
|
|
|
146
160
|
const runtime = o.runtime;
|
|
147
161
|
if (typeof runtime !== 'string' || !runtimeComPerfil(runtime))
|
|
148
162
|
throw new locale_1.ErroDoCatalogo((m) => m.accounts.runtimeDesconhecido);
|
|
149
|
-
const campo = runtime
|
|
150
|
-
|
|
151
|
-
if (o[outro] !== undefined || Object.keys(o).some(k => !['id', 'runtime', campo].includes(k)))
|
|
163
|
+
const campo = exports.CAMPO_DO_PERFIL[runtime];
|
|
164
|
+
if (Object.keys(o).some(k => !['id', 'runtime', campo].includes(k)))
|
|
152
165
|
throw new locale_1.ErroDoCatalogo((m) => m.accounts.despachoComCampo);
|
|
153
|
-
|
|
154
|
-
return runtime === 'claude-bg' ? { id, runtime, configDir: dir } : { id, runtime, codexHome: dir };
|
|
166
|
+
return comDiretorio(validarIdDePerfil(o.id), runtime, validarDiretorioDePerfil(o[campo]));
|
|
155
167
|
}
|
|
156
168
|
function perfilDeDespacho(p) {
|
|
157
|
-
return p.
|
|
158
|
-
: { id: p.id, runtime: p.runtime, codexHome: diretorioDoPerfil(p) };
|
|
169
|
+
return comDiretorio(p.id, p.runtime, diretorioDoPerfil(p));
|
|
159
170
|
}
|
|
160
171
|
/**
|
|
161
172
|
* Diretorio implicito de quem despacha sem perfil: o do ambiente informado, ou o padrao do
|
|
@@ -163,7 +174,7 @@ function perfilDeDespacho(p) {
|
|
|
163
174
|
*/
|
|
164
175
|
function diretorioImplicito(runtime, env = process.env) {
|
|
165
176
|
const valor = (env[exports.VARIAVEL_DO_PERFIL[runtime]] ?? '').trim();
|
|
166
|
-
return valor !== '' ? valor : path.join(os.homedir(), runtime
|
|
177
|
+
return valor !== '' ? valor : path.join(os.homedir(), PASTA_PADRAO[runtime]);
|
|
167
178
|
}
|
|
168
179
|
/** Diretorio efetivo: o do perfil registrado, ou o implicito quando a sessao nao tem perfil. */
|
|
169
180
|
function diretorioEfetivo(runtime, perfil, env = process.env) {
|
|
@@ -247,8 +258,8 @@ function validarPerfil(v) {
|
|
|
247
258
|
throw new locale_1.ErroDoCatalogo((m) => m.accounts.perfilInvalido);
|
|
248
259
|
const o = v;
|
|
249
260
|
const despacho = validarPerfilDeDespacho({ id: o.id, runtime: o.runtime,
|
|
250
|
-
...(
|
|
251
|
-
const permitidos = ['id', 'runtime',
|
|
261
|
+
...Object.fromEntries(CAMPOS_DE_DIRETORIO.filter(c => o[c] !== undefined).map(c => [c, o[c]])) });
|
|
262
|
+
const permitidos = ['id', 'runtime', ...CAMPOS_DE_DIRETORIO, 'estado', 'esgotadoAte', 'ultimaFalha', 'ultimoUso', 'criadoEm'];
|
|
252
263
|
if (Object.keys(o).some(k => !permitidos.includes(k)))
|
|
253
264
|
throw new locale_1.ErroDoCatalogo((m) => m.accounts.campoInesperado);
|
|
254
265
|
if (!exports.ESTADOS_DE_PERFIL.includes(o.estado))
|
|
@@ -539,8 +550,7 @@ function adicionarPerfil(raiz, novo, agoraIso = new Date().toISOString()) {
|
|
|
539
550
|
throw new locale_1.ErroDoCatalogo((m) => m.accounts.runtimeSemPerfil(novo.runtime));
|
|
540
551
|
const runtime = novo.runtime;
|
|
541
552
|
const dir = validarDiretorioDePerfil(novo.dir);
|
|
542
|
-
const perfil = {
|
|
543
|
-
...(runtime === 'claude-bg' ? { configDir: dir } : { codexHome: dir }),
|
|
553
|
+
const perfil = { ...comDiretorio(validarIdDePerfil(novo.id), runtime, dir),
|
|
544
554
|
estado: 'ativo', esgotadoAte: null, ultimaFalha: null, ultimoUso: null, criadoEm: agoraIso };
|
|
545
555
|
return atualizarPerfis(raiz, store => {
|
|
546
556
|
const existente = store.perfis.find(p => p.id === perfil.id);
|
package/dist/runtimes.js
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
* `claude agents --json` (homologado em 02/09/2026).
|
|
11
11
|
* codex o segundo runtime: `codex exec` headless desanexado, sessao verificada no
|
|
12
12
|
* rollout que o proprio Codex grava (homologado em 06/09/2026).
|
|
13
|
+
* grok RM-067 (F1 e F2): o Grok Build headless, `grok -p` com `streaming-json`, sessao
|
|
14
|
+
* verificada na pasta que o proprio runtime grava. Desde a F4, runtime de bloco e de
|
|
15
|
+
* fallback no `ork setup`, sempre com o modelo dado pelo dono; nunca o padrao do projeto
|
|
16
|
+
* (`runtime.adapter`), que segue com o claude-bg e o codex.
|
|
13
17
|
*
|
|
14
18
|
* Paridade sem downgrade: o contrato do claude-bg nao muda com a chegada do codex, e todo
|
|
15
19
|
* runtime novo entra por aqui com o MESMO contrato de despacho (dry-run, rate limit
|
|
@@ -49,11 +53,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
49
53
|
};
|
|
50
54
|
})();
|
|
51
55
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
-
exports.ORDEM_DOS_RUNTIMES = exports.RUNTIMES = exports.RUNTIME_PADRAO = void 0;
|
|
56
|
+
exports.RUNTIMES_SEM_COTA_TIPADA = exports.RUNTIMES_DE_BLOCO = exports.ORDEM_DOS_RUNTIMES = exports.RUNTIMES = exports.RUNTIME_PADRAO = void 0;
|
|
53
57
|
exports.runtimeConhecido = runtimeConhecido;
|
|
58
|
+
exports.runtimeDeBloco = runtimeDeBloco;
|
|
59
|
+
exports.runtimeDoManifesto = runtimeDoManifesto;
|
|
54
60
|
exports.resolverRuntime = resolverRuntime;
|
|
55
61
|
const claudeBg = __importStar(require("./adapters/claude-bg"));
|
|
56
62
|
const codex = __importStar(require("./adapters/codex"));
|
|
63
|
+
const grok = __importStar(require("./adapters/grok"));
|
|
57
64
|
const hitl_ingress_receipt_1 = require("./hitl-ingress-receipt");
|
|
58
65
|
const locale_1 = require("./locale");
|
|
59
66
|
exports.RUNTIME_PADRAO = 'claude-bg';
|
|
@@ -87,18 +94,48 @@ exports.RUNTIMES = {
|
|
|
87
94
|
montarComando: (p) => codex.montarComando(p),
|
|
88
95
|
despachar: (p) => comRecibosPublicos(p, codex.despachar),
|
|
89
96
|
},
|
|
97
|
+
grok: {
|
|
98
|
+
nome: grok.NOME_ADAPTER,
|
|
99
|
+
fonteVerificacao: grok.FONTE_VERIFICACAO,
|
|
100
|
+
disponivel: () => grok.disponivel(),
|
|
101
|
+
versao: grok.versao,
|
|
102
|
+
montarComando: (p) => grok.montarComando(p),
|
|
103
|
+
despachar: (p) => comRecibosPublicos(p, grok.despachar),
|
|
104
|
+
},
|
|
90
105
|
};
|
|
91
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Os runtimes que podem ser o padrao do projeto (`runtime.adapter` do manifesto), na ordem de maturidade (o padrao
|
|
108
|
+
* primeiro). RM-067 (F4): o grok fica fora, porque fazer dele o runtime padrao esta fora do escopo da RM-067 e ele nao tem
|
|
109
|
+
* modelo padrao.
|
|
110
|
+
*/
|
|
92
111
|
exports.ORDEM_DOS_RUNTIMES = ['claude-bg', 'codex'];
|
|
93
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Os runtimes que o setup aceita como runtime ou fallback de bloco. RM-067 (F4): os do padrao e o grok, este sempre com o
|
|
114
|
+
* modelo dado pelo dono (o setup exige `--model` ao trocar o runtime, e a entrada de fallback e `runtime:modelo[:esforco]`).
|
|
115
|
+
*/
|
|
116
|
+
exports.RUNTIMES_DE_BLOCO = [...exports.ORDEM_DOS_RUNTIMES, 'grok'];
|
|
117
|
+
/**
|
|
118
|
+
* RM-067 (F3): runtimes cuja cota esgotada ainda nao vem tipada do proprio runtime. A escada automatica nunca troca a conta
|
|
119
|
+
* deles: sem o sinal tipado, nada prova que o perfil esgotou. O grok sai daqui quando a F5 ler o formato estruturado.
|
|
120
|
+
*/
|
|
121
|
+
exports.RUNTIMES_SEM_COTA_TIPADA = ['grok'];
|
|
122
|
+
/** O nome e de um runtime homologado (resolve por nome no despacho)? */
|
|
94
123
|
function runtimeConhecido(nome) {
|
|
95
124
|
return Object.prototype.hasOwnProperty.call(exports.RUNTIMES, nome);
|
|
96
125
|
}
|
|
126
|
+
/** O runtime pode ser runtime de bloco ou fallback no setup? */
|
|
127
|
+
function runtimeDeBloco(nome) {
|
|
128
|
+
return exports.RUNTIMES_DE_BLOCO.includes(nome);
|
|
129
|
+
}
|
|
130
|
+
/** O runtime pode ser o `runtime.adapter` do manifesto? */
|
|
131
|
+
function runtimeDoManifesto(nome) {
|
|
132
|
+
return exports.ORDEM_DOS_RUNTIMES.includes(nome);
|
|
133
|
+
}
|
|
97
134
|
/** Resolve o adapter pelo nome, com erro tipado quando o runtime nao existe. */
|
|
98
135
|
function resolverRuntime(nome) {
|
|
99
|
-
const adapter = exports.RUNTIMES[nome];
|
|
136
|
+
const adapter = runtimeConhecido(nome) ? exports.RUNTIMES[nome] : undefined;
|
|
100
137
|
if (!adapter) {
|
|
101
|
-
throw new locale_1.ErroDoCatalogo((m) => m.phase.runtimeDesconhecido(nome, exports.
|
|
138
|
+
throw new locale_1.ErroDoCatalogo((m) => m.phase.runtimeDesconhecido(nome, exports.RUNTIMES_DE_BLOCO.join(', ')));
|
|
102
139
|
}
|
|
103
140
|
return adapter;
|
|
104
141
|
}
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.PRAZO_MINIMO_DO_CLASSIC_MS = exports.PRAZO_DO_BUILD_DA_IMAGEM_MS = exports.PRAZO_POR_REGRA_DO_SEMGREP_S = exports.SEMGREP_SEM_CACHE = void 0;
|
|
37
37
|
exports.especificacaoDoAgile = especificacaoDoAgile;
|
|
38
|
+
exports.prazoDoBuildDaImagem = prazoDoBuildDaImagem;
|
|
38
39
|
exports.estourouNoAgile = estourouNoAgile;
|
|
39
40
|
exports.motivoSemCredencial = motivoSemCredencial;
|
|
40
41
|
exports.resultadoDoTrabalhador = resultadoDoTrabalhador;
|
|
@@ -69,7 +70,6 @@ const tools_1 = require("./tools");
|
|
|
69
70
|
const TRABALHADOR = path.join(__dirname, 'trabalhador.js');
|
|
70
71
|
/** Sem prazo da rodada, o trabalhador ganha o maior prazo do catalogo para a HEAD e para a base, com folga. */
|
|
71
72
|
const FOLGA_MS = 60_000;
|
|
72
|
-
const aspas = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
73
73
|
/**
|
|
74
74
|
* O Semgrep baixa as regras do registro (`p/typescript`, ...) a cada rodada, e nao tem cache delas. Regra lida de arquivo
|
|
75
75
|
* local ganha outro `check_id` (o prefixo do caminho), o que muda a impressao digital de todo achado: o cache de regras
|
|
@@ -131,18 +131,24 @@ function eslintDoAgile(t, prazoMs, pecas) {
|
|
|
131
131
|
if (t.name !== 'eslint' || !t.install?.length)
|
|
132
132
|
return t;
|
|
133
133
|
// A4 do CHECK: o build roda antes dos trabalhadores; com teto curto, um link lento nao consome o prazo da varredura toda.
|
|
134
|
-
const imagem = (0, imagem_de_lint_1.garantirImagemDeLint)(t,
|
|
134
|
+
const imagem = (0, imagem_de_lint_1.garantirImagemDeLint)(t, prazoDoBuildDaImagem(prazoMs));
|
|
135
135
|
const comImagem = 'tag' in imagem ? (0, imagem_de_lint_1.eslintComImagem)(t, imagem.tag) : null;
|
|
136
136
|
if (comImagem) {
|
|
137
137
|
pecas.push({ peca: 'imagem-de-lint', estado: 'agile' });
|
|
138
138
|
return comImagem;
|
|
139
139
|
}
|
|
140
|
-
|
|
140
|
+
// RM-074 (F4): a ultima linha do `docker build` vem do registro do npm e pode trazer login na URL; vai ao ledger redigida.
|
|
141
|
+
pecas.push({ peca: 'imagem-de-lint', estado: 'fallback',
|
|
142
|
+
motivo: 'motivo' in imagem ? motivoSemCredencial(imagem.motivo, 200) : 'script do catalogo sem o npm install esperado',
|
|
141
143
|
fallback: 'eslint do catalogo, com npm install no container' });
|
|
142
144
|
return t;
|
|
143
145
|
}
|
|
144
146
|
/** O teto do build da imagem de lint (A4 do CHECK): estourou, o `eslint` do catalogo, com a peca em fallback. */
|
|
145
147
|
exports.PRAZO_DO_BUILD_DA_IMAGEM_MS = 180_000;
|
|
148
|
+
/** O prazo do build da imagem de lint: o que resta da ferramenta, nunca acima do teto (RM-074 F4: o caso do teto). */
|
|
149
|
+
function prazoDoBuildDaImagem(restanteMs) {
|
|
150
|
+
return Math.min(restanteMs, exports.PRAZO_DO_BUILD_DA_IMAGEM_MS);
|
|
151
|
+
}
|
|
146
152
|
/** O prazo minimo que sobra para a ferramenta que caiu no Agile rodar pelo caminho do Classic (A5 do CHECK). */
|
|
147
153
|
exports.PRAZO_MINIMO_DO_CLASSIC_MS = 30_000;
|
|
148
154
|
/** Os motivos tipados de estouro que o `scanTool` grava: o prazo da HEAD e o da base. */
|
|
@@ -228,8 +234,11 @@ function catalogoDoAgile(catalogo, agile, pecas) {
|
|
|
228
234
|
pecas.push({ peca: 'oxlint', estado: 'agile', motivo: 'primeiro passe antes do eslint, sem tirar regra dele (check.agile.oxlint)' });
|
|
229
235
|
return lista;
|
|
230
236
|
}
|
|
231
|
-
/**
|
|
232
|
-
|
|
237
|
+
/**
|
|
238
|
+
* A rodada do Agile: as mesmas regras do `runScan`, com as ferramentas em paralelo e os caches de banco. `rodar` e o
|
|
239
|
+
* grupo paralelo; os testes o trocam para ler o prazo e o argv de cada trabalhador (RM-074 F4).
|
|
240
|
+
*/
|
|
241
|
+
function runScanAgil(opts, rodar = check_paralelo_1.rodarEmParalelo) {
|
|
233
242
|
const start = path.resolve(opts.root);
|
|
234
243
|
const root = (0, run_1.git)(start, ['rev-parse', '--show-toplevel']) ?? start;
|
|
235
244
|
const generatedAt = (opts.now ?? (() => new Date()))().toISOString();
|
|
@@ -306,7 +315,9 @@ function runScanAgil(opts) {
|
|
|
306
315
|
ctx: { headTree, mainRoot, base, head, rangeCommits: count === null ? null : Number(count), deadline, ...(baseTree ? { baseTree } : {}) } };
|
|
307
316
|
const arquivo = path.join(dir, `${i}.json`);
|
|
308
317
|
fs.writeFileSync(arquivo, JSON.stringify(trabalho), { mode: 0o600 });
|
|
309
|
-
|
|
318
|
+
// RM-074 (F4): o trabalhador roda pelo argv, sem string de shell; o `comando` so identifica o item.
|
|
319
|
+
const argv = [process.execPath, TRABALHADOR, arquivo];
|
|
320
|
+
return { nome: t.name, comando: argv.join(' '), argv, cwd: root };
|
|
310
321
|
});
|
|
311
322
|
// S-f do CHECK 2: o teto dos trabalhadores e contado depois de todos montados, com o build da imagem de lint ja feito.
|
|
312
323
|
const prazo = deadline === null ? Math.max(...tools.map(t => t.timeoutMs)) * 2 + FOLGA_MS : Math.max(1000, deadline - Date.now() + FOLGA_MS);
|
|
@@ -316,7 +327,7 @@ function runScanAgil(opts) {
|
|
|
316
327
|
const maxParalelo = Number.isInteger(teto) && teto > 0 ? teto : undefined;
|
|
317
328
|
if (maxParalelo)
|
|
318
329
|
pecas[0] = { ...pecas[0], motivo: `ate ${maxParalelo} ferramenta(s) ao mesmo tempo, ao lado das lanes do verify` };
|
|
319
|
-
const processos = (
|
|
330
|
+
const processos = rodar(trabalhos, process.env, maxParalelo ? { maxParalelo } : {});
|
|
320
331
|
const excluded = new Set();
|
|
321
332
|
tools.forEach((t, i) => {
|
|
322
333
|
const trabalhador = resultadoDoTrabalhador(t, processos[i], trabalhos[i].prazoMs);
|
|
@@ -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
|
}
|
|
@@ -38,6 +38,7 @@ exports.defaultProbe = defaultProbe;
|
|
|
38
38
|
exports.chooseExecutor = chooseExecutor;
|
|
39
39
|
exports.nativeVersionOf = nativeVersionOf;
|
|
40
40
|
exports.defaultsDir = defaultsDir;
|
|
41
|
+
exports.argumentosDeCpuDoDocker = argumentosDeCpuDoDocker;
|
|
41
42
|
exports.expand = expand;
|
|
42
43
|
exports.ensureImage = ensureImage;
|
|
43
44
|
exports.runDocker = runDocker;
|
|
@@ -52,6 +53,7 @@ const crypto = __importStar(require("node:crypto"));
|
|
|
52
53
|
const fs = __importStar(require("node:fs"));
|
|
53
54
|
const path = __importStar(require("node:path"));
|
|
54
55
|
const guard_1 = require("./guard");
|
|
56
|
+
const agendador_cpu_1 = require("../agendador-cpu");
|
|
55
57
|
const PROBE_TIMEOUT_MS = 20000;
|
|
56
58
|
/** The probe of this machine, through the PATH. Each answer is computed once per probe. */
|
|
57
59
|
function defaultProbe() {
|
|
@@ -107,6 +109,11 @@ function defaultsDir() {
|
|
|
107
109
|
exports.CONFIG_FILES = { gitleaks: 'gitleaks.toml', eslint: 'eslint.config.mjs', ruff: 'ruff.toml', 'golangci-lint': '.golangci.yml' };
|
|
108
110
|
const CONTAINER = { src: '/src', out: '/out', config: '/config' };
|
|
109
111
|
const MAX_BUFFER = 512 * 1024 * 1024;
|
|
112
|
+
/** A cota so existe no grupo Agile; sem a variavel, o Classic continua com o argv de sempre. */
|
|
113
|
+
function argumentosDeCpuDoDocker(ambiente = process.env) {
|
|
114
|
+
const limite = Number(ambiente[agendador_cpu_1.ENV_CPUS_DOCKER]);
|
|
115
|
+
return Number.isFinite(limite) && limite > 0 ? ['--cpus', String(limite)] : [];
|
|
116
|
+
}
|
|
110
117
|
function expand(arg, values) {
|
|
111
118
|
return arg.replace(/\{(src|out|base|config|install|stackDir)\}/g, (_, k) => values[k]);
|
|
112
119
|
}
|
|
@@ -141,6 +148,7 @@ function runDocker(inv) {
|
|
|
141
148
|
fs.chmodSync(inv.outHost, 0o777);
|
|
142
149
|
const values = { src: CONTAINER.src, out: CONTAINER.out, base: inv.base, config: configCtr, install: (tool.install ?? []).join(' '), stackDir: stackDirArg(inv.stackDir) };
|
|
143
150
|
const args = ['run', '--rm', '--name', name, '--pull', 'never', '--user', containerUser(),
|
|
151
|
+
...argumentosDeCpuDoDocker(),
|
|
144
152
|
'--cap-drop', 'ALL', '--security-opt', 'no-new-privileges',
|
|
145
153
|
...(tool.network === 'none' ? ['--network', 'none'] : []),
|
|
146
154
|
'--tmpfs', '/tmp:exec,mode=1777',
|