@orkastery/cli 0.6.0 → 0.6.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 (65) hide show
  1. package/adapters/openclaw/openclaw.plugin.json +1 -1
  2. package/adapters/openclaw/package.json +1 -1
  3. package/dist/adapters/claude-bg.js +6 -6
  4. package/dist/adapters/grok-events.js +227 -0
  5. package/dist/adapters/grok-mcp-servidor.js +612 -0
  6. package/dist/adapters/grok-mcp.js +178 -0
  7. package/dist/adapters/grok.js +686 -0
  8. package/dist/agendador-cpu.js +92 -0
  9. package/dist/branch-de-estado.js +7 -2
  10. package/dist/check-agil.js +48 -20
  11. package/dist/check-paralelo.js +73 -18
  12. package/dist/conducao.js +5 -0
  13. package/dist/docs.js +9 -16
  14. package/dist/doctor-forja.js +1 -3
  15. package/dist/doctor.js +1 -1
  16. package/dist/entrega-pr.js +10 -10
  17. package/dist/fabrica-estado.js +20 -11
  18. package/dist/horario.js +4 -1
  19. package/dist/index.js +20 -10
  20. package/dist/integracoes-locais.js +2 -0
  21. package/dist/locale-accounts.js +11 -3
  22. package/dist/locale-ajuda.js +10 -6
  23. package/dist/locale-forja.js +2 -4
  24. package/dist/locale-operacao-restante.js +2 -2
  25. package/dist/locale-retry.js +40 -2
  26. package/dist/locale-ship.js +10 -2
  27. package/dist/manifest.js +6 -1
  28. package/dist/mcp-install.js +22 -12
  29. package/dist/mcp-server.js +42 -16
  30. package/dist/merge-da-entrega.js +85 -0
  31. package/dist/network-roadmap.js +18 -14
  32. package/dist/noctum-aceite.js +154 -14
  33. package/dist/noctum-cli.js +69 -12
  34. package/dist/noctum-entrega.js +55 -7
  35. package/dist/noctum-envelope.js +1 -1
  36. package/dist/noctum-execucao.js +5 -1
  37. package/dist/noctum-fechamento.js +18 -7
  38. package/dist/noctum-fila.js +6 -1
  39. package/dist/noctum-guarda.js +81 -4
  40. package/dist/noctum-maquinas.js +5 -1
  41. package/dist/noctum-modo.js +35 -7
  42. package/dist/noctum-reconciliacao.js +4 -1
  43. package/dist/noctum-rede.js +102 -0
  44. package/dist/noctum-relatorio.js +44 -10
  45. package/dist/noctum-retomada-rede.js +71 -0
  46. package/dist/noctum-vigia.js +49 -9
  47. package/dist/parado-no-condutor.js +14 -15
  48. package/dist/phase.js +43 -15
  49. package/dist/postura-local.js +7 -3
  50. package/dist/preflight.js +2 -1
  51. package/dist/ratelimit.js +1 -0
  52. package/dist/retry.js +103 -10
  53. package/dist/runtime-context.js +165 -45
  54. package/dist/runtime-escada.js +7 -1
  55. package/dist/runtime-profiles.js +27 -17
  56. package/dist/runtimes.js +42 -5
  57. package/dist/security-scan/agil.js +18 -7
  58. package/dist/security-scan/executor.js +8 -0
  59. package/dist/session-watcher-grok.js +425 -0
  60. package/dist/session-watcher.js +19 -4
  61. package/dist/sessoes-contas.js +33 -5
  62. package/dist/setup.js +11 -11
  63. package/dist/varredura-acoes.js +8 -15
  64. package/dist/verify.js +26 -10
  65. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -146,6 +146,7 @@ const setup_1 = require("./setup");
146
146
  const runtime_profiles_1 = require("./runtime-profiles");
147
147
  const claude_bg_1 = require("./adapters/claude-bg");
148
148
  const codex_1 = require("./adapters/codex");
149
+ const grok_1 = require("./adapters/grok");
149
150
  const conducao_1 = require("./conducao");
150
151
  const conducao_sentinela_1 = require("./conducao-sentinela");
151
152
  const autorizacao_duravel_1 = require("./autorizacao-duravel");
@@ -663,8 +664,9 @@ function comandoOnboarding(args) {
663
664
  }
664
665
  /**
665
666
  * I-33 (D8): `ork accounts list|add|remove|check`. O login e sempre do proprio CLI com o env do
666
- * perfil (`claude auth login`, `codex login`); o `ork` so guarda identidade, diretorio e estado,
667
- * nunca le, copia ou migra o que o CLI grava. A lista nao tem segredo porque o store nao tem.
667
+ * perfil (`claude auth login`, `codex login`, `grok login [--device-auth]`); o `ork` so guarda identidade,
668
+ * diretorio e estado, nunca le, copia ou migra o que o CLI grava (o `auth.json` do grok inclusive). A lista
669
+ * nao tem segredo porque o store nao tem.
668
670
  */
669
671
  /** A8: valor citado para colar no shell: aspas simples, e a aspa simples do proprio valor fechada e reaberta. */
670
672
  function aspasDeShell(valor) {
@@ -685,7 +687,8 @@ function comandoAccounts(args) {
685
687
  const raiz = carregado.raiz;
686
688
  const sub = args.posicionais[1] ?? 'list';
687
689
  // RM-061 (F3b, GO-FIX 1): a conferencia roda no escopo pt-BR (o detalhe vai ao store), e a impressao o traduz.
688
- const conferir = (p) => (0, locale_1.comLocale)('pt-BR', () => p.runtime === 'claude-bg' ? (0, claude_bg_1.conferirAuth)(p) : (0, codex_1.conferirAuth)(p));
690
+ const conferir = (p) => (0, locale_1.comLocale)('pt-BR', () => p.runtime === 'claude-bg' ? (0, claude_bg_1.conferirAuth)(p)
691
+ : p.runtime === 'grok' ? (0, grok_1.conferirAuth)(p) : (0, codex_1.conferirAuth)(p));
689
692
  const detalhe = (auth) => ma.detalheDoLogin((0, locale_1.remontar)(auth.detalhe));
690
693
  // RM-061 (F3b, D3): o texto pelo catalogo; o que se grava (store de perfis, registro de contas) roda no escopo pt-BR,
691
694
  // e o id, o runtime, o diretorio, o motivo tipado e o detalhe que o CLI do runtime devolve saem como vieram.
@@ -709,7 +712,9 @@ function comandoAccounts(args) {
709
712
  }
710
713
  if (sub === 'add') {
711
714
  const id = args.posicionais[2], runtime = texto(args.opcoes.runtime), dirBruto = texto(args.opcoes.dir);
712
- if (!id || !runtime || !dirBruto) {
715
+ // RM-067 (F3): o codigo de dispositivo e do login do grok; nos outros runtimes, a opcao e recusada.
716
+ const dispositivo = args.opcoes['device-auth'] === true;
717
+ if (!id || !runtime || !dirBruto || (dispositivo && runtime !== 'grok')) {
713
718
  console.error(ma.usoAdd);
714
719
  return 2;
715
720
  }
@@ -730,10 +735,13 @@ function comandoAccounts(args) {
730
735
  const despacho = (0, runtime_profiles_1.perfilDeDespacho)(perfil);
731
736
  const variavel = runtime_profiles_1.VARIAVEL_DO_PERFIL[perfil.runtime];
732
737
  // D13: o login do claude e fixado na assinatura (`--claudeai`), nunca no Console de API.
733
- const comando = perfil.runtime === 'claude-bg' ? ['claude', 'auth', 'login', '--claudeai'] : ['codex', 'login'];
738
+ // RM-067 (F3, D1 b): o grok entra pela assinatura, no login do proprio CLI (navegador ou codigo de dispositivo).
739
+ const comando = perfil.runtime === 'claude-bg' ? ['claude', 'auth', 'login', '--claudeai']
740
+ : perfil.runtime === 'grok' ? (0, grok_1.comandoDeLogin)(dispositivo) : ['codex', 'login'];
734
741
  if (args.opcoes['sem-login'] !== true && process.stdin.isTTY && process.stdout.isTTY) {
735
742
  // Login interativo do proprio CLI, com o env do perfil sobre a assinatura higienizada.
736
- const env = perfil.runtime === 'claude-bg' ? (0, claude_bg_1.ambienteDoPerfil)(despacho) : (0, codex_1.ambienteDoDespacho)(process.env, despacho);
743
+ const env = perfil.runtime === 'claude-bg' ? (0, claude_bg_1.ambienteDoPerfil)(despacho)
744
+ : perfil.runtime === 'grok' ? (0, grok_1.ambienteDoFilho)({ perfil: despacho }) : (0, codex_1.ambienteDoDespacho)(process.env, despacho);
737
745
  (0, node_child_process_1.spawnSync)(comando[0], comando.slice(1), { stdio: 'inherit', env });
738
746
  }
739
747
  else {
@@ -745,7 +753,7 @@ function comandoAccounts(args) {
745
753
  (0, locale_1.comLocale)('pt-BR', () => (0, runtime_profiles_1.marcarFalhaDePerfil)(raiz, id, auth.pago
746
754
  ? { estado: 'provider-pago', esgotadoAte: null, motivo: 'cost.violation', detalhe: auth.detalhe }
747
755
  : { estado: 'sem-auth', esgotadoAte: null, motivo: 'runtime.auth-missing', detalhe: auth.detalhe }));
748
- console.log(ma.resultadoAdd(id, perfil.runtime, dir, auth.ok ? ma.conferido
756
+ console.log(ma.resultadoAdd(id, perfil.runtime, dir, auth.semConferencia ? ma.semConferenciaAdd(detalhe(auth)) : auth.ok ? ma.conferido
749
757
  : auth.transitorio ? ma.inconclusivaAdd(detalhe(auth))
750
758
  : auth.pago ? ma.pagoAdd(detalhe(auth)) : ma.semLoginAdd(detalhe(auth))));
751
759
  return 0;
@@ -779,7 +787,8 @@ function comandoAccounts(args) {
779
787
  for (const p of perfis) {
780
788
  const auth = conferir((0, runtime_profiles_1.perfilDeDespacho)(p));
781
789
  (0, locale_1.comLocale)('pt-BR', () => {
782
- if (auth.ok && (p.estado === 'sem-auth' || p.estado === 'provider-pago'))
790
+ // RM-067 (F3): sem conferencia (grok), o estado fica: so o login que o proprio CLI confere devolve o perfil.
791
+ if (auth.ok && !auth.semConferencia && (p.estado === 'sem-auth' || p.estado === 'provider-pago'))
783
792
  (0, runtime_profiles_1.reativarPerfil)(raiz, p.id);
784
793
  if (!auth.ok && auth.transitorio)
785
794
  (0, runtime_profiles_1.registrarConferenciaInconclusiva)(raiz, p.id, auth.detalhe);
@@ -804,7 +813,7 @@ function comandoAccounts(args) {
804
813
  volta ? ma.voltaEm((0, horario_1.formatarDataHoraRotulada)(volta)) : ma.voltaSemMedida,
805
814
  ...(expirados.has(p.id) ? [ma.marcaExpirada] : []),
806
815
  ].join('; ');
807
- console.log(`${ma.resultadoCheck(p.id, p.runtime, auth.ok ? ma.conferido
816
+ console.log(`${ma.resultadoCheck(p.id, p.runtime, auth.semConferencia ? ma.semConferenciaCheck(detalhe(auth)) : auth.ok ? ma.conferido
808
817
  : auth.transitorio ? ma.inconclusivaCheck(detalhe(auth))
809
818
  : auth.pago ? ma.pagoCheck(detalhe(auth)) : ma.semLoginCheck(detalhe(auth)))}; ${operacional}`);
810
819
  }
@@ -4501,8 +4510,9 @@ function executarComando(argvBruto) {
4501
4510
  const permissoesFilho = texto(args.opcoes['child-permissions']) ?? 'interactive';
4502
4511
  const permissoesDono = texto(args.opcoes['owner-permissions']);
4503
4512
  const acao = args.posicionais[1];
4513
+ // RM-067 (F4b): o grok e host do install e do serve; o servidor dele recusa sem --thread (so a sessao filha).
4504
4514
  if (args.posicionais.length !== 2 || !['serve', 'install'].includes(acao) || !projeto ||
4505
- (host !== 'codex' && host !== 'claude-code') ||
4515
+ (host !== 'codex' && host !== 'claude-code' && host !== 'grok') ||
4506
4516
  Object.keys(args.opcoes).some(k => !['project', 'host', 'ship-transport', 'child-permissions', ...(acao === 'install' ? ['dry-run', 'owner-permissions', 'ssh-fingerprint'] : ['thread', 'dispatch'])].includes(k)) ||
4507
4517
  (args.opcoes.dispatch !== undefined && (!threadId || !dispatchId || !/^[a-f0-9-]{36}$/.test(dispatchId))) ||
4508
4518
  argv.filter(a => a === '--ship-transport' || a.startsWith('--ship-transport=')).length > 1 ||
@@ -22,4 +22,6 @@ exports.TESTES_DE_INTEGRACAO_LOCAL = new Set([
22
22
  'claims-conferir-sandbox.test.js',
23
23
  // Security scan (Task 13a): o scanner com o Docker real e as imagens do catalogo.
24
24
  'security-scan-integracao.test.js',
25
+ // RM-067 (F4c, D11): o grok falso confinado pelo Landlock do kernel, com o lancador em python3.
26
+ 'rm067-grok-landlock.test.js',
25
27
  ]);
@@ -12,7 +12,7 @@
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.ACCOUNTS_EN = exports.ACCOUNTS_PT_BR = void 0;
14
14
  /**
15
- * O detalhe da conferencia de login que o proprio ork escreve (`conferirAuth` do claude e do codex) e dado: vai ao store
15
+ * O detalhe da conferencia de login que o proprio ork escreve (`conferirAuth` do claude, do codex e do grok) e dado: vai ao store
16
16
  * em pt-BR e so a impressao o traduz, pela frase exata. A saida do CLI que vem dentro dele (o trecho do `codex`) segue
17
17
  * como veio.
18
18
  */
@@ -29,6 +29,10 @@ const DETALHES_DO_LOGIN_EN = [
29
29
  [/^codex login status: login por API key \(provider pago\)$/, () => 'codex login status: API key login (paid provider)'],
30
30
  [/^codex login status: login sem assinatura ChatGPT comprovada \(tratado como provider pago\)$/,
31
31
  () => 'codex login status: login without a proven ChatGPT subscription (treated as a paid provider)'],
32
+ [/^o grok nao documenta conferencia de login; o despacho prova o login \(erro de login do runtime vira runtime\.auth-missing\)$/,
33
+ () => 'grok documents no login check; the dispatch proves the login (a runtime login error becomes runtime.auth-missing)'],
34
+ [/^runtime\.profiles\.invalid: perfil sem grokHome no despacho grok$/,
35
+ () => 'runtime.profiles.invalid: profile without grokHome in the grok dispatch'],
32
36
  ];
33
37
  const ESTADOS_EN = {
34
38
  ativo: 'active', esgotado: 'exhausted', 'sem-auth': 'no-auth', 'provider-pago': 'paid-provider', desativado: 'disabled',
@@ -39,7 +43,7 @@ exports.ACCOUNTS_PT_BR = {
39
43
  /** O estado gravado no store, como o texto o mostra. */
40
44
  estado: (estado) => estado,
41
45
  falhaEm: (motivo, quando) => `${motivo} em ${quando}`,
42
- usoAdd: 'uso: ork accounts add <id> --runtime claude-bg|codex --dir <diretorio> [--sem-login]',
46
+ usoAdd: 'uso: ork accounts add <id> --runtime claude-bg|codex|grok --dir <diretorio> [--sem-login] [--device-auth (so grok)]',
43
47
  reativado: (id) => `Perfil ${id} reativado: mesmo id, runtime e diretorio do perfil desativado.`,
44
48
  recusado: (erro) => `perfil recusado: ${erro}`,
45
49
  loginPendente: (variavel, dir, comando, id) => `Login pendente: rode ${variavel}=${dir} ${comando} e depois ork accounts check ${id}`,
@@ -48,6 +52,7 @@ exports.ACCOUNTS_PT_BR = {
48
52
  /** O detalhe da conferencia de login (dado do store), como a impressao o mostra. */
49
53
  detalheDoLogin: (detalhe) => detalhe,
50
54
  inconclusivaAdd: (detalhe) => `conferencia de login inconclusiva (${detalhe}); o proximo despacho confere de novo`,
55
+ semConferenciaAdd: (detalhe) => `login sem conferencia previa (${detalhe}); o perfil entra no rodizio`,
51
56
  pagoAdd: (detalhe) => `provider pago (${detalhe}); nunca recebe despacho`,
52
57
  semLoginAdd: (detalhe) => `sem login (${detalhe}); fora do rodizio`,
53
58
  usoRemove: 'uso: ork accounts remove <id>',
@@ -55,6 +60,7 @@ exports.ACCOUNTS_PT_BR = {
55
60
  perfilAtivoNaoExiste: (alvo) => `perfil ativo "${alvo}" nao existe (veja: ork accounts list)`,
56
61
  resultadoCheck: (id, runtime, situacao) => `${id} (${runtime}): ${situacao}`,
57
62
  inconclusivaCheck: (detalhe) => `conferencia de login inconclusiva, estado mantido (${detalhe})`,
63
+ semConferenciaCheck: (detalhe) => `login sem conferencia previa, estado mantido (${detalhe})`,
58
64
  pagoCheck: (detalhe) => `provider pago, nunca despacha (${detalhe})`,
59
65
  semLoginCheck: (detalhe) => `sem login (${detalhe})`,
60
66
  tipoDeLimite: (tipo) => ({ sessao: 'sessao', semanal: 'semanal', 'gasto-admin': 'gasto definido pelo admin',
@@ -132,7 +138,7 @@ exports.ACCOUNTS_EN = {
132
138
  colunas: ['PROFILE', 'RUNTIME', 'DIRECTORY', 'STATE', 'EXHAUSTED UNTIL', 'LAST USE', 'LAST FAILURE'],
133
139
  estado: (estado) => ESTADOS_EN[estado] ?? estado,
134
140
  falhaEm: (motivo, quando) => `${motivo} at ${quando}`,
135
- usoAdd: 'usage: ork accounts add <id> --runtime claude-bg|codex --dir <directory> [--sem-login]',
141
+ usoAdd: 'usage: ork accounts add <id> --runtime claude-bg|codex|grok --dir <directory> [--sem-login] [--device-auth (grok only)]',
136
142
  reativado: (id) => `Profile ${id} reactivated: same id, runtime and directory as the disabled profile.`,
137
143
  recusado: (erro) => `profile refused: ${erro}`,
138
144
  loginPendente: (variavel, dir, comando, id) => `Login pending: run \`${variavel}=${dir} ${comando}\`, then \`ork accounts check ${id}\``,
@@ -143,6 +149,7 @@ exports.ACCOUNTS_EN = {
143
149
  return regra ? regra[1](...(regra[0].exec(detalhe) ?? []).slice(1)) : detalhe;
144
150
  },
145
151
  inconclusivaAdd: (detalhe) => `login check inconclusive (${detalhe}); the next dispatch checks again`,
152
+ semConferenciaAdd: (detalhe) => `login without a prior check (${detalhe}); the profile joins the rotation`,
146
153
  pagoAdd: (detalhe) => `paid provider (${detalhe}); never receives a dispatch`,
147
154
  semLoginAdd: (detalhe) => `no login (${detalhe}); out of the rotation`,
148
155
  usoRemove: 'usage: ork accounts remove <id>',
@@ -150,6 +157,7 @@ exports.ACCOUNTS_EN = {
150
157
  perfilAtivoNaoExiste: (alvo) => `active profile "${alvo}" does not exist (see: \`ork accounts list\`)`,
151
158
  resultadoCheck: (id, runtime, situacao) => `${id} (${runtime}): ${situacao}`,
152
159
  inconclusivaCheck: (detalhe) => `login check inconclusive, state kept (${detalhe})`,
160
+ semConferenciaCheck: (detalhe) => `login without a prior check, state kept (${detalhe})`,
153
161
  pagoCheck: (detalhe) => `paid provider, never dispatches (${detalhe})`,
154
162
  semLoginCheck: (detalhe) => `no login (${detalhe})`,
155
163
  tipoDeLimite: (tipo) => ({ sessao: 'session', semanal: 'weekly', 'gasto-admin': 'admin-defined spend',
@@ -33,12 +33,12 @@ Uso: ork [--projeto <nome|caminho>] <comando> [argumentos]
33
33
  experiencia uninstall <host> [--dry-run] [--json]
34
34
  Remove o bloco de Claude Code/Codex; sem --dry-run aplica a remoção
35
35
  setup <modo> Config atual de cada bloco do modo
36
- setup <modo> --bloco N [--runtime R] Edita o bloco (runtimes: claude-bg, codex);
36
+ setup <modo> --bloco N [--runtime R] Edita o bloco (runtimes: claude-bg, codex, grok);
37
37
  [--model M] [--effort E] [--por Q] evento setup_configured no ledger do projeto
38
38
  [--fallback R:M[:E],...] ordem de fallback de runtime do bloco (I-33)
39
39
  accounts list [--json] Perfis de conta por runtime, sem segredo (I-33)
40
40
  accounts add <id> --runtime R --dir D Cria o perfil e roda o login do proprio CLI com o env
41
- [--sem-login] do perfil (nunca copia credencial)
41
+ [--sem-login] [--device-auth] do perfil (nunca copia credencial; codigo de dispositivo so no grok)
42
42
  accounts remove <id> Desativa o perfil (diretorio e login ficam onde estao)
43
43
  accounts check [<id>] Confere o login de cada perfil e marca o store
44
44
  accounts esgotamentos [--desde 7d] [--json]
@@ -120,6 +120,8 @@ Uso: ork [--projeto <nome|caminho>] <comando> [argumentos]
120
120
  destrava (pega HITL de sessao SEM thread)
121
121
  noctum propor --arquivo <envelope.json> Propõe o envelope de um arco #Noctum (RM-058) e pergunta ao dono, com código
122
122
  curto e alternativas, também no canal dele; não autoriza nada
123
+ noctum maquina [--json] A entrada desta máquina em maquinas do envelope v3 (RM-058): o nome, a chave
124
+ pública e a impressão dela; a chave privada não sai desta raiz
123
125
  noctum revogar <arco> [--json] Pergunta ao dono se revoga o arco (RM-057); quem revoga é a resposta dele,
124
126
  no Telegram ou pelo diálogo do host
125
127
  noctum responder <arco> --resposta-stdin --origem telegram --canal C --por ID --mensagem REF [--conta ID]
@@ -352,7 +354,7 @@ Uso: ork [--projeto <nome|caminho>] <comando> [argumentos]
352
354
  o padrao e o item dela; --todos volta a todo item (RM-037)
353
355
  docs init Cria padroes, modelos, indices e o lint de Markdown no projeto
354
356
 
355
- mcp serve --project RAIZ --host HOST Servidor MCP stdio deste projeto (codex|claude-code)
357
+ mcp serve --project RAIZ --host HOST Servidor MCP stdio deste projeto (codex|claude-code; grok so na sessao filha, com --thread)
356
358
  mcp install --project RAIZ --host HOST Prepara MCP; aceita --dry-run, --ship-transport, --child-permissions e --owner-permissions (Codex)
357
359
 
358
360
  adapter list Adaptadores de host (Camada 1) e o destino de cada um
@@ -445,12 +447,12 @@ Usage: ork [--projeto <name|path>] <command> [arguments]
445
447
  experiencia uninstall <host> [--dry-run] [--json]
446
448
  Removes the Claude Code/Codex block; without --dry-run it applies the removal
447
449
  setup <mode> Current config of each block of the mode
448
- setup <mode> --bloco N [--runtime R] Edits the block (runtimes: claude-bg, codex);
450
+ setup <mode> --bloco N [--runtime R] Edits the block (runtimes: claude-bg, codex, grok);
449
451
  [--model M] [--effort E] [--por Q] setup_configured event in the project ledger
450
452
  [--fallback R:M[:E],...] runtime fallback order of the block (I-33)
451
453
  accounts list [--json] Account profiles per runtime, without secrets (I-33)
452
454
  accounts add <id> --runtime R --dir D Creates the profile and runs the CLI's own login with the profile
453
- [--sem-login] env (never copies a credential)
455
+ [--sem-login] [--device-auth] env (never copies a credential; device code only for grok)
454
456
  accounts remove <id> Deactivates the profile (directory and login stay where they are)
455
457
  accounts check [<id>] Checks the login of each profile and marks the store
456
458
  accounts esgotamentos [--desde 7d] [--json]
@@ -532,6 +534,8 @@ Usage: ork [--projeto <name|path>] <command> [arguments]
532
534
  unblocks it (catches HITL of sessions WITHOUT a thread)
533
535
  noctum propor --arquivo <envelope.json> Proposes the envelope of a #Noctum arc (RM-058) and asks the owner, with a short
534
536
  code and choices, also on the owner's channel; it authorizes nothing
537
+ noctum maquina [--json] This machine's entry in maquinas of the v3 envelope (RM-058): its name, public key
538
+ and fingerprint; the private key never leaves this root
535
539
  noctum revogar <arc> [--json] Asks the owner whether to revoke the arc (RM-057); the owner's answer revokes,
536
540
  on Telegram or through the host dialog
537
541
  noctum responder <arc> --resposta-stdin --origem telegram --canal C --por ID --mensagem REF [--conta ID]
@@ -764,7 +768,7 @@ Usage: ork [--projeto <name|path>] <command> [arguments]
764
768
  the default is its item; --todos goes back to every item (RM-037)
765
769
  docs init Creates standards, templates, indexes and the Markdown lint in the project
766
770
 
767
- mcp serve --project ROOT --host HOST stdio MCP server of this project (codex|claude-code)
771
+ mcp serve --project ROOT --host HOST stdio MCP server of this project (codex|claude-code; grok only in the child session, with --thread)
768
772
  mcp install --project ROOT --host HOST Prepares MCP; accepts --dry-run, --ship-transport, --child-permissions and --owner-permissions (Codex)
769
773
 
770
774
  adapter list Host adapters (Layer 1) and the target of each one
@@ -95,10 +95,9 @@ exports.FORJA_PT_BR = {
95
95
  projetoGitlab: (metodo, squash, mergedResults, mergeTrain) => `merge ${metodo}; squash ${squash}; merged results ${mergedResults}; merge train ${mergeTrain}`,
96
96
  projetoGithub: (merge, squash, rebase) => `merge commit ${merge}; squash ${squash}; rebase ${rebase}`,
97
97
  avisoFf: 'com fast-forward não há commit de merge: o assunto ship(<thread>) não chega à base',
98
- avisoMensagemPadrao: 'a mensagem de merge padrão (Merge branch …) não começa por ship(<thread>)',
99
98
  avisoSquash: (opcao) => `squash ${opcao}: a entrega por squash não se liga ao head verificado (entrega.sem-vinculo)`,
100
99
  avisoSemMergeCommit: 'sem merge commit, a entrega por PR não se liga ao head verificado (entrega.sem-vinculo)',
101
- projetoGitlabCorrecao: 'em Settings > Merge requests, use merge commit e um modelo de mensagem de merge que comece por %{title}',
100
+ projetoGitlabCorrecao: 'em Settings > Merge requests, use merge commit e deixe squash desativado',
102
101
  projetoGithubCorrecao: 'em Settings > General > Pull Requests, permita merge commits',
103
102
  capacidades: (ligadas) => `ligadas: ${ligadas}`,
104
103
  capacidadesDesligadas: (ligadas, desligadas) => `ligadas: ${ligadas}; desligadas (o adaptador não implementa): ${desligadas}`,
@@ -236,10 +235,9 @@ exports.FORJA_EN = {
236
235
  projetoGitlab: (metodo, squash, mergedResults, mergeTrain) => `merge ${metodo}; squash ${squash}; merged results ${mergedResults}; merge train ${mergeTrain}`,
237
236
  projetoGithub: (merge, squash, rebase) => `merge commit ${merge}; squash ${squash}; rebase ${rebase}`,
238
237
  avisoFf: 'with fast-forward there is no merge commit: the ship(<thread>) subject does not reach the base',
239
- avisoMensagemPadrao: 'the default merge message (Merge branch …) does not start with ship(<thread>)',
240
238
  avisoSquash: (opcao) => `squash ${opcao}: a squash delivery is not linked to the verified head (entrega.sem-vinculo)`,
241
239
  avisoSemMergeCommit: 'without merge commits, a PR delivery is not linked to the verified head (entrega.sem-vinculo)',
242
- projetoGitlabCorrecao: 'in Settings > Merge requests, use merge commit and a merge message template that starts with %{title}',
240
+ projetoGitlabCorrecao: 'in Settings > Merge requests, use merge commits and leave squash disabled',
243
241
  projetoGithubCorrecao: 'in Settings > General > Pull Requests, allow merge commits',
244
242
  capacidades: (ligadas) => `on: ${ligadas}`,
245
243
  capacidadesDesligadas: (ligadas, desligadas) => `on: ${ligadas}; off (the adapter does not implement them): ${desligadas}`,
@@ -446,7 +446,7 @@ exports.OPERACAO_RESTANTE_PT_BR = {
446
446
  },
447
447
  },
448
448
  mcp: {
449
- uso: 'uso: ork mcp serve|install --project <raiz absoluta> --host codex|claude-code [--ship-transport github-ssh|forja-ssh|forja-https|bare-local] [--ssh-fingerprint SHA256:... somente install forja-ssh] [--child-permissions interactive|worktree] [--owner-permissions interactive|orchestrate somente install Codex] [--dry-run somente install]',
449
+ uso: 'uso: ork mcp serve|install --project <raiz absoluta> --host codex|claude-code|grok [--ship-transport github-ssh|forja-ssh|forja-https|bare-local] [--ssh-fingerprint SHA256:... somente install forja-ssh] [--child-permissions interactive|worktree] [--owner-permissions interactive|orchestrate somente install Codex] [--dry-run somente install]',
450
450
  erro: (detalhe) => `mcp: ${detalhe}`,
451
451
  simulacao: 'Simulacao: nenhuma escrita.',
452
452
  preparada: 'Configuracao MCP preparada.',
@@ -921,7 +921,7 @@ exports.OPERACAO_RESTANTE_EN = {
921
921
  },
922
922
  },
923
923
  mcp: {
924
- uso: 'usage: ork mcp serve|install --project <absolute root> --host codex|claude-code [--ship-transport github-ssh|forja-ssh|forja-https|bare-local] [--ssh-fingerprint SHA256:... only for install with forja-ssh] [--child-permissions interactive|worktree] [--owner-permissions interactive|orchestrate only for Codex install] [--dry-run only for install]',
924
+ uso: 'usage: ork mcp serve|install --project <absolute root> --host codex|claude-code|grok [--ship-transport github-ssh|forja-ssh|forja-https|bare-local] [--ssh-fingerprint SHA256:... only for install with forja-ssh] [--child-permissions interactive|worktree] [--owner-permissions interactive|orchestrate only for Codex install] [--dry-run only for install]',
925
925
  erro: (detail) => `mcp: ${detail}`,
926
926
  simulacao: 'Simulation: no writes.',
927
927
  preparada: 'MCP configuration prepared.',
@@ -211,6 +211,24 @@ exports.RETRY_PT_BR = {
211
211
  correcoesNaRodada: (n, rodada, veredito) => `${n} correcao(oes) na rodada ${rodada}` + (veredito !== null ? `; CHECK-REVERIFY: ${veredito}` : ''),
212
212
  semDespachoFalho: (fase, thread) => `nao ha despacho falho registrado em ${fase} com prompt gravado: ` +
213
213
  `rode a fase de novo com \`ork phase run ${thread} ${fase} --prompt "..."\``,
214
+ perfilPedidoRecusado: (id, runtime, motivo, detalhe) => `perfil pedido "${id}" (${runtime}) preservado, mas indisponivel por ${motivo}: ${detalhe}. ` +
215
+ 'Nenhuma outra conta foi usada.',
216
+ correcaoDoPerfilPedido: (id, runtime, motivo, thread) => {
217
+ if (motivo === 'runtime.auth-missing')
218
+ return `refaca o login de assinatura do perfil "${id}" no ${runtime}, rode ` +
219
+ `\`ork accounts check ${id}\` e repita \`ork retry run ${thread}\``;
220
+ if (motivo === 'runtime.quota-exhausted')
221
+ return `aguarde o perfil "${id}" voltar a ativo em \`ork accounts list\` e ` +
222
+ `repita \`ork retry run ${thread}\`; para autorizar outra conta, rode a fase novamente sem \`--perfil\``;
223
+ if (motivo === 'runtime.profile-invalid')
224
+ return `rode \`ork accounts list\` e restaure o perfil "${id}" no runtime ${runtime}, ` +
225
+ 'ou rode a fase novamente com um perfil valido ou sem `--perfil`';
226
+ if (motivo === 'cost.violation')
227
+ return `refaca o login de assinatura do perfil "${id}", rode ` +
228
+ `\`ork accounts check ${id}\` e repita \`ork retry run ${thread}\`; perfil de provider pago nunca despacha`;
229
+ return `confira o runtime ${runtime} e o perfil "${id}" com \`ork accounts check ${id}\`; depois repita ` +
230
+ `\`ork retry run ${thread}\``;
231
+ },
214
232
  semConfianca: (motivo, cwd, thread) => `${motivo}: o runtime ainda nao confia em ${cwd}; nada foi despachado. ` +
215
233
  `Rode \`cd ${cwd} && claude\`, aceite a confianca e repita \`ork retry run ${thread}\``,
216
234
  /** RM-063 (F3): a sessao viva na thread; redespachar abriria a segunda na mesma worktree. */
@@ -254,7 +272,8 @@ exports.RETRY_PT_BR = {
254
272
  pulos: { 'sem-fallback': 'o bloco nao tem fallback de runtime',
255
273
  'adaptador-ausente': 'nenhum fallback tem adaptador instalado neste projeto',
256
274
  'fallback-sem-destino': 'nenhum alvo do fallback do bloco tem perfil disponivel',
257
- 'sem-outro-perfil': 'o runtime nao tem outro perfil disponivel' },
275
+ 'sem-outro-perfil': 'o runtime nao tem outro perfil disponivel',
276
+ 'cota-sem-sinal-tipado': 'o runtime ainda nao tipa a cota esgotada e fica fora da troca automatica de conta' },
258
277
  resultados: { redespachada: 'redespachada', falhou: 'falhou', pulado: 'pulado', interrompido: 'interrompido' },
259
278
  linhaDoDegrau: (n, tipo, resultado, motivo) => `degrau ${n} (${tipo}): ${resultado}${motivo ? ` (${motivo})` : ''}`,
260
279
  noPlano: (n, tipo) => ` escada degrau ${n} de 3, ${tipo}`,
@@ -466,6 +485,24 @@ exports.RETRY_EN = {
466
485
  correcoesNaRodada: (n, rodada, veredito) => `${n} fix(es) in round ${rodada}` + (veredito !== null ? `; CHECK-REVERIFY: ${veredito}` : ''),
467
486
  semDespachoFalho: (fase, thread) => `no failed dispatch with a written prompt is recorded in ${fase}: ` +
468
487
  `run the phase again with \`ork phase run ${thread} ${fase} --prompt "..."\``,
488
+ perfilPedidoRecusado: (id, runtime, motivo, detalhe) => `requested profile "${id}" (${runtime}) was preserved but is unavailable because of ${motivo}: ${detalhe}. ` +
489
+ 'No other account was used.',
490
+ correcaoDoPerfilPedido: (id, runtime, motivo, thread) => {
491
+ if (motivo === 'runtime.auth-missing')
492
+ return `sign profile "${id}" back in to its ${runtime} subscription, run ` +
493
+ `\`ork accounts check ${id}\`, and repeat \`ork retry run ${thread}\``;
494
+ if (motivo === 'runtime.quota-exhausted')
495
+ return `wait until profile "${id}" is active again in \`ork accounts list\`, then ` +
496
+ `repeat \`ork retry run ${thread}\`; to authorize another account, run the phase again without \`--perfil\``;
497
+ if (motivo === 'runtime.profile-invalid')
498
+ return `run \`ork accounts list\` and restore profile "${id}" under runtime ${runtime}, ` +
499
+ 'or run the phase again with a valid profile or without `--perfil`';
500
+ if (motivo === 'cost.violation')
501
+ return `sign profile "${id}" back in through the subscription, run ` +
502
+ `\`ork accounts check ${id}\`, and repeat \`ork retry run ${thread}\`; a paid-provider profile is never dispatched`;
503
+ return `check runtime ${runtime} and profile "${id}" with \`ork accounts check ${id}\`; then repeat ` +
504
+ `\`ork retry run ${thread}\``;
505
+ },
469
506
  semConfianca: (motivo, cwd, thread) => `${motivo}: the runtime does not trust ${cwd} yet; nothing was dispatched. ` +
470
507
  `Run \`cd ${cwd} && claude\`, accept the trust and repeat \`ork retry run ${thread}\``,
471
508
  sessaoAindaViva: (sessao, thread) => `session ${sessao} is still working on the thread in the runtime; nothing was ` +
@@ -505,7 +542,8 @@ exports.RETRY_EN = {
505
542
  'outro-perfil': 'another runtime profile' },
506
543
  pulos: { 'sem-fallback': 'the block has no runtime fallback', 'adaptador-ausente': 'no fallback has an adapter installed in this project',
507
544
  'fallback-sem-destino': 'no target of the block fallback has an available profile',
508
- 'sem-outro-perfil': 'the runtime has no other available profile' },
545
+ 'sem-outro-perfil': 'the runtime has no other available profile',
546
+ 'cota-sem-sinal-tipado': 'the runtime does not type the exhausted quota yet and stays out of the automatic account switch' },
509
547
  resultados: { redespachada: 'dispatched again', falhou: 'failed', pulado: 'skipped', interrompido: 'interrupted' },
510
548
  linhaDoDegrau: (n, tipo, resultado, motivo) => `step ${n} (${tipo}): ${resultado}${motivo ? ` (${motivo})` : ''}`,
511
549
  noPlano: (n, tipo) => ` ladder step ${n} of 3, ${tipo}`,
@@ -161,11 +161,15 @@ exports.SHIP_PT_BR = {
161
161
  situacoes: { 'proposto': 'proposto', 'agendado': 'agendado', 'vigente': 'vigente', 'expirado': 'expirado', 'revogado': 'revogado',
162
162
  'encerrado': 'encerrado' },
163
163
  origens: { 'envelope': 'pela lista do envelope', 'proposta': 'pela proposta que espera o dono', 'despacho': 'pelo log de despachos do arco',
164
- 'correlacao': 'pelo último despacho da thread' },
164
+ 'correlacao': 'pelo último despacho da thread', 'rede': 'pela rede do arco' },
165
165
  doArco: (thread, arco, situacao, origem) => `noctum.guarda.thread-do-arco: a thread ${thread} é trabalho do arco ${arco} (${situacao}, ${origem})`,
166
166
  doArcoCorrecao: (arco) => `a entrega desta thread é do passo da entrega do arco ${arco}: o SHIP e o MASTER dela são do arco (ork noctum status ${arco})`,
167
167
  arcoIlegivel: (thread, arco, motivo) => `noctum.guarda.arco-ilegivel: o último despacho da thread ${thread} foi do arco ${arco}, e o arco não se lê (${motivo})`,
168
168
  arcoIlegivelCorrecao: (arco) => `inspecione o arco antes de entregar a thread por fora dele (ork noctum status ${arco})`,
169
+ redeIlegivel: (thread, arco, motivo) => `noctum.guarda.rede-ilegivel: a thread ${thread} é trabalho do arco ${arco}, encerrado nesta máquina, e a rede não se lê (${motivo})`,
170
+ redeIlegivelCorrecao: (arco) => `restaure a leitura da rede antes de entregar a thread por fora do arco (ork noctum status ${arco})`,
171
+ redeDoArco: (thread, arco, estado, trabalho) => `noctum.guarda.thread-do-arco: a thread ${thread} é o trabalho ${trabalho} do arco ${arco}, ainda ${estado} na rede`,
172
+ redeDoArcoCorrecao: (arco) => `espere o trabalho terminar na rede ou entregue-o pelo passo da entrega do arco ${arco} (ork noctum status ${arco})`,
169
173
  retencao: (thread, arco, situacao) => `noctum.guarda.thread-do-arco: o arco ${arco} (${situacao}) despachou a thread ${thread} por último; a batida e a Sentinela ` +
170
174
  'não a despacham, não a retomam nem a mesclam até um despacho fora do arco ou um arco novo que a liste',
171
175
  // A2 do CHECK: o arco terminou, e a sessão que ele despachou ainda conduz a thread.
@@ -452,11 +456,15 @@ exports.SHIP_EN = {
452
456
  situacoes: { 'proposto': 'proposed', 'agendado': 'scheduled', 'vigente': 'in force', 'expirado': 'expired', 'revogado': 'revoked',
453
457
  'encerrado': 'closed' },
454
458
  origens: { 'envelope': 'by the envelope list', 'proposta': 'by the proposal waiting for the owner', 'despacho': 'by the arc dispatch log',
455
- 'correlacao': 'by the last dispatch of the thread' },
459
+ 'correlacao': 'by the last dispatch of the thread', 'rede': 'by the arc network' },
456
460
  doArco: (thread, arco, situacao, origem) => `noctum.guarda.thread-do-arco: thread ${thread} is work of arc ${arco} (${situacao}, ${origem})`,
457
461
  doArcoCorrecao: (arco) => `this thread is delivered by the delivery step of arc ${arco}: its SHIP and MASTER belong to the arc (ork noctum status ${arco})`,
458
462
  arcoIlegivel: (thread, arco, motivo) => `noctum.guarda.arco-ilegivel: the last dispatch of thread ${thread} came from arc ${arco}, and the arc cannot be read (${motivo})`,
459
463
  arcoIlegivelCorrecao: (arco) => `inspect the arc before delivering the thread outside it (ork noctum status ${arco})`,
464
+ redeIlegivel: (thread, arco, motivo) => `noctum.guarda.rede-ilegivel: thread ${thread} is work of arc ${arco}, closed on this machine, and its network cannot be read (${motivo})`,
465
+ redeIlegivelCorrecao: (arco) => `restore network reading before delivering the thread outside the arc (ork noctum status ${arco})`,
466
+ redeDoArco: (thread, arco, estado, trabalho) => `noctum.guarda.thread-do-arco: thread ${thread} is work ${trabalho} of arc ${arco}, still ${estado} on the network`,
467
+ redeDoArcoCorrecao: (arco) => `wait for the work to finish on the network or deliver it through the delivery step of arc ${arco} (ork noctum status ${arco})`,
460
468
  retencao: (thread, arco, situacao) => `noctum.guarda.thread-do-arco: arc ${arco} (${situacao}) dispatched thread ${thread} last; the beat and the Sentinel ` +
461
469
  'do not dispatch, resume or merge it until a dispatch outside the arc or a new arc that lists it',
462
470
  sessaoDoArco: (thread, arco, situacao, sessao) => `noctum.guarda.thread-do-arco: arc ${arco} is ${situacao}, and session ${sessao} that it dispatched still conducts thread ${thread}: ` +
package/dist/manifest.js CHANGED
@@ -772,7 +772,12 @@ function carregarManifesto(dirInicial = diretorioDoProjeto()) {
772
772
  // Runtime de despacho: so os homologados passam. Um typo aqui viraria erro apenas na
773
773
  // hora do despacho, com a thread ja aberta; reprovar no manifesto e mais barato.
774
774
  const adapterDeRuntime = texto(runtime.adapter, runtimes_1.RUNTIME_PADRAO);
775
- if (!(0, runtimes_1.runtimeConhecido)(adapterDeRuntime)) {
775
+ if ((0, runtimes_1.runtimeConhecido)(adapterDeRuntime) && !(0, runtimes_1.runtimeDoManifesto)(adapterDeRuntime)) {
776
+ // RM-067 (F4): runtime de bloco no setup, nunca o padrao do projeto.
777
+ erros.push(`runtime.adapter fora do padrao do projeto: "${adapterDeRuntime}" entra por ork setup <modo> --bloco N --runtime ` +
778
+ `${adapterDeRuntime} --model <modelo> ou por ork phase run --runtime ${adapterDeRuntime} (o padrao aceita: ${runtimes_1.ORDEM_DOS_RUNTIMES.join(', ')})`);
779
+ }
780
+ else if (!(0, runtimes_1.runtimeDoManifesto)(adapterDeRuntime)) {
776
781
  erros.push(`runtime.adapter desconhecido: "${adapterDeRuntime}" (homologados: ${runtimes_1.ORDEM_DOS_RUNTIMES.join(', ')})`);
777
782
  }
778
783
  const sandboxDoRuntime = texto(runtime.sandbox, codex_1.SANDBOX_PADRAO);
@@ -33,7 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ENV_VARS_CODEX_MCP = exports.BRAIN_WRITE_TOOLS = exports.BRAIN_READ_TOOLS = exports.TOOLS_FILHO_CODEX = exports.TOOLS_DONO_CODEX = exports.TRANSPORTES_SHIP_MCP = void 0;
36
+ exports.HOSTS_MCP = exports.ENV_VARS_CODEX_MCP = exports.BRAIN_WRITE_TOOLS = exports.BRAIN_READ_TOOLS = exports.TOOLS_FILHO_CODEX = exports.TOOLS_DONO_CODEX = exports.TRANSPORTES_SHIP_MCP = void 0;
37
+ exports.arquivoDoHostMcp = arquivoDoHostMcp;
37
38
  exports.validarGrantsCodex = validarGrantsCodex;
38
39
  exports.politicasFilhoCodex = politicasFilhoCodex;
39
40
  exports.configuracaoServidorMcp = configuracaoServidorMcp;
@@ -62,6 +63,11 @@ Object.defineProperty(exports, "BRAIN_READ_TOOLS", { enumerable: true, get: func
62
63
  Object.defineProperty(exports, "BRAIN_WRITE_TOOLS", { enumerable: true, get: function () { return company_brain_mcp_1.BRAIN_WRITE_TOOLS; } });
63
64
  /** Caminho de sessao, nunca credencial. O cliente resolve o valor no ambiente ao iniciar o MCP. */
64
65
  exports.ENV_VARS_CODEX_MCP = ['CODEX_HOME'];
66
+ exports.HOSTS_MCP = ['claude-code', 'codex', 'grok'];
67
+ /** O arquivo do projeto onde cada host le a entrada `orkastery`; o codex e o grok usam TOML com `mcp_servers`. */
68
+ function arquivoDoHostMcp(raiz, host) {
69
+ return host === 'claude-code' ? path.join(raiz, '.mcp.json') : path.join(raiz, host === 'codex' ? '.codex' : '.grok', 'config.toml');
70
+ }
65
71
  function objeto(v) {
66
72
  if (!v || typeof v !== 'object' || Array.isArray(v))
67
73
  throw Error('mcp.install.config.invalid: objeto esperado');
@@ -207,14 +213,14 @@ function migrarEnvVarsCodex(bruto, entrada) {
207
213
  /** O transporte SHIP de cada host do projeto com a entrada orkastery; config que nao se le nao conta. */
208
214
  function transportesDosHosts(raiz) {
209
215
  const achados = [];
210
- for (const host of ['claude-code', 'codex']) {
211
- const arquivo = path.join(raiz, host === 'codex' ? '.codex/config.toml' : '.mcp.json');
216
+ for (const host of exports.HOSTS_MCP) {
217
+ const arquivo = arquivoDoHostMcp(raiz, host), toml = host !== 'claude-code';
212
218
  try {
213
219
  const lido = ler(arquivo);
214
220
  if (!lido)
215
221
  continue;
216
- const bruto = lido.bytes.toString('utf8'), dados = objeto(host === 'codex' ? (0, smol_toml_1.parse)(bruto) : JSON.parse(bruto));
217
- const servidores = objeto(dados[host === 'codex' ? 'mcp_servers' : 'mcpServers']);
222
+ const bruto = lido.bytes.toString('utf8'), dados = objeto(toml ? (0, smol_toml_1.parse)(bruto) : JSON.parse(bruto));
223
+ const servidores = objeto(dados[toml ? 'mcp_servers' : 'mcpServers']);
218
224
  if (!Object.hasOwn(servidores, 'orkastery'))
219
225
  continue;
220
226
  const argv = objeto(servidores.orkastery).args, lista = Array.isArray(argv) ? argv : [], i = lista.indexOf('--ship-transport');
@@ -228,7 +234,7 @@ function instalarMcp(opcoes) {
228
234
  // Ensaio da 0.5.0: os READMEs dos plugins mandavam `--project .`, recusado sem dizer como acertar.
229
235
  if (!path.isAbsolute(opcoes.projeto))
230
236
  throw Error('mcp.install.project.invalid: raiz absoluta obrigatoria; na raiz do projeto, use --project "$PWD"');
231
- if (!['claude-code', 'codex'].includes(opcoes.host))
237
+ if (!exports.HOSTS_MCP.includes(opcoes.host))
232
238
  throw Error('mcp.install.host.invalid');
233
239
  if (opcoes.transporteShip !== undefined && !(0, mcp_transportes_1.ehTransporteShipMcp)(opcoes.transporteShip))
234
240
  throw Error('mcp.install.transport.invalid');
@@ -267,7 +273,9 @@ function instalarMcp(opcoes) {
267
273
  }
268
274
  const gravarFixacaoSePedida = () => { if (fixacao && !opcoes.dryRun)
269
275
  (0, mcp_ship_transporte_1.gravarFixacao)((0, mcp_ship_transporte_1.dirDaFixacao)(raiz), fixacao); };
270
- const pasta = opcoes.host === 'codex' ? path.join(raiz, '.codex') : raiz;
276
+ // RM-067 (F4b): o grok grava como o codex, em TOML; so o claude-code usa o `.mcp.json` da raiz.
277
+ const toml = opcoes.host !== 'claude-code';
278
+ const pasta = path.dirname(arquivoDoHostMcp(raiz, opcoes.host));
271
279
  const validarPasta = () => {
272
280
  try {
273
281
  const st = fs.lstatSync(pasta);
@@ -280,17 +288,17 @@ function instalarMcp(opcoes) {
280
288
  }
281
289
  };
282
290
  validarPasta();
283
- const arquivo = path.join(pasta, opcoes.host === 'codex' ? 'config.toml' : '.mcp.json');
291
+ const arquivo = arquivoDoHostMcp(raiz, opcoes.host);
284
292
  const anterior = ler(arquivo), bruto = anterior?.bytes.toString('utf8') ?? '';
285
293
  const { command: comando, args } = configuracaoServidorMcp(raiz, opcoes.host, undefined, opcoes.transporteShip, opcoes.permissoesFilho);
286
294
  let dados;
287
295
  try {
288
- dados = anterior ? objeto(opcoes.host === 'codex' ? (0, smol_toml_1.parse)(bruto) : JSON.parse(bruto)) : {};
296
+ dados = anterior ? objeto(toml ? (0, smol_toml_1.parse)(bruto) : JSON.parse(bruto)) : {};
289
297
  }
290
298
  catch {
291
299
  throw Error('mcp.install.config.invalid: configuracao existente nao foi alterada');
292
300
  }
293
- const chave = opcoes.host === 'codex' ? 'mcp_servers' : 'mcpServers';
301
+ const chave = toml ? 'mcp_servers' : 'mcpServers';
294
302
  const servidores = dados[chave] === undefined ? {} : objeto(dados[chave]);
295
303
  const existente = Object.hasOwn(servidores, 'orkastery') ? objeto(servidores.orkastery) : undefined;
296
304
  const faltaEnvCodex = opcoes.host === 'codex' && existente !== undefined &&
@@ -320,9 +328,11 @@ function instalarMcp(opcoes) {
320
328
  }
321
329
  }
322
330
  let proximo;
323
- if (opcoes.host === 'codex') {
331
+ if (toml) {
324
332
  // Append preserva comentarios e escolhas do usuario. TOML inline fechado pode impedir a extensao.
325
- proximo = bruto + (bruto.endsWith('\n') || !bruto ? '' : '\n') + (existente ? '' : '\n[mcp_servers.orkastery]\ncommand = ' + JSON.stringify(comando) + '\nargs = ' + JSON.stringify(args) + '\nenv_vars = ' + JSON.stringify([...exports.ENV_VARS_CODEX_MCP]) + '\n');
333
+ // RM-067 (F4b): o grok nao tem a lista de variaveis do codex; a entrada dele e so command e args.
334
+ proximo = bruto + (bruto.endsWith('\n') || !bruto ? '' : '\n') + (existente ? '' : '\n[mcp_servers.orkastery]\ncommand = ' + JSON.stringify(comando) + '\nargs = ' + JSON.stringify(args) + '\n' +
335
+ (opcoes.host === 'codex' ? 'env_vars = ' + JSON.stringify([...exports.ENV_VARS_CODEX_MCP]) + '\n' : ''));
326
336
  if (existente && faltaEnvCodex) {
327
337
  proximo = migrarEnvVarsCodex(proximo, existente);
328
338
  try {