@orkastery/cli 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/claude-code/agents/ork-master.md +2 -0
- package/adapters/claude-code/commands/master.md +8 -0
- package/adapters/claude-code/commands/ork.md +9 -0
- package/adapters/codex/skills/ork/SKILL.md +18 -3
- package/adapters/hermes/README.md +1 -0
- package/adapters/hermes/bin/ork-network-status.sh +10 -0
- package/adapters/hermes/hermes.plugin.json +1 -0
- package/adapters/hermes/hitl-ingress/__init__.py +2 -2
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +6 -5
- package/adapters/openclaw/README.md +24 -4
- package/adapters/openclaw/dist/hitl-ingress.js +2 -2
- package/adapters/openclaw/dist/index.js +46 -11
- package/adapters/openclaw/openclaw.plugin.json +5 -1
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +2 -2
- package/adapters/openclaw/src/index.ts +49 -11
- package/assets/orkmind_bridge.py +117 -9
- package/dist/adapters/claude-bg.js +39 -5
- package/dist/adapters/codex.js +4 -3
- package/dist/agents-md.js +1 -0
- package/dist/auditrun.js +5 -1
- package/dist/board.js +16 -14
- package/dist/branch-de-estado.js +66 -10
- package/dist/busca-semantica.js +52 -12
- package/dist/canarios-rm057.js +149 -0
- package/dist/canarios.js +2 -0
- package/dist/ci.js +8 -1
- package/dist/claims.js +39 -1
- package/dist/company-brain-context.js +158 -22
- package/dist/docs.js +48 -9
- package/dist/doctor-pulse-cron.js +194 -0
- package/dist/doctor-rede.js +149 -0
- package/dist/doctor.js +89 -9
- package/dist/entrega-pr.js +20 -8
- package/dist/esgotamentos.js +181 -0
- package/dist/experiencia.js +12 -2
- package/dist/fabrica-estado.js +14 -6
- package/dist/fabrica-publicar.js +6 -0
- package/dist/fechamento.js +20 -66
- package/dist/forja.js +31 -7
- package/dist/gates.js +5 -1
- package/dist/hitl-contract.js +59 -4
- package/dist/hitl-curto.js +11 -6
- package/dist/hitl-gates.js +5 -0
- package/dist/hitl-lote.js +5 -2
- package/dist/hitl-resumo.js +9 -0
- package/dist/hitl-tempo-parado.js +201 -0
- package/dist/hitl-texto-livre.js +5 -5
- package/dist/horario.js +27 -0
- package/dist/hosts.js +52 -10
- package/dist/impedimento.js +205 -0
- package/dist/index.js +391 -74
- package/dist/indice-vetorial.js +87 -10
- package/dist/indice.js +3 -1
- package/dist/init.js +17 -0
- package/dist/integracoes-locais.js +2 -0
- package/dist/intelligence-graph-cli.js +91 -8
- package/dist/intelligence-graph-contexto.js +215 -0
- package/dist/intelligence-graph-parsers.js +6 -4
- package/dist/leases.js +664 -87
- package/dist/ledger-stats.js +15 -1
- package/dist/ledger.js +3 -0
- package/dist/licoes.js +1 -0
- package/dist/maestro-runtime.js +4 -1
- package/dist/manifest.js +20 -1
- package/dist/master-nota.js +14 -5
- package/dist/master.js +129 -12
- package/dist/mcp-artifacts.js +34 -3
- package/dist/mcp-git.js +20 -3
- package/dist/mcp-grafo-worker.js +5 -3
- package/dist/mcp-grafo.js +50 -4
- package/dist/mcp-server.js +14 -1
- package/dist/memoria.js +48 -6
- package/dist/network-roadmap.js +191 -16
- package/dist/ocupacao.js +11 -3
- package/dist/orkmind.js +90 -5
- package/dist/orquestracao.js +12 -10
- package/dist/parado-no-condutor.js +188 -32
- package/dist/phase.js +68 -15
- package/dist/policies.js +52 -1
- package/dist/portfolio.js +4 -1
- package/dist/projeto-alvo.js +5 -1
- package/dist/prompts.js +36 -1
- package/dist/prova-ativacao.js +75 -6
- package/dist/pulse-delivery.js +34 -2
- package/dist/pulse.js +49 -3
- package/dist/ratelimit.js +20 -4
- package/dist/recall.js +3 -1
- package/dist/rede-adesao.js +399 -0
- package/dist/rede-forja.js +289 -0
- package/dist/rede-projetos.js +239 -0
- package/dist/rede-status.js +336 -0
- package/dist/rede.js +980 -0
- package/dist/retry.js +69 -2
- package/dist/roadmap-status.js +23 -3
- package/dist/runtime-profiles.js +22 -1
- package/dist/saida-segura.js +58 -0
- package/dist/session-watcher-claude.js +113 -23
- package/dist/sessoes-contas.js +187 -0
- package/dist/sessoes-inventario.js +6 -18
- package/dist/sessoes.js +83 -2
- package/dist/ship.js +85 -19
- package/dist/thread.js +192 -13
- package/dist/worktree.js +5 -2
- package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
- package/package.json +7 -3
- package/references/definition-of-done.md +1 -1
- package/skills/README.md +1 -1
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/master-metrics/SKILL.md +8 -3
package/dist/thread.js
CHANGED
|
@@ -47,7 +47,16 @@ exports.lerThread = lerThread;
|
|
|
47
47
|
exports.gravarThread = gravarThread;
|
|
48
48
|
exports.avisoDeThreadSemBase = avisoDeThreadSemBase;
|
|
49
49
|
exports.idDisponivel = idDisponivel;
|
|
50
|
+
exports.pastaDaWorktree = pastaDaWorktree;
|
|
51
|
+
exports.alvoDaWorktree = alvoDaWorktree;
|
|
52
|
+
exports.worktreePrevista = worktreePrevista;
|
|
50
53
|
exports.criarWorktree = criarWorktree;
|
|
54
|
+
exports.pedidoDeWorktree = pedidoDeWorktree;
|
|
55
|
+
exports.linhaDaWorktree = linhaDaWorktree;
|
|
56
|
+
exports.avisoDeThreadSemWorktree = avisoDeThreadSemWorktree;
|
|
57
|
+
exports.avisoDeWorktreeQueFalharia = avisoDeWorktreeQueFalharia;
|
|
58
|
+
exports.avisoDeChaveSemCommit = avisoDeChaveSemCommit;
|
|
59
|
+
exports.avisoDaWorktree = avisoDaWorktree;
|
|
51
60
|
exports.novaThread = novaThread;
|
|
52
61
|
exports.exigirVarianteCompativel = exigirVarianteCompativel;
|
|
53
62
|
exports.blocoDaThread = blocoDaThread;
|
|
@@ -141,6 +150,43 @@ function idDisponivel(raiz, abbrev, assunto) {
|
|
|
141
150
|
}
|
|
142
151
|
return { id: `${abbrev}-${candidato}`, assunto: candidato };
|
|
143
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Pasta da worktree de uma thread: `worktree.dir` resolvido na arvore principal, nunca na worktree de onde o comando
|
|
155
|
+
* roda. P4 do ensaio da 0.5.0 (CHECK): com a chave valendo, o `ork thread new` rodado de dentro da worktree de outra
|
|
156
|
+
* thread aninhava a nova na pasta da mae, e o release da mae levava a da filha junto.
|
|
157
|
+
*/
|
|
158
|
+
function pastaDaWorktree(carregado, id) {
|
|
159
|
+
return path.resolve((0, estado_thread_1.raizDoEstado)(carregado.raiz), carregado.manifesto.worktree.dir, id);
|
|
160
|
+
}
|
|
161
|
+
/** Pasta e branch da worktree de uma thread: o que `criarWorktree` cria e o `--dry-run` preve. */
|
|
162
|
+
function alvoDaWorktree(carregado, id, slug, opcoes = {}) {
|
|
163
|
+
return { dir: pastaDaWorktree(carregado, id), branch: opcoes.branchExistente ?? `ork/${slug}` };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* P4 do ensaio da 0.5.0: a worktree que `criarWorktree` criaria para este id, sem criar nada. Mesma pasta, mesma
|
|
167
|
+
* branch e o commit de onde ela partiria: a branch existente (ciclo `merge-branch`), senao a base do manifesto,
|
|
168
|
+
* senao o HEAD. Diz tambem o que faria a criacao recusar: a pasta que ja existe, o repositorio sem commit ou a
|
|
169
|
+
* branch nova que ja existe.
|
|
170
|
+
*/
|
|
171
|
+
function worktreePrevista(carregado, id, slug, opcoes = {}) {
|
|
172
|
+
const alvo = alvoDaWorktree(carregado, id, slug, opcoes);
|
|
173
|
+
const refs = opcoes.branchExistente
|
|
174
|
+
? [opcoes.branchExistente]
|
|
175
|
+
: [opcoes.base ?? carregado.manifesto.worktree.base_branch, 'HEAD'];
|
|
176
|
+
let commit = null;
|
|
177
|
+
for (const ref of refs) {
|
|
178
|
+
const r = (0, util_1.exec)('git', ['rev-parse', '--verify', ref], carregado.raiz);
|
|
179
|
+
if (r.ok) {
|
|
180
|
+
commit = r.stdout.trim();
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const branchJaExiste = !opcoes.branchExistente &&
|
|
185
|
+
(0, util_1.exec)('git', ['rev-parse', '--verify', '--quiet', `refs/heads/${alvo.branch}`], carregado.raiz).ok;
|
|
186
|
+
const falha = fs.existsSync(alvo.dir) ? 'pasta-existe'
|
|
187
|
+
: commit === null ? 'sem-commit' : branchJaExiste ? 'branch-existe' : null;
|
|
188
|
+
return { ...alvo, commit, falha };
|
|
189
|
+
}
|
|
144
190
|
/**
|
|
145
191
|
* Cria a worktree isolada da thread (paralelismo sem colisao entre threads).
|
|
146
192
|
*
|
|
@@ -150,8 +196,7 @@ function idDisponivel(raiz, abbrev, assunto) {
|
|
|
150
196
|
*/
|
|
151
197
|
function criarWorktree(carregado, id, slug, opcoes = {}) {
|
|
152
198
|
const { raiz, manifesto } = carregado;
|
|
153
|
-
const dir =
|
|
154
|
-
const branch = opcoes.branchExistente ?? `ork/${slug}`;
|
|
199
|
+
const { dir, branch } = alvoDaWorktree(carregado, id, slug, opcoes);
|
|
155
200
|
if (fs.existsSync(dir)) {
|
|
156
201
|
throw new Error(`worktree ja existe em ${dir}`);
|
|
157
202
|
}
|
|
@@ -170,7 +215,7 @@ function criarWorktree(carregado, id, slug, opcoes = {}) {
|
|
|
170
215
|
throw new Error(`git worktree add falhou: ${(r.stderr || r.stdout).trim()}`);
|
|
171
216
|
}
|
|
172
217
|
if (pastaNova)
|
|
173
|
-
(0, util_1.ignorarPastaNoGit)(pastaDasWorktrees, raiz);
|
|
218
|
+
(0, util_1.ignorarPastaNoGit)(pastaDasWorktrees, (0, estado_thread_1.raizDoEstado)(raiz));
|
|
174
219
|
const lista = (0, util_1.exec)('git', ['worktree', 'list', '--porcelain'], raiz);
|
|
175
220
|
const criada = lista.ok && lista.stdout.split('\n').some((l) => l.trim() === `worktree ${dir}`);
|
|
176
221
|
if (!criada) {
|
|
@@ -179,6 +224,105 @@ function criarWorktree(carregado, id, slug, opcoes = {}) {
|
|
|
179
224
|
(0, estado_thread_1.vincularEstado)(raiz, id, dir);
|
|
180
225
|
return { dir, branch };
|
|
181
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Resolve `--worktree`, `--sem-worktree` e `worktree.por_thread`. As flags vencem a chave; as duas juntas, ou
|
|
229
|
+
* `--sem-worktree` com valor (o parser leva o argumento seguinte), sao erro de uso. `--worktree` sozinho ou `auto`
|
|
230
|
+
* cria a worktree; outro texto e um diretorio que ja existe, como antes.
|
|
231
|
+
*/
|
|
232
|
+
function pedidoDeWorktree(flags, porThread) {
|
|
233
|
+
const worktree = flags.worktree === false ? undefined : flags.worktree;
|
|
234
|
+
if (typeof worktree === 'string' && !worktree.trim())
|
|
235
|
+
throw new Error('uso: --worktree pede auto ou um diretório que já existe');
|
|
236
|
+
if (typeof flags.semWorktree === 'string') {
|
|
237
|
+
throw new Error(`uso: --sem-worktree não leva valor (recebeu "${flags.semWorktree}")`);
|
|
238
|
+
}
|
|
239
|
+
const semWorktree = flags.semWorktree === true;
|
|
240
|
+
if (semWorktree && worktree !== undefined)
|
|
241
|
+
throw new Error('uso: --worktree e --sem-worktree se excluem; use um dos dois');
|
|
242
|
+
if (semWorktree)
|
|
243
|
+
return { criar: false, dir: null, origem: 'sem-worktree' };
|
|
244
|
+
if (worktree === true || worktree === 'auto')
|
|
245
|
+
return { criar: true, dir: null, origem: 'flag' };
|
|
246
|
+
if (typeof worktree === 'string')
|
|
247
|
+
return { criar: false, dir: worktree, origem: 'diretorio' };
|
|
248
|
+
return porThread ? { criar: true, dir: null, origem: 'chave' } : { criar: false, dir: null, origem: 'nenhuma' };
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* P4 do ensaio da 0.5.0: a linha que diz de onde veio a worktree da thread nova. Na criacao, so quando ela veio da
|
|
252
|
+
* chave (quem passou `--worktree auto` sabe de onde ela veio); no `--dry-run`, para qualquer origem.
|
|
253
|
+
*/
|
|
254
|
+
function linhaDaWorktree(por, gravada, variante) {
|
|
255
|
+
if (!por || (gravada && por !== 'chave'))
|
|
256
|
+
return null;
|
|
257
|
+
const verbo = gravada ? 'criada' : 'seria criada';
|
|
258
|
+
if (por === 'chave') {
|
|
259
|
+
return ` worktree: ${verbo} pela chave worktree.por_thread do orkastery.yaml; para criar sem ela, use --sem-worktree`;
|
|
260
|
+
}
|
|
261
|
+
if (por === 'flag')
|
|
262
|
+
return ` worktree: ${verbo} pelo --worktree auto`;
|
|
263
|
+
return ` worktree: ${verbo} pelo ciclo ${variante ?? 'da thread'}, que exige worktree isolada`;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* P4 do ensaio da 0.5.0: o que acontece no SHIP com a thread criada por `--sem-worktree`. O `ork ship` entrega a
|
|
267
|
+
* branch em que a raiz estava na criacao (`thread.base.branch`), e a policy `push_direto_na_base` do manifesto barra
|
|
268
|
+
* (`block`), avisa (outro valor) ou deixa passar (sem ela, ou `off`) a entrega de uma branch para ela mesma ou da
|
|
269
|
+
* base. Raiz fora de branch (HEAD destacado ou repositorio sem commit) nao tem branch de origem.
|
|
270
|
+
*/
|
|
271
|
+
function avisoDeThreadSemWorktree(thread, manifesto, gravada = true) {
|
|
272
|
+
const base = manifesto.worktree.base_branch;
|
|
273
|
+
const branch = thread.base.branch;
|
|
274
|
+
const inicio = gravada
|
|
275
|
+
? `Aviso: thread ${thread.id} sem worktree (--sem-worktree): ela trabalha na raiz do projeto`
|
|
276
|
+
: `Aviso: sem worktree (--sem-worktree), a thread ${thread.id} trabalharia na raiz do projeto`;
|
|
277
|
+
const ensure = `Antes do GO, ork worktree ensure ${thread.id} cria a worktree e a branch da thread`;
|
|
278
|
+
if (thread.base.commit === util_1.COMMIT_DESCONHECIDO) {
|
|
279
|
+
// Sem commit, nem o `ork worktree ensure` tem de onde partir: o caminho e o do aviso de thread sem base.
|
|
280
|
+
return `${inicio}, num repositório ainda sem commit, fora de qualquer branch, e o ork ship não tem branch de origem ` +
|
|
281
|
+
'para entregar. Faça o primeiro commit e siga o aviso de thread sem base.';
|
|
282
|
+
}
|
|
283
|
+
if (branch === 'HEAD') {
|
|
284
|
+
return `${inicio}, com o HEAD destacado, fora de qualquer branch, e o ork ship não tem branch de origem para entregar. ${ensure}.`;
|
|
285
|
+
}
|
|
286
|
+
if (branch !== base) {
|
|
287
|
+
return `${inicio}, na branch ${branch}, e o ork ship entrega essa branch como estiver, com o que mais entrar nela; ` +
|
|
288
|
+
`com --para ${branch}, a entrega vira push direto, que a policy push_direto_na_base confere. ${ensure}.`;
|
|
289
|
+
}
|
|
290
|
+
const policy = manifesto.policies?.push_direto_na_base;
|
|
291
|
+
const efeito = policy === 'block'
|
|
292
|
+
? 'o ork ship barra a entrega por push_direto_na_base (block): não há branch de thread para mergear'
|
|
293
|
+
: policy === undefined || policy === 'off'
|
|
294
|
+
? 'o ork ship empurra a base direto, sem branch de thread (push_direto_na_base desligada)'
|
|
295
|
+
: `o ork ship avisa push_direto_na_base (${policy}) e empurra a base direto, sem branch de thread`;
|
|
296
|
+
return `${inicio}, na branch base ${base}, e ${efeito}. ${ensure}; depois do GO, os commits já estão na base e o ship não os separa.`;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* P4 do ensaio da 0.5.0 (CHECK): no `--dry-run`, por que a criacao de verdade recusaria a worktree, em vez de preve-la.
|
|
300
|
+
* O ciclo que exige worktree nao aceita `--sem-worktree`, entao a saida so e sugerida para a chave e a flag.
|
|
301
|
+
*/
|
|
302
|
+
function avisoDeWorktreeQueFalharia(f) {
|
|
303
|
+
const semWorktree = f.por === 'ciclo' ? '' : ' ou crie com --sem-worktree';
|
|
304
|
+
if (f.motivo === 'pasta-existe') {
|
|
305
|
+
return `Aviso: a pasta ${f.dir} já existe, e a criação de verdade recusaria a worktree da thread: tire a pasta${semWorktree}.`;
|
|
306
|
+
}
|
|
307
|
+
if (f.motivo === 'branch-existe') {
|
|
308
|
+
return `Aviso: a branch ${f.branch} já existe, e a criação de verdade recusaria a worktree da thread: tire a branch${semWorktree}.`;
|
|
309
|
+
}
|
|
310
|
+
return 'Aviso: o repositório ainda não tem commit, e a criação de verdade recusaria a worktree da thread no git worktree add: ' +
|
|
311
|
+
'faça o primeiro commit antes.';
|
|
312
|
+
}
|
|
313
|
+
/** P4 do ensaio da 0.5.0: a worktree que a chave pede nao tem de onde partir num repositorio sem commit. */
|
|
314
|
+
function avisoDeChaveSemCommit(gravada) {
|
|
315
|
+
return 'Aviso: worktree.por_thread pede a worktree da thread, mas o repositório ainda não tem commit: ' +
|
|
316
|
+
`a thread ${gravada ? 'nasceu' : 'nasceria'} na raiz do projeto, sem worktree.`;
|
|
317
|
+
}
|
|
318
|
+
/** P4: o aviso de worktree do `ork thread new`, para o stderr, ou `null` quando nao ha o que avisar. */
|
|
319
|
+
function avisoDaWorktree(origem, resultado, manifesto) {
|
|
320
|
+
if (origem === 'sem-worktree')
|
|
321
|
+
return avisoDeThreadSemWorktree(resultado.thread, manifesto, resultado.gravada);
|
|
322
|
+
if (origem === 'chave' && !resultado.worktreePor)
|
|
323
|
+
return avisoDeChaveSemCommit(resultado.gravada);
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
182
326
|
/** Cria a thread: valida modo contra o manifesto, gera o slug e carimba a base. */
|
|
183
327
|
function novaThread(carregado, opcoes) {
|
|
184
328
|
if (opcoes.dryRun)
|
|
@@ -236,6 +380,13 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
236
380
|
else if (opcoes.branch) {
|
|
237
381
|
throw new Error('--branch so vale com --ciclo merge-branch');
|
|
238
382
|
}
|
|
383
|
+
// `greenfield`, `merge-branch` e `feature-xl-faseada` exigem worktree isolada: sao os
|
|
384
|
+
// ciclos que escrevem codigo em paralelo com outras threads.
|
|
385
|
+
const exigeWorktree = variante ? (0, ciclos_1.definicaoDaVariante)(variante).exigeWorktree : false;
|
|
386
|
+
// P4 do ensaio da 0.5.0 (D4): o ciclo que exige worktree nao nasce sem ela, e a recusa sai antes de gravar.
|
|
387
|
+
if (exigeWorktree && opcoes.origemDaWorktree === 'sem-worktree') {
|
|
388
|
+
throw new Error(`o ciclo ${variante} exige worktree isolada: crie a thread sem --sem-worktree ou escolha outro ciclo`);
|
|
389
|
+
}
|
|
239
390
|
const reservation = opcoes.reservation;
|
|
240
391
|
const operation = reservation ? (0, creation_operation_store_1.readCreationOperation)(raiz, reservation.operationId, reservation.principal) : null;
|
|
241
392
|
if (operation && (!operation.reserved.threadIds.includes(reservation.threadId)
|
|
@@ -260,11 +411,11 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
260
411
|
&& fs.readdirSync(dirThread(raiz, reservation.threadId)).some((name) => !/^\.thread\.json\..+\.tmp$/.test(name))) {
|
|
261
412
|
throw new Error('creation.conflict: diretório reservado sem origem confirmada');
|
|
262
413
|
}
|
|
414
|
+
// P4 do ensaio da 0.5.0 (CHECK): o ensaio usa o mesmo id livre da criacao (o `idDisponivel` so le o disco), para a
|
|
415
|
+
// worktree que ele mostra ser a que a criacao usaria.
|
|
263
416
|
const { id, assunto } = reservation
|
|
264
417
|
? { id: reservation.threadId, assunto: reservation.threadId.slice(abbrev.length + 1) }
|
|
265
|
-
:
|
|
266
|
-
? { id: `${abbrev}-${assuntoBruto}`, assunto: assuntoBruto }
|
|
267
|
-
: idDisponivel(raiz, abbrev, assuntoBruto);
|
|
418
|
+
: idDisponivel(raiz, abbrev, assuntoBruto);
|
|
268
419
|
const slug = opcoes.slug ?? (0, slug_1.montarSlug)(abbrev, assunto, blocos[0].slugFases);
|
|
269
420
|
// O override `--slug` do builder tambem passa pela regex canonica.
|
|
270
421
|
if (!(0, slug_1.slugValido)(slug)) {
|
|
@@ -300,13 +451,38 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
300
451
|
};
|
|
301
452
|
if (variante === 'feature-xl-faseada')
|
|
302
453
|
thread.fatias = opcoes.fatias ?? 3;
|
|
303
|
-
|
|
304
|
-
|
|
454
|
+
// P4 do ensaio da 0.5.0: por que a thread ganha a worktree. O ensaio e a chave preveem a worktree antes; a pedida
|
|
455
|
+
// por flag ou por ciclo segue direto ao git, como era. A pedida so pela chave espera o primeiro commit (D3): sem
|
|
456
|
+
// commit, a thread fica na raiz, como antes. O ciclo que exige worktree vence a chave e a flag na origem: a worktree
|
|
457
|
+
// e dele, e o `--sem-worktree` que a linha da chave sugeriria ele recusa (CHECK, rodada 2).
|
|
458
|
+
const pedeWorktree = opcoes.criarWorktree === true || exigeWorktree;
|
|
459
|
+
const pelaChave = opcoes.criarWorktree === true && opcoes.origemDaWorktree === 'chave';
|
|
460
|
+
const prevista = pedeWorktree && (opcoes.dryRun || pelaChave)
|
|
461
|
+
? worktreePrevista(carregado, id, slug, { branchExistente: opcoes.branch }) : null;
|
|
462
|
+
const worktreePor = !pedeWorktree || (pelaChave && !exigeWorktree && prevista?.falha === 'sem-commit') ? null
|
|
463
|
+
: exigeWorktree ? 'ciclo' : pelaChave ? 'chave' : 'flag';
|
|
464
|
+
if (opcoes.dryRun) {
|
|
465
|
+
// P4 (D8): o ensaio mostra a worktree que a criacao usaria; quando ela recusaria, diz por que, em vez de preve-la.
|
|
466
|
+
if (worktreePor && prevista?.falha) {
|
|
467
|
+
return { thread, gravada: false, worktreePor: null,
|
|
468
|
+
worktreeFalharia: { motivo: prevista.falha, dir: prevista.dir, branch: prevista.branch, por: worktreePor } };
|
|
469
|
+
}
|
|
470
|
+
if (worktreePor && prevista?.commit) {
|
|
471
|
+
thread.worktree = prevista.dir;
|
|
472
|
+
thread.base = { branch: prevista.branch, commit: prevista.commit };
|
|
473
|
+
}
|
|
474
|
+
return { thread, gravada: false, worktreePor };
|
|
475
|
+
}
|
|
476
|
+
// P4 (CHECK): a worktree pedida so pela chave, com a pasta ou a branch ja ocupadas, recusa dizendo de onde veio o
|
|
477
|
+
// pedido e qual e a saida.
|
|
478
|
+
const ocupadaPelaChave = pelaChave && !exigeWorktree && prevista &&
|
|
479
|
+
(prevista.falha === 'pasta-existe' || prevista.falha === 'branch-existe') ? prevista : null;
|
|
480
|
+
if (ocupadaPelaChave) {
|
|
481
|
+
const qual = ocupadaPelaChave.falha === 'pasta-existe' ? `a pasta ${ocupadaPelaChave.dir}` : `a branch ${ocupadaPelaChave.branch}`;
|
|
482
|
+
throw new Error(`${qual} já existe, e a chave worktree.por_thread pede a worktree da thread: tire-a ou crie com --sem-worktree`);
|
|
483
|
+
}
|
|
305
484
|
let worktreeCriada = null;
|
|
306
|
-
|
|
307
|
-
// ciclos que escrevem codigo em paralelo com outras threads.
|
|
308
|
-
const exigeWorktree = variante ? (0, ciclos_1.definicaoDaVariante)(variante).exigeWorktree : false;
|
|
309
|
-
if (opcoes.criarWorktree || exigeWorktree) {
|
|
485
|
+
if (worktreePor) {
|
|
310
486
|
worktreeCriada = criarWorktree(carregado, id, slug, {
|
|
311
487
|
branchExistente: opcoes.branch,
|
|
312
488
|
});
|
|
@@ -328,6 +504,8 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
328
504
|
base: thread.base,
|
|
329
505
|
projeto: manifesto.project.name,
|
|
330
506
|
worktree: thread.worktree,
|
|
507
|
+
// P4 do ensaio da 0.5.0 (D9): quem abriu a thread sem worktree de proposito fica no rastro.
|
|
508
|
+
...(opcoes.origemDaWorktree === 'sem-worktree' ? { semWorktree: true } : {}),
|
|
331
509
|
variante,
|
|
332
510
|
branchDeOrigem: opcoes.branch ?? null,
|
|
333
511
|
maquina: thread.maquina,
|
|
@@ -338,10 +516,11 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
338
516
|
dir: worktreeCriada.dir,
|
|
339
517
|
branch: worktreeCriada.branch,
|
|
340
518
|
base: manifesto.worktree.base_branch,
|
|
519
|
+
origem: worktreePor,
|
|
341
520
|
fonte: 'git worktree list --porcelain',
|
|
342
521
|
});
|
|
343
522
|
}
|
|
344
|
-
return { thread, gravada: true };
|
|
523
|
+
return { thread, gravada: true, worktreePor };
|
|
345
524
|
}
|
|
346
525
|
/**
|
|
347
526
|
* O bloco de loop que conduz a fase DESTA thread.
|
package/dist/worktree.js
CHANGED
|
@@ -64,9 +64,12 @@ const leases_1 = require("./leases");
|
|
|
64
64
|
const thread_1 = require("./thread");
|
|
65
65
|
const util_1 = require("./util");
|
|
66
66
|
const estado_thread_1 = require("./estado-thread");
|
|
67
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* Diretorio canonico da worktree de uma thread, resolvido pelo `ork` na arvore principal: o mesmo que a criacao usa,
|
|
69
|
+
* tambem quando o comando roda de dentro de outra worktree (P4 do ensaio da 0.5.0).
|
|
70
|
+
*/
|
|
68
71
|
function dirDaWorktree(carregado, id) {
|
|
69
|
-
return
|
|
72
|
+
return (0, thread_1.pastaDaWorktree)(carregado, id);
|
|
70
73
|
}
|
|
71
74
|
/** Branch canonica da worktree de uma thread. */
|
|
72
75
|
function branchDaWorktree(thread) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "fx-pedido-colado",
|
|
3
|
+
"sobre": "Incidente de 01/10/2026 (RM-057): o pedido colado com autorização explícita segue sem parar",
|
|
4
|
+
"precisa": [
|
|
5
|
+
"git"
|
|
6
|
+
],
|
|
7
|
+
"esperado": {
|
|
8
|
+
"simulado": true,
|
|
9
|
+
"modoDoPedido": "auto",
|
|
10
|
+
"semPausaDoModo": true,
|
|
11
|
+
"decisaoInformada": true,
|
|
12
|
+
"confirmoRecusado": "hitl.selecao.texto-livre",
|
|
13
|
+
"nadaGravadoNaRecusa": true,
|
|
14
|
+
"humanosNoPulse": 0,
|
|
15
|
+
"perguntasDeConducao": 0,
|
|
16
|
+
"tempoParadoMs": 0,
|
|
17
|
+
"adaptadoresComARegra": 4
|
|
18
|
+
},
|
|
19
|
+
"porque": "Na noite de 01 para 02/10 o condutor parou mais de 10 h pedindo um confirmo em texto livre a um pedido colado que já trazia a autorização. O canário prova, contra o código real, que o #Auto não pausa, a dúvida vira decisão informada, o confirmo em texto é recusado sem gravar nada, ninguém aparece esperando no pulse, o tempo parado é zero e os quatro adaptadores dizem a regra."
|
|
20
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orkastery/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "A software factory of AI agents that proves its work: parallel threads, verified results, and short decisions only when they matter.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/orkastery/orkastery#readme",
|
|
@@ -65,12 +65,16 @@
|
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "^22.10.2",
|
|
68
|
-
"markdownlint-cli2": "^0.
|
|
69
|
-
"typescript": "^5.9.2"
|
|
68
|
+
"markdownlint-cli2": "^0.22.1"
|
|
70
69
|
},
|
|
71
70
|
"dependencies": {
|
|
72
71
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
72
|
+
"decode-named-character-reference": "1.3.0",
|
|
73
|
+
"micromark": "4.0.2",
|
|
74
|
+
"micromark-extension-gfm-table": "2.1.1",
|
|
75
|
+
"micromark-util-decode-numeric-character-reference": "2.0.2",
|
|
73
76
|
"smol-toml": "1.8.0",
|
|
77
|
+
"typescript": "5.9.3",
|
|
74
78
|
"zod": "3.25.76",
|
|
75
79
|
"zod-to-json-schema": "3.25.2"
|
|
76
80
|
}
|
|
@@ -54,7 +54,7 @@ flowchart LR
|
|
|
54
54
|
|
|
55
55
|
| # | Verificacao | Como se comprova |
|
|
56
56
|
|---|---|---|
|
|
57
|
-
| 16 | Existe MASTER log valido contra o contrato congelado `ork.master-log/v1`, com POSTMORTEM tipado, classes de falha do catalogo fixo, score inteiro de 0 a 5 e justificativa nao vazia. Uma entrega sem MASTER log nao aconteceu. | `ork master <thread> --score N --justificativa "<texto>"
|
|
57
|
+
| 16 | Existe MASTER log valido contra o contrato congelado `ork.master-log/v1`, com POSTMORTEM tipado, classes de falha do catalogo fixo, score inteiro de 0 a 5 e justificativa nao vazia. Uma entrega sem MASTER log nao aconteceu. | `ork master <thread> --score N --justificativa "<texto>" --por <quem>`. O comando recusa score fora da escala, score sem justificativa, score sem autoria humana em `--por` e classe fora do catalogo, e nao grava nada quando recusa. |
|
|
58
58
|
|
|
59
59
|
## Toda thread, no seu inicio
|
|
60
60
|
|
package/skills/README.md
CHANGED
|
@@ -18,7 +18,7 @@ faz, o nucleo vence, e a divergencia e defeito da skill.
|
|
|
18
18
|
| phases | [go-implementation](phases/go-implementation/SKILL.md) | `ork worktree ensure`, `ork verify --baseline` |
|
|
19
19
|
| phases | [check-quality](phases/check-quality/SKILL.md) | `ork verify`, `ork gate request` |
|
|
20
20
|
| phases | [ship-release](phases/ship-release/SKILL.md) | `ork ship` |
|
|
21
|
-
| phases | [master-metrics](phases/master-metrics/SKILL.md) | `ork master`, `ork master --aceitar-omissao` |
|
|
21
|
+
| phases | [master-metrics](phases/master-metrics/SKILL.md) | `ork master`, `ork master <thread> --aceitar-omissao` |
|
|
22
22
|
| reviewers | [code-reviewer](reviewers/code-reviewer/SKILL.md) | `references/code-review-axes.md` |
|
|
23
23
|
| reviewers | [security-auditor](reviewers/security-auditor/SKILL.md) | `references/security-checklist.md` |
|
|
24
24
|
| reviewers | [test-engineer](reviewers/test-engineer/SKILL.md) | `references/testing-patterns.md` |
|
|
@@ -56,6 +56,7 @@ Prefira MCP no projeto fixado pelo servidor, sem outro root/cwd. No Claude com s
|
|
|
56
56
|
| Demanda nova | `ork_thread_new(nome, modo)` | `ork thread new "<nome>" --mode <modo> --worktree auto` |
|
|
57
57
|
| Despacho | `ork_phase_run(threadId, fase, prompt, runtime?, model?, effort?, dryRun?)` | `ork phase run <thread> GOAL --prompt "<pedido>"` |
|
|
58
58
|
| Progresso nativo | `ork_observe(threadId)` | `ork thread status <thread>` |
|
|
59
|
+
| Contexto do grafo (somente com `grafo.mcp: true`) | `ork_grafo_contexto(threadId, tetoBytes?)`; aprofundar com `ork_grafo_vizinhos`, `ork_grafo_chamadores`, `ork_grafo_importadores`, `ork_grafo_caminho` | `ork grafo contexto <thread> --json` |
|
|
59
60
|
| Pendencia/decisao | `ork_hitl_pending`, `ork_request_decision(threadId, pedidoId)` | Consulte o ingresso suportado; nao fabrique resposta. |
|
|
60
61
|
|
|
61
62
|
Prefira `ork_git_commit` (HEAD atual, paths com claims), `ork_verify` e `ork_ship` (HEADs fonte/destino reais) para registrar, verificar e entregar. Autoria/commit nao e SHIP; retorno incomplete exige reconciliacao antes de repetir. Para demandas novas, use `ork modos --do-pedido "<pedido do dono>"` e `ork_preflight({modo})` (CLI: `ork doctor --modo <modo>`). A sonda por bloco não comprova autenticação, gates ou entrega.
|
|
@@ -71,8 +72,7 @@ Dry-run nao inicia modelo, mas pode gravar prompt/eventos. Confira o trio efetiv
|
|
|
71
72
|
|
|
72
73
|
## Conducao durante o trabalho
|
|
73
74
|
|
|
74
|
-
O modo afrouxa a pausa, NUNCA a verificacao. Claims, verify, policies e gates tipados
|
|
75
|
-
rodam identicos em `#Classic` e em `#Auto`; o modo decide se o veredito espera o humano.
|
|
75
|
+
O modo afrouxa a pausa, NUNCA a verificacao. Claims, verify, policies e gates tipados rodam identicos em `#Classic` e em `#Auto`; o modo decide se o veredito espera o humano.
|
|
76
76
|
|
|
77
77
|
Depois de uma acao, use o resultado do nucleo para executar o proximo passo autorizado.
|
|
78
78
|
Em #Auto/#Maestro, nao termine um bloco apenas oferecendo continuar quando ainda ha trabalho
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: master-metrics
|
|
3
|
-
description: "Fase MASTER (F6): POSTMORTEM tipado, MASTER log no contrato congelado ork.master-log/v1 e o score humano de 0 a 5 com justificativa. Roteia para ork master e ork master --aceitar-omissao."
|
|
3
|
+
description: "Fase MASTER (F6): POSTMORTEM tipado, MASTER log no contrato congelado ork.master-log/v1 e o score humano de 0 a 5 com justificativa. Roteia para ork master e ork master <thread> --aceitar-omissao."
|
|
4
4
|
bucket: phases
|
|
5
|
-
roteia: "ork master <thread> --score N --justificativa \"...\" | ork master --aceitar-omissao"
|
|
5
|
+
roteia: "ork master <thread> --score N --justificativa \"...\" | ork master <thread> --aceitar-omissao"
|
|
6
6
|
license: MIT
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -21,9 +21,14 @@ ork master classes # as classes de falha do catalogo
|
|
|
21
21
|
ork master <thread> --score 4 --justificativa "<texto>" --classe base-avancou --por <quem>
|
|
22
22
|
ork master # as entregas, com o indice derivado do ledger
|
|
23
23
|
ork master --todas # inclusive as ja pontuadas
|
|
24
|
-
ork master --aceitar-omissao
|
|
24
|
+
ork master <thread> --aceitar-omissao # aceita so a entrega desta thread, com indice e insumos no ledger
|
|
25
|
+
ork master --aceitar-omissao --dry-run # lista o que a forma sem thread fecharia, sem gravar
|
|
25
26
|
```
|
|
26
27
|
|
|
28
|
+
Agente fecha so a propria thread: `ork master <thread> --aceitar-omissao`. Sem a thread, o comando
|
|
29
|
+
aceita TODAS as entregues do projeto, inclusive as de outras frentes paralelas (o que aconteceu tres
|
|
30
|
+
vezes em 03/10/2026); de processo de agente com mais de uma, o `ork` avisa em stderr.
|
|
31
|
+
|
|
27
32
|
## O que o MASTER entrega
|
|
28
33
|
|
|
29
34
|
1. **POSTMORTEM tipado**, com as fases percorridas, o que falhou e a classe de falha vinda de um
|