@orkastery/cli 0.5.1 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/claude-code/README.md +158 -0
- package/adapters/claude-code/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/claude-code/mods/autoridade.json +56 -0
- package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
- package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
- package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
- package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
- package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
- package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
- package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
- package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
- package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
- package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
- package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
- package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
- package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
- package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
- package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
- package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
- package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
- package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
- package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
- package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
- package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
- package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
- package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
- package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
- package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
- package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
- package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
- package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
- package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
- package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
- package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
- package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
- package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
- package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
- package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
- package/adapters/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 +7 -6
- package/adapters/openclaw/README.md +26 -5
- 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/docs-en/markdownlint-cli2.jsonc +22 -0
- package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
- package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
- package/assets/docs-en/produto/README.md +14 -0
- package/assets/docs-en/produto/_modelo-feature.md +62 -0
- package/assets/docs-en/roadmap/README.md +14 -0
- package/assets/docs-en/roadmap/_modelo-item.md +75 -0
- package/assets/orkmind_bridge.py +117 -9
- package/dist/adapters/claude-bg.js +116 -18
- package/dist/adapters/codex.js +14 -4
- package/dist/agents-md.js +24 -14
- package/dist/auditrun.js +22 -3
- package/dist/board.js +20 -17
- package/dist/branch-de-estado.js +88 -10
- package/dist/busca-semantica.js +52 -12
- package/dist/canarios-rm057.js +149 -0
- package/dist/canarios.js +2 -0
- package/dist/catalogo.js +33 -0
- package/dist/ci.js +21 -8
- package/dist/claims-conferir.js +342 -0
- package/dist/claims.js +41 -1
- package/dist/company-brain-client.js +36 -1
- package/dist/company-brain-context.js +158 -22
- package/dist/company-brain-journal.js +2 -1
- package/dist/company-brain-migration.js +36 -1
- package/dist/conducao-sentinela.js +388 -0
- package/dist/conducao-texto.js +12 -18
- package/dist/conducao.js +122 -30
- package/dist/conhecimento.js +490 -0
- package/dist/docs.js +70 -17
- package/dist/doctor-pulse-cron.js +349 -0
- package/dist/doctor-rede.js +150 -0
- package/dist/doctor.js +195 -111
- package/dist/entrega-pr.js +42 -29
- package/dist/escopo-escrita.js +10 -1
- package/dist/esgotamentos.js +181 -0
- package/dist/estado-thread.js +23 -1
- package/dist/experiencia-instalacao.js +45 -25
- package/dist/experiencia.js +12 -2
- package/dist/fabrica-batida.js +310 -0
- package/dist/fabrica-estado.js +52 -14
- package/dist/fabrica-publicar.js +9 -1
- package/dist/fechamento.js +20 -66
- package/dist/fila-pesada.js +444 -0
- package/dist/fix.js +3 -2
- package/dist/forja.js +31 -7
- package/dist/gates.js +3 -24
- package/dist/handoff.js +10 -6
- package/dist/hitl-contract.js +59 -4
- package/dist/hitl-curto.js +11 -6
- package/dist/hitl-gates.js +5 -0
- package/dist/hitl-local-receipt.js +2 -0
- package/dist/hitl-lote.js +5 -2
- package/dist/hitl-resumo.js +38 -3
- package/dist/hitl-tempo-parado.js +201 -0
- package/dist/hitl-texto-livre.js +5 -5
- package/dist/hitl.js +29 -33
- package/dist/horario.js +41 -7
- package/dist/hosts.js +104 -11
- package/dist/impedimento.js +299 -0
- package/dist/index.js +961 -542
- package/dist/indice-vetorial.js +87 -10
- package/dist/indice.js +9 -1
- package/dist/init.js +56 -43
- package/dist/instabilidade.js +144 -0
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +170 -16
- package/dist/intelligence-graph-contexto.js +254 -0
- package/dist/intelligence-graph-contract.js +2 -1
- package/dist/intelligence-graph-extract-md.js +56 -4
- package/dist/intelligence-graph-extract-ts.js +71 -3
- package/dist/intelligence-graph-parsers.js +6 -4
- package/dist/intelligence-graph-query.js +66 -19
- package/dist/leases.js +664 -87
- package/dist/ledger-stats.js +15 -1
- package/dist/ledger.js +18 -1
- package/dist/licoes.js +1 -0
- package/dist/liveness.js +6 -3
- package/dist/locale-ajuda.js +761 -0
- package/dist/locale-gerados.js +160 -0
- package/dist/locale-master.js +99 -0
- package/dist/locale-onboarding.js +92 -0
- package/dist/locale-phase.js +151 -0
- package/dist/locale-pulse.js +211 -0
- package/dist/locale-retry.js +385 -0
- package/dist/locale-roadmap.js +102 -0
- package/dist/locale-ship.js +494 -0
- package/dist/locale-thread.js +277 -0
- package/dist/locale-verify.js +125 -0
- package/dist/locale.js +714 -0
- package/dist/maestro-runtime.js +4 -1
- package/dist/manifest.js +149 -4
- package/dist/maquina.js +23 -4
- package/dist/master-digest.js +6 -1
- package/dist/master-nota.js +18 -11
- package/dist/master.js +145 -31
- package/dist/mcp-artifacts.js +43 -3
- package/dist/mcp-git.js +42 -8
- package/dist/mcp-grafo-worker.js +5 -3
- package/dist/mcp-grafo.js +55 -6
- package/dist/mcp-server.js +22 -3
- package/dist/mcp-ship.js +3 -1
- package/dist/mcp-verify.js +6 -1
- package/dist/memoria.js +48 -6
- package/dist/modos.js +3 -6
- package/dist/network-roadmap.js +196 -18
- package/dist/noctum-arco.js +911 -0
- package/dist/noctum-capacidade.js +141 -0
- package/dist/noctum-envelope.js +810 -0
- package/dist/noctum-execucao.js +304 -0
- package/dist/noctum-fila.js +280 -0
- package/dist/ocupacao.js +40 -5
- package/dist/onboarding.js +40 -21
- package/dist/orkmind.js +99 -7
- package/dist/orquestracao.js +24 -21
- package/dist/parado-no-condutor.js +219 -38
- package/dist/phase.js +160 -52
- package/dist/policies.js +56 -5
- package/dist/portfolio.js +8 -3
- package/dist/postura-local.js +234 -0
- package/dist/preflight.js +11 -10
- package/dist/procedencia.js +225 -0
- package/dist/projeto-alvo.js +132 -5
- package/dist/prompts.js +40 -1
- package/dist/prova-ativacao.js +75 -6
- package/dist/pulse-delivery.js +47 -4
- package/dist/pulse.js +98 -19
- package/dist/ratelimit.js +24 -6
- package/dist/recall.js +3 -1
- package/dist/redacao-saida.js +63 -0
- 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 +337 -0
- package/dist/rede.js +980 -0
- package/dist/retry.js +291 -140
- package/dist/roadmap-reservas.js +20 -3
- package/dist/roadmap-status.js +150 -34
- package/dist/runtime-context.js +181 -3
- package/dist/runtime-profiles.js +22 -1
- package/dist/runtimes.js +2 -1
- package/dist/saida-segura.js +58 -0
- package/dist/session-events.js +7 -3
- package/dist/session-watcher-claude.js +120 -24
- package/dist/session-watcher.js +185 -33
- package/dist/sessoes-contas.js +187 -0
- package/dist/sessoes-inventario.js +6 -18
- package/dist/sessoes.js +83 -2
- package/dist/ship-publicar.js +800 -0
- package/dist/ship.js +157 -88
- package/dist/steal.js +77 -0
- package/dist/thread-close.js +3 -2
- package/dist/thread.js +299 -49
- package/dist/util.js +8 -1
- package/dist/verify.js +141 -52
- package/dist/vida-da-thread.js +254 -0
- package/dist/worktree-local.js +165 -0
- package/dist/worktree.js +25 -2
- package/dist/yaml.js +27 -8
- package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
- package/package.json +7 -3
- package/references/definition-of-done.md +1 -1
- package/schemas/code-artifact-graph.v1.schema.json +2 -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
|
@@ -39,6 +39,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
39
39
|
};
|
|
40
40
|
})();
|
|
41
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.TETO_DO_PEDIDO = exports.ARQUIVO_DO_PEDIDO = void 0;
|
|
42
43
|
exports.dirThreads = dirThreads;
|
|
43
44
|
exports.dirThread = dirThread;
|
|
44
45
|
exports.caminhoThread = caminhoThread;
|
|
@@ -47,7 +48,18 @@ exports.lerThread = lerThread;
|
|
|
47
48
|
exports.gravarThread = gravarThread;
|
|
48
49
|
exports.avisoDeThreadSemBase = avisoDeThreadSemBase;
|
|
49
50
|
exports.idDisponivel = idDisponivel;
|
|
51
|
+
exports.pastaDaWorktree = pastaDaWorktree;
|
|
52
|
+
exports.alvoDaWorktree = alvoDaWorktree;
|
|
53
|
+
exports.worktreePrevista = worktreePrevista;
|
|
50
54
|
exports.criarWorktree = criarWorktree;
|
|
55
|
+
exports.pedidoDeWorktree = pedidoDeWorktree;
|
|
56
|
+
exports.linhaDaWorktree = linhaDaWorktree;
|
|
57
|
+
exports.avisoDeThreadSemWorktree = avisoDeThreadSemWorktree;
|
|
58
|
+
exports.avisoDeWorktreeQueFalharia = avisoDeWorktreeQueFalharia;
|
|
59
|
+
exports.avisoDeChaveSemCommit = avisoDeChaveSemCommit;
|
|
60
|
+
exports.avisoDaWorktree = avisoDaWorktree;
|
|
61
|
+
exports.prepararPedido = prepararPedido;
|
|
62
|
+
exports.pedidoDaThread = pedidoDaThread;
|
|
51
63
|
exports.novaThread = novaThread;
|
|
52
64
|
exports.exigirVarianteCompativel = exigirVarianteCompativel;
|
|
53
65
|
exports.blocoDaThread = blocoDaThread;
|
|
@@ -58,12 +70,14 @@ exports.resumoDaThread = resumoDaThread;
|
|
|
58
70
|
exports.threadsDaListagem = threadsDaListagem;
|
|
59
71
|
exports.tabelaDeThreads = tabelaDeThreads;
|
|
60
72
|
exports.exigirFase = exigirFase;
|
|
73
|
+
const worktree_local_1 = require("./worktree-local");
|
|
61
74
|
const fs = __importStar(require("node:fs"));
|
|
62
75
|
const path = __importStar(require("node:path"));
|
|
63
76
|
const ciclos_1 = require("./ciclos");
|
|
64
77
|
const modos_1 = require("./modos");
|
|
65
78
|
const manifest_1 = require("./manifest");
|
|
66
79
|
const slug_1 = require("./slug");
|
|
80
|
+
const node_crypto_1 = require("node:crypto");
|
|
67
81
|
const types_1 = require("./types");
|
|
68
82
|
const util_1 = require("./util");
|
|
69
83
|
const ledger_1 = require("./ledger");
|
|
@@ -72,6 +86,7 @@ const creation_operation_store_1 = require("./creation-operation-store");
|
|
|
72
86
|
const horario_1 = require("./horario");
|
|
73
87
|
const maquina_1 = require("./maquina");
|
|
74
88
|
const conducao_texto_1 = require("./conducao-texto");
|
|
89
|
+
const locale_1 = require("./locale");
|
|
75
90
|
/** Diretorio de threads do projeto. */
|
|
76
91
|
function dirThreads(raiz) {
|
|
77
92
|
return path.join((0, manifest_1.dirEstado)((0, estado_thread_1.raizDoEstado)(raiz)), 'threads');
|
|
@@ -99,7 +114,7 @@ function listarIds(raiz) {
|
|
|
99
114
|
function lerThread(raiz, id) {
|
|
100
115
|
const caminho = caminhoThread(raiz, id);
|
|
101
116
|
if (!fs.existsSync(caminho)) {
|
|
102
|
-
throw new
|
|
117
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.naoEncontrada(id, dirThreads(raiz)));
|
|
103
118
|
}
|
|
104
119
|
return (0, util_1.lerJson)(caminho);
|
|
105
120
|
}
|
|
@@ -124,11 +139,7 @@ function carimbarBase(raiz) {
|
|
|
124
139
|
function avisoDeThreadSemBase(thread, gravada) {
|
|
125
140
|
if (thread.base.commit !== util_1.COMMIT_DESCONHECIDO)
|
|
126
141
|
return null;
|
|
127
|
-
return gravada
|
|
128
|
-
? `Aviso: o repositório ainda não tem commit, e a thread ${thread.id} nasceu sem base: o ship não tem de onde partir. ` +
|
|
129
|
-
`Faça o primeiro commit, feche esta com ork thread close ${thread.id} --motivo engano --por <quem> ` +
|
|
130
|
-
'--justificativa "aberta antes do primeiro commit" e abra outra.'
|
|
131
|
-
: 'Aviso: o repositório ainda não tem commit, e a thread nasceria sem base: faça o primeiro commit antes de abrir a primeira thread.';
|
|
142
|
+
return (0, locale_1.msg)().thread.semBase(thread.id, gravada);
|
|
132
143
|
}
|
|
133
144
|
/** Resolve um id livre a partir do assunto normalizado (`<abbrev>-<assunto>`). */
|
|
134
145
|
function idDisponivel(raiz, abbrev, assunto) {
|
|
@@ -141,6 +152,43 @@ function idDisponivel(raiz, abbrev, assunto) {
|
|
|
141
152
|
}
|
|
142
153
|
return { id: `${abbrev}-${candidato}`, assunto: candidato };
|
|
143
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Pasta da worktree de uma thread: `worktree.dir` resolvido na arvore principal, nunca na worktree de onde o comando
|
|
157
|
+
* roda. P4 do ensaio da 0.5.0 (CHECK): com a chave valendo, o `ork thread new` rodado de dentro da worktree de outra
|
|
158
|
+
* thread aninhava a nova na pasta da mae, e o release da mae levava a da filha junto.
|
|
159
|
+
*/
|
|
160
|
+
function pastaDaWorktree(carregado, id) {
|
|
161
|
+
return path.resolve((0, estado_thread_1.raizDoEstado)(carregado.raiz), carregado.manifesto.worktree.dir, id);
|
|
162
|
+
}
|
|
163
|
+
/** Pasta e branch da worktree de uma thread: o que `criarWorktree` cria e o `--dry-run` preve. */
|
|
164
|
+
function alvoDaWorktree(carregado, id, slug, opcoes = {}) {
|
|
165
|
+
return { dir: pastaDaWorktree(carregado, id), branch: opcoes.branchExistente ?? `ork/${slug}` };
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* P4 do ensaio da 0.5.0: a worktree que `criarWorktree` criaria para este id, sem criar nada. Mesma pasta, mesma
|
|
169
|
+
* branch e o commit de onde ela partiria: a branch existente (ciclo `merge-branch`), senao a base do manifesto,
|
|
170
|
+
* senao o HEAD. Diz tambem o que faria a criacao recusar: a pasta que ja existe, o repositorio sem commit ou a
|
|
171
|
+
* branch nova que ja existe.
|
|
172
|
+
*/
|
|
173
|
+
function worktreePrevista(carregado, id, slug, opcoes = {}) {
|
|
174
|
+
const alvo = alvoDaWorktree(carregado, id, slug, opcoes);
|
|
175
|
+
const refs = opcoes.branchExistente
|
|
176
|
+
? [opcoes.branchExistente]
|
|
177
|
+
: [opcoes.base ?? carregado.manifesto.worktree.base_branch, 'HEAD'];
|
|
178
|
+
let commit = null;
|
|
179
|
+
for (const ref of refs) {
|
|
180
|
+
const r = (0, util_1.exec)('git', ['rev-parse', '--verify', ref], carregado.raiz);
|
|
181
|
+
if (r.ok) {
|
|
182
|
+
commit = r.stdout.trim();
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const branchJaExiste = !opcoes.branchExistente &&
|
|
187
|
+
(0, util_1.exec)('git', ['rev-parse', '--verify', '--quiet', `refs/heads/${alvo.branch}`], carregado.raiz).ok;
|
|
188
|
+
const falha = fs.existsSync(alvo.dir) ? 'pasta-existe'
|
|
189
|
+
: commit === null ? 'sem-commit' : branchJaExiste ? 'branch-existe' : null;
|
|
190
|
+
return { ...alvo, commit, falha };
|
|
191
|
+
}
|
|
144
192
|
/**
|
|
145
193
|
* Cria a worktree isolada da thread (paralelismo sem colisao entre threads).
|
|
146
194
|
*
|
|
@@ -150,8 +198,9 @@ function idDisponivel(raiz, abbrev, assunto) {
|
|
|
150
198
|
*/
|
|
151
199
|
function criarWorktree(carregado, id, slug, opcoes = {}) {
|
|
152
200
|
const { raiz, manifesto } = carregado;
|
|
153
|
-
|
|
154
|
-
|
|
201
|
+
// RM-047 (P3): worktree.dir do manifesto fora da raiz só cria checkout com a confirmação desta máquina.
|
|
202
|
+
(0, worktree_local_1.exigirPastaDasWorktrees)(raiz, manifesto);
|
|
203
|
+
const { dir, branch } = alvoDaWorktree(carregado, id, slug, opcoes);
|
|
155
204
|
if (fs.existsSync(dir)) {
|
|
156
205
|
throw new Error(`worktree ja existe em ${dir}`);
|
|
157
206
|
}
|
|
@@ -170,7 +219,7 @@ function criarWorktree(carregado, id, slug, opcoes = {}) {
|
|
|
170
219
|
throw new Error(`git worktree add falhou: ${(r.stderr || r.stdout).trim()}`);
|
|
171
220
|
}
|
|
172
221
|
if (pastaNova)
|
|
173
|
-
(0, util_1.ignorarPastaNoGit)(pastaDasWorktrees, raiz);
|
|
222
|
+
(0, util_1.ignorarPastaNoGit)(pastaDasWorktrees, (0, estado_thread_1.raizDoEstado)(raiz));
|
|
174
223
|
const lista = (0, util_1.exec)('git', ['worktree', 'list', '--porcelain'], raiz);
|
|
175
224
|
const criada = lista.ok && lista.stdout.split('\n').some((l) => l.trim() === `worktree ${dir}`);
|
|
176
225
|
if (!criada) {
|
|
@@ -179,6 +228,161 @@ function criarWorktree(carregado, id, slug, opcoes = {}) {
|
|
|
179
228
|
(0, estado_thread_1.vincularEstado)(raiz, id, dir);
|
|
180
229
|
return { dir, branch };
|
|
181
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Resolve `--worktree`, `--sem-worktree` e `worktree.por_thread`. As flags vencem a chave; as duas juntas, ou
|
|
233
|
+
* `--sem-worktree` com valor (o parser leva o argumento seguinte), sao erro de uso. `--worktree` sozinho ou `auto`
|
|
234
|
+
* cria a worktree; outro texto e um diretorio que ja existe, como antes.
|
|
235
|
+
*/
|
|
236
|
+
function pedidoDeWorktree(flags, porThread) {
|
|
237
|
+
const worktree = flags.worktree === false ? undefined : flags.worktree;
|
|
238
|
+
if (typeof worktree === 'string' && !worktree.trim())
|
|
239
|
+
throw new Error((0, locale_1.msg)().thread.worktreeVazia);
|
|
240
|
+
if (typeof flags.semWorktree === 'string')
|
|
241
|
+
throw new Error((0, locale_1.msg)().thread.semWorktreeComValor(flags.semWorktree));
|
|
242
|
+
const semWorktree = flags.semWorktree === true;
|
|
243
|
+
if (semWorktree && worktree !== undefined)
|
|
244
|
+
throw new Error((0, locale_1.msg)().thread.worktreeESemWorktree);
|
|
245
|
+
if (semWorktree)
|
|
246
|
+
return { criar: false, dir: null, origem: 'sem-worktree' };
|
|
247
|
+
if (worktree === true || worktree === 'auto')
|
|
248
|
+
return { criar: true, dir: null, origem: 'flag' };
|
|
249
|
+
if (typeof worktree === 'string')
|
|
250
|
+
return { criar: false, dir: worktree, origem: 'diretorio' };
|
|
251
|
+
return porThread ? { criar: true, dir: null, origem: 'chave' } : { criar: false, dir: null, origem: 'nenhuma' };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* 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
|
|
255
|
+
* chave (quem passou `--worktree auto` sabe de onde ela veio); no `--dry-run`, para qualquer origem.
|
|
256
|
+
*/
|
|
257
|
+
function linhaDaWorktree(por, gravada, variante) {
|
|
258
|
+
if (!por || (gravada && por !== 'chave'))
|
|
259
|
+
return null;
|
|
260
|
+
const m = (0, locale_1.msg)().thread;
|
|
261
|
+
if (por === 'chave')
|
|
262
|
+
return m.worktreeChave(gravada);
|
|
263
|
+
if (por === 'flag')
|
|
264
|
+
return m.worktreeFlag(gravada);
|
|
265
|
+
return m.worktreeCiclo(gravada, variante ?? null);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* P4 do ensaio da 0.5.0: o que acontece no SHIP com a thread criada por `--sem-worktree`. O `ork ship` entrega a
|
|
269
|
+
* branch em que a raiz estava na criacao (`thread.base.branch`), e a policy `push_direto_na_base` do manifesto barra
|
|
270
|
+
* (`block`), avisa (outro valor) ou deixa passar (sem ela, ou `off`) a entrega de uma branch para ela mesma ou da
|
|
271
|
+
* base. Raiz fora de branch (HEAD destacado ou repositorio sem commit) nao tem branch de origem.
|
|
272
|
+
*/
|
|
273
|
+
function avisoDeThreadSemWorktree(thread, manifesto, gravada = true) {
|
|
274
|
+
const base = manifesto.worktree.base_branch;
|
|
275
|
+
const branch = thread.base.branch;
|
|
276
|
+
const aviso = (c) => (0, locale_1.msg)().thread.avisoSemWorktree(thread.id, gravada, c);
|
|
277
|
+
// Sem commit, nem o `ork worktree ensure` tem de onde partir: o caminho e o do aviso de thread sem base.
|
|
278
|
+
if (thread.base.commit === util_1.COMMIT_DESCONHECIDO)
|
|
279
|
+
return aviso({ caso: 'sem-commit' });
|
|
280
|
+
if (branch === 'HEAD')
|
|
281
|
+
return aviso({ caso: 'head' });
|
|
282
|
+
if (branch !== base)
|
|
283
|
+
return aviso({ caso: 'outra', branch });
|
|
284
|
+
const policy = manifesto.policies?.push_direto_na_base;
|
|
285
|
+
return aviso({ caso: 'base', base, policy: policy === undefined ? undefined : String(policy) });
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* 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.
|
|
289
|
+
* O ciclo que exige worktree nao aceita `--sem-worktree`, entao a saida so e sugerida para a chave e a flag.
|
|
290
|
+
*/
|
|
291
|
+
function avisoDeWorktreeQueFalharia(f) {
|
|
292
|
+
return (0, locale_1.msg)().thread.worktreeFalharia(f.motivo, f.dir, f.branch, f.por === 'ciclo');
|
|
293
|
+
}
|
|
294
|
+
/** P4 do ensaio da 0.5.0: a worktree que a chave pede nao tem de onde partir num repositorio sem commit. */
|
|
295
|
+
function avisoDeChaveSemCommit(gravada) {
|
|
296
|
+
return (0, locale_1.msg)().thread.chaveSemCommit(gravada);
|
|
297
|
+
}
|
|
298
|
+
/** P4: o aviso de worktree do `ork thread new`, para o stderr, ou `null` quando nao ha o que avisar. */
|
|
299
|
+
function avisoDaWorktree(origem, resultado, manifesto) {
|
|
300
|
+
if (origem === 'sem-worktree')
|
|
301
|
+
return avisoDeThreadSemWorktree(resultado.thread, manifesto, resultado.gravada);
|
|
302
|
+
if (origem === 'chave' && !resultado.worktreePor)
|
|
303
|
+
return avisoDeChaveSemCommit(resultado.gravada);
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
/** RM-059 (T6.0): o arquivo do pedido guardado, na pasta da thread. */
|
|
307
|
+
exports.ARQUIVO_DO_PEDIDO = 'pedido.md';
|
|
308
|
+
/**
|
|
309
|
+
* O prompt da fase vai inteiro como UM argumento do `claude --bg`, e o Linux recusa argumento acima de
|
|
310
|
+
* 128 KiB (MAX_ARG_STRLEN); o pedido fica com a metade, para o template caber junto.
|
|
311
|
+
*/
|
|
312
|
+
exports.TETO_DO_PEDIDO = 64 * 1024;
|
|
313
|
+
/** O pedido como ele vai ser guardado: sem espaco nas pontas, nao vazio e dentro do teto. */
|
|
314
|
+
function prepararPedido(bruto) {
|
|
315
|
+
const texto = bruto.trim();
|
|
316
|
+
if (!texto)
|
|
317
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.pedidoVazio);
|
|
318
|
+
const bytes = Buffer.byteLength(texto, 'utf8');
|
|
319
|
+
if (bytes > exports.TETO_DO_PEDIDO)
|
|
320
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.pedidoGrande(bytes, exports.TETO_DO_PEDIDO));
|
|
321
|
+
return { texto, meta: { arquivo: exports.ARQUIVO_DO_PEDIDO, sha256: (0, node_crypto_1.createHash)('sha256').update(texto, 'utf8').digest('hex'), bytes } };
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* RM-059 (T6.0): o pedido guardado na criacao da thread, conferido contra o sha256 gravado; `null` na
|
|
325
|
+
* thread criada sem pedido. Arquivo que falta ou que nao bate com o sha256 (editado fora do nucleo) e
|
|
326
|
+
* erro tipado: o render nunca usa um pedido sem a prova de que e o da criacao.
|
|
327
|
+
*/
|
|
328
|
+
function pedidoDaThread(raiz, thread) {
|
|
329
|
+
const meta = thread.pedido;
|
|
330
|
+
if (!meta)
|
|
331
|
+
return null;
|
|
332
|
+
const restaurar = 'passe --pedido no render ou restaure o arquivo';
|
|
333
|
+
// O nome do arquivo e fixo: um thread.json editado nao aponta o render para outro arquivo do projeto.
|
|
334
|
+
if (meta.arquivo !== exports.ARQUIVO_DO_PEDIDO || !/^[a-f0-9]{64}$/.test(String(meta.sha256))) {
|
|
335
|
+
throw new Error(`thread.pedido.divergente: o pedido da thread ${thread.id} no thread.json nao e o que a criacao grava; ${restaurar}`);
|
|
336
|
+
}
|
|
337
|
+
const arquivo = path.join(dirThread(raiz, thread.id), exports.ARQUIVO_DO_PEDIDO);
|
|
338
|
+
let fd;
|
|
339
|
+
try {
|
|
340
|
+
fd = fs.openSync(arquivo, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
|
|
341
|
+
}
|
|
342
|
+
catch (e) {
|
|
343
|
+
if (e.code === 'ENOENT')
|
|
344
|
+
throw new Error(`thread.pedido.ausente: a thread ${thread.id} guardou o pedido em ${meta.arquivo} e ele sumiu; ${restaurar}`);
|
|
345
|
+
throw new Error(`thread.pedido.divergente: ${meta.arquivo} da thread ${thread.id} nao abre como arquivo comum; ${restaurar}`);
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
const st = fs.fstatSync(fd);
|
|
349
|
+
if (!st.isFile() || st.size > exports.TETO_DO_PEDIDO)
|
|
350
|
+
throw new Error(`thread.pedido.divergente: ${meta.arquivo} da thread ${thread.id} nao e o arquivo guardado; ${restaurar}`);
|
|
351
|
+
const bytes = fs.readFileSync(fd);
|
|
352
|
+
const sha256 = (0, node_crypto_1.createHash)('sha256').update(bytes).digest('hex');
|
|
353
|
+
if (sha256 !== meta.sha256) {
|
|
354
|
+
throw new Error(`thread.pedido.divergente: ${meta.arquivo} da thread ${thread.id} nao bate com o sha256 gravado na criacao ` +
|
|
355
|
+
`(${(0, util_1.shaCurto)(meta.sha256)}): foi editado fora do nucleo; ${restaurar}`);
|
|
356
|
+
}
|
|
357
|
+
return { texto: bytes.toString('utf8'), sha256 };
|
|
358
|
+
}
|
|
359
|
+
finally {
|
|
360
|
+
fs.closeSync(fd);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Grava o pedido sem meio-termo: escreve num temporario com fsync e o liga ao nome final, que nao pode existir
|
|
365
|
+
* (o `link` recusa sobrescrever). Uma falha no meio nao deixa `pedido.md` pela metade.
|
|
366
|
+
*/
|
|
367
|
+
function gravarPedido(dir, texto) {
|
|
368
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
369
|
+
const alvo = path.join(dir, exports.ARQUIVO_DO_PEDIDO);
|
|
370
|
+
const temporario = path.join(dir, `.${exports.ARQUIVO_DO_PEDIDO}.${process.pid}.${Date.now()}.tmp`);
|
|
371
|
+
const fd = fs.openSync(temporario, 'wx', 0o600);
|
|
372
|
+
try {
|
|
373
|
+
try {
|
|
374
|
+
fs.writeFileSync(fd, texto, 'utf8');
|
|
375
|
+
fs.fsyncSync(fd);
|
|
376
|
+
}
|
|
377
|
+
finally {
|
|
378
|
+
fs.closeSync(fd);
|
|
379
|
+
}
|
|
380
|
+
fs.linkSync(temporario, alvo);
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
fs.rmSync(temporario, { force: true });
|
|
384
|
+
}
|
|
385
|
+
}
|
|
182
386
|
/** Cria a thread: valida modo contra o manifesto, gera o slug e carimba a base. */
|
|
183
387
|
function novaThread(carregado, opcoes) {
|
|
184
388
|
if (opcoes.dryRun)
|
|
@@ -198,21 +402,23 @@ function exigirVarianteCompativel(variante, def) {
|
|
|
198
402
|
return;
|
|
199
403
|
const [unico, ...resto] = def.blocos;
|
|
200
404
|
if (unico && resto.length === 0 && unico.fases.length < types_1.FASES.length) {
|
|
201
|
-
throw new
|
|
202
|
-
`(${unico.fases.join('-')}): crie a thread sem --ciclo ou escolha um modo de ciclo completo`);
|
|
405
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.varianteIncompativel(variante, def.tag, unico.fases.join('-')));
|
|
203
406
|
}
|
|
204
407
|
}
|
|
205
408
|
function criarThreadSerializada(carregado, opcoes) {
|
|
206
409
|
const { raiz, manifesto } = carregado;
|
|
207
410
|
const permitidos = manifesto.conduction.allowed_modes;
|
|
208
411
|
if (!permitidos.includes(opcoes.modo)) {
|
|
209
|
-
|
|
210
|
-
|
|
412
|
+
const tag = modos_1.MODOS[opcoes.modo].tag, lista = permitidos.map((p) => modos_1.MODOS[p].tag).join(', ');
|
|
413
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.modoNaoPermitido(tag, lista));
|
|
211
414
|
}
|
|
212
415
|
const assuntoBruto = (0, slug_1.normalizarAssunto)(opcoes.assunto ?? opcoes.nome);
|
|
213
416
|
if (!assuntoBruto) {
|
|
214
|
-
|
|
417
|
+
const nome = opcoes.nome;
|
|
418
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.nomeSemAssunto(nome));
|
|
215
419
|
}
|
|
420
|
+
// RM-059 (T6.0): o pedido e conferido antes de qualquer gravacao, tambem no ensaio.
|
|
421
|
+
const pedido = opcoes.pedido !== undefined ? prepararPedido(opcoes.pedido) : null;
|
|
216
422
|
const abbrev = manifesto.project.abbrev;
|
|
217
423
|
const def = (0, modos_1.definicaoDoModo)(opcoes.modo);
|
|
218
424
|
const variante = opcoes.variante ?? null;
|
|
@@ -224,17 +430,25 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
224
430
|
if (variante) {
|
|
225
431
|
const dv = (0, ciclos_1.definicaoDaVariante)(variante);
|
|
226
432
|
if (dv.exigeBranch && !opcoes.branch) {
|
|
227
|
-
throw new
|
|
433
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.cicloExigeBranch(variante));
|
|
228
434
|
}
|
|
229
|
-
|
|
230
|
-
|
|
435
|
+
const branch = opcoes.branch;
|
|
436
|
+
if (branch) {
|
|
437
|
+
const existe = (0, util_1.exec)('git', ['rev-parse', '--verify', `refs/heads/${branch}`], raiz);
|
|
231
438
|
if (!existe.ok) {
|
|
232
|
-
throw new
|
|
439
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.branchInexistente(branch));
|
|
233
440
|
}
|
|
234
441
|
}
|
|
235
442
|
}
|
|
236
443
|
else if (opcoes.branch) {
|
|
237
|
-
throw new
|
|
444
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.branchSemCiclo);
|
|
445
|
+
}
|
|
446
|
+
// `greenfield`, `merge-branch` e `feature-xl-faseada` exigem worktree isolada: sao os
|
|
447
|
+
// ciclos que escrevem codigo em paralelo com outras threads.
|
|
448
|
+
const exigeWorktree = variante ? (0, ciclos_1.definicaoDaVariante)(variante).exigeWorktree : false;
|
|
449
|
+
// P4 do ensaio da 0.5.0 (D4): o ciclo que exige worktree nao nasce sem ela, e a recusa sai antes de gravar.
|
|
450
|
+
if (exigeWorktree && opcoes.origemDaWorktree === 'sem-worktree') {
|
|
451
|
+
throw new Error(`o ciclo ${variante} exige worktree isolada: crie a thread sem --sem-worktree ou escolha outro ciclo`);
|
|
238
452
|
}
|
|
239
453
|
const reservation = opcoes.reservation;
|
|
240
454
|
const operation = reservation ? (0, creation_operation_store_1.readCreationOperation)(raiz, reservation.operationId, reservation.principal) : null;
|
|
@@ -260,15 +474,15 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
260
474
|
&& fs.readdirSync(dirThread(raiz, reservation.threadId)).some((name) => !/^\.thread\.json\..+\.tmp$/.test(name))) {
|
|
261
475
|
throw new Error('creation.conflict: diretório reservado sem origem confirmada');
|
|
262
476
|
}
|
|
477
|
+
// 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
|
|
478
|
+
// worktree que ele mostra ser a que a criacao usaria.
|
|
263
479
|
const { id, assunto } = reservation
|
|
264
480
|
? { id: reservation.threadId, assunto: reservation.threadId.slice(abbrev.length + 1) }
|
|
265
|
-
:
|
|
266
|
-
? { id: `${abbrev}-${assuntoBruto}`, assunto: assuntoBruto }
|
|
267
|
-
: idDisponivel(raiz, abbrev, assuntoBruto);
|
|
481
|
+
: idDisponivel(raiz, abbrev, assuntoBruto);
|
|
268
482
|
const slug = opcoes.slug ?? (0, slug_1.montarSlug)(abbrev, assunto, blocos[0].slugFases);
|
|
269
483
|
// O override `--slug` do builder tambem passa pela regex canonica.
|
|
270
484
|
if (!(0, slug_1.slugValido)(slug)) {
|
|
271
|
-
throw new
|
|
485
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.slugInvalido(slug, slug_1.REGEX_SLUG.source));
|
|
272
486
|
}
|
|
273
487
|
const thread = {
|
|
274
488
|
...(origin ? { creationOrigin: origin } : {}),
|
|
@@ -291,6 +505,7 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
291
505
|
sessoes: [],
|
|
292
506
|
...(opcoes.exigeRuntimeDiferente === true ? { exigeRuntimeDiferente: true } : {}),
|
|
293
507
|
...(opcoes.doneWhen && opcoes.doneWhen.length > 0 ? { doneWhen: opcoes.doneWhen } : {}),
|
|
508
|
+
...(pedido ? { pedido: pedido.meta } : {}),
|
|
294
509
|
decisoes: [],
|
|
295
510
|
claims: [],
|
|
296
511
|
leases: [],
|
|
@@ -300,13 +515,39 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
300
515
|
};
|
|
301
516
|
if (variante === 'feature-xl-faseada')
|
|
302
517
|
thread.fatias = opcoes.fatias ?? 3;
|
|
303
|
-
|
|
304
|
-
|
|
518
|
+
// 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
|
|
519
|
+
// por flag ou por ciclo segue direto ao git, como era. A pedida so pela chave espera o primeiro commit (D3): sem
|
|
520
|
+
// commit, a thread fica na raiz, como antes. O ciclo que exige worktree vence a chave e a flag na origem: a worktree
|
|
521
|
+
// e dele, e o `--sem-worktree` que a linha da chave sugeriria ele recusa (CHECK, rodada 2).
|
|
522
|
+
const pedeWorktree = opcoes.criarWorktree === true || exigeWorktree;
|
|
523
|
+
const pelaChave = opcoes.criarWorktree === true && opcoes.origemDaWorktree === 'chave';
|
|
524
|
+
const prevista = pedeWorktree && (opcoes.dryRun || pelaChave)
|
|
525
|
+
? worktreePrevista(carregado, id, slug, { branchExistente: opcoes.branch }) : null;
|
|
526
|
+
const worktreePor = !pedeWorktree || (pelaChave && !exigeWorktree && prevista?.falha === 'sem-commit') ? null
|
|
527
|
+
: exigeWorktree ? 'ciclo' : pelaChave ? 'chave' : 'flag';
|
|
528
|
+
if (opcoes.dryRun) {
|
|
529
|
+
// P4 (D8): o ensaio mostra a worktree que a criacao usaria; quando ela recusaria, diz por que, em vez de preve-la.
|
|
530
|
+
if (worktreePor && prevista?.falha) {
|
|
531
|
+
return { thread, gravada: false, worktreePor: null,
|
|
532
|
+
worktreeFalharia: { motivo: prevista.falha, dir: prevista.dir, branch: prevista.branch, por: worktreePor } };
|
|
533
|
+
}
|
|
534
|
+
if (worktreePor && prevista?.commit) {
|
|
535
|
+
thread.worktree = prevista.dir;
|
|
536
|
+
thread.base = { branch: prevista.branch, commit: prevista.commit };
|
|
537
|
+
}
|
|
538
|
+
return { thread, gravada: false, worktreePor };
|
|
539
|
+
}
|
|
540
|
+
// P4 (CHECK): a worktree pedida so pela chave, com a pasta ou a branch ja ocupadas, recusa dizendo de onde veio o
|
|
541
|
+
// pedido e qual e a saida.
|
|
542
|
+
const ocupadaPelaChave = pelaChave && !exigeWorktree && prevista &&
|
|
543
|
+
(prevista.falha === 'pasta-existe' || prevista.falha === 'branch-existe') ? prevista : null;
|
|
544
|
+
if (ocupadaPelaChave) {
|
|
545
|
+
const pasta = ocupadaPelaChave.falha === 'pasta-existe';
|
|
546
|
+
const alvo = pasta ? ocupadaPelaChave.dir : ocupadaPelaChave.branch;
|
|
547
|
+
throw new locale_1.ErroDoCatalogo((m) => m.thread.ocupadaPelaChave(pasta, alvo));
|
|
548
|
+
}
|
|
305
549
|
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) {
|
|
550
|
+
if (worktreePor) {
|
|
310
551
|
worktreeCriada = criarWorktree(carregado, id, slug, {
|
|
311
552
|
branchExistente: opcoes.branch,
|
|
312
553
|
});
|
|
@@ -317,6 +558,10 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
317
558
|
commit: commitDaBranch.ok ? commitDaBranch.stdout.trim() : thread.base.commit,
|
|
318
559
|
};
|
|
319
560
|
}
|
|
561
|
+
// RM-059 (T6.0): o pedido vai ao lado do thread.json, so com permissao do dono, como ele, e antes dele: o
|
|
562
|
+
// thread.json nunca aponta para um pedido que nao foi gravado.
|
|
563
|
+
if (pedido)
|
|
564
|
+
gravarPedido(dirThread(raiz, id), pedido.texto);
|
|
320
565
|
gravarThread(raiz, thread);
|
|
321
566
|
(0, ledger_1.registrar)(dirThread(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.threadCriada, {
|
|
322
567
|
...(origin ? { creationOrigin: origin } : {}),
|
|
@@ -328,20 +573,24 @@ function criarThreadSerializada(carregado, opcoes) {
|
|
|
328
573
|
base: thread.base,
|
|
329
574
|
projeto: manifesto.project.name,
|
|
330
575
|
worktree: thread.worktree,
|
|
576
|
+
// P4 do ensaio da 0.5.0 (D9): quem abriu a thread sem worktree de proposito fica no rastro.
|
|
577
|
+
...(opcoes.origemDaWorktree === 'sem-worktree' ? { semWorktree: true } : {}),
|
|
331
578
|
variante,
|
|
332
579
|
branchDeOrigem: opcoes.branch ?? null,
|
|
333
580
|
maquina: thread.maquina,
|
|
334
581
|
...(thread.roadmap ? { roadmap: thread.roadmap } : {}),
|
|
582
|
+
...(pedido ? { pedido: pedido.meta } : {}),
|
|
335
583
|
});
|
|
336
584
|
if (worktreeCriada) {
|
|
337
585
|
(0, ledger_1.registrar)(dirThread(raiz, id), id, ledger_1.TIPOS_DE_EVENTO.worktreeCriada, {
|
|
338
586
|
dir: worktreeCriada.dir,
|
|
339
587
|
branch: worktreeCriada.branch,
|
|
340
588
|
base: manifesto.worktree.base_branch,
|
|
589
|
+
origem: worktreePor,
|
|
341
590
|
fonte: 'git worktree list --porcelain',
|
|
342
591
|
});
|
|
343
592
|
}
|
|
344
|
-
return { thread, gravada: true };
|
|
593
|
+
return { thread, gravada: true, worktreePor };
|
|
345
594
|
}
|
|
346
595
|
/**
|
|
347
596
|
* O bloco de loop que conduz a fase DESTA thread.
|
|
@@ -373,38 +622,39 @@ function canalDaSessao(s) {
|
|
|
373
622
|
}
|
|
374
623
|
function resumoDaThread(thread, conducao) {
|
|
375
624
|
const def = (0, modos_1.definicaoDoModo)(thread.modo);
|
|
625
|
+
const m = (0, locale_1.msg)().thread, r = m.rotulos;
|
|
626
|
+
// RM-061 (F2a): o rotulo vem do catalogo, na largura do locale; o valor gravado (nome, criterio) sai como esta.
|
|
627
|
+
const campo = (rotulo, valor) => ` ${rotulo.padEnd(m.largura)} ${valor}`;
|
|
376
628
|
const linhas = [];
|
|
377
|
-
linhas.push(
|
|
378
|
-
linhas.push(
|
|
379
|
-
linhas.push(
|
|
380
|
-
linhas.push(
|
|
381
|
-
linhas.push(
|
|
382
|
-
linhas.push(
|
|
383
|
-
linhas.push(
|
|
384
|
-
linhas.push(
|
|
385
|
-
linhas.push(
|
|
629
|
+
linhas.push(campo(r.id, thread.id));
|
|
630
|
+
linhas.push(campo(r.slug, thread.slug));
|
|
631
|
+
linhas.push(campo(r.nome, thread.nome));
|
|
632
|
+
linhas.push(campo(r.modo, m.modo(def.tag, pausasDaThread(thread))));
|
|
633
|
+
linhas.push(campo(r.ciclo, thread.variante ?? m.cicloPadrao));
|
|
634
|
+
linhas.push(campo(r.fase, thread.faseAtual));
|
|
635
|
+
linhas.push(campo(r.status, m.status(thread.status)));
|
|
636
|
+
linhas.push(campo(r.base, `${thread.base.branch} @ ${(0, util_1.shaCurto)(thread.base.commit)}`));
|
|
637
|
+
linhas.push(campo(r.worktree, thread.worktree ?? m.raizDoProjeto));
|
|
386
638
|
// I-36 (T17): quem passa a leitura da conducao ve a linha unica; sem ela o resumo fica como era.
|
|
387
639
|
if (conducao !== undefined)
|
|
388
|
-
linhas.push(
|
|
640
|
+
linhas.push(campo(r.conducao, conducao ? (0, conducao_texto_1.linhaDeConducao)(conducao) : m.ninguemConduz));
|
|
389
641
|
// I-43 (D4, viga a): a exigencia so aparece quando existe, para nao poluir o resumo
|
|
390
642
|
// das threads que nao a declararam.
|
|
391
|
-
if (thread.exigeRuntimeDiferente === true)
|
|
392
|
-
linhas.push(
|
|
393
|
-
}
|
|
643
|
+
if (thread.exigeRuntimeDiferente === true)
|
|
644
|
+
linhas.push(m.validacao);
|
|
394
645
|
// I-43 (D4, viga b): o criterio aparece COM o comando. Mostrar so o criterio seria
|
|
395
646
|
// reproduzir a prosa do envelope numa tela nova.
|
|
396
647
|
if (thread.doneWhen && thread.doneWhen.length > 0) {
|
|
397
|
-
linhas.push(
|
|
648
|
+
linhas.push(m.prontoQuando(thread.doneWhen.length));
|
|
398
649
|
for (const d of thread.doneWhen)
|
|
399
650
|
linhas.push(` ${d.criterio}\n $ ${d.comando}`);
|
|
400
651
|
}
|
|
401
652
|
if (thread.score) {
|
|
402
|
-
linhas.push(
|
|
403
|
-
`(${thread.score.regime}) em ${(0, horario_1.formatarDataHoraRotulada)(thread.score.avaliadoEm)}`);
|
|
653
|
+
linhas.push(campo(r.score, m.score(thread.score.valor, thread.score.avaliadoPor, thread.score.regime, (0, horario_1.formatarDataHoraRotulada)(thread.score.avaliadoEm))));
|
|
404
654
|
}
|
|
405
|
-
linhas.push(
|
|
655
|
+
linhas.push(m.blocosPrevistos);
|
|
406
656
|
for (const b of thread.blocos) {
|
|
407
|
-
const marca = b.pausa ?
|
|
657
|
+
const marca = b.pausa ? m.pausaPrevista(m.pausaSobre(b.pausaSobre)) : m.semPausa;
|
|
408
658
|
linhas.push(` ${b.slugFases.padEnd(6)} ${b.fases.join('-').padEnd(18)} ${marca}`);
|
|
409
659
|
}
|
|
410
660
|
return linhas.join('\n');
|
|
@@ -460,7 +710,7 @@ function tabelaDeThreads(raiz, opcoes = {}) {
|
|
|
460
710
|
function exigirFase(thread, bruto) {
|
|
461
711
|
const fase = bruto.toUpperCase();
|
|
462
712
|
if (!thread.fases.includes(fase)) {
|
|
463
|
-
throw new Error(
|
|
713
|
+
throw new Error((0, locale_1.msg)().phase.faseInvalida(bruto, thread.fases.join(', ')));
|
|
464
714
|
}
|
|
465
715
|
return fase;
|
|
466
716
|
}
|
package/dist/util.js
CHANGED
|
@@ -197,7 +197,14 @@ function lerJsonl(caminho) {
|
|
|
197
197
|
/** Anexa um registro ao armazem JSONL, criando o diretorio que faltar. */
|
|
198
198
|
function anexarJsonl(caminho, valor) {
|
|
199
199
|
fs.mkdirSync(path.dirname(caminho), { recursive: true });
|
|
200
|
-
|
|
200
|
+
// RM-047: O_NOFOLLOW; um armazém versionado como link (claims, board) não leva o append para fora da raiz.
|
|
201
|
+
const fd = fs.openSync(caminho, fs.constants.O_WRONLY | fs.constants.O_APPEND | fs.constants.O_CREAT | fs.constants.O_NOFOLLOW, 0o644);
|
|
202
|
+
try {
|
|
203
|
+
fs.writeFileSync(fd, JSON.stringify(valor) + '\n', 'utf8');
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
fs.closeSync(fd);
|
|
207
|
+
}
|
|
201
208
|
}
|
|
202
209
|
/** Proximo id sequencial de um armazem (`C1`, `C2`, ... / `F1`, `F2`, ...). */
|
|
203
210
|
function proximoIdSequencial(ids, prefixo) {
|