@orkastery/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/adapters/README.md +22 -0
  4. package/adapters/claude-code/.claude-plugin/marketplace.json +15 -0
  5. package/adapters/claude-code/.claude-plugin/plugin.json +31 -0
  6. package/adapters/claude-code/README.md +102 -0
  7. package/adapters/claude-code/agents/ork-check.md +32 -0
  8. package/adapters/claude-code/agents/ork-go.md +32 -0
  9. package/adapters/claude-code/agents/ork-goal.md +33 -0
  10. package/adapters/claude-code/agents/ork-master.md +32 -0
  11. package/adapters/claude-code/agents/ork-plan.md +32 -0
  12. package/adapters/claude-code/agents/ork-ship.md +32 -0
  13. package/adapters/claude-code/commands/check.md +45 -0
  14. package/adapters/claude-code/commands/go.md +46 -0
  15. package/adapters/claude-code/commands/goal.md +54 -0
  16. package/adapters/claude-code/commands/master.md +42 -0
  17. package/adapters/claude-code/commands/ork.md +37 -0
  18. package/adapters/claude-code/commands/plan.md +47 -0
  19. package/adapters/claude-code/commands/ship.md +45 -0
  20. package/adapters/claude-code/hooks/hooks.json +17 -0
  21. package/adapters/claude-code/hooks/ork-guard.js +130 -0
  22. package/adapters/hermes/README.md +45 -0
  23. package/adapters/hermes/bin/ork-abrir-thread.sh +25 -0
  24. package/adapters/hermes/hermes.plugin.json +21 -0
  25. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +116 -0
  26. package/adapters/openclaw/README.md +63 -0
  27. package/adapters/openclaw/bin/ork-abrir-thread.sh +24 -0
  28. package/adapters/openclaw/openclaw.plugin.json +138 -0
  29. package/dist/adapters/claude-bg.js +308 -0
  30. package/dist/auditoria.js +848 -0
  31. package/dist/auditrun.js +976 -0
  32. package/dist/board.js +314 -0
  33. package/dist/canarios.js +271 -0
  34. package/dist/catalogo.js +124 -0
  35. package/dist/ciclos.js +156 -0
  36. package/dist/claims.js +226 -0
  37. package/dist/divida.js +374 -0
  38. package/dist/doctor.js +246 -0
  39. package/dist/evalrunner.js +458 -0
  40. package/dist/fix.js +450 -0
  41. package/dist/gates.js +92 -0
  42. package/dist/handoff.js +521 -0
  43. package/dist/hosts.js +331 -0
  44. package/dist/index.js +1910 -0
  45. package/dist/init.js +231 -0
  46. package/dist/leases.js +508 -0
  47. package/dist/ledger.js +138 -0
  48. package/dist/manifest.js +255 -0
  49. package/dist/master.js +453 -0
  50. package/dist/memoria.js +773 -0
  51. package/dist/modos.js +220 -0
  52. package/dist/orkmind.js +487 -0
  53. package/dist/orquestracao.js +559 -0
  54. package/dist/phase.js +572 -0
  55. package/dist/policies.js +176 -0
  56. package/dist/prompts.js +406 -0
  57. package/dist/ratelimit.js +179 -0
  58. package/dist/recall.js +252 -0
  59. package/dist/retry.js +917 -0
  60. package/dist/sandbox.js +94 -0
  61. package/dist/sessoes.js +104 -0
  62. package/dist/ship.js +551 -0
  63. package/dist/slug.js +100 -0
  64. package/dist/superficie.js +1347 -0
  65. package/dist/thread.js +333 -0
  66. package/dist/tokens.js +228 -0
  67. package/dist/types.js +20 -0
  68. package/dist/util.js +156 -0
  69. package/dist/verify.js +262 -0
  70. package/dist/worktree.js +576 -0
  71. package/dist/yaml.js +112 -0
  72. package/eval/README.md +85 -0
  73. package/eval/casos/check-quality.json +103 -0
  74. package/eval/casos/code-reviewer.json +102 -0
  75. package/eval/casos/decision-triage.json +103 -0
  76. package/eval/casos/go-implementation.json +103 -0
  77. package/eval/casos/goal-definition.json +103 -0
  78. package/eval/casos/master-metrics.json +103 -0
  79. package/eval/casos/narrative-guardian.json +163 -0
  80. package/eval/casos/orkastery-bootstrap.json +102 -0
  81. package/eval/casos/plan-specification.json +102 -0
  82. package/eval/casos/roadmap-keeper.json +103 -0
  83. package/eval/casos/scope-check-capability-map.json +83 -0
  84. package/eval/casos/security-auditor.json +102 -0
  85. package/eval/casos/ship-release.json +122 -0
  86. package/eval/casos/test-engineer.json +122 -0
  87. package/eval/casos/thread-state.json +82 -0
  88. package/eval/casos/thread-tracing.json +83 -0
  89. package/eval/casos/web-performance-auditor.json +102 -0
  90. package/eval/fixtures/b0-slug-e-modos/caso.json +56 -0
  91. package/eval/fixtures/b2-master-log/caso.json +91 -0
  92. package/eval/fixtures/fx-concurrency/caso.json +15 -0
  93. package/eval/fixtures/fx-hallucination/caso.json +12 -0
  94. package/eval/fixtures/fx-happy/caso.json +16 -0
  95. package/eval/fixtures/fx-schema-drift/caso.json +15 -0
  96. package/eval/fixtures/fx-stale-base/caso.json +12 -0
  97. package/eval/fixtures/fx-wiki-destroy/caso.json +16 -0
  98. package/eval/fixtures/superficie-de-rede/README.md +22 -0
  99. package/eval/fixtures/superficie-de-rede/api-express.js +30 -0
  100. package/eval/fixtures/superficie-de-rede/api_fastapi.py +17 -0
  101. package/eval/fixtures/superficie-de-rede/api_gin.go +18 -0
  102. package/package.json +56 -0
  103. package/references/README.md +25 -0
  104. package/references/code-review-axes.md +82 -0
  105. package/references/definition-of-done.md +74 -0
  106. package/references/performance-checklist.md +53 -0
  107. package/references/security-checklist.md +101 -0
  108. package/references/testing-patterns.md +51 -0
  109. package/skills/README.md +43 -0
  110. package/skills/core/orkastery-bootstrap/SKILL.md +89 -0
  111. package/skills/core/thread-state/SKILL.md +86 -0
  112. package/skills/governance/decision-triage/SKILL.md +65 -0
  113. package/skills/governance/narrative-guardian/SKILL.md +66 -0
  114. package/skills/governance/roadmap-keeper/SKILL.md +60 -0
  115. package/skills/governance/scope-check-capability-map/SKILL.md +61 -0
  116. package/skills/observability/thread-tracing/SKILL.md +63 -0
  117. package/skills/phases/check-quality/SKILL.md +87 -0
  118. package/skills/phases/go-implementation/SKILL.md +70 -0
  119. package/skills/phases/goal-definition/SKILL.md +69 -0
  120. package/skills/phases/master-metrics/SKILL.md +65 -0
  121. package/skills/phases/plan-specification/SKILL.md +67 -0
  122. package/skills/phases/ship-release/SKILL.md +68 -0
  123. package/skills/reviewers/code-reviewer/SKILL.md +61 -0
  124. package/skills/reviewers/security-auditor/SKILL.md +68 -0
  125. package/skills/reviewers/test-engineer/SKILL.md +66 -0
  126. package/skills/reviewers/web-performance-auditor/SKILL.md +63 -0
package/dist/index.js ADDED
@@ -0,0 +1,1910 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * `ork`: nucleo CLI deterministico do Orkastery (bloco B0).
5
+ *
6
+ * Sem LLM embutido: o `ork` monta prompt, despacha pelo runtime adapter, verifica no
7
+ * mundo real e registra no ledger. Quem escreve codigo e a orquestra (Camada 3);
8
+ * quem decide e o humano; o meio e conduzido por software.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.parseArgs = parseArgs;
12
+ exports.main = main;
13
+ const auditoria_1 = require("./auditoria");
14
+ const auditrun_1 = require("./auditrun");
15
+ const superficie_1 = require("./superficie");
16
+ const board_1 = require("./board");
17
+ const orquestracao_1 = require("./orquestracao");
18
+ const divida_1 = require("./divida");
19
+ const ciclos_1 = require("./ciclos");
20
+ const claims_1 = require("./claims");
21
+ const catalogo_1 = require("./catalogo");
22
+ const doctor_1 = require("./doctor");
23
+ const evalrunner_1 = require("./evalrunner");
24
+ const gates_1 = require("./gates");
25
+ const handoff_1 = require("./handoff");
26
+ const hosts_1 = require("./hosts");
27
+ const init_1 = require("./init");
28
+ const leases_1 = require("./leases");
29
+ const master_1 = require("./master");
30
+ const manifest_1 = require("./manifest");
31
+ const memoria_1 = require("./memoria");
32
+ const recall_1 = require("./recall");
33
+ const fix_1 = require("./fix");
34
+ const ratelimit_1 = require("./ratelimit");
35
+ const retry_1 = require("./retry");
36
+ const modos_1 = require("./modos");
37
+ const phase_1 = require("./phase");
38
+ const prompts_1 = require("./prompts");
39
+ const sessoes_1 = require("./sessoes");
40
+ const util_1 = require("./util");
41
+ const ship_1 = require("./ship");
42
+ const thread_1 = require("./thread");
43
+ const tokens_1 = require("./tokens");
44
+ const types_1 = require("./types");
45
+ const verify_1 = require("./verify");
46
+ const worktree_1 = require("./worktree");
47
+ /** A versao publicada em `@orkastery/cli`. Anda junto com o `version` do package.json. */
48
+ const VERSAO = '0.2.0';
49
+ /** Parse simples de argumentos: `--chave valor`, `--chave=valor` e flags booleanas. */
50
+ function parseArgs(argv) {
51
+ const posicionais = [];
52
+ const opcoes = {};
53
+ for (let i = 0; i < argv.length; i++) {
54
+ const a = argv[i];
55
+ if (a.startsWith('--')) {
56
+ const igual = a.indexOf('=');
57
+ if (igual > 0) {
58
+ opcoes[a.slice(2, igual)] = a.slice(igual + 1);
59
+ }
60
+ else {
61
+ const proximo = argv[i + 1];
62
+ if (proximo !== undefined && !proximo.startsWith('--')) {
63
+ opcoes[a.slice(2)] = proximo;
64
+ i++;
65
+ }
66
+ else {
67
+ opcoes[a.slice(2)] = true;
68
+ }
69
+ }
70
+ }
71
+ else {
72
+ posicionais.push(a);
73
+ }
74
+ }
75
+ return { posicionais, opcoes };
76
+ }
77
+ function texto(v) {
78
+ return typeof v === 'string' ? v : undefined;
79
+ }
80
+ const AJUDA = `ork ${VERSAO}, nucleo de orquestracao do Orkastery
81
+
82
+ Uso: ork <comando> [argumentos]
83
+
84
+ doctor O que vale nesta maquina agora (sai != 0 se bloqueado)
85
+ init [--force] [--name N] [--abbrev A] Gera o orkastery.yaml do repositorio
86
+ modos Tabela dos 5 modos de conducao por #TAG
87
+
88
+ thread new <nome> --modo <MODO> Cria a thread, o slug de 3 partes e o ledger
89
+ [--slug S] [--assunto A] [--worktree auto|DIR] [--dry-run]
90
+ thread list Threads do projeto
91
+ thread status <thread-id> Estado da thread, cruzado com o runtime
92
+
93
+ phase run <thread-id> <FASE> --prompt "<texto>"
94
+ [--model M] [--effort E] [--dry-run] Despacha a fase como background agent
95
+ (so --model assume --effort high; o par
96
+ efetivo vai ao ledger como fato verificavel)
97
+ phase list <thread-id> Historico do ledger da thread
98
+ (mostra o modelo/esforco reais de cada fase)
99
+
100
+ sessions [--all] Sessoes vivas do runtime, cruzadas com as threads
101
+ sessions logs <sessao> [--linhas N] Logs de uma sessao
102
+ sessions stop <sessao> Para uma sessao
103
+ sessions attach <sessao> Imprime o comando de attach (precisa de TTY)
104
+
105
+ claims add <thread-id> <arquivo> --claim "<alegacao>" [--verificar "<comando>"] [--fase F]
106
+ Registra alegacao verificavel da thread
107
+ claims list <thread-id> Claims da thread e o estado de cada uma
108
+ claims verificar <thread-id> <claim-id> --comando "<comando>"
109
+ Anexa o comando que comprova uma claim ja feita
110
+ claims retirar <thread-id> <claim-id> --motivo "<motivo>"
111
+ Retira a alegacao (o historico fica no claims.jsonl)
112
+ verify <thread-id> [--baseline] Reexecuta claims e verify do manifesto no HEAD real
113
+ [--so-claims] --baseline grava o estado do mundo antes do GO
114
+
115
+ gate next <thread-id> [--proximo FASE] Gate de tokens: mesma sessao ou nova sessao
116
+ [--ocupacao 0..1] [--fonte F] [--transcript ARQ] [--janela N] [--refazer]
117
+ gate approve <thread-id> <sobre> --por Q Registra autorizacao humana no ledger
118
+
119
+ retry policy [--motivo M] [--json] Politica de retry por motivo tipado de gate
120
+ retry plan <thread-id> [--motivo M] O que o ork faria pelo ultimo gate reprovado
121
+ [--fase F] [--json] (calcula, nao executa, nao gasta tentativa)
122
+ retry run <thread-id> [--reverify] Executa a acao tipada do ultimo gate reprovado
123
+ [--por Q] [--dry-run] (--por autoriza quando o bloco do modo pausa)
124
+ retry list [--json] Fila DURAVEL de rate limit do projeto
125
+ retry resume [--id R1] [--agora ISO] Retoma a fase morta por rate limit na janela seguinte
126
+ [--ocupacao 0..1] [--forcar] [--dry-run] (playbooks: mesma-sessao, nova-sessao, escalada)
127
+ retry cancel <id> --motivo M Tira um pedido da fila, com motivo registrado
128
+ retry parse --stderr "<texto>" Le o horario de reset do stderr do adapter
129
+
130
+ fix open <thread-id> [--so-claims] GO-FIX: deriva a spec exata do CHECK reprovado
131
+ [--reverify] [--json] (uma correcao por motivo tipado, tipo A ou B)
132
+ fix list <thread-id> [--rodada N] Correcoes da rodada e o veredito de cada uma
133
+ fix reverify <thread-id> [--rodada N] CHECK-REVERIFY com veredito POR correcao
134
+ [--parcial] [--json] (--parcial e RECUSADO se houver tipo B)
135
+
136
+ handoff export <thread-id> Handoff triado CRITICO/IMPORTANTE/RESUMIVEL
137
+ [--proxima-fase FASE] [--slug S]
138
+ handoff recall <thread-id> <ponteiro> Resolve um ponteiro path#ancora de volta ao conteudo
139
+
140
+ recall <thread-id> --fase FASE Recuperacao TARDIA: resolve so os ponteiros do
141
+ [--id ptr-N] [--todos] [--forcar] momento (retrieve_when), nunca a janela inteira
142
+ [--sem-conteudo] [--json] (orkmind por tag, files por path#ancora)
143
+
144
+ memory status [--json] Regime efetivo (files|orkmind), tenant e degradacao
145
+ memory sync [<thread-id>] [--json] Publica decisoes, policies, handoff, licao e roadmap
146
+ memory search --tags '<json>' [--colecao C] Busca deterministica por tag (mandatory sempre volta)
147
+ [--limite N] [--json]
148
+
149
+ ship <thread-id> --para <branch> Merge --no-ff serializado por lease e push PROVADO
150
+ [--de <branch>] [--remoto origin] [--autorizar-push <quem>] [--sem-push] [--dry-run]
151
+
152
+ board [--all] Visao unica das threads (todos os perfis com --all)
153
+ board plan Escalonador: quem avanca agora, quem espera e por que
154
+
155
+ orquestracao status [--all] [--json] Monitor PROATIVO de pausas e impedimentos: quem esta
156
+ [--atencao N] [--so-paradas] parado, esperando o que, ha quanto tempo e o que
157
+ [--sem-runtime] [--exigir-limpo] destrava (alias curto: ork monitor)
158
+
159
+ worktree ensure <thread-id> Garante a worktree da thread (base resolvida pelo ork)
160
+ worktree sync <thread-id> [--dry-run] Rebasa a branch da thread quando a base avancou
161
+ worktree audit <thread-id> Confere a worktree no proprio git (sai != 0 se divergir)
162
+ worktree release <thread-id> [--forcar] Remove a worktree e limpa o registro
163
+
164
+ lease list Leases, familias e as filas (merge e colisao de regiao)
165
+ lease acquire <nome> --thread T --motivo M Toma um lease tipado (entra na fila se colidir)
166
+ lease release <nome> [--thread T] [--forcar]
167
+
168
+ master <thread-id> --score 0-5 --justificativa "<texto>"
169
+ [--classe C[,C]] [--resumo R] [--por Q] [--refazer]
170
+ Fecha a thread: POSTMORTEM + MASTER log + score
171
+ master --batch [--todas] Fila de review em bloco (threads entregues sem score)
172
+ master classes As classes de falha fixas do POSTMORTEM
173
+
174
+ ciclos Variantes de ciclo de "ork thread new --ciclo"
175
+ modos --do-pedido "<texto>" [--json] Le a #TAG do pedido do builder (usado pelos adaptadores)
176
+
177
+ prompt list Templates de prompt (embutidos e os do projeto)
178
+ prompt lint [--template ID] Reprova template quebrado antes de ele virar despacho
179
+ prompt render <thread-id> --fase F Mostra o prompt exato, com o sha256 que vai ao ledger
180
+ [--pedido "<texto>"] [--template ID]
181
+ prompt render --exemplo --fase F --modo M Renderiza sem thread nenhuma, para revisar o texto
182
+
183
+ adapter list Adaptadores de host (Camada 1) e o destino de cada um
184
+ adapter show <host> Os 3 pitfalls de instalacao do host
185
+ adapter install <host> [--dir D] Instala o adaptador (hermes|openclaw|claude-code)
186
+ [--dry-run] [--force]
187
+
188
+ eval [--skill S] [--canario C] Canarios de comportamento + corpus das skills finas
189
+ [--so-canarios] [--so-skills] [--json] (sai != 0 em qualquer falha)
190
+
191
+ audit packs [--estagio E] [--pack P] Os 7 packs, o estagio que os ativa e a postura
192
+ audit run <pack> [--profile P] Monta o prompt do pack e despacha pelo runtime adapter
193
+ [--since Nd] [--tudo] [--effort E] [--model M] [--agora "<quem>"] [--forcar] [--dry-run]
194
+ audit list Rodadas de auditoria do projeto
195
+ audit show <rodada> [--ledger] Contexto, achados e propostas de uma rodada
196
+ audit prompt <pack> [--since Nd] O prompt exato do pack, com o sha256 que vai ao ledger
197
+ audit lint Reprova template de auditoria quebrado (auditors/)
198
+ audit ingest <rodada> --arquivo J Registra em lote os achados que o auditor escreveu
199
+ audit finding add <rodada> --regra R Registra um achado com evidencia, claim e proposta
200
+ --titulo T --arquivo caminho:linha --impacto I --fix F --estimativa E
201
+ [--severidade critico|maior|menor] [--irreversivel "<passo>"] [--verificar "<comando>"]
202
+ audit verify <rodada> Reexecuta as claims dos achados (auditor sem self-report)
203
+ audit report <rodada> [--publicar] Relatorio com o bloco OBRIGATORIO de propostas
204
+ audit divida [--pack P] [--todos] Board de divida: propostas abertas e recorrencia
205
+ audit surface [<dir>] [--regra SPn] Varredura DETERMINISTICA da superficie de ataque de rede
206
+ [--limite N] [--json] (SP8..SP12; sai != 0 quando ha achado)
207
+ audit surface --registrar <rodada> Grava os achados da varredura no board da rodada
208
+ audit finding estado <id> <estado> Carimba o achado (aberto|adiado|resolvido|descartado)
209
+
210
+ thread new <nome> --from-finding <ID> Abre a thread a partir de um achado de auditoria
211
+ [--modo M] [--worktree auto] [--dry-run] (evidencia, claim e proposta viajam junto)
212
+
213
+ Regimes de memoria: files (fallback honesto) e orkmind (bloco B6, base propria por tenant
214
+ declarada em memory.database_url_env pelo NOME da variavel de ambiente, sem fallback).
215
+ Colecoes gravadas no OrkMind: decision, handoff, rule, learning, roadmap (source=agent,
216
+ nunca mandatory: regra critica so nasce de humano autenticado).
217
+
218
+ Retry tipado (bloco B3): reexecutar, corrigir-dirigido, sincronizar-worktree,
219
+ escalar-esforco, esperar-janela, escalar-humano, sem-retry. Violacao de custo
220
+ (cost.violation) NUNCA recebe retry automatico. O limite de escalacao do manifesto
221
+ (retry.max_tentativas) pausa QUALQUER modo, inclusive #Auto.
222
+
223
+ Monitor de orquestracao (ork orquestracao status / ork monitor): duas naturezas de parada.
224
+ pausa-humana e a parada PREVISTA pelo modo (o bloco fechou e espera veredito, com o
225
+ pausaSobre do bloco dizendo o que o humano decide); impedimento e a nao prevista
226
+ (lease.busy, runtime.rate-limited, concurrency.limite e os demais gates tipados). Tudo e
227
+ DERIVADO de thread.json, ledger.jsonl e das filas em disco: o monitor le, nunca grava.
228
+ --exigir-limpo sai != 0 enquanto houver thread parada, para virar watchdog do orquestrador.
229
+
230
+ Fases: GOAL PLAN GO CHECK SHIP MASTER. Modos: #Look #Default #Ork #Maestro #Auto.
231
+ Familias de lease: main-tree, worktree-write:<thread>, path:<glob>, board:<card>, service:<porta>.
232
+ Ciclos: greenfield, merge-branch, goal-plan, gap, feature-xl-faseada.
233
+ Fontes de medida do gate de tokens: runtime_reported, estimated, informada, unavailable.
234
+ Hosts de Camada 1: claude-code, hermes, openclaw. Canarios: fx-happy, fx-hallucination,
235
+ fx-stale-base, fx-wiki-destroy, fx-schema-drift, fx-concurrency.
236
+ Packs de auditoria: clean-code, reuse, architecture, data-model, ux, security-privacy, process.
237
+ Superficie de ataque de rede (SP8..SP12, varredura deterministica): rota sem auth, endpoint de
238
+ administracao exposto, rota sem rate limit, CORS permissivo, rota sem esquema de payload.
239
+ Estagios do produto: nascente, crescendo, maduro (hardening gradual, visao secao 5.2).
240
+ `;
241
+ function comandoThread(args) {
242
+ const sub = args.posicionais[1];
243
+ if (sub === 'new') {
244
+ const carregado = (0, manifest_1.exigirManifesto)();
245
+ // `--from-finding <id>`: o achado de auditoria vira thread sem retrabalho (bloco B5).
246
+ // O nome posicional passa a ser opcional, porque o titulo do achado ja serve de nome.
247
+ const doAchado = texto(args.opcoes['from-finding']) ?? texto(args.opcoes['do-achado']);
248
+ if (doAchado) {
249
+ const brutoModoAchado = texto(args.opcoes.modo) ?? texto(args.opcoes.mode);
250
+ const modoAchado = brutoModoAchado ? (0, modos_1.parseModo)(brutoModoAchado) : undefined;
251
+ if (brutoModoAchado && !modoAchado) {
252
+ console.error(`modo invalido: "${brutoModoAchado}". Use um de: ${Object.values(modos_1.MODOS).map((m) => m.tag).join(', ')}`);
253
+ return 2;
254
+ }
255
+ const brutoWorktreeAchado = args.opcoes.worktree;
256
+ const criarWorktreeAchado = brutoWorktreeAchado === true || brutoWorktreeAchado === 'auto';
257
+ const r = (0, auditrun_1.abrirThreadDoAchado)(carregado, doAchado, {
258
+ nome: args.posicionais[2],
259
+ modo: modoAchado ?? undefined,
260
+ slug: texto(args.opcoes.slug),
261
+ assunto: texto(args.opcoes.assunto),
262
+ criarWorktree: criarWorktreeAchado,
263
+ worktree: criarWorktreeAchado ? null : (texto(brutoWorktreeAchado) ?? null),
264
+ dryRun: args.opcoes['dry-run'] === true,
265
+ });
266
+ if (!r.ok) {
267
+ console.error(`Thread a partir do achado ${r.achado.id} RECUSADA.`);
268
+ console.error(` ${auditoria_1.DESCRICAO_DO_MOTIVO_DE_AUDITORIA[r.motivo ?? 'claims.failed']}`);
269
+ console.error(` motivo tipado: ${r.motivo}`);
270
+ console.error(` detalhe: ${r.detalhe}`);
271
+ console.error(` correcao: ${r.correcao}`);
272
+ return 1;
273
+ }
274
+ const gravadaDoAchado = args.opcoes['dry-run'] !== true;
275
+ console.log(gravadaDoAchado
276
+ ? `Thread criada a partir do achado ${r.achado.id}.`
277
+ : 'Simulacao (--dry-run), nada foi gravado.');
278
+ console.log((0, divida_1.textoDoAchado)(r.achado));
279
+ console.log('');
280
+ if (r.thread) {
281
+ console.log((0, thread_1.resumoDaThread)(r.thread));
282
+ console.log('');
283
+ console.log(` slug em 3 partes: ${(0, phase_1.descreverSlug)(r.thread.slug)}`);
284
+ }
285
+ if (r.motivo === 'claims.unverifiable') {
286
+ console.log('');
287
+ console.log(` ${r.detalhe}`);
288
+ }
289
+ // Bloco B6: a origem da thread vai para a colecao `roadmap` (achado -> proposta ->
290
+ // thread -> entrega e rastreavel sem abrir o board).
291
+ if (r.thread && gravadaDoAchado) {
292
+ relatarPublicacao((0, memoria_1.publicar)(carregado, r.thread.id, {
293
+ tipo: 'achado',
294
+ referencia: r.achado.id,
295
+ detalhe: `Achado ${r.achado.id} (${r.achado.pack}/${r.achado.regra}): ${r.achado.titulo}. ` +
296
+ `Fix proposto: ${r.achado.proposta.fix}`,
297
+ }));
298
+ }
299
+ if (gravadaDoAchado && r.thread) {
300
+ console.log(` origem do GOAL: .orkastery/threads/${r.thread.id}/achado.json`);
301
+ console.log('');
302
+ console.log('Pedido de GOAL ja montado a partir do achado:');
303
+ console.log('');
304
+ console.log(r.pedido);
305
+ console.log('');
306
+ console.log('Proximo passo:');
307
+ console.log(` ork phase run ${r.thread.id} GOAL --prompt "$(cat .orkastery/threads/${r.thread.id}/pedido-goal.md)"`);
308
+ }
309
+ return 0;
310
+ }
311
+ const nome = args.posicionais[2];
312
+ if (!nome) {
313
+ console.error('uso: ork thread new <nome> --modo <MODO>');
314
+ return 2;
315
+ }
316
+ const brutoModo = texto(args.opcoes.modo) ?? texto(args.opcoes.mode);
317
+ const modo = brutoModo
318
+ ? (0, modos_1.parseModo)(brutoModo)
319
+ : carregado.manifesto.conduction.default_mode;
320
+ if (!modo) {
321
+ console.error(`modo invalido: "${brutoModo}". Use um de: ${Object.values(modos_1.MODOS).map((m) => m.tag).join(', ')}`);
322
+ return 2;
323
+ }
324
+ const dryRun = args.opcoes['dry-run'] === true;
325
+ const brutoWorktree = args.opcoes.worktree;
326
+ // `--worktree auto` (ou `--worktree` sozinho) cria a worktree isolada da thread;
327
+ // um caminho reusa um diretorio que ja existe.
328
+ const criarWorktree = brutoWorktree === true || brutoWorktree === 'auto';
329
+ const brutoCiclo = texto(args.opcoes.ciclo) ?? texto(args.opcoes.variante);
330
+ const variante = brutoCiclo ? (0, ciclos_1.parseVariante)(brutoCiclo) : null;
331
+ if (brutoCiclo && !variante) {
332
+ console.error(`variante de ciclo invalida: "${brutoCiclo}". Use uma de: ${Object.keys(ciclos_1.VARIANTES).join(', ')}`);
333
+ return 2;
334
+ }
335
+ const brutoFatias = texto(args.opcoes.fatias);
336
+ const { thread, gravada } = (0, thread_1.novaThread)(carregado, {
337
+ nome,
338
+ modo,
339
+ slug: texto(args.opcoes.slug),
340
+ assunto: texto(args.opcoes.assunto),
341
+ worktree: criarWorktree ? null : (texto(brutoWorktree) ?? null),
342
+ criarWorktree,
343
+ dryRun,
344
+ variante,
345
+ branch: texto(args.opcoes.branch),
346
+ fatias: brutoFatias !== undefined ? Number(brutoFatias) : undefined,
347
+ });
348
+ console.log(gravada ? 'Thread criada.' : 'Simulacao (--dry-run), nada foi gravado.');
349
+ console.log((0, thread_1.resumoDaThread)(thread));
350
+ console.log('');
351
+ console.log(` slug em 3 partes: ${(0, phase_1.descreverSlug)(thread.slug)}`);
352
+ if (gravada) {
353
+ console.log(` estado: .orkastery/threads/${thread.id}/thread.json`);
354
+ // Bloco B6: a origem da thread e as policies do projeto vao para a memoria
355
+ // semantica quando ela esta ligada. Em regime files nada muda nesta saida.
356
+ relatarPublicacao((0, memoria_1.publicar)(carregado, thread.id));
357
+ console.log('');
358
+ console.log(`Proximo passo: ork phase run ${thread.id} ${thread.faseAtual} --prompt "<pedido>"`);
359
+ }
360
+ return 0;
361
+ }
362
+ if (sub === 'list' || sub === undefined) {
363
+ const carregado = (0, manifest_1.exigirManifesto)();
364
+ console.log((0, thread_1.tabelaDeThreads)(carregado.raiz));
365
+ return 0;
366
+ }
367
+ if (sub === 'status') {
368
+ const carregado = (0, manifest_1.exigirManifesto)();
369
+ const id = args.posicionais[2];
370
+ if (!id) {
371
+ console.error('uso: ork thread status <thread-id>');
372
+ return 2;
373
+ }
374
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
375
+ console.log(`Thread ${thread.id}`);
376
+ console.log((0, thread_1.resumoDaThread)(thread));
377
+ console.log('');
378
+ if (thread.sessoes.length === 0) {
379
+ console.log(' nenhuma sessao despachada ainda');
380
+ }
381
+ else {
382
+ console.log(' sessoes despachadas (estado real conferido em `ork sessions`)');
383
+ for (const s of thread.sessoes) {
384
+ console.log(` ${s.slug.padEnd(24)} ${s.fase.padEnd(6)} ${s.sessionId.slice(0, 8)} ` +
385
+ `verificada no runtime: ${s.verificada ? 'sim' : 'nao'}`);
386
+ }
387
+ }
388
+ console.log('');
389
+ console.log(` pausas humanas do modo: ${(0, modos_1.pausasDoModo)(thread.modo)}`);
390
+ return 0;
391
+ }
392
+ console.error(`subcomando desconhecido: thread ${sub}`);
393
+ return 2;
394
+ }
395
+ function comandoPhase(args) {
396
+ const sub = args.posicionais[1];
397
+ const carregado = (0, manifest_1.exigirManifesto)();
398
+ if (sub === 'run') {
399
+ const id = args.posicionais[2];
400
+ const faseBruta = args.posicionais[3];
401
+ const prompt = texto(args.opcoes.prompt);
402
+ if (!id || !faseBruta || !prompt) {
403
+ console.error('uso: ork phase run <thread-id> <FASE> --prompt "<texto>"');
404
+ return 2;
405
+ }
406
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
407
+ const fase = (0, thread_1.exigirFase)(thread, faseBruta);
408
+ const r = (0, phase_1.rodarFase)(carregado, id, {
409
+ fase,
410
+ prompt,
411
+ model: texto(args.opcoes.model),
412
+ effort: texto(args.opcoes.effort),
413
+ dryRun: args.opcoes['dry-run'] === true,
414
+ });
415
+ if (r.dryRun) {
416
+ console.log('Simulacao (--dry-run), nada foi despachado.');
417
+ console.log(` slug da sessao : ${r.slug}`);
418
+ console.log(` prompt : ${r.promptPath}`);
419
+ console.log(` sha256 : ${r.promptSha256}`);
420
+ console.log(` pausa ao fim : ${r.pausaAoFim ? 'sim' : 'nao'}`);
421
+ console.log(` modelo/esforco : ${r.model}/${r.effort}`);
422
+ console.log(` comando : claude --bg "<prompt>" --name ${r.slug} ...`);
423
+ return 0;
424
+ }
425
+ if (r.bloqueado) {
426
+ console.error(`Despacho BLOQUEADO pelo gate tipado: ${r.motivo}`);
427
+ for (const v of r.violacoes) {
428
+ console.error(` [${v.severidade}] policy ${v.policy}: ${v.detalhe}`);
429
+ console.error(` correcao: ${v.correcao}`);
430
+ }
431
+ console.error(` o prompt nao foi gravado em disco; evento gate_blocked no ledger de ${id}`);
432
+ return 1;
433
+ }
434
+ if (!r.sessionId) {
435
+ console.error(`Despacho falhou: ${r.erro}`);
436
+ console.error(` evento registrado no ledger de ${id}`);
437
+ return 1;
438
+ }
439
+ console.log(`Fase ${fase} despachada como background agent.`);
440
+ console.log(` sessionId : ${r.sessionId}`);
441
+ console.log(` slug da sessao : ${r.slug} (${(0, phase_1.descreverSlug)(r.slug)})`);
442
+ console.log(` prompt : ${r.promptPath}`);
443
+ console.log(` sha256 : ${r.promptSha256}`);
444
+ console.log(` modelo/esforco : ${r.model}/${r.effort} (gravado no ledger, veja \`ork phase list\`)`);
445
+ console.log(` verificada no runtime: ${r.verificada ? 'sim' : 'NAO (confira `ork sessions`)'}`);
446
+ console.log(` pausa ao fim do bloco: ${r.pausaAoFim ? 'sim' : 'nao (decisao autonoma no ledger)'}`);
447
+ console.log('');
448
+ console.log(`Acompanhe: claude attach ${r.sessionId} | ork phase list ${id}`);
449
+ return r.verificada ? 0 : 1;
450
+ }
451
+ if (sub === 'list') {
452
+ const id = args.posicionais[2];
453
+ if (!id) {
454
+ console.error('uso: ork phase list <thread-id>');
455
+ return 2;
456
+ }
457
+ console.log((0, phase_1.tabelaDoLedger)(carregado.raiz, id));
458
+ return 0;
459
+ }
460
+ console.error(`subcomando desconhecido: phase ${sub}`);
461
+ return 2;
462
+ }
463
+ function comandoSessions(args) {
464
+ const sub = args.posicionais[1];
465
+ const carregado = (0, manifest_1.carregarManifesto)();
466
+ const raiz = carregado?.raiz ?? process.cwd();
467
+ if (sub === undefined || sub === 'list') {
468
+ console.log((0, sessoes_1.tabelaDeSessoes)(raiz, args.opcoes.all === true));
469
+ return 0;
470
+ }
471
+ const chave = args.posicionais[2];
472
+ if (!chave) {
473
+ console.error(`uso: ork sessions ${sub} <sessao>`);
474
+ return 2;
475
+ }
476
+ if (sub === 'logs') {
477
+ const n = Number(texto(args.opcoes.linhas) ?? '60');
478
+ const r = (0, sessoes_1.logsDaSessao)(chave, Number.isFinite(n) ? n : 60);
479
+ console.log(r.texto);
480
+ return r.codigo;
481
+ }
482
+ if (sub === 'stop') {
483
+ const r = (0, sessoes_1.pararSessao)(chave);
484
+ console.log(r.texto);
485
+ return r.codigo;
486
+ }
487
+ if (sub === 'attach') {
488
+ const r = (0, sessoes_1.comandoDeAttach)(chave);
489
+ console.log(r.texto);
490
+ return r.codigo;
491
+ }
492
+ console.error(`subcomando desconhecido: sessions ${sub}`);
493
+ return 2;
494
+ }
495
+ function comandoClaims(args) {
496
+ const carregado = (0, manifest_1.exigirManifesto)();
497
+ const sub = args.posicionais[1];
498
+ if (sub === 'add') {
499
+ const id = args.posicionais[2];
500
+ const arquivo = args.posicionais[3];
501
+ const alegacao = texto(args.opcoes.claim) ?? texto(args.opcoes.alegacao);
502
+ if (!id || !arquivo || !alegacao) {
503
+ console.error('uso: ork claims add <thread-id> <arquivo> --claim "<alegacao>" [--verificar "<comando>"]');
504
+ return 2;
505
+ }
506
+ const comando = texto(args.opcoes.verificar) ?? texto(args.opcoes.verify);
507
+ const faseBruta = texto(args.opcoes.fase);
508
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
509
+ const claim = (0, claims_1.adicionarClaim)(carregado.raiz, id, {
510
+ arquivo,
511
+ alegacao,
512
+ verificar: comando ? [comando] : [],
513
+ fase: faseBruta ? (0, thread_1.exigirFase)(thread, faseBruta) : undefined,
514
+ });
515
+ console.log(`Claim ${claim.id} registrada na thread ${id}.`);
516
+ console.log(` arquivo ${claim.arquivo}`);
517
+ console.log(` alegacao ${claim.alegacao}`);
518
+ console.log(` negativa ${claim.negativa ? 'sim (exige comando de verificacao)' : 'nao'}`);
519
+ console.log(` verificar ${claim.verificar.join(' && ') || '(nenhum comando declarado)'}`);
520
+ console.log(` estado ${claim.estado}`);
521
+ if (claim.negativa && claim.verificar.length === 0) {
522
+ console.log('');
523
+ console.log('AVISO: alegacao negativa sem comando de verificacao reprova em `ork verify`.');
524
+ }
525
+ return 0;
526
+ }
527
+ if (sub === 'verificar') {
528
+ const id = args.posicionais[2];
529
+ const claimId = args.posicionais[3];
530
+ const comando = texto(args.opcoes.comando) ?? texto(args.opcoes.verificar);
531
+ if (!id || !claimId || !comando) {
532
+ console.error('uso: ork claims verificar <thread-id> <claim-id> --comando "<comando>"');
533
+ return 2;
534
+ }
535
+ const claim = (0, claims_1.anexarComando)(carregado.raiz, id, claimId, comando);
536
+ console.log(`Claim ${claim.id} agora tem comando de verificacao.`);
537
+ console.log(` verificar ${claim.verificar.join(' && ')}`);
538
+ console.log(` estado ${claim.estado}`);
539
+ console.log('');
540
+ console.log(`Prove agora: ork verify ${id}`);
541
+ return 0;
542
+ }
543
+ if (sub === 'retirar') {
544
+ const id = args.posicionais[2];
545
+ const claimId = args.posicionais[3];
546
+ const motivo = texto(args.opcoes.motivo);
547
+ if (!id || !claimId || !motivo) {
548
+ console.error('uso: ork claims retirar <thread-id> <claim-id> --motivo "<motivo>"');
549
+ return 2;
550
+ }
551
+ const claim = (0, claims_1.retirarClaim)(carregado.raiz, id, claimId, motivo);
552
+ console.log(`Claim ${claim.id} retirada da thread ${id}.`);
553
+ console.log(` alegacao ${claim.alegacao}`);
554
+ console.log(` motivo ${motivo}`);
555
+ console.log(' o historico da alegacao continua no claims.jsonl e no ledger.');
556
+ return 0;
557
+ }
558
+ if (sub === 'list' || sub === undefined) {
559
+ const id = args.posicionais[2];
560
+ if (!id) {
561
+ console.error('uso: ork claims list <thread-id>');
562
+ return 2;
563
+ }
564
+ console.log((0, claims_1.tabelaDeClaims)(carregado.raiz, id));
565
+ return 0;
566
+ }
567
+ console.error(`subcomando desconhecido: claims ${sub}`);
568
+ return 2;
569
+ }
570
+ function comandoVerify(args) {
571
+ const carregado = (0, manifest_1.exigirManifesto)();
572
+ const id = args.posicionais[1];
573
+ if (!id) {
574
+ console.error('uso: ork verify <thread-id> [--baseline] [--so-claims]');
575
+ return 2;
576
+ }
577
+ if (args.opcoes.baseline === true) {
578
+ const b = (0, verify_1.gravarBaseline)(carregado, id);
579
+ console.log(`Baseline gravada para a thread ${id}.`);
580
+ console.log(` commit ${b.commit}`);
581
+ for (const c of b.comandos) {
582
+ console.log(` ${c.nome.padEnd(10)} ${c.ok ? 'passava' : `ja falhava (codigo ${c.code})`} ${c.comando}`);
583
+ }
584
+ if (b.comandos.length === 0) {
585
+ console.log(' (nenhum comando em verify: no manifesto; sem baseline nao ha como separar regressao)');
586
+ }
587
+ return 0;
588
+ }
589
+ const r = (0, verify_1.verificar)(carregado, id, { soClaims: args.opcoes['so-claims'] === true });
590
+ console.log((0, verify_1.textoDoVerify)(r));
591
+ return r.ok ? 0 : 1;
592
+ }
593
+ function comandoGate(args) {
594
+ const carregado = (0, manifest_1.exigirManifesto)();
595
+ const sub = args.posicionais[1];
596
+ if (sub === 'next') {
597
+ const id = args.posicionais[2];
598
+ if (!id) {
599
+ console.error('uso: ork gate next <thread-id> [--proximo FASE] [--ocupacao 0..1]');
600
+ return 2;
601
+ }
602
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
603
+ const proximoBruto = texto(args.opcoes.proximo) ?? texto(args.opcoes['proxima-fase']);
604
+ const ocupacaoBruta = texto(args.opcoes.ocupacao);
605
+ const janelaBruta = texto(args.opcoes.janela);
606
+ const v = (0, tokens_1.gateDeTokens)(carregado, id, {
607
+ proximo: proximoBruto ? (0, thread_1.exigirFase)(thread, proximoBruto) : undefined,
608
+ ocupacao: ocupacaoBruta !== undefined ? Number(ocupacaoBruta) : undefined,
609
+ fonte: texto(args.opcoes.fonte),
610
+ transcript: texto(args.opcoes.transcript),
611
+ janela: janelaBruta !== undefined ? Number(janelaBruta) : undefined,
612
+ refazer: args.opcoes.refazer === true,
613
+ sessao: texto(args.opcoes.sessao),
614
+ });
615
+ console.log((0, tokens_1.textoDoGateDeTokens)(v));
616
+ return 0;
617
+ }
618
+ if (sub === 'approve') {
619
+ const id = args.posicionais[2];
620
+ const sobre = args.posicionais[3];
621
+ const por = texto(args.opcoes.por) ?? texto(args.opcoes.quem);
622
+ if (!id || !sobre || !por) {
623
+ console.error('uso: ork gate approve <thread-id> <sobre> --por <quem>');
624
+ return 2;
625
+ }
626
+ (0, thread_1.lerThread)(carregado.raiz, id);
627
+ const e = (0, gates_1.aprovarGateHumano)(carregado.raiz, id, sobre, por, texto(args.opcoes.obs));
628
+ console.log(`Autorizacao humana registrada no ledger da thread ${id}.`);
629
+ console.log(` sobre ${sobre}`);
630
+ console.log(` autorizado por ${por}`);
631
+ console.log(` quando ${e.ts}`);
632
+ return 0;
633
+ }
634
+ console.error(`subcomando desconhecido: gate ${sub}`);
635
+ return 2;
636
+ }
637
+ /**
638
+ * `ork retry`: a politica de retry tipada e a fila duravel de rate limit (bloco B3).
639
+ *
640
+ * O comando existe separado do `ork gate` porque ele nao decide VERDADE: ele decide o
641
+ * que fazer com uma verdade que o gate ja estabeleceu. `plan` calcula sem executar, e
642
+ * por isso nao gasta tentativa nem toca no repositorio.
643
+ */
644
+ function comandoRetry(args) {
645
+ const sub = args.posicionais[1];
646
+ if (sub === 'policy') {
647
+ const alvo = texto(args.opcoes.motivo);
648
+ if (alvo) {
649
+ const politica = retry_1.POLITICA_DE_RETRY[alvo];
650
+ if (!politica) {
651
+ console.error(`motivo tipado desconhecido: ${alvo}`);
652
+ console.error(` conhecidos: ${Object.keys(retry_1.POLITICA_DE_RETRY).join(', ')}`);
653
+ return 2;
654
+ }
655
+ if (args.opcoes.json === true) {
656
+ console.log(JSON.stringify(politica, null, 2));
657
+ return 0;
658
+ }
659
+ console.log(`motivo tipado: ${politica.motivo}`);
660
+ console.log(` significado ${auditoria_1.DESCRICAO_DO_MOTIVO_DE_AUDITORIA[politica.motivo]}`);
661
+ console.log(` acao ${politica.acao}`);
662
+ console.log(` automatica ${politica.automatica ? 'sim' : 'nao'}`);
663
+ console.log(` por que ${politica.porque}`);
664
+ console.log(` correcao ${politica.correcao}`);
665
+ return 0;
666
+ }
667
+ if (args.opcoes.json === true) {
668
+ console.log(JSON.stringify(Object.values(retry_1.POLITICA_DE_RETRY), null, 2));
669
+ return 0;
670
+ }
671
+ console.log('Politica de retry por motivo tipado de gate (bloco B3)');
672
+ console.log('');
673
+ console.log((0, retry_1.tabelaDaPolitica)());
674
+ console.log('');
675
+ console.log('A politica e a MESMA em todos os modos: o modo afrouxa a pausa, nunca a');
676
+ console.log('verificacao. cost.violation nunca recebe retry automatico, e o limite de');
677
+ console.log('escalacao (retry.max_tentativas) pausa qualquer modo, inclusive #Auto.');
678
+ return 0;
679
+ }
680
+ if (sub === 'parse') {
681
+ const bruto = texto(args.opcoes.stderr) ?? args.posicionais.slice(2).join(' ');
682
+ if (!bruto) {
683
+ console.error('uso: ork retry parse --stderr "<texto do stderr do adapter>"');
684
+ return 2;
685
+ }
686
+ const sinal = (0, ratelimit_1.parseRateLimit)(bruto);
687
+ if (args.opcoes.json === true) {
688
+ console.log(JSON.stringify(sinal, null, 2));
689
+ return sinal ? 0 : 1;
690
+ }
691
+ if (!sinal) {
692
+ console.log('Nenhum sinal de rate limit reconhecido neste texto.');
693
+ return 1;
694
+ }
695
+ console.log('Sinal de rate limit reconhecido no stderr do runtime:');
696
+ console.log(` fonte da hora ${sinal.fonte}`);
697
+ console.log(` reset em ${sinal.resetEm ?? '(o runtime nao disse a hora)'}`);
698
+ console.log(` trecho ${sinal.trecho}`);
699
+ if (sinal.resetEm === null) {
700
+ console.log('');
701
+ console.log(' Sem hora no texto, a fila usa retry.janela_padrao_min do manifesto e marca');
702
+ console.log(' o pedido como janela ESTIMADA. O `ork` nao inventa horario de reset.');
703
+ }
704
+ return 0;
705
+ }
706
+ const carregado = (0, manifest_1.exigirManifesto)();
707
+ if (sub === 'plan' || sub === 'run') {
708
+ const id = args.posicionais[2];
709
+ if (!id) {
710
+ console.error(`uso: ork retry ${sub} <thread-id> [--motivo M] [--fase F]`);
711
+ return 2;
712
+ }
713
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
714
+ const faseBruta = texto(args.opcoes.fase);
715
+ const opcoes = {
716
+ motivo: texto(args.opcoes.motivo),
717
+ fase: faseBruta ? (0, thread_1.exigirFase)(thread, faseBruta) : undefined,
718
+ autorizadoPor: texto(args.opcoes.por) ?? texto(args.opcoes.quem),
719
+ };
720
+ if (sub === 'plan') {
721
+ const plano = (0, retry_1.planejarRetry)(carregado, id, opcoes);
722
+ if (args.opcoes.json === true) {
723
+ console.log(JSON.stringify(plano, null, 2));
724
+ return 0;
725
+ }
726
+ console.log((0, retry_1.textoDoPlano)(plano));
727
+ return 0;
728
+ }
729
+ const r = (0, retry_1.executarRetry)(carregado, id, {
730
+ ...opcoes,
731
+ dryRun: args.opcoes['dry-run'] === true,
732
+ reverify: args.opcoes.reverify === true,
733
+ });
734
+ if (args.opcoes.json === true) {
735
+ console.log(JSON.stringify(r, null, 2));
736
+ }
737
+ else {
738
+ console.log((0, retry_1.textoDoRetry)(r));
739
+ }
740
+ // Codigo de saida != 0 quando nada pode ser feito sozinho: e o sinal para o
741
+ // orquestrador parar e chamar o humano, em vez de seguir achando que retomou.
742
+ return r.executada ? 0 : 1;
743
+ }
744
+ if (sub === 'list') {
745
+ if (args.opcoes.json === true) {
746
+ console.log(JSON.stringify((0, ratelimit_1.lerFilaDeRetomada)(carregado.raiz), null, 2));
747
+ return 0;
748
+ }
749
+ console.log((0, ratelimit_1.tabelaDaFila)(carregado.raiz));
750
+ const espera = (0, ratelimit_1.lerFilaDeRetomada)(carregado.raiz).filter((p) => p.estado === 'aguardando');
751
+ if (espera.length > 0) {
752
+ console.log('');
753
+ console.log(`Proxima janela: ${espera[0].liberaEm} (${(0, ratelimit_1.faltaPara)(espera[0])}).`);
754
+ console.log('Retome com: ork retry resume');
755
+ }
756
+ return 0;
757
+ }
758
+ if (sub === 'resume') {
759
+ const ocupacaoBruta = texto(args.opcoes.ocupacao);
760
+ const opcoes = {
761
+ quando: texto(args.opcoes.agora),
762
+ dryRun: args.opcoes['dry-run'] === true,
763
+ forcar: args.opcoes.forcar === true,
764
+ ocupacao: ocupacaoBruta !== undefined ? Number(ocupacaoBruta) : undefined,
765
+ fonte: texto(args.opcoes.fonte),
766
+ };
767
+ const idPedido = texto(args.opcoes.id);
768
+ const rs = idPedido
769
+ ? [(0, retry_1.retomarPorId)(carregado, idPedido, opcoes)]
770
+ : (0, retry_1.retomarFila)(carregado, opcoes);
771
+ if (args.opcoes.json === true) {
772
+ console.log(JSON.stringify(rs, null, 2));
773
+ }
774
+ else {
775
+ console.log((0, retry_1.textoDaRetomada)(rs));
776
+ }
777
+ // Escalada nao e sucesso: ela e o pedido de socorro que pausa qualquer modo.
778
+ return rs.some((r) => r.playbook === 'escalada') ? 1 : 0;
779
+ }
780
+ if (sub === 'cancel') {
781
+ const idPedido = args.posicionais[2];
782
+ const motivo = texto(args.opcoes.motivo);
783
+ if (!idPedido || !motivo) {
784
+ console.error('uso: ork retry cancel <id> --motivo "<motivo>"');
785
+ return 2;
786
+ }
787
+ const p = (0, retry_1.cancelarPedido)(carregado, idPedido, motivo);
788
+ console.log(`Pedido ${p.id} cancelado na fila de rate limit.`);
789
+ console.log(` thread ${p.thread}`);
790
+ console.log(` fase ${p.fase}`);
791
+ console.log(` motivo ${motivo}`);
792
+ return 0;
793
+ }
794
+ console.error(`subcomando desconhecido: retry ${sub ?? ''}`);
795
+ return 2;
796
+ }
797
+ /**
798
+ * `ork fix`: o sub-loop GO-FIX / CHECK-REVERIFY (bloco B3).
799
+ *
800
+ * `open` deriva a spec do resultado REAL do `ork verify`; `reverify` da veredito POR
801
+ * correcao. O `--parcial` e recusado quando a rodada tem correcao tipo B, porque
802
+ * parcial depois de tipo B nao e CHECK (DoD 10).
803
+ */
804
+ function comandoFix(args) {
805
+ const carregado = (0, manifest_1.exigirManifesto)();
806
+ const sub = args.posicionais[1];
807
+ const id = args.posicionais[2];
808
+ if (sub === 'open') {
809
+ if (!id) {
810
+ console.error('uso: ork fix open <thread-id> [--so-claims] [--reverify]');
811
+ return 2;
812
+ }
813
+ const rodada = (0, fix_1.abrirRodada)(carregado, id, { soClaims: args.opcoes['so-claims'] === true });
814
+ const reverify = args.opcoes.reverify === true && rodada.correcoes.length > 0
815
+ ? (0, fix_1.reverificar)(carregado, id, { rodada: rodada.rodada })
816
+ : null;
817
+ if (args.opcoes.json === true) {
818
+ console.log(JSON.stringify({ rodada, reverify }, null, 2));
819
+ }
820
+ else {
821
+ console.log((0, fix_1.textoDaRodada)(rodada));
822
+ if (reverify) {
823
+ console.log('');
824
+ console.log((0, fix_1.textoDoReverify)(reverify));
825
+ }
826
+ }
827
+ if (rodada.correcoes.length === 0)
828
+ return 0;
829
+ return reverify && reverify.veredito === 'PASSOU' ? 0 : 1;
830
+ }
831
+ if (sub === 'list') {
832
+ if (!id) {
833
+ console.error('uso: ork fix list <thread-id> [--rodada N]');
834
+ return 2;
835
+ }
836
+ (0, thread_1.lerThread)(carregado.raiz, id);
837
+ const rodadaBruta = texto(args.opcoes.rodada);
838
+ const rodada = rodadaBruta ? Number(rodadaBruta) : (0, fix_1.ultimaRodada)(carregado.raiz, id);
839
+ if (rodada === 0) {
840
+ console.log(`A thread ${id} nao tem rodada de GO-FIX. Abra com: ork fix open ${id}`);
841
+ return 0;
842
+ }
843
+ const correcoes = (0, fix_1.correcoesDaRodada)(carregado.raiz, id, rodada);
844
+ if (args.opcoes.json === true) {
845
+ console.log(JSON.stringify(correcoes, null, 2));
846
+ return 0;
847
+ }
848
+ console.log(`Correcoes da rodada ${rodada} da thread ${id}`);
849
+ console.log('');
850
+ console.log((0, util_1.tabela)(['ID', 'TIPO', 'MOTIVO', 'ALVO', 'ESTADO', 'JULGADO POR'], correcoes.map((c) => [
851
+ c.id,
852
+ c.tipo,
853
+ c.origem,
854
+ c.alvo,
855
+ c.estado,
856
+ c.verificar.join(' && ') || '(verify completo)',
857
+ ])));
858
+ return 0;
859
+ }
860
+ if (sub === 'reverify') {
861
+ if (!id) {
862
+ console.error('uso: ork fix reverify <thread-id> [--rodada N] [--parcial]');
863
+ return 2;
864
+ }
865
+ const rodadaBruta = texto(args.opcoes.rodada);
866
+ const r = (0, fix_1.reverificar)(carregado, id, {
867
+ rodada: rodadaBruta ? Number(rodadaBruta) : undefined,
868
+ parcial: args.opcoes.parcial === true,
869
+ });
870
+ if (args.opcoes.json === true) {
871
+ console.log(JSON.stringify(r, null, 2));
872
+ }
873
+ else {
874
+ console.log((0, fix_1.textoDoReverify)(r));
875
+ }
876
+ return r.veredito === 'PASSOU' ? 0 : 1;
877
+ }
878
+ console.error(`subcomando desconhecido: fix ${sub ?? ''}`);
879
+ return 2;
880
+ }
881
+ function comandoHandoff(args) {
882
+ const carregado = (0, manifest_1.exigirManifesto)();
883
+ const sub = args.posicionais[1];
884
+ const id = args.posicionais[2];
885
+ if (sub === 'export') {
886
+ if (!id) {
887
+ console.error('uso: ork handoff export <thread-id> [--proxima-fase FASE]');
888
+ return 2;
889
+ }
890
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
891
+ const faseBruta = texto(args.opcoes['proxima-fase']) ?? texto(args.opcoes.fase);
892
+ const r = (0, handoff_1.exportarHandoff)(carregado, id, {
893
+ proximaFase: faseBruta ? (0, thread_1.exigirFase)(thread, faseBruta) : undefined,
894
+ slugDestino: texto(args.opcoes.slug),
895
+ });
896
+ console.log((0, handoff_1.textoDoHandoff)(r.handoff, r.caminho));
897
+ console.log('');
898
+ console.log(`Historico: ${r.caminhoHistorico}`);
899
+ return 0;
900
+ }
901
+ if (sub === 'recall') {
902
+ const ponteiro = args.posicionais[3];
903
+ if (!id || !ponteiro) {
904
+ console.error('uso: ork handoff recall <thread-id> <path#ancora>');
905
+ return 2;
906
+ }
907
+ const r = (0, handoff_1.recall)(carregado, id, ponteiro);
908
+ console.log(`Ponteiro resolvido: ${r.location}`);
909
+ console.log(` metodo ${r.metodo}`);
910
+ console.log(` sha256 ${r.sha256}`);
911
+ console.log(` linhas ${r.intervalo ? `${r.intervalo.inicio}-${r.intervalo.fim}` : '(nao aplicavel)'}`);
912
+ console.log('');
913
+ console.log(r.conteudo);
914
+ return 0;
915
+ }
916
+ console.error(`subcomando desconhecido: handoff ${sub}`);
917
+ return 2;
918
+ }
919
+ function comandoShip(args) {
920
+ const carregado = (0, manifest_1.exigirManifesto)();
921
+ const id = args.posicionais[1];
922
+ const para = texto(args.opcoes.para) ?? texto(args.opcoes.to);
923
+ if (!id || !para) {
924
+ console.error('uso: ork ship <thread-id> --para <branch> [--de <branch>] [--dry-run]');
925
+ return 2;
926
+ }
927
+ const autorizar = args.opcoes['autorizar-push'];
928
+ const r = (0, ship_1.ship)(carregado, id, {
929
+ para,
930
+ de: texto(args.opcoes.de),
931
+ remoto: texto(args.opcoes.remoto),
932
+ mensagem: texto(args.opcoes.mensagem),
933
+ dryRun: args.opcoes['dry-run'] === true,
934
+ autorizarPush: typeof autorizar === 'string' ? autorizar : undefined,
935
+ semPush: args.opcoes['sem-push'] === true,
936
+ });
937
+ console.log((0, ship_1.textoDoShip)(r));
938
+ return r.ok ? 0 : 1;
939
+ }
940
+ function comandoLease(args) {
941
+ const carregado = (0, manifest_1.exigirManifesto)();
942
+ const sub = args.posicionais[1];
943
+ if (sub === undefined || sub === 'list') {
944
+ console.log((0, leases_1.tabelaDeLeases)(carregado.raiz));
945
+ return 0;
946
+ }
947
+ if (sub === 'acquire' || sub === 'take') {
948
+ const nome = args.posicionais[2];
949
+ const thread = texto(args.opcoes.thread);
950
+ const motivo = texto(args.opcoes.motivo) ?? 'sem motivo declarado';
951
+ if (!nome || !thread) {
952
+ console.error('uso: ork lease acquire <nome> --thread <thread-id> [--motivo "<motivo>"]');
953
+ return 2;
954
+ }
955
+ (0, thread_1.lerThread)(carregado.raiz, thread);
956
+ const r = (0, leases_1.adquirirRegiao)(carregado.raiz, nome, { thread, motivo });
957
+ if (r.ok) {
958
+ console.log(`Lease ${r.nome} [${r.tipo}] adquirido pela thread ${thread}.`);
959
+ console.log(` expira em ${r.lease?.expiraEm}`);
960
+ if (r.tomadoDeVencido)
961
+ console.log(' (o lease anterior estava VENCIDO e foi tomado)');
962
+ return 0;
963
+ }
964
+ console.error(`Lease ${r.nome} NAO adquirido.`);
965
+ console.error(` motivo tipado: ${r.motivo}`);
966
+ console.error(` detalhe: ${r.detalhe}`);
967
+ console.error(` posicao na fila: ${r.posicaoNaFila}`);
968
+ console.error(` correcao: ${r.correcao}`);
969
+ return 1;
970
+ }
971
+ if (sub === 'release') {
972
+ const nome = args.posicionais[2];
973
+ if (!nome) {
974
+ console.error('uso: ork lease release <nome> [--thread <thread-id>] [--forcar]');
975
+ return 2;
976
+ }
977
+ const r = (0, leases_1.liberar)(carregado.raiz, nome, texto(args.opcoes.thread) ?? '', args.opcoes.forcar === true);
978
+ console.log(r.detalhe);
979
+ return r.ok ? 0 : 1;
980
+ }
981
+ console.error(`subcomando desconhecido: lease ${sub}`);
982
+ return 2;
983
+ }
984
+ function comandoBoard(args) {
985
+ const carregado = (0, manifest_1.exigirManifesto)();
986
+ const sub = args.posicionais[1];
987
+ if (sub === 'plan' || sub === 'plano') {
988
+ console.log((0, board_1.textoDoPlano)((0, board_1.planejar)(carregado)));
989
+ return 0;
990
+ }
991
+ if (sub !== undefined && sub !== 'list') {
992
+ console.error(`subcomando desconhecido: board ${sub}`);
993
+ return 2;
994
+ }
995
+ console.log((0, board_1.textoDoBoard)(carregado, args.opcoes.all === true || args.opcoes.todos === true));
996
+ return 0;
997
+ }
998
+ /**
999
+ * `ork orquestracao status` (alias `ork monitor`): pausas e impedimentos de uma chamada.
1000
+ *
1001
+ * Existe para o orquestrador ser PROATIVO: ele roda isto em laco, ve quem esta parado
1002
+ * esperando veredito humano e avisa o humano com alternativas, em vez de descobrir a
1003
+ * pausa so quando o humano pergunta. O `ork` entrega o estado; quem notifica e a
1004
+ * Camada 1, que consome o `--json`.
1005
+ */
1006
+ function comandoOrquestracao(args) {
1007
+ const carregado = (0, manifest_1.exigirManifesto)();
1008
+ const sub = args.posicionais[1];
1009
+ if (sub !== undefined && sub !== 'status') {
1010
+ console.error(`subcomando desconhecido: orquestracao ${sub}`);
1011
+ console.error('uso: ork orquestracao status [--all] [--json] [--atencao N] [--so-paradas]');
1012
+ return 2;
1013
+ }
1014
+ const bruto = texto(args.opcoes.atencao);
1015
+ const atencaoMin = bruto === undefined ? undefined : Number(bruto);
1016
+ if (atencaoMin !== undefined && (!Number.isFinite(atencaoMin) || atencaoMin < 0)) {
1017
+ console.error(`--atencao espera minutos (inteiro >= 0), recebeu "${bruto}"`);
1018
+ return 2;
1019
+ }
1020
+ const monitor = (0, orquestracao_1.montarMonitor)(carregado, {
1021
+ todos: args.opcoes.all === true || args.opcoes.todos === true,
1022
+ atencaoMin,
1023
+ soParadas: args.opcoes['so-paradas'] === true,
1024
+ semRuntime: args.opcoes['sem-runtime'] === true,
1025
+ });
1026
+ console.log(args.opcoes.json === true ? JSON.stringify(monitor, null, 2) : (0, orquestracao_1.textoDoMonitor)(monitor));
1027
+ // `--exigir-limpo` transforma o monitor em watchdog: sai != 0 enquanto houver thread
1028
+ // parada. E o que deixa o orquestrador (ou um cron) tratar "tem gente esperando" como
1029
+ // falha acionavel, sem precisar interpretar texto.
1030
+ if (args.opcoes['exigir-limpo'] === true) {
1031
+ return monitor.resumo.aguardandoHumano + monitor.resumo.comImpedimento > 0 ? 1 : 0;
1032
+ }
1033
+ return 0;
1034
+ }
1035
+ function comandoWorktree(args) {
1036
+ const carregado = (0, manifest_1.exigirManifesto)();
1037
+ const sub = args.posicionais[1];
1038
+ const id = args.posicionais[2];
1039
+ if (!sub || !id) {
1040
+ console.error('uso: ork worktree <ensure|sync|audit|release> <thread-id>');
1041
+ return 2;
1042
+ }
1043
+ if (sub === 'ensure') {
1044
+ const r = (0, worktree_1.garantirWorktree)(carregado, id);
1045
+ if (!r.ok) {
1046
+ console.error(`Worktree da thread ${id} NAO garantida.`);
1047
+ console.error(` motivo tipado: ${r.motivo}`);
1048
+ console.error(` detalhe: ${r.detalhe}`);
1049
+ console.error(` correcao: ${r.correcao}`);
1050
+ return 1;
1051
+ }
1052
+ console.log(r.criada ? `Worktree criada para a thread ${id}.` : `Worktree ja existia para a thread ${id}.`);
1053
+ console.log(` dir ${r.dir}`);
1054
+ console.log(` branch ${r.branch}`);
1055
+ console.log(` base ${r.base} (resolvida pelo ork, nao pelo executor)`);
1056
+ console.log(` ${r.detalhe}`);
1057
+ return 0;
1058
+ }
1059
+ if (sub === 'sync') {
1060
+ const r = (0, worktree_1.sincronizarWorktree)(carregado, id, { dryRun: args.opcoes['dry-run'] === true });
1061
+ if (!r.ok) {
1062
+ console.error(`Sync da worktree da thread ${id} BLOQUEADO.`);
1063
+ console.error(` motivo tipado: ${r.motivo}`);
1064
+ console.error(` detalhe: ${r.detalhe}`);
1065
+ console.error(` correcao: ${r.correcao}`);
1066
+ return 1;
1067
+ }
1068
+ console.log(r.dryRun ? `Sync (--dry-run) da thread ${id}: nada foi executado.` : `Sync da thread ${id}.`);
1069
+ console.log(` base ${r.base} @ ${r.shaBase.slice(0, 8)}`);
1070
+ console.log(` branch ${r.branch} @ ${r.shaAntes.slice(0, 8)} -> ${r.shaDepois.slice(0, 8)}`);
1071
+ console.log(` rebase ${r.rebaseFeito ? 'feito' : r.jaAtualizada ? 'desnecessario' : 'seria feito'}`);
1072
+ console.log(` ${r.detalhe}`);
1073
+ if (r.passos.length > 0) {
1074
+ console.log('');
1075
+ console.log(' Comandos reais, na ordem:');
1076
+ for (const passo of r.passos)
1077
+ console.log(` ${passo}`);
1078
+ }
1079
+ return 0;
1080
+ }
1081
+ if (sub === 'audit') {
1082
+ const r = (0, worktree_1.auditarWorktree)(carregado, id);
1083
+ console.log((0, worktree_1.textoDoAudit)(id, r));
1084
+ return r.ok ? 0 : 1;
1085
+ }
1086
+ if (sub === 'release') {
1087
+ const r = (0, worktree_1.liberarWorktree)(carregado, id, { forcar: args.opcoes.forcar === true });
1088
+ if (!r.ok) {
1089
+ console.error(`Release da worktree da thread ${id} BLOQUEADO.`);
1090
+ console.error(` motivo tipado: ${r.motivo}`);
1091
+ console.error(` detalhe: ${r.detalhe}`);
1092
+ console.error(` correcao: ${r.correcao}`);
1093
+ return 1;
1094
+ }
1095
+ console.log(`Worktree da thread ${id} liberada.`);
1096
+ console.log(` dir ${r.dir}`);
1097
+ console.log(` removida ${r.removida ? 'sim' : 'nao (o diretorio ja nao existia)'}`);
1098
+ console.log(` leases ${r.leasesLiberados.join(', ') || '(nenhum lease de escrita para soltar)'}`);
1099
+ console.log(` ${r.detalhe}`);
1100
+ return 0;
1101
+ }
1102
+ console.error(`subcomando desconhecido: worktree ${sub}`);
1103
+ return 2;
1104
+ }
1105
+ function comandoMaster(args) {
1106
+ const carregado = (0, manifest_1.exigirManifesto)();
1107
+ const primeiro = args.posicionais[1];
1108
+ if (primeiro === 'classes') {
1109
+ console.log((0, master_1.tabelaDeClasses)());
1110
+ return 0;
1111
+ }
1112
+ if (args.opcoes.batch === true || primeiro === 'batch' || primeiro === undefined) {
1113
+ console.log((0, master_1.tabelaDeBatch)(carregado.raiz, args.opcoes.todas === true));
1114
+ return 0;
1115
+ }
1116
+ const id = primeiro;
1117
+ const brutoScore = texto(args.opcoes.score);
1118
+ const justificativa = texto(args.opcoes.justificativa) ?? texto(args.opcoes.porque);
1119
+ if (brutoScore === undefined) {
1120
+ console.error('uso: ork master <thread-id> --score 0-5 --justificativa "<texto>"');
1121
+ console.error(' o score do MASTER e humano, de 0 a 5, e a justificativa e obrigatoria.');
1122
+ return 2;
1123
+ }
1124
+ if (!justificativa) {
1125
+ console.error(`Score RECUSADO para a thread ${id}: falta --justificativa "<texto>".`);
1126
+ console.error(' Score sem justificativa nao vira aprendizado; o `ork` nao o registra.');
1127
+ console.error(` ork master ${id} --score ${brutoScore} --justificativa "<por que este score>"`);
1128
+ return 2;
1129
+ }
1130
+ const brutasClasses = texto(args.opcoes.classe) ?? texto(args.opcoes.classes);
1131
+ const classes = [];
1132
+ for (const bruta of (brutasClasses ?? '').split(',').map((c) => c.trim()).filter(Boolean)) {
1133
+ const classe = (0, master_1.parseClasse)(bruta);
1134
+ if (!classe) {
1135
+ console.error(`classe de falha invalida: "${bruta}".`);
1136
+ console.error(` classes fixas: ${master_1.ORDEM_DAS_CLASSES.join(', ')}`);
1137
+ return 2;
1138
+ }
1139
+ classes.push(classe);
1140
+ }
1141
+ const r = (0, master_1.registrarMaster)(carregado.raiz, id, {
1142
+ score: Number(brutoScore),
1143
+ justificativa,
1144
+ classes,
1145
+ resumo: texto(args.opcoes.resumo),
1146
+ por: texto(args.opcoes.por) ?? texto(args.opcoes.quem),
1147
+ refazer: args.opcoes.refazer === true,
1148
+ });
1149
+ console.log((0, master_1.textoDoMaster)(r));
1150
+ // Bloco B6: fechada a thread, a licao (POSTMORTEM + score) vai para a colecao
1151
+ // `learning`, e e o que uma thread NOVA do mesmo produto recebe no GOAL.
1152
+ relatarPublicacao((0, memoria_1.publicar)(carregado, id));
1153
+ console.log('');
1154
+ console.log(`Proximo passo: ork board --all | fila de score: ork master --batch`);
1155
+ return 0;
1156
+ }
1157
+ /**
1158
+ * `ork prompt list|lint|render`: os prompts do `ork` como templates versionados (bloco B4).
1159
+ *
1160
+ * O `lint` reprova template quebrado ANTES de ele virar despacho; o `render` mostra o prompt
1161
+ * exato com o mesmo sha256 que iria para o ledger, para o builder revisar texto sem gastar
1162
+ * uma sessao do runtime para descobrir o que foi pedido.
1163
+ */
1164
+ function comandoPrompt(args) {
1165
+ const sub = args.posicionais[1] ?? 'list';
1166
+ const carregado = (0, manifest_1.carregarManifesto)();
1167
+ const raiz = carregado?.raiz;
1168
+ if (sub === 'list') {
1169
+ console.log((0, prompts_1.tabelaDeTemplates)((0, prompts_1.carregarTemplates)(raiz)));
1170
+ return 0;
1171
+ }
1172
+ if (sub === 'lint') {
1173
+ const id = texto(args.opcoes.template);
1174
+ const templates = id ? [(0, prompts_1.exigirTemplate)(id, raiz)] : (0, prompts_1.carregarTemplates)(raiz);
1175
+ const problemas = templates.flatMap((t) => (0, prompts_1.lintTemplate)(t));
1176
+ console.log(`Lint dos templates de prompt${raiz ? ` (projeto ${raiz})` : ' (somente embutidos)'}`);
1177
+ console.log('');
1178
+ console.log((0, prompts_1.textoDoLint)(problemas, templates.length));
1179
+ return problemas.some((p) => p.gravidade === 'erro') ? 2 : 0;
1180
+ }
1181
+ if (sub === 'render') {
1182
+ const fase = exigirFaseCanonica(texto(args.opcoes.fase) ?? args.posicionais[3]);
1183
+ const pedido = texto(args.opcoes.pedido) ?? '<pedido do builder>';
1184
+ const idTemplate = texto(args.opcoes.template);
1185
+ // Modo exemplo: renderiza sem thread nenhuma, para revisar o texto de um modo antes de
1186
+ // abrir trabalho. Nada e gravado, e o `ork` diz em voz alta que a thread e ficticia.
1187
+ if (args.opcoes.exemplo === true || args.opcoes.modo !== undefined || args.opcoes.mode !== undefined) {
1188
+ const bruto = texto(args.opcoes.modo) ?? texto(args.opcoes.mode) ?? 'classic';
1189
+ const modo = (0, modos_1.parseModo)(bruto);
1190
+ if (!modo) {
1191
+ console.error(`modo invalido: "${bruto}". Use um de: ${Object.values(modos_1.MODOS).map((m) => m.tag).join(', ')}`);
1192
+ return 2;
1193
+ }
1194
+ const exemplo = (0, prompts_1.threadDeExemplo)(modo, fase, carregado?.manifesto.project);
1195
+ const template = idTemplate ? (0, prompts_1.exigirTemplate)(idTemplate, raiz) : (0, prompts_1.templateDaFase)(fase, raiz);
1196
+ const prompt = (0, prompts_1.renderizar)(template, (0, phase_1.valoresDoPrompt)(exemplo, fase, pedido));
1197
+ console.log(`# template ${template.id} v${template.versao} (origem: ${template.origem})`);
1198
+ console.log(`# thread de EXEMPLO (nada foi gravado), modo ${modos_1.MODOS[modo].tag}, sha256 ${(0, phase_1.hashDoPrompt)(prompt)}`);
1199
+ console.log('');
1200
+ console.log(prompt);
1201
+ return 0;
1202
+ }
1203
+ const obrigatorio = (0, manifest_1.exigirManifesto)();
1204
+ const threadId = args.posicionais[2];
1205
+ if (!threadId) {
1206
+ console.error('uso: ork prompt render <thread-id> <FASE> --pedido "<texto>"');
1207
+ console.error(' ork prompt render --exemplo --fase GOAL --modo auto --pedido "<texto>"');
1208
+ return 2;
1209
+ }
1210
+ const thread = (0, thread_1.lerThread)(obrigatorio.raiz, threadId);
1211
+ const template = idTemplate ? (0, prompts_1.exigirTemplate)(idTemplate, obrigatorio.raiz) : (0, prompts_1.templateDaFase)(fase, obrigatorio.raiz);
1212
+ const prompt = idTemplate
1213
+ ? (0, prompts_1.renderizar)(template, (0, phase_1.valoresDoPrompt)(thread, fase, pedido))
1214
+ : (0, phase_1.montarPrompt)(thread, fase, pedido, obrigatorio.raiz);
1215
+ console.log(`# template ${template.id} v${template.versao} (origem: ${template.origem})`);
1216
+ console.log(`# thread ${thread.id}, fase ${fase}, sha256 ${(0, phase_1.hashDoPrompt)(prompt)}`);
1217
+ console.log('');
1218
+ console.log(prompt);
1219
+ return 0;
1220
+ }
1221
+ console.error(`subcomando desconhecido: prompt ${sub}`);
1222
+ return 2;
1223
+ }
1224
+ /** Fase canonica a partir do texto do usuario, com erro tipado quando nao existe. */
1225
+ function exigirFaseCanonica(bruto) {
1226
+ const alvo = (bruto ?? '').toUpperCase();
1227
+ if (!types_1.FASES.includes(alvo)) {
1228
+ throw new Error(`fase "${bruto ?? ''}" fora do ciclo canonico (${types_1.FASES.join(' ')})`);
1229
+ }
1230
+ return alvo;
1231
+ }
1232
+ /**
1233
+ * `ork adapter list|show|install <host>`: instalacao dos adaptadores de Camada 1 (bloco B4).
1234
+ */
1235
+ function comandoAdapter(args) {
1236
+ const sub = args.posicionais[1] ?? 'list';
1237
+ if (sub === 'list') {
1238
+ console.log((0, hosts_1.tabelaDeHosts)());
1239
+ return 0;
1240
+ }
1241
+ if (sub === 'show') {
1242
+ const host = (0, hosts_1.parseHost)(args.posicionais[2]);
1243
+ if (!host) {
1244
+ console.error(`host desconhecido: "${args.posicionais[2] ?? ''}". Use: ${hosts_1.ORDEM_DOS_HOSTS.join(' | ')}`);
1245
+ return 2;
1246
+ }
1247
+ const def = hosts_1.HOSTS[host];
1248
+ console.log(`Adaptador ${host}`);
1249
+ console.log(` ${def.descricao}`);
1250
+ console.log(` destino padrao: <projeto>/${def.destinoPadrao}${def.subdir ? '/' + def.subdir : ''}`);
1251
+ console.log('');
1252
+ console.log((0, hosts_1.textoDosPitfalls)(host));
1253
+ return 0;
1254
+ }
1255
+ if (sub === 'install') {
1256
+ const host = (0, hosts_1.parseHost)(args.posicionais[2]);
1257
+ if (!host) {
1258
+ console.error(`host desconhecido: "${args.posicionais[2] ?? ''}". Use: ${hosts_1.ORDEM_DOS_HOSTS.join(' | ')}`);
1259
+ return 2;
1260
+ }
1261
+ const carregado = (0, manifest_1.carregarManifesto)();
1262
+ const r = (0, hosts_1.instalarAdaptador)(host, {
1263
+ projeto: carregado?.raiz ?? process.cwd(),
1264
+ dir: texto(args.opcoes.dir),
1265
+ dryRun: args.opcoes['dry-run'] === true,
1266
+ force: args.opcoes.force === true || args.opcoes.forcar === true,
1267
+ orkBin: texto(args.opcoes.ork),
1268
+ versao: VERSAO,
1269
+ });
1270
+ console.log((0, hosts_1.textoDaInstalacao)(r));
1271
+ return r.ok ? 0 : 2;
1272
+ }
1273
+ console.error(`subcomando desconhecido: adapter ${sub}`);
1274
+ return 2;
1275
+ }
1276
+ /**
1277
+ * `ork eval`: canarios de comportamento e o corpus das skills finas (bloco B4).
1278
+ *
1279
+ * Skill sem eval nao entra, e comportamento sem canario tambem nao. O comando sai diferente
1280
+ * de zero em qualquer falha, para o CI do kit poder barrar merge sem eval.
1281
+ */
1282
+ function comandoEval(args) {
1283
+ const catalogo = (0, catalogo_1.exigirCatalogo)((0, manifest_1.carregarManifesto)()?.raiz ?? process.cwd());
1284
+ const lista = (v) => {
1285
+ const t = texto(v);
1286
+ return t ? t.split(',').map((x) => x.trim()).filter(Boolean) : undefined;
1287
+ };
1288
+ const r = (0, evalrunner_1.rodarEval)({
1289
+ catalogo,
1290
+ skills: lista(args.opcoes.skill),
1291
+ canarios: lista(args.opcoes.canario) ?? lista(args.opcoes.fixture),
1292
+ soCanarios: args.opcoes['so-canarios'] === true,
1293
+ soSkills: args.opcoes['so-skills'] === true,
1294
+ });
1295
+ if (args.opcoes.json === true) {
1296
+ console.log(JSON.stringify(r, null, 2));
1297
+ }
1298
+ else {
1299
+ console.log((0, evalrunner_1.textoDoEval)(r));
1300
+ }
1301
+ return r.ok ? 0 : 1;
1302
+ }
1303
+ /**
1304
+ * `ork audit ...`: os auditores periodicos (bloco B5).
1305
+ *
1306
+ * O comando existe para ser chamado por CRON e por orquestrador sem sessao interativa:
1307
+ * e por isso que ele mora no CLI deterministico e nao numa skill. Todo subcomando sai
1308
+ * diferente de zero quando reprova, para o agendador do host perceber sem ler texto.
1309
+ */
1310
+ function comandoAudit(args) {
1311
+ const sub = args.posicionais[1] ?? 'packs';
1312
+ // `audit packs` e `audit lint` funcionam sem manifesto: sao catalogo, nao estado.
1313
+ if (sub === 'packs' || sub === 'pack') {
1314
+ const carregado = (0, manifest_1.carregarManifesto)();
1315
+ const bruto = texto(args.opcoes.estagio) ?? texto(args.opcoes.stage);
1316
+ const estagio = bruto ? (0, auditoria_1.parseEstagio)(bruto) : carregado?.manifesto.project.stage;
1317
+ if (bruto && !estagio) {
1318
+ console.error(`estagio invalido: "${bruto}". Use: nascente | crescendo | maduro`);
1319
+ return 2;
1320
+ }
1321
+ const pack = texto(args.opcoes.pack) ?? args.posicionais[2];
1322
+ if (pack) {
1323
+ const alvo = (0, auditoria_1.parsePack)(pack);
1324
+ if (!alvo) {
1325
+ console.error(`pack desconhecido: "${pack}". Use um de: ${auditoria_1.ORDEM_DOS_PACKS.join(', ')}`);
1326
+ return 2;
1327
+ }
1328
+ console.log((0, auditoria_1.textoDoPack)(alvo, estagio ?? undefined));
1329
+ return 0;
1330
+ }
1331
+ console.log(`Packs de auditoria periodica${estagio ? ` (estagio declarado do projeto: ${estagio})` : ''}`);
1332
+ console.log('');
1333
+ console.log((0, auditoria_1.tabelaDePacks)(estagio ?? undefined));
1334
+ if (estagio) {
1335
+ console.log('');
1336
+ console.log(`Ativos aqui e agora: ${(0, auditoria_1.packsAtivos)(estagio).join(', ')}`);
1337
+ console.log(`Postura: ${(0, auditoria_1.posturaDoPack)(estagio)}`);
1338
+ }
1339
+ return 0;
1340
+ }
1341
+ if (sub === 'lint') {
1342
+ const raiz = (0, manifest_1.carregarManifesto)()?.raiz;
1343
+ const templates = (0, auditoria_1.carregarTemplatesDeAuditoria)(raiz);
1344
+ const problemas = templates.flatMap((t) => (0, auditoria_1.lintTemplateDeAuditoria)(t));
1345
+ console.log(`Lint dos templates de auditoria${raiz ? ` (projeto ${raiz})` : ' (somente embutidos)'}`);
1346
+ console.log('');
1347
+ for (const p of problemas) {
1348
+ console.log(` [${p.gravidade}] ${p.template} :: ${p.regra}`);
1349
+ console.log(` ${p.detalhe}`);
1350
+ }
1351
+ if (problemas.length === 0)
1352
+ console.log(` nenhum problema em ${templates.length} template(s)`);
1353
+ console.log('');
1354
+ console.log(`templates: ${templates.length} | erros: ${problemas.filter((p) => p.gravidade === 'erro').length} | ` +
1355
+ `avisos: ${problemas.filter((p) => p.gravidade === 'aviso').length}`);
1356
+ return problemas.some((p) => p.gravidade === 'erro') ? 2 : 0;
1357
+ }
1358
+ const carregado = (0, manifest_1.exigirManifesto)();
1359
+ if (sub === 'run') {
1360
+ const pack = (0, auditoria_1.parsePack)(args.posicionais[2]);
1361
+ if (!pack) {
1362
+ console.error('uso: ork audit run <pack> [--profile P] [--since Nd]');
1363
+ console.error(` packs: ${auditoria_1.ORDEM_DOS_PACKS.join(', ')}`);
1364
+ return 2;
1365
+ }
1366
+ const autorizar = args.opcoes.agora;
1367
+ const r = (0, auditrun_1.rodarAuditoria)(carregado, pack, {
1368
+ perfil: texto(args.opcoes.profile) ?? texto(args.opcoes.perfil),
1369
+ since: texto(args.opcoes.since),
1370
+ tudo: args.opcoes.tudo === true,
1371
+ effort: texto(args.opcoes.effort),
1372
+ model: texto(args.opcoes.model),
1373
+ dryRun: args.opcoes['dry-run'] === true,
1374
+ agora: typeof autorizar === 'string' ? autorizar : undefined,
1375
+ forcar: args.opcoes.forcar === true || args.opcoes.force === true,
1376
+ });
1377
+ if (r.status === 'bloqueada') {
1378
+ console.error(`Rodada de auditoria ${r.id} BLOQUEADA.`);
1379
+ console.error(` ${auditoria_1.DESCRICAO_DO_MOTIVO_DE_AUDITORIA[r.motivo ?? 'runtime.unavailable']}`);
1380
+ console.error(` motivo tipado: ${r.motivo}`);
1381
+ console.error(` detalhe: ${r.detalhe}`);
1382
+ console.error(` estado da rodada: .orkastery/audits/${r.id}/run.json`);
1383
+ return 1;
1384
+ }
1385
+ if (r.status === 'ensaio') {
1386
+ console.log(`Simulacao (--dry-run) da rodada ${r.id}: nada foi despachado.`);
1387
+ console.log(` pack ${r.pack} (postura ${r.postura} no estagio ${r.estagio})`);
1388
+ console.log(` escopo ${r.escopo.detalhe}`);
1389
+ console.log(` graphify ${r.escopo.graphify}`);
1390
+ console.log(` custo effort ${r.custo.effort}, ${r.custo.janela.detalhe}`);
1391
+ console.log(` prompt ${r.promptPath} (sha256 ${r.promptSha256})`);
1392
+ console.log(` comando claude --bg "<prompt>" --name ${r.slug} --model ${r.custo.model} --effort ${r.custo.effort}`);
1393
+ if (r.superficie) {
1394
+ console.log(` superficie ${r.superficie.detalhe}`);
1395
+ console.log(` nada registrado no board (--dry-run). Para gravar: ork audit surface --registrar ${r.id}`);
1396
+ }
1397
+ return 0;
1398
+ }
1399
+ console.log(`Rodada de auditoria ${r.id} despachada pelo runtime adapter ${r.runtime}.`);
1400
+ console.log(` pack ${r.pack} (${auditoria_1.PACKS[r.pack].titulo})`);
1401
+ console.log(` produto ${r.produto} (perfil ${r.perfil}), estagio ${r.estagio}, postura ${r.postura}`);
1402
+ console.log(` escopo ${r.escopo.detalhe}`);
1403
+ console.log(` graphify ${r.escopo.graphify}`);
1404
+ console.log(` custo effort ${r.custo.effort}, model ${r.custo.model}`);
1405
+ console.log(` janela ${r.custo.janela.detalhe}`);
1406
+ console.log(` sessionId ${r.sessionId}`);
1407
+ console.log(` prompt ${r.promptPath} (sha256 ${r.promptSha256})`);
1408
+ console.log(` verificada no runtime: ${r.verificada ? 'sim' : 'NAO (confira `ork sessions`)'}`);
1409
+ if (r.superficie) {
1410
+ console.log(` superficie ${r.superficie.detalhe}`);
1411
+ console.log(` ${r.superficie.registrados} achado(s) de superficie ja no board de divida` +
1412
+ (r.superficie.aConfirmar > 0
1413
+ ? `, ${r.superficie.aConfirmar} com confianca baixa (pedem confirmacao humana)`
1414
+ : ''));
1415
+ }
1416
+ console.log('');
1417
+ console.log('A rodada termina em PROPOSTA para o roadmap, nunca em correcao aplicada.');
1418
+ console.log(`Depois dos achados: ork audit verify ${r.id} && ork audit report ${r.id}`);
1419
+ return r.verificada ? 0 : 1;
1420
+ }
1421
+ if (sub === 'list') {
1422
+ console.log((0, auditrun_1.tabelaDeRodadas)(carregado.raiz));
1423
+ console.log('');
1424
+ console.log(`Board de divida: ${(0, auditrun_1.resumoDoBoard)(carregado.raiz)}`);
1425
+ return 0;
1426
+ }
1427
+ if (sub === 'show') {
1428
+ const id = args.posicionais[2];
1429
+ if (!id) {
1430
+ console.error('uso: ork audit show <rodada> [--ledger]');
1431
+ return 2;
1432
+ }
1433
+ if (args.opcoes.ledger === true) {
1434
+ console.log((0, auditrun_1.tabelaDoLedgerDaRodada)(carregado.raiz, id));
1435
+ return 0;
1436
+ }
1437
+ console.log((0, auditrun_1.textoDaRodada)(carregado.raiz, id));
1438
+ return 0;
1439
+ }
1440
+ if (sub === 'prompt') {
1441
+ const pack = (0, auditoria_1.parsePack)(args.posicionais[2]);
1442
+ if (!pack) {
1443
+ console.error('uso: ork audit prompt <pack> [--since Nd]');
1444
+ console.error(` packs: ${auditoria_1.ORDEM_DOS_PACKS.join(', ')}`);
1445
+ return 2;
1446
+ }
1447
+ const { raiz, manifesto } = carregado;
1448
+ const estagio = manifesto.project.stage;
1449
+ const escopo = (0, auditoria_1.escopoDaRodada)(raiz, manifesto, {
1450
+ since: texto(args.opcoes.since),
1451
+ tudo: args.opcoes.tudo === true,
1452
+ pack,
1453
+ });
1454
+ const template = (0, auditoria_1.templateDoPack)(pack, raiz);
1455
+ const prompt = (0, auditoria_1.montarPromptDeAuditoria)({
1456
+ pack,
1457
+ produto: manifesto.project.name,
1458
+ perfil: texto(args.opcoes.profile) ?? manifesto.board.default,
1459
+ estagio,
1460
+ postura: (0, auditoria_1.posturaDoPack)(estagio),
1461
+ rodada: '<rodada ainda nao criada>',
1462
+ dirDaRodada: '.orkastery/audits/<rodada>',
1463
+ escopo,
1464
+ janela: (0, auditoria_1.janelaDeCusto)(manifesto),
1465
+ effort: texto(args.opcoes.effort) ?? manifesto.audit.effort,
1466
+ }, raiz);
1467
+ console.log(`# template ${template.id} v${template.versao} (origem: ${template.origem})`);
1468
+ console.log(`# pack ${pack}, estagio ${estagio}, sha256 ${(0, phase_1.hashDoPrompt)(prompt)}`);
1469
+ console.log('');
1470
+ console.log(prompt);
1471
+ return 0;
1472
+ }
1473
+ if (sub === 'ingest') {
1474
+ const id = args.posicionais[2];
1475
+ const arquivo = texto(args.opcoes.arquivo) ?? texto(args.opcoes.file);
1476
+ if (!id || !arquivo) {
1477
+ console.error('uso: ork audit ingest <rodada> --arquivo <achados.json>');
1478
+ return 2;
1479
+ }
1480
+ const r = (0, auditrun_1.ingerirAchados)(carregado, id, arquivo);
1481
+ console.log(`Ingestao da rodada ${r.rodada}: ${r.registrados.length} achado(s) no board de divida.`);
1482
+ // Bloco B6: cada proposta enderecada ao roadmap tambem vai para a colecao `roadmap`.
1483
+ if (r.registrados.length > 0) {
1484
+ const naMemoria = (0, memoria_1.publicarPropostas)(carregado, r.registrados);
1485
+ if (naMemoria.regime === 'orkmind') {
1486
+ console.log(`Memoria (orkmind): propostas na colecao roadmap, ${naMemoria.detalhe}.`);
1487
+ }
1488
+ }
1489
+ for (const a of r.registrados) {
1490
+ console.log((0, divida_1.textoDoAchado)(a));
1491
+ }
1492
+ if (r.duplicados.length > 0) {
1493
+ console.log('');
1494
+ console.log('Ja registrados nesta rodada, ignorados (a ingestao e idempotente): ' +
1495
+ r.duplicados.map((a) => a.id).join(', '));
1496
+ }
1497
+ if (r.recusados.length > 0) {
1498
+ console.log('');
1499
+ console.error(`RECUSADOS (${r.recusados.length}):`);
1500
+ for (const rec of r.recusados) {
1501
+ console.error(` achado #${rec.indice + 1}: ${rec.erro}`);
1502
+ }
1503
+ }
1504
+ console.log('');
1505
+ console.log(`Prove os achados antes de qualquer thread: ork audit verify ${r.rodada}`);
1506
+ return r.recusados.length > 0 ? 1 : 0;
1507
+ }
1508
+ if (sub === 'finding' || sub === 'achado') {
1509
+ const acao = args.posicionais[2];
1510
+ if (acao === 'add') {
1511
+ const id = args.posicionais[3];
1512
+ if (!id) {
1513
+ console.error('uso: ork audit finding add <rodada> --regra R --titulo T --arquivo caminho:linha --impacto I --fix F --estimativa E');
1514
+ return 2;
1515
+ }
1516
+ const verificar = texto(args.opcoes.verificar) ?? texto(args.opcoes.verify);
1517
+ const achado = (0, auditrun_1.registrarAchadoDaRodada)(carregado, id, {
1518
+ regra: texto(args.opcoes.regra),
1519
+ severidade: texto(args.opcoes.severidade) ?? texto(args.opcoes.severity),
1520
+ titulo: texto(args.opcoes.titulo),
1521
+ arquivo: texto(args.opcoes.arquivo),
1522
+ descricao: texto(args.opcoes.descricao),
1523
+ alegacao: texto(args.opcoes.alegacao) ?? texto(args.opcoes.claim),
1524
+ verificar: verificar ? [verificar] : [],
1525
+ impacto: texto(args.opcoes.impacto),
1526
+ fix: texto(args.opcoes.fix),
1527
+ irreversivel: texto(args.opcoes.irreversivel) ?? 'nenhum',
1528
+ estimativa: texto(args.opcoes.estimativa),
1529
+ });
1530
+ console.log(`Achado ${achado.id} registrado no board de divida da rodada ${id}.`);
1531
+ console.log((0, divida_1.textoDoAchado)(achado));
1532
+ const naMemoria = (0, memoria_1.publicarPropostas)(carregado, [achado]);
1533
+ if (naMemoria.regime === 'orkmind') {
1534
+ console.log(`Memoria (orkmind): proposta na colecao roadmap, ${naMemoria.detalhe}.`);
1535
+ }
1536
+ return 0;
1537
+ }
1538
+ if (acao === 'estado') {
1539
+ const id = args.posicionais[3];
1540
+ const estado = (0, divida_1.parseEstadoDeAchado)(args.posicionais[4]);
1541
+ if (!id || !estado) {
1542
+ console.error('uso: ork audit finding estado <achado-id> <aberto|adiado|resolvido|descartado>');
1543
+ return 2;
1544
+ }
1545
+ if (estado === 'virou-thread') {
1546
+ console.error('o estado `virou-thread` e carimbado pelo proprio `ork thread new --from-finding`.');
1547
+ return 2;
1548
+ }
1549
+ const achado = (0, divida_1.exigirAchado)(carregado.raiz, id);
1550
+ const atualizado = (0, divida_1.carimbarAchado)(carregado.raiz, achado, { estado });
1551
+ console.log(`Achado ${atualizado.id} agora esta ${atualizado.estado}.`);
1552
+ console.log((0, divida_1.textoDoAchado)(atualizado));
1553
+ return 0;
1554
+ }
1555
+ console.error(`subcomando desconhecido: audit finding ${acao ?? ''}`);
1556
+ return 2;
1557
+ }
1558
+ if (sub === 'verify') {
1559
+ const id = args.posicionais[2];
1560
+ if (!id) {
1561
+ console.error('uso: ork audit verify <rodada>');
1562
+ return 2;
1563
+ }
1564
+ const v = (0, auditrun_1.verificarRodada)(carregado, id);
1565
+ console.log(`Claims dos achados da rodada ${v.rodada}, reexecutadas no HEAD real.`);
1566
+ console.log(` HEAD real ${v.commit}`);
1567
+ console.log(` diretorio ${v.cwd}`);
1568
+ console.log('');
1569
+ if (v.resultados.length === 0) {
1570
+ console.log(' (nenhum achado aberto nesta rodada)');
1571
+ }
1572
+ for (const r of v.resultados) {
1573
+ console.log(` ${r.claim.id} verificado: ${r.verificado ? 'sim' : 'NAO'} ${r.claim.alegacao}`);
1574
+ console.log(` arquivo: ${r.claim.arquivo}`);
1575
+ console.log(` ${r.claim.verificar.length > 0 ? `comando(s): ${r.claim.verificar.join(' && ')}` : 'sem comando de verificacao'}`);
1576
+ if (!r.verificado)
1577
+ console.log(` motivo tipado: ${r.motivo} (${r.detalhe})`);
1578
+ }
1579
+ console.log('');
1580
+ console.log(v.ok
1581
+ ? 'Veredito: ACHADOS SUSTENTADOS (o auditor provou o que alegou).'
1582
+ : `Veredito: REPROVADO. Motivos tipados: ${v.motivos.join(', ')}`);
1583
+ if (v.motivos.includes('claims.unverifiable')) {
1584
+ console.log(' aviso: achado sem comando de verificacao avisa e nao bloqueia (regra do gate do B1).');
1585
+ }
1586
+ return v.ok ? 0 : 1;
1587
+ }
1588
+ if (sub === 'report' || sub === 'relatorio') {
1589
+ const id = args.posicionais[2];
1590
+ if (!id) {
1591
+ console.error('uso: ork audit report <rodada> [--publicar]');
1592
+ return 2;
1593
+ }
1594
+ const r = (0, auditrun_1.relatorioDaRodada)(carregado, id, { publicar: args.opcoes.publicar === true });
1595
+ console.log(r.texto);
1596
+ console.log(`(relatorio gravado em ${r.caminho})`);
1597
+ if (r.publicado)
1598
+ console.log(`(publicado em ${r.publicado})`);
1599
+ return 0;
1600
+ }
1601
+ if (sub === 'divida' || sub === 'board') {
1602
+ const bruto = texto(args.opcoes.pack);
1603
+ const pack = bruto ? (0, auditoria_1.parsePack)(bruto) : undefined;
1604
+ if (bruto && !pack) {
1605
+ console.error(`pack desconhecido: "${bruto}". Use um de: ${auditoria_1.ORDEM_DOS_PACKS.join(', ')}`);
1606
+ return 2;
1607
+ }
1608
+ console.log((0, divida_1.tabelaDaDivida)(carregado.raiz, {
1609
+ pack: pack ?? undefined,
1610
+ todos: args.opcoes.todos === true || args.opcoes.all === true,
1611
+ }));
1612
+ return 0;
1613
+ }
1614
+ // `audit surface`: a varredura deterministica da superficie de ataque de rede (SP8..SP12).
1615
+ // Ela roda sozinha dentro de `audit run security-privacy`; aqui ela e exposta para o
1616
+ // operador olhar a superficie sem despachar rodada nenhuma, e para registrar no board os
1617
+ // achados de uma rodada que rodou em `--dry-run`.
1618
+ if (sub === 'surface' || sub === 'superficie') {
1619
+ const bruta = texto(args.opcoes.regra);
1620
+ if (bruta && !superficie_1.REGRAS_DE_SUPERFICIE.includes(bruta.toUpperCase())) {
1621
+ console.error(`regra desconhecida: "${bruta}". Use uma de: ${superficie_1.REGRAS_DE_SUPERFICIE.join(', ')}`);
1622
+ return 2;
1623
+ }
1624
+ const regra = bruta ? bruta.toUpperCase() : undefined;
1625
+ const limiteBruto = texto(args.opcoes.limite);
1626
+ const limite = limiteBruto ? Number(limiteBruto) : undefined;
1627
+ if (limite !== undefined && (!Number.isFinite(limite) || limite < 1)) {
1628
+ console.error(`--limite invalido: "${limiteBruto}". Use um inteiro >= 1.`);
1629
+ return 2;
1630
+ }
1631
+ const rodadaAlvo = texto(args.opcoes.registrar);
1632
+ if (rodadaAlvo) {
1633
+ const r = (0, auditrun_1.varrerSuperficieDaRodada)(carregado, rodadaAlvo, { registrar: true, limitePorRegra: limite });
1634
+ console.log((0, superficie_1.textoDaVarredura)(r.resultado));
1635
+ console.log('');
1636
+ console.log(`Rodada ${r.rodada}: ${r.registrados.length} achado(s) registrado(s) no board de divida.`);
1637
+ for (const a of r.registrados)
1638
+ console.log(` ${a.id} ${a.regra} ${a.arquivo}:${a.linha} ${a.titulo}`);
1639
+ if (r.duplicados.length > 0) {
1640
+ console.log(` ja registrados nesta rodada: ${r.duplicados.map((a) => a.id).join(', ')}`);
1641
+ }
1642
+ for (const rec of r.recusados) {
1643
+ console.error(` RECUSADO ${rec.achado.regra} ${rec.achado.arquivo}:${rec.achado.linha}: ${rec.erro}`);
1644
+ }
1645
+ console.log('');
1646
+ console.log(`Prove os achados antes de qualquer thread: ork audit verify ${r.rodada}`);
1647
+ if (r.recusados.length > 0)
1648
+ return 1;
1649
+ return r.registrados.length > 0 ? 1 : 0;
1650
+ }
1651
+ const resultado = (0, superficie_1.varrerSuperficie)(carregado.raiz, {
1652
+ dir: args.posicionais[2],
1653
+ regra,
1654
+ limitePorRegra: limite,
1655
+ });
1656
+ if (args.opcoes.json === true) {
1657
+ console.log(JSON.stringify(resultado, null, 2));
1658
+ }
1659
+ else {
1660
+ console.log((0, superficie_1.textoDaVarredura)(resultado));
1661
+ }
1662
+ // Codigo != 0 com achado: o agendador do host percebe a superficie aberta sem ler texto.
1663
+ return resultado.achados.length > 0 ? 1 : 0;
1664
+ }
1665
+ console.error(`subcomando desconhecido: audit ${sub}`);
1666
+ return 2;
1667
+ }
1668
+ /** Roteia o comando. Devolve o codigo de saida do processo. */
1669
+ /**
1670
+ * Imprime o resultado de uma publicacao na memoria semantica (bloco B6).
1671
+ *
1672
+ * Em regime `files` ele nao imprime nada: o comando que chamou continua com a mesma saida
1673
+ * que sempre teve. E o que garante que ligar o B6 nao muda o que o builder ja conhece.
1674
+ */
1675
+ function relatarPublicacao(r) {
1676
+ if (r.regime !== 'orkmind')
1677
+ return;
1678
+ const gravados = [
1679
+ `${r.decisoes.gravadas.filter((g) => g.ok).length} decision`,
1680
+ `${r.policies.gravadas.filter((g) => g.ok).length} rule`,
1681
+ r.handoff?.ok ? '1 handoff' : '',
1682
+ r.learning?.ok ? '1 learning' : '',
1683
+ r.roadmap?.ok ? '1 roadmap' : '',
1684
+ ].filter((t) => t !== '');
1685
+ console.log('');
1686
+ console.log(`Memoria (orkmind, tenant ${r.estado.tenant}): ${gravados.join(', ') || 'nada a gravar'}.`);
1687
+ if (r.falhas > 0)
1688
+ console.log(` ${r.falhas} gravacao(oes) nao concluida(s); veja ork memory status.`);
1689
+ }
1690
+ /** `ork recall`: recuperacao tardia dos ponteiros do handoff, no momento indicado. */
1691
+ function comandoRecall(args) {
1692
+ const carregado = (0, manifest_1.exigirManifesto)();
1693
+ const id = args.posicionais[1];
1694
+ if (!id) {
1695
+ console.error('uso: ork recall <thread-id> [--fase FASE] [--id ptr-N] [--todos] [--forcar]');
1696
+ return 2;
1697
+ }
1698
+ const thread = (0, thread_1.lerThread)(carregado.raiz, id);
1699
+ const faseBruta = texto(args.opcoes.fase) ?? texto(args.opcoes.momento);
1700
+ const momento = faseBruta ? (0, thread_1.exigirFase)(thread, faseBruta) : undefined;
1701
+ const memoria = (0, memoria_1.abrirMemoria)(carregado);
1702
+ const r = (0, recall_1.recallDaThread)(carregado, memoria, id, {
1703
+ momento,
1704
+ id: texto(args.opcoes.id),
1705
+ todos: args.opcoes.todos === true,
1706
+ forcar: args.opcoes.forcar === true,
1707
+ });
1708
+ if (args.opcoes.json === true) {
1709
+ console.log(JSON.stringify(r, null, 2));
1710
+ }
1711
+ else {
1712
+ console.log((0, recall_1.textoDoRecall)(r, args.opcoes['sem-conteudo'] !== true));
1713
+ }
1714
+ // Ponteiro que deveria resolver e nao resolveu e falha, nao relatorio.
1715
+ return r.falhas.length > 0 ? 1 : 0;
1716
+ }
1717
+ /** `ork memory`: o regime, a publicacao e a busca deterministica por tag. */
1718
+ function comandoMemory(args) {
1719
+ const carregado = (0, manifest_1.exigirManifesto)();
1720
+ const sub = args.posicionais[1] ?? 'status';
1721
+ const memoria = (0, memoria_1.abrirMemoria)(carregado);
1722
+ if (sub === 'status') {
1723
+ if (args.opcoes.json === true) {
1724
+ console.log(JSON.stringify(memoria.estado, null, 2));
1725
+ return 0;
1726
+ }
1727
+ console.log((0, memoria_1.textoDoEstado)(memoria.estado));
1728
+ return 0;
1729
+ }
1730
+ if (sub === 'sync') {
1731
+ const threadId = args.posicionais[2];
1732
+ // Thread inexistente reprova aqui, e nao no meio da gravacao.
1733
+ if (threadId)
1734
+ (0, thread_1.lerThread)(carregado.raiz, threadId);
1735
+ const r = (0, memoria_1.sincronizarMemoria)(carregado, memoria, threadId ?? null);
1736
+ if (args.opcoes.json === true) {
1737
+ console.log(JSON.stringify(r, null, 2));
1738
+ }
1739
+ else {
1740
+ console.log((0, memoria_1.textoDoSync)(r));
1741
+ }
1742
+ return 0;
1743
+ }
1744
+ if (sub === 'search') {
1745
+ const tagsBrutas = texto(args.opcoes.tags);
1746
+ if (!tagsBrutas) {
1747
+ console.error('uso: ork memory search --tags \'{"project":["orkastery"],"skill":["orkastery-decision"]}\'');
1748
+ return 2;
1749
+ }
1750
+ let tags;
1751
+ try {
1752
+ tags = JSON.parse(tagsBrutas);
1753
+ }
1754
+ catch (e) {
1755
+ console.error(`--tags nao e JSON valido: ${e.message}`);
1756
+ return 2;
1757
+ }
1758
+ const colecao = texto(args.opcoes.colecao) ?? texto(args.opcoes.collection);
1759
+ const limiteBruto = texto(args.opcoes.limite);
1760
+ const entradas = memoria.buscar({
1761
+ collection: colecao,
1762
+ tags,
1763
+ limite: limiteBruto ? Number(limiteBruto) : undefined,
1764
+ });
1765
+ if (args.opcoes.json === true) {
1766
+ console.log(JSON.stringify(entradas, null, 2));
1767
+ return 0;
1768
+ }
1769
+ console.log(`Busca deterministica por tag (regime ${memoria.regime})`);
1770
+ console.log('');
1771
+ if (memoria.regime === 'files') {
1772
+ console.log(` ${memoria.estado.detalhe}`);
1773
+ console.log(` correcao: ${memoria.estado.correcao}`);
1774
+ return 0;
1775
+ }
1776
+ for (const e of entradas) {
1777
+ console.log(` [${e.collection}] ${e.id} ${e.priority}${e.mandatory ? ' [MANDATORY]' : ''}`);
1778
+ console.log(` ${e.content.split('\n')[0].slice(0, 100)}`);
1779
+ }
1780
+ console.log('');
1781
+ console.log(` ${entradas.length} entrada(s)`);
1782
+ return 0;
1783
+ }
1784
+ console.error(`subcomando desconhecido: memory ${sub}`);
1785
+ return 2;
1786
+ }
1787
+ function main(argv) {
1788
+ const args = parseArgs(argv);
1789
+ const comando = args.posicionais[0];
1790
+ if (!comando || args.opcoes.help === true || comando === 'help') {
1791
+ console.log(AJUDA);
1792
+ return 0;
1793
+ }
1794
+ if (args.opcoes.version === true || comando === 'version') {
1795
+ console.log(VERSAO);
1796
+ return 0;
1797
+ }
1798
+ switch (comando) {
1799
+ case 'doctor': {
1800
+ const r = (0, doctor_1.doctor)();
1801
+ console.log(r.texto);
1802
+ return r.codigo;
1803
+ }
1804
+ case 'init': {
1805
+ const r = (0, init_1.init)(process.cwd(), {
1806
+ force: args.opcoes.force === true,
1807
+ nome: texto(args.opcoes.name) ?? texto(args.opcoes.nome),
1808
+ abbrev: texto(args.opcoes.abbrev),
1809
+ });
1810
+ if (!r.criado) {
1811
+ console.log(`Manifesto ja existe: ${r.caminho}`);
1812
+ console.log('Nada foi sobrescrito. Use --force para regerar.');
1813
+ return 0;
1814
+ }
1815
+ console.log(`Manifesto criado: ${r.caminho}`);
1816
+ console.log(` projeto ${r.deteccao.nome} (abbrev "${r.deteccao.abbrev}")`);
1817
+ console.log(` branch base ${r.deteccao.baseBranch}`);
1818
+ console.log(` gerenciador ${r.deteccao.gerenciador}`);
1819
+ console.log(` verify ${Object.entries(r.deteccao.verify).map(([k, v]) => `${k}="${v}"`).join(', ') || '(nenhum script detectado)'}`);
1820
+ console.log('');
1821
+ console.log('Proximo passo: ork doctor');
1822
+ return 0;
1823
+ }
1824
+ case 'modos': {
1825
+ // `--do-pedido` existe para os adaptadores de host: eles extraem a #TAG do texto do
1826
+ // builder SEM reimplementar o parse, e repassam `--mode` ao `ork`. A validacao contra
1827
+ // `conduction.allowed_modes` continua sendo do nucleo, no `ork thread new`.
1828
+ const pedido = texto(args.opcoes['do-pedido']);
1829
+ if (pedido !== undefined) {
1830
+ const carregado = (0, manifest_1.carregarManifesto)();
1831
+ const extraido = (0, modos_1.extrairTagDoPedido)(pedido);
1832
+ const modo = extraido ?? carregado?.manifesto.conduction.default_mode ?? 'classic';
1833
+ if (args.opcoes.json === true) {
1834
+ console.log(JSON.stringify({
1835
+ modo,
1836
+ tag: modos_1.MODOS[modo].tag,
1837
+ daTag: extraido !== null,
1838
+ origem: extraido !== null ? 'tag no pedido' : 'conduction.default_mode',
1839
+ pausas: (0, modos_1.pausasDoModo)(modo),
1840
+ }));
1841
+ }
1842
+ else {
1843
+ console.log(modo);
1844
+ }
1845
+ return 0;
1846
+ }
1847
+ console.log((0, modos_1.tabelaDeModos)());
1848
+ return 0;
1849
+ }
1850
+ case 'thread':
1851
+ return comandoThread(args);
1852
+ case 'phase':
1853
+ return comandoPhase(args);
1854
+ case 'sessions':
1855
+ return comandoSessions(args);
1856
+ case 'claims':
1857
+ return comandoClaims(args);
1858
+ case 'verify':
1859
+ return comandoVerify(args);
1860
+ case 'gate':
1861
+ return comandoGate(args);
1862
+ case 'retry':
1863
+ return comandoRetry(args);
1864
+ case 'fix':
1865
+ return comandoFix(args);
1866
+ case 'handoff':
1867
+ return comandoHandoff(args);
1868
+ case 'recall':
1869
+ return comandoRecall(args);
1870
+ case 'memory':
1871
+ return comandoMemory(args);
1872
+ case 'ship':
1873
+ return comandoShip(args);
1874
+ case 'lease':
1875
+ return comandoLease(args);
1876
+ case 'board':
1877
+ return comandoBoard(args);
1878
+ case 'orquestracao':
1879
+ case 'monitor':
1880
+ return comandoOrquestracao(args);
1881
+ case 'worktree':
1882
+ return comandoWorktree(args);
1883
+ case 'master':
1884
+ return comandoMaster(args);
1885
+ case 'eval':
1886
+ return comandoEval(args);
1887
+ case 'audit':
1888
+ return comandoAudit(args);
1889
+ case 'adapter':
1890
+ return comandoAdapter(args);
1891
+ case 'prompt':
1892
+ return comandoPrompt(args);
1893
+ case 'ciclos':
1894
+ console.log((0, ciclos_1.tabelaDeVariantes)());
1895
+ return 0;
1896
+ default:
1897
+ console.error(`comando desconhecido: ${comando}`);
1898
+ console.log(AJUDA);
1899
+ return 2;
1900
+ }
1901
+ }
1902
+ if (require.main === module) {
1903
+ try {
1904
+ process.exitCode = main(process.argv.slice(2));
1905
+ }
1906
+ catch (e) {
1907
+ console.error(`erro: ${e.message}`);
1908
+ process.exitCode = 1;
1909
+ }
1910
+ }