@orkastery/cli 0.5.1 → 0.5.6

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 (260) hide show
  1. package/adapters/claude-code/README.md +158 -0
  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/ork.md +9 -0
  5. package/adapters/claude-code/mods/autoridade.json +56 -0
  6. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  7. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  8. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  9. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  10. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  11. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  12. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  13. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  14. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  15. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  16. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  17. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  18. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  19. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  20. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  21. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  22. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  23. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  24. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  25. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  27. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  28. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  29. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  30. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  31. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  32. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
  33. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  34. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  35. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  36. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  37. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  38. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  39. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  40. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  41. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  42. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  43. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  44. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  45. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  46. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  47. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  48. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  49. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  50. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  51. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  52. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  53. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  54. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  55. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  56. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  57. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  58. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  59. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  60. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  61. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  62. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  63. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  64. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  65. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  66. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  67. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  68. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  69. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  70. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  71. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  72. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  73. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  74. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  75. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  76. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  77. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  78. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  79. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  80. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  81. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  82. package/adapters/codex/skills/ork/SKILL.md +18 -3
  83. package/adapters/hermes/README.md +1 -0
  84. package/adapters/hermes/bin/ork-network-status.sh +10 -0
  85. package/adapters/hermes/hermes.plugin.json +1 -0
  86. package/adapters/hermes/hitl-ingress/__init__.py +2 -2
  87. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +7 -6
  88. package/adapters/openclaw/README.md +26 -5
  89. package/adapters/openclaw/dist/hitl-ingress.js +2 -2
  90. package/adapters/openclaw/dist/index.js +46 -11
  91. package/adapters/openclaw/openclaw.plugin.json +5 -1
  92. package/adapters/openclaw/package.json +2 -2
  93. package/adapters/openclaw/src/hitl-ingress.ts +2 -2
  94. package/adapters/openclaw/src/index.ts +49 -11
  95. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  96. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  97. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  98. package/assets/docs-en/produto/README.md +14 -0
  99. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  100. package/assets/docs-en/roadmap/README.md +14 -0
  101. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  102. package/assets/orkmind_bridge.py +117 -9
  103. package/dist/adapters/claude-bg.js +116 -18
  104. package/dist/adapters/codex.js +14 -4
  105. package/dist/agents-md.js +24 -14
  106. package/dist/auditrun.js +22 -3
  107. package/dist/board.js +20 -17
  108. package/dist/branch-de-estado.js +88 -10
  109. package/dist/busca-semantica.js +52 -12
  110. package/dist/canarios-rm057.js +149 -0
  111. package/dist/canarios.js +2 -0
  112. package/dist/catalogo.js +33 -0
  113. package/dist/ci.js +21 -8
  114. package/dist/claims-conferir.js +342 -0
  115. package/dist/claims.js +41 -1
  116. package/dist/company-brain-client.js +36 -1
  117. package/dist/company-brain-context.js +158 -22
  118. package/dist/company-brain-journal.js +2 -1
  119. package/dist/company-brain-migration.js +36 -1
  120. package/dist/conducao-sentinela.js +388 -0
  121. package/dist/conducao-texto.js +12 -18
  122. package/dist/conducao.js +122 -30
  123. package/dist/conhecimento.js +490 -0
  124. package/dist/docs.js +70 -17
  125. package/dist/doctor-pulse-cron.js +349 -0
  126. package/dist/doctor-rede.js +150 -0
  127. package/dist/doctor.js +195 -111
  128. package/dist/entrega-pr.js +42 -29
  129. package/dist/escopo-escrita.js +10 -1
  130. package/dist/esgotamentos.js +181 -0
  131. package/dist/estado-thread.js +23 -1
  132. package/dist/experiencia-instalacao.js +45 -25
  133. package/dist/experiencia.js +12 -2
  134. package/dist/fabrica-batida.js +310 -0
  135. package/dist/fabrica-estado.js +52 -14
  136. package/dist/fabrica-publicar.js +9 -1
  137. package/dist/fechamento.js +20 -66
  138. package/dist/fila-pesada.js +444 -0
  139. package/dist/fix.js +3 -2
  140. package/dist/forja.js +31 -7
  141. package/dist/gates.js +3 -24
  142. package/dist/handoff.js +10 -6
  143. package/dist/hitl-contract.js +59 -4
  144. package/dist/hitl-curto.js +11 -6
  145. package/dist/hitl-gates.js +5 -0
  146. package/dist/hitl-local-receipt.js +2 -0
  147. package/dist/hitl-lote.js +5 -2
  148. package/dist/hitl-resumo.js +38 -3
  149. package/dist/hitl-tempo-parado.js +201 -0
  150. package/dist/hitl-texto-livre.js +5 -5
  151. package/dist/hitl.js +29 -33
  152. package/dist/horario.js +41 -7
  153. package/dist/hosts.js +104 -11
  154. package/dist/impedimento.js +299 -0
  155. package/dist/index.js +961 -542
  156. package/dist/indice-vetorial.js +87 -10
  157. package/dist/indice.js +9 -1
  158. package/dist/init.js +56 -43
  159. package/dist/instabilidade.js +144 -0
  160. package/dist/integracoes-locais.js +4 -0
  161. package/dist/intelligence-graph-cli.js +170 -16
  162. package/dist/intelligence-graph-contexto.js +254 -0
  163. package/dist/intelligence-graph-contract.js +2 -1
  164. package/dist/intelligence-graph-extract-md.js +56 -4
  165. package/dist/intelligence-graph-extract-ts.js +71 -3
  166. package/dist/intelligence-graph-parsers.js +6 -4
  167. package/dist/intelligence-graph-query.js +66 -19
  168. package/dist/leases.js +664 -87
  169. package/dist/ledger-stats.js +15 -1
  170. package/dist/ledger.js +18 -1
  171. package/dist/licoes.js +1 -0
  172. package/dist/liveness.js +6 -3
  173. package/dist/locale-ajuda.js +761 -0
  174. package/dist/locale-gerados.js +160 -0
  175. package/dist/locale-master.js +99 -0
  176. package/dist/locale-onboarding.js +92 -0
  177. package/dist/locale-phase.js +151 -0
  178. package/dist/locale-pulse.js +211 -0
  179. package/dist/locale-retry.js +385 -0
  180. package/dist/locale-roadmap.js +102 -0
  181. package/dist/locale-ship.js +494 -0
  182. package/dist/locale-thread.js +277 -0
  183. package/dist/locale-verify.js +125 -0
  184. package/dist/locale.js +714 -0
  185. package/dist/maestro-runtime.js +4 -1
  186. package/dist/manifest.js +149 -4
  187. package/dist/maquina.js +23 -4
  188. package/dist/master-digest.js +6 -1
  189. package/dist/master-nota.js +18 -11
  190. package/dist/master.js +145 -31
  191. package/dist/mcp-artifacts.js +43 -3
  192. package/dist/mcp-git.js +42 -8
  193. package/dist/mcp-grafo-worker.js +5 -3
  194. package/dist/mcp-grafo.js +55 -6
  195. package/dist/mcp-server.js +22 -3
  196. package/dist/mcp-ship.js +3 -1
  197. package/dist/mcp-verify.js +6 -1
  198. package/dist/memoria.js +48 -6
  199. package/dist/modos.js +3 -6
  200. package/dist/network-roadmap.js +196 -18
  201. package/dist/noctum-arco.js +911 -0
  202. package/dist/noctum-capacidade.js +141 -0
  203. package/dist/noctum-envelope.js +810 -0
  204. package/dist/noctum-execucao.js +304 -0
  205. package/dist/noctum-fila.js +280 -0
  206. package/dist/ocupacao.js +40 -5
  207. package/dist/onboarding.js +40 -21
  208. package/dist/orkmind.js +99 -7
  209. package/dist/orquestracao.js +24 -21
  210. package/dist/parado-no-condutor.js +219 -38
  211. package/dist/phase.js +160 -52
  212. package/dist/policies.js +56 -5
  213. package/dist/portfolio.js +8 -3
  214. package/dist/postura-local.js +234 -0
  215. package/dist/preflight.js +11 -10
  216. package/dist/procedencia.js +225 -0
  217. package/dist/projeto-alvo.js +132 -5
  218. package/dist/prompts.js +40 -1
  219. package/dist/prova-ativacao.js +75 -6
  220. package/dist/pulse-delivery.js +47 -4
  221. package/dist/pulse.js +98 -19
  222. package/dist/ratelimit.js +24 -6
  223. package/dist/recall.js +3 -1
  224. package/dist/redacao-saida.js +63 -0
  225. package/dist/rede-adesao.js +399 -0
  226. package/dist/rede-forja.js +289 -0
  227. package/dist/rede-projetos.js +239 -0
  228. package/dist/rede-status.js +337 -0
  229. package/dist/rede.js +980 -0
  230. package/dist/retry.js +291 -140
  231. package/dist/roadmap-reservas.js +20 -3
  232. package/dist/roadmap-status.js +150 -34
  233. package/dist/runtime-context.js +181 -3
  234. package/dist/runtime-profiles.js +22 -1
  235. package/dist/runtimes.js +2 -1
  236. package/dist/saida-segura.js +58 -0
  237. package/dist/session-events.js +7 -3
  238. package/dist/session-watcher-claude.js +120 -24
  239. package/dist/session-watcher.js +185 -33
  240. package/dist/sessoes-contas.js +187 -0
  241. package/dist/sessoes-inventario.js +6 -18
  242. package/dist/sessoes.js +83 -2
  243. package/dist/ship-publicar.js +800 -0
  244. package/dist/ship.js +157 -88
  245. package/dist/steal.js +77 -0
  246. package/dist/thread-close.js +3 -2
  247. package/dist/thread.js +299 -49
  248. package/dist/util.js +8 -1
  249. package/dist/verify.js +141 -52
  250. package/dist/vida-da-thread.js +254 -0
  251. package/dist/worktree-local.js +165 -0
  252. package/dist/worktree.js +25 -2
  253. package/dist/yaml.js +27 -8
  254. package/eval/fixtures/fx-pedido-colado/caso.json +20 -0
  255. package/package.json +7 -3
  256. package/references/definition-of-done.md +1 -1
  257. package/schemas/code-artifact-graph.v1.schema.json +2 -1
  258. package/skills/README.md +1 -1
  259. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  260. package/skills/phases/master-metrics/SKILL.md +8 -3
@@ -56,13 +56,19 @@ exports.decodificarVetor = decodificarVetor;
56
56
  exports.lerIndice = lerIndice;
57
57
  exports.serializarIndice = serializarIndice;
58
58
  exports.gravarIndice = gravarIndice;
59
- exports.universoDoTenant = universoDoTenant;
59
+ exports.conferirUniverso = conferirUniverso;
60
+ exports.universoDaBusca = universoDaBusca;
61
+ exports.codigoDaFalha = codigoDaFalha;
60
62
  exports.conteudoRecusado = conteudoRecusado;
63
+ exports.indexavel = indexavel;
61
64
  exports.tokensEstimados = tokensEstimados;
62
65
  exports.dimDoModeloLocal = dimDoModeloLocal;
63
66
  exports.codigoDeEmbedding = codigoDeEmbedding;
64
67
  exports.espacoDoAlvo = espacoDoAlvo;
65
68
  exports.indexar = indexar;
69
+ exports.avisoDeCobertura = avisoDeCobertura;
70
+ exports.textoForaDaBusca = textoForaDaBusca;
71
+ exports.textoDoIndice = textoDoIndice;
66
72
  exports.vetoresCoerentes = vetoresCoerentes;
67
73
  const fs = __importStar(require("node:fs"));
68
74
  const os = __importStar(require("node:os"));
@@ -170,18 +176,48 @@ function gravarIndice(arquivo, indice) {
170
176
  return true;
171
177
  }
172
178
  /**
173
- * Universo do tenant: o export governado das colecoes do ork (filtro de injecao e visibilidade
174
- * da biblioteca), com checagem EXPLICITA do tenant antes de qualquer texto ir ao embed.
179
+ * RM-038 (D6): a fronteira do universo no `ork`, num lugar so. Entrada de outro tenant, de colecao
180
+ * fora do ork ou com id repetido e violacao tipada, nunca descarte silencioso: nada disso vai ao embed.
175
181
  */
176
- function universoDoTenant(fonte, tenant, colecoes = orkmind_1.COLECOES_DO_ORK) {
177
- return colecoes.flatMap(c => fonte.buscar({ collection: c, tags: { project: [tenant] } })
178
- .filter(e => e.collection === c && (e.tags.project ?? []).includes(tenant)))
179
- .sort((a, b) => a.collection.localeCompare(b.collection) || a.id.localeCompare(b.id));
182
+ function conferirUniverso(entradas, tenant, lidoEm = Date.now()) {
183
+ const vistos = new Set();
184
+ for (const e of entradas) {
185
+ if (!(0, orkmind_1.pertenceAoUniverso)(e, tenant, lidoEm) || vistos.has(e.id))
186
+ throw new Error('memory.query.scope-violation');
187
+ vistos.add(e.id);
188
+ }
189
+ }
190
+ /**
191
+ * RM-038 (D4): o universo da busca e do indice, o domicilio unico. A fonte le uma vez (a ponte
192
+ * filtra o tenant na origem e aplica a governanca da biblioteca); aqui a fronteira e conferida de
193
+ * novo, a ordem fica estavel e a contagem por colecao sai pronta para o status e o index.
194
+ */
195
+ function universoDaBusca(fonte, tenant) {
196
+ const lidoEm = Date.now();
197
+ const lido = fonte.universo(tenant);
198
+ conferirUniverso(lido.entradas, tenant, lidoEm);
199
+ const entradas = [...lido.entradas].sort((a, b) => a.collection.localeCompare(b.collection) || a.id.localeCompare(b.id));
200
+ const porColecao = Object.fromEntries(orkmind_1.COLECOES_DO_ORK.map(c => [c, 0]));
201
+ for (const e of entradas)
202
+ porColecao[e.collection] += 1;
203
+ return { tenant, lidoEm, entradas, porColecao, foraDaBusca: lido.foraDaBusca,
204
+ ...(lido.latenciaMs === undefined ? {} : { latenciaMs: lido.latenciaMs }) };
205
+ }
206
+ /** Codigo tipado de uma falha (`memory.query.window-saturated`), ou o padrao quando nao ha. */
207
+ function codigoDaFalha(erro, padrao = 'memory.universo.indisponivel') {
208
+ return /^[a-z]+(?:\.[a-z-]+)+/.exec(erro instanceof Error ? erro.message : '')?.[0] ?? padrao;
180
209
  }
181
210
  /** Conteudo que nunca vai ao provider: padrao de segredo da policy ou URL com credencial. */
182
211
  function conteudoRecusado(conteudo) {
183
212
  return (0, policies_1.procurarSegredos)(conteudo).length > 0 || URL_COM_CREDENCIAL.test(conteudo);
184
213
  }
214
+ /**
215
+ * RM-038: o indice embeda a entrada? Nao embeda texto vazio, acima do limite nem com padrao de
216
+ * segredo. Domicilio unico para o `indexar` e para o aviso de cobertura do status.
217
+ */
218
+ function indexavel(e) {
219
+ return e.content.trim() !== '' && e.content.length <= orkmind_1.EMBED_MAX_CARACTERES && !conteudoRecusado(e.content);
220
+ }
185
221
  function tokensEstimados(conteudo) {
186
222
  return Math.ceil(conteudo.length / exports.CARACTERES_POR_TOKEN);
187
223
  }
@@ -236,13 +272,20 @@ function espacoDoAlvo(config, alvo, env = process.env) {
236
272
  * que ja voltaram, porque cada vetor gravado e coerente por si.
237
273
  */
238
274
  function indexar(o) {
275
+ // RM-038 (D6): conferir de novo antes de qualquer coisa; nada de outro tenant vai ao embed, nem de
276
+ // um chamador que montou o universo a mao. Violacao falha alto, nunca vira descarte silencioso.
277
+ if (o.universo.tenant !== o.tenant)
278
+ throw new Error('memory.query.scope-violation');
279
+ conferirUniverso(o.universo.entradas, o.tenant, o.universo.lidoEm);
239
280
  const espaco = espacoDoAlvo(o.config, o.alvo, o.env);
240
- const universo = o.universo.filter(e => (e.tags.project ?? []).includes(o.tenant));
281
+ const universo = o.universo.entradas;
241
282
  const foraDoLimite = universo.filter(e => e.content.length > orkmind_1.EMBED_MAX_CARACTERES);
242
283
  const recusados = universo.filter(e => e.content.length <= orkmind_1.EMBED_MAX_CARACTERES && conteudoRecusado(e.content));
243
- const indexaveis = universo.filter(e => e.content.length <= orkmind_1.EMBED_MAX_CARACTERES && !conteudoRecusado(e.content) && e.content.trim());
284
+ const indexaveis = universo.filter(indexavel);
244
285
  const base = { alvo: o.alvo, modelo: null, dim: null, arquivo: null, dryRun: o.dryRun,
245
- universo: universo.length, coerentes: 0, embedados: 0, reescritos: 0, removidos: 0, recusados: recusados.length,
286
+ universo: universo.length, porColecao: { ...o.universo.porColecao }, foraDaBusca: o.universo.foraDaBusca,
287
+ latenciaUniversoMs: o.universo.latenciaMs ?? null,
288
+ coerentes: 0, embedados: 0, reescritos: 0, removidos: 0, recusados: recusados.length,
246
289
  foraDoLimite: foraDoLimite.length, truncados: 0, tokensEstimados: 0, custoEstimadoUsd: 0, chamadasAoProvider: 0, motivo: null, detalhe: '' };
247
290
  if ('motivo' in espaco) {
248
291
  const tokens = indexaveis.reduce((t, e) => t + tokensEstimados(e.content), 0);
@@ -302,6 +345,40 @@ function indexar(o) {
302
345
  return { ...r, motivo, detalhe: `indexacao interrompida depois de ${r.embedados} vetor(es); os lotes concluidos ficaram gravados` };
303
346
  return r;
304
347
  }
348
+ /**
349
+ * RM-038 (D7): o aviso de cobertura, o mesmo no status e na busca. Reindexar so e sugerido quando
350
+ * resolve; o que o indice nunca embeda (vazio, acima do limite, padrao de segredo) e dito a parte.
351
+ */
352
+ function avisoDeCobertura(coerentes, entradas, alvo, onde = '') {
353
+ if (coerentes >= entradas.length)
354
+ return null;
355
+ const foraPorDesenho = entradas.filter(e => !indexavel(e)).length;
356
+ const base = `o indice cobre ${coerentes} de ${entradas.length} entrada(s) que a busca enxerga${onde}`;
357
+ if (coerentes < entradas.length - foraPorDesenho)
358
+ return `${base}: rode ork memory index${alvo === 'fallback' ? ' --modelo fallback' : ''}`;
359
+ return `${base}; ${foraPorDesenho} fica(m) fora do indice por desenho (vazia, acima de ${orkmind_1.EMBED_MAX_CARACTERES} caracteres ou com padrao de segredo)`;
360
+ }
361
+ /** RM-038: a linha do que fica fora da busca, a mesma no `ork memory index` e no `ork memory status`. */
362
+ function textoForaDaBusca(f) {
363
+ return f ? `${f.injecao} com injection_risk e ${f.expiradas} expirada(s) (governanca da biblioteca), ` +
364
+ `${f.outrasColecoes} em outras colecoes (fora da busca do ork); nada disso vai ao embed` : 'nao medido nesta base';
365
+ }
366
+ /** Texto de `ork memory index`: de que universo, o que foi (ou seria) embedado e quanto custa estimado. */
367
+ function textoDoIndice(r) {
368
+ const custo = r.custoEstimadoUsd === null ? 'nao estimado' : `US$ ${r.custoEstimadoUsd.toFixed(8)}`;
369
+ const colecoes = Object.entries(r.porColecao).map(([c, n]) => `${c} ${n}`).join(', ');
370
+ return [
371
+ `Indice vetorial (${r.alvo}${r.dryRun ? ', --dry-run' : ''}): ${r.modelo ?? '(sem modelo)'}${r.dim ? ` / ${r.dim} dim` : ''}`,
372
+ ` universo da busca ${r.universo} entrada(s): ${colecoes}; coerentes ${r.coerentes}`,
373
+ ` fora da busca ${textoForaDaBusca(r.foraDaBusca)}`,
374
+ ` embedados ${r.embedados} (reescritos ${r.reescritos}); removidos ${r.removidos}`,
375
+ ` fora do indice ${r.recusados} recusada(s) por padrao de segredo, ${r.foraDoLimite} acima do limite`,
376
+ ...(r.truncados ? [` truncados ${r.truncados} acima do contexto do modelo local, embedados pelo comeco`] : []),
377
+ ` estimativa ${r.tokensEstimados} token(s), ${custo}; chamadas ao provider ${r.chamadasAoProvider}`,
378
+ ...(r.arquivo ? [` arquivo ${r.arquivo}`] : []),
379
+ ...(r.motivo ? [` motivo ${r.motivo}: ${r.detalhe}`] : r.detalhe ? [` ${r.detalhe}`] : []),
380
+ ].join('\n');
381
+ }
305
382
  /** Vetores coerentes de um indice para o universo informado: a base da busca e da cobertura. */
306
383
  function vetoresCoerentes(indice, universo) {
307
384
  const saida = new Map();
package/dist/indice.js CHANGED
@@ -59,11 +59,19 @@ exports.INSUMOS_DO_INDICE = [
59
59
  * reversao e `ship.ts`, que e quem sabe de merge e de base; aqui so se conta o evento
60
60
  * que ele gravou.
61
61
  */
62
+ function pausaPrevistaDoFast(e) {
63
+ return e.tipo === ledger_1.TIPOS_DE_EVENTO.shipBloqueado && e.modo === 'fast' && e.motivo === 'human.pending';
64
+ }
62
65
  function calcularIndice(eventos) {
63
66
  const parcelas = [];
64
67
  let valor = exports.INDICE_BASE;
65
68
  for (const insumo of exports.INSUMOS_DO_INDICE) {
66
- const ocorrencias = eventos.filter((e) => e.tipo === insumo.evento).length;
69
+ // Ensaio de 03/10/2026 (RM-049): o `ork ship --dry-run` barrado grava `ship_blocked` com `dryRun: true`;
70
+ // ensaio nao e tropeco da entrega, como ja nao e pausa no board (fatia 2 do ensaio da 0.5.0, P2).
71
+ // EN8 (a), decisao do dono de 11/10/2026: no #Fast, o ship sem autorizacao de push e a pausa prevista
72
+ // do modo, e o `ship_blocked` com `human.pending` tambem nao conta.
73
+ const ocorrencias = eventos.filter((e) => e.tipo === insumo.evento && e.dryRun !== true &&
74
+ !pausaPrevistaDoFast(e)).length;
67
75
  if (ocorrencias === 0)
68
76
  continue;
69
77
  const bruto = insumo.peso * ocorrencias;
package/dist/init.js CHANGED
@@ -46,7 +46,9 @@ exports.baseBranchDetectada = baseBranchDetectada;
46
46
  exports.verifyDetectado = verifyDetectado;
47
47
  exports.detectar = detectar;
48
48
  exports.manifestoYaml = manifestoYaml;
49
+ exports.exigirRepositorioParaInit = exigirRepositorioParaInit;
49
50
  exports.init = init;
51
+ const locale_1 = require("./locale");
50
52
  const fs = __importStar(require("node:fs"));
51
53
  const path = __importStar(require("node:path"));
52
54
  const manifest_1 = require("./manifest");
@@ -54,7 +56,8 @@ const slug_1 = require("./slug");
54
56
  const util_1 = require("./util");
55
57
  const horario_1 = require("./horario");
56
58
  const modos_1 = require("./modos");
57
- exports.PROXIMO_PASSO_INIT = 'Proximo passo: ork doctor; depois ork onboarding para conduzir a entrevista do projeto.';
59
+ /** O proximo passo do `ork init` em pt-BR; o texto do CLI sai pelo catalogo (`msg().init.proximoPasso`). */
60
+ exports.PROXIMO_PASSO_INIT = (0, locale_1.msg)('pt-BR').init.proximoPasso;
58
61
  /** Raiz do repositorio git, resolvendo tambem o caso de worktree. */
59
62
  function raizDoRepo(dirInicial) {
60
63
  const r = (0, util_1.exec)('git', ['rev-parse', '--show-toplevel'], dirInicial);
@@ -143,55 +146,57 @@ function detectar(dirInicial, nomeForcado, abbrevForcada) {
143
146
  verify: verifyDetectado(raiz),
144
147
  };
145
148
  }
146
- /** Serializa o manifesto v1 a partir da deteccao. */
147
- function manifestoYaml(d) {
148
- const linhaVerify = (chave, valor) => valor ? ` ${chave}: "${valor}"` : ` # ${chave}: nao detectado`;
149
- return `# Manifesto do Orkastery (v1, bloco B0)
150
- # Gerado por \`ork init\`. Fonte unica da configuracao do projeto.
151
- # Limite duro de 16 KB: prosa longa vai para a memoria com tag, nao para este arquivo.
149
+ /** Cada linha do texto vira comentario do YAML, com o recuo da chave em que ele fica. */
150
+ function comentario(texto, recuo = ' ') {
151
+ return texto.split('\n').map((linha) => `${recuo}# ${linha}`).join('\n');
152
+ }
153
+ /**
154
+ * Serializa o manifesto v1 a partir da deteccao. RM-061 (F3a, D1 a D3): os comentarios saem na lingua pedida, pela
155
+ * familia `gerados` do catalogo; chaves, valores e exemplos comentados sao este esqueleto, o mesmo nas duas linguas.
156
+ * Sem locale, pt-BR: so o `ork init` passa a lingua do dono (D2).
157
+ */
158
+ function manifestoYaml(d, locale = locale_1.LOCALE_PADRAO) {
159
+ const c = (0, locale_1.msg)(locale).gerados.manifesto;
160
+ const linhaVerify = (chave, valor) => valor ? ` ${chave}: "${valor}"` : ` # ${chave}: ${c.naoDetectado}`;
161
+ return `${comentario(c.cabecalho, '')}
152
162
 
153
163
  project:
154
164
  name: "${d.nome}"
155
- # abbrev: ate 3 caracteres [a-z0-9], parte 1 do slug de sessao, unica no workspace
165
+ ${comentario(c.abbrev)}
156
166
  abbrev: "${d.abbrev}"
157
167
  stage: nascente
158
168
 
159
169
  owner:
160
- # fuso do dono (nome IANA): todo horario mostrado a pessoas usa este fuso.
161
- # Ausente: fuso do sistema. Exemplo:
170
+ ${comentario(c.fuso)}
162
171
  # timezone: "${horario_1.FUSO_DE_BRASILIA}"
163
- # Preferências: ork onboarding set maestro --conteudo '{"owner":{"experience":true}}'
164
- # language: pt-BR # ausente: locale do sistema
172
+ ${comentario(c.preferencias(`ork onboarding set maestro --conteudo '{"owner":{"experience":true}}'`))}
173
+ # language: ${c.exemploDeIdioma} # ${c.idiomaAusente}
165
174
  # depth: curta # curta | detalhada
166
- # experience: true # false desativa o pacote na próxima instalação do adaptador
175
+ # experience: true # ${c.experienciaFalse}
167
176
 
168
177
  board:
169
178
  adapter: hermes-kanban
170
179
  default: default
171
180
 
172
181
  runtime:
173
- # Runtimes homologados:
174
- # claude-bg (padrao, mais maduro): despacha \`claude --bg\`, sessao visivel no app
175
- # e em \`claude agents --json\`
176
- # codex: despacha \`codex exec\` headless na sessao autenticada do Codex CLI,
177
- # verificado no rollout de $CODEX_HOME/sessions (requer \`codex login\`)
182
+ ${comentario(c.runtimes)}
178
183
  adapter: claude-bg
179
184
  model: opus
180
185
  effort: high
181
- # subscription-only: proibido despachar por provider pago (cobra por token, fora da assinatura)
186
+ ${comentario(c.providerPolicy)}
182
187
  provider_policy: subscription-only
183
- # sandbox do runtime codex: read-only | workspace-write | danger-full-access
184
- # (danger-full-access SO onde o bubblewrap nao roda; \`ork doctor\` tem a sonda)
188
+ ${comentario(c.sandbox)}
185
189
  sandbox: workspace-write
186
190
 
187
191
  conduction:
188
- # modo usado quando o pedido do builder nao traz #TAG
192
+ ${comentario(c.modoPadrao)}
189
193
  default_mode: classic
190
194
  allowed_modes: [${modos_1.ORDEM_DOS_MODOS.join(', ')}]
191
195
 
192
196
  worktree:
193
197
  base_branch: "${d.baseBranch}"
194
198
  dir: ".claude/worktrees"
199
+ ${comentario(c.porThread)}
195
200
  por_thread: true
196
201
 
197
202
  verify:
@@ -200,54 +205,46 @@ ${linhaVerify('test', d.verify.test)}
200
205
  ${linhaVerify('typecheck', d.verify.typecheck)}
201
206
 
202
207
  ci:
203
- # Ative depois de publicar o workflow e tornar ork-verify um check obrigatório.
208
+ ${comentario(c.ci)}
204
209
  required_for_ship: false
205
210
  context: ork-verify
206
- # command: "npm test" # perfil hermético opcional do runner; sem ele, usa verify acima
211
+ # command: "npm test" # ${c.ciComando}
207
212
 
208
213
  concurrency:
209
214
  max_parallel_threads: 3
210
- # thread despachada sem atividade (ledger parado, sessao nao-working) por mais que
211
- # isto NAO ocupa vaga do escalonador: a vaga volta para quem esta pronto para rodar
215
+ ${comentario(c.staleAfter)}
212
216
  stale_after_min: 240
213
217
 
214
218
  handoff:
215
- # gate de tokens (bloco B1): rotaciona a sessao acima destas ocupacoes de janela
219
+ ${comentario(c.handoff)}
216
220
  rotate_above: 0.70
217
221
  force_rotate_above: 0.85
218
222
 
219
223
  retry:
220
- # autonomia do bloco B3: retry tipado por motivo de gate e fila duravel de rate limit
221
- # max_tentativas e o LIMITE DE ESCALACAO: estourado, pausa qualquer modo, ate #Auto
224
+ ${comentario(c.retry)}
222
225
  max_tentativas: 3
223
- # janela usada so quando o runtime diz "rate limit" e NAO diz a hora do reset
224
- # (fica marcada como estimativa na fila; o ork nunca inventa horario medido)
226
+ ${comentario(c.janelaPadrao)}
225
227
  janela_padrao_min: 60
226
228
  escalar_esforco: true
227
229
 
228
230
  memory:
229
- # files = fallback honesto sem OrkMind (handoff por arquivos, ponteiro path#ancora)
230
- # orkmind = camada semantica do bloco B6 por cima, com degradacao honesta para files
231
+ ${comentario(c.memoriaModo)}
231
232
  mode: files
232
- # NOME da variavel de ambiente com a DSN da base PROPRIA deste tenant, nunca a DSN.
233
- # Vazio = o regime orkmind nao liga (o ork nao adivinha base: base alheia e pior que
234
- # base nenhuma, precedente do incidente memory-orkmind).
233
+ ${comentario(c.databaseUrl)}
235
234
  database_url_env: ""
236
235
  cli: orkmind
237
236
  timeout_ms: 15000
238
- # busca por significado (ork memory search --texto): sem o bloco, provider none (desligada).
239
- # api_key_env recebe o NOME da variavel com a chave dedicada, nunca o valor.
237
+ ${comentario(c.embedding)}
240
238
  # embedding:
241
239
  # provider: "none" # none | openrouter
242
240
  # model: "qwen/qwen3-embedding-8b"
243
241
  # dim: 1024
244
242
  # api_key_env: "ORKASTERY_EMBEDDING_API_KEY"
245
- # fallback_model: "" # modelo local offline, ex.: intfloat/multilingual-e5-small
243
+ # fallback_model: "" # ${c.modeloOffline}
246
244
  # max_tokens_por_execucao: 1000000
247
245
 
248
246
  audit:
249
- # governanca de custo dos auditores periodicos (bloco B5)
250
- # janela ociosa da assinatura: fora dela a rodada so anda com --agora <quem>
247
+ ${comentario(c.audit)}
251
248
  janela_ociosa: "22:00-06:00"
252
249
  effort: eco
253
250
  since_padrao: 7d
@@ -259,7 +256,23 @@ policies:
259
256
  push_direto_na_base: block
260
257
  `;
261
258
  }
262
- /** Gera o manifesto e o esqueleto de `.orkastery/`. Nao sobrescreve sem `force`. */
259
+ /**
260
+ * Ensaio de 03/10/2026 (RM-049): o `ork init` rodado por engano fora de um repositorio (no HOME, por
261
+ * exemplo) gravava manifesto, `AGENTS.md` e `.orkastery/` ali e saia 0; um repositorio criado depois
262
+ * dentro dessa pasta herdava o manifesto de fora, com outro nome e outra abbrev, e o doctor dizia PRONTO.
263
+ * A CLI recusa antes de gravar qualquer coisa. A funcao `init` segue aceitando qualquer pasta (demo e
264
+ * canarios montam o projeto por ela).
265
+ */
266
+ function exigirRepositorioParaInit(dir) {
267
+ const r = (0, util_1.exec)('git', ['rev-parse', '--is-inside-work-tree'], dir);
268
+ if (r.ok && r.stdout.trim() === 'true')
269
+ return;
270
+ throw new Error((0, locale_1.msg)().init.foraDoRepositorio(path.resolve(dir)));
271
+ }
272
+ /**
273
+ * Gera o manifesto e o esqueleto de `.orkastery/`. Nao sobrescreve sem `force`. Os comentarios do manifesto saem
274
+ * no `locale` pedido (RM-061, F3a), pt-BR por omissao.
275
+ */
263
276
  function init(dirInicial, opcoes = {}) {
264
277
  const deteccao = detectar(dirInicial, opcoes.nome, opcoes.abbrev);
265
278
  const caminho = path.join(deteccao.raiz, manifest_1.NOME_MANIFESTO);
@@ -267,7 +280,7 @@ function init(dirInicial, opcoes = {}) {
267
280
  if (existe && !opcoes.force) {
268
281
  return { caminho, criado: false, deteccao };
269
282
  }
270
- (0, util_1.gravar)(caminho, manifestoYaml(deteccao));
283
+ (0, util_1.gravar)(caminho, manifestoYaml(deteccao, opcoes.locale));
271
284
  const estado = path.join(deteccao.raiz, manifest_1.DIR_ESTADO);
272
285
  fs.mkdirSync(path.join(estado, 'threads'), { recursive: true });
273
286
  // Fatia 2 do ensaio da 0.5.0 (P3): o estado e da maquina; fica fora do git sem mexer no `.gitignore` do usuario.
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ /**
3
+ * RM-037 (fatia 6, P6/T15): o registro de instabilidade, contrato `ork.instabilidade/v1`.
4
+ *
5
+ * Arquivo `core/instabilidade.json` na arvore verificada. Nasce vazio. Uma entrada diz que um teste
6
+ * depende do relogio e por isso reprova sob steal alto; ela so entra com a taxa MEDIDA (falhas em
7
+ * rodadas, com o comando que mediu e a data) e com revalidacao em ate 30 dias da medida. Vencida a
8
+ * revalidacao, a entrada deixa de valer ate alguem medir de novo.
9
+ *
10
+ * O registro nunca atenua uma falha sozinho: ele so diz ao verify que aquele teste e de relogio, e
11
+ * a reprovacao so vira `verify.timeout` com o steal medido acima de 40% na janela do comando. Sem
12
+ * steal, o teste registrado reprova como qualquer outro.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CAUSAS_DE_INSTABILIDADE = exports.REVALIDACAO_MAXIMA_DIAS = exports.ARQUIVO_INSTABILIDADE = exports.CONTRATO_INSTABILIDADE = void 0;
16
+ exports.validarRegistro = validarRegistro;
17
+ exports.vigente = vigente;
18
+ exports.lerRegistroDeInstabilidade = lerRegistroDeInstabilidade;
19
+ exports.testesDeRelogioVigentes = testesDeRelogioVigentes;
20
+ const node_fs_1 = require("node:fs");
21
+ const node_path_1 = require("node:path");
22
+ exports.CONTRATO_INSTABILIDADE = 'ork.instabilidade/v1';
23
+ exports.ARQUIVO_INSTABILIDADE = 'core/instabilidade.json';
24
+ /** Prazo maximo entre a medida e a revalidacao. */
25
+ exports.REVALIDACAO_MAXIMA_DIAS = 30;
26
+ exports.CAUSAS_DE_INSTABILIDADE = ['relogio'];
27
+ const DIA_MS = 24 * 60 * 60 * 1000;
28
+ const CHAVES_DA_ENTRADA = new Set(['teste', 'arquivo', 'causa', 'taxa', 'revalidarAte', 'nota']);
29
+ const CHAVES_DA_TAXA = new Set(['falhas', 'rodadas', 'comando', 'medidaEm']);
30
+ function data(valor) {
31
+ if (typeof valor !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(valor))
32
+ return null;
33
+ const ms = Date.parse(`${valor}T00:00:00Z`);
34
+ return Number.isFinite(ms) && new Date(ms).toISOString().slice(0, 10) === valor ? ms : null;
35
+ }
36
+ const texto = (v) => typeof v === 'string' && v.trim() !== '';
37
+ const inteiro = (v) => typeof v === 'number' && Number.isInteger(v);
38
+ /** Os erros de contrato de um registro ja desserializado. Lista vazia: o registro vale. */
39
+ function validarRegistro(bruto) {
40
+ const erros = [];
41
+ if (!bruto || typeof bruto !== 'object' || Array.isArray(bruto))
42
+ return ['o registro precisa ser um objeto JSON'];
43
+ const r = bruto;
44
+ if (r.contrato !== exports.CONTRATO_INSTABILIDADE)
45
+ erros.push(`contrato precisa ser "${exports.CONTRATO_INSTABILIDADE}"`);
46
+ for (const chave of Object.keys(r)) {
47
+ if (chave !== 'contrato' && chave !== 'entradas')
48
+ erros.push(`chave desconhecida no registro: ${chave}`);
49
+ }
50
+ if (!Array.isArray(r.entradas))
51
+ return [...erros, 'entradas precisa ser uma lista (vazia no nascimento)'];
52
+ const vistos = new Set();
53
+ r.entradas.forEach((e, i) => {
54
+ const onde = `entradas[${i}]`;
55
+ if (!e || typeof e !== 'object' || Array.isArray(e)) {
56
+ erros.push(`${onde}: precisa ser um objeto`);
57
+ return;
58
+ }
59
+ const entrada = e;
60
+ for (const chave of Object.keys(entrada)) {
61
+ if (!CHAVES_DA_ENTRADA.has(chave))
62
+ erros.push(`${onde}: chave desconhecida ${chave}`);
63
+ }
64
+ if (!texto(entrada.teste))
65
+ erros.push(`${onde}.teste: nome do teste como o runner reporta`);
66
+ else if (vistos.has(entrada.teste))
67
+ erros.push(`${onde}.teste: "${entrada.teste}" repetido`);
68
+ else
69
+ vistos.add(entrada.teste);
70
+ if (!texto(entrada.arquivo))
71
+ erros.push(`${onde}.arquivo: caminho do teste`);
72
+ if (!exports.CAUSAS_DE_INSTABILIDADE.includes(entrada.causa)) {
73
+ erros.push(`${onde}.causa: ${exports.CAUSAS_DE_INSTABILIDADE.join(' ou ')}`);
74
+ }
75
+ if (entrada.nota !== undefined && typeof entrada.nota !== 'string')
76
+ erros.push(`${onde}.nota: texto`);
77
+ const taxa = entrada.taxa;
78
+ let medida = null;
79
+ if (!taxa || typeof taxa !== 'object' || Array.isArray(taxa)) {
80
+ erros.push(`${onde}.taxa: sem taxa medida a entrada nao entra (falhas, rodadas, comando, medidaEm)`);
81
+ }
82
+ else {
83
+ for (const chave of Object.keys(taxa)) {
84
+ if (!CHAVES_DA_TAXA.has(chave))
85
+ erros.push(`${onde}.taxa: chave desconhecida ${chave}`);
86
+ }
87
+ if (!inteiro(taxa.rodadas) || taxa.rodadas < 1)
88
+ erros.push(`${onde}.taxa.rodadas: inteiro de rodadas medidas, 1 ou mais`);
89
+ if (!inteiro(taxa.falhas) || taxa.falhas < 1)
90
+ erros.push(`${onde}.taxa.falhas: inteiro de reprovacoes medidas, 1 ou mais`);
91
+ else if (inteiro(taxa.rodadas) && taxa.falhas > taxa.rodadas)
92
+ erros.push(`${onde}.taxa.falhas: maior que rodadas`);
93
+ if (!texto(taxa.comando))
94
+ erros.push(`${onde}.taxa.comando: o comando que mediu, reproduzivel`);
95
+ medida = data(taxa.medidaEm);
96
+ if (medida === null)
97
+ erros.push(`${onde}.taxa.medidaEm: data AAAA-MM-DD valida`);
98
+ }
99
+ const revalidar = data(entrada.revalidarAte);
100
+ if (revalidar === null)
101
+ erros.push(`${onde}.revalidarAte: data AAAA-MM-DD valida`);
102
+ else if (medida !== null) {
103
+ if (revalidar < medida)
104
+ erros.push(`${onde}.revalidarAte: antes da medida`);
105
+ else if (revalidar - medida > exports.REVALIDACAO_MAXIMA_DIAS * DIA_MS) {
106
+ erros.push(`${onde}.revalidarAte: no maximo ${exports.REVALIDACAO_MAXIMA_DIAS} dias depois de taxa.medidaEm`);
107
+ }
108
+ }
109
+ });
110
+ return erros;
111
+ }
112
+ /** A entrada vale hoje? Vale ate o fim do dia de `revalidarAte`, em UTC. */
113
+ function vigente(entrada, agoraMs = Date.now()) {
114
+ const ate = data(entrada.revalidarAte);
115
+ return ate !== null && agoraMs < ate + DIA_MS;
116
+ }
117
+ /** Le o registro da arvore `cwd`. Ausente: vazio. Ilegivel ou fora do contrato: erros e nada vale. */
118
+ function lerRegistroDeInstabilidade(cwd, agoraMs = Date.now()) {
119
+ const arquivo = (0, node_path_1.join)(cwd, exports.ARQUIVO_INSTABILIDADE);
120
+ if (!(0, node_fs_1.existsSync)(arquivo))
121
+ return { arquivo: exports.ARQUIVO_INSTABILIDADE, presente: false, erros: [], vigentes: [], vencidas: [] };
122
+ let bruto;
123
+ try {
124
+ bruto = JSON.parse((0, node_fs_1.readFileSync)(arquivo, 'utf8'));
125
+ }
126
+ catch (e) {
127
+ return { arquivo: exports.ARQUIVO_INSTABILIDADE, presente: true, erros: [`JSON ilegivel: ${e.message}`], vigentes: [], vencidas: [] };
128
+ }
129
+ const erros = validarRegistro(bruto);
130
+ if (erros.length > 0)
131
+ return { arquivo: exports.ARQUIVO_INSTABILIDADE, presente: true, erros, vigentes: [], vencidas: [] };
132
+ const entradas = bruto.entradas;
133
+ return {
134
+ arquivo: exports.ARQUIVO_INSTABILIDADE,
135
+ presente: true,
136
+ erros: [],
137
+ vigentes: entradas.filter((e) => vigente(e, agoraMs)),
138
+ vencidas: entradas.filter((e) => !vigente(e, agoraMs)),
139
+ };
140
+ }
141
+ /** Os nomes dos testes de relogio que o verify pode considerar nesta rodada. */
142
+ function testesDeRelogioVigentes(registro) {
143
+ return new Set(registro.vigentes.filter((e) => e.causa === 'relogio').map((e) => e.teste));
144
+ }
@@ -16,4 +16,8 @@ exports.TESTES_DE_INTEGRACAO_LOCAL = new Set([
16
16
  'memory-publication-profile.test.js', 'native-fixture.test.js', 'orkmind-transport.test.js', 'verify-sandbox.test.js',
17
17
  // RM-037 (fatia 3): o worker do ork_git_commit e o sandbox do verify de verdade, como no mcp-git.test.js.
18
18
  'rm037-fatia3-hard-link-mcp-git.test.js', 'rm037-fatia3-lease-mcp-git.test.js',
19
+ // RM-038 (fatia de correcao): a ponte com o GovernedStore real da biblioteca instalada.
20
+ 'rm038-universo-ponte.test.js',
21
+ // RM-059 (T0.10): a conferencia pontual com o sandbox real do codex, como o mcp-verify.test.js.
22
+ 'claims-conferir-sandbox.test.js',
19
23
  ]);