@orkastery/cli 0.4.3 → 0.5.1
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/README.md +11 -2
- 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/onboarding.md +3 -2
- 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 +45 -2
- package/adapters/openclaw/dist/hitl-ingress.js +37 -3
- package/adapters/openclaw/dist/index.js +93 -21
- package/adapters/openclaw/openclaw.plugin.json +10 -1
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +32 -3
- package/adapters/openclaw/src/index.ts +109 -21
- 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 +24 -7
- package/dist/auditrun.js +1 -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/claim-lint.js +3 -1
- 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 +71 -18
- package/dist/decisao-autonoma.js +42 -0
- package/dist/docs.js +135 -25
- package/dist/doctor.js +242 -32
- package/dist/entrega-pr.js +116 -5
- package/dist/experiencia-instalacao.js +256 -0
- package/dist/experiencia.js +72 -0
- package/dist/fabrica-estado.js +63 -12
- package/dist/fechamento.js +105 -0
- package/dist/fix.js +3 -3
- package/dist/forja.js +435 -0
- package/dist/gates.js +9 -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 +57 -13
- package/dist/hitl-texto-livre.js +150 -0
- package/dist/hosts.js +92 -3
- package/dist/index.js +637 -45
- package/dist/indice-vetorial.js +317 -0
- package/dist/init.js +24 -5
- package/dist/integracoes-locais.js +3 -1
- package/dist/intelligence-benchmark-contract.js +570 -0
- package/dist/intelligence-graph-cli.js +584 -0
- package/dist/intelligence-graph-contract.js +636 -0
- package/dist/intelligence-graph-extract-md.js +487 -0
- package/dist/intelligence-graph-extract-ts.js +980 -0
- package/dist/intelligence-graph-extract.js +546 -0
- package/dist/intelligence-graph-index.js +693 -0
- package/dist/intelligence-graph-parsers.js +327 -0
- package/dist/intelligence-graph-query.js +344 -0
- package/dist/intelligence-graph-repo.js +197 -0
- package/dist/leases.js +100 -0
- package/dist/ledger.js +23 -0
- package/dist/licoes.js +5 -4
- package/dist/liveness.js +2 -1
- package/dist/maestro-cli.js +10 -1
- package/dist/maestro-contract.js +5 -1
- package/dist/maestro-discovery.js +16 -2
- package/dist/maestro-runtime.js +3 -0
- package/dist/maestro-snapshot.js +6 -2
- package/dist/manifest.js +166 -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-artifacts.js +2 -0
- package/dist/mcp-experiencia.js +164 -0
- package/dist/mcp-git.js +64 -12
- package/dist/mcp-grafo-worker.js +91 -0
- package/dist/mcp-grafo.js +233 -0
- package/dist/mcp-install.js +5 -2
- package/dist/mcp-maestro.js +3 -2
- package/dist/mcp-server.js +93 -5
- package/dist/mcp-ship.js +2 -0
- package/dist/mcp-verify.js +3 -1
- package/dist/memoria.js +147 -1
- package/dist/network-roadmap.js +907 -0
- package/dist/ocupacao.js +43 -3
- package/dist/onboarding.js +122 -11
- package/dist/orkmind.js +165 -9
- package/dist/orquestracao.js +2 -1
- package/dist/parado-no-condutor.js +933 -0
- package/dist/phase.js +166 -13
- package/dist/policies.js +29 -2
- package/dist/projeto-alvo.js +551 -0
- package/dist/prompts.js +1 -1
- package/dist/prova-ativacao.js +345 -0
- package/dist/pulse-consentimento.js +4 -2
- package/dist/pulse-delivery.js +32 -6
- package/dist/pulse-resposta.js +674 -49
- package/dist/pulse.js +74 -3
- package/dist/retry.js +51 -8
- package/dist/roadmap-reservas.js +262 -20
- package/dist/roadmap-status.js +348 -0
- package/dist/runtime-context.js +5 -1
- package/dist/sessoes-inventario.js +7 -1
- package/dist/sessoes.js +4 -1
- package/dist/ship.js +25 -1
- package/dist/thread-close.js +3 -0
- package/dist/thread.js +21 -2
- package/dist/util.js +71 -4
- package/dist/verify.js +6 -5
- package/dist/worktree.js +29 -6
- package/eval/casos/onboarding.json +1 -1
- 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 +10 -2
- 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/skills/phases/ship-release/SKILL.md +6 -3
|
@@ -0,0 +1,197 @@
|
|
|
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.TENANT_PADRAO = void 0;
|
|
37
|
+
exports.identidadeDaLeitura = identidadeDaLeitura;
|
|
38
|
+
exports.revisaoDaArvore = revisaoDaArvore;
|
|
39
|
+
exports.headsDasArvores = headsDasArvores;
|
|
40
|
+
exports.revisoesAncestrais = revisoesAncestrais;
|
|
41
|
+
exports.lerRepositorio = lerRepositorio;
|
|
42
|
+
/**
|
|
43
|
+
* RM-031 KG2 (D8): leitura do repositorio Git local para o extrator. E a unica borda de E/S do
|
|
44
|
+
* KG2: lista os arquivos rastreados, le os bytes da arvore de trabalho e fixa a revisao. Nao
|
|
45
|
+
* executa shell nem texto vindo do repositorio; o Git roda com argumentos fixos. O KG3 usa daqui a
|
|
46
|
+
* identidade da leitura e a revisao da arvore limpa, sem ler os arquivos.
|
|
47
|
+
*
|
|
48
|
+
* Fica fora e declarado: link simbolico, submodulo, arquivo em conflito, arquivo rastreado que
|
|
49
|
+
* sumiu da arvore, arquivo cujo caminho real sai da raiz e caminho que nao e UTF-8. A revisao so e
|
|
50
|
+
* o HEAD quando nada rastreado mudou e os bytes lidos sao os blobs do indice (sem filtro do Git).
|
|
51
|
+
*/
|
|
52
|
+
const node_crypto_1 = require("node:crypto");
|
|
53
|
+
const fs = __importStar(require("node:fs"));
|
|
54
|
+
const path = __importStar(require("node:path"));
|
|
55
|
+
const node_child_process_1 = require("node:child_process");
|
|
56
|
+
const yaml_1 = require("./yaml");
|
|
57
|
+
exports.TENANT_PADRAO = 'local';
|
|
58
|
+
const ID_DE_REPOSITORIO = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
59
|
+
/** Git com argumentos fixos; o fsmonitor do repositorio nao roda (seria comando externo configurado nele). */
|
|
60
|
+
function git(raiz, args) {
|
|
61
|
+
const r = (0, node_child_process_1.spawnSync)('git', ['-c', 'core.fsmonitor=false', ...args], {
|
|
62
|
+
cwd: raiz, maxBuffer: 512 * 1024 * 1024, env: { ...process.env, GIT_OPTIONAL_LOCKS: '0' },
|
|
63
|
+
});
|
|
64
|
+
return { ok: r.status === 0, saida: r.stdout ?? Buffer.alloc(0) };
|
|
65
|
+
}
|
|
66
|
+
function obrigatorio(raiz, args) {
|
|
67
|
+
const r = git(raiz, args);
|
|
68
|
+
if (!r.ok)
|
|
69
|
+
throw new Error(`extracao.repositorio.git-falhou em git ${args[0]}`);
|
|
70
|
+
return r.saida;
|
|
71
|
+
}
|
|
72
|
+
const utf8 = (b) => {
|
|
73
|
+
try {
|
|
74
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(b);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
/** Nome do projeto no `orkastery.yaml`, quando ha um valido na raiz. */
|
|
81
|
+
function nomeDoProjeto(raiz) {
|
|
82
|
+
const arquivo = path.join(raiz, 'orkastery.yaml');
|
|
83
|
+
if (!fs.existsSync(arquivo))
|
|
84
|
+
return null;
|
|
85
|
+
try {
|
|
86
|
+
const dados = (0, yaml_1.lerYaml)(fs.readFileSync(arquivo, 'utf8'));
|
|
87
|
+
const projeto = dados && typeof dados === 'object' && !Array.isArray(dados) ? dados.project : null;
|
|
88
|
+
const nome = projeto && typeof projeto === 'object' && !Array.isArray(projeto) ? projeto.name : null;
|
|
89
|
+
return typeof nome === 'string' && ID_DE_REPOSITORIO.test(nome) ? nome : null;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Repositorio, tenant e ACL da leitura: os informados, ou os padroes (D8). */
|
|
96
|
+
function identidadeDaLeitura(raiz, opcoes = {}) {
|
|
97
|
+
const repositorio = opcoes.repository_id ?? nomeDoProjeto(raiz);
|
|
98
|
+
if (!repositorio || !ID_DE_REPOSITORIO.test(repositorio))
|
|
99
|
+
throw new Error('extracao.repositorio.sem-id');
|
|
100
|
+
return { repository_id: repositorio, tenant_id: opcoes.tenant_id ?? exports.TENANT_PADRAO, acl_refs: [...(opcoes.acl_refs ?? [`repo:${repositorio}:leitura`])] };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* RM-031 KG3 (D3): o HEAD e se a arvore esta limpa nos rastreados, sem ler arquivo nenhum. O filtro
|
|
104
|
+
* do Git (eol, LFS) so aparece lendo os bytes: quem indexa confere a revisao do `lerRepositorio`.
|
|
105
|
+
*/
|
|
106
|
+
function revisaoDaArvore(diretorio) {
|
|
107
|
+
const raiz = obrigatorio(diretorio, ['rev-parse', '--show-toplevel']).toString('utf8').trim();
|
|
108
|
+
const head = git(raiz, ['rev-parse', '--verify', '-q', 'HEAD']);
|
|
109
|
+
if (!head.ok)
|
|
110
|
+
return { raiz, head: null, motivo: 'sem-commit' };
|
|
111
|
+
const sujo = obrigatorio(raiz, ['status', '--porcelain=v1', '-z', '--untracked-files=no']).length > 0;
|
|
112
|
+
return { raiz, head: head.saida.toString('utf8').trim(), motivo: sujo ? 'working-tree-modified' : null };
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* RM-031 KG3 (CHECK rodada 1, A6): o HEAD de cada arvore do repositorio (a principal e as worktrees),
|
|
116
|
+
* pelo `git worktree list --porcelain`. O estado do indice e compartilhado entre elas.
|
|
117
|
+
*/
|
|
118
|
+
function headsDasArvores(diretorio) {
|
|
119
|
+
const saida = obrigatorio(diretorio, ['worktree', 'list', '--porcelain']).toString('utf8');
|
|
120
|
+
return [...new Set(saida.split('\n').filter((l) => /^HEAD [0-9a-f]{40,64}$/.test(l)).map((l) => l.slice(5)))].sort();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* RM-031 KG4 (D1): o HEAD e as revisoes ancestrais dele (`git rev-list`), da mais recente para a mais
|
|
124
|
+
* antiga, ate o limite. Sem commit, ou com o Git falhando, nao ha ancestral.
|
|
125
|
+
*/
|
|
126
|
+
function revisoesAncestrais(diretorio, limite) {
|
|
127
|
+
const raiz = obrigatorio(diretorio, ['rev-parse', '--show-toplevel']).toString('utf8').trim();
|
|
128
|
+
const r = git(raiz, ['rev-list', `--max-count=${Math.max(1, Math.floor(limite))}`, 'HEAD']);
|
|
129
|
+
return r.ok ? r.saida.toString('utf8').split('\n').filter((l) => /^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(l)) : [];
|
|
130
|
+
}
|
|
131
|
+
/** Le o repositorio que contem `diretorio` e devolve a entrada do extrator. */
|
|
132
|
+
function lerRepositorio(diretorio, opcoes = {}) {
|
|
133
|
+
const raiz = obrigatorio(diretorio, ['rev-parse', '--show-toplevel']).toString('utf8').trim();
|
|
134
|
+
const { repository_id: repositorio, tenant_id, acl_refs } = identidadeDaLeitura(raiz, opcoes);
|
|
135
|
+
// `-s` traz modo e estagio: 120000 e link simbolico, 160000 e submodulo, estagio > 0 e conflito.
|
|
136
|
+
const registros = obrigatorio(raiz, ['ls-files', '-z', '-s', '--full-name']);
|
|
137
|
+
const porCaminho = new Map(), excluidas = [];
|
|
138
|
+
let inicio = 0;
|
|
139
|
+
for (let i = 0; i < registros.length; i++) {
|
|
140
|
+
if (registros[i] !== 0)
|
|
141
|
+
continue;
|
|
142
|
+
const registro = registros.subarray(inicio, i);
|
|
143
|
+
inicio = i + 1;
|
|
144
|
+
const tab = registro.indexOf(0x09);
|
|
145
|
+
if (tab < 0)
|
|
146
|
+
continue;
|
|
147
|
+
const [modo, objeto, estagio] = registro.subarray(0, tab).toString('latin1').split(' ');
|
|
148
|
+
const caminho = utf8(registro.subarray(tab + 1));
|
|
149
|
+
if (caminho === null) {
|
|
150
|
+
excluidas.push({ path: registro.subarray(tab + 1).toString('latin1'), motivo: 'caminho-nao-utf8' });
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const atual = porCaminho.get(caminho);
|
|
154
|
+
porCaminho.set(caminho, { modo, objeto, estagios: (atual?.estagios ?? 0) + (estagio === '0' ? 0 : 1) });
|
|
155
|
+
}
|
|
156
|
+
const fontes = [], raizReal = fs.realpathSync(raiz);
|
|
157
|
+
let filtrado = false;
|
|
158
|
+
for (const [caminho, { modo, objeto, estagios }] of porCaminho) {
|
|
159
|
+
if (estagios > 0)
|
|
160
|
+
excluidas.push({ path: caminho, motivo: 'conflito-de-merge' });
|
|
161
|
+
else if (modo === '120000')
|
|
162
|
+
excluidas.push({ path: caminho, motivo: 'link-simbolico' });
|
|
163
|
+
else if (modo === '160000')
|
|
164
|
+
excluidas.push({ path: caminho, motivo: 'submodulo' });
|
|
165
|
+
else {
|
|
166
|
+
const absoluto = path.join(raiz, caminho);
|
|
167
|
+
const st = fs.lstatSync(absoluto, { throwIfNoEntry: false });
|
|
168
|
+
if (!st)
|
|
169
|
+
excluidas.push({ path: caminho, motivo: 'ausente-na-arvore' });
|
|
170
|
+
else if (!st.isFile())
|
|
171
|
+
excluidas.push({ path: caminho, motivo: 'nao-e-arquivo' });
|
|
172
|
+
// Pasta do caminho trocada por link simbolico levaria a leitura para fora do repositorio.
|
|
173
|
+
else if (!fs.realpathSync(absoluto).startsWith(raizReal + path.sep))
|
|
174
|
+
excluidas.push({ path: caminho, motivo: 'fora-do-repositorio' });
|
|
175
|
+
else {
|
|
176
|
+
const bytes = fs.readFileSync(absoluto);
|
|
177
|
+
if ((0, node_crypto_1.createHash)('sha1').update(`blob ${bytes.length}\0`).update(bytes).digest('hex') !== objeto)
|
|
178
|
+
filtrado = true;
|
|
179
|
+
fontes.push({ path: caminho, bytes });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const head = git(raiz, ['rev-parse', '--verify', '-q', 'HEAD']);
|
|
184
|
+
const sujo = obrigatorio(raiz, ['status', '--porcelain=v1', '-z', '--untracked-files=no']).length > 0;
|
|
185
|
+
const revisao = head.ok ? head.saida.toString('utf8').trim() : null;
|
|
186
|
+
// A5: filtro do Git (eol, LFS) deixa o status limpo com bytes que nao sao o blob da revisao.
|
|
187
|
+
const motivo = !revisao ? 'sem-commit' : sujo ? 'working-tree-modified' : filtrado ? 'filtro-do-git' : null;
|
|
188
|
+
return {
|
|
189
|
+
tenant_id,
|
|
190
|
+
repository_id: repositorio,
|
|
191
|
+
revision: motivo === null ? revisao : null,
|
|
192
|
+
revision_unavailable_reason: motivo,
|
|
193
|
+
acl_refs,
|
|
194
|
+
fontes,
|
|
195
|
+
excluidas,
|
|
196
|
+
};
|
|
197
|
+
}
|
package/dist/leases.js
CHANGED
|
@@ -76,6 +76,9 @@ exports.posicaoNaFila = posicaoNaFila;
|
|
|
76
76
|
exports.proximoDaFila = proximoDaFila;
|
|
77
77
|
exports.adquirirRegiao = adquirirRegiao;
|
|
78
78
|
exports.tabelaDeLeases = tabelaDeLeases;
|
|
79
|
+
exports.soltarDaThread = soltarDaThread;
|
|
80
|
+
exports.soltarThreadFechada = soltarThreadFechada;
|
|
81
|
+
exports.podarRegioesDeThreadsFechadas = podarRegioesDeThreadsFechadas;
|
|
79
82
|
const fs = __importStar(require("node:fs"));
|
|
80
83
|
const path = __importStar(require("node:path"));
|
|
81
84
|
const manifest_1 = require("./manifest");
|
|
@@ -83,6 +86,8 @@ const estado_thread_1 = require("./estado-thread");
|
|
|
83
86
|
const util_1 = require("./util");
|
|
84
87
|
const horario_1 = require("./horario");
|
|
85
88
|
const conducao_texto_1 = require("./conducao-texto");
|
|
89
|
+
const ledger_1 = require("./ledger");
|
|
90
|
+
const thread_1 = require("./thread");
|
|
86
91
|
/** Nome do lease que serializa o merge na base (visao, paridade 5). */
|
|
87
92
|
exports.LEASE_MAIN_TREE = 'main-tree';
|
|
88
93
|
/** TTL padrao de 30 minutos: um SHIP que passe disso deixou de existir. */
|
|
@@ -433,6 +438,12 @@ function proximoDaFila(raiz, nome) {
|
|
|
433
438
|
function adquirirRegiao(raiz, nome, opcoes) {
|
|
434
439
|
const tipo = tipoDoLease(nome);
|
|
435
440
|
const base = { nome, tipo, lease: null, ocupadoPor: null, tomadoDeVencido: false };
|
|
441
|
+
// A poda e limpeza de estado alheio: erro de E/S nela nunca impede a thread viva de pedir a regiao
|
|
442
|
+
// (achado A1 do CHECK 1); o que nao saiu agora sai no proximo pedido.
|
|
443
|
+
try {
|
|
444
|
+
podarThreadsFechadas(raiz, nome, opcoes.thread);
|
|
445
|
+
}
|
|
446
|
+
catch { /* a regra de colisao abaixo decide */ }
|
|
436
447
|
const colidentes = leasesColidentes(raiz, nome, opcoes.thread);
|
|
437
448
|
if (colidentes.length > 0) {
|
|
438
449
|
const dono = colidentes[0];
|
|
@@ -550,3 +561,92 @@ function tabelaDeLeases(raiz) {
|
|
|
550
561
|
linhas.push((0, horario_1.legendaDoFuso)());
|
|
551
562
|
return linhas.join('\n');
|
|
552
563
|
}
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
// RM-037 (rm037noite, defeito 2): thread fechada nao segura regiao nem fila.
|
|
566
|
+
// ---------------------------------------------------------------------------
|
|
567
|
+
/**
|
|
568
|
+
* Thread fechada nesta maquina? So `status: fechada` conta: thread que nao existe aqui (outro
|
|
569
|
+
* perfil, estado apagado) segue contando, porque ninguem prova que ela acabou.
|
|
570
|
+
*/
|
|
571
|
+
function threadFechada(raiz, thread) {
|
|
572
|
+
try {
|
|
573
|
+
return (0, thread_1.lerThread)(raiz, thread).status === 'fechada';
|
|
574
|
+
}
|
|
575
|
+
catch {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Tira da thread os leases de escrita e as entradas dela na fila. O `exec:` fica de fora: a
|
|
581
|
+
* conducao tem ciclo proprio e ja trata thread fechada como sem conducao.
|
|
582
|
+
*/
|
|
583
|
+
function soltarDaThread(raiz, thread) {
|
|
584
|
+
const leases = [];
|
|
585
|
+
for (const lease of listarLeases(raiz)) {
|
|
586
|
+
if (lease.thread !== thread || tipoDoLease(lease.nome) === 'exec')
|
|
587
|
+
continue;
|
|
588
|
+
// Achado A2 do CHECK 1: rele logo antes de apagar. Outra poda pode ter soltado este lease e uma
|
|
589
|
+
// thread viva pode ter adquirido o mesmo nome no meio; apagar pelo caminho da listagem levaria o
|
|
590
|
+
// lease dela. So sai o arquivo que ainda e o da thread fechada, com o mesmo carimbo.
|
|
591
|
+
const atual = lerLease(raiz, lease.nome);
|
|
592
|
+
if (!atual || atual.thread !== thread || atual.adquiridoEm !== lease.adquiridoEm)
|
|
593
|
+
continue;
|
|
594
|
+
try {
|
|
595
|
+
fs.unlinkSync(caminhoLease(raiz, lease.nome));
|
|
596
|
+
leases.push(lease.nome);
|
|
597
|
+
}
|
|
598
|
+
catch { /* outra limpeza chegou antes */ }
|
|
599
|
+
}
|
|
600
|
+
const fila = lerFila(raiz);
|
|
601
|
+
const dela = fila.filter((p) => p.thread === thread);
|
|
602
|
+
if (dela.length > 0)
|
|
603
|
+
gravarFila(raiz, fila.filter((p) => p.thread !== thread));
|
|
604
|
+
return { leases, fila: dela.map((p) => p.nome) };
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Solta o que a thread fechada deixou e registra no ledger dela: `lease_released` por lease e
|
|
608
|
+
* `lease_dequeued` por entrada de fila, com a origem (o fechamento ou a poda de quem pediu a regiao).
|
|
609
|
+
*/
|
|
610
|
+
function soltarThreadFechada(raiz, thread, origem, pedidaPor) {
|
|
611
|
+
const solto = soltarDaThread(raiz, thread);
|
|
612
|
+
const dir = (0, thread_1.dirThread)(raiz, thread);
|
|
613
|
+
const quem = pedidaPor ? { pedidaPor } : {};
|
|
614
|
+
for (const lease of solto.leases) {
|
|
615
|
+
(0, ledger_1.registrarSeExiste)(dir, thread, ledger_1.TIPOS_DE_EVENTO.leaseLiberado, { lease, ok: true, detalhe: 'thread fechada: lease solto', origem, ...quem });
|
|
616
|
+
}
|
|
617
|
+
for (const lease of solto.fila) {
|
|
618
|
+
(0, ledger_1.registrarSeExiste)(dir, thread, ledger_1.TIPOS_DE_EVENTO.leaseDesenfileirado, { lease, detalhe: 'thread fechada: saiu da fila', origem, ...quem });
|
|
619
|
+
}
|
|
620
|
+
return solto;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Antes de decidir a vez, quem pede a regiao tira da frente o que e de thread ja fechada: o lease
|
|
624
|
+
* colidente e a espera na fila. E a cura do que ficou preso antes de o fechamento soltar sozinho
|
|
625
|
+
* (a ork-companybrai3, fechada, na frente da fila de `path:docs/roadmap/README.md`).
|
|
626
|
+
*/
|
|
627
|
+
function podarThreadsFechadas(raiz, nome, quem) {
|
|
628
|
+
const suspeitas = new Set([
|
|
629
|
+
...listarLeases(raiz).filter((l) => leasesColidem(nome, l.nome)).map((l) => l.thread),
|
|
630
|
+
...esperandoPor(raiz, nome).map((p) => p.thread),
|
|
631
|
+
]);
|
|
632
|
+
suspeitas.delete(quem);
|
|
633
|
+
for (const thread of suspeitas) {
|
|
634
|
+
if (threadFechada(raiz, thread))
|
|
635
|
+
soltarThreadFechada(raiz, thread, 'poda', quem);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* RM-037 (fatia 3, defeito 4): a mesma poda, para as conferencias previas do MCP. O `ork_git_commit`
|
|
640
|
+
* conferia `lerLease` antes do `adquirirRegiao` e recusava com `lease.busy` o lease que a ork-companybrai3
|
|
641
|
+
* (fechada) deixou, e soltar o lease de outra thread exigia o dono. Lease e fila de thread fechada sao
|
|
642
|
+
* orfaos: saem aqui, com registro no ledger dela. Lease de thread aberta, vencido ou nao, e o da propria
|
|
643
|
+
* thread seguem como estao, e a conferencia de quem chama decide. De melhor esforco, como no `adquirirRegiao`.
|
|
644
|
+
*/
|
|
645
|
+
function podarRegioesDeThreadsFechadas(raiz, nomes, quem) {
|
|
646
|
+
for (const nome of nomes) {
|
|
647
|
+
try {
|
|
648
|
+
podarThreadsFechadas(raiz, nome, quem);
|
|
649
|
+
}
|
|
650
|
+
catch { /* a conferencia de quem chama decide */ }
|
|
651
|
+
}
|
|
652
|
+
}
|
package/dist/ledger.js
CHANGED
|
@@ -45,6 +45,7 @@ exports.caminhoLedger = caminhoLedger;
|
|
|
45
45
|
exports.registrar = registrar;
|
|
46
46
|
exports.threadPresente = threadPresente;
|
|
47
47
|
exports.registrarSeExiste = registrarSeExiste;
|
|
48
|
+
exports.ehEnsaio = ehEnsaio;
|
|
48
49
|
exports.lerLedger = lerLedger;
|
|
49
50
|
const fs = __importStar(require("node:fs"));
|
|
50
51
|
const path = __importStar(require("node:path"));
|
|
@@ -99,8 +100,18 @@ exports.TIPOS_DE_EVENTO = {
|
|
|
99
100
|
worktreeAuditada: 'worktree_audited',
|
|
100
101
|
worktreeLiberada: 'worktree_released',
|
|
101
102
|
leaseEnfileirado: 'lease_queued',
|
|
103
|
+
// RM-037 (rm037noite, defeito 2): a entrada da fila que saiu porque a thread fechou.
|
|
104
|
+
leaseDesenfileirado: 'lease_dequeued',
|
|
105
|
+
// RM-037 (rm037noite, defeito 3): a reserva do roadmap que a thread fechada soltou (ou reapontou),
|
|
106
|
+
// e a que ficou para depois porque nao deu para soltar agora.
|
|
107
|
+
reservaLiberada: 'roadmap_reserva_liberada',
|
|
108
|
+
reservaPendente: 'roadmap_reserva_pendente',
|
|
109
|
+
// A parte do fechamento que falhou (E/S), com o erro; o fechamento segue valendo.
|
|
110
|
+
solturaFalhou: 'soltura_ao_fechar_falhou',
|
|
102
111
|
postmortemGravado: 'postmortem_recorded',
|
|
103
112
|
masterConcluido: 'master_done',
|
|
113
|
+
// RM-048 (item 8): o pedido de nota ao dono, com codigo curto; a nota volta pelo ingresso.
|
|
114
|
+
notaPedida: 'master_nota_pedida',
|
|
104
115
|
scoreProposto: 'score_proposto',
|
|
105
116
|
masterMigrado: 'master_migrated',
|
|
106
117
|
threadFechadaAdmin: 'thread_closed_admin',
|
|
@@ -138,6 +149,8 @@ exports.TIPOS_DE_EVENTO = {
|
|
|
138
149
|
onboardingRegistrado: 'onboarding_recorded',
|
|
139
150
|
// Correcao do escalonador: vaga devolvida por thread sem procura ativa (`ork board reap`)
|
|
140
151
|
vagaLiberada: 'slot_released',
|
|
152
|
+
// RM-037 (rm037defeito, defeito 3): o `phase run` recusou o despacho por falta de vaga no projeto.
|
|
153
|
+
vagaRecusada: 'slot_refused',
|
|
141
154
|
// I-07: estimativa humana no PLAN para comparacao economica posterior.
|
|
142
155
|
estimativaPlano: 'plan_estimate',
|
|
143
156
|
// I-42 (D5): ciclo sem CHECK que nao achou teste nem comando honesto declara a ausencia de
|
|
@@ -156,6 +169,8 @@ exports.TIPOS_DE_EVENTO = {
|
|
|
156
169
|
conducaoLiberada: 'conducao_liberada',
|
|
157
170
|
conducaoOrfaLiberada: 'conducao_orfa_liberada',
|
|
158
171
|
conducaoAssumida: 'conducao_assumida',
|
|
172
|
+
// RM-037 (rm037defeito, A-1 do CHECK 3): o despacho recusado antes da sessao devolveu o lease que a tomada consumiu.
|
|
173
|
+
conducaoDevolvida: 'conducao_devolvida',
|
|
159
174
|
conducaoRenovada: 'conducao_renovada',
|
|
160
175
|
};
|
|
161
176
|
/**
|
|
@@ -222,6 +237,14 @@ function registrarSeExiste(dirThread, threadId, tipo, dados = {}) {
|
|
|
222
237
|
}
|
|
223
238
|
return evento;
|
|
224
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* Fatia 2 do ensaio da 0.5.0 (P2): o evento que um `--dry-run` grava (`dryRun: true`) e ensaio, nao
|
|
242
|
+
* estado. O ledger o guarda como rastro; board, escalonador, monitor (o pulse) e maestro o descartam.
|
|
243
|
+
* O ensaio do ship gravava `gate_blocked human.pending` e a thread aparecia pausada sem ninguem pedir.
|
|
244
|
+
*/
|
|
245
|
+
function ehEnsaio(e) {
|
|
246
|
+
return e.dryRun === true;
|
|
247
|
+
}
|
|
225
248
|
/** Le o ledger inteiro. Linha corrompida vira evento `ledger_corrupted` em vez de quebrar a leitura. */
|
|
226
249
|
function lerLedger(dirThread) {
|
|
227
250
|
const caminho = caminhoLedger(dirThread);
|
package/dist/licoes.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.PISO_DA_PROPOSTA = exports.JANELA_DA_PROPOSTA_DIAS = void 0;
|
|
36
|
+
exports.PISO_DA_PROPOSTA = exports.JANELA_DA_PROPOSTA_DIAS = exports.DICA_DO_MOTIVO = void 0;
|
|
37
37
|
exports.lerLicoes = lerLicoes;
|
|
38
38
|
exports.resumoDasLicoes = resumoDasLicoes;
|
|
39
39
|
exports.textoDasLicoes = textoDasLicoes;
|
|
@@ -59,7 +59,7 @@ const estado_thread_1 = require("./estado-thread");
|
|
|
59
59
|
const ledger_1 = require("./ledger");
|
|
60
60
|
const policies_1 = require("./policies");
|
|
61
61
|
/** O que evita cada bloqueio, na forma de comando. Sem dica, a licao so conta a recorrencia. */
|
|
62
|
-
|
|
62
|
+
exports.DICA_DO_MOTIVO = {
|
|
63
63
|
'claims.failed': 'rode o comando da claim antes de registra-la; claim sem prova local volta como GO-FIX',
|
|
64
64
|
'verify.regression': 'grave a baseline antes do GO (`ork verify <thread> --baseline`) e rode os testes focados antes do CHECK',
|
|
65
65
|
'verify.failed': 'grave a baseline antes do GO, para a falha ter com que ser comparada',
|
|
@@ -67,7 +67,8 @@ const DICA_DO_MOTIVO = {
|
|
|
67
67
|
'runtime.unavailable': 'declare a ordem de fallback do bloco (`ork setup <modo> --bloco N --fallback runtime:modelo`)',
|
|
68
68
|
'runtime.quota-exhausted': 'tenha um segundo perfil da conta (`ork accounts add`) ou fallback no bloco',
|
|
69
69
|
'tree.blocked': 'sincronize a worktree com a base antes do SHIP (`ork worktree sync <thread>`)',
|
|
70
|
-
|
|
70
|
+
// Fatia 2 do ensaio da 0.5.0 (P6): o que o CI do projeto roda, e nao o script do Orkastery.
|
|
71
|
+
'ci.failed': 'rode antes do push o que o CI do projeto roda (`ci.command` do manifesto ou, sem ele, os comandos de `verify`)',
|
|
71
72
|
'artifact.missing': 'grave o artefato da fase exatamente no caminho que o prompt pede',
|
|
72
73
|
};
|
|
73
74
|
const DICA_DA_CLASSE = {
|
|
@@ -116,7 +117,7 @@ function recorrencias(licoes) {
|
|
|
116
117
|
const classes = new Map();
|
|
117
118
|
for (const l of licoes) {
|
|
118
119
|
for (const m of l.motivos) {
|
|
119
|
-
const r = motivos.get(m) ?? { chave: `motivo:${m}`, tipo: 'motivo', nome: m, threads: [], vezes: 0, dica: DICA_DO_MOTIVO[m] ?? null };
|
|
120
|
+
const r = motivos.get(m) ?? { chave: `motivo:${m}`, tipo: 'motivo', nome: m, threads: [], vezes: 0, dica: exports.DICA_DO_MOTIVO[m] ?? null };
|
|
120
121
|
r.threads.push(l.thread);
|
|
121
122
|
motivos.set(m, r);
|
|
122
123
|
}
|
package/dist/liveness.js
CHANGED
|
@@ -120,7 +120,8 @@ function detectarFasesOrfas(carregado, opcoes = {}) {
|
|
|
120
120
|
const t = (0, thread_1.lerThread)(carregado.raiz, id), dir = (0, thread_1.dirThread)(carregado.raiz, id);
|
|
121
121
|
if (t.status !== 'aberta')
|
|
122
122
|
continue;
|
|
123
|
-
|
|
123
|
+
// Fatia 2 do ensaio da 0.5.0 (P2; CHECK, rodada 1, A1): o gate do `ship --dry-run` nao e gate em aberto.
|
|
124
|
+
const eventos = (0, ledger_1.lerLedger)(dir).filter(e => !(0, ledger_1.ehEnsaio)(e)), di = eventos.map(e => e.tipo).lastIndexOf('phase_dispatch');
|
|
124
125
|
if (di < 0)
|
|
125
126
|
continue;
|
|
126
127
|
const d = eventos[di], inicio = Date.parse(d.ts), fase = d.fase;
|
package/dist/maestro-cli.js
CHANGED
|
@@ -31,10 +31,19 @@ function readMaestro(context, options) {
|
|
|
31
31
|
return sources;
|
|
32
32
|
} });
|
|
33
33
|
}
|
|
34
|
+
/** RM-052: de onde veio o projeto do panorama, na lingua do dono. */
|
|
35
|
+
const ORIGEM_DO_PANORAMA = Object.freeze({
|
|
36
|
+
installation: 'fixado na instalação', cwd: 'pelo diretório atual', worktree: 'pela worktree da thread',
|
|
37
|
+
selection: 'pedido explicitamente (--projeto ou ORK_PROJETO)',
|
|
38
|
+
});
|
|
34
39
|
function maestroText(snapshot) {
|
|
35
|
-
|
|
40
|
+
const p = snapshot.project;
|
|
41
|
+
return [`${p.name} · panorama Maestro`,
|
|
36
42
|
// I-35: o snapshot guarda ISO; o texto ao dono diz quando consultou, no fuso dele.
|
|
37
43
|
`• Consulta: ${(0, horario_1.formatarDataHoraRotulada)(snapshot.observedAt, { agora: snapshot.observedAt })}`,
|
|
44
|
+
// RM-052: qual cópia foi lida e o que o panorama não lê, antes de qualquer seção.
|
|
45
|
+
`• Projeto consultado: ${p.name}${p.root ? ` · ${p.root}` : ''}${p.remote === undefined ? '' : ` · ${p.remote ?? 'sem remoto'}`} · ${ORIGEM_DO_PANORAMA[p.origin]}`,
|
|
46
|
+
...(snapshot.notConsulted?.length ? [`• Não lido: ${snapshot.notConsulted.join(' · ')}`] : []),
|
|
38
47
|
...maestro_contract_1.SECTION_NAMES.map(name => {
|
|
39
48
|
const s = snapshot.sections[name];
|
|
40
49
|
return `• ${name}: ${s.state} · ${s.coverage.returned}/${s.coverage.total ?? '?'}${s.coverage.omitted ? ' · mais itens disponíveis' : ''}`;
|
package/dist/maestro-contract.js
CHANGED
|
@@ -31,10 +31,14 @@ exports.maestroSectionSchema = zod_1.z.object({
|
|
|
31
31
|
}).strict();
|
|
32
32
|
exports.maestroSnapshotSchema = zod_1.z.object({
|
|
33
33
|
schema: zod_1.z.literal(exports.MAESTRO_SCHEMA), observedAt: zod_1.z.string().datetime(), fingerprint,
|
|
34
|
-
|
|
34
|
+
// RM-052: a raiz exibida (com ~) e o remoto sem credencial dizem QUAL copia foi lida.
|
|
35
|
+
project: zod_1.z.object({ id: identity, name: text, origin: zod_1.z.enum(['installation', 'cwd', 'worktree', 'selection']), fingerprint,
|
|
36
|
+
root: text.optional(), remote: text.nullable().optional() }).strict(),
|
|
35
37
|
limits: zod_1.z.object({ items: zod_1.z.literal(50), bytes: zod_1.z.literal(65536), sourceMs: zod_1.z.literal(2000), totalMs: zod_1.z.literal(10000) }).strict(),
|
|
36
38
|
sections: zod_1.z.object(Object.fromEntries(exports.SECTION_NAMES.map(name => [name, exports.maestroSectionSchema]))).strict(),
|
|
37
39
|
gaps: zod_1.z.array(text).max(100), conflicts: zod_1.z.array(text).max(100),
|
|
40
|
+
// RM-052: o que o panorama NAO le (roadmap, reservas, outras maquinas): lacuna declarada nunca vira "vazio".
|
|
41
|
+
notConsulted: zod_1.z.array(text).max(20).optional(),
|
|
38
42
|
}).strict();
|
|
39
43
|
function validateMaestroSnapshot(input) {
|
|
40
44
|
const value = exports.maestroSnapshotSchema.parse(input);
|
|
@@ -42,6 +42,20 @@ const node_crypto_1 = require("node:crypto");
|
|
|
42
42
|
const manifest_1 = require("./manifest");
|
|
43
43
|
const estado_thread_1 = require("./estado-thread");
|
|
44
44
|
const thread_1 = require("./thread");
|
|
45
|
+
const projeto_alvo_1 = require("./projeto-alvo");
|
|
46
|
+
/**
|
|
47
|
+
* RM-052: o panorama le threads, sessoes e filas deste projeto nesta maquina. Roadmap, reservas e
|
|
48
|
+
* as outras maquinas NAO entram nele; quem le o panorama precisa saber disso para nao concluir
|
|
49
|
+
* "roadmap vazio" a partir de zero threads, que foi o incidente de 29/09.
|
|
50
|
+
*/
|
|
51
|
+
function consultaDoMaestro(value, countOtherProjects) {
|
|
52
|
+
const loaded = (0, manifest_1.carregarManifesto)(value.root);
|
|
53
|
+
const others = countOtherProjects ? (0, projeto_alvo_1.outrosProjetosConhecidos)(value.root) : 0;
|
|
54
|
+
return { ...value, project: { ...value.project, root: (0, projeto_alvo_1.raizParaExibir)(value.root),
|
|
55
|
+
remote: (0, projeto_alvo_1.remotoDoProjeto)(value.root, loaded?.manifesto.fabrica?.remoto ?? 'origin') },
|
|
56
|
+
notConsulted: [projeto_alvo_1.FORA_DA_CONSULTA.roadmap, projeto_alvo_1.FORA_DA_CONSULTA.reservas, projeto_alvo_1.FORA_DA_CONSULTA.outrasMaquinas,
|
|
57
|
+
...(others > 0 ? [`outros projetos desta máquina: ${others} (ork projetos)`] : [])] };
|
|
58
|
+
}
|
|
45
59
|
const inside = (root, file) => file === root || file.startsWith(root + path.sep);
|
|
46
60
|
function physical(file) {
|
|
47
61
|
const absolute = path.resolve(file);
|
|
@@ -121,9 +135,9 @@ function discoverMaestro(options) {
|
|
|
121
135
|
if (fs.lstatSync(file).isSymbolicLink() && fs.realpathSync(file) !== target)
|
|
122
136
|
throw Error('maestro.project.scope');
|
|
123
137
|
}
|
|
124
|
-
return context(canonical, 'worktree');
|
|
138
|
+
return consultaDoMaestro(context(canonical, 'worktree'), options.countOtherProjects !== false);
|
|
125
139
|
}
|
|
126
|
-
return context(chosen, origin);
|
|
140
|
+
return consultaDoMaestro(context(chosen, origin), options.countOtherProjects !== false);
|
|
127
141
|
}
|
|
128
142
|
function revalidateMaestroContext(value) {
|
|
129
143
|
const current = context(value.root, value.project.origin);
|
package/dist/maestro-runtime.js
CHANGED
|
@@ -47,6 +47,7 @@ const hitl_sessions_1 = require("./hitl-sessions");
|
|
|
47
47
|
const thread_1 = require("./thread");
|
|
48
48
|
const hitl_gates_1 = require("./hitl-gates");
|
|
49
49
|
const ocupacao_1 = require("./ocupacao");
|
|
50
|
+
const ledger_1 = require("./ledger");
|
|
50
51
|
const horario_1 = require("./horario");
|
|
51
52
|
const conducao_1 = require("./conducao");
|
|
52
53
|
const conducao_texto_1 = require("./conducao-texto");
|
|
@@ -95,6 +96,8 @@ function operationalSources(reader, threads, native = [], now = new Date().toISO
|
|
|
95
96
|
events = raw.split('\n').filter(Boolean).map(line => JSON.parse(line));
|
|
96
97
|
if (events.some(e => typeof e.tipo !== 'string' || e.thread !== t.id))
|
|
97
98
|
throw Error('invalid');
|
|
99
|
+
// Fatia 2 do ensaio da 0.5.0 (P2): o ensaio (`dryRun: true`) nao vira bloqueio nem entrega incompleta.
|
|
100
|
+
events = events.filter(e => !(0, ledger_1.ehEnsaio)(e));
|
|
98
101
|
}
|
|
99
102
|
catch {
|
|
100
103
|
for (const name of names.filter(n => !['leases', 'retries'].includes(n)))
|
package/dist/maestro-snapshot.js
CHANGED
|
@@ -51,9 +51,13 @@ function maestroSnapshot(context, options = {}) {
|
|
|
51
51
|
coverage: { total: unavailable ? null : all.length, offset, returned: items.length, omitted: unavailable ? null : omitted,
|
|
52
52
|
nextOffset: omitted ? offset + items.length : null, limit: 50 }, items, gaps: publicMessages(src?.gaps ?? ['maestro.source.unavailable'], 4) };
|
|
53
53
|
}
|
|
54
|
+
// RM-052: raiz e remoto passam pela mesma redacao dos demais campos publicos.
|
|
55
|
+
const { root, remote } = context.project;
|
|
54
56
|
const result = { schema: maestro_contract_1.MAESTRO_SCHEMA, observedAt, fingerprint: (0, maestro_sources_1.digest)([context.fingerprint, sources.fingerprint]),
|
|
55
|
-
project: { ...context.project, name: (0, maestro_sources_1.safeText)(context.project.name) }
|
|
56
|
-
|
|
57
|
+
project: { ...context.project, name: (0, maestro_sources_1.safeText)(context.project.name), ...(root === undefined ? {} : { root: (0, maestro_sources_1.safeText)(root) }),
|
|
58
|
+
...(remote === undefined ? {} : { remote: remote === null ? null : (0, maestro_sources_1.safeText)(remote) }) }, limits: maestro_contract_1.MAESTRO_LIMITS, sections, gaps: publicMessages(sources.gaps, 12),
|
|
59
|
+
conflicts: publicMessages([...sources.conflicts, ...(!stable ? ['maestro.snapshot.stale'] : [])], 12),
|
|
60
|
+
...(context.notConsulted ? { notConsulted: publicMessages(context.notConsulted, 19) } : {}) };
|
|
57
61
|
// Orçamento incremental; mantém um item por seção para nextOffset avançar.
|
|
58
62
|
const sizes = new Map(Object.values(sections).map(s => [s, Buffer.byteLength(JSON.stringify(s))]));
|
|
59
63
|
let bytes = Buffer.byteLength(JSON.stringify(result));
|