@orkastery/cli 0.4.3 → 0.5.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 (121) 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/agents/ork-check.md +1 -1
  4. package/adapters/claude-code/agents/ork-go.md +2 -2
  5. package/adapters/claude-code/agents/ork-goal.md +1 -1
  6. package/adapters/claude-code/agents/ork-master.md +1 -1
  7. package/adapters/claude-code/agents/ork-plan.md +1 -1
  8. package/adapters/claude-code/agents/ork-ship.md +1 -1
  9. package/adapters/claude-code/commands/master.md +11 -8
  10. package/adapters/claude-code/commands/ork.md +8 -0
  11. package/adapters/claude-code/commands/ship.md +2 -2
  12. package/adapters/codex/skills/ork/SKILL.md +12 -1
  13. package/adapters/hermes/README.md +3 -0
  14. package/adapters/hermes/bin/ork-abrir-thread.sh +17 -2
  15. package/adapters/hermes/bin/ork-brain.sh +3 -0
  16. package/adapters/hermes/bin/ork-maestro.sh +4 -1
  17. package/adapters/hermes/bin/ork-network-roadmap.sh +11 -0
  18. package/adapters/hermes/bin/ork-roadmap-status.sh +9 -0
  19. package/adapters/hermes/hermes.plugin.json +2 -0
  20. package/adapters/hermes/hitl-ingress/__init__.py +36 -3
  21. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +19 -20
  22. package/adapters/openclaw/README.md +34 -2
  23. package/adapters/openclaw/dist/hitl-ingress.js +37 -3
  24. package/adapters/openclaw/dist/index.js +92 -20
  25. package/adapters/openclaw/openclaw.plugin.json +10 -1
  26. package/adapters/openclaw/package.json +2 -2
  27. package/adapters/openclaw/src/hitl-ingress.ts +32 -3
  28. package/adapters/openclaw/src/index.ts +108 -20
  29. package/assets/docs/padroes/documentacao-de-produto.md +2 -2
  30. package/assets/docs/padroes/roadmap-de-produto.md +1 -1
  31. package/assets/docs/produto/_modelo-feature.md +2 -0
  32. package/assets/orkmind_bridge.py +214 -1
  33. package/dist/adapters/claude-bg.js +6 -3
  34. package/dist/board.js +74 -0
  35. package/dist/branch-de-estado.js +5 -4
  36. package/dist/busca-semantica.js +161 -0
  37. package/dist/ci.js +141 -10
  38. package/dist/company-brain-cli.js +27 -2
  39. package/dist/company-brain-context.js +132 -0
  40. package/dist/company-brain-dossie.js +376 -0
  41. package/dist/company-brain-mcp.js +4 -1
  42. package/dist/conducao.js +71 -18
  43. package/dist/decisao-autonoma.js +42 -0
  44. package/dist/docs.js +64 -22
  45. package/dist/doctor.js +33 -0
  46. package/dist/entrega-pr.js +109 -5
  47. package/dist/experiencia-instalacao.js +256 -0
  48. package/dist/experiencia.js +72 -0
  49. package/dist/fabrica-estado.js +43 -10
  50. package/dist/fechamento.js +105 -0
  51. package/dist/forja.js +435 -0
  52. package/dist/gates.js +9 -1
  53. package/dist/hitl-classificacao.js +11 -1
  54. package/dist/hitl-contract.js +50 -7
  55. package/dist/hitl-curto.js +158 -0
  56. package/dist/hitl-gates.js +67 -1
  57. package/dist/hitl-lote.js +30 -15
  58. package/dist/hitl-presentation.js +10 -7
  59. package/dist/hitl-resumo.js +33 -12
  60. package/dist/hitl-texto-livre.js +150 -0
  61. package/dist/hosts.js +86 -1
  62. package/dist/index.js +602 -38
  63. package/dist/indice-vetorial.js +317 -0
  64. package/dist/init.js +13 -0
  65. package/dist/integracoes-locais.js +1 -1
  66. package/dist/intelligence-benchmark-contract.js +570 -0
  67. package/dist/intelligence-graph-cli.js +430 -0
  68. package/dist/intelligence-graph-contract.js +577 -0
  69. package/dist/intelligence-graph-extract-md.js +469 -0
  70. package/dist/intelligence-graph-extract-ts.js +810 -0
  71. package/dist/intelligence-graph-extract.js +369 -0
  72. package/dist/intelligence-graph-index.js +512 -0
  73. package/dist/intelligence-graph-parsers.js +327 -0
  74. package/dist/intelligence-graph-query.js +344 -0
  75. package/dist/intelligence-graph-repo.js +187 -0
  76. package/dist/leases.js +84 -0
  77. package/dist/ledger.js +14 -0
  78. package/dist/maestro-cli.js +10 -1
  79. package/dist/maestro-contract.js +5 -1
  80. package/dist/maestro-discovery.js +16 -2
  81. package/dist/maestro-snapshot.js +6 -2
  82. package/dist/manifest.js +142 -5
  83. package/dist/master-batch.js +3 -2
  84. package/dist/master-digest.js +2 -2
  85. package/dist/master-nota.js +203 -0
  86. package/dist/master.js +4 -0
  87. package/dist/mcp-experiencia.js +164 -0
  88. package/dist/mcp-git.js +4 -0
  89. package/dist/mcp-install.js +3 -1
  90. package/dist/mcp-maestro.js +3 -2
  91. package/dist/mcp-server.js +84 -5
  92. package/dist/memoria.js +147 -1
  93. package/dist/network-roadmap.js +907 -0
  94. package/dist/ocupacao.js +38 -2
  95. package/dist/onboarding.js +113 -7
  96. package/dist/orkmind.js +165 -9
  97. package/dist/phase.js +166 -13
  98. package/dist/policies.js +2 -0
  99. package/dist/projeto-alvo.js +551 -0
  100. package/dist/prompts.js +1 -1
  101. package/dist/pulse-consentimento.js +4 -2
  102. package/dist/pulse-delivery.js +5 -0
  103. package/dist/pulse-resposta.js +674 -49
  104. package/dist/pulse.js +21 -0
  105. package/dist/retry.js +51 -8
  106. package/dist/roadmap-reservas.js +262 -20
  107. package/dist/roadmap-status.js +213 -0
  108. package/dist/thread-close.js +3 -0
  109. package/dist/verify.js +4 -3
  110. package/eval/casos/orchestration-experience-pt-br.json +48 -0
  111. package/eval/casos/orchestration-experience.json +48 -0
  112. package/package.json +1 -1
  113. package/schemas/code-artifact-graph.v1.schema.json +581 -0
  114. package/schemas/graph-benchmark.v1.schema.json +2240 -0
  115. package/schemas/maestro-snapshot.schema.json +23 -0
  116. package/skills/README.md +7 -5
  117. package/skills/core/onboarding/SKILL.md +7 -0
  118. package/skills/core/orchestration-experience/SKILL.md +113 -0
  119. package/skills/core/orchestration-experience-pt-br/SKILL.md +112 -0
  120. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  121. package/skills/phases/go-implementation/SKILL.md +2 -0
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,7 +214,13 @@ 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
@@ -211,6 +232,9 @@ Uso: ork <comando> [argumentos]
211
232
  [--reset [etapa]] Reset seletivo ou total, idempotente
212
233
  onboarding sync [--json] Publicação opcional na memória, com degradação
213
234
  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,38 @@ 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; --verificar
382
+ confere contrato, bytes e determinismo; precisa de typescript e micromark
383
+ grafo status [--json] Indices guardados, o do HEAD, os analisadores e o tamanho
384
+ grafo vizinhos <no> [--profundidade N] Vizinhanca de arquivo ou simbolo, com extrator e evidencia de cada aresta
385
+ [--sentido entrada|saida|ambos] [--tipo T,...] [--limite N] [--json]
386
+ grafo chamadores <simbolo> Quem chama (arestas calls que chegam) [--profundidade N] [--limite N] [--json]
387
+ grafo importadores <arquivo|simbolo> Quem importa (arestas imports que chegam) [--profundidade N] [--limite N] [--json]
388
+ grafo caminho <de> <para> Menor caminho pelas arestas [--sentido saida|entrada|ambos] [--tipo T,...] [--json]
389
+ grafo amostra [--por-estrato N] Amostra de arestas para auditoria manual; --conferir ARQ confere a auditada
390
+ grafo limpar [--tudo] [--json] Apaga os indices que nao sao do HEAD e as sobras com mais de uma hora
345
391
 
346
392
  ship <thread-id> --para <branch> Merge --no-ff serializado por lease e push PROVADO
347
393
  ship registrar-pr <thread-id>|--todas A entrega feita por PR vira ship_done: merge ship(<thread>) na base
348
394
  [--remoto R] [--json] remota e CI verde no head do PR; depois, ork master --aceitar-omissao
395
+ [--repo <dono/nome> --pr <n>] PR mesclado em repositorio externo de ci.external_repositories
349
396
  [--de <branch>] [--remoto origin] [--autorizar-push <quem>] [--sem-push] [--dry-run]
350
397
 
351
398
  board [--all] [--sem-remoto] Visao unica das threads (todos os perfis com --all); com a
@@ -375,7 +422,11 @@ Uso: ork <comando> [argumentos]
375
422
  master digest <enviar|preview|responder> Digest semanal com recibos do host
376
423
  master <thread-id> --score 0-5 --justificativa "<texto>"
377
424
  [--classe C[,C]] [--resumo R] [--por Q] [--refazer]
378
- Fecha a thread: POSTMORTEM + MASTER log + score
425
+ Fecha a thread: POSTMORTEM + MASTER log + score (so do terminal;
426
+ de processo de host e recusado com master.prova-de-canal)
427
+ master pedir <thread-id> [--formato telegram|terminal|json]
428
+ Pede a nota ao dono com codigo curto; ele responde pelo Telegram
429
+ (<codigo> <0 a 5> <porque>) e a nota vai ao ledger com o recibo (RM-048)
379
430
  master [--todas] [--json] As entregas, com o indice derivado do ledger
380
431
  master --aceitar-omissao [--json] Aceita as entregues por omissao, com registro
381
432
  master classes As classes de falha fixas do POSTMORTEM
@@ -395,11 +446,17 @@ Uso: ork <comando> [argumentos]
395
446
  [--pedido "<texto>"] [--template ID]
396
447
  prompt render --exemplo --fase F --modo M Renderiza sem thread nenhuma, para revisar o texto
397
448
 
449
+ roadmap status [--json] Status report unico do roadmap: grupos com icones, #HITL no que espera
450
+ voce e o fecho com o que precisa de voce e o que vem a seguir (RM-048)
398
451
  roadmap reservas [--json] [--remoto R] Quem esta com cada item do roadmap, lido da branch ork/roadmap-reservas
452
+ [--soltar-orfas] marca a reserva de thread ja fechada (orfa) e, com a opcao, solta
453
+ ou passa para outra thread aberta do mesmo item, com registro
399
454
  roadmap pegar <RM-NNN> [--thread T] Reserva o item para esta maquina (push atomico: o primeiro vence)
400
455
  [--nota N] [--por Q] [--maquina M] maquina = --maquina, ORK_MAQUINA ou o hostname
401
456
  [--forcar --motivo M] tomar a reserva de outra maquina fica registrado
402
457
  roadmap soltar <RM-NNN> [--forcar --motivo M] Devolve o item
458
+ roadmap feat [--thread T] [--nota N] Reserva o proximo numero de FEAT na mesma branch (push atomico: duas
459
+ maquinas nunca levam o mesmo numero; numero reservado nao volta)
403
460
  fabrica [--json] [--sem-remoto] O que cada maquina conduz, lido da branch ork/fabrica-estado (I-51)
404
461
  fabrica entrar [--maquina NOME] Esta maquina entra na fabrica compartilhada deste usuario, com
405
462
  este nome (~/.orkastery/maquina.json), e publica o primeiro retrato
@@ -407,10 +464,15 @@ Uso: ork <comando> [argumentos]
407
464
  depois de entrar, sai sozinho ao criar thread, despachar fase,
408
465
  entregar e fechar, e a cada batida do pulse
409
466
  fabrica sair Para de publicar daqui e tira o retrato desta maquina da branch
467
+ network roadmap [--projeto P] [--json] Roadmap, reservas e threads de cada maquina de cada projeto, de qualquer diretorio:
468
+ [--sem-remoto] fonte e hora de cada parte, lacuna tipada no que nao leu. P = caminho do clone,
469
+ github:dono/repo, gitlab:grupo/repo ou nome conhecido; sem clone, le a forja (RM-054)
410
470
  docs verificar [--json] Documentacao de produto e roadmap contra o codigo e o git
411
471
  (padrao do dono: frontmatter, leitura, paridade; sai != 0 com erro)
412
472
  docs sincronizar [--escrever] Fatos do ledger e do git para o roadmap (merge, fase) e indices;
413
473
  sem --escrever so mostra; nunca muda status por passagem de tempo
474
+ [--so RM-NNN[,RM-MMM]] [--todos] so esses itens (e os indices); na worktree de uma thread com item,
475
+ o padrao e o item dela; --todos volta a todo item (RM-037)
414
476
  docs init Cria padroes, modelos, indices e o lint de Markdown no projeto
415
477
 
416
478
  mcp serve --project RAIZ --host HOST Servidor MCP stdio deste projeto (codex|claude-code)
@@ -526,6 +588,10 @@ function comandoThread(args) {
526
588
  return 1;
527
589
  }
528
590
  const gravadaDoAchado = args.opcoes['dry-run'] !== true;
591
+ // RM-052 (D7): thread nova, projeto conhecido; o aviso nunca derruba a criacao.
592
+ const avisoDoRegistroDoAchado = gravadaDoAchado && r.thread ? (0, projeto_alvo_1.registrarProjetoEmSilencio)(carregado.raiz, 'thread new') : null;
593
+ if (avisoDoRegistroDoAchado)
594
+ console.error(avisoDoRegistroDoAchado);
529
595
  console.log(gravadaDoAchado
530
596
  ? `Thread criada a partir do achado ${r.achado.id}.`
531
597
  : 'Simulacao (--dry-run), nada foi gravado.');
@@ -567,6 +633,9 @@ function comandoThread(args) {
567
633
  console.error('uso: ork thread new <nome> --modo <MODO>');
568
634
  return 2;
569
635
  }
636
+ const avisoRoadmap = avisoRoadmapSemAssociacao(nome, texto(args.opcoes.roadmap));
637
+ if (avisoRoadmap)
638
+ console.error(avisoRoadmap);
570
639
  const brutoModo = texto(args.opcoes.modo) ?? texto(args.opcoes.mode);
571
640
  let modo;
572
641
  try {
@@ -646,6 +715,10 @@ function comandoThread(args) {
646
715
  // I-51 (RM-047): com a fabrica compartilhada, as outras maquinas veem a thread nova.
647
716
  if (gravada)
648
717
  (0, fabrica_publicar_1.publicarEmSegundoPlano)(carregado.raiz);
718
+ // RM-052 (D7): quem abre thread aqui conhece este projeto; o aviso nunca derruba a criacao.
719
+ const avisoDoRegistro = gravada ? (0, projeto_alvo_1.registrarProjetoEmSilencio)(carregado.raiz, 'thread new') : null;
720
+ if (avisoDoRegistro)
721
+ console.error(avisoDoRegistro);
649
722
  console.log(gravada ? 'Thread criada.' : 'Simulacao (--dry-run), nada foi gravado.');
650
723
  if (reservaDoItem)
651
724
  console.log(` roadmap: ${reservaDoItem.item} reservado para esta maquina (${reservaDoItem.reserva?.maquina})`);
@@ -762,7 +835,7 @@ function comandoOnboarding(args) {
762
835
  estado = (0, onboarding_1.resetarOnboarding)(raiz, etapa, por);
763
836
  else
764
837
  estado = (0, onboarding_1.lerOnboarding)(raiz);
765
- console.log(args.opcoes.json === true ? JSON.stringify(estado, null, 2) : (0, onboarding_1.textoDaPauta)(estado));
838
+ console.log(args.opcoes.json === true ? JSON.stringify(estado, null, 2) : (0, onboarding_1.textoDaPauta)(estado, (0, manifest_1.exigirManifesto)(raiz).manifesto.owner));
766
839
  return 0;
767
840
  }
768
841
  /**
@@ -1014,6 +1087,32 @@ function comandoPhase(args) {
1014
1087
  console.log(args.opcoes.json === true && r.recusa ? JSON.stringify(r.recusa, null, 2) : r.recusa?.texto ?? r.erro);
1015
1088
  return 3;
1016
1089
  }
1090
+ // RM-037 (defeito 3): a recusa por vaga e espera, como a da conducao (codigo 3), e diz quem ocupa.
1091
+ if (r.motivo === 'concurrency.limite' && r.vaga) {
1092
+ if (args.opcoes.json === true) {
1093
+ console.log(JSON.stringify({ motivo: r.motivo, ...r.vaga }, null, 2));
1094
+ return 3;
1095
+ }
1096
+ console.log(`Despacho recusado: concurrency.limite. O projeto ja tem ${r.vaga.ocupam.length} sessao(oes) viva(s) ` +
1097
+ `em outras threads e o limite e ${r.vaga.limite} (concurrency.max_parallel_threads).`);
1098
+ for (const o of r.vaga.ocupam) {
1099
+ console.log(` ${o.thread.padEnd(20)} ${(o.fase ?? '-').padEnd(6)} ` +
1100
+ `${o.sessao ? `${o.runtime} ${o.sessao.slice(0, 8)}` : 'despacho em curso'}, desde ${(0, horario_1.localizarTextoRotulado)(o.desde)}`);
1101
+ }
1102
+ console.log(` correcao: ${r.vaga.correcao}`);
1103
+ console.log(r.dryRun ? ' ensaio (--dry-run): nada foi gravado.' : ` evento slot_refused no ledger de ${id}; nenhuma sessao aberta.`);
1104
+ return 3;
1105
+ }
1106
+ // RM-037 (S-4 do CHECK 3): a baseline que o despacho nao conseguiu gravar nao e gate reprovado.
1107
+ if (r.motivo === 'baseline.pendente') {
1108
+ if (args.opcoes.json === true) {
1109
+ console.log(JSON.stringify({ motivo: r.motivo, detalhe: r.erro }, null, 2));
1110
+ return 1;
1111
+ }
1112
+ console.error(`Despacho recusado: ${r.erro}`);
1113
+ console.error(' nenhuma sessao aberta; o ledger nao ganhou gate_blocked');
1114
+ return 1;
1115
+ }
1017
1116
  if (r.dryRun && !r.bloqueado) {
1018
1117
  console.log('Simulacao (--dry-run), nada foi despachado.');
1019
1118
  console.log(` slug da sessao : ${r.slug}`);
@@ -1136,7 +1235,7 @@ function comandoSessionsHitl(args, raiz) {
1136
1235
  function comandoSessions(args) {
1137
1236
  const sub = args.posicionais[1];
1138
1237
  const carregado = (0, manifest_1.carregarManifesto)();
1139
- const raiz = carregado?.raiz ?? process.cwd();
1238
+ const raiz = carregado?.raiz ?? (0, manifest_1.diretorioDoProjeto)();
1140
1239
  if (sub === 'watch') {
1141
1240
  const id = texto(args.opcoes.thread);
1142
1241
  if (!carregado || !id) {
@@ -1260,12 +1359,21 @@ function comandoDecisao(args) {
1260
1359
  if (separador < 1 || !['manifesto', 'ledger', 'medicao'].includes(tipo) || !referencia.trim()) {
1261
1360
  throw new Error('decisao registrar: --criterio manifesto:CHAVE, ledger:REF ou medicao:COMANDO');
1262
1361
  }
1263
- const { pedido, evento } = (0, decisao_autonoma_1.registrarDecisao)(carregado.raiz, id, {
1362
+ const entrada = {
1264
1363
  decidido: campo('decidido'), porque: campo('porque'), comoMudar: campo('como-mudar'),
1265
1364
  custoDeReverter: { agora: campo('custo-agora'), depois: campo('custo-depois') },
1266
1365
  criterio: { tipo, referencia }, quemDecidiu: campo('quem'), evidencia: campo('evidencia'),
1267
1366
  razao: texto(args.opcoes.razao), reverte: texto(args.opcoes.reverte),
1268
- });
1367
+ };
1368
+ let registro;
1369
+ // RM-037 (defeito 4): a recusa cita a flag que o dono digitou, com o tamanho e o teto reais.
1370
+ try {
1371
+ registro = (0, decisao_autonoma_1.registrarDecisao)(carregado.raiz, id, entrada);
1372
+ }
1373
+ catch (e) {
1374
+ throw new Error((0, hitl_contract_1.recusaNaSuperficie)(e.message, hitl_contract_1.CAMPOS_DA_DECISAO_NO_CLI));
1375
+ }
1376
+ const { pedido, evento } = registro;
1269
1377
  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
1378
  console.log(JSON.stringify({ ok: true, pedidoId: pedido.id, eventId: evento.eventId, fase: pedido.fase, placar }));
1271
1379
  return 0;
@@ -1461,6 +1569,14 @@ function comandoConducao(args) {
1461
1569
  }
1462
1570
  throw new Error('uso: ork conducao status|assumir <thread-id>');
1463
1571
  }
1572
+ /** RM-048 (D1): o gate aberto no contrato curto, com o codigo estavel e o "desde" do ledger. */
1573
+ function textoDoGateCurto(raiz, pedido, canal) {
1574
+ const quando = new Date().toISOString();
1575
+ const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, pedido.thread));
1576
+ const codigo = pedido.codigo;
1577
+ 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' } });
1578
+ return (0, hitl_curto_1.textoDoPedidoCurto)(curto, canal);
1579
+ }
1464
1580
  function comandoGate(args) {
1465
1581
  const carregado = (0, manifest_1.exigirManifesto)();
1466
1582
  const sub = args.posicionais[1];
@@ -1479,7 +1595,13 @@ function comandoGate(args) {
1479
1595
  const id = args.posicionais[2];
1480
1596
  if (!id)
1481
1597
  throw new Error('gate request exige thread');
1482
- console.log(JSON.stringify((0, hitl_gates_1.abrirPedidoGate)(carregado.raiz, id, texto(args.opcoes.motivo))));
1598
+ const formato = texto(args.opcoes.formato);
1599
+ if (formato !== undefined && formato !== 'telegram' && formato !== 'terminal')
1600
+ throw new Error('gate request: --formato telegram|terminal');
1601
+ const pedido = (0, hitl_gates_1.abrirPedidoGate)(carregado.raiz, id, texto(args.opcoes.motivo));
1602
+ // RM-048 (D1): com --formato, o que sai e o pedido no contrato curto, pronto para o canal, com
1603
+ // o codigo estavel na ultima linha. Sem ele, o JSON de sempre, para quem integra.
1604
+ console.log(formato ? textoDoGateCurto(carregado.raiz, pedido, formato) : JSON.stringify(pedido));
1483
1605
  return 0;
1484
1606
  }
1485
1607
  if (sub === 'answer') {
@@ -1827,11 +1949,14 @@ function comandoShip(args) {
1827
1949
  // I-57 (RM-008): a entrega feita por PR vira ship_done, provada no remoto e no CI.
1828
1950
  const alvo = args.posicionais[2];
1829
1951
  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]');
1952
+ // RM-037 (defeito 5): PR mesclado em repositorio externo declarado em ci.external_repositories.
1953
+ const repo = texto(args.opcoes.repo), numeroDoPr = texto(args.opcoes.pr);
1954
+ if ((!alvo && args.opcoes.todas !== true) || (!!repo !== !!numeroDoPr) || (repo && !alvo)) {
1955
+ console.error('uso: ork ship registrar-pr <thread-id> [--repo <dono/nome> --pr <n>] | --todas [--remoto R] [--json]');
1832
1956
  return 2;
1833
1957
  }
1834
- const r = alvo ? [(0, entrega_pr_1.registrarEntregaPorPr)(carregado, alvo, { remoto })] : (0, entrega_pr_1.registrarEntregasPorPr)(carregado, { remoto });
1958
+ const r = alvo && repo ? [(0, entrega_pr_1.registrarEntregaExternaPorPr)(carregado, alvo, { repositorio: repo, pr: Number(numeroDoPr) })]
1959
+ : alvo ? [(0, entrega_pr_1.registrarEntregaPorPr)(carregado, alvo, { remoto })] : (0, entrega_pr_1.registrarEntregasPorPr)(carregado, { remoto });
1835
1960
  if (args.opcoes.json === true) {
1836
1961
  console.log(JSON.stringify(r, null, 2));
1837
1962
  return r.some((x) => x.acao === 'recusada') ? 1 : 0;
@@ -2028,9 +2153,16 @@ function comandoCi(args) {
2028
2153
  console.log(JSON.stringify(result, null, 2));
2029
2154
  return result.ok ? 0 : 1;
2030
2155
  }
2156
+ // RM-037 (rm037noite, defeito 1): o CI passa a branch e acha o `.ork-ci/<thread>.json` dela.
2157
+ const branch = texto(args.opcoes.branch);
2158
+ if (branch) {
2159
+ const result = (0, ci_1.executarCiDaBranch)(carregado, branch);
2160
+ console.log(JSON.stringify(result, null, 2));
2161
+ return result.ok ? 0 : 1;
2162
+ }
2031
2163
  const thread = args.posicionais[2];
2032
2164
  if (!thread) {
2033
- console.error('uso: ork ci run <thread-id> [--json] | ork ci run --bundle <arquivo>');
2165
+ console.error('uso: ork ci run <thread-id> [--json] | ork ci run --bundle <arquivo> | ork ci run --branch <branch>');
2034
2166
  return 2;
2035
2167
  }
2036
2168
  const result = (0, ci_1.executarCi)(carregado, thread);
@@ -2094,12 +2226,34 @@ function comandoLease(args) {
2094
2226
  console.error(`subcomando desconhecido: lease ${sub}`);
2095
2227
  return 2;
2096
2228
  }
2229
+ /**
2230
+ * RM-052: o cabecalho do board. O board le as threads DESTE projeto nesta maquina; o roadmap nunca
2231
+ * e lido aqui, e "0 threads" nunca quer dizer "roadmap vazio". As outras maquinas so entram com a
2232
+ * fabrica compartilhada e um remoto de verdade.
2233
+ */
2234
+ function consultaDoBoard(carregado, opcoes) {
2235
+ const remoto = carregado.manifesto.fabrica.remoto;
2236
+ const comFabrica = !opcoes.plano && (0, maquina_1.fabricaCompartilhada)(carregado.manifesto);
2237
+ const url = (0, projeto_alvo_1.remotoDoProjeto)(carregado.raiz, remoto);
2238
+ return (0, projeto_alvo_1.consultaDoProjeto)(carregado, {
2239
+ remoto: url,
2240
+ lido: [`${projeto_alvo_1.FORA_DA_CONSULTA.threadsDaMaquina}${opcoes.todos ? ' (todos os perfis)' : ''}`,
2241
+ ...(comFabrica && url !== null ? [`outras máquinas (ork/fabrica-estado em ${remoto})`] : [])],
2242
+ naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.roadmap, projeto_alvo_1.FORA_DA_CONSULTA.reservas,
2243
+ ...(url === null ? [(0, projeto_alvo_1.semRemoto)(remoto)] : comFabrica ? [] : [projeto_alvo_1.FORA_DA_CONSULTA.outrasMaquinas])],
2244
+ });
2245
+ }
2097
2246
  function comandoBoard(args) {
2098
2247
  const carregado = (0, manifest_1.exigirManifesto)();
2099
2248
  const sub = args.posicionais[1];
2249
+ const todos = args.opcoes.all === true || args.opcoes.todos === true;
2100
2250
  if (sub === 'plan' || sub === 'plano') {
2101
2251
  const plano = (0, board_1.planejar)(carregado);
2102
- console.log(args.opcoes.json === true ? JSON.stringify(plano, null, 2) : (0, board_1.textoDoPlano)(plano));
2252
+ const consulta = consultaDoBoard(carregado, { plano: true, todos: false });
2253
+ if (args.opcoes.json === true)
2254
+ console.log(JSON.stringify({ ...plano, consulta }, null, 2));
2255
+ else
2256
+ console.log([...(0, projeto_alvo_1.linhasDaConsulta)(consulta), '', (0, board_1.textoDoPlano)(plano)].join('\n'));
2103
2257
  return 0;
2104
2258
  }
2105
2259
  if (sub === 'reap') {
@@ -2115,21 +2269,31 @@ function comandoBoard(args) {
2115
2269
  console.error('uso: ork board [list|plan|reap] [--all] [--por <quem>] [--json]');
2116
2270
  return 2;
2117
2271
  }
2118
- const todos = args.opcoes.all === true || args.opcoes.todos === true;
2272
+ const consulta = consultaDoBoard(carregado, { plano: false, todos });
2119
2273
  if (args.opcoes.json === true) {
2120
- console.log(JSON.stringify((0, board_1.threadsDeTodosOsPerfis)(carregado, todos), null, 2));
2274
+ // RM-052 (D6): objeto com o cabecalho; a lista de threads continua inteira em `threads`.
2275
+ console.log(JSON.stringify({ contrato: CONTRATO_DO_BOARD, consulta, threads: (0, board_1.threadsDeTodosOsPerfis)(carregado, todos) }, null, 2));
2121
2276
  return 0;
2122
2277
  }
2278
+ console.log([...(0, projeto_alvo_1.linhasDaConsulta)(consulta), ''].join('\n'));
2123
2279
  console.log((0, board_1.textoDoBoard)(carregado, todos));
2124
2280
  // I-51 (RM-047): com a fabrica compartilhada, o board mostra tambem as outras maquinas.
2125
2281
  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
2282
  console.log('');
2129
- console.log((0, fabrica_estado_1.textoDasOutrasMaquinas)(painel, (0, maquina_1.nomeDaMaquina)()));
2283
+ // RM-052: sem o remoto, nada foi lido; dizer "nenhuma publicou" seria a frase do incidente de 29/09.
2284
+ if (consulta.projeto.remoto === null) {
2285
+ 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.`);
2286
+ }
2287
+ else {
2288
+ const painel = (0, fabrica_estado_1.lerFabrica)(carregado.raiz, { remoto: carregado.manifesto.fabrica.remoto,
2289
+ semRemoto: args.opcoes['sem-remoto'] === true });
2290
+ console.log((0, fabrica_estado_1.textoDasOutrasMaquinas)(painel, (0, maquina_1.nomeDaMaquina)()));
2291
+ }
2130
2292
  }
2131
2293
  return 0;
2132
2294
  }
2295
+ /** RM-052 (D6): `ork board --json` deixou de ser lista para carregar o cabecalho da consulta. */
2296
+ const CONTRATO_DO_BOARD = 'ork.board/v1';
2133
2297
  /**
2134
2298
  * I-51 (RM-047): `ork fabrica` mostra o que cada maquina conduz; `ork fabrica publicar` grava o
2135
2299
  * retrato desta maquina na branch `ork/fabrica-estado`. O `--silencioso` e o da publicacao em
@@ -2173,6 +2337,10 @@ function comandoFabrica(args) {
2173
2337
  const config = (0, maquina_1.gravarConfigDaMaquina)({ nome: texto(args.opcoes.maquina) ?? (0, maquina_1.lerConfigDaMaquina)()?.nome ?? (0, maquina_1.nomeDaMaquina)(),
2174
2338
  fabricaCompartilhada: true });
2175
2339
  const r = (0, fabrica_estado_1.publicarMaquina)(carregado, { remoto, forcar: true });
2340
+ // RM-052 (D7): a maquina que entra na fabrica deste projeto passa a conhece-lo pelo nome.
2341
+ const avisoDoRegistro = (0, projeto_alvo_1.registrarProjetoEmSilencio)(carregado.raiz, 'fabrica entrar');
2342
+ if (avisoDoRegistro)
2343
+ console.error(avisoDoRegistro);
2176
2344
  console.log(`Fabrica: esta maquina entrou como ${config.nome}; publica ao criar thread, despachar fase, entregar e fechar,`);
2177
2345
  console.log(` e a cada batida do pulse. Primeiro retrato: ${r.threads} thread(s) em ork/fabrica-estado (${r.commit?.slice(0, 7)}).`);
2178
2346
  if (process.env.ORK_MAQUINA && process.env.ORK_MAQUINA.trim() !== config.nome) {
@@ -2195,10 +2363,82 @@ function comandoFabrica(args) {
2195
2363
  console.error('uso: ork fabrica [--json] [--sem-remoto] | fabrica publicar [--forcar] [--json] | fabrica entrar [--maquina NOME] | fabrica sair');
2196
2364
  return 2;
2197
2365
  }
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)()));
2366
+ // RM-052: a fabrica le a branch de UM projeto, no remoto dele; o cabecalho diz qual e o que ficou de fora.
2367
+ const url = (0, projeto_alvo_1.remotoDoProjeto)(carregado.raiz, remoto);
2368
+ const painel = url === null ? { maquinas: [], atualizado: false, ponta: null }
2369
+ : (0, fabrica_estado_1.lerFabrica)(carregado.raiz, { remoto, semRemoto: args.opcoes['sem-remoto'] === true });
2370
+ const consulta = (0, projeto_alvo_1.consultaDoProjeto)(carregado, {
2371
+ remoto: url,
2372
+ lido: url === null ? [] : [`ork/fabrica-estado em ${remoto} (${painel.atualizado ? 'lido agora' : 'última cópia local'})`],
2373
+ naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.roadmap, projeto_alvo_1.FORA_DA_CONSULTA.reservas, ...(url === null ? [(0, projeto_alvo_1.semRemoto)(remoto)] : [])],
2374
+ });
2375
+ if (args.opcoes.json === true) {
2376
+ console.log(JSON.stringify({ ...painel, consulta }, null, 2));
2377
+ return 0;
2378
+ }
2379
+ console.log([...(0, projeto_alvo_1.linhasDaConsulta)(consulta), ''].join('\n'));
2380
+ console.log(url === null
2381
+ ? `Fabrica: o projeto ${carregado.manifesto.project.name} nao tem o remoto ${remoto}; nada foi lido de ork/fabrica-estado.`
2382
+ : (0, fabrica_estado_1.textoDaFabrica)(painel, (0, maquina_1.nomeDaMaquina)()));
2200
2383
  return 0;
2201
2384
  }
2385
+ /**
2386
+ * RM-052: `ork projetos` lista o registro desta maquina (`~/.orkastery/projetos.json`); `registrar`
2387
+ * poe uma copia que ja existia antes do registro (init, thread new e fabrica entrar ja registram) e
2388
+ * `esquecer` tira a copia que sumiu ou sobrou. Sem segredo: so nome, abbrev, raiz e remoto redigido.
2389
+ */
2390
+ function comandoProjetos(args, projeto) {
2391
+ const sub = args.posicionais[1] ?? 'list';
2392
+ if (sub === 'list' || sub === 'listar') {
2393
+ const projetos = (0, projeto_alvo_1.listarProjetos)();
2394
+ if (args.opcoes.json === true) {
2395
+ console.log(JSON.stringify({ contrato: projeto_alvo_1.CONTRATO_PROJETOS, arquivo: (0, projeto_alvo_1.caminhoDoRegistro)(), projetos }, null, 2));
2396
+ return 0;
2397
+ }
2398
+ console.log(`Projetos conhecidos desta maquina (${(0, projeto_alvo_1.raizParaExibir)((0, projeto_alvo_1.caminhoDoRegistro)())})`);
2399
+ console.log('');
2400
+ if (projetos.length === 0) {
2401
+ console.log(' Nenhum ainda. ork init, ork thread new e ork fabrica entrar registram; ou: ork projetos registrar <caminho>');
2402
+ return 0;
2403
+ }
2404
+ console.log((0, util_1.tabela)(['NOME', 'ABBREV', 'RAIZ', 'REMOTO', 'NO DISCO', 'ATUALIZADO'], projetos.map((p) => [
2405
+ p.nome, p.abbrev || '-', (0, projeto_alvo_1.raizParaExibir)(p.raiz), p.remoto ?? 'sem remoto', p.presente ? 'sim' : 'ausente',
2406
+ (0, horario_1.formatarDataHora)(p.atualizadoEm)
2407
+ ])));
2408
+ console.log('');
2409
+ console.log('Use --projeto <nome> em qualquer comando (ORK_PROJETO vale para o shell inteiro). ' + (0, horario_1.legendaDoFuso)());
2410
+ return 0;
2411
+ }
2412
+ if (sub === 'registrar') {
2413
+ const caminho = args.posicionais[2];
2414
+ if (caminho !== undefined && projeto !== undefined)
2415
+ throw new Error('uso: ork projetos registrar [caminho] (um caminho ou --projeto, não os dois)');
2416
+ const alvo = caminho === undefined ? (0, projeto_alvo_1.resolverProjetoAlvo)({ opcao: projeto ?? null }) : null;
2417
+ const p = (0, projeto_alvo_1.registrarProjeto)(caminho ?? alvo?.raiz ?? process.cwd(), 'projetos registrar');
2418
+ if (args.opcoes.json === true) {
2419
+ console.log(JSON.stringify(p, null, 2));
2420
+ return 0;
2421
+ }
2422
+ console.log(`Projeto ${p.nome} (${p.abbrev || '-'}) registrado: ${(0, projeto_alvo_1.raizParaExibir)(p.raiz)} · ${p.remoto ?? 'sem remoto'}`);
2423
+ return 0;
2424
+ }
2425
+ if (sub === 'esquecer') {
2426
+ const alvo = args.posicionais[2] ?? projeto;
2427
+ if (!alvo)
2428
+ throw new Error('uso: ork projetos esquecer <nome|caminho>');
2429
+ const sairam = (0, projeto_alvo_1.esquecerProjeto)(alvo);
2430
+ if (args.opcoes.json === true) {
2431
+ console.log(JSON.stringify(sairam, null, 2));
2432
+ return 0;
2433
+ }
2434
+ for (const p of sairam)
2435
+ console.log(`Projeto ${p.nome} esquecido: ${(0, projeto_alvo_1.raizParaExibir)(p.raiz)} (nada no disco foi apagado)`);
2436
+ return 0;
2437
+ }
2438
+ console.error(`subcomando desconhecido: projetos ${sub}`);
2439
+ console.error('uso: ork projetos [--json] | projetos registrar [caminho] | projetos esquecer <nome|caminho>');
2440
+ return 2;
2441
+ }
2202
2442
  /**
2203
2443
  * `ork orquestracao status` (alias `ork monitor`): pausas e impedimentos de uma chamada.
2204
2444
  *
@@ -2314,9 +2554,20 @@ function comandoMaster(args) {
2314
2554
  console.log(JSON.stringify(r, null, 2));
2315
2555
  return r.ok ? 0 : 1;
2316
2556
  }
2557
+ if (primeiro === 'pedir') {
2558
+ // RM-048 (item 8): a nota com prova. O canal mostra a linha; o dono responde pelo Telegram.
2559
+ const id = args.posicionais[2];
2560
+ const formato = texto(args.opcoes.formato) ?? 'telegram';
2561
+ if (!id || !['telegram', 'terminal', 'json'].includes(formato))
2562
+ throw new Error('uso: ork master pedir <thread> [--formato telegram|terminal|json]');
2563
+ const pedido = (0, master_nota_1.pedirNota)(carregado.raiz, id, { codigosEmUso: (0, pulse_resposta_1.codigosEmUso)(carregado.raiz) });
2564
+ console.log(formato === 'json' ? JSON.stringify(pedido, null, 2) : (0, master_nota_1.textoDoPedidoDeNota)(carregado.raiz, pedido, formato));
2565
+ return 0;
2566
+ }
2317
2567
  if (primeiro === 'digest') {
2318
2568
  const sub = args.posicionais[2];
2319
2569
  if (sub === 'responder') {
2570
+ (0, master_nota_1.exigirNotaSemHost)();
2320
2571
  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
2572
  return 0;
2322
2573
  }
@@ -2339,6 +2590,7 @@ function comandoMaster(args) {
2339
2590
  return 0;
2340
2591
  }
2341
2592
  if (primeiro === 'ratificar' || ((args.opcoes.batch === true || primeiro === 'batch') && args.opcoes.aceitar)) {
2593
+ (0, master_nota_1.exigirNotaSemHost)();
2342
2594
  let selecao;
2343
2595
  if (primeiro === 'ratificar') {
2344
2596
  const partes = (texto(args.opcoes.resposta) ?? '').trim().split(/\s+/);
@@ -2434,6 +2686,8 @@ function comandoMaster(args) {
2434
2686
  console.log(JSON.stringify((0, master_1.proporMaster)(carregado.raiz, id, opcoesMaster), null, 2));
2435
2687
  return 0;
2436
2688
  }
2689
+ // RM-048 (D8): nota em nome de pessoa, de processo de host, so pelo ingresso autenticado.
2690
+ (0, master_nota_1.exigirNotaSemHost)();
2437
2691
  const r = (0, master_2.registrarMaster)(carregado.raiz, id, opcoesMaster);
2438
2692
  console.log((0, master_2.textoDoMaster)(r));
2439
2693
  // Bloco B6: fechada a thread, a licao (POSTMORTEM + score) vai para a colecao
@@ -2478,13 +2732,47 @@ function comandoRoadmap(args) {
2478
2732
  const sub = args.posicionais[1] ?? 'reservas';
2479
2733
  const remoto = texto(args.opcoes.remoto);
2480
2734
  if (sub === 'reservas') {
2735
+ // RM-037 (rm037noite, defeito 3): a reserva de thread ja fechada aparece como orfa e sai com registro.
2736
+ if (args.opcoes['soltar-orfas'] === true) {
2737
+ const soltas = (0, roadmap_reservas_1.soltarReservasOrfas)(carregado.raiz, { remoto });
2738
+ if (args.opcoes.json === true)
2739
+ console.log(JSON.stringify(soltas, null, 2));
2740
+ else
2741
+ console.log(soltas.length === 0 ? 'Nenhuma reserva órfã desta máquina.'
2742
+ : soltas.map((s) => `${s.item}: ${s.detalhe} (thread fechada ${s.thread})`).join('\n'));
2743
+ return 0;
2744
+ }
2481
2745
  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));
2746
+ const orfas = (0, roadmap_reservas_1.reservasOrfas)(carregado.raiz, painel.reservas);
2747
+ console.log(args.opcoes.json === true ? JSON.stringify({ ...painel, orfas }, null, 2) : (0, roadmap_reservas_1.textoDasReservas)(painel, orfas));
2748
+ return 0;
2749
+ }
2750
+ if (sub === 'status') {
2751
+ // RM-048 (item 7): o status report unico do roadmap. Os canais chamam isto e transportam o texto.
2752
+ // RM-052: com o projeto consultado e o que ficou de fora (as outras maquinas nao sao lidas aqui).
2753
+ const consulta = (0, projeto_alvo_1.consultaDoProjeto)(carregado, { lido: ['roadmap (docs/roadmap)', projeto_alvo_1.FORA_DA_CONSULTA.threadsDaMaquina],
2754
+ naoLido: [projeto_alvo_1.FORA_DA_CONSULTA.reservas, 'threads de outras máquinas (ork network roadmap)'] });
2755
+ const status = (0, roadmap_status_1.montarStatusDoRoadmap)(carregado.raiz, { projeto: carregado.manifesto.project.name, consulta });
2756
+ console.log(args.opcoes.json === true ? JSON.stringify(status, null, 2) : (0, roadmap_status_1.textoDoStatusDoRoadmap)(status));
2757
+ return 0;
2758
+ }
2759
+ // RM-037 (rm037noite, defeito 6): o numero da FEAT nova sai da mesma branch de reservas.
2760
+ if (sub === 'feat') {
2761
+ const r = (0, roadmap_reservas_1.reservarFeat)(carregado.raiz, { remoto, por: texto(args.opcoes.por), maquina: texto(args.opcoes.maquina),
2762
+ thread: texto(args.opcoes.thread) ?? null, nota: texto(args.opcoes.nota) ?? null });
2763
+ if (args.opcoes.json === true)
2764
+ console.log(JSON.stringify(r, null, 2));
2765
+ else {
2766
+ console.log(`${r.feat}: reservado para esta maquina${r.reserva.thread ? `, thread ${r.reserva.thread}` : ''}.`);
2767
+ console.log(` crie docs/produto/${r.feat}-<assunto>.md; o numero nao volta, mesmo que a feature nao saia`);
2768
+ console.log(` branch ork/roadmap-reservas em ${r.commit.slice(0, 7)}`);
2769
+ }
2483
2770
  return 0;
2484
2771
  }
2485
2772
  const item = args.posicionais[2];
2486
2773
  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]');
2774
+ console.error('uso: ork roadmap status [--json] | reservas [--soltar-orfas] | pegar <RM-NNN> [--thread T] [--nota N] | ' +
2775
+ 'soltar <RM-NNN> [--forcar --motivo M] | feat [--thread T] [--nota N]');
2488
2776
  return 2;
2489
2777
  }
2490
2778
  const opcoes = {
@@ -2510,10 +2798,35 @@ function comandoRoadmap(args) {
2510
2798
  console.log(` branch ork/roadmap-reservas em ${r.commit.slice(0, 7)}`);
2511
2799
  return 0;
2512
2800
  }
2801
+ /**
2802
+ * RM-054 (fatia 1): `ork network roadmap`, o roadmap da rede de qualquer diretorio. Pedido de projeto
2803
+ * ambiguo ou desconhecido e resposta, nao erro: a recusa com os candidatos, e o codigo da RM-052.
2804
+ */
2805
+ function comandoNetwork(args) {
2806
+ const pedido = texto(args.opcoes.projeto);
2807
+ if (args.posicionais[1] !== 'roadmap' || args.posicionais.length > 2 || (args.opcoes.projeto !== undefined && !pedido)) {
2808
+ console.error('uso: ork network roadmap [--projeto <caminho|github:dono/repo|gitlab:grupo/repo|nome>] [--json] [--sem-remoto]');
2809
+ return 2;
2810
+ }
2811
+ try {
2812
+ // RM-054 (fatia 2, D-G4 e D-G6): o host que declara nao ter cwd de projeto (RM-052, D3) pede por
2813
+ // nome ou pela forja, e o projeto do diretorio dele so entra pelo registro.
2814
+ const host = (process.env[projeto_alvo_1.ENV_PROJETO_EXPLICITO] ?? '').trim() === '1';
2815
+ const p = (0, network_roadmap_1.montarPanoramaDaRede)({ pedido, semRemoto: args.opcoes['sem-remoto'] === true, host });
2816
+ console.log(args.opcoes.json === true ? JSON.stringify(p, null, 2) : (0, network_roadmap_1.textoDoPanoramaDaRede)(p));
2817
+ return p.projetos.length ? 0 : 2;
2818
+ }
2819
+ catch (e) {
2820
+ if (!(e instanceof network_roadmap_1.ErroDoPedidoDeProjeto))
2821
+ throw e;
2822
+ console.log(args.opcoes.json === true ? JSON.stringify(e.recusa, null, 2) : e.texto);
2823
+ return network_roadmap_1.SAIDA_DO_PEDIDO;
2824
+ }
2825
+ }
2513
2826
  function comandoDocs(args) {
2514
2827
  const sub = args.posicionais[1] ?? 'verificar';
2515
2828
  const carregado = (0, manifest_1.carregarManifesto)();
2516
- const raiz = carregado?.raiz ?? process.cwd();
2829
+ const raiz = carregado?.raiz ?? (0, manifest_1.diretorioDoProjeto)();
2517
2830
  const baseBranch = carregado?.manifesto.worktree?.base_branch ?? 'main';
2518
2831
  if (sub === 'verificar') {
2519
2832
  const { docs, achados } = (0, docs_1.verificarDocs)(raiz, { baseBranch, ajudaDoCli: AJUDA });
@@ -2528,8 +2841,36 @@ function comandoDocs(args) {
2528
2841
  }
2529
2842
  if (sub === 'sincronizar') {
2530
2843
  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));
2844
+ // RM-037 (rm037noite, defeito 5): o escopo. `--so` diz os itens; sem ele, na worktree de uma thread
2845
+ // com item, so o item dela; `--todos` (ou fora de worktree de thread) volta a todo item.
2846
+ // Sugestao 4 do CHECK 1 (e 8 do CHECK 2, `--so=`): `--so` sem item e erro de uso, nunca o escopo
2847
+ // padrao em silencio.
2848
+ if (args.opcoes.so === true || (typeof args.opcoes.so === 'string' && !args.opcoes.so.trim())) {
2849
+ console.error('uso: ork docs sincronizar --so RM-NNN[,RM-MMM] (faltou o item depois de --so)');
2850
+ return 2;
2851
+ }
2852
+ const so = texto(args.opcoes.so);
2853
+ let itens;
2854
+ let escopo = 'todo item do roadmap';
2855
+ if (so) {
2856
+ itens = so.split(',').map((i) => i.trim().toUpperCase()).filter(Boolean);
2857
+ const fora = itens.filter((i) => !/^RM-\d{3}$/.test(i));
2858
+ if (fora.length || itens.length === 0) {
2859
+ console.error(`uso: ork docs sincronizar --so RM-NNN[,RM-MMM] (recebido: ${so})`);
2860
+ return 2;
2861
+ }
2862
+ escopo = `so ${itens.join(', ')} (--so)`;
2863
+ }
2864
+ else if (args.opcoes.todos !== true) {
2865
+ const padrao = (0, docs_1.escopoPadraoDoSync)(raiz);
2866
+ if (padrao.itens) {
2867
+ itens = padrao.itens;
2868
+ escopo = `so ${itens.join(', ')}, o item da thread ${padrao.thread} desta worktree (--todos para todo item)`;
2869
+ }
2870
+ }
2871
+ const r = (0, docs_1.sincronizarDocs)(raiz, { baseBranch, escrever, itens });
2872
+ console.log(args.opcoes.json === true ? JSON.stringify({ ...r, escopo: itens ?? null }, null, 2)
2873
+ : `Escopo: ${escopo}.\n${(0, docs_1.textoDaSincronizacao)(r, escrever)}`);
2533
2874
  return 0;
2534
2875
  }
2535
2876
  if (sub === 'init') {
@@ -2540,7 +2881,7 @@ function comandoDocs(args) {
2540
2881
  'Proximo passo: copie docs/produto/_modelo-feature.md e docs/roadmap/_modelo-item.md, e rode ork docs verificar'].join('\n'));
2541
2882
  return 0;
2542
2883
  }
2543
- console.error(`uso: ork docs verificar [--json] | sincronizar [--escrever] | init`);
2884
+ console.error(`uso: ork docs verificar [--json] | sincronizar [--escrever] [--so RM-NNN] [--todos] | init`);
2544
2885
  return 2;
2545
2886
  }
2546
2887
  function comandoPrompt(args) {
@@ -2645,7 +2986,7 @@ function comandoAdapter(args) {
2645
2986
  }
2646
2987
  const carregado = (0, manifest_1.carregarManifesto)();
2647
2988
  const r = (0, hosts_1.instalarAdaptador)(host, {
2648
- projeto: carregado?.raiz ?? process.cwd(),
2989
+ projeto: carregado?.raiz ?? (0, manifest_1.diretorioDoProjeto)(),
2649
2990
  dir: texto(args.opcoes.dir),
2650
2991
  dryRun: args.opcoes['dry-run'] === true,
2651
2992
  force: args.opcoes.force === true || args.opcoes.forcar === true,
@@ -2669,7 +3010,7 @@ function comandoAdapter(args) {
2669
3010
  * de zero em qualquer falha, para o CI do kit poder barrar merge sem eval.
2670
3011
  */
2671
3012
  function comandoEval(args) {
2672
- const catalogo = (0, catalogo_1.exigirCatalogo)((0, manifest_1.carregarManifesto)()?.raiz ?? process.cwd());
3013
+ const catalogo = (0, catalogo_1.exigirCatalogo)((0, manifest_1.carregarManifesto)()?.raiz ?? (0, manifest_1.diretorioDoProjeto)());
2673
3014
  const lista = (v) => {
2674
3015
  const t = texto(v);
2675
3016
  return t ? t.split(',').map((x) => x.trim()).filter(Boolean) : undefined;
@@ -3161,7 +3502,12 @@ function comandoMemory(args) {
3161
3502
  if (sub === 'sync' && args.posicionais[2])
3162
3503
  (0, escopo_escrita_1.validarDiretorioDeThread)(carregado.raiz, args.posicionais[2]);
3163
3504
  if (sub === 'status') {
3164
- const memoria = (0, memoria_1.abrirMemoria)(candidate);
3505
+ const memoria = (0, memoria_1.abrirMemoria)(candidate, { embeddings: 'detalhado' });
3506
+ // I-38 (D7): --sondar faz UMA chamada real pelo caminho ativo e mede a latencia.
3507
+ if (args.opcoes.sondar === true && memoria.ativo && memoria.estado.embeddings) {
3508
+ const driver = new orkmind_1.DriverCliOrkMind((0, orkmind_1.configDoManifesto)(carregado.manifesto));
3509
+ 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);
3510
+ }
3165
3511
  if (args.opcoes.json === true) {
3166
3512
  console.log(JSON.stringify({ ...memoria.estado, configSource: memoria.configSource, configDivergent: memoria.configDivergent }, null, 2));
3167
3513
  return 0;
@@ -3207,6 +3553,8 @@ function comandoMemory(args) {
3207
3553
  }
3208
3554
  return r.estado.pedido === 'orkmind' && r.falhas > 0 ? 1 : 0;
3209
3555
  }
3556
+ if (sub === 'search' && args.opcoes.texto !== undefined)
3557
+ return buscaPorTexto(args, carregado);
3210
3558
  if (sub === 'search') {
3211
3559
  const threadId = texto(args.opcoes.thread);
3212
3560
  if ((args.opcoes.restrito !== undefined || args.opcoes.thread !== undefined ||
@@ -3261,15 +3609,175 @@ function comandoMemory(args) {
3261
3609
  console.log(` ${entradas.length} entrada(s)`);
3262
3610
  return 0;
3263
3611
  }
3612
+ if (sub === 'index') {
3613
+ const modelo = texto(args.opcoes.modelo) ?? 'primario';
3614
+ if (!['primario', 'fallback', 'todos'].includes(modelo)) {
3615
+ console.error('uso: ork memory index [--modelo primario|fallback|todos] [--dry-run] [--json]');
3616
+ return 2;
3617
+ }
3618
+ const memoria = (0, memoria_1.abrirMemoria)(carregado);
3619
+ if (!memoria.ativo) {
3620
+ const falha = { motivo: memoria.estado.motivo, detalhe: memoria.estado.detalhe, correcao: memoria.estado.correcao };
3621
+ if (args.opcoes.json === true)
3622
+ console.log(JSON.stringify(falha, null, 2));
3623
+ else
3624
+ console.error(`memory.index: regime ${memoria.regime} (${memoria.estado.motivo}); ${memoria.estado.correcao}`);
3625
+ return 1;
3626
+ }
3627
+ const config = (0, manifest_1.configDeEmbedding)(carregado.manifesto);
3628
+ const driver = (0, orkmind_1.configDoManifesto)(carregado.manifesto);
3629
+ const embedder = new orkmind_1.DriverCliOrkMind(driver);
3630
+ const universo = (0, indice_vetorial_1.universoDoTenant)(memoria, memoria.estado.tenant);
3631
+ const alvos = modelo === 'todos' ? ['primario', 'fallback'] : [modelo];
3632
+ const resultados = alvos.map(alvo => (0, indice_vetorial_1.indexar)({ raiz: carregado.raiz, tenant: memoria.estado.tenant,
3633
+ dsn: driver.dsn, config, alvo, universo, dryRun: args.opcoes['dry-run'] === true,
3634
+ chavePresente: !!config.api_key_env && (0, orkmind_1.chaveDeEmbeddingAceita)((process.env[config.api_key_env] ?? '').trim(), driver.dsn),
3635
+ chaveRecusada: !!config.api_key_env && (process.env[config.api_key_env] ?? '').trim() !== '' &&
3636
+ !(0, orkmind_1.chaveDeEmbeddingAceita)((process.env[config.api_key_env] ?? '').trim(), driver.dsn),
3637
+ embeddar: (p, o) => embedder.embeddar(p, o) }));
3638
+ if (args.opcoes.json === true) {
3639
+ console.log(JSON.stringify(modelo === 'todos' ? { alvo: 'todos', resultados } : resultados[0], null, 2));
3640
+ }
3641
+ else {
3642
+ for (const r of resultados)
3643
+ console.log(textoDoIndice(r));
3644
+ }
3645
+ return resultados.some(r => !r.dryRun && r.motivo) ? 1 : 0;
3646
+ }
3264
3647
  console.error(`subcomando desconhecido: memory ${sub}`);
3265
3648
  return 2;
3266
3649
  }
3267
- function main(argv) {
3268
- // I-35: todo horário para pessoa sai no fuso do dono deste projeto (lido só se for preciso).
3650
+ /** Aviso informativo: não consulta rede, não reserva e não bloqueia criação. */
3651
+ function avisoRoadmapSemAssociacao(nome, roadmap) {
3652
+ const item = /\bRM-\d{3}\b/i.exec(nome)?.[0].toUpperCase();
3653
+ if (!item || roadmap)
3654
+ return null;
3655
+ 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.`;
3656
+ }
3657
+ /**
3658
+ * `ork memory search --texto` (I-38 D7): busca por significado, separada da busca por tag.
3659
+ * Nao combina com --tags nem com a leitura restrita por thread nesta versao (erro tipado).
3660
+ */
3661
+ function buscaPorTexto(args, carregado) {
3662
+ const frase = texto(args.opcoes.texto);
3663
+ if (args.opcoes.tags !== undefined || args.opcoes.thread !== undefined || args.opcoes.restrito !== undefined ||
3664
+ args.opcoes.janela !== undefined) {
3665
+ console.error('memory.search.texto-exclusivo: --texto nao combina com --tags, --thread, --restrito nem --janela');
3666
+ return 2;
3667
+ }
3668
+ const modo = (texto(args.opcoes.modo) ?? 'hibrido');
3669
+ const colecao = texto(args.opcoes.colecao) ?? texto(args.opcoes.collection);
3670
+ const limiteBruto = texto(args.opcoes.limite);
3671
+ const limite = limiteBruto === undefined ? busca_semantica_1.LIMITE_PADRAO_DA_BUSCA : Number(limiteBruto);
3672
+ if (!(0, orkmind_1.textoDeBuscaValido)(frase) || !busca_semantica_1.MODOS_DE_BUSCA.includes(modo) ||
3673
+ (colecao !== undefined && !orkmind_1.COLECOES_DO_ORK.includes(colecao)) ||
3674
+ !Number.isInteger(limite) || limite < 1 || limite > busca_semantica_1.LIMITE_MAXIMO_DA_BUSCA) {
3675
+ 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]`);
3676
+ return 2;
3677
+ }
3678
+ const memoria = (0, memoria_1.abrirMemoria)(carregado);
3679
+ const config = (0, manifest_1.configDeEmbedding)(carregado.manifesto);
3680
+ let r;
3681
+ if (!memoria.ativo) {
3682
+ r = { texto: frase, modo, origem: 'nenhum', modeloUsado: null, deterministico: false, motivo: memoria.estado.motivo,
3683
+ detalhe: `${memoria.estado.detalhe}; correcao: ${memoria.estado.correcao}`, resultados: [], listas: { vetor: [], fts: [] } };
3684
+ }
3685
+ else {
3686
+ const driver = (0, orkmind_1.configDoManifesto)(carregado.manifesto);
3687
+ const transporte = new orkmind_1.DriverCliOrkMind(driver);
3688
+ const fallback = memoria.estado.embeddings?.fallback;
3689
+ r = (0, busca_semantica_1.buscarPorSignificado)({ raiz: carregado.raiz, tenant: memoria.estado.tenant, dsn: driver.dsn, config,
3690
+ universo: (0, indice_vetorial_1.universoDoTenant)(memoria, memoria.estado.tenant, colecao ? [colecao] : orkmind_1.COLECOES_DO_ORK),
3691
+ texto: frase, modo, limite, timeoutMs: driver.timeoutMs,
3692
+ chavePresente: memoria.estado.embeddings?.chavePresente === true,
3693
+ fallbackUsavel: memoria.estado.embeddings?.sondado === true && fallback?.dependencias === true,
3694
+ embeddar: (p, o) => transporte.embeddar(p, o), buscarTexto: (t, q) => transporte.buscarTexto(t, q) });
3695
+ }
3696
+ if (args.opcoes.json === true) {
3697
+ console.log(JSON.stringify(r, null, 2));
3698
+ return 0;
3699
+ }
3700
+ console.log(`Busca por significado (NAO deterministica; modo ${r.modo}, origem ${r.origem}${r.modeloUsado ? ` ${r.modeloUsado}` : ''})`);
3701
+ if (r.motivo)
3702
+ console.log(` motivo: ${r.motivo}${r.detalhe ? `; ${r.detalhe}` : ''}`);
3703
+ console.log('');
3704
+ r.resultados.forEach((e, i) => {
3705
+ const sim = e.similaridade === null ? '' : ` similaridade ${e.similaridade}`;
3706
+ console.log(` ${i + 1}. [${e.collection}] ${e.id} score ${e.score} ${e.fontes.join('+')}${sim}`);
3707
+ console.log(` ${e.resumo}`);
3708
+ });
3709
+ console.log('');
3710
+ console.log(` ${r.resultados.length} resultado(s); busca por tag continua em ork memory search --tags`);
3711
+ return 0;
3712
+ }
3713
+ /** Texto de `ork memory index`: o que foi (ou seria) embedado e quanto custa estimado. */
3714
+ function textoDoIndice(r) {
3715
+ const custo = r.custoEstimadoUsd === null ? 'nao estimado' : `US$ ${r.custoEstimadoUsd.toFixed(8)}`;
3716
+ return [
3717
+ `Indice vetorial (${r.alvo}${r.dryRun ? ', --dry-run' : ''}): ${r.modelo ?? '(sem modelo)'}${r.dim ? ` / ${r.dim} dim` : ''}`,
3718
+ ` universo do tenant ${r.universo} entrada(s); coerentes ${r.coerentes}`,
3719
+ ` embedados ${r.embedados} (reescritos ${r.reescritos}); removidos ${r.removidos}`,
3720
+ ` fora do indice ${r.recusados} recusada(s) por padrao de segredo, ${r.foraDoLimite} acima do limite`,
3721
+ ...(r.truncados ? [` truncados ${r.truncados} acima do contexto do modelo local, embedados pelo comeco`] : []),
3722
+ ` estimativa ${r.tokensEstimados} token(s), ${custo}; chamadas ao provider ${r.chamadasAoProvider}`,
3723
+ ...(r.arquivo ? [` arquivo ${r.arquivo}`] : []),
3724
+ ...(r.motivo ? [` motivo ${r.motivo}: ${r.detalhe}`] : r.detalhe ? [` ${r.detalhe}`] : []),
3725
+ ].join('\n');
3726
+ }
3727
+ /**
3728
+ * RM-052: `--projeto <nome|caminho>` e opcao GLOBAL. Sai do argv em qualquer posicao, antes de
3729
+ * qualquer despacho (inclusive do `maestro`, que tem parse proprio), e so aparece uma vez.
3730
+ */
3731
+ function extrairOpcaoDeProjeto(argv) {
3732
+ const resto = [];
3733
+ let projeto;
3734
+ for (let i = 0; i < argv.length; i++) {
3735
+ const a = argv[i];
3736
+ if (a !== '--projeto' && !a.startsWith('--projeto=')) {
3737
+ resto.push(a);
3738
+ continue;
3739
+ }
3740
+ if (projeto !== undefined)
3741
+ throw new Error('uso: --projeto <nome|caminho> aparece uma vez só');
3742
+ if (a !== '--projeto') {
3743
+ projeto = a.slice('--projeto='.length);
3744
+ continue;
3745
+ }
3746
+ const valor = argv[i + 1];
3747
+ projeto = valor !== undefined && !valor.startsWith('--') ? valor : '';
3748
+ if (projeto)
3749
+ i++;
3750
+ }
3751
+ return { argv: resto, projeto };
3752
+ }
3753
+ /** Comandos que nao leem projeto: o alvo nao e resolvido (nem recusado) para eles. */
3754
+ const COMANDOS_SEM_PROJETO = new Set(['demo', 'ciclos', 'mcp', 'init', 'projetos']);
3755
+ /**
3756
+ * Comandos cujo `--projeto` e DELES (RM-054: `ork network roadmap --projeto github:dono/repo`, que
3757
+ * le varios projetos). A opcao volta intacta ao argv do subcomando e o alvo global nao e resolvido:
3758
+ * nem `--projeto`, nem `ORK_PROJETO`, nem o modo host escolhem um projeto por eles.
3759
+ */
3760
+ exports.COMANDOS_COM_PROJETO_PROPRIO = new Set(['network']);
3761
+ /** Resolve e fixa o projeto-alvo do processo (D2, D3). `null`: vale o cwd de sempre. */
3762
+ function fixarAlvoDoProcesso(projeto) {
3763
+ const alvo = (0, projeto_alvo_1.resolverProjetoAlvo)({ opcao: projeto ?? null });
3764
+ (0, projeto_alvo_1.fixarProjetoAlvo)(alvo);
3765
+ return alvo;
3766
+ }
3767
+ function main(argvBruto) {
3768
+ // I-35: todo horário para pessoa sai no fuso do dono deste projeto (lido só se for preciso, e já
3769
+ // depois de o projeto-alvo abaixo estar fixado: a fonte é preguiçosa).
3269
3770
  (0, horario_1.registrarFonteDoFuso)(() => (0, horario_1.fusoDoManifesto)((0, manifest_1.carregarManifesto)()));
3771
+ // RM-052: sem alvo herdado de uma chamada anterior no mesmo processo (os testes chamam `main` em serie).
3772
+ (0, projeto_alvo_1.fixarProjetoAlvo)(null);
3773
+ const extraida = extrairOpcaoDeProjeto(argvBruto);
3774
+ const proprio = exports.COMANDOS_COM_PROJETO_PROPRIO.has(parseArgs(extraida.argv).posicionais[0] ?? '');
3775
+ const argv = proprio && extraida.projeto !== undefined
3776
+ ? [...extraida.argv, ...(extraida.projeto ? ['--projeto', extraida.projeto] : ['--projeto'])] : extraida.argv;
3777
+ const projeto = proprio ? undefined : extraida.projeto;
3270
3778
  // Helper fixo do host confiável: o projeto vem da instalação, nunca de toolargs.
3271
3779
  if (argv[0] === 'receipt-verifiers') {
3272
- if (argv.length !== 2 || argv[1] !== '--json')
3780
+ if (argv.length !== 2 || argv[1] !== '--json' || projeto !== undefined)
3273
3781
  throw Error('uso: ork receipt-verifiers --json');
3274
3782
  const root = process.env.ORK_HITL_ROOT;
3275
3783
  const privateKey = Object.keys(process.env).some(name => /^ORK_HITL_(?:INGRESS_KEY|NATIVE_KEY)/.test(name));
@@ -3285,8 +3793,14 @@ function main(argv) {
3285
3793
  console.log((0, hitl_public_receipt_1.publicHitlVerifiers)() ?? 'null');
3286
3794
  return 0;
3287
3795
  }
3288
- if (argv[0] === 'maestro')
3289
- return (0, maestro_cli_1.runMaestroCli)(argv.slice(1));
3796
+ if (argv[0] === 'maestro') {
3797
+ if (argv.length === 2 && argv[1] === '--help')
3798
+ return (0, maestro_cli_1.runMaestroCli)(argv.slice(1));
3799
+ // RM-052: o alvo explicito vira SELECAO entre as raizes permitidas; sem ele, o cwd de sempre.
3800
+ const alvo = fixarAlvoDoProcesso(projeto);
3801
+ return alvo ? (0, maestro_cli_1.runMaestroCli)(argv.slice(1), alvo.raiz, { allowedRoots: [alvo.raiz], selected: alvo.raiz })
3802
+ : (0, maestro_cli_1.runMaestroCli)(argv.slice(1));
3803
+ }
3290
3804
  const args = parseArgs(argv);
3291
3805
  const comando = args.posicionais[0];
3292
3806
  // `ork --version` tambem chega sem comando: a versao e conferida antes da ajuda.
@@ -3298,6 +3812,14 @@ function main(argv) {
3298
3812
  console.log(AJUDA);
3299
3813
  return 0;
3300
3814
  }
3815
+ if (!COMANDOS_SEM_PROJETO.has(comando) && !proprio)
3816
+ fixarAlvoDoProcesso(projeto);
3817
+ else if (projeto !== undefined && comando !== 'projetos') {
3818
+ throw new Error(comando === 'init'
3819
+ ? 'uso: ork init cria o projeto no diretório atual; entre nele e rode ork init, sem --projeto'
3820
+ : comando === 'mcp' ? 'uso: o servidor MCP recebe a raiz por --project <raiz absoluta>, não por --projeto'
3821
+ : `uso: ork ${comando} não lê projeto; tire --projeto`);
3822
+ }
3301
3823
  const nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)();
3302
3824
  const ambienteManifesto = (0, manifest_1.carregarManifesto)();
3303
3825
  if (ambienteManifesto?.manifesto.runtime.provider_policy === 'subscription-only') {
@@ -3347,11 +3869,11 @@ function main(argv) {
3347
3869
  if (args.posicionais.length !== 1 || !bruto ||
3348
3870
  Object.keys(args.opcoes).some(k => k !== 'modo') || argv.filter(a => a === '--modo' || a.startsWith('--modo=')).length !== 1)
3349
3871
  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);
3872
+ const r = (0, preflight_1.preflight)((0, manifest_1.diretorioDoProjeto)(), (0, modos_1.exigirModoVivo)(bruto), nomesHerdados);
3351
3873
  console.log((0, preflight_1.textoPreflight)(r));
3352
3874
  return r.prontoPrimeiroBloco ? 0 : 1;
3353
3875
  }
3354
- const r = (0, doctor_1.doctor)(process.cwd(), nomesHerdados);
3876
+ const r = (0, doctor_1.doctor)((0, manifest_1.diretorioDoProjeto)(), nomesHerdados);
3355
3877
  console.log(r.texto);
3356
3878
  return r.codigo;
3357
3879
  }
@@ -3363,6 +3885,10 @@ function main(argv) {
3363
3885
  });
3364
3886
  const carregado = (0, manifest_1.exigirManifesto)(r.deteccao.raiz);
3365
3887
  const agents = (0, agents_md_1.atualizarAgentsMd)(r.deteccao.raiz, carregado.manifesto);
3888
+ // RM-052 (D7): o projeto entra no registro desta maquina; falha vira aviso, nunca derruba o init.
3889
+ const avisoDoRegistro = (0, projeto_alvo_1.registrarProjetoEmSilencio)(r.deteccao.raiz, 'init');
3890
+ if (avisoDoRegistro)
3891
+ console.error(avisoDoRegistro);
3366
3892
  if (!r.criado) {
3367
3893
  console.log(`Manifesto ja existe: ${r.caminho}`);
3368
3894
  console.log('Nada foi sobrescrito. Use --force para regerar.');
@@ -3430,6 +3956,30 @@ function main(argv) {
3430
3956
  return comandoAccounts(args);
3431
3957
  case 'onboarding':
3432
3958
  return comandoOnboarding(args);
3959
+ case 'experiencia': {
3960
+ if (args.posicionais[1] === 'uninstall') {
3961
+ const host = (0, hosts_1.parseHost)(args.posicionais[2]);
3962
+ if (!host || !['claude-code', 'codex'].includes(host) || args.posicionais.length !== 3 ||
3963
+ Object.keys(args.opcoes).some(k => !['dry-run', 'json'].includes(k)) ||
3964
+ Object.values(args.opcoes).some(v => v !== true))
3965
+ throw Error('uso: ork experiencia uninstall claude-code|codex [--dry-run] [--json]');
3966
+ const r = (0, hosts_2.desinstalarExperiencia)((0, manifest_1.exigirManifesto)().raiz, host, args.opcoes['dry-run'] === true);
3967
+ console.log(args.opcoes.json ? JSON.stringify(r, null, 2) :
3968
+ `${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.`);
3969
+ return 0;
3970
+ }
3971
+ if ((args.posicionais[1] ?? 'show') !== 'show' || args.posicionais.length > 2 ||
3972
+ Object.keys(args.opcoes).some(k => k !== 'json') || ('json' in args.opcoes && args.opcoes.json !== true)) {
3973
+ throw Error('uso: ork experiencia show [--json]');
3974
+ }
3975
+ const manifesto = (0, manifest_1.exigirManifesto)(), p = (0, experiencia_1.resolverExperiencia)(manifesto.manifesto.owner);
3976
+ // Preferência inválida vale o padrão e faz o adapter install pular o pacote: a consulta avisa.
3977
+ const avisos = manifesto.avisos.filter(a => a.startsWith('experiencia.config.invalid'));
3978
+ console.log(args.opcoes.json ? JSON.stringify({ ...p, avisos }, null, 2) :
3979
+ `Experiência ${p.experience ? 'ativa' : 'desativada'}: ${p.language}, ${p.timezone}, profundidade ${p.depth}.\nSkill: ${p.skill}\nOrigens: ${JSON.stringify(p.origem)}` +
3980
+ avisos.map(a => `\nAviso: ${a}; o adapter install pula o pacote até ork onboarding set maestro corrigir.`).join(''));
3981
+ return 0;
3982
+ }
3433
3983
  case 'thread':
3434
3984
  return comandoThread(args);
3435
3985
  case 'objective':
@@ -3494,6 +4044,11 @@ function main(argv) {
3494
4044
  }
3495
4045
  case 'memory':
3496
4046
  return comandoMemory(args);
4047
+ case 'grafo': {
4048
+ // RM-031 KG3 (D7): o argv cru depois do comando; o parser do grafo e estrito.
4049
+ const carregado = (0, manifest_1.exigirManifesto)();
4050
+ 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) });
4051
+ }
3497
4052
  case 'ship':
3498
4053
  return comandoShip(args);
3499
4054
  case 'activation':
@@ -3530,6 +4085,10 @@ function main(argv) {
3530
4085
  }
3531
4086
  case 'fabrica':
3532
4087
  return comandoFabrica(args);
4088
+ case 'projetos':
4089
+ return comandoProjetos(args, projeto);
4090
+ case 'network':
4091
+ return comandoNetwork(args);
3533
4092
  case 'licoes':
3534
4093
  return comandoLicoes(args);
3535
4094
  case 'ciclos':
@@ -3551,6 +4110,11 @@ if (require.main === module) {
3551
4110
  console.log(process.argv.includes('--json') ? JSON.stringify(e.recusa, null, 2) : e.recusa.texto);
3552
4111
  process.exitCode = 3;
3553
4112
  }
4113
+ else if (e instanceof projeto_alvo_1.ErroDeProjeto) {
4114
+ // RM-052 (D3): a recusa de projeto-alvo e a resposta (a escolha, os candidatos), nao um stack trace.
4115
+ console.log(process.argv.includes('--json') ? JSON.stringify(e.recusa, null, 2) : e.texto);
4116
+ process.exitCode = projeto_alvo_1.SAIDA_DE_PROJETO;
4117
+ }
3554
4118
  else {
3555
4119
  console.error(`erro: ${e.message}`);
3556
4120
  process.exitCode = 1;