@orkastery/cli 0.4.3 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/adapters/README.md +11 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +3 -1
  3. package/adapters/claude-code/README.md +11 -2
  4. package/adapters/claude-code/agents/ork-check.md +1 -1
  5. package/adapters/claude-code/agents/ork-go.md +2 -2
  6. package/adapters/claude-code/agents/ork-goal.md +1 -1
  7. package/adapters/claude-code/agents/ork-master.md +1 -1
  8. package/adapters/claude-code/agents/ork-plan.md +1 -1
  9. package/adapters/claude-code/agents/ork-ship.md +1 -1
  10. package/adapters/claude-code/commands/master.md +11 -8
  11. package/adapters/claude-code/commands/onboarding.md +3 -2
  12. package/adapters/claude-code/commands/ork.md +8 -0
  13. package/adapters/claude-code/commands/ship.md +2 -2
  14. package/adapters/codex/skills/ork/SKILL.md +12 -1
  15. package/adapters/hermes/README.md +3 -0
  16. package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
  17. package/adapters/hermes/bin/ork-brain.sh +3 -0
  18. package/adapters/hermes/bin/ork-maestro.sh +4 -1
  19. package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
  20. package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
  21. package/adapters/hermes/hermes.plugin.json +2 -0
  22. package/adapters/hermes/hitl-ingress/__init__.py +36 -3
  23. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
  24. package/adapters/openclaw/README.md +45 -2
  25. package/adapters/openclaw/dist/hitl-ingress.js +37 -3
  26. package/adapters/openclaw/dist/index.js +93 -21
  27. package/adapters/openclaw/openclaw.plugin.json +10 -1
  28. package/adapters/openclaw/package.json +2 -2
  29. package/adapters/openclaw/src/hitl-ingress.ts +32 -3
  30. package/adapters/openclaw/src/index.ts +109 -21
  31. package/assets/docs/padroes/documentacao-de-produto.md +2 -2
  32. package/assets/docs/padroes/roadmap-de-produto.md +1 -1
  33. package/assets/docs/produto/_modelo-feature.md +2 -0
  34. package/assets/orkmind_bridge.py +214 -1
  35. package/dist/adapters/claude-bg.js +24 -7
  36. package/dist/auditrun.js +1 -1
  37. package/dist/board.js +74 -0
  38. package/dist/branch-de-estado.js +5 -4
  39. package/dist/busca-semantica.js +161 -0
  40. package/dist/ci.js +141 -10
  41. package/dist/claim-lint.js +3 -1
  42. package/dist/company-brain-cli.js +27 -2
  43. package/dist/company-brain-context.js +132 -0
  44. package/dist/company-brain-dossie.js +376 -0
  45. package/dist/company-brain-mcp.js +4 -1
  46. package/dist/conducao.js +71 -18
  47. package/dist/decisao-autonoma.js +42 -0
  48. package/dist/docs.js +135 -25
  49. package/dist/doctor.js +242 -32
  50. package/dist/entrega-pr.js +116 -5
  51. package/dist/experiencia-instalacao.js +256 -0
  52. package/dist/experiencia.js +72 -0
  53. package/dist/fabrica-estado.js +63 -12
  54. package/dist/fechamento.js +105 -0
  55. package/dist/fix.js +3 -3
  56. package/dist/forja.js +435 -0
  57. package/dist/gates.js +9 -1
  58. package/dist/hitl-classificacao.js +11 -1
  59. package/dist/hitl-contract.js +50 -7
  60. package/dist/hitl-curto.js +158 -0
  61. package/dist/hitl-gates.js +67 -1
  62. package/dist/hitl-lote.js +30 -15
  63. package/dist/hitl-presentation.js +10 -7
  64. package/dist/hitl-resumo.js +57 -13
  65. package/dist/hitl-texto-livre.js +150 -0
  66. package/dist/hosts.js +92 -3
  67. package/dist/index.js +637 -45
  68. package/dist/indice-vetorial.js +317 -0
  69. package/dist/init.js +24 -5
  70. package/dist/integracoes-locais.js +3 -1
  71. package/dist/intelligence-benchmark-contract.js +570 -0
  72. package/dist/intelligence-graph-cli.js +584 -0
  73. package/dist/intelligence-graph-contract.js +636 -0
  74. package/dist/intelligence-graph-extract-md.js +487 -0
  75. package/dist/intelligence-graph-extract-ts.js +980 -0
  76. package/dist/intelligence-graph-extract.js +546 -0
  77. package/dist/intelligence-graph-index.js +693 -0
  78. package/dist/intelligence-graph-parsers.js +327 -0
  79. package/dist/intelligence-graph-query.js +344 -0
  80. package/dist/intelligence-graph-repo.js +197 -0
  81. package/dist/leases.js +100 -0
  82. package/dist/ledger.js +23 -0
  83. package/dist/licoes.js +5 -4
  84. package/dist/liveness.js +2 -1
  85. package/dist/maestro-cli.js +10 -1
  86. package/dist/maestro-contract.js +5 -1
  87. package/dist/maestro-discovery.js +16 -2
  88. package/dist/maestro-runtime.js +3 -0
  89. package/dist/maestro-snapshot.js +6 -2
  90. package/dist/manifest.js +166 -5
  91. package/dist/master-batch.js +3 -2
  92. package/dist/master-digest.js +2 -2
  93. package/dist/master-nota.js +203 -0
  94. package/dist/master.js +4 -0
  95. package/dist/mcp-artifacts.js +2 -0
  96. package/dist/mcp-experiencia.js +164 -0
  97. package/dist/mcp-git.js +64 -12
  98. package/dist/mcp-grafo-worker.js +91 -0
  99. package/dist/mcp-grafo.js +233 -0
  100. package/dist/mcp-install.js +5 -2
  101. package/dist/mcp-maestro.js +3 -2
  102. package/dist/mcp-server.js +93 -5
  103. package/dist/mcp-ship.js +2 -0
  104. package/dist/mcp-verify.js +3 -1
  105. package/dist/memoria.js +147 -1
  106. package/dist/network-roadmap.js +907 -0
  107. package/dist/ocupacao.js +43 -3
  108. package/dist/onboarding.js +122 -11
  109. package/dist/orkmind.js +165 -9
  110. package/dist/orquestracao.js +2 -1
  111. package/dist/parado-no-condutor.js +933 -0
  112. package/dist/phase.js +166 -13
  113. package/dist/policies.js +29 -2
  114. package/dist/projeto-alvo.js +551 -0
  115. package/dist/prompts.js +1 -1
  116. package/dist/prova-ativacao.js +345 -0
  117. package/dist/pulse-consentimento.js +4 -2
  118. package/dist/pulse-delivery.js +32 -6
  119. package/dist/pulse-resposta.js +674 -49
  120. package/dist/pulse.js +74 -3
  121. package/dist/retry.js +51 -8
  122. package/dist/roadmap-reservas.js +262 -20
  123. package/dist/roadmap-status.js +348 -0
  124. package/dist/runtime-context.js +5 -1
  125. package/dist/sessoes-inventario.js +7 -1
  126. package/dist/sessoes.js +4 -1
  127. package/dist/ship.js +25 -1
  128. package/dist/thread-close.js +3 -0
  129. package/dist/thread.js +21 -2
  130. package/dist/util.js +71 -4
  131. package/dist/verify.js +6 -5
  132. package/dist/worktree.js +29 -6
  133. package/eval/casos/onboarding.json +1 -1
  134. package/eval/casos/orchestration-experience-pt-br.json +48 -0
  135. package/eval/casos/orchestration-experience.json +48 -0
  136. package/package.json +1 -1
  137. package/schemas/code-artifact-graph.v1.schema.json +581 -0
  138. package/schemas/graph-benchmark.v1.schema.json +2240 -0
  139. package/schemas/maestro-snapshot.schema.json +23 -0
  140. package/skills/README.md +7 -5
  141. package/skills/core/onboarding/SKILL.md +10 -2
  142. package/skills/core/orchestration-experience/SKILL.md +113 -0
  143. package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
  144. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  145. package/skills/phases/go-implementation/SKILL.md +2 -0
  146. package/skills/phases/ship-release/SKILL.md +6 -3
package/dist/index.js CHANGED
@@ -34,12 +34,20 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  };
35
35
  })();
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.COMANDOS_COM_PROJETO_PROPRIO = void 0;
37
38
  exports.parseArgs = parseArgs;
39
+ exports.avisoRoadmapSemAssociacao = avisoRoadmapSemAssociacao;
40
+ exports.extrairOpcaoDeProjeto = extrairOpcaoDeProjeto;
38
41
  exports.main = main;
39
42
  const company_brain_cli_1 = require("./company-brain-cli");
43
+ const estado_thread_1 = require("./estado-thread");
44
+ const intelligence_graph_cli_1 = require("./intelligence-graph-cli");
40
45
  const maestro_cli_1 = require("./maestro-cli");
41
46
  const hitl_public_receipt_1 = require("./hitl-public-receipt");
42
47
  const hitl_presentation_1 = require("./hitl-presentation");
48
+ const hitl_curto_1 = require("./hitl-curto");
49
+ const roadmap_status_1 = require("./roadmap-status");
50
+ const master_nota_1 = require("./master-nota");
43
51
  const hitl_native_offer_1 = require("./hitl-native-offer");
44
52
  const hitl_ingress_receipt_1 = require("./hitl-ingress-receipt");
45
53
  const node_path_1 = require("node:path");
@@ -79,6 +87,7 @@ const pulse_1 = require("./pulse");
79
87
  const pulse_resposta_1 = require("./pulse-resposta");
80
88
  const pulse_cadencia_1 = require("./pulse-cadencia");
81
89
  const decisao_autonoma_1 = require("./decisao-autonoma");
90
+ const hitl_contract_1 = require("./hitl-contract");
82
91
  const orquestracao_1 = require("./orquestracao");
83
92
  const divida_1 = require("./divida");
84
93
  const ciclos_1 = require("./ciclos");
@@ -105,9 +114,13 @@ const master_2 = require("./master");
105
114
  const manifest_1 = require("./manifest");
106
115
  const horario_1 = require("./horario");
107
116
  const onboarding_1 = require("./onboarding");
117
+ const experiencia_1 = require("./experiencia");
118
+ const hosts_2 = require("./hosts");
108
119
  const init_2 = require("./init");
109
120
  const memoria_1 = require("./memoria");
110
121
  const orkmind_1 = require("./orkmind");
122
+ const indice_vetorial_1 = require("./indice-vetorial");
123
+ const busca_semantica_1 = require("./busca-semantica");
111
124
  const recall_1 = require("./recall");
112
125
  const memory_migration_1 = require("./memory-migration");
113
126
  const fix_1 = require("./fix");
@@ -132,6 +145,7 @@ const thread_1 = require("./thread");
132
145
  const docs_1 = require("./docs");
133
146
  const roadmap_reservas_1 = require("./roadmap-reservas");
134
147
  const fabrica_estado_1 = require("./fabrica-estado");
148
+ const network_roadmap_1 = require("./network-roadmap");
135
149
  const fabrica_publicar_1 = require("./fabrica-publicar");
136
150
  const maquina_1 = require("./maquina");
137
151
  const ledger_1 = require("./ledger");
@@ -143,6 +157,7 @@ const claim_lint_1 = require("./claim-lint");
143
157
  const licoes_1 = require("./licoes");
144
158
  const demo_1 = require("./demo");
145
159
  const entrega_pr_1 = require("./entrega-pr");
160
+ const projeto_alvo_1 = require("./projeto-alvo");
146
161
  /** A versao publicada em `@orkastery/cli`, lida do package.json (`versao.ts`). */
147
162
  // Antes de qualquer arquivo ou despacho: sem escrita de grupo nem de outros, que o sensor recusaria.
148
163
  (0, preflight_1.endurecerUmask)();
@@ -199,18 +214,27 @@ function conducaoDoCli(args) {
199
214
  }
200
215
  const AJUDA = `ork ${VERSAO}, nucleo de orquestracao do Orkastery
201
216
 
202
- Uso: ork <comando> [argumentos]
217
+ Uso: ork [--projeto <nome|caminho>] <comando> [argumentos]
218
+
219
+ --projeto <nome|caminho> Projeto-alvo de qualquer comando (RM-052): vence ORK_PROJETO, que vence o
220
+ diretorio atual; nome ambiguo ou desconhecido recusa com os candidatos (saida 4)
221
+ projetos [--json] Projetos conhecidos desta maquina (~/.orkastery/projetos.json)
222
+ projetos registrar [caminho] Registra a copia (init, thread new e fabrica entrar ja registram)
223
+ projetos esquecer <nome|caminho> Tira do registro a copia que sumiu ou sobrou (nada no disco e apagado)
203
224
 
204
225
  doctor O que vale nesta maquina agora (sai != 0 se bloqueado)
205
226
  init [--force] [--name N] [--abbrev A] Gera o orkastery.yaml do repositorio
206
227
  modos Tabela dos ${modos_1.ORDEM_DOS_MODOS.length} modos de conducao vivos por #TAG
207
228
 
208
229
  setup Pauta da entrevista #setup: runtime/modelo/esforco
230
+ por bloco de cada modo (default claude-bg/opus/high; #Fast: sonnet)
209
231
  onboarding [show|set <etapa>|reset [etapa]] Pauta e respostas do projeto (9 etapas)
210
- [--conteudo JSON] [--por Q] [--json] Valores secretos somente em ~/.hermes/.env
232
+ [--conteudo JSON] [--por Q] [--json] Segredos ficam ${onboarding_1.ONDE_FICAM_OS_SEGREDOS}
211
233
  [--reset [etapa]] Reset seletivo ou total, idempotente
212
234
  onboarding sync [--json] Publicação opcional na memória, com degradação
213
- por bloco de cada modo (default claude-bg/opus/high; #Fast: sonnet)
235
+ experiencia show [--json] Preferências efetivas; configure por onboarding set maestro --conteudo '{"owner":{"experience":true}}'
236
+ experiencia uninstall <host> [--dry-run] [--json]
237
+ Remove o bloco de Claude Code/Codex; sem --dry-run aplica a remoção
214
238
  setup <modo> Config atual de cada bloco do modo
215
239
  setup <modo> --bloco N [--runtime R] Edita o bloco (runtimes: claude-bg, codex);
216
240
  [--model M] [--effort E] [--por Q] evento setup_configured no ledger do projeto
@@ -298,13 +322,15 @@ Uso: ork <comando> [argumentos]
298
322
  verify <thread-id> [--baseline] Reexecuta claims e verify do manifesto no HEAD real
299
323
  [--so-claims] --baseline grava o estado do mundo antes do GO
300
324
  [--canal C] [--esperar [min]] So executa com a conducao da thread (sai 3 se outra conduz)
301
- ci prepare <thread-id> Exporta claims/comandos para a candidata
325
+ ci prepare <thread-id> Exporta claims/comandos para a candidata (.ork-ci/<thread>.json)
302
326
  ci run [<thread-id>] [--bundle ARQ] Executa o CHECK no runner independente
327
+ [--branch B] acha o bundle da thread pelo nome da branch (o CI usa)
303
328
  ci status [--sha SHA] [--remoto origin] Consulta o check exato publicado no GitHub
304
329
 
305
330
  gate next <thread-id> [--proximo FASE] Gate de tokens: mesma sessao ou nova sessao
306
331
  [--ocupacao 0..1] [--fonte F] [--transcript ARQ] [--janela N] [--refazer]
307
332
  gate request <thread-id> [--motivo M] Apresenta pedido HITL correlacionado à pausa
333
+ [--formato telegram|terminal] no contrato curto, com o codigo estavel para responder
308
334
  gate answer <thread-id> <pedido> Recebe envelope do ingresso humano autenticado
309
335
  --resposta-stdin --por Q --mensagem ID --origem telegram [--canal hermes|openclaw]
310
336
  [--conta ID] conta homologada do canal; obrigatoria no canal openclaw
@@ -335,17 +361,43 @@ Uso: ork <comando> [argumentos]
335
361
  [--id ptr-N] [--todos] [--forcar] momento (retrieve_when), nunca a janela inteira
336
362
  [--sem-conteudo] [--json] (orkmind por tag, files por path#ancora)
337
363
 
338
- brain status|inventory|get|query|receipts|sync|reconcile|apply|rollback|bind
339
- memory status [--json] Regime efetivo (files|orkmind), tenant e degradacao
364
+ brain status|inventory|get|query|receipts|context|dossie|sync|reconcile|apply|rollback|bind
365
+ brain dossie --thread T [--decisao ID] Dossie de decisao: vinculo, contexto citavel, alternativas,
366
+ quem decidiu e evidencia, com os ids do Brain (so leitura)
367
+ memory status [--json] [--sondar] Regime efetivo (files|orkmind), tenant, degradacao e embeddings
368
+ (--sondar: uma chamada real de embedding, com a latencia)
340
369
  memory sync [<thread-id>] [--json] Publica decisoes, policies, handoff, licao e roadmap
341
370
  memory inventory --escopo <threads> [--json] Inventaria fontes canonicas e tenants excluidos, sem gravar
342
371
  memory migrate --operadora <thread> --escopo <threads> [--dry-run] [--json] Migra handoffs por G3, com pacote integral e readback
343
372
  memory search --tags '<json>' [--colecao C] Busca deterministica por tag (mandatory sempre volta)
344
373
  [--thread ID] [--restrito] [--janela N] [--limite N] [--json]
374
+ memory search --texto "<frase>" Busca por significado (I-38): vetor + FTS por RRF no tenant,
375
+ [--modo hibrido|vetor|fts] NAO deterministica; nao combina com --tags nem --thread
376
+ [--colecao C] [--limite N] [--json]
377
+ memory index [--modelo primario|fallback|todos] Indice vetorial local do tenant (I-38), idempotente,
378
+ [--dry-run] [--json] com tokens e custo estimados; --dry-run nao chama o provider
379
+
380
+ grafo indexar [--verificar] [--forcar] Indice do grafo de codigo do HEAD limpo (RM-031 KG3) no estado do projeto:
381
+ [--json] pastas 0700, chave por revisao e extrator, idempotente; incremental (KG4)
382
+ a partir do indice ancestral, ou completo com o motivo; --forcar extrai
383
+ completo; --verificar confere contrato, bytes, determinismo e o incremental
384
+ contra a completa; precisa de typescript e micromark
385
+ grafo status [--json] Indices guardados, o do HEAD, os analisadores e o tamanho
386
+ grafo vizinhos <no> [--profundidade N] Vizinhanca de arquivo ou simbolo, com extrator e evidencia de cada aresta
387
+ [--sentido entrada|saida|ambos] [--tipo T,...] [--limite N] [--json]
388
+ grafo chamadores <simbolo> Quem chama (arestas calls que chegam) [--profundidade N] [--limite N] [--json]
389
+ grafo importadores <arquivo|simbolo> Quem importa (arestas imports que chegam) [--profundidade N] [--limite N] [--json]
390
+ grafo caminho <de> <para> Menor caminho pelas arestas [--sentido saida|entrada|ambos] [--tipo T,...] [--json]
391
+ [--json --teto-bytes N] Nas quatro consultas (KG5): JSON compacto de no maximo N bytes; as arestas mais
392
+ longe do alvo saem ate caber, e o caminho que nao cabe recusa
393
+ grafo amostra [--por-estrato N] Amostra de arestas para auditoria manual; --conferir ARQ confere a auditada
394
+ grafo limpar [--tudo] [--json] Apaga os indices que nao sao do HEAD e as sobras com mais de uma hora
345
395
 
346
396
  ship <thread-id> --para <branch> Merge --no-ff serializado por lease e push PROVADO
347
397
  ship registrar-pr <thread-id>|--todas A entrega feita por PR vira ship_done: merge ship(<thread>) na base
348
398
  [--remoto R] [--json] remota e CI verde no head do PR; depois, ork master --aceitar-omissao
399
+ [--repo <dono/nome> --pr <n>] PR mesclado em repositorio externo de ci.external_repositories
400
+ [--dry-run] Ensaio: as mesmas conferencias, sem gravar ship_done, fase nem fabrica
349
401
  [--de <branch>] [--remoto origin] [--autorizar-push <quem>] [--sem-push] [--dry-run]
350
402
 
351
403
  board [--all] [--sem-remoto] Visao unica das threads (todos os perfis com --all); com a
@@ -375,7 +427,11 @@ Uso: ork <comando> [argumentos]
375
427
  master digest <enviar|preview|responder> Digest semanal com recibos do host
376
428
  master <thread-id> --score 0-5 --justificativa "<texto>"
377
429
  [--classe C[,C]] [--resumo R] [--por Q] [--refazer]
378
- Fecha a thread: POSTMORTEM + MASTER log + score
430
+ Fecha a thread: POSTMORTEM + MASTER log + score (so do terminal;
431
+ de processo de host e recusado com master.prova-de-canal)
432
+ master pedir <thread-id> [--formato telegram|terminal|json]
433
+ Pede a nota ao dono com codigo curto; ele responde pelo Telegram
434
+ (<codigo> <0 a 5> <porque>) e a nota vai ao ledger com o recibo (RM-048)
379
435
  master [--todas] [--json] As entregas, com o indice derivado do ledger
380
436
  master --aceitar-omissao [--json] Aceita as entregues por omissao, com registro
381
437
  master classes As classes de falha fixas do POSTMORTEM
@@ -395,11 +451,17 @@ Uso: ork <comando> [argumentos]
395
451
  [--pedido "<texto>"] [--template ID]
396
452
  prompt render --exemplo --fase F --modo M Renderiza sem thread nenhuma, para revisar o texto
397
453
 
454
+ roadmap status [--json] Status report unico do roadmap: grupos com icones, #HITL no que espera
455
+ voce e o fecho com o que precisa de voce e o que vem a seguir (RM-048)
398
456
  roadmap reservas [--json] [--remoto R] Quem esta com cada item do roadmap, lido da branch ork/roadmap-reservas
457
+ [--soltar-orfas] marca a reserva de thread ja fechada (orfa) e, com a opcao, solta
458
+ ou passa para outra thread aberta do mesmo item, com registro
399
459
  roadmap pegar <RM-NNN> [--thread T] Reserva o item para esta maquina (push atomico: o primeiro vence)
400
460
  [--nota N] [--por Q] [--maquina M] maquina = --maquina, ORK_MAQUINA ou o hostname
401
461
  [--forcar --motivo M] tomar a reserva de outra maquina fica registrado
402
462
  roadmap soltar <RM-NNN> [--forcar --motivo M] Devolve o item
463
+ roadmap feat [--thread T] [--nota N] Reserva o proximo numero de FEAT na mesma branch (push atomico: duas
464
+ maquinas nunca levam o mesmo numero; numero reservado nao volta)
403
465
  fabrica [--json] [--sem-remoto] O que cada maquina conduz, lido da branch ork/fabrica-estado (I-51)
404
466
  fabrica entrar [--maquina NOME] Esta maquina entra na fabrica compartilhada deste usuario, com
405
467
  este nome (~/.orkastery/maquina.json), e publica o primeiro retrato
@@ -407,10 +469,16 @@ Uso: ork <comando> [argumentos]
407
469
  depois de entrar, sai sozinho ao criar thread, despachar fase,
408
470
  entregar e fechar, e a cada batida do pulse
409
471
  fabrica sair Para de publicar daqui e tira o retrato desta maquina da branch
410
- docs verificar [--json] Documentacao de produto e roadmap contra o codigo e o git
472
+ network roadmap [--projeto P] [--json] Roadmap, reservas e threads de cada maquina de cada projeto, de qualquer diretorio:
473
+ [--sem-remoto] fonte e hora de cada parte, lacuna tipada no que nao leu. P = caminho do clone,
474
+ github:dono/repo, gitlab:grupo/repo ou nome conhecido; sem clone, le a forja (RM-054)
475
+ docs verificar [--json] [--pr] Documentacao de produto e roadmap contra o codigo e o git; no PR (--pr),
476
+ o merge de outra thread e o indice que divergem da main so avisam
411
477
  (padrao do dono: frontmatter, leitura, paridade; sai != 0 com erro)
412
478
  docs sincronizar [--escrever] Fatos do ledger e do git para o roadmap (merge, fase) e indices;
413
479
  sem --escrever so mostra; nunca muda status por passagem de tempo
480
+ [--so RM-NNN[,RM-MMM]] [--todos] so esses itens (e os indices); na worktree de uma thread com item,
481
+ o padrao e o item dela; --todos volta a todo item (RM-037)
414
482
  docs init Cria padroes, modelos, indices e o lint de Markdown no projeto
415
483
 
416
484
  mcp serve --project RAIZ --host HOST Servidor MCP stdio deste projeto (codex|claude-code)
@@ -526,6 +594,10 @@ function comandoThread(args) {
526
594
  return 1;
527
595
  }
528
596
  const gravadaDoAchado = args.opcoes['dry-run'] !== true;
597
+ // RM-052 (D7): thread nova, projeto conhecido; o aviso nunca derruba a criacao.
598
+ const avisoDoRegistroDoAchado = gravadaDoAchado && r.thread ? (0, projeto_alvo_1.registrarProjetoEmSilencio)(carregado.raiz, 'thread new') : null;
599
+ if (avisoDoRegistroDoAchado)
600
+ console.error(avisoDoRegistroDoAchado);
529
601
  console.log(gravadaDoAchado
530
602
  ? `Thread criada a partir do achado ${r.achado.id}.`
531
603
  : 'Simulacao (--dry-run), nada foi gravado.');
@@ -567,6 +639,9 @@ function comandoThread(args) {
567
639
  console.error('uso: ork thread new <nome> --modo <MODO>');
568
640
  return 2;
569
641
  }
642
+ const avisoRoadmap = avisoRoadmapSemAssociacao(nome, texto(args.opcoes.roadmap));
643
+ if (avisoRoadmap)
644
+ console.error(avisoRoadmap);
570
645
  const brutoModo = texto(args.opcoes.modo) ?? texto(args.opcoes.mode);
571
646
  let modo;
572
647
  try {
@@ -646,20 +721,30 @@ function comandoThread(args) {
646
721
  // I-51 (RM-047): com a fabrica compartilhada, as outras maquinas veem a thread nova.
647
722
  if (gravada)
648
723
  (0, fabrica_publicar_1.publicarEmSegundoPlano)(carregado.raiz);
724
+ // RM-052 (D7): quem abre thread aqui conhece este projeto; o aviso nunca derruba a criacao.
725
+ const avisoDoRegistro = gravada ? (0, projeto_alvo_1.registrarProjetoEmSilencio)(carregado.raiz, 'thread new') : null;
726
+ if (avisoDoRegistro)
727
+ console.error(avisoDoRegistro);
649
728
  console.log(gravada ? 'Thread criada.' : 'Simulacao (--dry-run), nada foi gravado.');
650
729
  if (reservaDoItem)
651
730
  console.log(` roadmap: ${reservaDoItem.item} reservado para esta maquina (${reservaDoItem.reserva?.maquina})`);
652
731
  console.log((0, thread_1.resumoDaThread)(thread));
653
732
  console.log('');
654
733
  console.log(` slug em 3 partes: ${(0, phase_1.descreverSlug)(thread.slug)}`);
734
+ const avisoSemBase = (0, thread_1.avisoDeThreadSemBase)(thread, gravada);
655
735
  if (gravada) {
656
736
  console.log(` estado: .orkastery/threads/${thread.id}/thread.json`);
657
737
  // Bloco B6: a origem da thread e as policies do projeto vao para a memoria
658
738
  // semantica quando ela esta ligada. Em regime files nada muda nesta saida.
659
739
  relatarPublicacao((0, memoria_1.publicar)(carregado, thread.id));
660
- console.log('');
661
- console.log(`Proximo passo: ork phase run ${thread.id} ${thread.faseAtual} --prompt "<pedido>"`);
740
+ // Thread sem base nao tem fase para rodar: o proximo passo e o do aviso.
741
+ if (!avisoSemBase) {
742
+ console.log('');
743
+ console.log(`Proximo passo: ork phase run ${thread.id} ${thread.faseAtual} --prompt "<pedido>"`);
744
+ }
662
745
  }
746
+ if (avisoSemBase)
747
+ console.error(avisoSemBase);
663
748
  return 0;
664
749
  }
665
750
  if (sub === 'list' || sub === undefined) {
@@ -762,7 +847,7 @@ function comandoOnboarding(args) {
762
847
  estado = (0, onboarding_1.resetarOnboarding)(raiz, etapa, por);
763
848
  else
764
849
  estado = (0, onboarding_1.lerOnboarding)(raiz);
765
- console.log(args.opcoes.json === true ? JSON.stringify(estado, null, 2) : (0, onboarding_1.textoDaPauta)(estado));
850
+ console.log(args.opcoes.json === true ? JSON.stringify(estado, null, 2) : (0, onboarding_1.textoDaPauta)(estado, (0, manifest_1.exigirManifesto)(raiz).manifesto.owner));
766
851
  return 0;
767
852
  }
768
853
  /**
@@ -1014,6 +1099,32 @@ function comandoPhase(args) {
1014
1099
  console.log(args.opcoes.json === true && r.recusa ? JSON.stringify(r.recusa, null, 2) : r.recusa?.texto ?? r.erro);
1015
1100
  return 3;
1016
1101
  }
1102
+ // RM-037 (defeito 3): a recusa por vaga e espera, como a da conducao (codigo 3), e diz quem ocupa.
1103
+ if (r.motivo === 'concurrency.limite' && r.vaga) {
1104
+ if (args.opcoes.json === true) {
1105
+ console.log(JSON.stringify({ motivo: r.motivo, ...r.vaga }, null, 2));
1106
+ return 3;
1107
+ }
1108
+ console.log(`Despacho recusado: concurrency.limite. O projeto ja tem ${r.vaga.ocupam.length} sessao(oes) viva(s) ` +
1109
+ `em outras threads e o limite e ${r.vaga.limite} (concurrency.max_parallel_threads).`);
1110
+ for (const o of r.vaga.ocupam) {
1111
+ console.log(` ${o.thread.padEnd(20)} ${(o.fase ?? '-').padEnd(6)} ` +
1112
+ `${o.sessao ? `${o.runtime} ${o.sessao.slice(0, 8)}` : 'despacho em curso'}, desde ${(0, horario_1.localizarTextoRotulado)(o.desde)}`);
1113
+ }
1114
+ console.log(` correcao: ${r.vaga.correcao}`);
1115
+ console.log(r.dryRun ? ' ensaio (--dry-run): nada foi gravado.' : ` evento slot_refused no ledger de ${id}; nenhuma sessao aberta.`);
1116
+ return 3;
1117
+ }
1118
+ // RM-037 (S-4 do CHECK 3): a baseline que o despacho nao conseguiu gravar nao e gate reprovado.
1119
+ if (r.motivo === 'baseline.pendente') {
1120
+ if (args.opcoes.json === true) {
1121
+ console.log(JSON.stringify({ motivo: r.motivo, detalhe: r.erro }, null, 2));
1122
+ return 1;
1123
+ }
1124
+ console.error(`Despacho recusado: ${r.erro}`);
1125
+ console.error(' nenhuma sessao aberta; o ledger nao ganhou gate_blocked');
1126
+ return 1;
1127
+ }
1017
1128
  if (r.dryRun && !r.bloqueado) {
1018
1129
  console.log('Simulacao (--dry-run), nada foi despachado.');
1019
1130
  console.log(` slug da sessao : ${r.slug}`);
@@ -1136,7 +1247,7 @@ function comandoSessionsHitl(args, raiz) {
1136
1247
  function comandoSessions(args) {
1137
1248
  const sub = args.posicionais[1];
1138
1249
  const carregado = (0, manifest_1.carregarManifesto)();
1139
- const raiz = carregado?.raiz ?? process.cwd();
1250
+ const raiz = carregado?.raiz ?? (0, manifest_1.diretorioDoProjeto)();
1140
1251
  if (sub === 'watch') {
1141
1252
  const id = texto(args.opcoes.thread);
1142
1253
  if (!carregado || !id) {
@@ -1260,12 +1371,21 @@ function comandoDecisao(args) {
1260
1371
  if (separador < 1 || !['manifesto', 'ledger', 'medicao'].includes(tipo) || !referencia.trim()) {
1261
1372
  throw new Error('decisao registrar: --criterio manifesto:CHAVE, ledger:REF ou medicao:COMANDO');
1262
1373
  }
1263
- const { pedido, evento } = (0, decisao_autonoma_1.registrarDecisao)(carregado.raiz, id, {
1374
+ const entrada = {
1264
1375
  decidido: campo('decidido'), porque: campo('porque'), comoMudar: campo('como-mudar'),
1265
1376
  custoDeReverter: { agora: campo('custo-agora'), depois: campo('custo-depois') },
1266
1377
  criterio: { tipo, referencia }, quemDecidiu: campo('quem'), evidencia: campo('evidencia'),
1267
1378
  razao: texto(args.opcoes.razao), reverte: texto(args.opcoes.reverte),
1268
- });
1379
+ };
1380
+ let registro;
1381
+ // RM-037 (defeito 4): a recusa cita a flag que o dono digitou, com o tamanho e o teto reais.
1382
+ try {
1383
+ registro = (0, decisao_autonoma_1.registrarDecisao)(carregado.raiz, id, entrada);
1384
+ }
1385
+ catch (e) {
1386
+ throw new Error((0, hitl_contract_1.recusaNaSuperficie)(e.message, hitl_contract_1.CAMPOS_DA_DECISAO_NO_CLI));
1387
+ }
1388
+ const { pedido, evento } = registro;
1269
1389
  const placar = (0, decisao_autonoma_1.placarDaThread)((0, ledger_1.lerLedger)((0, thread_1.dirThread)(carregado.raiz, id))).find(f => f.fase === pedido.fase);
1270
1390
  console.log(JSON.stringify({ ok: true, pedidoId: pedido.id, eventId: evento.eventId, fase: pedido.fase, placar }));
1271
1391
  return 0;
@@ -1426,7 +1546,8 @@ function comandoVerify(args) {
1426
1546
  console.log(` ${c.nome.padEnd(10)} ${c.ok ? 'passava' : `ja falhava (codigo ${c.code})`} ${c.comando}`);
1427
1547
  }
1428
1548
  if (b.comandos.length === 0) {
1429
- console.log(' (nenhum comando em verify: no manifesto; sem baseline nao ha como separar regressao)');
1549
+ // Fatia 2 do ensaio da 0.5.0 (R5): a baseline foi gravada; o que falta e comando, nao baseline.
1550
+ console.log(' (nenhum comando em verify: no manifesto: a baseline guarda so o commit, e o verify nao tem como separar regressao de divida)');
1430
1551
  }
1431
1552
  return 0;
1432
1553
  }
@@ -1461,6 +1582,14 @@ function comandoConducao(args) {
1461
1582
  }
1462
1583
  throw new Error('uso: ork conducao status|assumir <thread-id>');
1463
1584
  }
1585
+ /** RM-048 (D1): o gate aberto no contrato curto, com o codigo estavel e o "desde" do ledger. */
1586
+ function textoDoGateCurto(raiz, pedido, canal) {
1587
+ const quando = new Date().toISOString();
1588
+ const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, pedido.thread));
1589
+ const codigo = pedido.codigo;
1590
+ const curto = (0, hitl_curto_1.montarPedidoCurto)((0, hitl_curto_1.entradaDoPedido)(pedido, (0, hitl_curto_1.desdeDoPedido)(eventos, pedido)), { quando, responder: typeof codigo === 'string' ? { tipo: 'codigo', codigo } : { tipo: 'dialogo' } });
1591
+ return (0, hitl_curto_1.textoDoPedidoCurto)(curto, canal);
1592
+ }
1464
1593
  function comandoGate(args) {
1465
1594
  const carregado = (0, manifest_1.exigirManifesto)();
1466
1595
  const sub = args.posicionais[1];
@@ -1479,7 +1608,13 @@ function comandoGate(args) {
1479
1608
  const id = args.posicionais[2];
1480
1609
  if (!id)
1481
1610
  throw new Error('gate request exige thread');
1482
- console.log(JSON.stringify((0, hitl_gates_1.abrirPedidoGate)(carregado.raiz, id, texto(args.opcoes.motivo))));
1611
+ const formato = texto(args.opcoes.formato);
1612
+ if (formato !== undefined && formato !== 'telegram' && formato !== 'terminal')
1613
+ throw new Error('gate request: --formato telegram|terminal');
1614
+ const pedido = (0, hitl_gates_1.abrirPedidoGate)(carregado.raiz, id, texto(args.opcoes.motivo));
1615
+ // RM-048 (D1): com --formato, o que sai e o pedido no contrato curto, pronto para o canal, com
1616
+ // o codigo estavel na ultima linha. Sem ele, o JSON de sempre, para quem integra.
1617
+ console.log(formato ? textoDoGateCurto(carregado.raiz, pedido, formato) : JSON.stringify(pedido));
1483
1618
  return 0;
1484
1619
  }
1485
1620
  if (sub === 'answer') {
@@ -1827,24 +1962,36 @@ function comandoShip(args) {
1827
1962
  // I-57 (RM-008): a entrega feita por PR vira ship_done, provada no remoto e no CI.
1828
1963
  const alvo = args.posicionais[2];
1829
1964
  const remoto = texto(args.opcoes.remoto);
1830
- if (!alvo && args.opcoes.todas !== true) {
1831
- console.error('uso: ork ship registrar-pr <thread-id> | --todas [--remoto R] [--json]');
1965
+ // RM-037 (defeito 5): PR mesclado em repositorio externo declarado em ci.external_repositories.
1966
+ const repo = texto(args.opcoes.repo), numeroDoPr = texto(args.opcoes.pr);
1967
+ if ((!alvo && args.opcoes.todas !== true) || (!!repo !== !!numeroDoPr) || (repo && !alvo)) {
1968
+ console.error('uso: ork ship registrar-pr <thread-id> [--repo <dono/nome> --pr <n>] | --todas [--remoto R] [--json] [--dry-run]');
1832
1969
  return 2;
1833
1970
  }
1834
- const r = alvo ? [(0, entrega_pr_1.registrarEntregaPorPr)(carregado, alvo, { remoto })] : (0, entrega_pr_1.registrarEntregasPorPr)(carregado, { remoto });
1971
+ // RM-037 (fatia 3, defeito 6): o `--dry-run` era ignorado, e o ensaio gravava o ship_done de verdade.
1972
+ const dryRun = args.opcoes['dry-run'] === true;
1973
+ const r = alvo && repo ? [(0, entrega_pr_1.registrarEntregaExternaPorPr)(carregado, alvo, { repositorio: repo, pr: Number(numeroDoPr), dryRun })]
1974
+ : alvo ? [(0, entrega_pr_1.registrarEntregaPorPr)(carregado, alvo, { remoto, dryRun })] : (0, entrega_pr_1.registrarEntregasPorPr)(carregado, { remoto, dryRun });
1835
1975
  if (args.opcoes.json === true) {
1836
1976
  console.log(JSON.stringify(r, null, 2));
1837
1977
  return r.some((x) => x.acao === 'recusada') ? 1 : 0;
1838
1978
  }
1979
+ if (dryRun)
1980
+ console.log('Ensaio (--dry-run): nada foi gravado.');
1839
1981
  if (r.length === 0)
1840
1982
  console.log('Nenhuma thread aberta com merge ship(<thread>) na base.');
1841
1983
  for (const x of r)
1842
1984
  console.log(` ${x.thread.padEnd(20)} ${x.acao.padEnd(13)} ${x.motivo}`);
1843
1985
  const registradas = r.filter((x) => x.acao === 'registrou').length;
1986
+ const registrariam = r.filter((x) => x.acao === 'registraria').length;
1844
1987
  if (registradas) {
1845
1988
  console.log('');
1846
1989
  console.log(`${registradas} entrega(s) registrada(s). Fechar pelo MASTER: ork master --aceitar-omissao (a nota humana sobrescreve).`);
1847
1990
  }
1991
+ if (registrariam) {
1992
+ console.log('');
1993
+ console.log(`${registrariam} entrega(s) seria(m) registrada(s). Para gravar, rode o mesmo comando sem --dry-run.`);
1994
+ }
1848
1995
  return r.some((x) => x.acao === 'recusada') ? 1 : 0;
1849
1996
  }
1850
1997
  const id = args.posicionais[1];
@@ -2028,9 +2175,16 @@ function comandoCi(args) {
2028
2175
  console.log(JSON.stringify(result, null, 2));
2029
2176
  return result.ok ? 0 : 1;
2030
2177
  }
2178
+ // RM-037 (rm037noite, defeito 1): o CI passa a branch e acha o `.ork-ci/<thread>.json` dela.
2179
+ const branch = texto(args.opcoes.branch);
2180
+ if (branch) {
2181
+ const result = (0, ci_1.executarCiDaBranch)(carregado, branch);
2182
+ console.log(JSON.stringify(result, null, 2));
2183
+ return result.ok ? 0 : 1;
2184
+ }
2031
2185
  const thread = args.posicionais[2];
2032
2186
  if (!thread) {
2033
- console.error('uso: ork ci run <thread-id> [--json] | ork ci run --bundle <arquivo>');
2187
+ console.error('uso: ork ci run <thread-id> [--json] | ork ci run --bundle <arquivo> | ork ci run --branch <branch>');
2034
2188
  return 2;
2035
2189
  }
2036
2190
  const result = (0, ci_1.executarCi)(carregado, thread);
@@ -2094,12 +2248,34 @@ function comandoLease(args) {
2094
2248
  console.error(`subcomando desconhecido: lease ${sub}`);
2095
2249
  return 2;
2096
2250
  }
2251
+ /**
2252
+ * RM-052: o cabecalho do board. O board le as threads DESTE projeto nesta maquina; o roadmap nunca
2253
+ * e lido aqui, e "0 threads" nunca quer dizer "roadmap vazio". As outras maquinas so entram com a
2254
+ * fabrica compartilhada e um remoto de verdade.
2255
+ */
2256
+ function consultaDoBoard(carregado, opcoes) {
2257
+ const remoto = carregado.manifesto.fabrica.remoto;
2258
+ const comFabrica = !opcoes.plano && (0, maquina_1.fabricaCompartilhada)(carregado.manifesto);
2259
+ const url = (0, projeto_alvo_1.remotoDoProjeto)(carregado.raiz, remoto);
2260
+ return (0, projeto_alvo_1.consultaDoProjeto)(carregado, {
2261
+ remoto: url,
2262
+ lido: [`${projeto_alvo_1.FORA_DA_CONSULTA.threadsDaMaquina}${opcoes.todos ? ' (todos os perfis)' : ''}`,
2263
+ ...(comFabrica && url !== null ? [`outras máquinas (ork/fabrica-estado em ${remoto})`] : [])],
2264
+ naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.roadmap, projeto_alvo_1.FORA_DA_CONSULTA.reservas,
2265
+ ...(url === null ? [(0, projeto_alvo_1.semRemoto)(remoto)] : comFabrica ? [] : [projeto_alvo_1.FORA_DA_CONSULTA.outrasMaquinas])],
2266
+ });
2267
+ }
2097
2268
  function comandoBoard(args) {
2098
2269
  const carregado = (0, manifest_1.exigirManifesto)();
2099
2270
  const sub = args.posicionais[1];
2271
+ const todos = args.opcoes.all === true || args.opcoes.todos === true;
2100
2272
  if (sub === 'plan' || sub === 'plano') {
2101
2273
  const plano = (0, board_1.planejar)(carregado);
2102
- console.log(args.opcoes.json === true ? JSON.stringify(plano, null, 2) : (0, board_1.textoDoPlano)(plano));
2274
+ const consulta = consultaDoBoard(carregado, { plano: true, todos: false });
2275
+ if (args.opcoes.json === true)
2276
+ console.log(JSON.stringify({ ...plano, consulta }, null, 2));
2277
+ else
2278
+ console.log([...(0, projeto_alvo_1.linhasDaConsulta)(consulta), '', (0, board_1.textoDoPlano)(plano)].join('\n'));
2103
2279
  return 0;
2104
2280
  }
2105
2281
  if (sub === 'reap') {
@@ -2115,21 +2291,31 @@ function comandoBoard(args) {
2115
2291
  console.error('uso: ork board [list|plan|reap] [--all] [--por <quem>] [--json]');
2116
2292
  return 2;
2117
2293
  }
2118
- const todos = args.opcoes.all === true || args.opcoes.todos === true;
2294
+ const consulta = consultaDoBoard(carregado, { plano: false, todos });
2119
2295
  if (args.opcoes.json === true) {
2120
- console.log(JSON.stringify((0, board_1.threadsDeTodosOsPerfis)(carregado, todos), null, 2));
2296
+ // RM-052 (D6): objeto com o cabecalho; a lista de threads continua inteira em `threads`.
2297
+ console.log(JSON.stringify({ contrato: CONTRATO_DO_BOARD, consulta, threads: (0, board_1.threadsDeTodosOsPerfis)(carregado, todos) }, null, 2));
2121
2298
  return 0;
2122
2299
  }
2300
+ console.log([...(0, projeto_alvo_1.linhasDaConsulta)(consulta), ''].join('\n'));
2123
2301
  console.log((0, board_1.textoDoBoard)(carregado, todos));
2124
2302
  // I-51 (RM-047): com a fabrica compartilhada, o board mostra tambem as outras maquinas.
2125
2303
  if ((0, maquina_1.fabricaCompartilhada)(carregado.manifesto)) {
2126
- const painel = (0, fabrica_estado_1.lerFabrica)(carregado.raiz, { remoto: carregado.manifesto.fabrica.remoto,
2127
- semRemoto: args.opcoes['sem-remoto'] === true });
2128
2304
  console.log('');
2129
- console.log((0, fabrica_estado_1.textoDasOutrasMaquinas)(painel, (0, maquina_1.nomeDaMaquina)()));
2305
+ // RM-052: sem o remoto, nada foi lido; dizer "nenhuma publicou" seria a frase do incidente de 29/09.
2306
+ if (consulta.projeto.remoto === null) {
2307
+ console.log(`Outras maquinas: o projeto ${carregado.manifesto.project.name} nao tem o remoto ${carregado.manifesto.fabrica.remoto}; nada foi lido de ork/fabrica-estado.`);
2308
+ }
2309
+ else {
2310
+ const painel = (0, fabrica_estado_1.lerFabrica)(carregado.raiz, { remoto: carregado.manifesto.fabrica.remoto,
2311
+ semRemoto: args.opcoes['sem-remoto'] === true });
2312
+ console.log((0, fabrica_estado_1.textoDasOutrasMaquinas)(painel, (0, maquina_1.nomeDaMaquina)()));
2313
+ }
2130
2314
  }
2131
2315
  return 0;
2132
2316
  }
2317
+ /** RM-052 (D6): `ork board --json` deixou de ser lista para carregar o cabecalho da consulta. */
2318
+ const CONTRATO_DO_BOARD = 'ork.board/v1';
2133
2319
  /**
2134
2320
  * I-51 (RM-047): `ork fabrica` mostra o que cada maquina conduz; `ork fabrica publicar` grava o
2135
2321
  * retrato desta maquina na branch `ork/fabrica-estado`. O `--silencioso` e o da publicacao em
@@ -2173,6 +2359,10 @@ function comandoFabrica(args) {
2173
2359
  const config = (0, maquina_1.gravarConfigDaMaquina)({ nome: texto(args.opcoes.maquina) ?? (0, maquina_1.lerConfigDaMaquina)()?.nome ?? (0, maquina_1.nomeDaMaquina)(),
2174
2360
  fabricaCompartilhada: true });
2175
2361
  const r = (0, fabrica_estado_1.publicarMaquina)(carregado, { remoto, forcar: true });
2362
+ // RM-052 (D7): a maquina que entra na fabrica deste projeto passa a conhece-lo pelo nome.
2363
+ const avisoDoRegistro = (0, projeto_alvo_1.registrarProjetoEmSilencio)(carregado.raiz, 'fabrica entrar');
2364
+ if (avisoDoRegistro)
2365
+ console.error(avisoDoRegistro);
2176
2366
  console.log(`Fabrica: esta maquina entrou como ${config.nome}; publica ao criar thread, despachar fase, entregar e fechar,`);
2177
2367
  console.log(` e a cada batida do pulse. Primeiro retrato: ${r.threads} thread(s) em ork/fabrica-estado (${r.commit?.slice(0, 7)}).`);
2178
2368
  if (process.env.ORK_MAQUINA && process.env.ORK_MAQUINA.trim() !== config.nome) {
@@ -2195,10 +2385,82 @@ function comandoFabrica(args) {
2195
2385
  console.error('uso: ork fabrica [--json] [--sem-remoto] | fabrica publicar [--forcar] [--json] | fabrica entrar [--maquina NOME] | fabrica sair');
2196
2386
  return 2;
2197
2387
  }
2198
- const painel = (0, fabrica_estado_1.lerFabrica)(carregado.raiz, { remoto, semRemoto: args.opcoes['sem-remoto'] === true });
2199
- console.log(args.opcoes.json === true ? JSON.stringify(painel, null, 2) : (0, fabrica_estado_1.textoDaFabrica)(painel, (0, maquina_1.nomeDaMaquina)()));
2388
+ // RM-052: a fabrica le a branch de UM projeto, no remoto dele; o cabecalho diz qual e o que ficou de fora.
2389
+ const url = (0, projeto_alvo_1.remotoDoProjeto)(carregado.raiz, remoto);
2390
+ const painel = url === null ? { maquinas: [], atualizado: false, ponta: null }
2391
+ : (0, fabrica_estado_1.lerFabrica)(carregado.raiz, { remoto, semRemoto: args.opcoes['sem-remoto'] === true });
2392
+ const consulta = (0, projeto_alvo_1.consultaDoProjeto)(carregado, {
2393
+ remoto: url,
2394
+ lido: url === null ? [] : [`ork/fabrica-estado em ${remoto} (${painel.atualizado ? 'lido agora' : 'última cópia local'})`],
2395
+ naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.roadmap, projeto_alvo_1.FORA_DA_CONSULTA.reservas, ...(url === null ? [(0, projeto_alvo_1.semRemoto)(remoto)] : [])],
2396
+ });
2397
+ if (args.opcoes.json === true) {
2398
+ console.log(JSON.stringify({ ...painel, consulta }, null, 2));
2399
+ return 0;
2400
+ }
2401
+ console.log([...(0, projeto_alvo_1.linhasDaConsulta)(consulta), ''].join('\n'));
2402
+ console.log(url === null
2403
+ ? `Fabrica: o projeto ${carregado.manifesto.project.name} nao tem o remoto ${remoto}; nada foi lido de ork/fabrica-estado.`
2404
+ : (0, fabrica_estado_1.textoDaFabrica)(painel, (0, maquina_1.nomeDaMaquina)()));
2200
2405
  return 0;
2201
2406
  }
2407
+ /**
2408
+ * RM-052: `ork projetos` lista o registro desta maquina (`~/.orkastery/projetos.json`); `registrar`
2409
+ * poe uma copia que ja existia antes do registro (init, thread new e fabrica entrar ja registram) e
2410
+ * `esquecer` tira a copia que sumiu ou sobrou. Sem segredo: so nome, abbrev, raiz e remoto redigido.
2411
+ */
2412
+ function comandoProjetos(args, projeto) {
2413
+ const sub = args.posicionais[1] ?? 'list';
2414
+ if (sub === 'list' || sub === 'listar') {
2415
+ const projetos = (0, projeto_alvo_1.listarProjetos)();
2416
+ if (args.opcoes.json === true) {
2417
+ console.log(JSON.stringify({ contrato: projeto_alvo_1.CONTRATO_PROJETOS, arquivo: (0, projeto_alvo_1.caminhoDoRegistro)(), projetos }, null, 2));
2418
+ return 0;
2419
+ }
2420
+ console.log(`Projetos conhecidos desta maquina (${(0, projeto_alvo_1.raizParaExibir)((0, projeto_alvo_1.caminhoDoRegistro)())})`);
2421
+ console.log('');
2422
+ if (projetos.length === 0) {
2423
+ console.log(' Nenhum ainda. ork init, ork thread new e ork fabrica entrar registram; ou: ork projetos registrar <caminho>');
2424
+ return 0;
2425
+ }
2426
+ console.log((0, util_1.tabela)(['NOME', 'ABBREV', 'RAIZ', 'REMOTO', 'NO DISCO', 'ATUALIZADO'], projetos.map((p) => [
2427
+ p.nome, p.abbrev || '-', (0, projeto_alvo_1.raizParaExibir)(p.raiz), p.remoto ?? 'sem remoto', p.presente ? 'sim' : 'ausente',
2428
+ (0, horario_1.formatarDataHora)(p.atualizadoEm)
2429
+ ])));
2430
+ console.log('');
2431
+ console.log('Use --projeto <nome> em qualquer comando (ORK_PROJETO vale para o shell inteiro). ' + (0, horario_1.legendaDoFuso)());
2432
+ return 0;
2433
+ }
2434
+ if (sub === 'registrar') {
2435
+ const caminho = args.posicionais[2];
2436
+ if (caminho !== undefined && projeto !== undefined)
2437
+ throw new Error('uso: ork projetos registrar [caminho] (um caminho ou --projeto, não os dois)');
2438
+ const alvo = caminho === undefined ? (0, projeto_alvo_1.resolverProjetoAlvo)({ opcao: projeto ?? null }) : null;
2439
+ const p = (0, projeto_alvo_1.registrarProjeto)(caminho ?? alvo?.raiz ?? process.cwd(), 'projetos registrar');
2440
+ if (args.opcoes.json === true) {
2441
+ console.log(JSON.stringify(p, null, 2));
2442
+ return 0;
2443
+ }
2444
+ console.log(`Projeto ${p.nome} (${p.abbrev || '-'}) registrado: ${(0, projeto_alvo_1.raizParaExibir)(p.raiz)} · ${p.remoto ?? 'sem remoto'}`);
2445
+ return 0;
2446
+ }
2447
+ if (sub === 'esquecer') {
2448
+ const alvo = args.posicionais[2] ?? projeto;
2449
+ if (!alvo)
2450
+ throw new Error('uso: ork projetos esquecer <nome|caminho>');
2451
+ const sairam = (0, projeto_alvo_1.esquecerProjeto)(alvo);
2452
+ if (args.opcoes.json === true) {
2453
+ console.log(JSON.stringify(sairam, null, 2));
2454
+ return 0;
2455
+ }
2456
+ for (const p of sairam)
2457
+ console.log(`Projeto ${p.nome} esquecido: ${(0, projeto_alvo_1.raizParaExibir)(p.raiz)} (nada no disco foi apagado)`);
2458
+ return 0;
2459
+ }
2460
+ console.error(`subcomando desconhecido: projetos ${sub}`);
2461
+ console.error('uso: ork projetos [--json] | projetos registrar [caminho] | projetos esquecer <nome|caminho>');
2462
+ return 2;
2463
+ }
2202
2464
  /**
2203
2465
  * `ork orquestracao status` (alias `ork monitor`): pausas e impedimentos de uma chamada.
2204
2466
  *
@@ -2314,9 +2576,20 @@ function comandoMaster(args) {
2314
2576
  console.log(JSON.stringify(r, null, 2));
2315
2577
  return r.ok ? 0 : 1;
2316
2578
  }
2579
+ if (primeiro === 'pedir') {
2580
+ // RM-048 (item 8): a nota com prova. O canal mostra a linha; o dono responde pelo Telegram.
2581
+ const id = args.posicionais[2];
2582
+ const formato = texto(args.opcoes.formato) ?? 'telegram';
2583
+ if (!id || !['telegram', 'terminal', 'json'].includes(formato))
2584
+ throw new Error('uso: ork master pedir <thread> [--formato telegram|terminal|json]');
2585
+ const pedido = (0, master_nota_1.pedirNota)(carregado.raiz, id, { codigosEmUso: (0, pulse_resposta_1.codigosEmUso)(carregado.raiz) });
2586
+ console.log(formato === 'json' ? JSON.stringify(pedido, null, 2) : (0, master_nota_1.textoDoPedidoDeNota)(carregado.raiz, pedido, formato));
2587
+ return 0;
2588
+ }
2317
2589
  if (primeiro === 'digest') {
2318
2590
  const sub = args.posicionais[2];
2319
2591
  if (sub === 'responder') {
2592
+ (0, master_nota_1.exigirNotaSemHost)();
2320
2593
  console.log(JSON.stringify((0, master_digest_1.responderLoteDigest)(carregado.raiz, texto(args.opcoes.resposta) ?? '', texto(args.opcoes.por) ?? '').map(r => ({ thread: r.thread.id, score: r.masterLog.score })), null, 2));
2321
2594
  return 0;
2322
2595
  }
@@ -2339,6 +2612,7 @@ function comandoMaster(args) {
2339
2612
  return 0;
2340
2613
  }
2341
2614
  if (primeiro === 'ratificar' || ((args.opcoes.batch === true || primeiro === 'batch') && args.opcoes.aceitar)) {
2615
+ (0, master_nota_1.exigirNotaSemHost)();
2342
2616
  let selecao;
2343
2617
  if (primeiro === 'ratificar') {
2344
2618
  const partes = (texto(args.opcoes.resposta) ?? '').trim().split(/\s+/);
@@ -2434,6 +2708,8 @@ function comandoMaster(args) {
2434
2708
  console.log(JSON.stringify((0, master_1.proporMaster)(carregado.raiz, id, opcoesMaster), null, 2));
2435
2709
  return 0;
2436
2710
  }
2711
+ // RM-048 (D8): nota em nome de pessoa, de processo de host, so pelo ingresso autenticado.
2712
+ (0, master_nota_1.exigirNotaSemHost)();
2437
2713
  const r = (0, master_2.registrarMaster)(carregado.raiz, id, opcoesMaster);
2438
2714
  console.log((0, master_2.textoDoMaster)(r));
2439
2715
  // Bloco B6: fechada a thread, a licao (POSTMORTEM + score) vai para a colecao
@@ -2478,13 +2754,47 @@ function comandoRoadmap(args) {
2478
2754
  const sub = args.posicionais[1] ?? 'reservas';
2479
2755
  const remoto = texto(args.opcoes.remoto);
2480
2756
  if (sub === 'reservas') {
2757
+ // RM-037 (rm037noite, defeito 3): a reserva de thread ja fechada aparece como orfa e sai com registro.
2758
+ if (args.opcoes['soltar-orfas'] === true) {
2759
+ const soltas = (0, roadmap_reservas_1.soltarReservasOrfas)(carregado.raiz, { remoto });
2760
+ if (args.opcoes.json === true)
2761
+ console.log(JSON.stringify(soltas, null, 2));
2762
+ else
2763
+ console.log(soltas.length === 0 ? 'Nenhuma reserva órfã desta máquina.'
2764
+ : soltas.map((s) => `${s.item}: ${s.detalhe} (thread fechada ${s.thread})`).join('\n'));
2765
+ return 0;
2766
+ }
2481
2767
  const painel = (0, roadmap_reservas_1.listarReservas)(carregado.raiz, { remoto });
2482
- console.log(args.opcoes.json === true ? JSON.stringify(painel, null, 2) : (0, roadmap_reservas_1.textoDasReservas)(painel));
2768
+ const orfas = (0, roadmap_reservas_1.reservasOrfas)(carregado.raiz, painel.reservas);
2769
+ console.log(args.opcoes.json === true ? JSON.stringify({ ...painel, orfas }, null, 2) : (0, roadmap_reservas_1.textoDasReservas)(painel, orfas));
2770
+ return 0;
2771
+ }
2772
+ if (sub === 'status') {
2773
+ // RM-048 (item 7): o status report unico do roadmap. Os canais chamam isto e transportam o texto.
2774
+ // RM-052: com o projeto consultado e o que ficou de fora (as outras maquinas nao sao lidas aqui).
2775
+ const consulta = (0, projeto_alvo_1.consultaDoProjeto)(carregado, { lido: ['roadmap (docs/roadmap)', projeto_alvo_1.FORA_DA_CONSULTA.threadsDaMaquina],
2776
+ naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.reservas, 'threads de outras máquinas (ork network roadmap)'] });
2777
+ const status = (0, roadmap_status_1.montarStatusDoRoadmap)(carregado.raiz, { projeto: carregado.manifesto.project.name, consulta });
2778
+ console.log(args.opcoes.json === true ? JSON.stringify(status, null, 2) : (0, roadmap_status_1.textoDoStatusDoRoadmap)(status));
2779
+ return 0;
2780
+ }
2781
+ // RM-037 (rm037noite, defeito 6): o numero da FEAT nova sai da mesma branch de reservas.
2782
+ if (sub === 'feat') {
2783
+ const r = (0, roadmap_reservas_1.reservarFeat)(carregado.raiz, { remoto, por: texto(args.opcoes.por), maquina: texto(args.opcoes.maquina),
2784
+ thread: texto(args.opcoes.thread) ?? null, nota: texto(args.opcoes.nota) ?? null });
2785
+ if (args.opcoes.json === true)
2786
+ console.log(JSON.stringify(r, null, 2));
2787
+ else {
2788
+ console.log(`${r.feat}: reservado para esta maquina${r.reserva.thread ? `, thread ${r.reserva.thread}` : ''}.`);
2789
+ console.log(` crie docs/produto/${r.feat}-<assunto>.md; o numero nao volta, mesmo que a feature nao saia`);
2790
+ console.log(` branch ork/roadmap-reservas em ${r.commit.slice(0, 7)}`);
2791
+ }
2483
2792
  return 0;
2484
2793
  }
2485
2794
  const item = args.posicionais[2];
2486
2795
  if ((sub !== 'pegar' && sub !== 'soltar') || !item) {
2487
- console.error('uso: ork roadmap reservas | pegar <RM-NNN> [--thread T] [--nota N] | soltar <RM-NNN> [--forcar --motivo M]');
2796
+ console.error('uso: ork roadmap status [--json] | reservas [--soltar-orfas] | pegar <RM-NNN> [--thread T] [--nota N] | ' +
2797
+ 'soltar <RM-NNN> [--forcar --motivo M] | feat [--thread T] [--nota N]');
2488
2798
  return 2;
2489
2799
  }
2490
2800
  const opcoes = {
@@ -2510,13 +2820,39 @@ function comandoRoadmap(args) {
2510
2820
  console.log(` branch ork/roadmap-reservas em ${r.commit.slice(0, 7)}`);
2511
2821
  return 0;
2512
2822
  }
2823
+ /**
2824
+ * RM-054 (fatia 1): `ork network roadmap`, o roadmap da rede de qualquer diretorio. Pedido de projeto
2825
+ * ambiguo ou desconhecido e resposta, nao erro: a recusa com os candidatos, e o codigo da RM-052.
2826
+ */
2827
+ function comandoNetwork(args) {
2828
+ const pedido = texto(args.opcoes.projeto);
2829
+ if (args.posicionais[1] !== 'roadmap' || args.posicionais.length > 2 || (args.opcoes.projeto !== undefined && !pedido)) {
2830
+ console.error('uso: ork network roadmap [--projeto <caminho|github:dono/repo|gitlab:grupo/repo|nome>] [--json] [--sem-remoto]');
2831
+ return 2;
2832
+ }
2833
+ try {
2834
+ // RM-054 (fatia 2, D-G4 e D-G6): o host que declara nao ter cwd de projeto (RM-052, D3) pede por
2835
+ // nome ou pela forja, e o projeto do diretorio dele so entra pelo registro.
2836
+ const host = (process.env[projeto_alvo_1.ENV_PROJETO_EXPLICITO] ?? '').trim() === '1';
2837
+ const p = (0, network_roadmap_1.montarPanoramaDaRede)({ pedido, semRemoto: args.opcoes['sem-remoto'] === true, host });
2838
+ console.log(args.opcoes.json === true ? JSON.stringify(p, null, 2) : (0, network_roadmap_1.textoDoPanoramaDaRede)(p));
2839
+ return p.projetos.length ? 0 : 2;
2840
+ }
2841
+ catch (e) {
2842
+ if (!(e instanceof network_roadmap_1.ErroDoPedidoDeProjeto))
2843
+ throw e;
2844
+ console.log(args.opcoes.json === true ? JSON.stringify(e.recusa, null, 2) : e.texto);
2845
+ return network_roadmap_1.SAIDA_DO_PEDIDO;
2846
+ }
2847
+ }
2513
2848
  function comandoDocs(args) {
2514
2849
  const sub = args.posicionais[1] ?? 'verificar';
2515
2850
  const carregado = (0, manifest_1.carregarManifesto)();
2516
- const raiz = carregado?.raiz ?? process.cwd();
2851
+ const raiz = carregado?.raiz ?? (0, manifest_1.diretorioDoProjeto)();
2517
2852
  const baseBranch = carregado?.manifesto.worktree?.base_branch ?? 'main';
2518
2853
  if (sub === 'verificar') {
2519
- const { docs, achados } = (0, docs_1.verificarDocs)(raiz, { baseBranch, ajudaDoCli: AJUDA });
2854
+ // RM-037 (fatia 3, GO-FIX 2): o CI passa --pr no pull_request; no push da main as duas regras novas reprovam.
2855
+ const { docs, achados } = (0, docs_1.verificarDocs)(raiz, { baseBranch, ajudaDoCli: AJUDA, pr: args.opcoes.pr === true });
2520
2856
  if (args.opcoes.json === true) {
2521
2857
  console.log(JSON.stringify({ paginas: docs.length, erros: achados.filter((a) => a.gravidade === 'erro').length,
2522
2858
  achados }, null, 2));
@@ -2528,8 +2864,36 @@ function comandoDocs(args) {
2528
2864
  }
2529
2865
  if (sub === 'sincronizar') {
2530
2866
  const escrever = args.opcoes.escrever === true;
2531
- const r = (0, docs_1.sincronizarDocs)(raiz, { baseBranch, escrever });
2532
- console.log(args.opcoes.json === true ? JSON.stringify(r, null, 2) : (0, docs_1.textoDaSincronizacao)(r, escrever));
2867
+ // RM-037 (rm037noite, defeito 5): o escopo. `--so` diz os itens; sem ele, na worktree de uma thread
2868
+ // com item, so o item dela; `--todos` (ou fora de worktree de thread) volta a todo item.
2869
+ // Sugestao 4 do CHECK 1 (e 8 do CHECK 2, `--so=`): `--so` sem item e erro de uso, nunca o escopo
2870
+ // padrao em silencio.
2871
+ if (args.opcoes.so === true || (typeof args.opcoes.so === 'string' && !args.opcoes.so.trim())) {
2872
+ console.error('uso: ork docs sincronizar --so RM-NNN[,RM-MMM] (faltou o item depois de --so)');
2873
+ return 2;
2874
+ }
2875
+ const so = texto(args.opcoes.so);
2876
+ let itens;
2877
+ let escopo = 'todo item do roadmap';
2878
+ if (so) {
2879
+ itens = so.split(',').map((i) => i.trim().toUpperCase()).filter(Boolean);
2880
+ const fora = itens.filter((i) => !/^RM-\d{3}$/.test(i));
2881
+ if (fora.length || itens.length === 0) {
2882
+ console.error(`uso: ork docs sincronizar --so RM-NNN[,RM-MMM] (recebido: ${so})`);
2883
+ return 2;
2884
+ }
2885
+ escopo = `so ${itens.join(', ')} (--so)`;
2886
+ }
2887
+ else if (args.opcoes.todos !== true) {
2888
+ const padrao = (0, docs_1.escopoPadraoDoSync)(raiz);
2889
+ if (padrao.itens) {
2890
+ itens = padrao.itens;
2891
+ escopo = `so ${itens.join(', ')}, o item da thread ${padrao.thread} desta worktree (--todos para todo item)`;
2892
+ }
2893
+ }
2894
+ const r = (0, docs_1.sincronizarDocs)(raiz, { baseBranch, escrever, itens });
2895
+ console.log(args.opcoes.json === true ? JSON.stringify({ ...r, escopo: itens ?? null }, null, 2)
2896
+ : `Escopo: ${escopo}.\n${(0, docs_1.textoDaSincronizacao)(r, escrever)}`);
2533
2897
  return 0;
2534
2898
  }
2535
2899
  if (sub === 'init') {
@@ -2540,7 +2904,7 @@ function comandoDocs(args) {
2540
2904
  'Proximo passo: copie docs/produto/_modelo-feature.md e docs/roadmap/_modelo-item.md, e rode ork docs verificar'].join('\n'));
2541
2905
  return 0;
2542
2906
  }
2543
- console.error(`uso: ork docs verificar [--json] | sincronizar [--escrever] | init`);
2907
+ console.error(`uso: ork docs verificar [--json] [--pr] | sincronizar [--escrever] [--so RM-NNN] [--todos] | init`);
2544
2908
  return 2;
2545
2909
  }
2546
2910
  function comandoPrompt(args) {
@@ -2645,7 +3009,7 @@ function comandoAdapter(args) {
2645
3009
  }
2646
3010
  const carregado = (0, manifest_1.carregarManifesto)();
2647
3011
  const r = (0, hosts_1.instalarAdaptador)(host, {
2648
- projeto: carregado?.raiz ?? process.cwd(),
3012
+ projeto: carregado?.raiz ?? (0, manifest_1.diretorioDoProjeto)(),
2649
3013
  dir: texto(args.opcoes.dir),
2650
3014
  dryRun: args.opcoes['dry-run'] === true,
2651
3015
  force: args.opcoes.force === true || args.opcoes.forcar === true,
@@ -2669,7 +3033,7 @@ function comandoAdapter(args) {
2669
3033
  * de zero em qualquer falha, para o CI do kit poder barrar merge sem eval.
2670
3034
  */
2671
3035
  function comandoEval(args) {
2672
- const catalogo = (0, catalogo_1.exigirCatalogo)((0, manifest_1.carregarManifesto)()?.raiz ?? process.cwd());
3036
+ const catalogo = (0, catalogo_1.exigirCatalogo)((0, manifest_1.carregarManifesto)()?.raiz ?? (0, manifest_1.diretorioDoProjeto)());
2673
3037
  const lista = (v) => {
2674
3038
  const t = texto(v);
2675
3039
  return t ? t.split(',').map((x) => x.trim()).filter(Boolean) : undefined;
@@ -3161,7 +3525,12 @@ function comandoMemory(args) {
3161
3525
  if (sub === 'sync' && args.posicionais[2])
3162
3526
  (0, escopo_escrita_1.validarDiretorioDeThread)(carregado.raiz, args.posicionais[2]);
3163
3527
  if (sub === 'status') {
3164
- const memoria = (0, memoria_1.abrirMemoria)(candidate);
3528
+ const memoria = (0, memoria_1.abrirMemoria)(candidate, { embeddings: 'detalhado' });
3529
+ // I-38 (D7): --sondar faz UMA chamada real pelo caminho ativo e mede a latencia.
3530
+ if (args.opcoes.sondar === true && memoria.ativo && memoria.estado.embeddings) {
3531
+ const driver = new orkmind_1.DriverCliOrkMind((0, orkmind_1.configDoManifesto)(carregado.manifesto));
3532
+ memoria.estado.embeddings.sonda = (0, memoria_1.sondarEmbeddings)(carregado.manifesto, memoria.estado.embeddings, (p, o) => driver.embeddar(p, o), (0, orkmind_1.configDoManifesto)(carregado.manifesto).timeoutMs);
3533
+ }
3165
3534
  if (args.opcoes.json === true) {
3166
3535
  console.log(JSON.stringify({ ...memoria.estado, configSource: memoria.configSource, configDivergent: memoria.configDivergent }, null, 2));
3167
3536
  return 0;
@@ -3207,6 +3576,8 @@ function comandoMemory(args) {
3207
3576
  }
3208
3577
  return r.estado.pedido === 'orkmind' && r.falhas > 0 ? 1 : 0;
3209
3578
  }
3579
+ if (sub === 'search' && args.opcoes.texto !== undefined)
3580
+ return buscaPorTexto(args, carregado);
3210
3581
  if (sub === 'search') {
3211
3582
  const threadId = texto(args.opcoes.thread);
3212
3583
  if ((args.opcoes.restrito !== undefined || args.opcoes.thread !== undefined ||
@@ -3261,15 +3632,175 @@ function comandoMemory(args) {
3261
3632
  console.log(` ${entradas.length} entrada(s)`);
3262
3633
  return 0;
3263
3634
  }
3635
+ if (sub === 'index') {
3636
+ const modelo = texto(args.opcoes.modelo) ?? 'primario';
3637
+ if (!['primario', 'fallback', 'todos'].includes(modelo)) {
3638
+ console.error('uso: ork memory index [--modelo primario|fallback|todos] [--dry-run] [--json]');
3639
+ return 2;
3640
+ }
3641
+ const memoria = (0, memoria_1.abrirMemoria)(carregado);
3642
+ if (!memoria.ativo) {
3643
+ const falha = { motivo: memoria.estado.motivo, detalhe: memoria.estado.detalhe, correcao: memoria.estado.correcao };
3644
+ if (args.opcoes.json === true)
3645
+ console.log(JSON.stringify(falha, null, 2));
3646
+ else
3647
+ console.error(`memory.index: regime ${memoria.regime} (${memoria.estado.motivo}); ${memoria.estado.correcao}`);
3648
+ return 1;
3649
+ }
3650
+ const config = (0, manifest_1.configDeEmbedding)(carregado.manifesto);
3651
+ const driver = (0, orkmind_1.configDoManifesto)(carregado.manifesto);
3652
+ const embedder = new orkmind_1.DriverCliOrkMind(driver);
3653
+ const universo = (0, indice_vetorial_1.universoDoTenant)(memoria, memoria.estado.tenant);
3654
+ const alvos = modelo === 'todos' ? ['primario', 'fallback'] : [modelo];
3655
+ const resultados = alvos.map(alvo => (0, indice_vetorial_1.indexar)({ raiz: carregado.raiz, tenant: memoria.estado.tenant,
3656
+ dsn: driver.dsn, config, alvo, universo, dryRun: args.opcoes['dry-run'] === true,
3657
+ chavePresente: !!config.api_key_env && (0, orkmind_1.chaveDeEmbeddingAceita)((process.env[config.api_key_env] ?? '').trim(), driver.dsn),
3658
+ chaveRecusada: !!config.api_key_env && (process.env[config.api_key_env] ?? '').trim() !== '' &&
3659
+ !(0, orkmind_1.chaveDeEmbeddingAceita)((process.env[config.api_key_env] ?? '').trim(), driver.dsn),
3660
+ embeddar: (p, o) => embedder.embeddar(p, o) }));
3661
+ if (args.opcoes.json === true) {
3662
+ console.log(JSON.stringify(modelo === 'todos' ? { alvo: 'todos', resultados } : resultados[0], null, 2));
3663
+ }
3664
+ else {
3665
+ for (const r of resultados)
3666
+ console.log(textoDoIndice(r));
3667
+ }
3668
+ return resultados.some(r => !r.dryRun && r.motivo) ? 1 : 0;
3669
+ }
3264
3670
  console.error(`subcomando desconhecido: memory ${sub}`);
3265
3671
  return 2;
3266
3672
  }
3267
- function main(argv) {
3268
- // I-35: todo horário para pessoa sai no fuso do dono deste projeto (lido só se for preciso).
3673
+ /** Aviso informativo: não consulta rede, não reserva e não bloqueia criação. */
3674
+ function avisoRoadmapSemAssociacao(nome, roadmap) {
3675
+ const item = /\bRM-\d{3}\b/i.exec(nome)?.[0].toUpperCase();
3676
+ if (!item || roadmap)
3677
+ return null;
3678
+ return `Aviso: ${item} no nome não associa a thread ao roadmap. No terminal, consulte ork roadmap reservas e ork fabrica; para associar e reservar, use --roadmap ${item} em ork thread new. Nenhuma reserva foi criada por este aviso.`;
3679
+ }
3680
+ /**
3681
+ * `ork memory search --texto` (I-38 D7): busca por significado, separada da busca por tag.
3682
+ * Nao combina com --tags nem com a leitura restrita por thread nesta versao (erro tipado).
3683
+ */
3684
+ function buscaPorTexto(args, carregado) {
3685
+ const frase = texto(args.opcoes.texto);
3686
+ if (args.opcoes.tags !== undefined || args.opcoes.thread !== undefined || args.opcoes.restrito !== undefined ||
3687
+ args.opcoes.janela !== undefined) {
3688
+ console.error('memory.search.texto-exclusivo: --texto nao combina com --tags, --thread, --restrito nem --janela');
3689
+ return 2;
3690
+ }
3691
+ const modo = (texto(args.opcoes.modo) ?? 'hibrido');
3692
+ const colecao = texto(args.opcoes.colecao) ?? texto(args.opcoes.collection);
3693
+ const limiteBruto = texto(args.opcoes.limite);
3694
+ const limite = limiteBruto === undefined ? busca_semantica_1.LIMITE_PADRAO_DA_BUSCA : Number(limiteBruto);
3695
+ if (!(0, orkmind_1.textoDeBuscaValido)(frase) || !busca_semantica_1.MODOS_DE_BUSCA.includes(modo) ||
3696
+ (colecao !== undefined && !orkmind_1.COLECOES_DO_ORK.includes(colecao)) ||
3697
+ !Number.isInteger(limite) || limite < 1 || limite > busca_semantica_1.LIMITE_MAXIMO_DA_BUSCA) {
3698
+ console.error(`uso: ork memory search --texto "<frase>" [--modo ${busca_semantica_1.MODOS_DE_BUSCA.join('|')}] [--colecao ${orkmind_1.COLECOES_DO_ORK.join('|')}] [--limite 1..${busca_semantica_1.LIMITE_MAXIMO_DA_BUSCA}] [--json]`);
3699
+ return 2;
3700
+ }
3701
+ const memoria = (0, memoria_1.abrirMemoria)(carregado);
3702
+ const config = (0, manifest_1.configDeEmbedding)(carregado.manifesto);
3703
+ let r;
3704
+ if (!memoria.ativo) {
3705
+ r = { texto: frase, modo, origem: 'nenhum', modeloUsado: null, deterministico: false, motivo: memoria.estado.motivo,
3706
+ detalhe: `${memoria.estado.detalhe}; correcao: ${memoria.estado.correcao}`, resultados: [], listas: { vetor: [], fts: [] } };
3707
+ }
3708
+ else {
3709
+ const driver = (0, orkmind_1.configDoManifesto)(carregado.manifesto);
3710
+ const transporte = new orkmind_1.DriverCliOrkMind(driver);
3711
+ const fallback = memoria.estado.embeddings?.fallback;
3712
+ r = (0, busca_semantica_1.buscarPorSignificado)({ raiz: carregado.raiz, tenant: memoria.estado.tenant, dsn: driver.dsn, config,
3713
+ universo: (0, indice_vetorial_1.universoDoTenant)(memoria, memoria.estado.tenant, colecao ? [colecao] : orkmind_1.COLECOES_DO_ORK),
3714
+ texto: frase, modo, limite, timeoutMs: driver.timeoutMs,
3715
+ chavePresente: memoria.estado.embeddings?.chavePresente === true,
3716
+ fallbackUsavel: memoria.estado.embeddings?.sondado === true && fallback?.dependencias === true,
3717
+ embeddar: (p, o) => transporte.embeddar(p, o), buscarTexto: (t, q) => transporte.buscarTexto(t, q) });
3718
+ }
3719
+ if (args.opcoes.json === true) {
3720
+ console.log(JSON.stringify(r, null, 2));
3721
+ return 0;
3722
+ }
3723
+ console.log(`Busca por significado (NAO deterministica; modo ${r.modo}, origem ${r.origem}${r.modeloUsado ? ` ${r.modeloUsado}` : ''})`);
3724
+ if (r.motivo)
3725
+ console.log(` motivo: ${r.motivo}${r.detalhe ? `; ${r.detalhe}` : ''}`);
3726
+ console.log('');
3727
+ r.resultados.forEach((e, i) => {
3728
+ const sim = e.similaridade === null ? '' : ` similaridade ${e.similaridade}`;
3729
+ console.log(` ${i + 1}. [${e.collection}] ${e.id} score ${e.score} ${e.fontes.join('+')}${sim}`);
3730
+ console.log(` ${e.resumo}`);
3731
+ });
3732
+ console.log('');
3733
+ console.log(` ${r.resultados.length} resultado(s); busca por tag continua em ork memory search --tags`);
3734
+ return 0;
3735
+ }
3736
+ /** Texto de `ork memory index`: o que foi (ou seria) embedado e quanto custa estimado. */
3737
+ function textoDoIndice(r) {
3738
+ const custo = r.custoEstimadoUsd === null ? 'nao estimado' : `US$ ${r.custoEstimadoUsd.toFixed(8)}`;
3739
+ return [
3740
+ `Indice vetorial (${r.alvo}${r.dryRun ? ', --dry-run' : ''}): ${r.modelo ?? '(sem modelo)'}${r.dim ? ` / ${r.dim} dim` : ''}`,
3741
+ ` universo do tenant ${r.universo} entrada(s); coerentes ${r.coerentes}`,
3742
+ ` embedados ${r.embedados} (reescritos ${r.reescritos}); removidos ${r.removidos}`,
3743
+ ` fora do indice ${r.recusados} recusada(s) por padrao de segredo, ${r.foraDoLimite} acima do limite`,
3744
+ ...(r.truncados ? [` truncados ${r.truncados} acima do contexto do modelo local, embedados pelo comeco`] : []),
3745
+ ` estimativa ${r.tokensEstimados} token(s), ${custo}; chamadas ao provider ${r.chamadasAoProvider}`,
3746
+ ...(r.arquivo ? [` arquivo ${r.arquivo}`] : []),
3747
+ ...(r.motivo ? [` motivo ${r.motivo}: ${r.detalhe}`] : r.detalhe ? [` ${r.detalhe}`] : []),
3748
+ ].join('\n');
3749
+ }
3750
+ /**
3751
+ * RM-052: `--projeto <nome|caminho>` e opcao GLOBAL. Sai do argv em qualquer posicao, antes de
3752
+ * qualquer despacho (inclusive do `maestro`, que tem parse proprio), e so aparece uma vez.
3753
+ */
3754
+ function extrairOpcaoDeProjeto(argv) {
3755
+ const resto = [];
3756
+ let projeto;
3757
+ for (let i = 0; i < argv.length; i++) {
3758
+ const a = argv[i];
3759
+ if (a !== '--projeto' && !a.startsWith('--projeto=')) {
3760
+ resto.push(a);
3761
+ continue;
3762
+ }
3763
+ if (projeto !== undefined)
3764
+ throw new Error('uso: --projeto <nome|caminho> aparece uma vez só');
3765
+ if (a !== '--projeto') {
3766
+ projeto = a.slice('--projeto='.length);
3767
+ continue;
3768
+ }
3769
+ const valor = argv[i + 1];
3770
+ projeto = valor !== undefined && !valor.startsWith('--') ? valor : '';
3771
+ if (projeto)
3772
+ i++;
3773
+ }
3774
+ return { argv: resto, projeto };
3775
+ }
3776
+ /** Comandos que nao leem projeto: o alvo nao e resolvido (nem recusado) para eles. */
3777
+ const COMANDOS_SEM_PROJETO = new Set(['demo', 'ciclos', 'mcp', 'init', 'projetos']);
3778
+ /**
3779
+ * Comandos cujo `--projeto` e DELES (RM-054: `ork network roadmap --projeto github:dono/repo`, que
3780
+ * le varios projetos). A opcao volta intacta ao argv do subcomando e o alvo global nao e resolvido:
3781
+ * nem `--projeto`, nem `ORK_PROJETO`, nem o modo host escolhem um projeto por eles.
3782
+ */
3783
+ exports.COMANDOS_COM_PROJETO_PROPRIO = new Set(['network']);
3784
+ /** Resolve e fixa o projeto-alvo do processo (D2, D3). `null`: vale o cwd de sempre. */
3785
+ function fixarAlvoDoProcesso(projeto) {
3786
+ const alvo = (0, projeto_alvo_1.resolverProjetoAlvo)({ opcao: projeto ?? null });
3787
+ (0, projeto_alvo_1.fixarProjetoAlvo)(alvo);
3788
+ return alvo;
3789
+ }
3790
+ function main(argvBruto) {
3791
+ // I-35: todo horário para pessoa sai no fuso do dono deste projeto (lido só se for preciso, e já
3792
+ // depois de o projeto-alvo abaixo estar fixado: a fonte é preguiçosa).
3269
3793
  (0, horario_1.registrarFonteDoFuso)(() => (0, horario_1.fusoDoManifesto)((0, manifest_1.carregarManifesto)()));
3794
+ // RM-052: sem alvo herdado de uma chamada anterior no mesmo processo (os testes chamam `main` em serie).
3795
+ (0, projeto_alvo_1.fixarProjetoAlvo)(null);
3796
+ const extraida = extrairOpcaoDeProjeto(argvBruto);
3797
+ const proprio = exports.COMANDOS_COM_PROJETO_PROPRIO.has(parseArgs(extraida.argv).posicionais[0] ?? '');
3798
+ const argv = proprio && extraida.projeto !== undefined
3799
+ ? [...extraida.argv, ...(extraida.projeto ? ['--projeto', extraida.projeto] : ['--projeto'])] : extraida.argv;
3800
+ const projeto = proprio ? undefined : extraida.projeto;
3270
3801
  // Helper fixo do host confiável: o projeto vem da instalação, nunca de toolargs.
3271
3802
  if (argv[0] === 'receipt-verifiers') {
3272
- if (argv.length !== 2 || argv[1] !== '--json')
3803
+ if (argv.length !== 2 || argv[1] !== '--json' || projeto !== undefined)
3273
3804
  throw Error('uso: ork receipt-verifiers --json');
3274
3805
  const root = process.env.ORK_HITL_ROOT;
3275
3806
  const privateKey = Object.keys(process.env).some(name => /^ORK_HITL_(?:INGRESS_KEY|NATIVE_KEY)/.test(name));
@@ -3285,8 +3816,14 @@ function main(argv) {
3285
3816
  console.log((0, hitl_public_receipt_1.publicHitlVerifiers)() ?? 'null');
3286
3817
  return 0;
3287
3818
  }
3288
- if (argv[0] === 'maestro')
3289
- return (0, maestro_cli_1.runMaestroCli)(argv.slice(1));
3819
+ if (argv[0] === 'maestro') {
3820
+ if (argv.length === 2 && argv[1] === '--help')
3821
+ return (0, maestro_cli_1.runMaestroCli)(argv.slice(1));
3822
+ // RM-052: o alvo explicito vira SELECAO entre as raizes permitidas; sem ele, o cwd de sempre.
3823
+ const alvo = fixarAlvoDoProcesso(projeto);
3824
+ return alvo ? (0, maestro_cli_1.runMaestroCli)(argv.slice(1), alvo.raiz, { allowedRoots: [alvo.raiz], selected: alvo.raiz })
3825
+ : (0, maestro_cli_1.runMaestroCli)(argv.slice(1));
3826
+ }
3290
3827
  const args = parseArgs(argv);
3291
3828
  const comando = args.posicionais[0];
3292
3829
  // `ork --version` tambem chega sem comando: a versao e conferida antes da ajuda.
@@ -3298,6 +3835,14 @@ function main(argv) {
3298
3835
  console.log(AJUDA);
3299
3836
  return 0;
3300
3837
  }
3838
+ if (!COMANDOS_SEM_PROJETO.has(comando) && !proprio)
3839
+ fixarAlvoDoProcesso(projeto);
3840
+ else if (projeto !== undefined && comando !== 'projetos') {
3841
+ throw new Error(comando === 'init'
3842
+ ? 'uso: ork init cria o projeto no diretório atual; entre nele e rode ork init, sem --projeto'
3843
+ : comando === 'mcp' ? 'uso: o servidor MCP recebe a raiz por --project <raiz absoluta>, não por --projeto'
3844
+ : `uso: ork ${comando} não lê projeto; tire --projeto`);
3845
+ }
3301
3846
  const nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)();
3302
3847
  const ambienteManifesto = (0, manifest_1.carregarManifesto)();
3303
3848
  if (ambienteManifesto?.manifesto.runtime.provider_policy === 'subscription-only') {
@@ -3347,11 +3892,11 @@ function main(argv) {
3347
3892
  if (args.posicionais.length !== 1 || !bruto ||
3348
3893
  Object.keys(args.opcoes).some(k => k !== 'modo') || argv.filter(a => a === '--modo' || a.startsWith('--modo=')).length !== 1)
3349
3894
  throw Error(`uso: ork doctor --modo ${modos_1.ORDEM_DOS_MODOS.join('|')}`);
3350
- const r = (0, preflight_1.preflight)(process.cwd(), (0, modos_1.exigirModoVivo)(bruto), nomesHerdados);
3895
+ const r = (0, preflight_1.preflight)((0, manifest_1.diretorioDoProjeto)(), (0, modos_1.exigirModoVivo)(bruto), nomesHerdados);
3351
3896
  console.log((0, preflight_1.textoPreflight)(r));
3352
3897
  return r.prontoPrimeiroBloco ? 0 : 1;
3353
3898
  }
3354
- const r = (0, doctor_1.doctor)(process.cwd(), nomesHerdados);
3899
+ const r = (0, doctor_1.doctor)((0, manifest_1.diretorioDoProjeto)(), nomesHerdados);
3355
3900
  console.log(r.texto);
3356
3901
  return r.codigo;
3357
3902
  }
@@ -3363,6 +3908,10 @@ function main(argv) {
3363
3908
  });
3364
3909
  const carregado = (0, manifest_1.exigirManifesto)(r.deteccao.raiz);
3365
3910
  const agents = (0, agents_md_1.atualizarAgentsMd)(r.deteccao.raiz, carregado.manifesto);
3911
+ // RM-052 (D7): o projeto entra no registro desta maquina; falha vira aviso, nunca derruba o init.
3912
+ const avisoDoRegistro = (0, projeto_alvo_1.registrarProjetoEmSilencio)(r.deteccao.raiz, 'init');
3913
+ if (avisoDoRegistro)
3914
+ console.error(avisoDoRegistro);
3366
3915
  if (!r.criado) {
3367
3916
  console.log(`Manifesto ja existe: ${r.caminho}`);
3368
3917
  console.log('Nada foi sobrescrito. Use --force para regerar.');
@@ -3375,6 +3924,9 @@ function main(argv) {
3375
3924
  console.log(` gerenciador ${r.deteccao.gerenciador}`);
3376
3925
  console.log(` verify ${Object.entries(r.deteccao.verify).map(([k, v]) => `${k}="${v}"`).join(', ') || '(nenhum script detectado)'}`);
3377
3926
  console.log(` AGENTS.md ${agents.estado}: ${agents.caminho}`);
3927
+ // Fatia 2 do ensaio da 0.5.0 (P3): o estado fica fora do git por um `.gitignore` proprio.
3928
+ if (r.estadoIgnorado)
3929
+ console.log(` estado ${manifest_1.DIR_ESTADO}/ fora do git (${manifest_1.DIR_ESTADO}/.gitignore com *; o seu .gitignore fica como está)`);
3378
3930
  console.log('');
3379
3931
  console.log(init_2.PROXIMO_PASSO_INIT);
3380
3932
  return 0;
@@ -3430,6 +3982,32 @@ function main(argv) {
3430
3982
  return comandoAccounts(args);
3431
3983
  case 'onboarding':
3432
3984
  return comandoOnboarding(args);
3985
+ case 'experiencia': {
3986
+ if (args.posicionais[1] === 'uninstall') {
3987
+ const host = (0, hosts_1.parseHost)(args.posicionais[2]);
3988
+ if (!host || !['claude-code', 'codex'].includes(host) || args.posicionais.length !== 3 ||
3989
+ Object.keys(args.opcoes).some(k => !['dry-run', 'json'].includes(k)) ||
3990
+ Object.values(args.opcoes).some(v => v !== true))
3991
+ throw Error('uso: ork experiencia uninstall claude-code|codex [--dry-run] [--json]');
3992
+ const r = (0, hosts_2.desinstalarExperiencia)((0, manifest_1.exigirManifesto)().raiz, host, args.opcoes['dry-run'] === true);
3993
+ console.log(args.opcoes.json ? JSON.stringify(r, null, 2) :
3994
+ `${r.dryRun ? 'Simulação de remoção' : 'Remoção concluída'}: ${r.arquivos.length} arquivo(s). O adaptador permanece instalado. Para manter o pacote desativado, configure owner.experience:false no onboarding.`);
3995
+ return 0;
3996
+ }
3997
+ if ((args.posicionais[1] ?? 'show') !== 'show' || args.posicionais.length > 2 ||
3998
+ Object.keys(args.opcoes).some(k => k !== 'json') || ('json' in args.opcoes && args.opcoes.json !== true)) {
3999
+ throw Error('uso: ork experiencia show [--json]');
4000
+ }
4001
+ const manifesto = (0, manifest_1.exigirManifesto)(), p = (0, experiencia_1.resolverExperiencia)(manifesto.manifesto.owner);
4002
+ // Preferência inválida vale o padrão e faz o adapter install pular o pacote: a consulta avisa.
4003
+ const avisos = manifesto.avisos.filter(a => a.startsWith('experiencia.config.invalid'));
4004
+ console.log(args.opcoes.json ? JSON.stringify({ ...p, avisos }, null, 2) :
4005
+ `Experiência ${p.experience ? 'ativa' : 'desativada'}: ${p.language}, ${p.timezone}, profundidade ${p.depth}.\nSkill: ${p.skill}\n` +
4006
+ // Fatia 2 do ensaio da 0.5.0 (R2): as origens em texto, e nao o JSON cru.
4007
+ `Origens: ${Object.entries(p.origem).map(([chave, origem]) => `${chave} ${origem}`).join(', ')}` +
4008
+ avisos.map(a => `\nAviso: ${a}; o adapter install pula o pacote até ork onboarding set maestro corrigir.`).join(''));
4009
+ return 0;
4010
+ }
3433
4011
  case 'thread':
3434
4012
  return comandoThread(args);
3435
4013
  case 'objective':
@@ -3494,6 +4072,11 @@ function main(argv) {
3494
4072
  }
3495
4073
  case 'memory':
3496
4074
  return comandoMemory(args);
4075
+ case 'grafo': {
4076
+ // RM-031 KG3 (D7): o argv cru depois do comando; o parser do grafo e estrito.
4077
+ const carregado = (0, manifest_1.exigirManifesto)();
4078
+ return (0, intelligence_graph_cli_1.executarGrafo)(argv.slice(argv.indexOf('grafo') + 1), { raiz: carregado.raiz, estado: (0, estado_thread_1.raizDoEstado)(carregado.raiz), repositorio: carregado.manifesto.project.name, escrever: (texto) => console.log(texto) });
4079
+ }
3497
4080
  case 'ship':
3498
4081
  return comandoShip(args);
3499
4082
  case 'activation':
@@ -3530,6 +4113,10 @@ function main(argv) {
3530
4113
  }
3531
4114
  case 'fabrica':
3532
4115
  return comandoFabrica(args);
4116
+ case 'projetos':
4117
+ return comandoProjetos(args, projeto);
4118
+ case 'network':
4119
+ return comandoNetwork(args);
3533
4120
  case 'licoes':
3534
4121
  return comandoLicoes(args);
3535
4122
  case 'ciclos':
@@ -3551,6 +4138,11 @@ if (require.main === module) {
3551
4138
  console.log(process.argv.includes('--json') ? JSON.stringify(e.recusa, null, 2) : e.recusa.texto);
3552
4139
  process.exitCode = 3;
3553
4140
  }
4141
+ else if (e instanceof projeto_alvo_1.ErroDeProjeto) {
4142
+ // RM-052 (D3): a recusa de projeto-alvo e a resposta (a escolha, os candidatos), nao um stack trace.
4143
+ console.log(process.argv.includes('--json') ? JSON.stringify(e.recusa, null, 2) : e.texto);
4144
+ process.exitCode = projeto_alvo_1.SAIDA_DE_PROJETO;
4145
+ }
3554
4146
  else {
3555
4147
  console.error(`erro: ${e.message}`);
3556
4148
  process.exitCode = 1;