@orkastery/cli 0.5.3 → 0.5.6
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 +158 -0
- package/adapters/claude-code/mods/autoridade.json +56 -0
- package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
- package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
- package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
- package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
- package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
- package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
- package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
- package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
- package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
- package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
- package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
- package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
- package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
- package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
- package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
- package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
- package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
- package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
- package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
- package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
- package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
- package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
- package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
- package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
- package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
- package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
- package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
- package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
- package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
- package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
- package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
- package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
- package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +1 -1
- package/adapters/openclaw/README.md +2 -1
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
- package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
- package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
- package/assets/docs-en/produto/README.md +14 -0
- package/assets/docs-en/produto/_modelo-feature.md +62 -0
- package/assets/docs-en/roadmap/README.md +14 -0
- package/assets/docs-en/roadmap/_modelo-item.md +75 -0
- package/dist/adapters/claude-bg.js +77 -13
- package/dist/adapters/codex.js +10 -1
- package/dist/agents-md.js +24 -15
- package/dist/auditrun.js +17 -2
- package/dist/board.js +4 -3
- package/dist/branch-de-estado.js +23 -1
- package/dist/catalogo.js +33 -0
- package/dist/ci.js +13 -7
- package/dist/claims-conferir.js +342 -0
- package/dist/claims.js +3 -1
- package/dist/company-brain-client.js +36 -1
- package/dist/company-brain-journal.js +2 -1
- package/dist/company-brain-migration.js +36 -1
- package/dist/conducao-sentinela.js +388 -0
- package/dist/conducao-texto.js +12 -18
- package/dist/conducao.js +122 -30
- package/dist/conhecimento.js +490 -0
- package/dist/docs.js +22 -8
- package/dist/doctor-pulse-cron.js +182 -27
- package/dist/doctor-rede.js +18 -17
- package/dist/doctor.js +115 -111
- package/dist/entrega-pr.js +22 -21
- package/dist/escopo-escrita.js +10 -1
- package/dist/estado-thread.js +23 -1
- package/dist/experiencia-instalacao.js +45 -25
- package/dist/fabrica-batida.js +310 -0
- package/dist/fabrica-estado.js +38 -8
- package/dist/fabrica-publicar.js +3 -1
- package/dist/fila-pesada.js +444 -0
- package/dist/fix.js +3 -2
- package/dist/forja.js +1 -1
- package/dist/gates.js +3 -28
- package/dist/handoff.js +10 -6
- package/dist/hitl-local-receipt.js +2 -0
- package/dist/hitl-resumo.js +29 -3
- package/dist/hitl-tempo-parado.js +4 -4
- package/dist/hitl.js +29 -33
- package/dist/horario.js +14 -7
- package/dist/hosts.js +52 -1
- package/dist/impedimento.js +108 -14
- package/dist/index.js +623 -521
- package/dist/indice.js +7 -1
- package/dist/init.js +43 -47
- package/dist/instabilidade.js +144 -0
- package/dist/integracoes-locais.js +2 -0
- package/dist/intelligence-graph-cli.js +92 -21
- package/dist/intelligence-graph-contexto.js +56 -17
- package/dist/intelligence-graph-contract.js +2 -1
- package/dist/intelligence-graph-extract-md.js +56 -4
- package/dist/intelligence-graph-extract-ts.js +71 -3
- package/dist/intelligence-graph-query.js +66 -19
- package/dist/ledger.js +15 -1
- package/dist/liveness.js +6 -3
- package/dist/locale-ajuda.js +761 -0
- package/dist/locale-gerados.js +160 -0
- package/dist/locale-master.js +99 -0
- package/dist/locale-onboarding.js +92 -0
- package/dist/locale-phase.js +151 -0
- package/dist/locale-pulse.js +211 -0
- package/dist/locale-retry.js +385 -0
- package/dist/locale-roadmap.js +102 -0
- package/dist/locale-ship.js +494 -0
- package/dist/locale-thread.js +277 -0
- package/dist/locale-verify.js +125 -0
- package/dist/locale.js +714 -0
- package/dist/manifest.js +129 -3
- package/dist/maquina.js +23 -4
- package/dist/master-digest.js +6 -1
- package/dist/master-nota.js +4 -6
- package/dist/master.js +21 -24
- package/dist/mcp-artifacts.js +11 -2
- package/dist/mcp-git.js +23 -6
- package/dist/mcp-grafo.js +7 -4
- package/dist/mcp-server.js +8 -2
- package/dist/mcp-ship.js +3 -1
- package/dist/mcp-verify.js +6 -1
- package/dist/modos.js +3 -6
- package/dist/network-roadmap.js +5 -2
- package/dist/noctum-arco.js +911 -0
- package/dist/noctum-capacidade.js +141 -0
- package/dist/noctum-envelope.js +810 -0
- package/dist/noctum-execucao.js +304 -0
- package/dist/noctum-fila.js +280 -0
- package/dist/ocupacao.js +29 -2
- package/dist/onboarding.js +40 -21
- package/dist/orkmind.js +9 -2
- package/dist/orquestracao.js +13 -12
- package/dist/parado-no-condutor.js +34 -9
- package/dist/phase.js +94 -39
- package/dist/policies.js +4 -4
- package/dist/portfolio.js +4 -2
- package/dist/postura-local.js +234 -0
- package/dist/preflight.js +11 -10
- package/dist/procedencia.js +225 -0
- package/dist/projeto-alvo.js +127 -4
- package/dist/prompts.js +6 -2
- package/dist/pulse-delivery.js +13 -2
- package/dist/pulse.js +52 -19
- package/dist/ratelimit.js +4 -2
- package/dist/redacao-saida.js +63 -0
- package/dist/rede-status.js +3 -2
- package/dist/retry.js +232 -148
- package/dist/roadmap-reservas.js +20 -3
- package/dist/roadmap-status.js +129 -33
- package/dist/runtime-context.js +181 -3
- package/dist/runtimes.js +2 -1
- package/dist/session-events.js +7 -3
- package/dist/session-watcher-claude.js +7 -1
- package/dist/session-watcher.js +185 -33
- package/dist/sessoes-contas.js +1 -1
- package/dist/ship-publicar.js +800 -0
- package/dist/ship.js +84 -81
- package/dist/steal.js +77 -0
- package/dist/thread-close.js +3 -2
- package/dist/thread.js +153 -82
- package/dist/util.js +8 -1
- package/dist/verify.js +141 -52
- package/dist/vida-da-thread.js +254 -0
- package/dist/worktree-local.js +165 -0
- package/dist/worktree.js +20 -0
- package/dist/yaml.js +27 -8
- package/package.json +1 -1
- package/schemas/code-artifact-graph.v1.schema.json +2 -1
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* pulse configurado (`.orkastery/monitor/pulse-host.json`), o doctor le o `crontab -l` e avisa,
|
|
8
8
|
* sem bloquear, quando a linha da varredura falta ou bate mais devagar que o template
|
|
9
9
|
* `monitor/pulse.cron`. O doctor nunca edita o crontab: a correcao traz a linha pronta.
|
|
10
|
+
*
|
|
11
|
+
* RM-063 (F1): com thread aberta no projeto, a falta da batida REPROVA, com ou sem `pulse-host.json`.
|
|
12
|
+
* Sem transporte o doctor calava, e o maquina-b ficou de 03/10 a 12/10/2026 sem varredura nenhuma. A
|
|
13
|
+
* correcao e o `ork fabrica batida instalar`, que instala a linha do template de forma idempotente.
|
|
10
14
|
*/
|
|
11
15
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
16
|
if (k2 === undefined) k2 = k;
|
|
@@ -42,16 +46,27 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
42
46
|
};
|
|
43
47
|
})();
|
|
44
48
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.COMANDO_DO_TEMPLATE = exports.SCRIPT_DA_VARREDURA = exports.BATIDA_DO_TEMPLATE = void 0;
|
|
49
|
+
exports.COMANDO_DE_INSTALAR_A_BATIDA = exports.ATRASO_DA_BATIDA_MIN = exports.COMANDO_DO_TEMPLATE = exports.SCRIPT_DA_VARREDURA = exports.BATIDA_DO_TEMPLATE = void 0;
|
|
46
50
|
exports.lerCrontabDoSistema = lerCrontabDoSistema;
|
|
47
51
|
exports.intervaloEmMinutos = intervaloEmMinutos;
|
|
48
|
-
exports.
|
|
52
|
+
exports.valorNoShell = valorNoShell;
|
|
53
|
+
exports.projetoDaLinha = projetoDaLinha;
|
|
54
|
+
exports.scriptsDaLinha = scriptsDaLinha;
|
|
55
|
+
exports.entradasDaVarredura = entradasDaVarredura;
|
|
56
|
+
exports.entradaDoProjeto = entradaDoProjeto;
|
|
57
|
+
exports.mesmoCaminho = mesmoCaminho;
|
|
58
|
+
exports.entradaNaoEDeOutro = entradaNaoEDeOutro;
|
|
59
|
+
exports.ultimaRodadaDaVarredura = ultimaRodadaDaVarredura;
|
|
60
|
+
exports.threadsAbertasNoEstado = threadsAbertasNoEstado;
|
|
61
|
+
exports.citarNoShell = citarNoShell;
|
|
49
62
|
exports.scriptDaVarreduraDoOrk = scriptDaVarreduraDoOrk;
|
|
50
63
|
exports.comandoDaVarredura = comandoDaVarredura;
|
|
51
64
|
exports.checarCronDoPulse = checarCronDoPulse;
|
|
52
65
|
const fs = __importStar(require("node:fs"));
|
|
66
|
+
const os = __importStar(require("node:os"));
|
|
53
67
|
const path = __importStar(require("node:path"));
|
|
54
68
|
const util_1 = require("./util");
|
|
69
|
+
const locale_1 = require("./locale");
|
|
55
70
|
/** A batida do template `monitor/pulse.cron` (I-50): a menor cadencia das tags. */
|
|
56
71
|
exports.BATIDA_DO_TEMPLATE = '*/15 * * * *';
|
|
57
72
|
/** O script que o template agenda; a linha do crontab e achada por ele. */
|
|
@@ -64,9 +79,12 @@ function lerCrontabDoSistema() {
|
|
|
64
79
|
if (r.ok)
|
|
65
80
|
return { ok: true, texto: r.stdout };
|
|
66
81
|
if (r.error === 'ENOENT')
|
|
67
|
-
return { ok: false, motivo:
|
|
68
|
-
|
|
69
|
-
|
|
82
|
+
return { ok: false, motivo: (0, locale_1.msg)().doctor.cronSemComando };
|
|
83
|
+
// RM-063 (F1): o usuario sem crontab tem um crontab vazio, nao uma leitura que falhou; e o caso da maquina nova.
|
|
84
|
+
if (/no crontab for /i.test(`${r.stderr}${r.stdout}`))
|
|
85
|
+
return { ok: true, texto: '' };
|
|
86
|
+
const primeira = (r.stderr || r.stdout).trim().split('\n')[0] ?? '';
|
|
87
|
+
return { ok: false, motivo: primeira ? (0, locale_1.msg)().doctor.cronFalhou(primeira) : (0, locale_1.msg)().doctor.cronSaiu(r.code) };
|
|
70
88
|
}
|
|
71
89
|
const MACROS = { '@hourly': 60, '@daily': 1440, '@midnight': 1440, '@weekly': 10080,
|
|
72
90
|
'@monthly': 43200, '@yearly': 525600, '@annually': 525600 };
|
|
@@ -124,13 +142,140 @@ function dividirLinha(linha) {
|
|
|
124
142
|
const m = /^(\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.+)$/.exec(t);
|
|
125
143
|
return m ? { quando: m[1], comando: m[2] } : null;
|
|
126
144
|
}
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
145
|
+
/**
|
|
146
|
+
* RM-063 (F1, GO-FIX): um valor como o `sh` do cron o le: aspas simples literais; aspas duplas com `$HOME`; sem aspas,
|
|
147
|
+
* com o `~` do comeco e `$HOME`. So o que a linha da varredura usa; o resto fica como esta.
|
|
148
|
+
*/
|
|
149
|
+
function valorNoShell(bruto, home = os.homedir()) {
|
|
150
|
+
const comHome = (v) => v.replace(/\$\{HOME\}|\$HOME(?![A-Za-z0-9_])/g, home);
|
|
151
|
+
if (bruto.length >= 2 && bruto.startsWith(`'`) && bruto.endsWith(`'`))
|
|
152
|
+
return bruto.slice(1, -1).replace(/'\\''/g, `'`);
|
|
153
|
+
if (bruto.length >= 2 && bruto.startsWith('"') && bruto.endsWith('"'))
|
|
154
|
+
return comHome(bruto.slice(1, -1).replace(/\\(["\\$`])/g, '$1'));
|
|
155
|
+
return comHome(bruto === '~' ? home : bruto.startsWith('~/') ? home + bruto.slice(1) : bruto);
|
|
156
|
+
}
|
|
157
|
+
/** Um valor de atribuicao ou um caminho: entre aspas simples, entre aspas duplas, ou ate o espaco. */
|
|
158
|
+
const VALOR = String.raw `(?:'(?:[^']|'\\'')*'|"(?:[^"\\]|\\.)*"|[^\s;&|<>()]+)`;
|
|
159
|
+
/** O valor de `ORK_PULSE_PROJECT=` na linha, como o `sh` o le; `null` quando a linha nao o diz. */
|
|
160
|
+
function projetoDaLinha(linha, home = os.homedir()) {
|
|
161
|
+
const m = new RegExp(`(?:^|\\s)ORK_PULSE_PROJECT=(${VALOR})`).exec(linha);
|
|
162
|
+
return m ? valorNoShell(m[1], home) : null;
|
|
163
|
+
}
|
|
164
|
+
/** Os scripts da varredura citados na linha, como o `sh` os le; `varredura-pulse.sh.bak` nao e o script. */
|
|
165
|
+
function scriptsDaLinha(linha, home = os.homedir()) {
|
|
166
|
+
const nome = exports.SCRIPT_DA_VARREDURA.replace(/\./g, '\\.');
|
|
167
|
+
const re = new RegExp(`(?:^|[\\s=])('[^']*${nome}'|"[^"]*${nome}"|[^\\s'";&|<>()]*${nome})(?=$|[\\s;&|<>)])`, 'g');
|
|
168
|
+
return [...linha.matchAll(re)].map((m) => valorNoShell(m[1], home));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* RM-063 (F1, GO-FIX): as entradas da varredura, na ordem. A linha de ambiente do crontab (`NOME=valor`) vale para as
|
|
172
|
+
* entradas que vem depois dela: o template sem `ORK_PULSE_PROJECT` abaixo de `ORK_PULSE_PROJECT=/outro` varre o outro.
|
|
173
|
+
*/
|
|
174
|
+
function entradasDaVarredura(crontab, home = os.homedir()) {
|
|
175
|
+
const ambiente = {};
|
|
176
|
+
const entradas = [];
|
|
177
|
+
for (const linha of crontab.split('\n')) {
|
|
178
|
+
const t = linha.trim();
|
|
179
|
+
if (!t || t.startsWith('#'))
|
|
180
|
+
continue;
|
|
181
|
+
const env = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(t);
|
|
182
|
+
if (env) {
|
|
183
|
+
ambiente[env[1]] = valorNoShell(env[2].trim(), ambiente.HOME ?? home);
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const casa = ambiente.HOME ?? home;
|
|
187
|
+
const scripts = scriptsDaLinha(t, casa);
|
|
188
|
+
if (!scripts.length)
|
|
189
|
+
continue;
|
|
190
|
+
entradas.push({ linha, projeto: projetoDaLinha(t, casa) ?? ambiente.ORK_PULSE_PROJECT ?? null, scripts });
|
|
191
|
+
}
|
|
192
|
+
return entradas;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* RM-063 (F1): a entrada roda, com certeza, a varredura DESTE projeto: o `ORK_PULSE_PROJECT` efetivo e ele, ou nao ha
|
|
196
|
+
* projeto nenhum e o script e o do proprio checkout (que entao e o alvo, como no template).
|
|
197
|
+
*/
|
|
198
|
+
function entradaDoProjeto(e, raiz) {
|
|
199
|
+
if (e.projeto !== null)
|
|
200
|
+
return mesmoCaminho(e.projeto, raiz);
|
|
201
|
+
const doCheckout = path.join(raiz, 'monitor', exports.SCRIPT_DA_VARREDURA);
|
|
202
|
+
return e.scripts.some((s) => mesmoCaminho(s, doCheckout));
|
|
203
|
+
}
|
|
204
|
+
/** O mesmo caminho, escrito igual ou pelo mesmo destino real. */
|
|
205
|
+
function mesmoCaminho(a, b) {
|
|
206
|
+
if (path.resolve(a) === path.resolve(b))
|
|
207
|
+
return true;
|
|
208
|
+
try {
|
|
209
|
+
return fs.realpathSync(a) === fs.realpathSync(b);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
131
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* A entrada vale para o aviso de cadencia (sem thread aberta) quando nao aponta OUTRO projeto: a linha antiga do
|
|
217
|
+
* template, sem projeto, continua valendo como na RM-039.
|
|
218
|
+
*/
|
|
219
|
+
function entradaNaoEDeOutro(e, raiz) {
|
|
220
|
+
return e.projeto === null || mesmoCaminho(e.projeto, raiz);
|
|
221
|
+
}
|
|
222
|
+
/** Acima disto sem rodada nova no `hitl.log`, a batida esta atrasada: duas batidas do template perdidas. */
|
|
223
|
+
exports.ATRASO_DA_BATIDA_MIN = 30;
|
|
224
|
+
function ultimaRodadaDaVarredura(dirMonitor) {
|
|
225
|
+
const arquivo = path.join(dirMonitor, 'hitl.log');
|
|
226
|
+
let texto;
|
|
227
|
+
try {
|
|
228
|
+
const fd = fs.openSync(arquivo, 'r');
|
|
229
|
+
try {
|
|
230
|
+
const tamanho = fs.fstatSync(fd).size, lido = Math.min(tamanho, 64 * 1024);
|
|
231
|
+
const buffer = Buffer.alloc(lido);
|
|
232
|
+
fs.readSync(fd, buffer, 0, lido, tamanho - lido);
|
|
233
|
+
texto = buffer.toString('utf8');
|
|
234
|
+
}
|
|
235
|
+
finally {
|
|
236
|
+
fs.closeSync(fd);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
for (const linha of texto.split('\n').reverse()) {
|
|
243
|
+
try {
|
|
244
|
+
const e = JSON.parse(linha);
|
|
245
|
+
if (e.tipo !== 'pulse_scan' || typeof e.ts !== 'string' || !Number.isFinite(Date.parse(e.ts)))
|
|
246
|
+
continue;
|
|
247
|
+
return { em: e.ts, code: typeof e.code === 'number' ? e.code : null, detalhe: typeof e.detalhe === 'string' ? e.detalhe : '' };
|
|
248
|
+
}
|
|
249
|
+
catch { /* linha cortada no inicio do trecho, ou ilegivel */ }
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
/** RM-063 (F1): threads nao fechadas no estado do projeto (`.orkastery/threads/<id>/thread.json`). */
|
|
254
|
+
function threadsAbertasNoEstado(dirEstado) {
|
|
255
|
+
const dir = path.join(dirEstado, 'threads');
|
|
256
|
+
let nomes;
|
|
257
|
+
try {
|
|
258
|
+
nomes = fs.readdirSync(dir);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
let abertas = 0;
|
|
264
|
+
for (const nome of nomes) {
|
|
265
|
+
try {
|
|
266
|
+
const t = JSON.parse(fs.readFileSync(path.join(dir, nome, 'thread.json'), 'utf8'));
|
|
267
|
+
// O registro de adocao nao tem trabalho a conduzir; a thread pausada espera o dono, e a batida e quem o lembra.
|
|
268
|
+
if (t.status !== 'fechada' && t.origem !== 'adocao')
|
|
269
|
+
abertas++;
|
|
270
|
+
}
|
|
271
|
+
catch { /* pasta sem thread.json, ou ilegivel: nao e thread a vigiar */ }
|
|
272
|
+
}
|
|
273
|
+
return abertas;
|
|
274
|
+
}
|
|
275
|
+
/** O comando que instala a batida; e a correcao do doctor quando ela falta (RM-063, F1). */
|
|
276
|
+
exports.COMANDO_DE_INSTALAR_A_BATIDA = 'ork fabrica batida instalar';
|
|
132
277
|
/** Aspas de shell so quando o caminho precisa (a linha vai colada no crontab, que roda por `sh`). */
|
|
133
|
-
function
|
|
278
|
+
function citarNoShell(caminho) {
|
|
134
279
|
return /^[A-Za-z0-9_./:@+-]+$/.test(caminho) ? caminho : `'${caminho.replace(/'/g, `'\\''`)}'`;
|
|
135
280
|
}
|
|
136
281
|
/**
|
|
@@ -154,27 +299,40 @@ function scriptDaVarreduraDoOrk(dirDoDist = __dirname) {
|
|
|
154
299
|
function comandoDaVarredura(raizDoProjeto, scriptDoOrk = scriptDaVarreduraDoOrk()) {
|
|
155
300
|
const doProjeto = path.join(raizDoProjeto, 'monitor', exports.SCRIPT_DA_VARREDURA);
|
|
156
301
|
if (fs.existsSync(doProjeto) || !scriptDoOrk)
|
|
157
|
-
return
|
|
158
|
-
return `ORK_PULSE_PROJECT=${
|
|
302
|
+
return citarNoShell(doProjeto);
|
|
303
|
+
return `ORK_PULSE_PROJECT=${citarNoShell(raizDoProjeto)} ${citarNoShell(scriptDoOrk)}`;
|
|
159
304
|
}
|
|
160
305
|
/**
|
|
161
|
-
* Check "cadencia do pulse no cron". `null` quando o projeto nao tem transporte do pulse
|
|
162
|
-
* `pulse-host.json`
|
|
306
|
+
* Check "cadencia do pulse no cron". `null` quando o projeto nao tem transporte do pulse nem thread
|
|
307
|
+
* aberta: sem `pulse-host.json` e sem thread a vigiar, o doctor nao fala de cron.
|
|
308
|
+
*
|
|
309
|
+
* RM-063 (F1): com thread aberta (`abertas`, contadas no estado ao lado de `dirMonitor`), a falta da
|
|
310
|
+
* batida reprova, com ou sem transporte, e a correcao e o `ork fabrica batida instalar`.
|
|
163
311
|
*/
|
|
164
|
-
function checarCronDoPulse(dirMonitor, raizDoCheckout, ler = lerCrontabDoSistema, scriptDoOrk = scriptDaVarreduraDoOrk()) {
|
|
165
|
-
|
|
312
|
+
function checarCronDoPulse(dirMonitor, raizDoCheckout, ler = lerCrontabDoSistema, scriptDoOrk = scriptDaVarreduraDoOrk(), abertas = threadsAbertasNoEstado(path.dirname(dirMonitor))) {
|
|
313
|
+
const comHost = fs.existsSync(path.join(dirMonitor, 'pulse-host.json'));
|
|
314
|
+
if (!comHost && abertas === 0)
|
|
166
315
|
return null;
|
|
167
316
|
const nome = 'cadencia do pulse no cron';
|
|
168
317
|
const comandoSugerido = comandoDaVarredura(raizDoCheckout, scriptDoOrk);
|
|
169
318
|
const linhaNova = (comando) => `${exports.BATIDA_DO_TEMPLATE} ${comando}`;
|
|
170
|
-
const ausente = (detalhe) =>
|
|
171
|
-
|
|
319
|
+
const ausente = (detalhe) => abertas > 0
|
|
320
|
+
? { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.batidaAusente(abertas, detalhe),
|
|
321
|
+
correcao: (0, locale_1.msg)().doctor.batidaInstale(exports.COMANDO_DE_INSTALAR_A_BATIDA) }
|
|
322
|
+
: { nome, nivel: 'warn', detalhe, correcao: (0, locale_1.msg)().doctor.cronAdicione(linhaNova(comandoSugerido)) };
|
|
323
|
+
// RM-063 (F1, GO-FIX): a varredura que bate por outro agendador (timer do systemd, batida do host) se prova pelo hitl.log.
|
|
324
|
+
const rodada = ultimaRodadaDaVarredura(dirMonitor);
|
|
325
|
+
const haMin = rodada ? Math.floor((Date.now() - Date.parse(rodada.em)) / 60000) : null;
|
|
326
|
+
const semCron = (detalhe) => haMin !== null && haMin >= 0 && haMin <= exports.ATRASO_DA_BATIDA_MIN
|
|
327
|
+
? { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.batidaPeloLog(haMin) } : ausente(detalhe);
|
|
172
328
|
const leitura = ler();
|
|
173
329
|
if (!leitura.ok)
|
|
174
|
-
return
|
|
175
|
-
|
|
330
|
+
return semCron(comHost ? (0, locale_1.msg)().doctor.cronSemLeitura(leitura.motivo) : (0, locale_1.msg)().doctor.batidaSemLeitura(leitura.motivo));
|
|
331
|
+
// Com thread aberta, so a batida DESTE projeto; sem thread, o aviso de cadencia aceita a linha antiga sem projeto.
|
|
332
|
+
const linhas = entradasDaVarredura(leitura.texto)
|
|
333
|
+
.filter(e => abertas > 0 ? entradaDoProjeto(e, raizDoCheckout) : entradaNaoEDeOutro(e, raizDoCheckout)).map(e => e.linha.trim());
|
|
176
334
|
if (linhas.length === 0)
|
|
177
|
-
return
|
|
335
|
+
return semCron(comHost ? (0, locale_1.msg)().doctor.cronSemLinha(exports.SCRIPT_DA_VARREDURA) : (0, locale_1.msg)().doctor.batidaSemLinha(exports.SCRIPT_DA_VARREDURA));
|
|
178
336
|
const lentas = [];
|
|
179
337
|
for (const linha of linhas) {
|
|
180
338
|
const partes = dividirLinha(linha);
|
|
@@ -183,12 +341,9 @@ function checarCronDoPulse(dirMonitor, raizDoCheckout, ler = lerCrontabDoSistema
|
|
|
183
341
|
lentas.push({ linha, comando: partes?.comando ?? comandoSugerido, intervalo });
|
|
184
342
|
}
|
|
185
343
|
if (lentas.length < linhas.length) {
|
|
186
|
-
return { nome, nivel: 'ok', detalhe:
|
|
344
|
+
return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.cronOk(linhas.length) };
|
|
187
345
|
}
|
|
188
346
|
const l = lentas[0];
|
|
189
|
-
|
|
190
|
-
:
|
|
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)}` };
|
|
347
|
+
return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.cronLento((0, locale_1.msg)().doctor.cronRitmo(l.intervalo), l.linha),
|
|
348
|
+
correcao: (0, locale_1.msg)().doctor.cronTroque(linhaNova(l.comando)) };
|
|
194
349
|
}
|
package/dist/doctor-rede.js
CHANGED
|
@@ -41,7 +41,7 @@ exports.checarRede = checarRede;
|
|
|
41
41
|
* RM-053 (fatia 2): o check "rede" do `ork doctor`.
|
|
42
42
|
*
|
|
43
43
|
* A rede pessoal publica sozinha (batida do pulse e eventos de thread) e so deixava rastro em
|
|
44
|
-
* `~/.orkastery/rede/rede.log`: a
|
|
44
|
+
* `~/.orkastery/rede/rede.log`: a maquina-b ficou de 02/10 em diante como membro herdado da fabrica,
|
|
45
45
|
* com toda publicacao caindo em `rede.sem-repositorio`, e o doctor dizia PRONTO sem uma palavra.
|
|
46
46
|
*
|
|
47
47
|
* O check diz a adesao, a casa, a ultima batida publicada e a ultima falha do log. Ele so le
|
|
@@ -56,6 +56,7 @@ const rede_1 = require("./rede");
|
|
|
56
56
|
const rede_adesao_1 = require("./rede-adesao");
|
|
57
57
|
const rede_status_1 = require("./rede-status");
|
|
58
58
|
const saida_segura_1 = require("./saida-segura");
|
|
59
|
+
const locale_1 = require("./locale");
|
|
59
60
|
/** O fim do `rede.log` que o doctor le: o log so cresce, e o que importa e o mais recente. */
|
|
60
61
|
exports.CAUDA_DO_LOG_BYTES = 64 * 1024;
|
|
61
62
|
/** As linhas legiveis do fim do `rede.log`, da mais antiga para a mais nova. Sem log, lista vazia. */
|
|
@@ -102,16 +103,16 @@ const curto = (s, teto = 200) => {
|
|
|
102
103
|
/** A correcao pela familia do erro da ultima falha (o prefixo tipado, como `rede.sem-repositorio`). */
|
|
103
104
|
function correcaoDaFalha(erro) {
|
|
104
105
|
const codigo = /^([a-z]+\.[a-z-]+):/.exec(erro)?.[1] ?? '';
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
const m = (0, locale_1.msg)().doctor;
|
|
107
|
+
if (codigo === 'rede.sem-repositorio' || codigo === 'rede.repositorio-alheio')
|
|
108
|
+
return m.redeSemCasaCorrecao;
|
|
108
109
|
if (codigo === 'rede.sem-forja')
|
|
109
|
-
return
|
|
110
|
+
return m.redeSemForjaCorrecao;
|
|
110
111
|
if (codigo === 'rede.repositorio-publico')
|
|
111
|
-
return
|
|
112
|
+
return m.redePublicaCorrecao;
|
|
112
113
|
if (codigo === 'rede.nome-em-uso')
|
|
113
|
-
return
|
|
114
|
-
return
|
|
114
|
+
return m.redeNomeCorrecao;
|
|
115
|
+
return m.redeOutraCorrecao;
|
|
115
116
|
}
|
|
116
117
|
/** O check "rede". `agoraMs` e o log ficam injetaveis para o teste. */
|
|
117
118
|
function checarRede(opcoes = {}) {
|
|
@@ -120,8 +121,8 @@ function checarRede(opcoes = {}) {
|
|
|
120
121
|
const adesao = (0, rede_adesao_1.adesaoDaRede)();
|
|
121
122
|
if (!adesao.membro) {
|
|
122
123
|
return { nome, nivel: 'ok', detalhe: adesao.config && !adesao.config.membro
|
|
123
|
-
?
|
|
124
|
-
:
|
|
124
|
+
? (0, locale_1.msg)().doctor.redeSaiu
|
|
125
|
+
: (0, locale_1.msg)().doctor.foraDaRede };
|
|
125
126
|
}
|
|
126
127
|
const marca = (0, rede_1.lerMarcaDaRede)();
|
|
127
128
|
const config = adesao.config;
|
|
@@ -131,19 +132,19 @@ function checarRede(opcoes = {}) {
|
|
|
131
132
|
const falha = [...registros].reverse().find((r) => r.acao === 'falhou') ?? null;
|
|
132
133
|
const emBatida = marca && typeof marca.em === 'string' && Number.isFinite(Date.parse(marca.em)) ? marca.em : null;
|
|
133
134
|
const idade = emBatida ? agora - Date.parse(emBatida) : NaN;
|
|
135
|
+
const m = (0, locale_1.msg)().doctor;
|
|
134
136
|
const partes = [
|
|
135
|
-
adesao.adesao === 'fabrica' ?
|
|
136
|
-
casa ?
|
|
137
|
-
emBatida ?
|
|
138
|
-
falha ?
|
|
139
|
-
:
|
|
137
|
+
adesao.adesao === 'fabrica' ? m.redeMembroHerdado : m.redeMembro,
|
|
138
|
+
casa ? m.redeCasa(curto(casa, 120)) : m.redeSemCasa,
|
|
139
|
+
emBatida ? m.redeBatida((0, horario_1.formatarDataHora)(emBatida), (0, rede_status_1.duracao)(idade)) : m.redeSemBatida,
|
|
140
|
+
falha ? m.redeFalha((0, horario_1.formatarDataHora)(falha.ts), falha.origem ? curto(falha.origem, 20) : null, curto(falha.erro ?? m.redeSemDetalhe))
|
|
141
|
+
: m.redeSemFalha,
|
|
140
142
|
];
|
|
141
143
|
// A falha mais nova que a ultima batida e o estado de agora; a de antes ja passou.
|
|
142
144
|
const falhaAtual = !!falha && (!emBatida || Date.parse(falha.ts) > Date.parse(emBatida));
|
|
143
145
|
const parada = !emBatida || !(idade <= rede_status_1.SEM_BATIDA_MS);
|
|
144
146
|
if (!falhaAtual && !parada)
|
|
145
147
|
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
|
+
const correcao = falhaAtual ? correcaoDaFalha(falha.erro ?? '') : m.redeParadaCorrecao;
|
|
148
149
|
return { nome, nivel: 'warn', detalhe: partes.join('; '), correcao };
|
|
149
150
|
}
|