@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
package/dist/manifest.js
CHANGED
|
@@ -37,7 +37,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
37
37
|
};
|
|
38
38
|
})();
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.EMBEDDING_PADRAO = exports.LIMITE_MANIFESTO_BYTES = exports.DIR_ESTADO = exports.NOME_MANIFESTO_LEGADO = exports.NOME_MANIFESTO = void 0;
|
|
40
|
+
exports.EMBEDDING_PADRAO = exports.TETO_MAXIMO_DE_CUSTO_USD = exports.TETO_MAXIMO_DE_TEAMMATES = exports.LIMITE_MANIFESTO_BYTES = exports.DIR_ESTADO = exports.NOME_MANIFESTO_LEGADO = exports.NOME_MANIFESTO = void 0;
|
|
41
41
|
exports.fixarDiretorioDoProjeto = fixarDiretorioDoProjeto;
|
|
42
42
|
exports.diretorioDoProjeto = diretorioDoProjeto;
|
|
43
43
|
exports.acharRaiz = acharRaiz;
|
|
@@ -45,6 +45,8 @@ exports.dirEstado = dirEstado;
|
|
|
45
45
|
exports.validarOptInPlaybook = validarOptInPlaybook;
|
|
46
46
|
exports.configDeEmbedding = configDeEmbedding;
|
|
47
47
|
exports.carregarManifesto = carregarManifesto;
|
|
48
|
+
exports.cliDaMemoriaValido = cliDaMemoriaValido;
|
|
49
|
+
exports.comandosDoTextoDoManifesto = comandosDoTextoDoManifesto;
|
|
48
50
|
exports.exigirManifesto = exigirManifesto;
|
|
49
51
|
const fs = __importStar(require("node:fs"));
|
|
50
52
|
const path = __importStar(require("node:path"));
|
|
@@ -59,6 +61,8 @@ const horario_1 = require("./horario");
|
|
|
59
61
|
const experiencia_1 = require("./experiencia");
|
|
60
62
|
const runtime_ambiente_1 = require("./runtime-ambiente");
|
|
61
63
|
const orkmind_1 = require("./orkmind");
|
|
64
|
+
const locale_1 = require("./locale");
|
|
65
|
+
const branch_de_estado_1 = require("./branch-de-estado");
|
|
62
66
|
exports.NOME_MANIFESTO = 'orkastery.yaml';
|
|
63
67
|
exports.NOME_MANIFESTO_LEGADO = 'devmaster.yaml';
|
|
64
68
|
exports.DIR_ESTADO = '.orkastery';
|
|
@@ -91,7 +95,12 @@ function acharRaiz(dirInicial = diretorioDoProjeto()) {
|
|
|
91
95
|
}
|
|
92
96
|
/** Caminho do diretorio de estado da raiz informada. */
|
|
93
97
|
function dirEstado(raiz) {
|
|
94
|
-
|
|
98
|
+
// RM-047 (fronteira de confiança): `.orkastery` versionado como link levaria o estado para fora da raiz.
|
|
99
|
+
const dir = path.join(raiz, exports.DIR_ESTADO);
|
|
100
|
+
if (fs.lstatSync(dir, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
101
|
+
throw new Error(`estado.link: ${exports.DIR_ESTADO} é link simbólico; o estado do ork fica numa pasta de verdade dentro da raiz. Remova o link.`);
|
|
102
|
+
}
|
|
103
|
+
return dir;
|
|
95
104
|
}
|
|
96
105
|
function texto(v, padrao) {
|
|
97
106
|
return typeof v === 'string' ? v : typeof v === 'number' ? String(v) : padrao;
|
|
@@ -99,6 +108,15 @@ function texto(v, padrao) {
|
|
|
99
108
|
function numero(v, padrao) {
|
|
100
109
|
return typeof v === 'number' ? v : typeof v === 'string' && v.trim() !== '' && !isNaN(Number(v)) ? Number(v) : padrao;
|
|
101
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* RM-058 N2: as vagas da fila pesada, inteiras de 0 a 64. So o 0 escrito desliga a fila; fracao positiva sobe para 1 e
|
|
113
|
+
* valor sem sentido volta ao padrao 1, nunca a "sem fila".
|
|
114
|
+
*/
|
|
115
|
+
function vagasPesadas(v) {
|
|
116
|
+
if (!Number.isFinite(v) || v < 0)
|
|
117
|
+
return 1;
|
|
118
|
+
return v === 0 ? 0 : Math.min(64, Math.max(1, Math.trunc(v)));
|
|
119
|
+
}
|
|
102
120
|
/**
|
|
103
121
|
* I-37 (D2): `verify.timeout_ms` e `verify.timeout_ms_por_comando`. Prazo so vale inteiro
|
|
104
122
|
* positivo em milissegundos, entre 1 s e 24 h; o resto e erro do manifesto, porque um prazo
|
|
@@ -187,6 +205,65 @@ function lerGrafo(v, avisos) {
|
|
|
187
205
|
avisos.push(`grafo.mcp deve ser true ou false; vale false (${mostrar(mcp)} nao reconhecido)`);
|
|
188
206
|
return { mcp: false };
|
|
189
207
|
}
|
|
208
|
+
/** RM-059 (T10.4): os limites dos tetos de agent teams, os mesmos que o Portao de Tarefas aceita do ambiente. */
|
|
209
|
+
exports.TETO_MAXIMO_DE_TEAMMATES = 8;
|
|
210
|
+
exports.TETO_MAXIMO_DE_CUSTO_USD = 500;
|
|
211
|
+
/**
|
|
212
|
+
* RM-059 (T10.4, D11 da thread ork-rm059portao): agent teams no despacho do GO, so em piloto. `runtime.agent_teams`
|
|
213
|
+
* liga com `ligado: true` e os dois tetos validos: `teammates` inteiro de 1 a 8 e `custo_usd` maior que 0 e ate 500,
|
|
214
|
+
* escrito como numero decimal simples. Ausente ou `ligado: false` fica desligado sem aviso; ligado com teto invalido,
|
|
215
|
+
* outro tipo ou chave desconhecida avisa e fica desligado, nunca erro: a chave e experimental e nao para a fabrica.
|
|
216
|
+
*/
|
|
217
|
+
function lerAgentTeams(v, avisos) {
|
|
218
|
+
const mostrar = (x) => (x === undefined ? 'ausente' : JSON.stringify(x).slice(0, 80));
|
|
219
|
+
if (v === undefined || v === null)
|
|
220
|
+
return undefined;
|
|
221
|
+
if (typeof v !== 'object' || Array.isArray(v)) {
|
|
222
|
+
avisos.push(`runtime.agent_teams deve ser um mapa com ligado, teammates e custo_usd; fica desligado (${mostrar(v)} nao reconhecido)`);
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
for (const chave of Object.keys(v)) {
|
|
226
|
+
if (!['ligado', 'teammates', 'custo_usd'].includes(chave))
|
|
227
|
+
avisos.push(`runtime.agent_teams.${chave} desconhecida; o bloco so tem ligado, teammates e custo_usd`);
|
|
228
|
+
}
|
|
229
|
+
if (v.ligado !== true) {
|
|
230
|
+
if (v.ligado !== undefined && v.ligado !== null && v.ligado !== false) {
|
|
231
|
+
avisos.push(`runtime.agent_teams.ligado deve ser true ou false; fica desligado (${mostrar(v.ligado)} nao reconhecido)`);
|
|
232
|
+
}
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
const teammates = v.teammates;
|
|
236
|
+
const custo = v.custo_usd;
|
|
237
|
+
const tetoOk = typeof teammates === 'number' && Number.isInteger(teammates) && teammates >= 1 && teammates <= exports.TETO_MAXIMO_DE_TEAMMATES;
|
|
238
|
+
const custoOk = typeof custo === 'number' && /^\d+(?:\.\d+)?$/.test(String(custo)) && custo > 0 && custo <= exports.TETO_MAXIMO_DE_CUSTO_USD;
|
|
239
|
+
if (!tetoOk || !custoOk) {
|
|
240
|
+
avisos.push(`runtime.agent_teams ligado sem teto valido (teammates inteiro de 1 a ${exports.TETO_MAXIMO_DE_TEAMMATES} e custo_usd maior que 0 ` +
|
|
241
|
+
`e ate ${exports.TETO_MAXIMO_DE_CUSTO_USD}; recebido teammates ${mostrar(teammates)} e custo_usd ${mostrar(custo)}); fica desligado`);
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
return { teammates: teammates, custo_usd: custo };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* RM-026 K7 (D1): `conhecimento.dir`, a pasta dos documentos `ork.conhecimento/v1`. Sem o bloco, o projeto nao
|
|
248
|
+
* declarou conhecimento. Bloco que nao e mapa e `dir` vazio avisam e ficam declarados com `dir` vazio, que o
|
|
249
|
+
* leitor (`conhecimento.ts`) recusa com `conhecimento.dir-invalido`: quem declarou nao ouve que nao declarou.
|
|
250
|
+
* Chave desconhecida so avisa. Ler a pasta nao executa nada, e a regra do caminho mora no leitor.
|
|
251
|
+
*/
|
|
252
|
+
function lerBlocoConhecimento(v, avisos) {
|
|
253
|
+
if (v === undefined || v === null)
|
|
254
|
+
return undefined;
|
|
255
|
+
if (typeof v !== 'object' || Array.isArray(v)) {
|
|
256
|
+
avisos.push('conhecimento deve ser um mapa com dir: <pasta dentro da raiz>; o leitor recusa ate corrigir');
|
|
257
|
+
return { dir: '' };
|
|
258
|
+
}
|
|
259
|
+
for (const chave of Object.keys(v))
|
|
260
|
+
if (chave !== 'dir')
|
|
261
|
+
avisos.push(`conhecimento.${chave} desconhecida; o bloco conhecimento so tem dir`);
|
|
262
|
+
const dir = texto(v.dir, '').trim();
|
|
263
|
+
if (!dir)
|
|
264
|
+
avisos.push('conhecimento.dir deve ser uma pasta dentro da raiz, como docs/conhecimento; o leitor recusa ate corrigir');
|
|
265
|
+
return { dir };
|
|
266
|
+
}
|
|
190
267
|
/** Mesmo contrato na leitura do YAML e nos consumidores de manifesto em memoria. */
|
|
191
268
|
function validarOptInPlaybook(valor) {
|
|
192
269
|
if (valor === undefined)
|
|
@@ -334,6 +411,12 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
334
411
|
erros.push('conduction.delegation exige thread, escopo premissas, prazo ISO, evidencia e delegado');
|
|
335
412
|
}
|
|
336
413
|
const worktree = mapa(dados.worktree);
|
|
414
|
+
// RM-047 (fronteira de confiança): a base vai ao git em rev-parse, log, fetch e worktree add. Nome que o
|
|
415
|
+
// git não aceita como branch (começa com `-`, tem `..`) viraria opção dele; a regra é a do check-ref-format.
|
|
416
|
+
if (worktree.base_branch !== undefined && worktree.base_branch !== null && !(0, branch_de_estado_1.branchValida)(texto(worktree.base_branch, ''))) {
|
|
417
|
+
erros.push(`worktree.base_branch invalido: ${JSON.stringify(texto(worktree.base_branch, '')).slice(0, 60)} ` +
|
|
418
|
+
'(esperado nome de branch do git, sem "-" no começo e sem "..")');
|
|
419
|
+
}
|
|
337
420
|
const verify = mapa(dados.verify);
|
|
338
421
|
const ci = mapa(dados.ci);
|
|
339
422
|
const concurrency = mapa(dados.concurrency);
|
|
@@ -445,6 +528,8 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
445
528
|
if (!codex_1.SANDBOXES_DO_CODEX.includes(sandboxDoRuntime)) {
|
|
446
529
|
erros.push(`runtime.sandbox invalido: "${sandboxDoRuntime}" (aceitos: ${codex_1.SANDBOXES_DO_CODEX.join(', ')})`);
|
|
447
530
|
}
|
|
531
|
+
// RM-059 (T10.4): agent teams no despacho do GO, so no piloto e desligado por padrao.
|
|
532
|
+
const agentTeams = lerAgentTeams(runtime.agent_teams, avisos);
|
|
448
533
|
// Bloco B6, isolamento por tenant (precedente do incidente memory-orkmind):
|
|
449
534
|
// `database_url_env` recebe o NOME da variavel de ambiente, nunca a string de conexao.
|
|
450
535
|
// Uma DSN colada aqui e exatamente o defeito que fez a memoria de um produto escrever
|
|
@@ -461,6 +546,14 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
461
546
|
else if (variavelDaDsn !== '' && !/^[A-Z][A-Z0-9_]*$/.test(variavelDaDsn)) {
|
|
462
547
|
erros.push(`memory.database_url_env invalido: "${variavelDaDsn}" (esperado nome de variavel de ambiente, [A-Z][A-Z0-9_]*)`);
|
|
463
548
|
}
|
|
549
|
+
// RM-047 (fronteira de confiança): `memory.cli` escolhe o executável que o `ork doctor`, a memória e o
|
|
550
|
+
// `ork brain` rodam. Caminho relativo apontaria para um arquivo do próprio clone; só nome procurado no
|
|
551
|
+
// PATH (o `orkmind` instalado) ou caminho absoluto escolhido por quem instalou.
|
|
552
|
+
const cliDaMemoria = texto(memory.cli, 'orkmind');
|
|
553
|
+
if (!cliDaMemoriaValido(cliDaMemoria)) {
|
|
554
|
+
erros.push(`memory.cli invalido: ${JSON.stringify(cliDaMemoria).slice(0, 60)} ` +
|
|
555
|
+
'(esperado nome de executável no PATH, como orkmind, ou caminho absoluto; caminho relativo não é aceito)');
|
|
556
|
+
}
|
|
464
557
|
if (modoDeMemoria === 'orkmind' && variavelDaDsn === '') {
|
|
465
558
|
avisos.push('memory.mode: orkmind sem memory.database_url_env: o regime efetivo cai para files ' +
|
|
466
559
|
'(o `ork` nao adivinha DSN, e base alheia e pior do que base nenhuma)');
|
|
@@ -478,6 +571,7 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
478
571
|
if (achado.legado) {
|
|
479
572
|
avisos.push(`lendo ${exports.NOME_MANIFESTO_LEGADO} como fallback; migre para ${exports.NOME_MANIFESTO}`);
|
|
480
573
|
}
|
|
574
|
+
const conhecimento = lerBlocoConhecimento(dados.conhecimento, avisos);
|
|
481
575
|
const manifesto = {
|
|
482
576
|
project: {
|
|
483
577
|
name: nomeProjeto,
|
|
@@ -496,6 +590,7 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
496
590
|
effort: texto(runtime.effort, 'high'),
|
|
497
591
|
provider_policy: providerPolicy,
|
|
498
592
|
sandbox: sandboxDoRuntime,
|
|
593
|
+
...(agentTeams ? { agent_teams: agentTeams } : {}),
|
|
499
594
|
},
|
|
500
595
|
conduction: {
|
|
501
596
|
default_mode: defaultModo ?? 'classic',
|
|
@@ -529,6 +624,8 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
529
624
|
concurrency: {
|
|
530
625
|
max_parallel_threads: numero(concurrency.max_parallel_threads, 3),
|
|
531
626
|
stale_after_min: Math.max(1, Math.trunc(numero(concurrency.stale_after_min, 240))),
|
|
627
|
+
// RM-058 N2 (D9): uma operacao pesada por vez nesta raiz, por padrao; 0 desliga a fila.
|
|
628
|
+
max_parallel_heavy: vagasPesadas(numero(concurrency.max_parallel_heavy, 1)),
|
|
532
629
|
},
|
|
533
630
|
liveness: { silencio_max_min: silencioMaxMin },
|
|
534
631
|
handoff: {
|
|
@@ -577,15 +674,44 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
|
|
|
577
674
|
},
|
|
578
675
|
// RM-031 KG5 (D2): expor as tools do grafo no MCP e opt-in do dono.
|
|
579
676
|
grafo: lerGrafo(dados.grafo, avisos),
|
|
677
|
+
...(conhecimento ? { conhecimento } : {}),
|
|
580
678
|
policies: Object.fromEntries(Object.entries(mapa(dados.policies)).map(([k, v]) => [k, texto(v, '')])),
|
|
581
679
|
};
|
|
582
680
|
return { caminho: achado.caminho, raiz, legado: achado.legado, bytes, manifesto, erros, avisos };
|
|
583
681
|
}
|
|
682
|
+
/**
|
|
683
|
+
* RM-047: `memory.cli` aceito. Nome simples (procurado no PATH, sem barra e sem `-` no começo) ou caminho
|
|
684
|
+
* absoluto normalizado. Caminho relativo (`./bin/x`, `bin/x`) resolveria dentro do repositório clonado.
|
|
685
|
+
*/
|
|
686
|
+
function cliDaMemoriaValido(cli) {
|
|
687
|
+
// eslint-disable-next-line no-control-regex
|
|
688
|
+
if (cli === '' || /[\x00-\x1f\x7f]/.test(cli))
|
|
689
|
+
return false;
|
|
690
|
+
if (/^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/.test(cli))
|
|
691
|
+
return true;
|
|
692
|
+
return path.isAbsolute(cli) && path.normalize(cli) === cli;
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* RM-059 (A15 da revisao da ork-rm059pista): os comandos de verify e o do CI de um `orkastery.yaml` lido como texto (o
|
|
696
|
+
* do HEAD de uma branch, pelo `git show`), com as mesmas regras do `carregarManifesto`. `null` quando o texto nao abre.
|
|
697
|
+
*/
|
|
698
|
+
function comandosDoTextoDoManifesto(bruto) {
|
|
699
|
+
let dados;
|
|
700
|
+
try {
|
|
701
|
+
dados = mapa((0, yaml_1.lerYaml)(bruto));
|
|
702
|
+
}
|
|
703
|
+
catch {
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
const verify = mapa(dados.verify), ci = mapa(dados.ci);
|
|
707
|
+
const opcional = (v) => (v === null || v === undefined ? undefined : texto(v, ''));
|
|
708
|
+
return { typecheck: opcional(verify.typecheck), build: opcional(verify.build), test: opcional(verify.test), ciCommand: opcional(ci.command) };
|
|
709
|
+
}
|
|
584
710
|
/** Carrega o manifesto ou encerra com mensagem acionavel (uso nos subcomandos). */
|
|
585
711
|
function exigirManifesto(dirInicial = diretorioDoProjeto()) {
|
|
586
712
|
const carregado = carregarManifesto(dirInicial);
|
|
587
713
|
if (!carregado) {
|
|
588
|
-
throw new
|
|
714
|
+
throw new locale_1.ErroDoCatalogo((m) => m.cli.manifestoNaoEncontrado(exports.NOME_MANIFESTO, dirInicial));
|
|
589
715
|
}
|
|
590
716
|
if (carregado.erros.length > 0) {
|
|
591
717
|
throw new Error(`manifesto invalido (${carregado.caminho}):\n - ${carregado.erros.join('\n - ')}`);
|
package/dist/maquina.js
CHANGED
|
@@ -39,6 +39,7 @@ exports.lerConfigDaMaquina = lerConfigDaMaquina;
|
|
|
39
39
|
exports.gravarConfigDaMaquina = gravarConfigDaMaquina;
|
|
40
40
|
exports.nomeDaMaquina = nomeDaMaquina;
|
|
41
41
|
exports.fabricaCompartilhada = fabricaCompartilhada;
|
|
42
|
+
exports.avisoDaFabricaPedida = avisoDaFabricaPedida;
|
|
42
43
|
/**
|
|
43
44
|
* I-51 (RM-047): esta maquina na fabrica.
|
|
44
45
|
*
|
|
@@ -49,8 +50,11 @@ exports.fabricaCompartilhada = fabricaCompartilhada;
|
|
|
49
50
|
* nao carregam o perfil do shell, e a mesma maquina apareceria com dois nomes.
|
|
50
51
|
*
|
|
51
52
|
* Precedencia do nome: `--maquina`, `ORK_MAQUINA`, o arquivo, o hostname.
|
|
52
|
-
* Precedencia da adesao: `ORK_FABRICA_COMPARTILHADA` (1 liga, 0 desliga), senao o
|
|
53
|
-
*
|
|
53
|
+
* Precedencia da adesao: `ORK_FABRICA_COMPARTILHADA` (1 liga, 0 desliga), senao o arquivo.
|
|
54
|
+
*
|
|
55
|
+
* RM-047 (fronteira de confianca, P5): o `fabrica.compartilhada` do manifesto vem com o repositorio e
|
|
56
|
+
* nao liga a publicacao desta maquina. Ele so diz que o time pede a fabrica compartilhada; o `ork`
|
|
57
|
+
* avisa, e quem liga e a maquina, com `ork fabrica entrar` (ou a variavel de ambiente).
|
|
54
58
|
*/
|
|
55
59
|
const fs = __importStar(require("node:fs"));
|
|
56
60
|
const os = __importStar(require("node:os"));
|
|
@@ -91,12 +95,27 @@ function gravarConfigDaMaquina(mudanca) {
|
|
|
91
95
|
function nomeDaMaquina(explicito) {
|
|
92
96
|
return (explicito ?? '').trim() || (process.env.ORK_MAQUINA ?? '').trim() || lerConfigDaMaquina()?.nome || os.hostname();
|
|
93
97
|
}
|
|
94
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* Esta maquina publica o estado da fabrica deste projeto (e le o das outras)? Decide a maquina: a
|
|
100
|
+
* variavel de ambiente ou o `~/.orkastery/maquina.json`. O manifesto nao entra (RM-047, P5); o
|
|
101
|
+
* parametro fica para quem chama dizer de que projeto se trata.
|
|
102
|
+
*/
|
|
95
103
|
function fabricaCompartilhada(manifesto) {
|
|
104
|
+
void manifesto;
|
|
96
105
|
const env = (process.env.ORK_FABRICA_COMPARTILHADA ?? '').trim();
|
|
97
106
|
if (env === '1')
|
|
98
107
|
return true;
|
|
99
108
|
if (env === '0')
|
|
100
109
|
return false;
|
|
101
|
-
return
|
|
110
|
+
return lerConfigDaMaquina()?.fabricaCompartilhada === true;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* RM-047 (P5): o manifesto pede a fabrica compartilhada e esta maquina nao entrou. Devolve o aviso,
|
|
114
|
+
* com o comando que liga, ou `null`.
|
|
115
|
+
*/
|
|
116
|
+
function avisoDaFabricaPedida(manifesto) {
|
|
117
|
+
if (manifesto.fabrica?.compartilhada !== true || fabricaCompartilhada(manifesto))
|
|
118
|
+
return null;
|
|
119
|
+
return 'fabrica.nao-confirmada: o orkastery.yaml pede fabrica.compartilhada: true, mas quem liga a publicacao ' +
|
|
120
|
+
'do retrato desta maquina e a propria maquina, nao o repositorio. Nada foi publicado. Para entrar: ork fabrica entrar';
|
|
102
121
|
}
|
package/dist/master-digest.js
CHANGED
|
@@ -46,6 +46,7 @@ const node_crypto_1 = require("node:crypto");
|
|
|
46
46
|
const master_batch_1 = require("./master-batch");
|
|
47
47
|
const master_1 = require("./master");
|
|
48
48
|
const estado_thread_1 = require("./estado-thread");
|
|
49
|
+
const procedencia_1 = require("./procedencia");
|
|
49
50
|
const hitl_1 = require("./hitl");
|
|
50
51
|
const pulse_delivery_1 = require("./pulse-delivery");
|
|
51
52
|
const util_1 = require("./util");
|
|
@@ -125,7 +126,11 @@ function enviarDigest(opcoes) {
|
|
|
125
126
|
if (job.concluidoEm)
|
|
126
127
|
return { code: 0, detalhe: 'semana já confirmada', enviadas, semana };
|
|
127
128
|
salvar(file, job);
|
|
128
|
-
|
|
129
|
+
// RM-047 (P2): o executavel do transporte so sai do arquivo local, nunca de um versionado no git.
|
|
130
|
+
const hostLocal = path.join(raiz, '.orkastery/monitor/master-host.json');
|
|
131
|
+
if (!opcoes.transporte && !opcoes.enviar)
|
|
132
|
+
(0, procedencia_1.exigirHostLocal)(raiz, hostLocal);
|
|
133
|
+
const config = opcoes.transporte ?? (!opcoes.enviar ? (0, util_1.lerJson)(hostLocal) : undefined);
|
|
129
134
|
for (const [indice, p] of job.paginas.entries()) {
|
|
130
135
|
if (job.recibos.some(r => r.pagina === indice && r.sha256 === hash(p)))
|
|
131
136
|
continue;
|
package/dist/master-nota.js
CHANGED
|
@@ -81,6 +81,7 @@ const thread_close_1 = require("./thread-close");
|
|
|
81
81
|
const conducao_1 = require("./conducao");
|
|
82
82
|
const pulse_consentimento_1 = require("./pulse-consentimento");
|
|
83
83
|
const monitor_lock_1 = require("./monitor-lock");
|
|
84
|
+
const locale_1 = require("./locale");
|
|
84
85
|
exports.CONTRATO_PEDIDO_DE_NOTA = 'ork.master-nota/v1';
|
|
85
86
|
exports.ERRO_PROVA_DE_CANAL = 'master.prova-de-canal';
|
|
86
87
|
const sha = (s) => (0, node_crypto_1.createHash)('sha256').update(s).digest('hex');
|
|
@@ -101,7 +102,7 @@ function marcaDeHost(ambiente = process.env) {
|
|
|
101
102
|
// thread e conduzida do terminal, e o Claude Code e o Codex marcam os proprios processos. Qualquer
|
|
102
103
|
// marca de host ou de despacho conta, mesmo com o canal declarado como terminal.
|
|
103
104
|
return canal !== 'cli' ? canal
|
|
104
|
-
: ambiente.ORK_DISPATCH_ID ?
|
|
105
|
+
: ambiente.ORK_DISPATCH_ID ? (0, locale_1.msg)().master.marcaDespachada
|
|
105
106
|
: ambiente.CLAUDECODE === '1' ? 'claude-code (CLAUDECODE)'
|
|
106
107
|
: ambiente.CODEX_SANDBOX || ambiente.CODEX_SANDBOX_NETWORK_DISABLED ? 'codex (CODEX_SANDBOX)'
|
|
107
108
|
: (ambiente.HERMES_HOME ?? '').trim() ? 'hermes (HERMES_HOME)' : undefined;
|
|
@@ -177,11 +178,8 @@ function pedidoDeNotaDoCodigo(raiz, codigo, estadoDir) {
|
|
|
177
178
|
function textoDoPedidoDeNota(raiz, p, canal) {
|
|
178
179
|
const t = (0, thread_1.lerThread)(raiz, p.thread);
|
|
179
180
|
const tg = canal === 'telegram';
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
`${tg ? '• ' : '- '}Sem nota, vale a aceita por omissão, com o índice derivado do ledger ao lado.`,
|
|
183
|
-
`${tg ? '↩️ ' : ''}Responda: ${p.codigo} <0 a 5> <porquê>, por exemplo: ${p.codigo} 4 entregou o que pedi.`,
|
|
184
|
-
].join('\n');
|
|
181
|
+
const m = (0, locale_1.msg)().master;
|
|
182
|
+
return [m.notaTitulo(tg, p.thread, t.nome.slice(0, 80)), m.notaSemNota(tg), m.notaResponda(tg, p.codigo)].join('\n');
|
|
185
183
|
}
|
|
186
184
|
/** "4 entregou o que pedi" vira nota e justificativa; o resto e devolvido como pergunta. */
|
|
187
185
|
function lerNota(resto) {
|
package/dist/master.js
CHANGED
|
@@ -87,6 +87,7 @@ const modos_1 = require("./modos");
|
|
|
87
87
|
const thread_1 = require("./thread");
|
|
88
88
|
const types_1 = require("./types");
|
|
89
89
|
const util_1 = require("./util");
|
|
90
|
+
const locale_1 = require("./locale");
|
|
90
91
|
const fs = __importStar(require("node:fs"));
|
|
91
92
|
const horario_1 = require("./horario");
|
|
92
93
|
const indice_1 = require("./indice");
|
|
@@ -732,6 +733,7 @@ function pendentesDeScore(raiz, todas = false) {
|
|
|
732
733
|
* inteiro, e a nota humana continua sobrescrevendo o indice quando o dono reclama.
|
|
733
734
|
*/
|
|
734
735
|
function tabelaDeEntregas(raiz, todas = false) {
|
|
736
|
+
const m = (0, locale_1.msg)().master;
|
|
735
737
|
const pendentes = pendentesDeScore(raiz, todas);
|
|
736
738
|
const omissoes = aceitosPorOmissao(raiz);
|
|
737
739
|
// A1: o indice da coluna e o de AGORA; `SCORE GRAVADO` e o que o MASTER log congelou.
|
|
@@ -739,23 +741,18 @@ function tabelaDeEntregas(raiz, todas = false) {
|
|
|
739
741
|
const caiuDepoisDeAceita = omissoes.filter((o) => typeof o.scoreGravado === 'number' && o.indice.valor < o.scoreGravado);
|
|
740
742
|
const secaoOmissao = omissoes.length === 0
|
|
741
743
|
? []
|
|
742
|
-
: ['',
|
|
743
|
-
(0, util_1.tabela)([
|
|
744
|
+
: ['', m.aceitasTitulo(omissoes.length), '',
|
|
745
|
+
(0, util_1.tabela)([...m.colunasAceitas], omissoes.map((o) => [o.thread, `${o.indice.valor}/${o.indice.base}`,
|
|
744
746
|
typeof o.scoreGravado === 'number' ? `${o.scoreGravado}/5` : '-',
|
|
745
747
|
(0, horario_1.formatarDataHora)(o.aceitoEm)])),
|
|
746
748
|
(0, horario_1.legendaDoFuso)(),
|
|
747
749
|
...(caiuDepoisDeAceita.length === 0 ? [] : ['',
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
' registro humano alcancar o fato; o registro da omissao permanece no ledger.']),
|
|
752
|
-
'', 'Discordou de alguma? A nota humana sobrescreve, e o registro da omissao permanece:',
|
|
753
|
-
' ork master <thread-id> --score <0-5> --justificativa "<por que>" --por <humano>'];
|
|
750
|
+
m.caiuDepois(caiuDepoisDeAceita.length, caiuDepoisDeAceita.map((o) => o.thread).join(', ')),
|
|
751
|
+
m.caiuDepoisLinha1, m.caiuDepoisLinha2]),
|
|
752
|
+
'', m.discordouDeAlguma, m.pontuar];
|
|
754
753
|
if (pendentes.length === 0) {
|
|
755
754
|
return [
|
|
756
|
-
todas
|
|
757
|
-
? 'Nenhuma thread aberta sem score.'
|
|
758
|
-
: 'Nenhuma entrega esperando decisao. Para ver tambem as que ainda nao entregaram: ork master --todas',
|
|
755
|
+
todas ? m.semEntregaTodas : m.semEntrega,
|
|
759
756
|
...secaoOmissao,
|
|
760
757
|
].join('\n');
|
|
761
758
|
}
|
|
@@ -766,23 +763,23 @@ function tabelaDeEntregas(raiz, todas = false) {
|
|
|
766
763
|
p.thread.slug,
|
|
767
764
|
(0, modos_1.tagDoModo)(p.thread.modo),
|
|
768
765
|
p.thread.faseAtual,
|
|
769
|
-
p.thread.status,
|
|
770
|
-
p.entregou
|
|
766
|
+
(0, locale_1.msg)().thread.status(p.thread.status),
|
|
767
|
+
m.simNao(p.entregou),
|
|
771
768
|
`${indice.valor}/${indice.base}`,
|
|
772
|
-
indice.parcelas.length === 0 ?
|
|
769
|
+
indice.parcelas.length === 0 ? m.semTropeco : indice.parcelas.map((x) => `${x.evento} x${x.ocorrencias}`).join(', '),
|
|
773
770
|
];
|
|
774
771
|
});
|
|
775
772
|
return [
|
|
776
|
-
|
|
773
|
+
m.entregas(pendentes.length),
|
|
777
774
|
'',
|
|
778
|
-
(0, util_1.tabela)([
|
|
775
|
+
(0, util_1.tabela)([...m.colunas], linhas),
|
|
779
776
|
'',
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
777
|
+
m.entregueEAceito,
|
|
778
|
+
m.aceitarEsta,
|
|
779
|
+
m.aceitarTodas,
|
|
780
|
+
m.reclamar,
|
|
784
781
|
'',
|
|
785
|
-
|
|
782
|
+
m.classesFixas(exports.ORDEM_DAS_CLASSES.join(', ')),
|
|
786
783
|
...secaoOmissao,
|
|
787
784
|
].join('\n');
|
|
788
785
|
}
|
|
@@ -818,13 +815,13 @@ function entregasParaOmissao(raiz, thread) {
|
|
|
818
815
|
function motivoForaDaOmissao(raiz, id) {
|
|
819
816
|
const thread = (0, thread_1.lerThread)(raiz, id);
|
|
820
817
|
if (thread.fechamentoAdmin) {
|
|
821
|
-
return { motivo: 'fechamento-admin', texto:
|
|
818
|
+
return { motivo: 'fechamento-admin', texto: (0, locale_1.msg)().master.foraAdmin(id, thread.fechamentoAdmin.motivo) };
|
|
822
819
|
}
|
|
823
820
|
if (masterRatificado(raiz, id)) {
|
|
824
|
-
return { motivo: 'ja-fechada', texto:
|
|
821
|
+
return { motivo: 'ja-fechada', texto: (0, locale_1.msg)().master.foraJaFechada(id) };
|
|
825
822
|
}
|
|
826
823
|
if (!entregou(raiz, id)) {
|
|
827
|
-
return { motivo: 'sem-entrega', texto:
|
|
824
|
+
return { motivo: 'sem-entrega', texto: (0, locale_1.msg)().master.foraSemEntrega(id) };
|
|
828
825
|
}
|
|
829
826
|
return null;
|
|
830
827
|
}
|
package/dist/mcp-artifacts.js
CHANGED
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.diagnosticoNomeForaDeUtf8 = diagnosticoNomeForaDeUtf8;
|
|
36
37
|
exports.validarArquivosEstadoMcp = validarArquivosEstadoMcp;
|
|
37
38
|
exports.lerArtefatoMcp = lerArtefatoMcp;
|
|
38
39
|
exports.escreverArtefatoMcp = escreverArtefatoMcp;
|
|
@@ -49,6 +50,14 @@ const claims_1 = require("./claims");
|
|
|
49
50
|
const fases = { goal: 'GOAL', plan: 'PLAN', check: 'CHECK' };
|
|
50
51
|
const limite = 128 * 1024;
|
|
51
52
|
const hash = (bytes) => (0, node_crypto_1.createHash)('sha256').update(bytes).digest('hex');
|
|
53
|
+
/** Diagnostico relativo, sem perda de bytes nem controles de terminal; nao e um comando shell. */
|
|
54
|
+
function diagnosticoNomeForaDeUtf8(raiz, pasta, nome) {
|
|
55
|
+
const pai = path.relative(raiz, pasta);
|
|
56
|
+
const entrada = Buffer.concat([Buffer.from(pai ? pai + path.sep : ''), nome]);
|
|
57
|
+
const rotulo = Array.from(entrada, byte => byte >= 0x20 && byte <= 0x7e && byte !== 0x5c
|
|
58
|
+
? String.fromCharCode(byte) : '\\x' + byte.toString(16).padStart(2, '0')).join('');
|
|
59
|
+
return `nome fora de UTF-8 em ${rotulo}\nRenomeie a entrada pelo shell para um nome UTF-8 valido e repita a operacao.`;
|
|
60
|
+
}
|
|
52
61
|
/** Core legado usa nomes de arquivos: este preflight recusa links existentes, nao promete CAS contra writers hostis. */
|
|
53
62
|
function validarArquivosEstadoMcp(raiz, id) {
|
|
54
63
|
validarId(id);
|
|
@@ -154,7 +163,7 @@ function comEscrita(raiz, id, executar) {
|
|
|
154
163
|
const nome = nomeBytes.toString('utf8');
|
|
155
164
|
// Antes do lstat: uma decodificacao com perda nao prova que a entrada desapareceu.
|
|
156
165
|
if (!Buffer.from(nome, 'utf8').equals(nomeBytes))
|
|
157
|
-
throw Error('mcp.state.unsafe:
|
|
166
|
+
throw Error('mcp.state.unsafe: ' + diagnosticoNomeForaDeUtf8(raiz, pastaLeases, nomeBytes));
|
|
158
167
|
const entrada = path.join(pastaLeases, nome), s = fs.lstatSync(entrada, { throwIfNoEntry: false });
|
|
159
168
|
if (!s)
|
|
160
169
|
continue; // Uma retomada pode ter acabado durante o preflight.
|
|
@@ -174,7 +183,7 @@ function comEscrita(raiz, id, executar) {
|
|
|
174
183
|
for (const candidatoBytes of candidatos) {
|
|
175
184
|
const candidato = candidatoBytes.toString('utf8');
|
|
176
185
|
if (!Buffer.from(candidato, 'utf8').equals(candidatoBytes))
|
|
177
|
-
throw Error('mcp.state.unsafe:
|
|
186
|
+
throw Error('mcp.state.unsafe: ' + diagnosticoNomeForaDeUtf8(raiz, entrada, candidatoBytes));
|
|
178
187
|
const c = fs.lstatSync(path.join(entrada, candidato), { throwIfNoEntry: false });
|
|
179
188
|
if (!c)
|
|
180
189
|
continue;
|
package/dist/mcp-git.js
CHANGED
|
@@ -221,7 +221,7 @@ function arvoreMetadados(root, alvo, opcoes = {}) {
|
|
|
221
221
|
const n = bytes.toString('utf8');
|
|
222
222
|
// Perda de bytes nao e ENOENT transitorio: o nome decodificado pode nem apontar para esta entrada.
|
|
223
223
|
if (!Buffer.from(n, 'utf8').equals(bytes))
|
|
224
|
-
falha(
|
|
224
|
+
falha('metadata.unsafe: ' + (0, mcp_artifacts_1.diagnosticoNomeForaDeUtf8)(opcoes.relativoA ?? path.dirname(root), f, bytes));
|
|
225
225
|
visitar(path.join(f, n), profundidade + 1);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
@@ -354,7 +354,7 @@ function estadoGitMcp(raiz, threadId) {
|
|
|
354
354
|
scope: 'local-only', observedAt: new Date().toISOString() };
|
|
355
355
|
}
|
|
356
356
|
/** Somente o worker dedicado chama este corpo; não altera env do servidor. */
|
|
357
|
-
function executar(raiz, p) {
|
|
357
|
+
function executar(raiz, p, dispatchId) {
|
|
358
358
|
const proprias = [];
|
|
359
359
|
let commit = null, estadoAuditado = false;
|
|
360
360
|
try {
|
|
@@ -364,6 +364,23 @@ function executar(raiz, p) {
|
|
|
364
364
|
fisico(raiz, (0, thread_1.dirThread)(raiz, p.threadId));
|
|
365
365
|
(0, mcp_artifacts_1.validarArquivosEstadoMcp)(raiz, p.threadId);
|
|
366
366
|
const t = (0, thread_1.lerThread)(raiz, p.threadId), wt = t.worktree;
|
|
367
|
+
// Identidade vem do startup do servidor, nunca dos argumentos públicos da tool.
|
|
368
|
+
// Sem vínculo conhecido, o recibo continua sem atribuição de sessão.
|
|
369
|
+
let vinculo;
|
|
370
|
+
if (dispatchId !== undefined) {
|
|
371
|
+
if (!/^[a-f0-9-]{36}$/.test(dispatchId))
|
|
372
|
+
falha('session.invalid');
|
|
373
|
+
const despachos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, t.id)).filter(e => e.tipo === 'phase_dispatch');
|
|
374
|
+
const despacho = despachos.filter(e => e.identidade?.dispatchId === dispatchId).at(-1);
|
|
375
|
+
const proximo = despacho ? despachos[despachos.indexOf(despacho) + 1] : undefined;
|
|
376
|
+
const sessoes = despacho ? t.sessoes.filter(s => s.sessionId === despacho.sessionId && s.origem !== 'adocao' &&
|
|
377
|
+
s.fase === despacho.fase && s.promptSha256 === despacho.promptSha256 && typeof s.despachadaEm === 'string' &&
|
|
378
|
+
Date.parse(s.despachadaEm) >= Date.parse(despacho.ts) &&
|
|
379
|
+
(!proximo || Date.parse(s.despachadaEm) < Date.parse(proximo.ts))) : [];
|
|
380
|
+
if (sessoes.length !== 1)
|
|
381
|
+
falha('session.invalid');
|
|
382
|
+
vinculo = { sessionId: sessoes[0].sessionId, despachoEm: sessoes[0].despachadaEm };
|
|
383
|
+
}
|
|
367
384
|
if (!wt || t.status === 'fechada' || !(0, thread_1.blocoDaThread)(t, t.faseAtual).fases.includes('GO') || wt === raiz)
|
|
368
385
|
falha('thread.invalid');
|
|
369
386
|
// I-42 (D7): ciclo sem PLAN nem CHECK nao commita contrato publico; a mudanca vira iniciativa.
|
|
@@ -445,7 +462,7 @@ function executar(raiz, p) {
|
|
|
445
462
|
const alterados = git(wt, ['diff-tree', '--no-commit-id', '--name-only', '-r', '-z', commit]).split('\0').filter(Boolean);
|
|
446
463
|
if (!alterados.length || alterados.some(f => !p.paths.includes(f)))
|
|
447
464
|
falha('commit.paths-invalid');
|
|
448
|
-
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, t.id), t.id, 'mcp_git_committed', { commit, paths: alterados, origem: 'mcp.git', estadoAuditado });
|
|
465
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, t.id), t.id, 'mcp_git_committed', { commit, paths: alterados, origem: 'mcp.git', estadoAuditado, ...vinculo });
|
|
449
466
|
return { ok: true, commit, erro: null, estadoAuditado };
|
|
450
467
|
}
|
|
451
468
|
catch (e) {
|
|
@@ -459,7 +476,7 @@ function executar(raiz, p) {
|
|
|
459
476
|
}
|
|
460
477
|
}
|
|
461
478
|
/** Entrada do servidor: argumentos nunca escolhem executável/env/cwd/opções Git. */
|
|
462
|
-
async function commitMcp(raiz, pedido, signal) {
|
|
479
|
+
async function commitMcp(raiz, pedido, signal, dispatchId) {
|
|
463
480
|
validar(pedido);
|
|
464
481
|
if (signal?.aborted)
|
|
465
482
|
return { ok: false, commit: null, erro: 'mcp.git.cancelled', estadoAuditado: false };
|
|
@@ -483,7 +500,7 @@ async function commitMcp(raiz, pedido, signal) {
|
|
|
483
500
|
erro = true;
|
|
484
501
|
child.stdin.end();
|
|
485
502
|
return;
|
|
486
|
-
} child.stdin.end(JSON.stringify({ raiz, pedido })); });
|
|
503
|
+
} child.stdin.end(JSON.stringify({ raiz, pedido, dispatchId })); });
|
|
487
504
|
child.stdin.on('error', () => { erro = true; });
|
|
488
505
|
child.on('error', () => { erro = true; });
|
|
489
506
|
child.stdout.on('data', (b) => { if (Buffer.byteLength(stdout) + b.length > LIMITE)
|
|
@@ -516,7 +533,7 @@ if (require.main === module && process.argv[2] === '--worker') {
|
|
|
516
533
|
if (Buffer.byteLength(raw) > LIMITE)
|
|
517
534
|
falha('request.invalid');
|
|
518
535
|
const p = JSON.parse(raw);
|
|
519
|
-
process.stdout.write(JSON.stringify(executar(p.raiz, p.pedido)));
|
|
536
|
+
process.stdout.write(JSON.stringify(executar(p.raiz, p.pedido, p.dispatchId)));
|
|
520
537
|
}
|
|
521
538
|
catch {
|
|
522
539
|
process.stdout.write(JSON.stringify({ ok: false, commit: null, erro: 'mcp.git.worker.invalid', estadoAuditado: false }));
|
package/dist/mcp-grafo.js
CHANGED
|
@@ -45,7 +45,8 @@ exports.registrarConsultasDoGrafo = registrarConsultasDoGrafo;
|
|
|
45
45
|
* Cinco tools de leitura com o contrato do `ork grafo` (D6): cada uma roda, na worktree da thread, o
|
|
46
46
|
* argv que a CLI receberia (`<consulta> ... --json --teto-bytes N`) e devolve o que ela escreve, sem
|
|
47
47
|
* transformar: a resposta e JSON `ork.code-graph-query/v0` com a evidencia de cada aresta e no maximo
|
|
48
|
-
* `tetoBytes` bytes (D4); contexto usa ork.thread-graph-context/v2. A recusa nao passa pelo teto.
|
|
48
|
+
* `tetoBytes` bytes (D4); contexto usa ork.thread-graph-context/v2. A recusa nao passa pelo teto. Desde a
|
|
49
|
+
* fatia 5, a resposta traz as fontes (sha256 e blob) e diz por aresta se elas conferem com a arvore.
|
|
49
50
|
*
|
|
50
51
|
* Desligadas por padrao (D2): so existem com `grafo.mcp: true` no manifesto da raiz, lido no startup, e
|
|
51
52
|
* cada chamada confere a flag de novo. A consulta roda num worker (D3), um processo filho por chamada,
|
|
@@ -75,7 +76,7 @@ const TETO_DO_STDOUT = 1024 * 1024;
|
|
|
75
76
|
* O vocabulario e os limites da consulta do KG3, repetidos aqui porque este modulo nao importa a
|
|
76
77
|
* familia do grafo (D8); o teste confere que sao os mesmos do contrato v1 e da consulta.
|
|
77
78
|
*/
|
|
78
|
-
exports.TIPOS_DE_ARESTA_DO_MCP = ['contains', 'declares', 'imports', 'calls', 'references', 'derived_from'];
|
|
79
|
+
exports.TIPOS_DE_ARESTA_DO_MCP = ['contains', 'declares', 'imports', 'calls', 'references', 'derived_from', 'cites'];
|
|
79
80
|
exports.PROFUNDIDADE_MAXIMA_DO_MCP = 5;
|
|
80
81
|
exports.LIMITE_MAXIMO_DO_MCP = 10_000;
|
|
81
82
|
/** D2: so o booleano `true` do manifesto da raiz liga as tools. */
|
|
@@ -98,7 +99,8 @@ const tipos = zod_1.z.array(zod_1.z.enum(exports.TIPOS_DE_ARESTA_DO_MCP)).min(1)
|
|
|
98
99
|
const tetoBytes = zod_1.z.number().int().min(exports.TETO_MINIMO).max(exports.TETO_MAXIMO).optional()
|
|
99
100
|
.describe(`teto da resposta em bytes (padrao ${exports.TETO_PADRAO}); acima, saem as arestas mais longe`);
|
|
100
101
|
const COMUM = 'Leitura do grafo do HEAD da worktree da thread (o do ork grafo): so o que o extrator prova. '
|
|
101
|
-
+ 'Resposta JSON ork.code-graph-query/v0 de ate tetoBytes; sem indice do HEAD, recusa com a correcao ork grafo indexar.'
|
|
102
|
+
+ 'Resposta JSON ork.code-graph-query/v0 de ate tetoBytes; sem indice do HEAD, recusa com a correcao ork grafo indexar. '
|
|
103
|
+
+ 'Cada aresta traz arvore (modificada quando uma fonte dela mudou depois do HEAD) e a resposta traz fontes, com o sha256 e o blob de cada arquivo citado.';
|
|
102
104
|
/** As opcoes da CLI, na ordem dela, com `=`: o valor nunca vira outro argumento. */
|
|
103
105
|
function opcoes(a) {
|
|
104
106
|
const r = [];
|
|
@@ -141,7 +143,8 @@ const DEFINICOES = [
|
|
|
141
143
|
{
|
|
142
144
|
nome: 'ork_grafo_contexto',
|
|
143
145
|
descricao: 'Pacote deterministico da thread: diff da worktree contra base (ignorado sem worktree), GOAL, PLAN e claims; fan-in agregado e evidencias compactas. '
|
|
144
|
-
+ 'JSON ork.thread-graph-context/v2 limitado em bytes, refs locais, prioridade entre arquivos e por proximidade ao diff.
|
|
146
|
+
+ 'JSON ork.thread-graph-context/v2 limitado em bytes, refs locais, prioridade entre arquivos e por proximidade ao diff. Citacoes literais cites; segundo salto marcado usa a sobra apos ligacoes diretas. '
|
|
147
|
+
+ 'Grupo com fonte que mudou depois do HEAD traz arvore: modificada. Sem indice do HEAD, recusa com ork grafo indexar.',
|
|
145
148
|
schema: zod_1.z.object({ threadId, tetoBytes }).strict(),
|
|
146
149
|
argv: (a) => ['contexto', a.threadId, ...opcoes(a)],
|
|
147
150
|
},
|
package/dist/mcp-server.js
CHANGED
|
@@ -57,6 +57,7 @@ const hitl_gates_1 = require("./hitl-gates");
|
|
|
57
57
|
const hitl_contract_1 = require("./hitl-contract");
|
|
58
58
|
const hitl_presentation_1 = require("./hitl-presentation");
|
|
59
59
|
const roadmap_status_1 = require("./roadmap-status");
|
|
60
|
+
const pulse_1 = require("./pulse");
|
|
60
61
|
const network_roadmap_1 = require("./network-roadmap");
|
|
61
62
|
const rede_status_1 = require("./rede-status");
|
|
62
63
|
const hitl_sessions_1 = require("./hitl-sessions");
|
|
@@ -68,6 +69,7 @@ const modos_1 = require("./modos");
|
|
|
68
69
|
const versao_1 = require("./versao");
|
|
69
70
|
const mcp_verify_1 = require("./mcp-verify");
|
|
70
71
|
const conducao_1 = require("./conducao");
|
|
72
|
+
const fila_pesada_1 = require("./fila-pesada");
|
|
71
73
|
const decisao_autonoma_1 = require("./decisao-autonoma");
|
|
72
74
|
const conducao_texto_1 = require("./conducao-texto");
|
|
73
75
|
const mcp_ship_1 = require("./mcp-ship");
|
|
@@ -411,6 +413,9 @@ function criarServidorMcp(opcoes) {
|
|
|
411
413
|
// I-36 (T18): a mesma recusa tipada do CLI, com o mesmo texto, sem reescrever nada no host.
|
|
412
414
|
if (e instanceof conducao_1.ErroDeConducao)
|
|
413
415
|
return { ...resposta(e.recusa), isError: true };
|
|
416
|
+
// RM-058 N2 (A6 do CHECK): a fila pesada que nao deu a vez no prazo responde como a conducao.
|
|
417
|
+
if (e instanceof fila_pesada_1.ErroDaFilaPesada)
|
|
418
|
+
return { ...resposta(e.recusa), isError: true };
|
|
414
419
|
throw e;
|
|
415
420
|
}
|
|
416
421
|
});
|
|
@@ -420,7 +425,7 @@ function criarServidorMcp(opcoes) {
|
|
|
420
425
|
annotations: { readOnlyHint: false, destructiveHint: false } }, async (args, extra) => {
|
|
421
426
|
thread(args.threadId);
|
|
422
427
|
livre(args.threadId);
|
|
423
|
-
const r = await (0, mcp_git_1.commitMcp)(raiz, args, extra.signal);
|
|
428
|
+
const r = await (0, mcp_git_1.commitMcp)(raiz, args, extra.signal, opcoes.dispatchId);
|
|
424
429
|
return { ...resposta(r), ...(r.ok ? {} : { isError: true }) };
|
|
425
430
|
});
|
|
426
431
|
const documento = daThread.extend({ tipo: zod_1.z.enum(['goal', 'plan', 'check']) }).strict();
|
|
@@ -492,7 +497,8 @@ function criarServidorMcp(opcoes) {
|
|
|
492
497
|
// RM-052: origem `instalacao`; o servidor fixado nao revela os outros projetos da maquina.
|
|
493
498
|
const consulta = (0, projeto_alvo_1.consultaDoProjeto)(c, { origem: 'instalacao', outrosProjetos: false,
|
|
494
499
|
lido: ['roadmap (docs/roadmap)', projeto_alvo_1.FORA_DA_CONSULTA.threadsDaMaquina], naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.reservas, 'threads de outras máquinas (ork network roadmap)'] });
|
|
495
|
-
|
|
500
|
+
// RM-063 (F2): a mesma fila do `ork pulse`; a consulta que falha e dita no fecho, nunca "Nada agora".
|
|
501
|
+
const status = (0, roadmap_status_1.montarStatusDoRoadmap)(raiz, { projeto: c.manifesto.project.name, consulta, fila: (quando) => (0, pulse_1.filaDoDono)(c, { quando }) });
|
|
496
502
|
return resposta({ texto: (0, roadmap_status_1.textoDoStatusDoRoadmap)(status), status });
|
|
497
503
|
});
|
|
498
504
|
/**
|