@orkastery/cli 0.5.0 → 0.5.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 +11 -2
- package/adapters/claude-code/agents/ork-master.md +2 -0
- package/adapters/claude-code/commands/master.md +8 -0
- package/adapters/claude-code/commands/onboarding.md +3 -2
- package/adapters/claude-code/commands/ork.md +9 -0
- package/adapters/codex/skills/ork/SKILL.md +18 -3
- package/adapters/hermes/README.md +1 -0
- package/adapters/hermes/bin/ork-network-status.sh +10 -0
- package/adapters/hermes/hermes.plugin.json +1 -0
- package/adapters/hermes/hitl-ingress/__init__.py +2 -2
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +6 -5
- package/adapters/openclaw/README.md +35 -4
- package/adapters/openclaw/dist/hitl-ingress.js +2 -2
- package/adapters/openclaw/dist/index.js +47 -12
- package/adapters/openclaw/openclaw.plugin.json +5 -1
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +2 -2
- package/adapters/openclaw/src/index.ts +50 -12
- package/assets/orkmind_bridge.py +117 -9
- package/dist/adapters/claude-bg.js +59 -11
- package/dist/adapters/codex.js +4 -3
- package/dist/agents-md.js +1 -0
- package/dist/auditrun.js +6 -2
- package/dist/board.js +16 -14
- package/dist/branch-de-estado.js +66 -10
- package/dist/busca-semantica.js +52 -12
- package/dist/canarios-rm057.js +149 -0
- package/dist/canarios.js +2 -0
- package/dist/ci.js +8 -1
- package/dist/claim-lint.js +3 -1
- package/dist/claims.js +39 -1
- package/dist/company-brain-context.js +158 -22
- package/dist/docs.js +110 -3
- package/dist/doctor-pulse-cron.js +194 -0
- package/dist/doctor-rede.js +149 -0
- package/dist/doctor.js +294 -37
- package/dist/entrega-pr.js +27 -8
- package/dist/esgotamentos.js +181 -0
- package/dist/experiencia.js +12 -2
- package/dist/fabrica-estado.js +35 -9
- package/dist/fabrica-publicar.js +6 -0
- package/dist/fechamento.js +20 -66
- package/dist/fix.js +3 -3
- package/dist/forja.js +31 -7
- package/dist/gates.js +5 -1
- package/dist/hitl-contract.js +59 -4
- package/dist/hitl-curto.js +11 -6
- package/dist/hitl-gates.js +5 -0
- package/dist/hitl-lote.js +5 -2
- package/dist/hitl-resumo.js +33 -1
- package/dist/hitl-tempo-parado.js +201 -0
- package/dist/hitl-texto-livre.js +5 -5
- package/dist/horario.js +27 -0
- package/dist/hosts.js +59 -13
- package/dist/impedimento.js +205 -0
- package/dist/index.js +433 -88
- package/dist/indice-vetorial.js +87 -10
- package/dist/indice.js +3 -1
- package/dist/init.js +28 -5
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +267 -30
- package/dist/intelligence-graph-contexto.js +215 -0
- package/dist/intelligence-graph-contract.js +71 -12
- package/dist/intelligence-graph-extract-md.js +41 -23
- package/dist/intelligence-graph-extract-ts.js +181 -11
- package/dist/intelligence-graph-extract.js +186 -9
- package/dist/intelligence-graph-index.js +205 -24
- package/dist/intelligence-graph-parsers.js +6 -4
- package/dist/intelligence-graph-repo.js +10 -0
- package/dist/leases.js +680 -87
- package/dist/ledger-stats.js +15 -1
- package/dist/ledger.js +12 -0
- package/dist/licoes.js +6 -4
- package/dist/liveness.js +2 -1
- package/dist/maestro-runtime.js +7 -1
- package/dist/manifest.js +44 -1
- package/dist/master-nota.js +14 -5
- package/dist/master.js +129 -12
- package/dist/mcp-artifacts.js +36 -3
- package/dist/mcp-git.js +80 -15
- package/dist/mcp-grafo-worker.js +93 -0
- package/dist/mcp-grafo.js +279 -0
- package/dist/mcp-install.js +2 -1
- package/dist/mcp-server.js +23 -1
- package/dist/mcp-ship.js +2 -0
- package/dist/mcp-verify.js +3 -1
- package/dist/memoria.js +48 -6
- package/dist/network-roadmap.js +195 -20
- package/dist/ocupacao.js +17 -5
- package/dist/onboarding.js +9 -4
- package/dist/orkmind.js +90 -5
- package/dist/orquestracao.js +14 -11
- package/dist/parado-no-condutor.js +1089 -0
- package/dist/phase.js +68 -15
- package/dist/policies.js +79 -3
- package/dist/portfolio.js +4 -1
- package/dist/projeto-alvo.js +5 -1
- package/dist/prompts.js +36 -1
- package/dist/prova-ativacao.js +414 -0
- package/dist/pulse-delivery.js +60 -7
- package/dist/pulse.js +99 -3
- package/dist/ratelimit.js +20 -4
- package/dist/recall.js +3 -1
- package/dist/rede-adesao.js +399 -0
- package/dist/rede-forja.js +289 -0
- package/dist/rede-projetos.js +239 -0
- package/dist/rede-status.js +336 -0
- package/dist/rede.js +980 -0
- package/dist/retry.js +69 -2
- package/dist/roadmap-status.js +162 -7
- package/dist/runtime-context.js +5 -1
- package/dist/runtime-profiles.js +22 -1
- package/dist/saida-segura.js +58 -0
- package/dist/session-watcher-claude.js +113 -23
- package/dist/sessoes-contas.js +187 -0
- package/dist/sessoes-inventario.js +6 -12
- package/dist/sessoes.js +87 -3
- package/dist/ship.js +110 -20
- package/dist/thread.js +212 -14
- package/dist/util.js +71 -4
- package/dist/verify.js +2 -2
- package/dist/worktree.js +34 -8
- package/eval/casos/onboarding.json +1 -1
- package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
- package/package.json +7 -3
- package/references/definition-of-done.md +1 -1
- package/skills/README.md +1 -1
- package/skills/core/onboarding/SKILL.md +3 -2
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/master-metrics/SKILL.md +8 -3
- package/skills/phases/ship-release/SKILL.md +6 -3
package/dist/hosts.js
CHANGED
|
@@ -57,6 +57,7 @@ exports.ORDEM_DOS_HOSTS = exports.HOSTS = exports.MAESTRO_HOST_SURFACES = export
|
|
|
57
57
|
exports.parseHost = parseHost;
|
|
58
58
|
exports.lerRecibo = lerRecibo;
|
|
59
59
|
exports.classificarDivergencia = classificarDivergencia;
|
|
60
|
+
exports.avisoDoOrkNoPath = avisoDoOrkNoPath;
|
|
60
61
|
exports.renderizarArquivo = renderizarArquivo;
|
|
61
62
|
exports.instalarAdaptador = instalarAdaptador;
|
|
62
63
|
exports.desinstalarExperiencia = desinstalarExperiencia;
|
|
@@ -64,6 +65,7 @@ exports.tabelaDeHosts = tabelaDeHosts;
|
|
|
64
65
|
exports.textoDosPitfalls = textoDosPitfalls;
|
|
65
66
|
exports.textoDaInstalacao = textoDaInstalacao;
|
|
66
67
|
const node_crypto_1 = require("node:crypto");
|
|
68
|
+
const node_child_process_1 = require("node:child_process");
|
|
67
69
|
const fs = __importStar(require("node:fs"));
|
|
68
70
|
exports.BRAIN_HOST_SURFACES = {
|
|
69
71
|
hermes: 'cli', openclaw: 'cli', 'claude-code': 'mcp', codex: 'mcp',
|
|
@@ -92,8 +94,8 @@ exports.HOSTS = {
|
|
|
92
94
|
pitfalls: [
|
|
93
95
|
{
|
|
94
96
|
titulo: 'manifesto sem os caminhos das skills instala limpo e nao expoe nada',
|
|
95
|
-
detalhe: 'o plugin auto-descobre skills/<nome>/SKILL.md e para ai: ele nao desce nos buckets (core/, phases/, reviewers/, ...) que este catalogo usa, entao o plugin.json declara
|
|
96
|
-
prova: 'claude plugin details orkastery #
|
|
97
|
+
detalhe: 'o plugin auto-descobre skills/<nome>/SKILL.md e para ai: ele nao desce nos buckets (core/, phases/, reviewers/, ...) que este catalogo usa, entao o plugin.json declara cada caminho de skill, um a um',
|
|
98
|
+
prova: 'claude plugin details orkastery # Skills (N) soma as skills do plugin.json e os comandos de commands/',
|
|
97
99
|
},
|
|
98
100
|
{
|
|
99
101
|
titulo: 'duas copias do catalogo divergem',
|
|
@@ -246,6 +248,31 @@ function listarArquivos(dir, prefixo = '') {
|
|
|
246
248
|
}
|
|
247
249
|
return achados;
|
|
248
250
|
}
|
|
251
|
+
function mesmoArquivo(a, b) {
|
|
252
|
+
try {
|
|
253
|
+
return fs.realpathSync(a) === fs.realpathSync(b);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return path.resolve(a) === path.resolve(b);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Ensaio de 03/10: com outro `ork` primeiro no PATH, a extensão segue apontando para o binário que roda o
|
|
261
|
+
* install, e o aviso diz as duas versões para ninguém descobrir a diferença pela extensão chamando o velho.
|
|
262
|
+
*/
|
|
263
|
+
function avisoDoOrkNoPath(emExecucao, versao, env = process.env) {
|
|
264
|
+
const doPath = (0, util_1.noPath)('ork', env);
|
|
265
|
+
if (!doPath || mesmoArquivo(doPath, emExecucao))
|
|
266
|
+
return undefined;
|
|
267
|
+
let outra = 'versão desconhecida';
|
|
268
|
+
try {
|
|
269
|
+
const saida = (0, node_child_process_1.execFileSync)(doPath, ['--version'], { encoding: 'utf8', timeout: 5000, stdio: ['ignore', 'pipe', 'ignore'], env });
|
|
270
|
+
outra = saida.trim().split('\n')[0]?.trim() || outra;
|
|
271
|
+
}
|
|
272
|
+
catch { /* o aviso sai mesmo sem a versão */ }
|
|
273
|
+
return `o ork do PATH (${doPath}, ${outra}) não é o que roda este install (${emExecucao}, ${versao}). ` +
|
|
274
|
+
`A extensão chama ${emExecucao}; para outro binário, passe --ork <caminho>.`;
|
|
275
|
+
}
|
|
249
276
|
/** Substitui os tres placeholders. Nao ha template engine aqui de proposito. */
|
|
250
277
|
function renderizarArquivo(conteudo, valores) {
|
|
251
278
|
return conteudo
|
|
@@ -267,8 +294,10 @@ function instalarAdaptador(host, opcoes = {}) {
|
|
|
267
294
|
? path.resolve(projeto, opcoes.dir)
|
|
268
295
|
: path.join(projeto, def.destinoPadrao);
|
|
269
296
|
const destino = def.subdir ? path.join(base, def.subdir) : base;
|
|
270
|
-
const orkBin = opcoes.orkBin ?? (0, util_1.noPath)('ork') ?? (0, catalogo_1.cliDoCatalogo)(catalogo);
|
|
297
|
+
const orkBin = opcoes.orkBin ?? opcoes.orkEmExecucao ?? (0, util_1.noPath)('ork') ?? (0, catalogo_1.cliDoCatalogo)(catalogo);
|
|
271
298
|
const versao = opcoes.versao ?? versao_1.VERSAO_DO_ORK;
|
|
299
|
+
const avisoOrk = opcoes.orkBin === undefined && opcoes.orkEmExecucao
|
|
300
|
+
? avisoDoOrkNoPath(opcoes.orkEmExecucao, versao) : undefined;
|
|
272
301
|
const dirDoHost = path.join(catalogo, 'adapters', host);
|
|
273
302
|
if (!fs.existsSync(dirDoHost)) {
|
|
274
303
|
throw new Error(`adaptador do host ${host} nao existe em ${dirDoHost}`);
|
|
@@ -424,6 +453,7 @@ function instalarAdaptador(host, opcoes = {}) {
|
|
|
424
453
|
...(reciboVizinho ? { reciboVizinho } : {}),
|
|
425
454
|
ok: !barrado,
|
|
426
455
|
orkBin,
|
|
456
|
+
...(avisoOrk ? { avisoOrk } : {}),
|
|
427
457
|
pitfalls: def.pitfalls,
|
|
428
458
|
...(preferencias || avisoExperiencia ? { experiencia: { ativa: host !== 'openclaw' && !!preferencias?.experience && !avisoExperiencia,
|
|
429
459
|
arquivos: planoExperiencia?.mudancas.map(m => path.relative(planoExperiencia.projeto, m.arquivo)) ?? [], skill: preferencias?.skill ?? '',
|
|
@@ -510,8 +540,12 @@ function textoDosPitfalls(host) {
|
|
|
510
540
|
/** Texto de `ork adapter install`. */
|
|
511
541
|
function textoDaInstalacao(r) {
|
|
512
542
|
const linhas = [];
|
|
543
|
+
// Ensaio da 0.5.0: com o pacote ativo e pulado por aviso (catalogo fora do projeto), a linha dizia
|
|
544
|
+
// "desativada"; o aviso logo abaixo diz o motivo.
|
|
513
545
|
if (r.experiencia)
|
|
514
|
-
linhas.push(`Experiência: ${r.experiencia.ativa ? 'ativação preparada'
|
|
546
|
+
linhas.push(`Experiência: ${r.experiencia.ativa ? 'ativação preparada'
|
|
547
|
+
: r.experiencia.aviso ? 'pacote pulado nesta instalação, veja o aviso abaixo' : 'desativada ou sem integração de skills'}` +
|
|
548
|
+
`${r.experiencia.skill ? ` (${r.experiencia.skill})` : ''}.`);
|
|
515
549
|
if (r.experiencia?.aviso)
|
|
516
550
|
linhas.push(`Aviso: ${r.experiencia.aviso}`);
|
|
517
551
|
linhas.push(r.dryRun
|
|
@@ -519,28 +553,35 @@ function textoDaInstalacao(r) {
|
|
|
519
553
|
: r.ok
|
|
520
554
|
? `Arquivos do adaptador ${r.host} preparados.`
|
|
521
555
|
: `Instalacao do adaptador ${r.host} BARRADA: ha arquivo diferente no destino.`);
|
|
556
|
+
// Ensaio de 03/10 (R6): a ativacao sai no comeco e de novo no fim, depois da lista de arquivos e dos
|
|
557
|
+
// pitfalls, para que o fim da saida diga o proximo passo.
|
|
558
|
+
const ativacao = [];
|
|
522
559
|
if (r.ok && !r.dryRun && r.host === 'claude-code') {
|
|
523
560
|
const destino = "'" + r.destino.replace(/'/g, "'\"'\"'") + "'";
|
|
524
561
|
linhas.push('Uso no Claude Code ainda nao verificado por esta copia.');
|
|
525
562
|
linhas.push('No diretorio deste projeto, valide e ative o plugin:');
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
563
|
+
ativacao.push(` claude plugin validate ${destino}`);
|
|
564
|
+
ativacao.push(` claude plugin marketplace add ${destino} --scope project`);
|
|
565
|
+
ativacao.push(' claude plugin install orkastery@orkastery --scope project');
|
|
566
|
+
ativacao.push(' claude plugin list --json');
|
|
567
|
+
ativacao.push('Depois, na sessao deste projeto: /orkastery:ork');
|
|
531
568
|
}
|
|
532
569
|
else if (r.ok && !r.dryRun && r.host === 'codex') {
|
|
533
|
-
|
|
534
|
-
|
|
570
|
+
ativacao.push('Abra o Codex neste projeto e use $ork.');
|
|
571
|
+
ativacao.push('Descoberta e uso nativo ainda nao verificados por esta copia.');
|
|
535
572
|
}
|
|
536
573
|
if (r.ok && !r.dryRun && (r.host === 'codex' || r.host === 'claude-code')) {
|
|
537
574
|
const projeto = "'" + r.projeto.replace(/'/g, "'\"'\"'") + "'";
|
|
538
|
-
|
|
539
|
-
linhas.push('A configuracao MCP exige descoberta e consentimento no cliente; a copia nao concede aprovacoes.');
|
|
575
|
+
ativacao.push(`Prepare tambem as ferramentas do projeto: ork mcp install --project ${projeto} --host ${r.host}`);
|
|
540
576
|
}
|
|
577
|
+
linhas.push(...ativacao);
|
|
578
|
+
if (ativacao.length)
|
|
579
|
+
linhas.push('A configuracao MCP exige descoberta e consentimento no cliente; a copia nao concede aprovacoes.');
|
|
541
580
|
linhas.push(` catalogo: ${r.catalogo}`);
|
|
542
581
|
linhas.push(` destino: ${r.destino}`);
|
|
543
582
|
linhas.push(` ork: ${r.orkBin}`);
|
|
583
|
+
if (r.avisoOrk)
|
|
584
|
+
linhas.push(` Aviso: ${r.avisoOrk}`);
|
|
544
585
|
linhas.push('');
|
|
545
586
|
const novos = r.arquivos.filter((a) => a.estado === 'novo').length;
|
|
546
587
|
const iguais = r.arquivos.filter((a) => a.estado === 'igual').length;
|
|
@@ -588,5 +629,10 @@ function textoDaInstalacao(r) {
|
|
|
588
629
|
}
|
|
589
630
|
linhas.push('');
|
|
590
631
|
linhas.push(textoDosPitfalls(r.host));
|
|
632
|
+
if (ativacao.length) {
|
|
633
|
+
linhas.push('');
|
|
634
|
+
linhas.push(r.host === 'claude-code' ? 'Proximo passo, no diretorio deste projeto (o mesmo do comeco):' : 'Proximo passo (o mesmo do comeco):');
|
|
635
|
+
linhas.push(...ativacao);
|
|
636
|
+
}
|
|
591
637
|
return linhas.join('\n');
|
|
592
638
|
}
|
|
@@ -0,0 +1,205 @@
|
|
|
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.MOTIVOS_DE_IMPEDIMENTO_DO_DONO = void 0;
|
|
37
|
+
exports.ehImpedimentoDoDono = ehImpedimentoDoDono;
|
|
38
|
+
exports.ehEsperaDoDono = ehEsperaDoDono;
|
|
39
|
+
exports.classificarImpedimento = classificarImpedimento;
|
|
40
|
+
exports.impedimentoResolvido = impedimentoResolvido;
|
|
41
|
+
exports.correcaoDoImpedimento = correcaoDoImpedimento;
|
|
42
|
+
exports.registrarImpedimentoDoDono = registrarImpedimentoDoDono;
|
|
43
|
+
exports.impedimentoDoEvento = impedimentoDoEvento;
|
|
44
|
+
exports.pedidoCurtoDoImpedimento = pedidoCurtoDoImpedimento;
|
|
45
|
+
/**
|
|
46
|
+
* RM-055: impedimento que so o dono resolve vira HITL.
|
|
47
|
+
*
|
|
48
|
+
* Em 29/09/2026 tres despachos `claude --bg` morreram com "Workspace not trusted. Run `claude` in
|
|
49
|
+
* <worktree> once and accept the trust prompt". O ledger guardou so `phase_dispatch_failed`, as threads
|
|
50
|
+
* ficaram `aberta` e o board, a fabrica e o pulse disseram "espera voce: -". O dono descobriu horas
|
|
51
|
+
* depois, perguntando.
|
|
52
|
+
*
|
|
53
|
+
* Aqui a saida do runtime vira motivo tipado. O motivo que so o dono resolve (aceitar a confianca do
|
|
54
|
+
* diretorio, aceitar termos novos do CLI) abre a pausa do dono com o que trava, o comando exato que ele
|
|
55
|
+
* roda e o que o `ork` faz depois: `ork retry run <thread>` re-despacha a MESMA fase com o MESMO prompt
|
|
56
|
+
* gravado, sem o dono reescrever o pedido. Login ausente e cota esgotada continuam na rotacao de conta
|
|
57
|
+
* (I-33): la quem resolve primeiro e o orquestrador, trocando de perfil. Motivo desconhecido continua
|
|
58
|
+
* generico (`runtime.unavailable`).
|
|
59
|
+
*/
|
|
60
|
+
const fs = __importStar(require("node:fs"));
|
|
61
|
+
const os = __importStar(require("node:os"));
|
|
62
|
+
const path = __importStar(require("node:path"));
|
|
63
|
+
const gates_1 = require("./gates");
|
|
64
|
+
const hitl_curto_1 = require("./hitl-curto");
|
|
65
|
+
exports.MOTIVOS_DE_IMPEDIMENTO_DO_DONO = Object.freeze([
|
|
66
|
+
'runtime.workspace-untrusted', 'runtime.consent-pending',
|
|
67
|
+
]);
|
|
68
|
+
function ehImpedimentoDoDono(motivo) {
|
|
69
|
+
return typeof motivo === 'string' && exports.MOTIVOS_DE_IMPEDIMENTO_DO_DONO.includes(motivo);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Um evento do ledger que espera o dono: a escalada `human.pending` ou o impedimento tipado do despacho.
|
|
73
|
+
* E a mesma regra para o monitor, a ocupacao de vaga, a fabrica e o pulse.
|
|
74
|
+
*/
|
|
75
|
+
function ehEsperaDoDono(e, tipoGateBloqueado = 'gate_blocked') {
|
|
76
|
+
return e.tipo === tipoGateBloqueado && (e.motivo === 'human.pending' || ehImpedimentoDoDono(e.motivo));
|
|
77
|
+
}
|
|
78
|
+
/** Aspas de shell so quando o caminho precisa. */
|
|
79
|
+
function citar(caminho) {
|
|
80
|
+
return /^[A-Za-z0-9_./:@+-]+$/.test(caminho) ? caminho : `'${caminho.replace(/'/g, `'\\''`)}'`;
|
|
81
|
+
}
|
|
82
|
+
const FRASES_DE_CONFIANCA = [
|
|
83
|
+
/workspace not trusted/i,
|
|
84
|
+
/accept the trust (?:prompt|dialog)/i,
|
|
85
|
+
/not inside a trusted directory/i,
|
|
86
|
+
/(?:folder|directory|workspace) (?:is )?not trusted/i,
|
|
87
|
+
];
|
|
88
|
+
const FRASES_DE_CONSENTIMENTO = [
|
|
89
|
+
/accept (?:the )?(?:updated |new )?(?:terms|consumer terms|privacy policy|usage policy)/i,
|
|
90
|
+
/(?:terms|policy) (?:have|has) (?:been )?updated[^\n]*accept/i,
|
|
91
|
+
/consent (?:is )?required/i,
|
|
92
|
+
];
|
|
93
|
+
function trechoDa(texto, regra) {
|
|
94
|
+
const linha = texto.split(/\r?\n/).find(l => regra.test(l)) ?? texto;
|
|
95
|
+
return linha.replace(/\s+/g, ' ').trim().slice(0, 240);
|
|
96
|
+
}
|
|
97
|
+
function binarioDo(runtime) {
|
|
98
|
+
return runtime === 'codex' ? 'codex' : 'claude';
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Le a saida do runtime (stderr e o erro do adapter) e devolve o impedimento do dono, ou null.
|
|
102
|
+
* Null quer dizer "nao e do dono": o despacho segue no caminho de antes.
|
|
103
|
+
*/
|
|
104
|
+
function classificarImpedimento(saida, ctx) {
|
|
105
|
+
const texto = saida ?? '';
|
|
106
|
+
const bin = binarioDo(ctx.runtime);
|
|
107
|
+
const depois = `depois, \`ork retry run ${ctx.thread}\` re-despacha ${ctx.fase} com o mesmo prompt gravado`;
|
|
108
|
+
const confianca = FRASES_DE_CONFIANCA.find(r => r.test(texto));
|
|
109
|
+
if (confianca) {
|
|
110
|
+
return {
|
|
111
|
+
motivo: 'runtime.workspace-untrusted',
|
|
112
|
+
trava: `o ${bin} não confia no diretório da worktree e recusou o despacho de ${ctx.fase}`,
|
|
113
|
+
comando: `cd ${citar(ctx.cwd)} && ${bin}`,
|
|
114
|
+
depois: `aceite a confiança no diretório e saia; ${depois}`,
|
|
115
|
+
trecho: trechoDa(texto, confianca),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const consentimento = FRASES_DE_CONSENTIMENTO.find(r => r.test(texto));
|
|
119
|
+
if (consentimento) {
|
|
120
|
+
return {
|
|
121
|
+
motivo: 'runtime.consent-pending',
|
|
122
|
+
trava: `o ${bin} espera você aceitar termos novos e recusou o despacho de ${ctx.fase}`,
|
|
123
|
+
comando: bin,
|
|
124
|
+
depois: `aceite os termos e saia; ${depois}`,
|
|
125
|
+
trecho: trechoDa(texto, consentimento),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* O impedimento ja foi resolvido? So o de confianca do diretorio tem prova local: o `claude` grava
|
|
132
|
+
* `hasTrustDialogAccepted` por projeto no `.claude.json` da conta (o do perfil, com `CLAUDE_CONFIG_DIR`),
|
|
133
|
+
* e a confianca de um diretorio vale para os de baixo. `null` e "nao sei": o retry despacha e o runtime
|
|
134
|
+
* decide; se recusar de novo, a mesma pausa volta.
|
|
135
|
+
*/
|
|
136
|
+
function impedimentoResolvido(motivo, ctx) {
|
|
137
|
+
if (motivo !== 'runtime.workspace-untrusted' || ctx.runtime !== 'claude-bg')
|
|
138
|
+
return null;
|
|
139
|
+
// A conta do processo segue o `CLAUDE_CONFIG_DIR` do ambiente, como o proprio `claude`.
|
|
140
|
+
const configDir = ctx.configDir ?? (ctx.home ? null : process.env.CLAUDE_CONFIG_DIR) ?? null;
|
|
141
|
+
const arquivo = configDir ? path.join(configDir, '.claude.json') : path.join(ctx.home ?? os.homedir(), '.claude.json');
|
|
142
|
+
let projetos;
|
|
143
|
+
try {
|
|
144
|
+
const dados = JSON.parse(fs.readFileSync(arquivo, 'utf8'));
|
|
145
|
+
if (!dados || typeof dados.projects !== 'object' || dados.projects === null)
|
|
146
|
+
return null;
|
|
147
|
+
projetos = dados.projects;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
for (let dir = path.resolve(ctx.cwd);; dir = path.dirname(dir)) {
|
|
153
|
+
if (projetos[dir]?.hasTrustDialogAccepted === true)
|
|
154
|
+
return true;
|
|
155
|
+
if (path.dirname(dir) === dir)
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** A frase de correcao que vai ao gate e ao monitor: o comando e o que vem depois. */
|
|
160
|
+
function correcaoDoImpedimento(i) {
|
|
161
|
+
return `rode \`${i.comando}\`; ${i.depois}`;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* RM-055: classifica a saida de um despacho recusado e, quando so o dono resolve, grava o `gate_blocked`
|
|
165
|
+
* tipado que o monitor, a fabrica, o board e o pulse leem como espera do dono. Devolve null quando o
|
|
166
|
+
* motivo nao e do dono (o chamador segue no caminho de antes). Tambem usado pelo redespacho do retry.
|
|
167
|
+
*/
|
|
168
|
+
function registrarImpedimentoDoDono(dir, thread, d) {
|
|
169
|
+
const impedimento = classificarImpedimento(d.saida, { thread: thread.id, fase: d.fase, runtime: d.runtime, cwd: d.cwd });
|
|
170
|
+
if (!impedimento)
|
|
171
|
+
return null;
|
|
172
|
+
(0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: impedimento.motivo, modo: thread.modo,
|
|
173
|
+
detalhe: impedimento.trava, correcao: correcaoDoImpedimento(impedimento), fase: d.fase, slug: d.slug,
|
|
174
|
+
runtime: d.runtime, cwd: d.cwd, origem: d.origem, promptPath: d.promptPath, promptSha256: d.promptSha256,
|
|
175
|
+
impedimento: { motivo: impedimento.motivo, comando: impedimento.comando, depois: impedimento.depois, trecho: impedimento.trecho },
|
|
176
|
+
...(d.perfil ? { perfil: d.perfil } : {}), pausaQualquerModo: true,
|
|
177
|
+
evidencia: 'stderr real do runtime adapter no despacho, nao relato do agente' });
|
|
178
|
+
return impedimento;
|
|
179
|
+
}
|
|
180
|
+
/** O impedimento gravado no `gate_blocked`, lido de volta com tipos; null quando o evento nao o traz. */
|
|
181
|
+
function impedimentoDoEvento(e) {
|
|
182
|
+
const i = e.impedimento;
|
|
183
|
+
if (!i || typeof i.comando !== 'string' || typeof i.depois !== 'string')
|
|
184
|
+
return null;
|
|
185
|
+
return { comando: i.comando, depois: i.depois, trecho: typeof i.trecho === 'string' ? i.trecho : '' };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* RM-055 (b): o pedido do impedimento no contrato curto da RM-048 (`ork.hitl-curto/v1`): o que trava,
|
|
189
|
+
* desde quando, o comando exato que o dono roda e o que o ork faz depois. A recomendada e o re-despacho
|
|
190
|
+
* do mesmo prompt; as outras dizem o custo de nao fazer nada e de trocar o runtime do bloco.
|
|
191
|
+
*/
|
|
192
|
+
function pedidoCurtoDoImpedimento(d, quando) {
|
|
193
|
+
const retry = `ork retry run ${d.thread}`;
|
|
194
|
+
return (0, hitl_curto_1.montarPedidoCurto)({
|
|
195
|
+
thread: d.thread, fase: d.fase, desde: d.desdeEm,
|
|
196
|
+
pergunta: `Você roda \`${d.impedimento.comando}\` no terminal para destravar o despacho?`,
|
|
197
|
+
corpo: [`${d.motivo}: ${d.detalhe}`, `Depois: ${d.impedimento.depois}.`],
|
|
198
|
+
alternativas: [
|
|
199
|
+
{ chave: 'a', texto: 'Rodei o comando', consequencia: `\`${retry}\` re-despacha ${d.fase ?? 'a fase'} com o mesmo prompt gravado`,
|
|
200
|
+
recomendada: { porque: 'nada rodou ainda; o pedido volta igual, sem você reescrever nada' } },
|
|
201
|
+
{ chave: 'b', texto: 'Trocar o runtime do bloco', consequencia: 'ork setup <modo> --bloco N --runtime <outro>, e depois o mesmo retry' },
|
|
202
|
+
{ chave: 'c', texto: 'Deixar parada', consequencia: 'nada é despachado; a thread segue esperando você' },
|
|
203
|
+
],
|
|
204
|
+
}, { quando, responder: { tipo: 'terminal', comando: retry } });
|
|
205
|
+
}
|