@orkastery/cli 0.5.0 → 0.5.3

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 (131) hide show
  1. package/adapters/claude-code/README.md +11 -2
  2. package/adapters/claude-code/agents/ork-master.md +2 -0
  3. package/adapters/claude-code/commands/master.md +8 -0
  4. package/adapters/claude-code/commands/onboarding.md +3 -2
  5. package/adapters/claude-code/commands/ork.md +9 -0
  6. package/adapters/codex/skills/ork/SKILL.md +18 -3
  7. package/adapters/hermes/README.md +1 -0
  8. package/adapters/hermes/bin/ork-network-status.sh +10 -0
  9. package/adapters/hermes/hermes.plugin.json +1 -0
  10. package/adapters/hermes/hitl-ingress/__init__.py +2 -2
  11. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +6 -5
  12. package/adapters/openclaw/README.md +35 -4
  13. package/adapters/openclaw/dist/hitl-ingress.js +2 -2
  14. package/adapters/openclaw/dist/index.js +47 -12
  15. package/adapters/openclaw/openclaw.plugin.json +5 -1
  16. package/adapters/openclaw/package.json +2 -2
  17. package/adapters/openclaw/src/hitl-ingress.ts +2 -2
  18. package/adapters/openclaw/src/index.ts +50 -12
  19. package/assets/orkmind_bridge.py +117 -9
  20. package/dist/adapters/claude-bg.js +59 -11
  21. package/dist/adapters/codex.js +4 -3
  22. package/dist/agents-md.js +1 -0
  23. package/dist/auditrun.js +6 -2
  24. package/dist/board.js +16 -14
  25. package/dist/branch-de-estado.js +66 -10
  26. package/dist/busca-semantica.js +52 -12
  27. package/dist/canarios-rm057.js +149 -0
  28. package/dist/canarios.js +2 -0
  29. package/dist/ci.js +8 -1
  30. package/dist/claim-lint.js +3 -1
  31. package/dist/claims.js +39 -1
  32. package/dist/company-brain-context.js +158 -22
  33. package/dist/docs.js +110 -3
  34. package/dist/doctor-pulse-cron.js +194 -0
  35. package/dist/doctor-rede.js +149 -0
  36. package/dist/doctor.js +294 -37
  37. package/dist/entrega-pr.js +27 -8
  38. package/dist/esgotamentos.js +181 -0
  39. package/dist/experiencia.js +12 -2
  40. package/dist/fabrica-estado.js +35 -9
  41. package/dist/fabrica-publicar.js +6 -0
  42. package/dist/fechamento.js +20 -66
  43. package/dist/fix.js +3 -3
  44. package/dist/forja.js +31 -7
  45. package/dist/gates.js +5 -1
  46. package/dist/hitl-contract.js +59 -4
  47. package/dist/hitl-curto.js +11 -6
  48. package/dist/hitl-gates.js +5 -0
  49. package/dist/hitl-lote.js +5 -2
  50. package/dist/hitl-resumo.js +33 -1
  51. package/dist/hitl-tempo-parado.js +201 -0
  52. package/dist/hitl-texto-livre.js +5 -5
  53. package/dist/horario.js +27 -0
  54. package/dist/hosts.js +59 -13
  55. package/dist/impedimento.js +205 -0
  56. package/dist/index.js +433 -88
  57. package/dist/indice-vetorial.js +87 -10
  58. package/dist/indice.js +3 -1
  59. package/dist/init.js +28 -5
  60. package/dist/integracoes-locais.js +4 -0
  61. package/dist/intelligence-graph-cli.js +267 -30
  62. package/dist/intelligence-graph-contexto.js +215 -0
  63. package/dist/intelligence-graph-contract.js +71 -12
  64. package/dist/intelligence-graph-extract-md.js +41 -23
  65. package/dist/intelligence-graph-extract-ts.js +181 -11
  66. package/dist/intelligence-graph-extract.js +186 -9
  67. package/dist/intelligence-graph-index.js +205 -24
  68. package/dist/intelligence-graph-parsers.js +6 -4
  69. package/dist/intelligence-graph-repo.js +10 -0
  70. package/dist/leases.js +680 -87
  71. package/dist/ledger-stats.js +15 -1
  72. package/dist/ledger.js +12 -0
  73. package/dist/licoes.js +6 -4
  74. package/dist/liveness.js +2 -1
  75. package/dist/maestro-runtime.js +7 -1
  76. package/dist/manifest.js +44 -1
  77. package/dist/master-nota.js +14 -5
  78. package/dist/master.js +129 -12
  79. package/dist/mcp-artifacts.js +36 -3
  80. package/dist/mcp-git.js +80 -15
  81. package/dist/mcp-grafo-worker.js +93 -0
  82. package/dist/mcp-grafo.js +279 -0
  83. package/dist/mcp-install.js +2 -1
  84. package/dist/mcp-server.js +23 -1
  85. package/dist/mcp-ship.js +2 -0
  86. package/dist/mcp-verify.js +3 -1
  87. package/dist/memoria.js +48 -6
  88. package/dist/network-roadmap.js +195 -20
  89. package/dist/ocupacao.js +17 -5
  90. package/dist/onboarding.js +9 -4
  91. package/dist/orkmind.js +90 -5
  92. package/dist/orquestracao.js +14 -11
  93. package/dist/parado-no-condutor.js +1089 -0
  94. package/dist/phase.js +68 -15
  95. package/dist/policies.js +79 -3
  96. package/dist/portfolio.js +4 -1
  97. package/dist/projeto-alvo.js +5 -1
  98. package/dist/prompts.js +36 -1
  99. package/dist/prova-ativacao.js +414 -0
  100. package/dist/pulse-delivery.js +60 -7
  101. package/dist/pulse.js +99 -3
  102. package/dist/ratelimit.js +20 -4
  103. package/dist/recall.js +3 -1
  104. package/dist/rede-adesao.js +399 -0
  105. package/dist/rede-forja.js +289 -0
  106. package/dist/rede-projetos.js +239 -0
  107. package/dist/rede-status.js +336 -0
  108. package/dist/rede.js +980 -0
  109. package/dist/retry.js +69 -2
  110. package/dist/roadmap-status.js +162 -7
  111. package/dist/runtime-context.js +5 -1
  112. package/dist/runtime-profiles.js +22 -1
  113. package/dist/saida-segura.js +58 -0
  114. package/dist/session-watcher-claude.js +113 -23
  115. package/dist/sessoes-contas.js +187 -0
  116. package/dist/sessoes-inventario.js +6 -12
  117. package/dist/sessoes.js +87 -3
  118. package/dist/ship.js +110 -20
  119. package/dist/thread.js +212 -14
  120. package/dist/util.js +71 -4
  121. package/dist/verify.js +2 -2
  122. package/dist/worktree.js +34 -8
  123. package/eval/casos/onboarding.json +1 -1
  124. package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
  125. package/package.json +7 -3
  126. package/references/definition-of-done.md +1 -1
  127. package/skills/README.md +1 -1
  128. package/skills/core/onboarding/SKILL.md +3 -2
  129. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  130. package/skills/phases/master-metrics/SKILL.md +8 -3
  131. package/skills/phases/ship-release/SKILL.md +6 -3
package/dist/phase.js CHANGED
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.REGRAS_DE_EVIDENCIA = exports.CONTRATO_DAS_FASES = void 0;
37
37
  exports.escolherPerfil = escolherPerfil;
38
+ exports.perfilPedido = perfilPedido;
38
39
  exports.perfilParaDespacho = perfilParaDespacho;
39
40
  exports.runtimeCruzadoParaDespacho = runtimeCruzadoParaDespacho;
40
41
  exports.estadoParaDespacho = estadoParaDespacho;
@@ -71,12 +72,15 @@ const board_1 = require("./board");
71
72
  const verify_1 = require("./verify");
72
73
  const session_watcher_1 = require("./session-watcher");
73
74
  const session_watcher_claude_1 = require("./session-watcher-claude");
75
+ const manifest_1 = require("./manifest");
76
+ const mcp_grafo_1 = require("./mcp-grafo");
74
77
  const runtimes_1 = require("./runtimes");
75
78
  const setup_1 = require("./setup");
76
79
  const modos_1 = require("./modos");
77
80
  const gates_1 = require("./gates");
78
81
  const policies_1 = require("./policies");
79
82
  const ratelimit_1 = require("./ratelimit");
83
+ const impedimento_1 = require("./impedimento");
80
84
  const claude_bg_1 = require("./adapters/claude-bg");
81
85
  const codex_1 = require("./adapters/codex");
82
86
  const memoria_1 = require("./memoria");
@@ -89,6 +93,7 @@ const ledger_1 = require("./ledger");
89
93
  const estado_thread_1 = require("./estado-thread");
90
94
  const horario_1 = require("./horario");
91
95
  const runtime_profiles_1 = require("./runtime-profiles");
96
+ const sessoes_contas_1 = require("./sessoes-contas");
92
97
  const maquina_1 = require("./maquina");
93
98
  const fabrica_publicar_1 = require("./fabrica-publicar");
94
99
  const conducao_1 = require("./conducao");
@@ -102,18 +107,14 @@ function escolherPerfil(raiz, runtime, opcoes = {}) {
102
107
  // I-49: o despacho enxerga o estado que as outras fabricas viram na mesma conta.
103
108
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz, opcoes.agoraMs);
104
109
  const doRuntime = (0, runtime_profiles_1.perfisDoRuntime)(store, runtime);
105
- if (opcoes.perfil !== undefined) {
106
- const pedido = doRuntime.find(p => p.id === opcoes.perfil);
107
- if (!pedido)
108
- return { perfil: null, configurados: doRuntime.length, erro: `perfil "${opcoes.perfil}" nao existe para o runtime ${runtime}` };
109
- if (!(0, runtime_profiles_1.perfilDisponivel)(pedido, opcoes.agoraMs))
110
- return { perfil: null, configurados: doRuntime.length,
111
- erro: `perfil "${pedido.id}" esta ${pedido.estado}${pedido.esgotadoAte ? ` ate ${pedido.esgotadoAte}` : ''}` };
112
- return { perfil: (0, runtime_profiles_1.perfilDeDespacho)(pedido), configurados: doRuntime.length };
113
- }
110
+ if (opcoes.perfil !== undefined)
111
+ return perfilPedido(store, runtime, opcoes.perfil, opcoes.agoraMs);
114
112
  if (doRuntime.length === 0)
115
113
  return { perfil: null, configurados: 0 };
116
- const proximo = (0, runtime_profiles_1.proximoPerfilDisponivel)(store, runtime, opcoes.politica ?? runtime_profiles_1.POLITICA_PADRAO, opcoes);
114
+ const politica = opcoes.politica ?? runtime_profiles_1.POLITICA_PADRAO;
115
+ const proximo = politica.distribuir === 'carga' && opcoes.carga
116
+ ? (0, runtime_profiles_1.proximoPerfilPorCarga)(store, runtime, politica, opcoes.carga, opcoes)
117
+ : (0, runtime_profiles_1.proximoPerfilDisponivel)(store, runtime, politica, opcoes);
117
118
  if (proximo)
118
119
  return { perfil: (0, runtime_profiles_1.perfilDeDespacho)(proximo), configurados: doRuntime.length };
119
120
  const agoraMs = opcoes.agoraMs ?? Date.now();
@@ -125,6 +126,41 @@ function escolherPerfil(raiz, runtime, opcoes = {}) {
125
126
  return { perfil: null, configurados: doRuntime.length, motivo,
126
127
  erro: `nenhum perfil disponivel do runtime ${runtime} (${doRuntime.map(p => `${p.id}: ${p.estado}`).join(', ')})` };
127
128
  }
129
+ /**
130
+ * RM-056 (D1): o perfil PEDIDO (`--perfil`), validado contra o store. Recusa com motivo tipado e nunca
131
+ * troca de perfil: inexistente ou de outro runtime e `runtime.profile-invalid`; esgotado, a cota; sem
132
+ * login (ou de provider pago), o motivo do estado. Funcao propria, para o despacho da RM-055 rebasar limpo.
133
+ */
134
+ function perfilPedido(store, runtime, id, agoraMs = Date.now()) {
135
+ const doRuntime = (0, runtime_profiles_1.perfisDoRuntime)(store, runtime);
136
+ const pedido = doRuntime.find(p => p.id === id);
137
+ if (!pedido) {
138
+ const outro = store.perfis.find(p => p.id === id);
139
+ return { perfil: null, configurados: doRuntime.length, motivo: 'runtime.profile-invalid',
140
+ erro: outro ? `perfil "${id}" e do runtime ${outro.runtime}, nao do ${runtime}`
141
+ : `perfil "${id}" nao existe no store (${doRuntime.length ? `perfis do ${runtime}: ${doRuntime.map(p => p.id).join(', ')}` : `nenhum perfil do ${runtime}`})` };
142
+ }
143
+ if ((0, runtime_profiles_1.perfilDisponivel)(pedido, agoraMs))
144
+ return { perfil: (0, runtime_profiles_1.perfilDeDespacho)(pedido), configurados: doRuntime.length };
145
+ const motivo = pedido.estado === 'esgotado' ? 'runtime.quota-exhausted' : pedido.estado === 'sem-auth'
146
+ ? 'runtime.auth-missing' : pedido.estado === 'provider-pago' ? 'cost.violation' : 'runtime.profile-invalid';
147
+ return { perfil: null, configurados: doRuntime.length, motivo,
148
+ erro: `perfil "${pedido.id}" esta ${pedido.estado}${pedido.esgotadoAte ? ` ate ${pedido.esgotadoAte}` : ''}` };
149
+ }
150
+ /**
151
+ * RM-056 (D3): a carga dos perfis do runtime, so quando o manifesto pede `distribuir: carga` e o
152
+ * dono nao pediu um perfil. Consulta falha vale carga desconhecida (zero): decide o desempate.
153
+ */
154
+ function cargaDoDespacho(carregado, runtime, politica, pedido) {
155
+ if (politica.distribuir !== 'carga' || pedido !== undefined || !(0, runtime_profiles_1.runtimeComPerfil)(runtime))
156
+ return undefined;
157
+ try {
158
+ return (0, sessoes_contas_1.sessoesVivasPorPerfil)(carregado.raiz, runtime, carregado.manifesto.concurrency.stale_after_min);
159
+ }
160
+ catch {
161
+ return new Map();
162
+ }
163
+ }
128
164
  /**
129
165
  * I-33 (D7, D13): preflight de auth antes do despacho. O perfil escolhido tem o login conferido
130
166
  * pelo proprio CLI com o env dele; reprovado, vira `sem-auth` no store (ou `provider-pago`, quando
@@ -136,8 +172,9 @@ function perfilParaDespacho(carregado, thread, fase, runtime, opcoes) {
136
172
  const { raiz } = carregado;
137
173
  const excluir = [...(opcoes.excluir ?? [])];
138
174
  const politica = (0, runtime_profiles_1.politicaDeRotacao)(carregado.manifesto);
175
+ const carga = cargaDoDespacho(carregado, runtime, politica, opcoes.perfil);
139
176
  for (;;) {
140
- const escolha = escolherPerfil(raiz, runtime, { perfil: opcoes.perfil, excluir, politica });
177
+ const escolha = escolherPerfil(raiz, runtime, { perfil: opcoes.perfil, excluir, politica, carga });
141
178
  if (escolha.erro || !escolha.perfil || opcoes.dryRun)
142
179
  return escolha;
143
180
  const auth = runtime === 'claude-bg' ? (0, claude_bg_1.conferirAuth)(escolha.perfil) : runtime === 'codex' ? (0, codex_1.conferirAuth)(escolha.perfil)
@@ -164,7 +201,7 @@ function perfilParaDespacho(carregado, thread, fase, runtime, opcoes) {
164
201
  razao = 'o preflight de auth reprovou o perfil antes do despacho (D7): perfil sem login nunca recebe despacho';
165
202
  }
166
203
  excluir.push(escolha.perfil.id);
167
- const proximo = opcoes.perfil === undefined ? escolherPerfil(raiz, runtime, { excluir, politica }).perfil : null;
204
+ const proximo = opcoes.perfil === undefined ? escolherPerfil(raiz, runtime, { excluir, politica, carga }).perfil : null;
168
205
  (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread.id), thread.id, ledger_1.TIPOS_DE_EVENTO.perfilRotacionado, {
169
206
  fase, motivo, origem: `${opcoes.origem}.preflight`,
170
207
  de: { runtime, perfil: escolha.perfil.id }, para: proximo ? { runtime, perfil: proximo.id } : null,
@@ -314,8 +351,10 @@ function montarPrompt(thread, fase, pedido, raiz, memoriaInjetada = '') {
314
351
  */
315
352
  function montarPromptComMemoria(carregado, thread, fase, pedido, memoria) {
316
353
  const injecao = (0, memoria_1.injecaoDaFase)(carregado, memoria, thread, fase);
354
+ // Mesma raiz usada pelo MCP e runtime-context; o manifesto da WT nao habilita a dica.
355
+ const ligado = (0, mcp_grafo_1.grafoLigado)((0, manifest_1.exigirManifesto)((0, estado_thread_1.raizDoEstado)(carregado.raiz)).manifesto);
317
356
  return {
318
- prompt: montarPrompt(thread, fase, pedido, carregado.raiz, injecao.texto),
357
+ prompt: montarPrompt(thread, fase, (0, prompts_1.pedidoComDicaDoGrafo)(pedido, thread.id, ligado), carregado.raiz, injecao.texto),
319
358
  injecao,
320
359
  };
321
360
  }
@@ -1039,6 +1078,15 @@ tomadaPrevia) {
1039
1078
  erro,
1040
1079
  };
1041
1080
  }
1081
+ // RM-055: o que so o dono resolve no terminal vira a pausa dele, com o comando exato e o que o ork
1082
+ // faz depois. O prompt ja esta gravado com o sha256 acima, e e ele que o retry re-despacha.
1083
+ const impedimento = (0, impedimento_1.registrarImpedimentoDoDono)(dir, thread, { fase, slug, runtime, cwd, origem: 'phase.run',
1084
+ promptPath, promptSha256: sha, perfil, saida: `${resultado.stderr}\n${erro}` });
1085
+ if (impedimento) {
1086
+ return { thread, slug, promptPath, promptSha256: sha, comando: resultado.comando, controlador: resultado.controlador,
1087
+ sessionId: null, verificada: false, pausaAoFim, dryRun: false, runtime, model, effort, bloqueado: false,
1088
+ motivo: impedimento.motivo, violacoes, naFila: null, erro: `${impedimento.motivo}: ${impedimento.trecho}` };
1089
+ }
1042
1090
  return {
1043
1091
  thread,
1044
1092
  slug,
@@ -1130,8 +1178,13 @@ function tabelaDoLedger(raiz, threadId) {
1130
1178
  detalhe.push(`acao ${String(e.acao)}`);
1131
1179
  if (e.playbook)
1132
1180
  detalhe.push(`playbook ${String(e.playbook)}`);
1133
- if (e.pedido)
1134
- detalhe.push(`pedido ${String(e.pedido)}`);
1181
+ // Ensaio de 03/10/2026 (RM-049): na decisao autonoma o pedido e o objeto `ork.hitl/v2`, e a tabela
1182
+ // mostrava "pedido [object Object]"; do objeto sai o id curto.
1183
+ if (typeof e.pedido === 'string' && e.pedido !== '')
1184
+ detalhe.push(`pedido ${e.pedido}`);
1185
+ else if (e.pedido && typeof e.pedido === 'object' && typeof e.pedido.id === 'string') {
1186
+ detalhe.push(`pedido ${e.pedido.id.slice(0, 8)}`);
1187
+ }
1135
1188
  if (e.rodada !== undefined)
1136
1189
  detalhe.push(`rodada ${String(e.rodada)}`);
1137
1190
  if (e.cobertura)
package/dist/policies.js CHANGED
@@ -11,8 +11,9 @@
11
11
  * ela volta na lista de desconhecidas, para o `doctor` e o CLI dizerem que ela nao vale.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.POLICIES_CONHECIDAS = void 0;
14
+ exports.POLICIES_DE_PROVA_LOCAL = exports.POLICIES_CONHECIDAS = void 0;
15
15
  exports.procurarSegredos = procurarSegredos;
16
+ exports.policyDeProvaLocal = policyDeProvaLocal;
16
17
  exports.policiesDesconhecidas = policiesDesconhecidas;
17
18
  exports.avaliarPolicies = avaliarPolicies;
18
19
  exports.avisos = avisos;
@@ -95,7 +96,39 @@ exports.POLICIES_CONHECIDAS = {
95
96
  quando: ['ship'],
96
97
  descricao: 'avisa quando a branch da thread esta atras da base',
97
98
  },
99
+ // RM-008 (B8): a licao `claims.failed` ("rode o comando da claim antes de registra-la"). Desligada por
100
+ // padrao; declarada, o `ork claims add` roda o comando uma vez no prazo do verify. So avisa, nunca para.
101
+ claim_sem_prova_local: {
102
+ quando: ['claims.add'],
103
+ descricao: 'avisa quando o comando da claim reprova (ou estoura o prazo do verify) no registro',
104
+ },
105
+ claims_failed: {
106
+ quando: ['claims.add'],
107
+ descricao: 'a mesma conferencia de claim_sem_prova_local, com o nome que o ork licoes propoe',
108
+ },
98
109
  };
110
+ /** RM-008 (B8): as policies que conferem a claim no registro (um aviso so, como verify_regression e verify_failed). */
111
+ exports.POLICIES_DE_PROVA_LOCAL = ['claim_sem_prova_local', 'claims_failed'];
112
+ /** A primeira policy de prova local declarada fora de `off`, ou `null` (o `claims add` nao roda nada). */
113
+ function policyDeProvaLocal(manifesto) {
114
+ const declaradas = manifesto.policies ?? {};
115
+ for (const [nome, bruta] of Object.entries(declaradas)) {
116
+ if (exports.POLICIES_DE_PROVA_LOCAL.includes(nome) && severidade(bruta) !== 'off')
117
+ return nome;
118
+ }
119
+ return null;
120
+ }
121
+ /**
122
+ * Ensaio da 0.5.0: a thread criada sem `--worktree auto` entrega a base para a base, e a correcao
123
+ * repetia o proprio `ork ship`. A thread que ainda nao passou do GO ganha a branch com
124
+ * `ork worktree ensure`. Depois do GO, nao: os commits ja estao na base, a branch nova nasce com eles
125
+ * e o ship sem delta empurraria a base direto, que e o que esta policy barra (CHECK, rodada 1).
126
+ */
127
+ function correcaoSemBranchDaThread(threadId, base) {
128
+ return `entregue a branch da thread (ork/<slug>) com --para ${base || '<base>'}; sem worktree e antes do GO, ` +
129
+ `crie-a com ork worktree ensure ${threadId || '<thread>'} (thread nova: --worktree auto); depois do GO, ` +
130
+ 'os commits ja estao na base e o ship nao os separa: leve-os para a branch da thread antes de entregar';
131
+ }
99
132
  function severidade(bruta) {
100
133
  if (bruta === 'block' || bruta === 'warn' || bruta === 'off')
101
134
  return bruta;
@@ -111,6 +144,8 @@ function avaliarPolicies(manifesto, ctx) {
111
144
  const violacoes = [];
112
145
  // verify_regression e verify_failed conferem a mesma coisa: um aviso so, com o nome da primeira declarada.
113
146
  let baselineJaAvaliada = false;
147
+ // claim_sem_prova_local e claims_failed idem.
148
+ let provaLocalJaAvaliada = false;
114
149
  for (const [nome, bruta] of Object.entries(declaradas)) {
115
150
  const conhecida = exports.POLICIES_CONHECIDAS[nome];
116
151
  if (!conhecida || !conhecida.quando.includes(ctx.gate))
@@ -158,7 +193,7 @@ function avaliarPolicies(manifesto, ctx) {
158
193
  severidade: sev,
159
194
  motivo: 'policy.violation',
160
195
  detalhe: `origem e destino sao a mesma branch ("${de}"): isso e push direto na base, nao merge de thread`,
161
- correcao: 'entregue a partir da branch da thread: ork ship <thread> --para ' + (base || 'main'),
196
+ correcao: correcaoSemBranchDaThread(ctx.threadId, base),
162
197
  });
163
198
  }
164
199
  else if (de && base && de === base) {
@@ -167,7 +202,21 @@ function avaliarPolicies(manifesto, ctx) {
167
202
  severidade: sev,
168
203
  motivo: 'policy.violation',
169
204
  detalhe: `a origem "${de}" e a propria branch base do projeto: nenhuma branch de thread foi usada`,
170
- correcao: 'crie a thread com --worktree auto e entregue a branch ork/<slug>',
205
+ correcao: correcaoSemBranchDaThread(ctx.threadId, base),
206
+ });
207
+ }
208
+ else if (ctx.semDeltaComBaseAFrente === true) {
209
+ // Fatia 2 do ensaio da 0.5.0 (P9): a thread que perdeu a branch depois do GO ganha uma com os commits
210
+ // ja na base; o ship ve nada a mergear e empurraria a base, que e o que esta policy barra.
211
+ const remoto = ctx.remoto ?? 'origin';
212
+ violacoes.push({
213
+ policy: nome,
214
+ severidade: sev,
215
+ motivo: 'policy.violation',
216
+ detalhe: `a branch "${de}" nao traz commit alem de "${para}", e ${para} local tem commit que ${remoto}/${para} nao tem: ` +
217
+ 'o ship empurraria a base direto, sem merge de thread',
218
+ correcao: `leve os commits que estao so em ${para} local para a branch da thread antes de entregar, ou entregue-os ` +
219
+ `pela thread que os criou (conferido em refs/remotes/${remoto}/${para}, sem rede)`,
171
220
  });
172
221
  }
173
222
  continue;
@@ -199,6 +248,33 @@ function avaliarPolicies(manifesto, ctx) {
199
248
  }
200
249
  continue;
201
250
  }
251
+ if (exports.POLICIES_DE_PROVA_LOCAL.includes(nome)) {
252
+ if (provaLocalJaAvaliada)
253
+ continue;
254
+ provaLocalJaAvaliada = true;
255
+ const r = ctx.provaLocalReprovada;
256
+ if (r) {
257
+ const id = ctx.threadId ?? '<thread>';
258
+ violacoes.push({
259
+ policy: nome,
260
+ // O registro de claim nunca para: `block` declarado avisa como `warn`.
261
+ severidade: 'warn',
262
+ motivo: r.estourou ? 'verify.timeout' : 'claims.failed',
263
+ detalhe: r.semDiretorio
264
+ ? `a worktree da thread (${r.semDiretorio}) nao existe; o comando da claim ${r.claim} nao rodou e a claim entrou sem prova local`
265
+ : r.estourou
266
+ ? `o comando da claim ${r.claim} estourou o prazo do verify (${Math.round(r.prazoMs / 1000)} s) no registro; a claim entrou sem prova local`
267
+ : `o comando da claim ${r.claim} saiu ${r.code} no registro; a claim entrou sem prova local e reprova no verify`,
268
+ correcao: r.semDiretorio
269
+ ? `recrie a worktree da thread (ou feche a thread que perdeu a worktree); depois, ork verify ${id}`
270
+ : r.estourou
271
+ ? `divida o comando ou suba verify.timeout_ms; depois, ork verify ${id}`
272
+ : `corrija o produto ou o comando e anexe o certo com ork claims verificar ${id} ${r.claim} --comando "<comando>"; ` +
273
+ `se a alegacao nao vale, ork claims retirar ${id} ${r.claim} --motivo "<motivo>"`,
274
+ });
275
+ }
276
+ continue;
277
+ }
202
278
  if (nome === 'tree_blocked') {
203
279
  if (ctx.branchAtrasDaBase === true) {
204
280
  violacoes.push({
package/dist/portfolio.js CHANGED
@@ -44,6 +44,7 @@ exports.assertCycleScope = assertCycleScope;
44
44
  /** Catálogo determinístico de produto -> projeto -> iniciativa. */
45
45
  const fs = __importStar(require("node:fs"));
46
46
  const project_state_1 = require("./project-state");
47
+ const estado_thread_1 = require("./estado-thread");
47
48
  const company_brain_journal_1 = require("./company-brain-journal");
48
49
  const util_1 = require("./util");
49
50
  const creation_operation_store_1 = require("./creation-operation-store");
@@ -65,7 +66,9 @@ function readPortfolio(root) {
65
66
  }
66
67
  function persist(root, value) { value.updatedAt = (0, util_1.agora)(); (0, company_brain_journal_1.replaceWithJournal)(file(root), value); return value; }
67
68
  function mutatePortfolio(root, run) {
68
- return (0, creation_operation_store_1.withCreationLock)(root, 'portfolio', () => (0, company_brain_journal_1.portfolioMutation)(file(root), run));
69
+ // RM-036 (D5): o portfolio.json e canonico, e o lock de espera tambem: chamado da raiz ou de uma worktree,
70
+ // quem chega depois espera a vez, em vez de recusar com brain.journal.busy no lock interno.
71
+ return (0, creation_operation_store_1.withCreationLock)((0, estado_thread_1.raizDoEstado)(root), 'portfolio', () => (0, company_brain_journal_1.portfolioMutation)(file(root), run));
69
72
  }
70
73
  function validateBase(kind, input) {
71
74
  if (!ID.test(input.id) || !input.id.startsWith(PREFIX[kind]))
@@ -75,6 +75,7 @@ exports.linhasDaConsulta = linhasDaConsulta;
75
75
  const fs = __importStar(require("node:fs"));
76
76
  const os = __importStar(require("node:os"));
77
77
  const path = __importStar(require("node:path"));
78
+ const branch_de_estado_1 = require("./branch-de-estado");
78
79
  const estado_thread_1 = require("./estado-thread");
79
80
  const manifest_1 = require("./manifest");
80
81
  const maquina_1 = require("./maquina");
@@ -198,7 +199,10 @@ function remotoSemCredencial(url) {
198
199
  }
199
200
  /** URL do remoto, sem credencial. `null` quando o projeto nao tem aquele remoto. */
200
201
  function remotoDoProjeto(raiz, remoto = 'origin') {
201
- const r = (0, util_1.exec)('git', ['remote', 'get-url', remoto], raiz, 5000);
202
+ // RM-047: o nome vem do manifesto; fora do formato de remoto, nada vai ao git.
203
+ if (!(0, branch_de_estado_1.remotoValido)(remoto))
204
+ return null;
205
+ const r = (0, util_1.exec)('git', ['remote', 'get-url', '--', remoto], raiz, 5000);
202
206
  const url = r.ok ? r.stdout.trim() : '';
203
207
  return url ? remotoSemCredencial(url) : null;
204
208
  }
package/dist/prompts.js CHANGED
@@ -49,11 +49,13 @@ var __importStar = (this && this.__importStar) || (function () {
49
49
  };
50
50
  })();
51
51
  Object.defineProperty(exports, "__esModule", { value: true });
52
- exports.TEMPLATES_EMBUTIDOS = exports.TEMPLATE_FASE_PADRAO = exports.CONTRATO_DE_FASE = exports.REGRA_CENTRAL = exports.SECOES_OBRIGATORIAS = exports.LIMITE_TEMPLATE_BYTES = void 0;
52
+ exports.TEMPLATES_EMBUTIDOS = exports.TEMPLATE_FASE_PADRAO = exports.PADROES_DE_HITL_EM_TEXTO_LIVRE = exports.CONTRATO_DE_FASE = exports.REGRA_CENTRAL = exports.SECOES_OBRIGATORIAS = exports.LIMITE_TEMPLATE_BYTES = void 0;
53
+ exports.pedidoComDicaDoGrafo = pedidoComDicaDoGrafo;
53
54
  exports.dirDeTemplates = dirDeTemplates;
54
55
  exports.variaveisUsadas = variaveisUsadas;
55
56
  exports.renderizar = renderizar;
56
57
  exports.parseTemplate = parseTemplate;
58
+ exports.procurarHitlEmTextoLivre = procurarHitlEmTextoLivre;
57
59
  exports.lintTemplate = lintTemplate;
58
60
  exports.carregarTemplatesDe = carregarTemplatesDe;
59
61
  exports.carregarTemplates = carregarTemplates;
@@ -69,6 +71,15 @@ const policies_1 = require("./policies");
69
71
  const types_1 = require("./types");
70
72
  /** Limite duro de um template, o mesmo do manifesto: prosa longa nao vira prompt. */
71
73
  exports.LIMITE_TEMPLATE_BYTES = 16384;
74
+ /** KG5 fatia 2: dica opt-in no pedido; desligada preserva o texto byte a byte. */
75
+ function pedidoComDicaDoGrafo(pedido, thread, ligado) {
76
+ if (!ligado)
77
+ return pedido;
78
+ return pedido.trimEnd() + '\n\n## Contexto do grafo (opcional)\n'
79
+ + `Consulte ork_grafo_contexto {threadId: "${thread}"} ou ork grafo contexto ${thread} --json para o pacote da thread com evidencias e teto em bytes.\n`
80
+ + 'As tools ork_grafo_vizinhos, ork_grafo_chamadores, ork_grafo_importadores e ork_grafo_caminho permitem aprofundar. '
81
+ + 'Sem indice do HEAD, rode ork grafo indexar. O grafo e parcial; com arvore modificada, descreve o HEAD.\n';
82
+ }
72
83
  /** Onde um projeto guarda os templates que sobrescrevem os embutidos. */
73
84
  function dirDeTemplates(raiz) {
74
85
  return path.join(raiz, 'prompts');
@@ -170,6 +181,27 @@ exports.CONTRATO_DE_FASE = {
170
181
  variavelObrigatoria: 'pedido',
171
182
  validaFases: true,
172
183
  };
184
+ /**
185
+ * RM-057: os jeitos de um template pedir ao dono texto livre ou texto colado. Lista fechada, como o
186
+ * vocabulario do pulse: acrescentar um padrao e decisao de contrato, com teste. Casa sobre a linha
187
+ * em minusculas e sem acento.
188
+ */
189
+ exports.PADROES_DE_HITL_EM_TEXTO_LIVRE = Object.freeze([
190
+ { oQue: 'que o dono cole texto', padrao: /\b(cole|colar|colem)\b[^.\n]{0,60}\b(texto|aqui|mensagem|pedido|resposta|saida|conteudo)\b/ },
191
+ { oQue: 'que o dono cole texto', padrao: /\bpaste\b/ },
192
+ { oQue: 'confirmacao em texto livre', padrao: /\b(responda|digite|escreva|confirme|responder|digitar|escrever)\b[^.\n]{0,40}(\bconfirmo\b|texto livre|\bem texto\b)/ },
193
+ { oQue: 'confirmacao em texto livre', padrao: /\b(peca|peco|pedir|solicite|solicitar)\b[^.\n]{0,30}\bconfirmacao\b[^.\n]{0,20}\b(por escrito|em texto|textual)\b/ },
194
+ ]);
195
+ function procurarHitlEmTextoLivre(corpo) {
196
+ const achados = [];
197
+ corpo.split('\n').forEach((bruta, i) => {
198
+ const linha = bruta.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase();
199
+ const casou = exports.PADROES_DE_HITL_EM_TEXTO_LIVRE.find(p => p.padrao.test(linha));
200
+ if (casou)
201
+ achados.push({ linha: i + 1, oQue: casou.oQue });
202
+ });
203
+ return achados;
204
+ }
173
205
  /**
174
206
  * Lint de um template. Devolve os problemas; lista vazia quer dizer aprovado.
175
207
  *
@@ -231,6 +263,9 @@ function lintTemplate(t, contrato = exports.CONTRATO_DE_FASE) {
231
263
  if (bytes > exports.LIMITE_TEMPLATE_BYTES) {
232
264
  erro('tamanho', `${bytes} bytes acima do limite de ${exports.LIMITE_TEMPLATE_BYTES}`);
233
265
  }
266
+ for (const achado of procurarHitlEmTextoLivre(t.corpo)) {
267
+ erro('hitl-texto-livre', `linha ${achado.linha} pede ${achado.oQue}; HITL de conducao e selecao de 3 a 5 alternativas com uma Recomendacao (RM-057)`);
268
+ }
234
269
  if (t.bruto.includes('—')) {
235
270
  aviso('idioma', 'o template usa travessao longo (U+2014); o padrao do projeto e hifen ou virgula');
236
271
  }