@orkastery/cli 0.4.2 → 0.5.0
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/README.md +11 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +3 -1
- package/adapters/claude-code/agents/ork-check.md +1 -1
- package/adapters/claude-code/agents/ork-go.md +2 -2
- package/adapters/claude-code/agents/ork-goal.md +1 -1
- package/adapters/claude-code/agents/ork-master.md +1 -1
- package/adapters/claude-code/agents/ork-plan.md +1 -1
- package/adapters/claude-code/agents/ork-ship.md +1 -1
- package/adapters/claude-code/commands/master.md +11 -8
- package/adapters/claude-code/commands/ork.md +8 -0
- package/adapters/claude-code/commands/ship.md +2 -2
- package/adapters/codex/skills/ork/SKILL.md +12 -1
- package/adapters/hermes/README.md +3 -0
- package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
- package/adapters/hermes/bin/ork-brain.sh +3 -0
- package/adapters/hermes/bin/ork-maestro.sh +4 -1
- package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
- package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
- package/adapters/hermes/hermes.plugin.json +2 -0
- package/adapters/hermes/hitl-ingress/__init__.py +36 -3
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
- package/adapters/openclaw/README.md +34 -3
- package/adapters/openclaw/dist/hitl-ingress.js +37 -3
- package/adapters/openclaw/dist/index.js +92 -39
- package/adapters/openclaw/openclaw.plugin.json +10 -3
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +32 -3
- package/adapters/openclaw/src/index.ts +108 -41
- package/assets/docs/padroes/documentacao-de-produto.md +2 -2
- package/assets/docs/padroes/roadmap-de-produto.md +1 -1
- package/assets/docs/produto/_modelo-feature.md +2 -0
- package/assets/orkmind_bridge.py +214 -1
- package/dist/adapters/claude-bg.js +88 -9
- package/dist/adapters/codex-events.js +3 -1
- package/dist/board.js +74 -0
- package/dist/branch-de-estado.js +5 -4
- package/dist/busca-semantica.js +161 -0
- package/dist/ci.js +141 -10
- package/dist/company-brain-cli.js +27 -2
- package/dist/company-brain-context.js +132 -0
- package/dist/company-brain-dossie.js +376 -0
- package/dist/company-brain-mcp.js +4 -1
- package/dist/conducao.js +117 -31
- package/dist/decisao-autonoma.js +42 -0
- package/dist/docs.js +64 -22
- package/dist/doctor.js +33 -0
- package/dist/entrega-pr.js +109 -5
- package/dist/experiencia-instalacao.js +256 -0
- package/dist/experiencia.js +72 -0
- package/dist/fabrica-estado.js +43 -10
- package/dist/fechamento.js +105 -0
- package/dist/fix.js +1 -1
- package/dist/forja.js +435 -0
- package/dist/gates.js +10 -1
- package/dist/hitl-classificacao.js +11 -1
- package/dist/hitl-contract.js +50 -7
- package/dist/hitl-curto.js +158 -0
- package/dist/hitl-gates.js +67 -1
- package/dist/hitl-lote.js +30 -15
- package/dist/hitl-presentation.js +10 -7
- package/dist/hitl-resumo.js +33 -12
- package/dist/hitl-texto-livre.js +150 -0
- package/dist/hosts.js +86 -1
- package/dist/index.js +605 -41
- package/dist/indice-vetorial.js +317 -0
- package/dist/init.js +13 -0
- package/dist/integracoes-locais.js +1 -1
- package/dist/intelligence-benchmark-contract.js +570 -0
- package/dist/intelligence-graph-cli.js +430 -0
- package/dist/intelligence-graph-contract.js +577 -0
- package/dist/intelligence-graph-extract-md.js +469 -0
- package/dist/intelligence-graph-extract-ts.js +810 -0
- package/dist/intelligence-graph-extract.js +369 -0
- package/dist/intelligence-graph-index.js +512 -0
- package/dist/intelligence-graph-parsers.js +327 -0
- package/dist/intelligence-graph-query.js +344 -0
- package/dist/intelligence-graph-repo.js +187 -0
- package/dist/leases.js +84 -0
- package/dist/ledger.js +14 -0
- package/dist/maestro-cli.js +10 -1
- package/dist/maestro-contract.js +5 -1
- package/dist/maestro-discovery.js +16 -2
- package/dist/maestro-snapshot.js +6 -2
- package/dist/manifest.js +142 -5
- package/dist/master-batch.js +3 -2
- package/dist/master-digest.js +2 -2
- package/dist/master-nota.js +203 -0
- package/dist/master.js +4 -0
- package/dist/mcp-experiencia.js +164 -0
- package/dist/mcp-git.js +36 -10
- package/dist/mcp-install.js +3 -1
- package/dist/mcp-maestro.js +3 -2
- package/dist/mcp-server.js +84 -5
- package/dist/memoria.js +147 -1
- package/dist/network-roadmap.js +907 -0
- package/dist/ocupacao.js +38 -2
- package/dist/onboarding.js +113 -7
- package/dist/orkmind.js +165 -9
- package/dist/phase.js +166 -13
- package/dist/policies.js +2 -0
- package/dist/projeto-alvo.js +551 -0
- package/dist/prompts.js +1 -1
- package/dist/pulse-consentimento.js +4 -2
- package/dist/pulse-delivery.js +5 -0
- package/dist/pulse-resposta.js +674 -49
- package/dist/pulse.js +21 -0
- package/dist/ratelimit.js +3 -2
- package/dist/retry.js +230 -9
- package/dist/roadmap-reservas.js +262 -20
- package/dist/roadmap-status.js +213 -0
- package/dist/runtime-ambiente.js +12 -1
- package/dist/session-watcher-claude.js +26 -0
- package/dist/sessoes.js +49 -15
- package/dist/thread-close.js +3 -0
- package/dist/verify.js +5 -4
- package/dist/worktree.js +77 -0
- package/eval/casos/orchestration-experience-pt-br.json +48 -0
- package/eval/casos/orchestration-experience.json +48 -0
- package/package.json +1 -1
- package/schemas/code-artifact-graph.v1.schema.json +581 -0
- package/schemas/graph-benchmark.v1.schema.json +2240 -0
- package/schemas/maestro-snapshot.schema.json +23 -0
- package/skills/README.md +7 -5
- package/skills/core/onboarding/SKILL.md +7 -0
- package/skills/core/orchestration-experience/SKILL.md +113 -0
- package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/go-implementation/SKILL.md +2 -0
package/dist/master-batch.js
CHANGED
|
@@ -24,7 +24,7 @@ function listarBatch(raiz, todas = false) {
|
|
|
24
24
|
return (0, master_1.pendentesDeScore)(raiz, todas).map(p => ({ thread: p.thread.id, nome: p.thread.nome, entregue: p.entregou,
|
|
25
25
|
proposta: p.thread.score_proposto ?? null, assinatura: p.thread.score_proposto ? assinaturaProposta(p.thread.score_proposto) : null }));
|
|
26
26
|
}
|
|
27
|
-
function ratificarBatch(raiz, selecao, por) {
|
|
27
|
+
function ratificarBatch(raiz, selecao, por, prova) {
|
|
28
28
|
(0, master_1.exigirAutoriaHumana)(por);
|
|
29
29
|
if (!selecao.length || new Set(selecao.map(s => s.thread)).size !== selecao.length)
|
|
30
30
|
throw new Error('selecione threads distintas explicitamente');
|
|
@@ -34,7 +34,8 @@ function ratificarBatch(raiz, selecao, por) {
|
|
|
34
34
|
if (!item?.proposta || item.assinatura !== s.assinatura)
|
|
35
35
|
throw new Error(`proposta ausente ou alterada: ${s.thread}; revise o batch`);
|
|
36
36
|
const p = item.proposta;
|
|
37
|
-
const opcoes = { score: p.valor, justificativa: p.justificativa, classes: s.classe ? [s.classe] : p.classes, resumo: p.resumo, por
|
|
37
|
+
const opcoes = { score: p.valor, justificativa: p.justificativa, classes: s.classe ? [s.classe] : p.classes, resumo: p.resumo, por,
|
|
38
|
+
...(prova ? { prova } : {}) };
|
|
38
39
|
(0, master_1.preflightMaster)(raiz, s.thread, opcoes);
|
|
39
40
|
return { id: s.thread, opcoes };
|
|
40
41
|
});
|
package/dist/master-digest.js
CHANGED
|
@@ -100,14 +100,14 @@ function lerDigest(raiz, semana) {
|
|
|
100
100
|
throw new Error('digest inválido');
|
|
101
101
|
return job;
|
|
102
102
|
}
|
|
103
|
-
function responderLoteDigest(raiz, resposta, por) {
|
|
103
|
+
function responderLoteDigest(raiz, resposta, por, prova) {
|
|
104
104
|
const partes = resposta.trim().split(/\s+/);
|
|
105
105
|
if (partes.length !== 3 || partes[0] !== 'ratificar-lote')
|
|
106
106
|
throw new Error('resposta de lote inválida');
|
|
107
107
|
const job = lerDigest(raiz, partes[1]);
|
|
108
108
|
if (!job.concluidoEm || partes[2] !== job.assinatura)
|
|
109
109
|
throw new Error('lote não entregue ou assinatura divergente');
|
|
110
|
-
return (0, master_batch_1.ratificarBatch)(raiz, job.selecao, por);
|
|
110
|
+
return (0, master_batch_1.ratificarBatch)(raiz, job.selecao, por, prova);
|
|
111
111
|
}
|
|
112
112
|
function enviarDigest(opcoes) {
|
|
113
113
|
const quando = opcoes.quando ?? new Date().toISOString(), semana = sextaLocal(quando);
|
|
@@ -0,0 +1,203 @@
|
|
|
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.ERRO_PROVA_DE_CANAL = exports.CONTRATO_PEDIDO_DE_NOTA = void 0;
|
|
37
|
+
exports.exigirNotaSemHost = exigirNotaSemHost;
|
|
38
|
+
exports.arquivoDasNotas = arquivoDasNotas;
|
|
39
|
+
exports.pedirNota = pedirNota;
|
|
40
|
+
exports.pedidoDeNotaDoCodigo = pedidoDeNotaDoCodigo;
|
|
41
|
+
exports.textoDoPedidoDeNota = textoDoPedidoDeNota;
|
|
42
|
+
exports.lerNota = lerNota;
|
|
43
|
+
exports.reciboDoCanal = reciboDoCanal;
|
|
44
|
+
exports.mensagemJaUsadaEmNota = mensagemJaUsadaEmNota;
|
|
45
|
+
/**
|
|
46
|
+
* RM-048 (item 8, D8): a nota do MASTER com prova de origem humana.
|
|
47
|
+
*
|
|
48
|
+
* Ate aqui toda nota gravava o nome que viesse em `--por`: a `ork_master` do OpenClaw repassava o
|
|
49
|
+
* parametro `quem` do modelo, e `master ratificar`, `batch --aceitar` e `digest responder` idem.
|
|
50
|
+
* `autoriaHumana` so recusa nome de agente; ela mesma diz que nao e autenticacao. O dono pediu que
|
|
51
|
+
* a nota dada por ferramenta de host passe pela MESMA prova de canal que o gate ja exige.
|
|
52
|
+
*
|
|
53
|
+
* O caminho com prova e este, e ele nao cria autenticacao nova:
|
|
54
|
+
*
|
|
55
|
+
* 1. `ork master pedir <thread>` guarda um pedido de nota com codigo curto e devolve a linha
|
|
56
|
+
* "<codigo> <0 a 5> <porque>" para o canal mostrar ao dono;
|
|
57
|
+
* 2. o dono responde no Telegram; o ingresso (Hermes ou OpenClaw) assina o texto dele no
|
|
58
|
+
* endereco do pulse, com a chave do proprio canal, e o nucleo confere com a mesma
|
|
59
|
+
* `autenticarResposta` de sempre, ANTES de ler o conteudo;
|
|
60
|
+
* 3. a nota e gravada com `por` = o remetente autenticado (`telegram:<id>`) e com o recibo:
|
|
61
|
+
* canal, conta, mensagem, instante, o sha da prova e o envelope assinado guardado para a
|
|
62
|
+
* auditoria reconferir o HMAC depois.
|
|
63
|
+
*
|
|
64
|
+
* O teclado do digest semanal ("ratificar <thread> <assinatura> <classe>") passa pelo mesmo
|
|
65
|
+
* endereco. E o processo de host (Claude Code, Codex, Hermes, OpenClaw, sessao despachada) que
|
|
66
|
+
* tenta gravar nota com `--por` recebe `master.prova-de-canal`.
|
|
67
|
+
*
|
|
68
|
+
* LIMITE DITO: o canal do processo e declarado pelo ambiente (`canalDoProcesso`). Ele serve para
|
|
69
|
+
* RECUSAR, nunca para autorizar, e um agente que apague as variaveis do proprio host de proposito
|
|
70
|
+
* passa como terminal. Essa e a mesma fronteira do `humano-no-cli` do SHIP; fecha-la de vez exige o
|
|
71
|
+
* dialogo nativo do host para a nota, que fica fora desta entrega.
|
|
72
|
+
*/
|
|
73
|
+
const fs = __importStar(require("node:fs"));
|
|
74
|
+
const path = __importStar(require("node:path"));
|
|
75
|
+
const node_crypto_1 = require("node:crypto");
|
|
76
|
+
const estado_thread_1 = require("./estado-thread");
|
|
77
|
+
const thread_1 = require("./thread");
|
|
78
|
+
const ledger_1 = require("./ledger");
|
|
79
|
+
const thread_close_1 = require("./thread-close");
|
|
80
|
+
const conducao_1 = require("./conducao");
|
|
81
|
+
const pulse_consentimento_1 = require("./pulse-consentimento");
|
|
82
|
+
const monitor_lock_1 = require("./monitor-lock");
|
|
83
|
+
exports.CONTRATO_PEDIDO_DE_NOTA = 'ork.master-nota/v1';
|
|
84
|
+
exports.ERRO_PROVA_DE_CANAL = 'master.prova-de-canal';
|
|
85
|
+
const sha = (s) => (0, node_crypto_1.createHash)('sha256').update(s).digest('hex');
|
|
86
|
+
/**
|
|
87
|
+
* D8: nota em nome de pessoa, vinda de processo de host, e recusada. O canal e lido SO do
|
|
88
|
+
* ambiente: `--canal` em argv nao conta, porque quem escreve argv e justamente quem chama.
|
|
89
|
+
*/
|
|
90
|
+
function exigirNotaSemHost(ambiente = process.env) {
|
|
91
|
+
let canal;
|
|
92
|
+
try {
|
|
93
|
+
canal = (0, conducao_1.canalDoProcesso)(undefined, ambiente);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
canal = 'mcp';
|
|
97
|
+
}
|
|
98
|
+
// B2 do CHECK: `ORK_CANAL=cli` NAO absolve. A sessao despachada herda `ORK_CANAL=cli` quando a
|
|
99
|
+
// thread e conduzida do terminal, e o Claude Code e o Codex marcam os proprios processos. Qualquer
|
|
100
|
+
// marca de host ou de despacho recusa, mesmo com o canal declarado como terminal.
|
|
101
|
+
const marca = canal !== 'cli' ? canal
|
|
102
|
+
: ambiente.ORK_DISPATCH_ID ? 'sessão despachada (ORK_DISPATCH_ID)'
|
|
103
|
+
: ambiente.CLAUDECODE === '1' ? 'claude-code (CLAUDECODE)'
|
|
104
|
+
: ambiente.CODEX_SANDBOX || ambiente.CODEX_SANDBOX_NETWORK_DISABLED ? 'codex (CODEX_SANDBOX)'
|
|
105
|
+
: (ambiente.HERMES_HOME ?? '').trim() ? 'hermes (HERMES_HOME)' : undefined;
|
|
106
|
+
if (marca) {
|
|
107
|
+
throw new Error(`${exports.ERRO_PROVA_DE_CANAL}: nota em nome de pessoa vinda de ${marca} exige a prova de canal do ingresso. ` +
|
|
108
|
+
'Peça a nota com ork master pedir <thread>: o dono responde pelo Telegram com o código, e a nota é gravada com o recibo.');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function arquivoDasNotas(raiz, estadoDir) {
|
|
112
|
+
return path.join(estadoDir ?? path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery', 'monitor'), 'master-notas.json');
|
|
113
|
+
}
|
|
114
|
+
function lerNotas(raiz, estadoDir) {
|
|
115
|
+
const arquivo = arquivoDasNotas(raiz, estadoDir);
|
|
116
|
+
if (!fs.existsSync(arquivo))
|
|
117
|
+
return {};
|
|
118
|
+
const v = JSON.parse(fs.readFileSync(arquivo, 'utf8'));
|
|
119
|
+
if (v.contrato !== exports.CONTRATO_PEDIDO_DE_NOTA || !v.notas || typeof v.notas !== 'object')
|
|
120
|
+
throw new Error('pedidos de nota: estado inválido; exige inspeção');
|
|
121
|
+
return v.notas;
|
|
122
|
+
}
|
|
123
|
+
function gravarNotas(raiz, notas, estadoDir) {
|
|
124
|
+
const arquivo = arquivoDasNotas(raiz, estadoDir);
|
|
125
|
+
fs.mkdirSync(path.dirname(arquivo), { recursive: true });
|
|
126
|
+
const tmp = `${arquivo}.${process.pid}.tmp`;
|
|
127
|
+
fs.writeFileSync(tmp, JSON.stringify({ contrato: exports.CONTRATO_PEDIDO_DE_NOTA, notas }) + '\n', { mode: 0o600 });
|
|
128
|
+
fs.renameSync(tmp, arquivo);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Pede a nota ao dono. Idempotente: a mesma entrega sem nota devolve o MESMO codigo, para a
|
|
132
|
+
* linha que o dono recebeu nao vencer. So entrega provada recebe pedido de nota.
|
|
133
|
+
*/
|
|
134
|
+
function pedirNota(raiz, thread, opcoes = {}) {
|
|
135
|
+
const quando = opcoes.quando ?? new Date().toISOString();
|
|
136
|
+
(0, thread_close_1.exigirEntrega)(raiz, thread);
|
|
137
|
+
const estadoDir = opcoes.estadoDir ?? path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery', 'monitor');
|
|
138
|
+
// A4 do CHECK: o registro dos pedidos de nota tem dois escritores (pedir e o receptor do pulse);
|
|
139
|
+
// um de cada vez, pelo mesmo lock da conversa.
|
|
140
|
+
return (0, monitor_lock_1.comLockDaConversa)(estadoDir, () => {
|
|
141
|
+
const notas = lerNotas(raiz, estadoDir);
|
|
142
|
+
const existente = Object.values(notas).find(n => n.thread === thread);
|
|
143
|
+
if (existente && !notaDada(raiz, existente))
|
|
144
|
+
return existente;
|
|
145
|
+
// A1 do CHECK: o codigo da nota nao repete o de gate aberto nem o do resumo (quem chama passa).
|
|
146
|
+
const codigo = (0, pulse_consentimento_1.gerarCodigo)([...Object.keys(notas), ...(opcoes.codigosEmUso ?? [])]);
|
|
147
|
+
const pedido = { contrato: exports.CONTRATO_PEDIDO_DE_NOTA, pedidoId: (0, node_crypto_1.randomUUID)(), thread, codigo, criadoEm: quando };
|
|
148
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread), thread, ledger_1.TIPOS_DE_EVENTO.notaPedida, { fase: 'MASTER', pedidoId: pedido.pedidoId, codigo });
|
|
149
|
+
gravarNotas(raiz, { ...Object.fromEntries(Object.entries(notas).filter(([, n]) => n.thread !== thread)), [codigo]: pedido }, estadoDir);
|
|
150
|
+
return pedido;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/** A nota deste pedido ja foi dada pelo canal. */
|
|
154
|
+
function notaDada(raiz, p) {
|
|
155
|
+
return (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, p.thread)).some(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido &&
|
|
156
|
+
e.notaPedida?.pedidoId === p.pedidoId);
|
|
157
|
+
}
|
|
158
|
+
/** O pedido de nota que usa este codigo, quando ha um. */
|
|
159
|
+
function pedidoDeNotaDoCodigo(raiz, codigo, estadoDir) {
|
|
160
|
+
try {
|
|
161
|
+
return lerNotas(raiz, estadoDir)[codigo.trim().toUpperCase()];
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** A linha que o canal mostra ao dono. Uma linha de contexto e uma de resposta. */
|
|
168
|
+
function textoDoPedidoDeNota(raiz, p, canal) {
|
|
169
|
+
const t = (0, thread_1.lerThread)(raiz, p.thread);
|
|
170
|
+
const tg = canal === 'telegram';
|
|
171
|
+
return [
|
|
172
|
+
`${tg ? '🧾 ' : ''}Nota da entrega ${p.thread} (${t.nome.slice(0, 80)})`,
|
|
173
|
+
`${tg ? '• ' : '- '}Sem nota, vale a aceita por omissão, com o índice derivado do ledger ao lado.`,
|
|
174
|
+
`${tg ? '↩️ ' : ''}Responda: ${p.codigo} <0 a 5> <porquê>, por exemplo: ${p.codigo} 4 entregou o que pedi.`,
|
|
175
|
+
].join('\n');
|
|
176
|
+
}
|
|
177
|
+
/** "4 entregou o que pedi" vira nota e justificativa; o resto e devolvido como pergunta. */
|
|
178
|
+
function lerNota(resto) {
|
|
179
|
+
const m = /^\s*([0-5])(?:\s*\/\s*5)?\s*[-:,.]?\s+(\S[\s\S]{2,})$/.exec(resto);
|
|
180
|
+
return m ? { score: Number(m[1]), justificativa: m[2].trim() } : undefined;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* O recibo que acompanha a nota no `master_done`. O envelope assinado inteiro fica guardado, para
|
|
184
|
+
* que a auditoria reconfira o HMAC do canal depois (`autenticarResposta` no instante recebido). Um
|
|
185
|
+
* arquivo por mensagem: a mesma mensagem nunca vira duas notas.
|
|
186
|
+
*/
|
|
187
|
+
function reciboDoCanal(raiz, envelope, vinculo, estadoDir) {
|
|
188
|
+
const dir = path.join(estadoDir ?? path.join((0, estado_thread_1.raizDoEstado)(raiz), '.orkastery', 'monitor'), 'master-nota');
|
|
189
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
190
|
+
const arquivo = path.join(dir, `${sha(envelope.mensagem)}.json`);
|
|
191
|
+
const corpo = JSON.stringify({ contrato: exports.CONTRATO_PEDIDO_DE_NOTA, vinculo, envelope }) + '\n';
|
|
192
|
+
if (!fs.existsSync(arquivo))
|
|
193
|
+
fs.writeFileSync(arquivo, corpo, { mode: 0o600, flag: 'wx' });
|
|
194
|
+
return {
|
|
195
|
+
origem: envelope.origem, canal: envelope.canal ?? null, conta: envelope.conta ?? null, mensagem: envelope.mensagem,
|
|
196
|
+
recebidoEm: envelope.recebidoEm, recibo: sha(envelope.prova), contratoResposta: envelope.canal === undefined ? 'ork.hitl-answer/v1' : 'ork.hitl-answer/v2',
|
|
197
|
+
evidencia: path.relative((0, estado_thread_1.raizDoEstado)(raiz), arquivo), evidenciaSha256: sha(fs.readFileSync(arquivo, 'utf8')), ...vinculo,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** Mensagem ja usada numa nota desta thread nao vale de novo, igual ao gate. */
|
|
201
|
+
function mensagemJaUsadaEmNota(raiz, thread, mensagem) {
|
|
202
|
+
return (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread)).some(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido && e.mensagem === mensagem);
|
|
203
|
+
}
|
package/dist/master.js
CHANGED
|
@@ -88,6 +88,7 @@ const horario_1 = require("./horario");
|
|
|
88
88
|
const indice_1 = require("./indice");
|
|
89
89
|
const ship_1 = require("./ship");
|
|
90
90
|
const fabrica_publicar_1 = require("./fabrica-publicar");
|
|
91
|
+
const fechamento_1 = require("./fechamento");
|
|
91
92
|
/** Identificador do contrato congelado do MASTER log. */
|
|
92
93
|
exports.CONTRATO_MASTER_LOG = 'ork.master-log/v1';
|
|
93
94
|
/** Versao do contrato. Uma mudanca de contrato exige uma versao nova, nao um campo novo. */
|
|
@@ -392,7 +393,10 @@ function registrarMaster(raiz, id, opcoes) {
|
|
|
392
393
|
classesDeFalha: masterLog.classesDeFalha, regime: postmortem.score.regime,
|
|
393
394
|
contrato: exports.CONTRATO_MASTER_LOG, arquivo: path.relative((0, estado_thread_1.raizDoEstado)(raiz), r.caminhoMasterLog), estado: 'thread fechada',
|
|
394
395
|
masterLogSha256: hashDocumento(r.caminhoMasterLog), postmortemSha256: hashDocumento(r.caminhoPostmortem),
|
|
396
|
+
...(opcoes.prova ? { prova: 'ingresso-autenticado', ...opcoes.prova } : {}),
|
|
395
397
|
});
|
|
398
|
+
// RM-037 (rm037noite): a thread fechada solta o que segurava, com registro no ledger dela.
|
|
399
|
+
(0, fechamento_1.liberarAoFechar)(raiz, id);
|
|
396
400
|
return r;
|
|
397
401
|
}
|
|
398
402
|
exports.CONTRATO_MASTER_PENDENTE = 'ork.master-pending/v1';
|
|
@@ -0,0 +1,164 @@
|
|
|
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.consultaExperienciaSchema = void 0;
|
|
37
|
+
exports.apresentarConsulta = apresentarConsulta;
|
|
38
|
+
exports.consultarPainel = consultarPainel;
|
|
39
|
+
exports.criarLeitorExperiencia = criarLeitorExperiencia;
|
|
40
|
+
exports.registrarConsultasExperiencia = registrarConsultasExperiencia;
|
|
41
|
+
/** Consultas do projeto fixado. Nunca reserva item, publica máquina ou executa push. */
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const path = __importStar(require("node:path"));
|
|
44
|
+
const node_child_process_1 = require("node:child_process");
|
|
45
|
+
const node_crypto_1 = require("node:crypto");
|
|
46
|
+
const zod_1 = require("zod");
|
|
47
|
+
const roadmap_reservas_1 = require("./roadmap-reservas");
|
|
48
|
+
const fabrica_estado_1 = require("./fabrica-estado");
|
|
49
|
+
const mcp_ship_1 = require("./mcp-ship");
|
|
50
|
+
const mcp_git_1 = require("./mcp-git");
|
|
51
|
+
exports.consultaExperienciaSchema = zod_1.z.object({}).strict();
|
|
52
|
+
function apresentarConsulta(painel) {
|
|
53
|
+
const estado = painel.atualizado ? 'atualizado' : painel.ponta ? 'desatualizado' : 'indisponivel';
|
|
54
|
+
return { estado, dados: estado === 'indisponivel' ? null : painel,
|
|
55
|
+
motivo: estado === 'atualizado' ? null : 'mcp.experiencia.remoto.indisponivel' };
|
|
56
|
+
}
|
|
57
|
+
const indisponivel = () => ({ estado: 'indisponivel', dados: null, motivo: 'mcp.experiencia.consulta.indisponivel' });
|
|
58
|
+
/** Chamada somente depois de validar a fixação do worker. */
|
|
59
|
+
function consultarPainel(raiz, tipo) {
|
|
60
|
+
try {
|
|
61
|
+
return apresentarConsulta(tipo === 'reservas' ? (0, roadmap_reservas_1.listarReservas)(raiz, { remoto: 'origin' })
|
|
62
|
+
: (0, fabrica_estado_1.lerFabrica)(raiz, { remoto: 'origin', timeoutMs: 15000 }));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return indisponivel();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Usa as mesmas guardas de transporte do núcleo; não cria autorização de SHIP. */
|
|
69
|
+
function assinatura(raiz, transporte) {
|
|
70
|
+
(0, mcp_ship_1.criarPerfilShipMcp)(raiz, transporte);
|
|
71
|
+
const g = path.join(raiz, '.git');
|
|
72
|
+
(0, mcp_git_1.perfilGitMcp)(raiz, g, g, 'consulta-experiencia', []);
|
|
73
|
+
const st = fs.statSync(raiz);
|
|
74
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify([st.dev, st.ino, fs.realpathSync(raiz),
|
|
75
|
+
(0, mcp_git_1.gitPassivoMcp)(raiz, ['remote', 'get-url', '--all', 'origin']),
|
|
76
|
+
(0, mcp_git_1.gitPassivoMcp)(raiz, ['config', '--null', '--list'])])).digest('hex');
|
|
77
|
+
}
|
|
78
|
+
const PRAZO_DA_CONSULTA_MS = 90000;
|
|
79
|
+
/**
|
|
80
|
+
* O worker herda somente ambiente permitido; nunca modifica env do servidor. Roda assíncrono para
|
|
81
|
+
* o servidor MCP seguir atendendo as outras tools durante a consulta remota, e em grupo próprio:
|
|
82
|
+
* prazo ou cancelamento da chamada matam o worker e o git que ele abriu.
|
|
83
|
+
*/
|
|
84
|
+
function criarLeitorExperiencia(raiz, transporte, prazoMs = PRAZO_DA_CONSULTA_MS) {
|
|
85
|
+
let fixacao = null;
|
|
86
|
+
try {
|
|
87
|
+
fixacao = assinatura(raiz, transporte);
|
|
88
|
+
}
|
|
89
|
+
catch { /* ferramenta continua descoberta, com lacuna explícita */ }
|
|
90
|
+
return (tipo, signal) => new Promise(resolve => {
|
|
91
|
+
if (!fixacao || signal?.aborted) {
|
|
92
|
+
resolve(indisponivel());
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const grupo = process.platform !== 'win32';
|
|
96
|
+
const filho = (0, node_child_process_1.spawn)(process.execPath, [__filename, '--consulta-experiencia'], {
|
|
97
|
+
cwd: raiz, env: { ...(0, mcp_git_1.ambienteGitMcp)(), SSH_AUTH_SOCK: process.env.SSH_AUTH_SOCK },
|
|
98
|
+
stdio: ['pipe', 'pipe', 'ignore'], detached: grupo,
|
|
99
|
+
});
|
|
100
|
+
let saida = '', terminado = false;
|
|
101
|
+
const concluir = (r) => {
|
|
102
|
+
if (terminado)
|
|
103
|
+
return;
|
|
104
|
+
terminado = true;
|
|
105
|
+
clearTimeout(prazo);
|
|
106
|
+
signal?.removeEventListener('abort', abortar);
|
|
107
|
+
resolve(r);
|
|
108
|
+
};
|
|
109
|
+
const abortar = () => {
|
|
110
|
+
if (terminado)
|
|
111
|
+
return;
|
|
112
|
+
filho.stdout?.destroy();
|
|
113
|
+
try {
|
|
114
|
+
if (filho.pid)
|
|
115
|
+
process.kill(grupo ? -filho.pid : filho.pid, 'SIGKILL');
|
|
116
|
+
}
|
|
117
|
+
catch { /* já terminou */ }
|
|
118
|
+
concluir(indisponivel());
|
|
119
|
+
};
|
|
120
|
+
const prazo = setTimeout(abortar, prazoMs);
|
|
121
|
+
signal?.addEventListener('abort', abortar, { once: true });
|
|
122
|
+
filho.stdout.setEncoding('utf8');
|
|
123
|
+
filho.stdout.on('data', (parte) => { saida += parte; if (saida.length > 1024 * 1024)
|
|
124
|
+
abortar(); });
|
|
125
|
+
filho.stdin.on('error', () => undefined);
|
|
126
|
+
filho.on('error', () => concluir(indisponivel()));
|
|
127
|
+
filho.on('close', (codigo, sinal) => {
|
|
128
|
+
if (codigo !== 0 || sinal) {
|
|
129
|
+
concluir(indisponivel());
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
concluir(JSON.parse(saida));
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
concluir(indisponivel());
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
filho.stdin.end(JSON.stringify({ raiz, transporte, fixacao, tipo }));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function registrarConsultasExperiencia(registrar, opcoes) {
|
|
143
|
+
const ler = criarLeitorExperiencia(opcoes.raiz, opcoes.transporte);
|
|
144
|
+
for (const [nome, tipo] of [['ork_roadmap_reservas', 'reservas'], ['ork_fabrica', 'fabrica']]) {
|
|
145
|
+
registrar(nome, { description: 'Consulta de ' + tipo + ' do projeto e origin fixados; distingue remoto atualizado, cópia desatualizada e indisponibilidade. Não reserva nem publica.',
|
|
146
|
+
inputSchema: exports.consultaExperienciaSchema, annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true } }, async (_args, extra) => {
|
|
147
|
+
opcoes.carregar();
|
|
148
|
+
return { content: [{ type: 'text', text: JSON.stringify(await ler(tipo, extra.signal)) }] };
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (require.main === module && process.argv[2] === '--consulta-experiencia') {
|
|
153
|
+
try {
|
|
154
|
+
const p = zod_1.z.object({ raiz: zod_1.z.string(), transporte: zod_1.z.enum(['github-ssh', 'bare-local']),
|
|
155
|
+
fixacao: zod_1.z.string().regex(/^[a-f0-9]{64}$/), tipo: zod_1.z.enum(['reservas', 'fabrica']) }).strict()
|
|
156
|
+
.parse(JSON.parse(fs.readFileSync(0, 'utf8')));
|
|
157
|
+
if (assinatura(p.raiz, p.transporte) !== p.fixacao)
|
|
158
|
+
throw Error('scope.changed');
|
|
159
|
+
process.stdout.write(JSON.stringify(consultarPainel(p.raiz, p.tipo)));
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
process.stdout.write(JSON.stringify(indisponivel()));
|
|
163
|
+
}
|
|
164
|
+
}
|
package/dist/mcp-git.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.HOOKS_ESTRITOS = exports.HOOKS_DO_COMMIT = exports.HOOKS_INERTES_DO_COMMIT = void 0;
|
|
36
37
|
exports.estadoGitMcp = estadoGitMcp;
|
|
37
38
|
exports.commitMcp = commitMcp;
|
|
38
39
|
exports.perfilGitMcp = perfil;
|
|
@@ -41,8 +42,8 @@ exports.caminhoFisicoGitMcp = fisico;
|
|
|
41
42
|
exports.metadadosGitMcp = arvoreMetadados;
|
|
42
43
|
exports.configuracaoPassivaGitMcp = configPassiva;
|
|
43
44
|
exports.ambienteGitMcp = ambiente;
|
|
44
|
-
/** Commit estreito no núcleo instalado. Repositórios com hooks/helpers
|
|
45
|
-
* explicitamente indisponíveis; nenhum hook ou configuração é desativado. */
|
|
45
|
+
/** Commit estreito no núcleo instalado. Repositórios com hooks/helpers que as operações
|
|
46
|
+
* executariam ficam explicitamente indisponíveis; nenhum hook ou configuração é desativado. */
|
|
46
47
|
const fs = __importStar(require("node:fs"));
|
|
47
48
|
const path = __importStar(require("node:path"));
|
|
48
49
|
const node_crypto_1 = require("node:crypto");
|
|
@@ -130,6 +131,14 @@ function configPassiva(chave, valor, credenciaisInertes = false) {
|
|
|
130
131
|
return valor.length <= 8192 && !valor.includes('\0');
|
|
131
132
|
if (['user.name', 'user.email'].includes(chave))
|
|
132
133
|
return !!valor.trim() && valor.length <= 512 && !/[\x00-\x1f]/.test(valor);
|
|
134
|
+
// RM-051: só afrouxa a checagem de dono, e o Git só a lê no sistema ou no global; o repositório
|
|
135
|
+
// continua conferido chave a chave aqui. A imagem do runner hospedado do GitHub grava `safe.directory=*`.
|
|
136
|
+
if (chave === 'safe.directory')
|
|
137
|
+
return valor.length <= 4096 && !/[\x00-\x1f\x7f]/.test(valor);
|
|
138
|
+
// RM-037 (defeitosdeco D-3): a seção do próprio produto (por exemplo `orkastery.cortefeito`, lida
|
|
139
|
+
// pela trava do corte no pre-push). O Git nunca lê essa seção, então ela não executa nada.
|
|
140
|
+
if (/^orkastery\.[a-z0-9-]+$/.test(chave))
|
|
141
|
+
return valor.length <= 512 && !/[\x00-\x1f\x7f]/.test(valor);
|
|
133
142
|
if (['core.filemode', 'core.logallrefupdates', 'core.ignorecase', 'core.precomposeunicode'].includes(chave))
|
|
134
143
|
return /^(true|false)$/.test(valor);
|
|
135
144
|
if (chave === 'core.repositoryformatversion')
|
|
@@ -195,7 +204,22 @@ function atributosPassivos(wt, id, selecionados) {
|
|
|
195
204
|
}
|
|
196
205
|
return resultados.join('\0');
|
|
197
206
|
}
|
|
198
|
-
|
|
207
|
+
/**
|
|
208
|
+
* RM-037 (defeitosdeco D-3): hooks que os comandos Git do status e do commit (`config`, `ls-files`,
|
|
209
|
+
* `check-attr`, `rev-parse`, `symbolic-ref`, `diff`, `diff-tree`, `add` e `commit` sem `--amend`)
|
|
210
|
+
* nunca invocam. Lista positiva: nome fora dela (`pre-commit`, `commit-msg`, `reference-transaction`,
|
|
211
|
+
* `post-index-change`, nome que o Git criar amanhã) continua recusado, e nada é desativado.
|
|
212
|
+
*/
|
|
213
|
+
exports.HOOKS_INERTES_DO_COMMIT = new Set(['pre-push', 'pre-rebase', 'post-checkout', 'post-merge',
|
|
214
|
+
'pre-receive', 'update', 'proc-receive', 'post-receive', 'post-update', 'push-to-checkout', 'applypatch-msg',
|
|
215
|
+
'pre-applypatch', 'post-applypatch', 'sendemail-validate', 'pre-merge-commit', 'post-rewrite',
|
|
216
|
+
'p4-changelist', 'p4-prepare-changelist', 'p4-post-changelist', 'p4-pre-submit']);
|
|
217
|
+
exports.HOOKS_DO_COMMIT = { inertes: exports.HOOKS_INERTES_DO_COMMIT,
|
|
218
|
+
correcao: 'o commit do MCP o executaria; commite pelo shell da worktree, onde o hook roda como sempre' };
|
|
219
|
+
/** Padrão estrito (SHIP): merge e push executariam qualquer hook, inclusive o pre-push. */
|
|
220
|
+
exports.HOOKS_ESTRITOS = { inertes: new Set(),
|
|
221
|
+
correcao: 'o SHIP do MCP o executaria (merge ou push); entregue por PR com o bundle do ork ci prepare, ou pelo ork ship do CLI' };
|
|
222
|
+
function perfil(wt, comum, gitdir, id, selecionados, hooksDaOperacao = exports.HOOKS_ESTRITOS) {
|
|
199
223
|
fisico(path.dirname(comum), comum);
|
|
200
224
|
fisico(comum, gitdir);
|
|
201
225
|
for (const nome of ['objects', 'refs', 'logs', 'info'])
|
|
@@ -224,9 +248,11 @@ function perfil(wt, comum, gitdir, id, selecionados) {
|
|
|
224
248
|
if (fs.lstatSync(hooks, { throwIfNoEntry: false })) {
|
|
225
249
|
fisico(base, hooks);
|
|
226
250
|
for (const nome of fs.readdirSync(hooks)) {
|
|
227
|
-
const f = path.join(hooks, nome), s = fs.lstatSync(f);
|
|
228
|
-
if (!s.isFile() || s.isSymbolicLink()
|
|
229
|
-
falha(
|
|
251
|
+
const f = path.join(hooks, nome), s = fs.lstatSync(f), rotulo = nome.replace(/[^A-Za-z0-9._-]/g, '?').slice(0, 64);
|
|
252
|
+
if (!s.isFile() || s.isSymbolicLink())
|
|
253
|
+
falha(`execution-profile.unsupported: hooks preservados (${rotulo} nao e arquivo regular)`);
|
|
254
|
+
if (!nome.endsWith('.sample') && (s.mode & 0o111) !== 0 && !hooksDaOperacao.inertes.has(nome))
|
|
255
|
+
falha(`execution-profile.unsupported: hooks preservados (${rotulo}); ${hooksDaOperacao.correcao}`);
|
|
230
256
|
}
|
|
231
257
|
}
|
|
232
258
|
}
|
|
@@ -259,7 +285,7 @@ function estadoGitMcp(raiz, threadId) {
|
|
|
259
285
|
if (!match)
|
|
260
286
|
falha('worktree.invalid');
|
|
261
287
|
const comum = path.join(raiz, '.git'), gitdir = path.resolve(wt, match[1].trim());
|
|
262
|
-
perfil(wt, comum, gitdir, t.id, []);
|
|
288
|
+
perfil(wt, comum, gitdir, t.id, [], exports.HOOKS_DO_COMMIT);
|
|
263
289
|
if ((0, estado_thread_1.raizDoEstado)(wt) !== raiz)
|
|
264
290
|
falha('worktree.invalid');
|
|
265
291
|
const branch = (0, worktree_1.branchDaWorktree)(t), destino = c.manifesto.worktree.base_branch;
|
|
@@ -300,10 +326,10 @@ function executar(raiz, p) {
|
|
|
300
326
|
fisico(comum, gitdir);
|
|
301
327
|
if ((0, estado_thread_1.raizDoEstado)(wt) !== raiz)
|
|
302
328
|
falha('worktree.invalid');
|
|
303
|
-
const originalPerfil = perfil(wt, comum, gitdir, t.id, p.paths);
|
|
329
|
+
const originalPerfil = perfil(wt, comum, gitdir, t.id, p.paths, exports.HOOKS_DO_COMMIT);
|
|
304
330
|
const conferir = () => {
|
|
305
331
|
(0, mcp_artifacts_1.validarArquivosEstadoMcp)(raiz, t.id);
|
|
306
|
-
if (perfil(wt, comum, gitdir, t.id, p.paths) !== originalPerfil)
|
|
332
|
+
if (perfil(wt, comum, gitdir, t.id, p.paths, exports.HOOKS_DO_COMMIT) !== originalPerfil)
|
|
307
333
|
falha('execution-profile.changed');
|
|
308
334
|
if (git(wt, ['rev-parse', 'HEAD']).trim() !== p.expectedHead)
|
|
309
335
|
falha('head.stale');
|
|
@@ -344,7 +370,7 @@ function executar(raiz, p) {
|
|
|
344
370
|
git(wt, ['commit', '-m', p.mensagem, '--', ...p.paths]);
|
|
345
371
|
commit = git(wt, ['rev-parse', 'HEAD']).trim();
|
|
346
372
|
});
|
|
347
|
-
if (perfil(wt, comum, gitdir, t.id, p.paths) !== originalPerfil)
|
|
373
|
+
if (perfil(wt, comum, gitdir, t.id, p.paths, exports.HOOKS_DO_COMMIT) !== originalPerfil)
|
|
348
374
|
falha('execution-profile.changed');
|
|
349
375
|
estadoAuditado = (0, estado_thread_1.auditarEstado)(raiz, t.id, wt).nivel === 'ok';
|
|
350
376
|
if (!estadoAuditado)
|
package/dist/mcp-install.js
CHANGED
|
@@ -47,7 +47,9 @@ const node_util_1 = require("node:util");
|
|
|
47
47
|
const smol_toml_1 = require("smol-toml");
|
|
48
48
|
const manifest_1 = require("./manifest");
|
|
49
49
|
exports.TOOLS_DONO_CODEX = ['ork_thread_new', 'ork_phase_run', 'ork_request_decision'];
|
|
50
|
-
|
|
50
|
+
// RM-037 (rm037defeito, defeito 1): a decisao autonoma da sessao entra com as outras mutacoes do filho;
|
|
51
|
+
// sem o grant, o codex com approval_policy never recusaria a chamada.
|
|
52
|
+
exports.TOOLS_FILHO_CODEX = ['ork_artifact_write', 'ork_claim_add', 'ork_decision_record', 'ork_git_commit', 'ork_verify', 'ork_ship'];
|
|
51
53
|
// Brain mutation tools are deliberately excluded from the existing opt-in bundle.
|
|
52
54
|
// A native integration must request exact startup grants plus scoped activation.
|
|
53
55
|
var company_brain_mcp_1 = require("./company-brain-mcp");
|
package/dist/mcp-maestro.js
CHANGED
|
@@ -9,7 +9,7 @@ const maestro_cli_1 = require("./maestro-cli");
|
|
|
9
9
|
exports.maestroInputSchema = zod_1.z.object({ threadId: zod_1.z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/).optional(),
|
|
10
10
|
section: zod_1.z.enum(maestro_contract_1.SECTION_NAMES).optional(), offset: zod_1.z.number().int().min(0).max(100000).optional() }).strict();
|
|
11
11
|
function registerMaestro(register, options) {
|
|
12
|
-
register('ork_maestro', { description: 'Panorama Maestro somente leitura, fixado ao projeto e ao escopo da sessão; cobertura, lacunas e próximas ações pelos endpoints existentes.',
|
|
12
|
+
register('ork_maestro', { description: 'Panorama Maestro somente leitura, fixado ao projeto e ao escopo da sessão; cobertura, lacunas e próximas ações pelos endpoints existentes. Não lê o roadmap, as reservas nem as outras máquinas (veja notConsulted): zero threads nunca é roadmap vazio; para o roadmap, com as threads de todas as máquinas, use ork_network_roadmap.',
|
|
13
13
|
inputSchema: exports.maestroInputSchema, annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false } }, async (args) => {
|
|
14
14
|
options.load();
|
|
15
15
|
if ((args.section === undefined) !== (args.offset === undefined))
|
|
@@ -17,7 +17,8 @@ function registerMaestro(register, options) {
|
|
|
17
17
|
const threadId = args.threadId ?? options.threadId;
|
|
18
18
|
if (threadId)
|
|
19
19
|
options.checkThread(threadId);
|
|
20
|
-
|
|
20
|
+
// RM-052 (D5): fixado no projeto servido; os outros projetos da maquina nao entram na conta.
|
|
21
|
+
const context = (0, maestro_discovery_1.discoverMaestro)({ cwd: options.root, pinned: options.root, countOtherProjects: false });
|
|
21
22
|
const result = (0, maestro_cli_1.readMaestro)(context, { threadId, native: true, offsets: args.section ? { [args.section]: args.offset } : undefined,
|
|
22
23
|
host: { tools: options.tools(), child: !!options.threadId } });
|
|
23
24
|
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|