@orkastery/cli 0.5.1 → 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/agents/ork-master.md +2 -0
- package/adapters/claude-code/commands/master.md +8 -0
- 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 +24 -4
- package/adapters/openclaw/dist/hitl-ingress.js +2 -2
- package/adapters/openclaw/dist/index.js +46 -11
- 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 +49 -11
- package/assets/orkmind_bridge.py +117 -9
- package/dist/adapters/claude-bg.js +39 -5
- package/dist/adapters/codex.js +4 -3
- package/dist/agents-md.js +1 -0
- package/dist/auditrun.js +5 -1
- 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/claims.js +39 -1
- package/dist/company-brain-context.js +158 -22
- package/dist/docs.js +48 -9
- package/dist/doctor-pulse-cron.js +194 -0
- package/dist/doctor-rede.js +149 -0
- package/dist/doctor.js +89 -9
- package/dist/entrega-pr.js +20 -8
- package/dist/esgotamentos.js +181 -0
- package/dist/experiencia.js +12 -2
- package/dist/fabrica-estado.js +14 -6
- package/dist/fabrica-publicar.js +6 -0
- package/dist/fechamento.js +20 -66
- 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 +9 -0
- 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 +52 -10
- package/dist/impedimento.js +205 -0
- package/dist/index.js +391 -74
- package/dist/indice-vetorial.js +87 -10
- package/dist/indice.js +3 -1
- package/dist/init.js +17 -0
- package/dist/integracoes-locais.js +2 -0
- package/dist/intelligence-graph-cli.js +91 -8
- package/dist/intelligence-graph-contexto.js +215 -0
- package/dist/intelligence-graph-parsers.js +6 -4
- package/dist/leases.js +664 -87
- package/dist/ledger-stats.js +15 -1
- package/dist/ledger.js +3 -0
- package/dist/licoes.js +1 -0
- package/dist/maestro-runtime.js +4 -1
- package/dist/manifest.js +20 -1
- package/dist/master-nota.js +14 -5
- package/dist/master.js +129 -12
- package/dist/mcp-artifacts.js +34 -3
- package/dist/mcp-git.js +20 -3
- package/dist/mcp-grafo-worker.js +5 -3
- package/dist/mcp-grafo.js +50 -4
- package/dist/mcp-server.js +14 -1
- package/dist/memoria.js +48 -6
- package/dist/network-roadmap.js +191 -16
- package/dist/ocupacao.js +11 -3
- package/dist/orkmind.js +90 -5
- package/dist/orquestracao.js +12 -10
- package/dist/parado-no-condutor.js +188 -32
- package/dist/phase.js +68 -15
- package/dist/policies.js +52 -1
- package/dist/portfolio.js +4 -1
- package/dist/projeto-alvo.js +5 -1
- package/dist/prompts.js +36 -1
- package/dist/prova-ativacao.js +75 -6
- package/dist/pulse-delivery.js +34 -2
- package/dist/pulse.js +49 -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 +23 -3
- 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 -18
- package/dist/sessoes.js +83 -2
- package/dist/ship.js +85 -19
- package/dist/thread.js +192 -13
- package/dist/worktree.js +5 -2
- 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/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/master-metrics/SKILL.md +8 -3
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* RM-039 (B6): o `ork doctor` acusa o pulse que bate devagar demais.
|
|
4
|
+
*
|
|
5
|
+
* A cadencia por tag (#OrkPulseOn-15m e as outras) so vale inteira com a varredura do cron de 15
|
|
6
|
+
* em 15 minutos. A instalacao antiga fica em `0 * * * *`, e nada avisava. Com o transporte do
|
|
7
|
+
* pulse configurado (`.orkastery/monitor/pulse-host.json`), o doctor le o `crontab -l` e avisa,
|
|
8
|
+
* sem bloquear, quando a linha da varredura falta ou bate mais devagar que o template
|
|
9
|
+
* `monitor/pulse.cron`. O doctor nunca edita o crontab: a correcao traz a linha pronta.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.COMANDO_DO_TEMPLATE = exports.SCRIPT_DA_VARREDURA = exports.BATIDA_DO_TEMPLATE = void 0;
|
|
46
|
+
exports.lerCrontabDoSistema = lerCrontabDoSistema;
|
|
47
|
+
exports.intervaloEmMinutos = intervaloEmMinutos;
|
|
48
|
+
exports.linhasDaVarredura = linhasDaVarredura;
|
|
49
|
+
exports.scriptDaVarreduraDoOrk = scriptDaVarreduraDoOrk;
|
|
50
|
+
exports.comandoDaVarredura = comandoDaVarredura;
|
|
51
|
+
exports.checarCronDoPulse = checarCronDoPulse;
|
|
52
|
+
const fs = __importStar(require("node:fs"));
|
|
53
|
+
const path = __importStar(require("node:path"));
|
|
54
|
+
const util_1 = require("./util");
|
|
55
|
+
/** A batida do template `monitor/pulse.cron` (I-50): a menor cadencia das tags. */
|
|
56
|
+
exports.BATIDA_DO_TEMPLATE = '*/15 * * * *';
|
|
57
|
+
/** O script que o template agenda; a linha do crontab e achada por ele. */
|
|
58
|
+
exports.SCRIPT_DA_VARREDURA = 'varredura-pulse.sh';
|
|
59
|
+
/** Comando do template antes da troca do caminho pelo checkout de quem instala. */
|
|
60
|
+
exports.COMANDO_DO_TEMPLATE = '/CAMINHO/orkastery/monitor/varredura-pulse.sh';
|
|
61
|
+
/** Le o crontab do usuario do processo, sem shell e com prazo. */
|
|
62
|
+
function lerCrontabDoSistema() {
|
|
63
|
+
const r = (0, util_1.exec)('crontab', ['-l'], undefined, 5000);
|
|
64
|
+
if (r.ok)
|
|
65
|
+
return { ok: true, texto: r.stdout };
|
|
66
|
+
if (r.error === 'ENOENT')
|
|
67
|
+
return { ok: false, motivo: 'comando crontab ausente nesta maquina' };
|
|
68
|
+
const msg = (r.stderr || r.stdout).trim().split('\n')[0] ?? '';
|
|
69
|
+
return { ok: false, motivo: msg ? `crontab -l falhou: ${msg}` : `crontab -l saiu ${r.code}` };
|
|
70
|
+
}
|
|
71
|
+
const MACROS = { '@hourly': 60, '@daily': 1440, '@midnight': 1440, '@weekly': 10080,
|
|
72
|
+
'@monthly': 43200, '@yearly': 525600, '@annually': 525600 };
|
|
73
|
+
/**
|
|
74
|
+
* Maior intervalo, em minutos, entre duas batidas da linha (so os campos de minuto e hora; dia,
|
|
75
|
+
* mes e dia da semana restritos contam como mais devagar que uma hora). `null` quando a expressao
|
|
76
|
+
* nao e reconhecida: o doctor entao avisa pela linha, sem adivinhar.
|
|
77
|
+
*/
|
|
78
|
+
function intervaloEmMinutos(expressao) {
|
|
79
|
+
const campos = expressao.trim().split(/\s+/);
|
|
80
|
+
if (campos.length === 1 && campos[0].startsWith('@'))
|
|
81
|
+
return MACROS[campos[0]] ?? null;
|
|
82
|
+
if (campos.length !== 5)
|
|
83
|
+
return null;
|
|
84
|
+
const [minuto, hora, dia, mes, semana] = campos;
|
|
85
|
+
const minutos = valoresDoCampo(minuto, 0, 59);
|
|
86
|
+
if (!minutos)
|
|
87
|
+
return null;
|
|
88
|
+
if (hora !== '*' || dia !== '*' || mes !== '*' || semana !== '*')
|
|
89
|
+
return Math.max(60, maiorLacuna(minutos, 60));
|
|
90
|
+
return maiorLacuna(minutos, 60);
|
|
91
|
+
}
|
|
92
|
+
function valoresDoCampo(campo, min, max) {
|
|
93
|
+
const valores = new Set();
|
|
94
|
+
for (const parte of campo.split(',')) {
|
|
95
|
+
const m = /^(\*|(\d+)(?:-(\d+))?)(?:\/(\d+))?$/.exec(parte);
|
|
96
|
+
if (!m)
|
|
97
|
+
return null;
|
|
98
|
+
const inicio = m[1] === '*' ? min : Number(m[2]);
|
|
99
|
+
const fim = m[1] === '*' ? max : m[3] !== undefined ? Number(m[3]) : m[4] !== undefined ? max : inicio;
|
|
100
|
+
const passo = m[4] !== undefined ? Number(m[4]) : 1;
|
|
101
|
+
if (passo < 1 || inicio < min || fim > max || inicio > fim)
|
|
102
|
+
return null;
|
|
103
|
+
for (let v = inicio; v <= fim; v += passo)
|
|
104
|
+
valores.add(v);
|
|
105
|
+
}
|
|
106
|
+
return [...valores].sort((a, b) => a - b);
|
|
107
|
+
}
|
|
108
|
+
/** Maior distancia entre dois valores consecutivos, contando a volta do ciclo. */
|
|
109
|
+
function maiorLacuna(valores, ciclo) {
|
|
110
|
+
let maior = 0;
|
|
111
|
+
for (let i = 0; i < valores.length; i++) {
|
|
112
|
+
const proximo = i + 1 < valores.length ? valores[i + 1] : valores[0] + ciclo;
|
|
113
|
+
maior = Math.max(maior, proximo - valores[i]);
|
|
114
|
+
}
|
|
115
|
+
return maior;
|
|
116
|
+
}
|
|
117
|
+
/** Separa a expressao de horario do comando numa linha do crontab. */
|
|
118
|
+
function dividirLinha(linha) {
|
|
119
|
+
const t = linha.trim();
|
|
120
|
+
if (t.startsWith('@')) {
|
|
121
|
+
const m = /^(@\S+)\s+(.+)$/.exec(t);
|
|
122
|
+
return m ? { quando: m[1], comando: m[2] } : null;
|
|
123
|
+
}
|
|
124
|
+
const m = /^(\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.+)$/.exec(t);
|
|
125
|
+
return m ? { quando: m[1], comando: m[2] } : null;
|
|
126
|
+
}
|
|
127
|
+
/** Linhas ativas (nao comentario, nao variavel) que agendam a varredura do pulse. */
|
|
128
|
+
function linhasDaVarredura(crontab) {
|
|
129
|
+
return crontab.split('\n').map(l => l.trim())
|
|
130
|
+
.filter(l => l && !l.startsWith('#') && !/^[A-Za-z_][A-Za-z0-9_]*\s*=/.test(l) && l.includes(exports.SCRIPT_DA_VARREDURA));
|
|
131
|
+
}
|
|
132
|
+
/** Aspas de shell so quando o caminho precisa (a linha vai colada no crontab, que roda por `sh`). */
|
|
133
|
+
function citar(caminho) {
|
|
134
|
+
return /^[A-Za-z0-9_./:@+-]+$/.test(caminho) ? caminho : `'${caminho.replace(/'/g, `'\\''`)}'`;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* O script da varredura que este `ork` traz: no pacote do npm, `monitor/` fica ao lado de `dist/`; no
|
|
138
|
+
* checkout, na raiz do repositorio, dois niveis acima de `core/dist/`. `null` quando nenhum existe.
|
|
139
|
+
*/
|
|
140
|
+
function scriptDaVarreduraDoOrk(dirDoDist = __dirname) {
|
|
141
|
+
for (const dir of [path.join(dirDoDist, '..', 'monitor'), path.join(dirDoDist, '..', '..', 'monitor')]) {
|
|
142
|
+
const script = path.join(dir, exports.SCRIPT_DA_VARREDURA);
|
|
143
|
+
if (fs.existsSync(script))
|
|
144
|
+
return path.resolve(script);
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* O comando que a linha nova do crontab roda. Ensaio de 03/10/2026 (RM-049): a correcao apontava
|
|
150
|
+
* `<projeto>/monitor/varredura-pulse.sh`, que so existe no checkout do proprio Orkastery; quem instalou
|
|
151
|
+
* pelo npm recebia um caminho que nao existe. Quando o projeto nao traz o script, a linha usa o do `ork`
|
|
152
|
+
* instalado e diz o projeto por `ORK_PULSE_PROJECT` (o cron nao roda no diretorio do projeto).
|
|
153
|
+
*/
|
|
154
|
+
function comandoDaVarredura(raizDoProjeto, scriptDoOrk = scriptDaVarreduraDoOrk()) {
|
|
155
|
+
const doProjeto = path.join(raizDoProjeto, 'monitor', exports.SCRIPT_DA_VARREDURA);
|
|
156
|
+
if (fs.existsSync(doProjeto) || !scriptDoOrk)
|
|
157
|
+
return citar(doProjeto);
|
|
158
|
+
return `ORK_PULSE_PROJECT=${citar(raizDoProjeto)} ${citar(scriptDoOrk)}`;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check "cadencia do pulse no cron". `null` quando o projeto nao tem transporte do pulse: sem
|
|
162
|
+
* `pulse-host.json` nao ha resumo para entregar, e o doctor nao fala de cron.
|
|
163
|
+
*/
|
|
164
|
+
function checarCronDoPulse(dirMonitor, raizDoCheckout, ler = lerCrontabDoSistema, scriptDoOrk = scriptDaVarreduraDoOrk()) {
|
|
165
|
+
if (!fs.existsSync(path.join(dirMonitor, 'pulse-host.json')))
|
|
166
|
+
return null;
|
|
167
|
+
const nome = 'cadencia do pulse no cron';
|
|
168
|
+
const comandoSugerido = comandoDaVarredura(raizDoCheckout, scriptDoOrk);
|
|
169
|
+
const linhaNova = (comando) => `${exports.BATIDA_DO_TEMPLATE} ${comando}`;
|
|
170
|
+
const ausente = (detalhe) => ({ nome, nivel: 'warn', detalhe,
|
|
171
|
+
correcao: `adicione ao crontab (crontab -e), como no template monitor/pulse.cron: ${linhaNova(comandoSugerido)}` });
|
|
172
|
+
const leitura = ler();
|
|
173
|
+
if (!leitura.ok)
|
|
174
|
+
return ausente(`pulse-host.json presente, mas sem crontab para ler (${leitura.motivo}): a varredura nao bate`);
|
|
175
|
+
const linhas = linhasDaVarredura(leitura.texto);
|
|
176
|
+
if (linhas.length === 0)
|
|
177
|
+
return ausente(`pulse-host.json presente, e nenhuma linha do crontab roda ${exports.SCRIPT_DA_VARREDURA}: o resumo nao sai`);
|
|
178
|
+
const lentas = [];
|
|
179
|
+
for (const linha of linhas) {
|
|
180
|
+
const partes = dividirLinha(linha);
|
|
181
|
+
const intervalo = partes ? intervaloEmMinutos(partes.quando) : null;
|
|
182
|
+
if (intervalo === null || intervalo > 15)
|
|
183
|
+
lentas.push({ linha, comando: partes?.comando ?? comandoSugerido, intervalo });
|
|
184
|
+
}
|
|
185
|
+
if (lentas.length < linhas.length) {
|
|
186
|
+
return { nome, nivel: 'ok', detalhe: `varredura no cron a cada 15 minutos ou menos (${linhas.length} linha(s))` };
|
|
187
|
+
}
|
|
188
|
+
const l = lentas[0];
|
|
189
|
+
const ritmo = l.intervalo === null ? 'com horario que o doctor nao le' : l.intervalo === 60 ? 'de hora em hora'
|
|
190
|
+
: `a cada ${l.intervalo} minutos`;
|
|
191
|
+
return { nome, nivel: 'warn',
|
|
192
|
+
detalhe: `a varredura do pulse bate ${ritmo} (\`${l.linha}\`): a cadencia por tag (RM-039) pede 15 minutos`,
|
|
193
|
+
correcao: `troque a linha no crontab (crontab -e) por: ${linhaNova(l.comando)}` };
|
|
194
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
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.CAUDA_DO_LOG_BYTES = void 0;
|
|
37
|
+
exports.caudaDoLogDaRede = caudaDoLogDaRede;
|
|
38
|
+
exports.correcaoDaFalha = correcaoDaFalha;
|
|
39
|
+
exports.checarRede = checarRede;
|
|
40
|
+
/**
|
|
41
|
+
* RM-053 (fatia 2): o check "rede" do `ork doctor`.
|
|
42
|
+
*
|
|
43
|
+
* A rede pessoal publica sozinha (batida do pulse e eventos de thread) e so deixava rastro em
|
|
44
|
+
* `~/.orkastery/rede/rede.log`: a srvjcp86 ficou de 02/10 em diante como membro herdado da fabrica,
|
|
45
|
+
* com toda publicacao caindo em `rede.sem-repositorio`, e o doctor dizia PRONTO sem uma palavra.
|
|
46
|
+
*
|
|
47
|
+
* O check diz a adesao, a casa, a ultima batida publicada e a ultima falha do log. Ele so le
|
|
48
|
+
* arquivos locais (`rede.json`, `maquina.json`, `rede/publicada.json`, `rede/rede.log`): nao chama
|
|
49
|
+
* a forja, nao cria estado e roda de qualquer diretorio. Nunca reprova: a rede e opcional e o
|
|
50
|
+
* doctor e gate de despacho; o pior nivel e `warn`, com a correcao.
|
|
51
|
+
*/
|
|
52
|
+
const fs = __importStar(require("node:fs"));
|
|
53
|
+
const path = __importStar(require("node:path"));
|
|
54
|
+
const horario_1 = require("./horario");
|
|
55
|
+
const rede_1 = require("./rede");
|
|
56
|
+
const rede_adesao_1 = require("./rede-adesao");
|
|
57
|
+
const rede_status_1 = require("./rede-status");
|
|
58
|
+
const saida_segura_1 = require("./saida-segura");
|
|
59
|
+
/** O fim do `rede.log` que o doctor le: o log so cresce, e o que importa e o mais recente. */
|
|
60
|
+
exports.CAUDA_DO_LOG_BYTES = 64 * 1024;
|
|
61
|
+
/** As linhas legiveis do fim do `rede.log`, da mais antiga para a mais nova. Sem log, lista vazia. */
|
|
62
|
+
function caudaDoLogDaRede(arquivo = path.join((0, rede_adesao_1.pastaDaRede)(), 'rede.log')) {
|
|
63
|
+
let texto;
|
|
64
|
+
try {
|
|
65
|
+
const fd = fs.openSync(arquivo, 'r');
|
|
66
|
+
try {
|
|
67
|
+
const tamanho = fs.fstatSync(fd).size;
|
|
68
|
+
const inicio = Math.max(0, tamanho - exports.CAUDA_DO_LOG_BYTES);
|
|
69
|
+
const buf = Buffer.alloc(tamanho - inicio);
|
|
70
|
+
fs.readSync(fd, buf, 0, buf.length, inicio);
|
|
71
|
+
texto = buf.toString('utf8');
|
|
72
|
+
// A primeira linha de uma cauda cortada vem pela metade.
|
|
73
|
+
if (inicio > 0)
|
|
74
|
+
texto = texto.slice(texto.indexOf('\n') + 1);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
fs.closeSync(fd);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
const registros = [];
|
|
84
|
+
for (const linha of texto.split('\n')) {
|
|
85
|
+
if (!linha.trim())
|
|
86
|
+
continue;
|
|
87
|
+
try {
|
|
88
|
+
const r = JSON.parse(linha);
|
|
89
|
+
if (typeof r.ts !== 'string' || !Number.isFinite(Date.parse(r.ts)) || typeof r.acao !== 'string')
|
|
90
|
+
continue;
|
|
91
|
+
registros.push({ ts: r.ts, acao: r.acao, origem: typeof r.origem === 'string' ? r.origem : null,
|
|
92
|
+
erro: typeof r.erro === 'string' ? r.erro : null });
|
|
93
|
+
}
|
|
94
|
+
catch { /* linha ilegivel: o log e informativo */ }
|
|
95
|
+
}
|
|
96
|
+
return registros;
|
|
97
|
+
}
|
|
98
|
+
const curto = (s, teto = 200) => {
|
|
99
|
+
const limpo = (0, saida_segura_1.emUmaLinha)(s).trim();
|
|
100
|
+
return limpo.length > teto ? `${limpo.slice(0, teto - 3)}...` : limpo;
|
|
101
|
+
};
|
|
102
|
+
/** A correcao pela familia do erro da ultima falha (o prefixo tipado, como `rede.sem-repositorio`). */
|
|
103
|
+
function correcaoDaFalha(erro) {
|
|
104
|
+
const codigo = /^([a-z]+\.[a-z-]+):/.exec(erro)?.[1] ?? '';
|
|
105
|
+
if (codigo === 'rede.sem-repositorio' || codigo === 'rede.repositorio-alheio') {
|
|
106
|
+
return 'a casa da rede ainda nao existe: o dono roda ork network entrar, que cria o repositorio privado; ou ork network sair, para tirar esta maquina da rede';
|
|
107
|
+
}
|
|
108
|
+
if (codigo === 'rede.sem-forja')
|
|
109
|
+
return 'faca login na forja (gh auth login ou glab auth login) e rode ork network publicar';
|
|
110
|
+
if (codigo === 'rede.repositorio-publico')
|
|
111
|
+
return 'torne a casa da rede privada na forja; nada e publicado num repositorio publico';
|
|
112
|
+
if (codigo === 'rede.nome-em-uso')
|
|
113
|
+
return 'escolha outro nome com ork network entrar --maquina NOME, ou tome este com --forcar';
|
|
114
|
+
return 'ork network status mostra as lacunas; ork network publicar tenta de novo';
|
|
115
|
+
}
|
|
116
|
+
/** O check "rede". `agoraMs` e o log ficam injetaveis para o teste. */
|
|
117
|
+
function checarRede(opcoes = {}) {
|
|
118
|
+
const nome = 'rede';
|
|
119
|
+
const agora = opcoes.agoraMs ?? Date.now();
|
|
120
|
+
const adesao = (0, rede_adesao_1.adesaoDaRede)();
|
|
121
|
+
if (!adesao.membro) {
|
|
122
|
+
return { nome, nivel: 'ok', detalhe: adesao.config && !adesao.config.membro
|
|
123
|
+
? 'fora da rede (saiu com ork network sair)'
|
|
124
|
+
: 'fora da rede; ork network entrar poe esta maquina na rede da pessoa' };
|
|
125
|
+
}
|
|
126
|
+
const marca = (0, rede_1.lerMarcaDaRede)();
|
|
127
|
+
const config = adesao.config;
|
|
128
|
+
const casa = config?.host && config.dono && config.repositorio ? `${config.host}/${config.dono}/${config.repositorio}`
|
|
129
|
+
: typeof marca?.casa === 'string' ? marca.casa : null;
|
|
130
|
+
const registros = caudaDoLogDaRede(opcoes.log);
|
|
131
|
+
const falha = [...registros].reverse().find((r) => r.acao === 'falhou') ?? null;
|
|
132
|
+
const emBatida = marca && typeof marca.em === 'string' && Number.isFinite(Date.parse(marca.em)) ? marca.em : null;
|
|
133
|
+
const idade = emBatida ? agora - Date.parse(emBatida) : NaN;
|
|
134
|
+
const partes = [
|
|
135
|
+
adesao.adesao === 'fabrica' ? 'membro herdado da fabrica' : 'membro',
|
|
136
|
+
casa ? `casa ${curto(casa, 120)}` : 'casa ainda nao gravada',
|
|
137
|
+
emBatida ? `ultima batida ${(0, horario_1.formatarDataHora)(emBatida)} (ha ${(0, rede_status_1.duracao)(idade)})` : 'nenhuma batida publicada',
|
|
138
|
+
falha ? `ultima falha ${(0, horario_1.formatarDataHora)(falha.ts)}${falha.origem ? ` (${curto(falha.origem, 20)})` : ''}: ${curto(falha.erro ?? 'sem detalhe')}`
|
|
139
|
+
: 'nenhuma falha no rede.log',
|
|
140
|
+
];
|
|
141
|
+
// A falha mais nova que a ultima batida e o estado de agora; a de antes ja passou.
|
|
142
|
+
const falhaAtual = !!falha && (!emBatida || Date.parse(falha.ts) > Date.parse(emBatida));
|
|
143
|
+
const parada = !emBatida || !(idade <= rede_status_1.SEM_BATIDA_MS);
|
|
144
|
+
if (!falhaAtual && !parada)
|
|
145
|
+
return { nome, nivel: 'ok', detalhe: partes.join('; ') };
|
|
146
|
+
const correcao = falhaAtual ? correcaoDaFalha(falha.erro ?? '')
|
|
147
|
+
: 'a batida sai do pulse: confira o cron do pulse e rode ork network publicar';
|
|
148
|
+
return { nome, nivel: 'warn', detalhe: partes.join('; '), correcao };
|
|
149
|
+
}
|
package/dist/doctor.js
CHANGED
|
@@ -40,6 +40,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
40
40
|
})();
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
42
|
exports.TETO_DO_DONO_DO_GIT = void 0;
|
|
43
|
+
exports.manifestoForaDoRepositorio = manifestoForaDoRepositorio;
|
|
43
44
|
exports.checarContas = checarContas;
|
|
44
45
|
exports.checarChaveDeEmbedding = checarChaveDeEmbedding;
|
|
45
46
|
exports.checarDonoDoGit = checarDonoDoGit;
|
|
@@ -69,6 +70,41 @@ const runtime_ambiente_1 = require("./runtime-ambiente");
|
|
|
69
70
|
const runtime_profiles_1 = require("./runtime-profiles");
|
|
70
71
|
const preflight_1 = require("./preflight");
|
|
71
72
|
const setup_1 = require("./setup");
|
|
73
|
+
const doctor_pulse_cron_1 = require("./doctor-pulse-cron");
|
|
74
|
+
const doctor_rede_1 = require("./doctor-rede");
|
|
75
|
+
/**
|
|
76
|
+
* Ensaio de 03/10/2026 (RM-049): o manifesto e achado subindo a partir do diretorio atual. Um
|
|
77
|
+
* `orkastery.yaml` de uma pasta acima do repositorio (um `ork init` rodado por engano no HOME) era
|
|
78
|
+
* lido como o deste projeto, com outro nome e outra abbrev, e o doctor dizia PRONTO. Vale o manifesto
|
|
79
|
+
* dentro do repositorio ou na arvore principal dele (a worktree de thread le o da arvore principal).
|
|
80
|
+
*/
|
|
81
|
+
function manifestoForaDoRepositorio(dirInicial, caminhoDoManifesto) {
|
|
82
|
+
const topo = (0, util_1.exec)('git', ['rev-parse', '--show-toplevel'], dirInicial);
|
|
83
|
+
if (!topo.ok)
|
|
84
|
+
return null;
|
|
85
|
+
const real = (p) => { try {
|
|
86
|
+
return fs.realpathSync(p);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return path.resolve(p);
|
|
90
|
+
} };
|
|
91
|
+
const dirDoManifesto = real(path.dirname(caminhoDoManifesto));
|
|
92
|
+
const dentro = (raiz) => {
|
|
93
|
+
const r = path.relative(real(raiz), dirDoManifesto);
|
|
94
|
+
return r === '' || (!r.startsWith('..') && !path.isAbsolute(r));
|
|
95
|
+
};
|
|
96
|
+
if (dentro(topo.stdout.trim()))
|
|
97
|
+
return null;
|
|
98
|
+
const comum = (0, util_1.exec)('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], dirInicial);
|
|
99
|
+
if (comum.ok && path.basename(comum.stdout.trim()) === '.git' && dentro(path.dirname(comum.stdout.trim())))
|
|
100
|
+
return null;
|
|
101
|
+
return {
|
|
102
|
+
nome: 'manifesto do repositorio',
|
|
103
|
+
nivel: 'warn',
|
|
104
|
+
detalhe: `o ${manifest_1.NOME_MANIFESTO} lido fica fora deste repositorio (${caminhoDoManifesto}): o ork conduz o projeto daquela pasta, nao o de ${topo.stdout.trim()}`,
|
|
105
|
+
correcao: `rode ork init na raiz deste repositorio (${topo.stdout.trim()}); se o manifesto de fora nasceu por engano, apague-o junto com o AGENTS.md e o .orkastery/ ao lado dele`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
72
108
|
/**
|
|
73
109
|
* I-33 (D7): check "contas por runtime". Cada perfil ativo tem o login conferido pelo proprio
|
|
74
110
|
* CLI com o env dele (`claude auth status`, `codex login status`); o doctor so le e relata, sem
|
|
@@ -294,15 +330,40 @@ function textoDosBlocos(blocos) {
|
|
|
294
330
|
porModo.set(b.tag, [...(porModo.get(b.tag) ?? []), b.bloco]);
|
|
295
331
|
return [...porModo].map(([tag, numeros]) => `${tag} ${numeros.join(', ')}`).join('; ');
|
|
296
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Ensaio de 03/10 (R1): com perfil ativo do runtime, quem confere o login e o check "contas por runtime";
|
|
335
|
+
* sem perfil (ou com o store ilegivel, que aquele check reprova), o despacho usa o login do `claude` do processo.
|
|
336
|
+
*/
|
|
337
|
+
function temPerfilAtivo(carregado, runtime) {
|
|
338
|
+
if (!carregado || carregado.erros.length)
|
|
339
|
+
return false;
|
|
340
|
+
try {
|
|
341
|
+
return (0, runtime_profiles_1.lerPerfisComContas)(carregado.raiz).perfis.some(p => p.runtime === runtime && p.estado !== 'desativado');
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
297
347
|
/**
|
|
298
348
|
* Fatia 2 do ensaio da 0.5.0 (P1): o `claude` so e obrigatorio quando algum bloco de modo permitido
|
|
299
349
|
* despacha por ele. Sem manifesto, com manifesto invalido ou com setup ilegivel vale o padrao (todo
|
|
300
350
|
* bloco no claude-bg), e a falta reprova como antes.
|
|
301
351
|
*/
|
|
302
|
-
function checarRuntimeClaude(carregado, claude, versao) {
|
|
352
|
+
function checarRuntimeClaude(carregado, claude, versao, auth = null) {
|
|
303
353
|
const nome = 'runtime claude-bg';
|
|
304
|
-
if (claude)
|
|
305
|
-
|
|
354
|
+
if (claude) {
|
|
355
|
+
const detalhe = `${claude} (${versao ?? 'versao desconhecida'})`;
|
|
356
|
+
// Ensaio de 03/10 (R1): sem perfil de conta, o despacho usa o login do proprio `claude`; sem ele, o
|
|
357
|
+
// primeiro despacho falha. Conferencia inconclusiva (timeout, JSON ilegivel) nao prova falta de login.
|
|
358
|
+
if (auth && !auth.ok && !auth.transitorio) {
|
|
359
|
+
return { nome, nivel: 'warn', detalhe: `${detalhe}; ${auth.detalhe}: o despacho pelo claude-bg falharia`,
|
|
360
|
+
correcao: auth.pago
|
|
361
|
+
? 'faca o login de assinatura (claude.ai) no `claude`, sem API key nem provider de nuvem'
|
|
362
|
+
: 'rode `claude` uma vez, faca o login de assinatura (/login) e aceite a confianca no diretorio do projeto; ' +
|
|
363
|
+
'ou crie um perfil com ork accounts add <id> --runtime claude-bg --dir <pasta>' };
|
|
364
|
+
}
|
|
365
|
+
return { nome, nivel: 'ok', detalhe };
|
|
366
|
+
}
|
|
306
367
|
const blocos = carregado && carregado.erros.length === 0 ? blocosDoRuntime(carregado, 'claude-bg') : null;
|
|
307
368
|
if (blocos && blocos.principal.length === 0) {
|
|
308
369
|
// CHECK, rodada 1 (S6): as fases nao precisam dele, mas o `ork audit run` despacha sempre pelo claude-bg.
|
|
@@ -351,8 +412,12 @@ function checarDespachoPeloCodex(carregado, codex, sonda) {
|
|
|
351
412
|
: undefined,
|
|
352
413
|
};
|
|
353
414
|
}
|
|
354
|
-
/**
|
|
355
|
-
|
|
415
|
+
/**
|
|
416
|
+
* Roda todos os checks a partir do diretorio informado. RM-031: `analisadores` e o check do grafo
|
|
417
|
+
* (`checarAnalisadoresDoGrafo` do CLI do grafo), que o `index.ts` passa: fora da familia do grafo so
|
|
418
|
+
* ele e o worker do MCP a abrem (fronteira do KG1), e o doctor nao a importa.
|
|
419
|
+
*/
|
|
420
|
+
function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), lerCrontab = doctor_pulse_cron_1.lerCrontabDoSistema, conferirAuthDoClaude = () => adapter.conferirAuth(null), analisadores) {
|
|
356
421
|
const checks = [];
|
|
357
422
|
const major = versaoNode();
|
|
358
423
|
checks.push({
|
|
@@ -361,6 +426,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
361
426
|
detalhe: `v${process.versions.node}`,
|
|
362
427
|
correcao: major >= 20 ? undefined : 'instale Node 20 ou superior',
|
|
363
428
|
});
|
|
429
|
+
if (analisadores)
|
|
430
|
+
checks.push(analisadores());
|
|
364
431
|
const git = (0, util_1.noPath)('git');
|
|
365
432
|
checks.push({
|
|
366
433
|
nome: 'git',
|
|
@@ -390,7 +457,7 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
390
457
|
const carregado = (0, manifest_1.carregarManifesto)(dirInicial);
|
|
391
458
|
const claude = adapter.disponivel();
|
|
392
459
|
const v = claude ? adapter.versao() : null;
|
|
393
|
-
checks.push(checarRuntimeClaude(carregado, claude, v));
|
|
460
|
+
checks.push(checarRuntimeClaude(carregado, claude, v, claude && !temPerfilAtivo(carregado, 'claude-bg') ? conferirAuthDoClaude() : null));
|
|
394
461
|
// Segundo runtime homologado. Ausente e `warn`, nao `fail`: o claude-bg segue sendo o
|
|
395
462
|
// padrao, e um projeto que nunca pediu codex nao pode ficar bloqueado por ele.
|
|
396
463
|
const codex = codexAdapter.disponivel();
|
|
@@ -433,7 +500,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
433
500
|
nome: 'manifesto',
|
|
434
501
|
nivel: 'fail',
|
|
435
502
|
detalhe: `${manifest_1.NOME_MANIFESTO} nao encontrado a partir de ${dirInicial}`,
|
|
436
|
-
|
|
503
|
+
// Ensaio de 03/10/2026 (RM-049): fora de repositorio, o `ork init` recusa; a correcao diz onde roda-lo.
|
|
504
|
+
correcao: dentroDeRepo ? 'ork init' : 'entre no repositorio do projeto (ou crie um com git init e o primeiro commit) e rode ork init',
|
|
437
505
|
});
|
|
438
506
|
}
|
|
439
507
|
else {
|
|
@@ -446,6 +514,11 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
446
514
|
(carregado.avisos.length > 0 ? `; ${carregado.avisos.join('; ')}` : ''),
|
|
447
515
|
correcao: carregado.erros.length > 0 ? 'corrija o manifesto e rode ork doctor de novo' : undefined,
|
|
448
516
|
});
|
|
517
|
+
if (dentroDeRepo) {
|
|
518
|
+
const fora = manifestoForaDoRepositorio(dirInicial, carregado.caminho);
|
|
519
|
+
if (fora)
|
|
520
|
+
checks.push(fora);
|
|
521
|
+
}
|
|
449
522
|
checks.push(...checarOnboarding(carregado));
|
|
450
523
|
const abbrev = carregado.manifesto.project.abbrev;
|
|
451
524
|
const checkAbbrev = (0, slug_1.validarAbbrev)(abbrev);
|
|
@@ -554,6 +627,11 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
554
627
|
: `${dirEstadoProjeto} ausente`,
|
|
555
628
|
correcao: fs.existsSync(dirEstadoProjeto) ? undefined : 'ork init cria o diretorio de estado',
|
|
556
629
|
});
|
|
630
|
+
// RM-039 (B6): com o transporte do pulse configurado, a varredura tem de bater de 15 em 15
|
|
631
|
+
// minutos; a instalacao antiga em `0 * * * *` vira aviso com a linha nova. Nunca edita o crontab.
|
|
632
|
+
const cronDoPulse = (0, doctor_pulse_cron_1.checarCronDoPulse)(path.join(dirEstadoProjeto, 'monitor'), (0, estado_thread_1.raizDoEstado)(carregado.raiz), lerCrontab);
|
|
633
|
+
if (cronDoPulse)
|
|
634
|
+
checks.push(cronDoPulse);
|
|
557
635
|
checks.push(checarContas(carregado.raiz));
|
|
558
636
|
// I-33 (D7): umask e permissoes do estado, na mesma regra do sensor (sem bits 0o022).
|
|
559
637
|
checks.push(...(0, preflight_1.sondasDeAmbiente)(carregado.raiz));
|
|
@@ -573,6 +651,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
|
|
|
573
651
|
});
|
|
574
652
|
}
|
|
575
653
|
}
|
|
654
|
+
// RM-053 (fatia 2): a rede da pessoa e da maquina, nao do projeto; vale de qualquer diretorio.
|
|
655
|
+
checks.push((0, doctor_rede_1.checarRede)());
|
|
576
656
|
return checks;
|
|
577
657
|
}
|
|
578
658
|
/** Texto do relatorio, com o resumo "o que vale nesta maquina agora". */
|
|
@@ -608,8 +688,8 @@ function relatorio(checks) {
|
|
|
608
688
|
return linhas.join('\n');
|
|
609
689
|
}
|
|
610
690
|
/** Executa o doctor e devolve o codigo de saida (0 = pronto). */
|
|
611
|
-
function doctor(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)()) {
|
|
612
|
-
const checks = checar(dirInicial, nomesHerdados);
|
|
691
|
+
function doctor(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), analisadores) {
|
|
692
|
+
const checks = checar(dirInicial, nomesHerdados, undefined, undefined, analisadores);
|
|
613
693
|
const falhas = checks.filter((c) => c.nivel === 'fail').length;
|
|
614
694
|
return { texto: relatorio(checks), codigo: falhas > 0 ? 1 : 0 };
|
|
615
695
|
}
|
package/dist/entrega-pr.js
CHANGED
|
@@ -16,7 +16,9 @@ exports.registrarEntregasPorPr = registrarEntregasPorPr;
|
|
|
16
16
|
* remota (ancestralidade conferida contra a ponta que o `ls-remote` devolve) e o check do CI no
|
|
17
17
|
* head do PR. Sem CI verde, nao registra: merge sem prova independente nao e entrega.
|
|
18
18
|
*/
|
|
19
|
+
const branch_de_estado_1 = require("./branch-de-estado");
|
|
19
20
|
const ci_1 = require("./ci");
|
|
21
|
+
const docs_1 = require("./docs");
|
|
20
22
|
const fabrica_publicar_1 = require("./fabrica-publicar");
|
|
21
23
|
const ledger_1 = require("./ledger");
|
|
22
24
|
const modos_1 = require("./modos");
|
|
@@ -49,7 +51,7 @@ function avancarParaShip(raiz, threadId) {
|
|
|
49
51
|
(0, thread_1.gravarThread)(raiz, atualizada);
|
|
50
52
|
}
|
|
51
53
|
function resultado(thread, acao, motivo, extra = {}) {
|
|
52
|
-
return { thread, acao, motivo, mergeSha: null, headSha: null, ci: null, ...extra };
|
|
54
|
+
return { thread, acao, motivo, mergeSha: null, headSha: null, ci: null, docsPendentes: [], ...extra };
|
|
53
55
|
}
|
|
54
56
|
/**
|
|
55
57
|
* `ork ship registrar-pr <thread>`: grava o `ship_done` da entrega feita por PR. Idempotente:
|
|
@@ -57,22 +59,26 @@ function resultado(thread, acao, motivo, extra = {}) {
|
|
|
57
59
|
*/
|
|
58
60
|
function registrarEntregaPorPr(carregado, threadId, opcoes = {}) {
|
|
59
61
|
const raiz = carregado.raiz;
|
|
60
|
-
|
|
62
|
+
// RM-047: o `--remoto` vem da linha de comando; so nome de remoto chega ao git, e depois do `--`.
|
|
63
|
+
const remoto = (0, branch_de_estado_1.exigirRemoto)(opcoes.remoto ?? 'origin', 'ship');
|
|
61
64
|
const base = carregado.manifesto.worktree.base_branch;
|
|
62
65
|
const thread = (0, thread_1.lerThread)(raiz, threadId);
|
|
63
66
|
if (thread.status === 'fechada')
|
|
64
67
|
return resultado(threadId, 'ja-registrada', 'thread ja fechada');
|
|
65
68
|
if (opcoes.buscar !== false)
|
|
66
|
-
(0, util_1.exec)('git', ['fetch', '-q', remoto, `+refs/heads/${base}:refs/remotes/${remoto}/${base}`], raiz);
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
+
(0, util_1.exec)('git', ['fetch', '-q', '--', remoto, `+refs/heads/${base}:refs/remotes/${remoto}/${base}`], raiz);
|
|
70
|
+
const encontrado = mergeDaEntrega(raiz, threadId, remoto, base);
|
|
71
|
+
if (!encontrado)
|
|
69
72
|
return resultado(threadId, 'sem-merge', `nenhum merge ship(${threadId}) em ${remoto}/${base}`);
|
|
73
|
+
// RM-044 (A3): o condutor roda o registrar-pr logo depois do merge; e aqui que ele fica sabendo da pagina que
|
|
74
|
+
// vai deixar o push da base vermelho, lida da base remota que o fetch acabou de trazer.
|
|
75
|
+
const merge = { ...encontrado, docsPendentes: (0, docs_1.docsPendentesDoMerge)(raiz, threadId, `refs/remotes/${remoto}/${base}`) };
|
|
70
76
|
const dir = (0, thread_1.dirThread)(raiz, threadId);
|
|
71
77
|
const jaTem = (0, ledger_1.lerLedger)(dir).some((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.shipConcluido && e.mergeSha === merge.mergeSha);
|
|
72
78
|
if (jaTem)
|
|
73
79
|
return resultado(threadId, 'ja-registrada', 'esta entrega ja tem ship_done', merge);
|
|
74
80
|
// A ponta do remoto AGORA, e o merge dentro dela: e o que torna o push provado, nao presumido.
|
|
75
|
-
const remotoAgora = (0, util_1.exec)('git', ['ls-remote', remoto, `refs/heads/${base}`], raiz);
|
|
81
|
+
const remotoAgora = (0, util_1.exec)('git', ['ls-remote', '--', remoto, `refs/heads/${base}`], raiz);
|
|
76
82
|
const ponta = remotoAgora.ok ? remotoAgora.stdout.split('\t')[0].trim() : '';
|
|
77
83
|
if (!ponta || !(0, util_1.exec)('git', ['merge-base', '--is-ancestor', merge.mergeSha, ponta], raiz).ok) {
|
|
78
84
|
return resultado(threadId, 'recusada', `o merge ${merge.mergeSha.slice(0, 7)} nao esta na ponta de ${remoto}/${base}`, merge);
|
|
@@ -90,6 +96,9 @@ function registrarEntregaPorPr(carregado, threadId, opcoes = {}) {
|
|
|
90
96
|
para: base,
|
|
91
97
|
shaDe: merge.headSha,
|
|
92
98
|
mergeSha: merge.mergeSha,
|
|
99
|
+
// RM-037 (fatia 5, A1): a ponta que o ls-remote provou vai em campo proprio; o recibo do Maestro confere o push
|
|
100
|
+
// contra ela quando a base andou depois do merge.
|
|
101
|
+
pontaDaBase: ponta,
|
|
93
102
|
jaIncorporado: true,
|
|
94
103
|
remoto,
|
|
95
104
|
shaRemoto: ponta,
|
|
@@ -189,6 +198,9 @@ function registrarEntregaExternaPorPr(carregado, threadId, opcoes) {
|
|
|
189
198
|
url: pr.html_url ?? `https://github.com/${repo}/pull/${n}`,
|
|
190
199
|
shaDe: headSha,
|
|
191
200
|
mergeSha,
|
|
201
|
+
// RM-037 (fatia 5, A1; aviso da rodada 1 do CHECK): a ponta conferida vai em campo proprio, como no PR local; a
|
|
202
|
+
// comparacao aceita `ahead`, e o recibo do Maestro confere o push contra ela.
|
|
203
|
+
pontaDaBase: ponta,
|
|
192
204
|
jaIncorporado: true,
|
|
193
205
|
remoto: `github:${repo}`,
|
|
194
206
|
shaRemoto: ponta,
|
|
@@ -207,9 +219,9 @@ function registrarEntregaExternaPorPr(carregado, threadId, opcoes) {
|
|
|
207
219
|
}
|
|
208
220
|
/** `ork ship registrar-pr --todas`: toda thread aberta que ja tem merge `ship(<thread>)` na base. */
|
|
209
221
|
function registrarEntregasPorPr(carregado, opcoes = {}) {
|
|
210
|
-
const remoto = opcoes.remoto ?? 'origin';
|
|
222
|
+
const remoto = (0, branch_de_estado_1.exigirRemoto)(opcoes.remoto ?? 'origin', 'ship');
|
|
211
223
|
const base = carregado.manifesto.worktree.base_branch;
|
|
212
|
-
(0, util_1.exec)('git', ['fetch', '-q', remoto, `+refs/heads/${base}:refs/remotes/${remoto}/${base}`], carregado.raiz);
|
|
224
|
+
(0, util_1.exec)('git', ['fetch', '-q', '--', remoto, `+refs/heads/${base}:refs/remotes/${remoto}/${base}`], carregado.raiz);
|
|
213
225
|
const r = (0, thread_1.listarIds)(carregado.raiz)
|
|
214
226
|
.filter((id) => (0, thread_1.lerThread)(carregado.raiz, id).status !== 'fechada')
|
|
215
227
|
.filter((id) => mergeDaEntrega(carregado.raiz, id, remoto, base) !== null)
|