@orkastery/cli 0.2.0 → 0.4.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 (257) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +86 -65
  3. package/adapters/README.md +30 -15
  4. package/adapters/claude-code/.claude-plugin/plugin.json +11 -5
  5. package/adapters/claude-code/README.md +110 -8
  6. package/adapters/claude-code/commands/check.md +4 -3
  7. package/adapters/claude-code/commands/goal.md +3 -2
  8. package/adapters/claude-code/commands/master.md +3 -2
  9. package/adapters/claude-code/commands/onboarding.md +21 -0
  10. package/adapters/claude-code/commands/ork.md +99 -27
  11. package/adapters/claude-code/hooks/hooks.json +6 -1
  12. package/adapters/claude-code/hooks/ork-guard.js +1 -1
  13. package/adapters/claude-code/hooks/ork-sensor.js +66 -0
  14. package/adapters/codex/skills/ork/SKILL.md +57 -0
  15. package/adapters/hermes/README.md +161 -0
  16. package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
  17. package/adapters/hermes/bin/ork-brain.sh +4 -0
  18. package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
  19. package/adapters/hermes/bin/ork-maestro.sh +6 -0
  20. package/adapters/hermes/bin/ork-master-enviar.py +84 -0
  21. package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
  22. package/adapters/hermes/hermes.plugin.json +24 -4
  23. package/adapters/hermes/hitl-ingress/__init__.py +356 -0
  24. package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
  25. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
  26. package/adapters/openclaw/README.md +136 -27
  27. package/adapters/openclaw/bin/ork-brain.sh +4 -0
  28. package/adapters/openclaw/construir.sh +19 -0
  29. package/adapters/openclaw/dist/hitl-ingress.js +199 -0
  30. package/adapters/openclaw/dist/index.js +437 -0
  31. package/adapters/openclaw/openclaw.plugin.json +39 -134
  32. package/adapters/openclaw/package.json +26 -0
  33. package/adapters/openclaw/src/hitl-ingress.ts +180 -0
  34. package/adapters/openclaw/src/index.ts +460 -0
  35. package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
  36. package/adapters/openclaw/tsconfig.json +15 -0
  37. package/assets/docs/markdownlint-cli2.jsonc +22 -0
  38. package/assets/docs/padroes/documentacao-de-produto.md +133 -0
  39. package/assets/docs/padroes/roadmap-de-produto.md +98 -0
  40. package/assets/docs/produto/README.md +14 -0
  41. package/assets/docs/produto/_modelo-feature.md +59 -0
  42. package/assets/docs/roadmap/README.md +14 -0
  43. package/assets/docs/roadmap/_modelo-item.md +73 -0
  44. package/assets/orkmind-native-schema.json +32 -0
  45. package/assets/orkmind_bridge.py +357 -0
  46. package/assets/orkmind_fixture.py +67 -0
  47. package/assets/orkmind_prospective.py +138 -0
  48. package/assets/reference-tariffs-i07.json +23 -0
  49. package/dist/adapters/claude-bg.js +488 -39
  50. package/dist/adapters/codex-controller-sensor.js +449 -0
  51. package/dist/adapters/codex-controller-worker.js +361 -0
  52. package/dist/adapters/codex-controller.js +252 -0
  53. package/dist/adapters/codex-events.js +205 -0
  54. package/dist/adapters/codex-question.js +26 -0
  55. package/dist/adapters/codex-runner.js +133 -0
  56. package/dist/adapters/codex.js +394 -0
  57. package/dist/agents-md.js +84 -0
  58. package/dist/auditoria.js +12 -9
  59. package/dist/auditrun.js +5 -4
  60. package/dist/board.js +174 -23
  61. package/dist/branch-de-estado.js +136 -0
  62. package/dist/canarios-hitl.js +177 -0
  63. package/dist/canarios-i43.js +543 -0
  64. package/dist/canarios-pulse.js +147 -0
  65. package/dist/canarios-sensores.js +129 -0
  66. package/dist/canarios.js +111 -2
  67. package/dist/catalogo.js +9 -0
  68. package/dist/ci.js +223 -0
  69. package/dist/ciclos.js +2 -1
  70. package/dist/claim-lint.js +64 -0
  71. package/dist/claims.js +60 -0
  72. package/dist/company-brain-capture.js +195 -0
  73. package/dist/company-brain-cli.js +123 -0
  74. package/dist/company-brain-client.js +61 -0
  75. package/dist/company-brain-contract.js +166 -0
  76. package/dist/company-brain-journal.js +192 -0
  77. package/dist/company-brain-mcp.js +33 -0
  78. package/dist/company-brain-migration.js +60 -0
  79. package/dist/company-brain-source.js +177 -0
  80. package/dist/company-brain-worker.js +18 -0
  81. package/dist/conducao-texto.js +61 -0
  82. package/dist/conducao.js +876 -0
  83. package/dist/contrato-publico.js +39 -0
  84. package/dist/creation-operation-store.js +251 -0
  85. package/dist/creation-operation.js +148 -0
  86. package/dist/decisao-autonoma.js +183 -0
  87. package/dist/delegation.js +79 -0
  88. package/dist/demo.js +120 -0
  89. package/dist/docs.js +828 -0
  90. package/dist/doctor.js +184 -25
  91. package/dist/entrega-pr.js +117 -0
  92. package/dist/escopo-escrita.js +71 -0
  93. package/dist/estado-thread.js +222 -0
  94. package/dist/evalrunner.js +12 -0
  95. package/dist/fabrica-estado.js +329 -0
  96. package/dist/fabrica-publicar.js +76 -0
  97. package/dist/fix.js +22 -1
  98. package/dist/gates.js +59 -11
  99. package/dist/handoff.js +39 -23
  100. package/dist/hitl-canais.js +333 -0
  101. package/dist/hitl-classificacao.js +131 -0
  102. package/dist/hitl-contract.js +465 -0
  103. package/dist/hitl-estado.js +136 -0
  104. package/dist/hitl-gates.js +554 -0
  105. package/dist/hitl-ingress-receipt.js +382 -0
  106. package/dist/hitl-local-atestado.js +57 -0
  107. package/dist/hitl-local-receipt.js +328 -0
  108. package/dist/hitl-local.js +143 -0
  109. package/dist/hitl-lock.js +139 -0
  110. package/dist/hitl-lote.js +223 -0
  111. package/dist/hitl-native-offer.js +97 -0
  112. package/dist/hitl-native.js +65 -0
  113. package/dist/hitl-presentation.js +209 -0
  114. package/dist/hitl-public-receipt.js +176 -0
  115. package/dist/hitl-resumo.js +209 -0
  116. package/dist/hitl-sessions.js +475 -0
  117. package/dist/hitl.js +711 -0
  118. package/dist/horario.js +269 -0
  119. package/dist/hosts.js +198 -22
  120. package/dist/index.js +1741 -94
  121. package/dist/indice.js +99 -0
  122. package/dist/init.js +28 -3
  123. package/dist/integracoes-locais.js +17 -0
  124. package/dist/leases.js +65 -21
  125. package/dist/ledger-stats.js +272 -0
  126. package/dist/ledger.js +109 -2
  127. package/dist/licoes.js +221 -0
  128. package/dist/liveness.js +218 -0
  129. package/dist/maestro-actions.js +51 -0
  130. package/dist/maestro-authority.js +152 -0
  131. package/dist/maestro-cli.js +97 -0
  132. package/dist/maestro-contract.js +55 -0
  133. package/dist/maestro-discovery.js +132 -0
  134. package/dist/maestro-runtime.js +268 -0
  135. package/dist/maestro-snapshot.js +86 -0
  136. package/dist/maestro-sources.js +224 -0
  137. package/dist/manifest.js +165 -6
  138. package/dist/maquina.js +102 -0
  139. package/dist/master-audit.js +101 -0
  140. package/dist/master-batch.js +43 -0
  141. package/dist/master-digest.js +149 -0
  142. package/dist/master-migracao.js +155 -0
  143. package/dist/master.js +361 -77
  144. package/dist/mcp-artifacts.js +234 -0
  145. package/dist/mcp-git.js +433 -0
  146. package/dist/mcp-install.js +310 -0
  147. package/dist/mcp-maestro.js +25 -0
  148. package/dist/mcp-server.js +469 -0
  149. package/dist/mcp-ship.js +436 -0
  150. package/dist/mcp-verify.js +173 -0
  151. package/dist/memoria-humana.js +207 -0
  152. package/dist/memoria.js +314 -78
  153. package/dist/memory-migration.js +279 -0
  154. package/dist/memory-prospective.js +148 -0
  155. package/dist/modos-migracao.js +191 -0
  156. package/dist/modos.js +151 -15
  157. package/dist/monitor-lock.js +110 -0
  158. package/dist/objective.js +449 -0
  159. package/dist/ocupacao.js +267 -0
  160. package/dist/onboarding.js +303 -0
  161. package/dist/orkmind.js +389 -90
  162. package/dist/orquestracao.js +96 -69
  163. package/dist/phase.js +612 -151
  164. package/dist/playbook-capabilities.js +150 -0
  165. package/dist/playbook-contracts.js +188 -0
  166. package/dist/policies.js +72 -0
  167. package/dist/portfolio-context.js +61 -0
  168. package/dist/portfolio.js +180 -0
  169. package/dist/preflight.js +207 -0
  170. package/dist/process-audit.js +112 -0
  171. package/dist/project-state.js +93 -0
  172. package/dist/prompts.js +25 -5
  173. package/dist/prova-minima.js +112 -0
  174. package/dist/pulse-cadencia.js +163 -0
  175. package/dist/pulse-consentimento.js +260 -0
  176. package/dist/pulse-delivery.js +323 -0
  177. package/dist/pulse-resposta.js +542 -0
  178. package/dist/pulse.js +262 -0
  179. package/dist/ratelimit.js +35 -2
  180. package/dist/recall.js +80 -3
  181. package/dist/redacao-saida.js +45 -0
  182. package/dist/redacao-url.js +66 -0
  183. package/dist/retry.js +640 -118
  184. package/dist/roadmap-reservas.js +243 -0
  185. package/dist/runtime-ambiente.js +38 -0
  186. package/dist/runtime-context.js +215 -0
  187. package/dist/runtime-profiles.js +869 -0
  188. package/dist/runtimes.js +103 -0
  189. package/dist/sandbox.js +9 -0
  190. package/dist/session-events.js +203 -0
  191. package/dist/session-watcher-claude.js +637 -0
  192. package/dist/session-watcher.js +700 -0
  193. package/dist/sessoes-adopt.js +154 -0
  194. package/dist/sessoes-inventario.js +159 -0
  195. package/dist/sessoes.js +16 -35
  196. package/dist/setup.js +691 -0
  197. package/dist/ship.js +168 -19
  198. package/dist/slug.js +1 -1
  199. package/dist/thread-close.js +115 -0
  200. package/dist/thread.js +142 -28
  201. package/dist/tokens.js +1 -1
  202. package/dist/util.js +4 -2
  203. package/dist/verify-sandbox.js +265 -0
  204. package/dist/verify.js +270 -25
  205. package/dist/versao.js +60 -0
  206. package/dist/worktree.js +31 -2
  207. package/dist/write-activation.js +291 -0
  208. package/dist/yaml.js +5 -1
  209. package/eval/casos/master-metrics.json +1 -1
  210. package/eval/casos/onboarding.json +102 -0
  211. package/eval/casos/orkastery-bootstrap.json +37 -3
  212. package/eval/casos/scope-check-capability-map.json +45 -7
  213. package/eval/casos/ship-release.json +3 -3
  214. package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
  215. package/eval/fixtures/b2-master-log/caso.json +1 -1
  216. package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
  217. package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
  218. package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
  219. package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
  220. package/eval/fixtures/fx-codex-dry/caso.json +18 -0
  221. package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
  222. package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
  223. package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
  224. package/eval/fixtures/fx-happy/caso.json +6 -4
  225. package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
  226. package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
  227. package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
  228. package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
  229. package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
  230. package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
  231. package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
  232. package/eval/fixtures/fx-omnicanal/caso.json +17 -0
  233. package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
  234. package/monitor/company-brain.cjs +17 -0
  235. package/monitor/pulse-scope.cjs +45 -0
  236. package/monitor/pulse.cron +18 -0
  237. package/monitor/varredura-pulse.sh +27 -0
  238. package/package.json +28 -7
  239. package/references/definition-of-done.md +2 -2
  240. package/schemas/claims.schema.json +25 -0
  241. package/schemas/company-brain.schema.json +1158 -0
  242. package/schemas/creation-operation.schema.json +365 -0
  243. package/schemas/maestro-snapshot.schema.json +2716 -0
  244. package/skills/README.md +3 -3
  245. package/skills/core/onboarding/SKILL.md +50 -0
  246. package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
  247. package/skills/core/thread-state/SKILL.md +3 -1
  248. package/skills/governance/decision-triage/SKILL.md +4 -4
  249. package/skills/governance/narrative-guardian/SKILL.md +1 -1
  250. package/skills/governance/roadmap-keeper/SKILL.md +1 -1
  251. package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
  252. package/skills/observability/thread-tracing/SKILL.md +1 -1
  253. package/skills/phases/check-quality/SKILL.md +2 -2
  254. package/skills/phases/goal-definition/SKILL.md +1 -1
  255. package/skills/phases/master-metrics/SKILL.md +9 -7
  256. package/skills/phases/plan-specification/SKILL.md +1 -1
  257. package/skills/phases/ship-release/SKILL.md +1 -1
@@ -61,9 +61,8 @@ var __importStar = (this && this.__importStar) || (function () {
61
61
  };
62
62
  })();
63
63
  Object.defineProperty(exports, "__esModule", { value: true });
64
- exports.ATENCAO_PADRAO_MIN = void 0;
64
+ exports.duracaoCurta = exports.ATENCAO_PADRAO_MIN = void 0;
65
65
  exports.minutosEntre = minutosEntre;
66
- exports.duracaoCurta = duracaoCurta;
67
66
  exports.montarMonitor = montarMonitor;
68
67
  exports.textoDoMonitor = textoDoMonitor;
69
68
  const adapter = __importStar(require("./adapters/claude-bg"));
@@ -71,36 +70,17 @@ const board_1 = require("./board");
71
70
  const gates_1 = require("./gates");
72
71
  const ledger_1 = require("./ledger");
73
72
  const modos_1 = require("./modos");
73
+ const ocupacao_1 = require("./ocupacao");
74
74
  const ratelimit_1 = require("./ratelimit");
75
+ const hitl_1 = require("./hitl");
75
76
  const thread_1 = require("./thread");
76
77
  const util_1 = require("./util");
78
+ const horario_1 = require("./horario");
79
+ Object.defineProperty(exports, "duracaoCurta", { enumerable: true, get: function () { return horario_1.duracaoCurta; } });
80
+ const conducao_1 = require("./conducao");
81
+ const conducao_texto_1 = require("./conducao-texto");
77
82
  /** Limite de atencao padrao, em minutos: parada mais velha que isso e destacada. */
78
83
  exports.ATENCAO_PADRAO_MIN = 30;
79
- /** Estado que o `ork phase run` grava quando o bloco despachado pausa ao fim. */
80
- const PAUSA_PREVISTA = 'prevista ao fim do bloco';
81
- /**
82
- * Eventos que destravam uma reprovacao de gate.
83
- *
84
- * `phase_dispatch` entra pela porta da frente: o `ork phase run` grava `gate_blocked`
85
- * ANTES de despachar e aborta o despacho, entao um `phase_dispatch` posterior so existe
86
- * se aquele bloqueio deixou de valer.
87
- */
88
- const EVENTOS_QUE_DESTRAVAM = [
89
- ledger_1.TIPOS_DE_EVENTO.gateLiberado,
90
- ledger_1.TIPOS_DE_EVENTO.faseDespachada,
91
- ledger_1.TIPOS_DE_EVENTO.leaseAdquirido,
92
- ledger_1.TIPOS_DE_EVENTO.rateLimitRetomado,
93
- ledger_1.TIPOS_DE_EVENTO.shipConcluido,
94
- ledger_1.TIPOS_DE_EVENTO.masterConcluido,
95
- ];
96
- /** O evento e uma autorizacao humana ja registrada (`ork gate approve`)? */
97
- function ehAprovacaoHumana(e) {
98
- return e.tipo === ledger_1.TIPOS_DE_EVENTO.pausaHumana && e.estado === 'aprovado';
99
- }
100
- /** O evento e a pausa PREVISTA gravada no despacho do ultimo bloco? */
101
- function ehPausaPrevista(e) {
102
- return e.tipo === ledger_1.TIPOS_DE_EVENTO.pausaHumana && e.estado === PAUSA_PREVISTA;
103
- }
104
84
  /** Minutos inteiros entre dois carimbos ISO (nunca negativo). */
105
85
  function minutosEntre(desdeEm, ateEm) {
106
86
  const inicio = Date.parse(desdeEm);
@@ -109,15 +89,6 @@ function minutosEntre(desdeEm, ateEm) {
109
89
  return 0;
110
90
  return Math.max(0, Math.floor((fim - inicio) / 60000));
111
91
  }
112
- /** Duracao curta para a tabela: `12min`, `3h05`, `2d 04h`. */
113
- function duracaoCurta(minutos) {
114
- if (minutos < 60)
115
- return `${minutos}min`;
116
- const horas = Math.floor(minutos / 60);
117
- if (horas < 24)
118
- return `${horas}h${String(minutos % 60).padStart(2, '0')}`;
119
- return `${Math.floor(horas / 24)}d ${String(horas % 24).padStart(2, '0')}h`;
120
- }
121
92
  /** Indice da fase no ciclo REAL da thread (a variante de ciclo pode encurtar o ciclo). */
122
93
  function indiceDaFase(thread, fase) {
123
94
  return typeof fase === 'string' ? thread.fases.indexOf(fase) : -1;
@@ -140,8 +111,8 @@ function blocoDaFase(thread, fase) {
140
111
  }
141
112
  }
142
113
  /** Comando que o humano roda para liberar uma pausa da thread. */
143
- function comandoDeAprovacao(threadId, sobre) {
144
- return `ork gate approve ${threadId} "${sobre || 'pausa'}" --por <quem>`;
114
+ function comandoDeAprovacao(threadId, _sobre) {
115
+ return `ork gate request ${threadId}`;
145
116
  }
146
117
  function parada(dados, quando) {
147
118
  return { ...dados, paradaHaMin: minutosEntre(dados.desdeEm, quando) };
@@ -152,7 +123,7 @@ function parada(dados, quando) {
152
123
  * Tres fontes, na ordem de confianca. A mesma fase nunca vira duas linhas: a primeira
153
124
  * fonte que a reivindica fica com ela, e as demais so acrescentam evidencia.
154
125
  */
155
- function pausasAbertas(thread, eventos, vivas, quando) {
126
+ function pausasAbertas(thread, eventos, estados, quando) {
156
127
  const porFase = new Map();
157
128
  if (thread.status === 'fechada')
158
129
  return [];
@@ -160,12 +131,18 @@ function pausasAbertas(thread, eventos, vivas, quando) {
160
131
  // sessao que a produziu. Aberta enquanto ninguem aprovou e a conducao nao passou
161
132
  // para uma fase POSTERIOR (redespachar a mesma fase nao resolve pausa nenhuma).
162
133
  eventos.forEach((e, i) => {
163
- if (!ehPausaPrevista(e))
134
+ if (!(0, ocupacao_1.ehPausaPrevista)(e))
164
135
  return;
165
136
  const fase = faseDoEvento(thread, e);
137
+ // A previsão antiga não substitui o modo corrente nem cria pausa intermediária.
138
+ if (!fase)
139
+ return;
140
+ const previsto = (0, thread_1.blocoDaThread)(thread, fase);
141
+ if (!previsto.pausa || previsto.fases.at(-1) !== fase)
142
+ return;
166
143
  const iFase = fase ? thread.fases.indexOf(fase) : -1;
167
144
  const resolvida = eventos.slice(i + 1).some((p) => {
168
- if (ehAprovacaoHumana(p))
145
+ if ((0, ocupacao_1.ehAprovacaoHumana)(p))
169
146
  return true;
170
147
  if (p.tipo === ledger_1.TIPOS_DE_EVENTO.masterConcluido)
171
148
  return true;
@@ -174,7 +151,12 @@ function pausasAbertas(thread, eventos, vivas, quando) {
174
151
  if (resolvida)
175
152
  return;
176
153
  const sessionId = typeof e.sessionId === 'string' ? e.sessionId : '';
177
- const sessaoViva = vivas === null ? null : vivas.has(sessionId);
154
+ // "Viva" aqui quer dizer TRABALHANDO, e nao "aparece na lista do runtime". Foi essa
155
+ // confusao que deixou passar o incidente de 05/09/2026: a sessao travada em HITL
156
+ // continua listada, e o monitor a lia como uma sessao que ainda ia terminar. Uma
157
+ // sessao `blocked` e o contrario disso -- ela e a pausa, ja chegada.
158
+ const sessaoEstado = estados === null ? null : estados.get(sessionId) ?? null;
159
+ const sessaoViva = estados === null ? null : sessaoEstado === 'working' || sessaoEstado === '';
178
160
  const sobre = typeof e.previstaSobre === 'string' && e.previstaSobre !== ''
179
161
  ? e.previstaSobre
180
162
  : blocoDaFase(thread, fase).pausaSobre;
@@ -186,12 +168,19 @@ function pausasAbertas(thread, eventos, vivas, quando) {
186
168
  bloco: blocoDaFase(thread, fase).bloco,
187
169
  pausaSobre: sobre,
188
170
  detalhe: sessaoViva === true
189
- ? `a sessao ${sessionId.slice(0, 8)} do bloco ainda esta viva no runtime: a pausa chega quando ela terminar`
190
- : `bloco fechado em ${fase ?? '?'}: espera o veredito humano sobre ${sobre || 'a pausa do bloco'}`,
191
- evidencia: `ledger ${ledger_1.TIPOS_DE_EVENTO.pausaHumana} (${PAUSA_PREVISTA})${sessionId ? `, sessao ${sessionId.slice(0, 8)}` : ''}`,
192
- correcao: comandoDeAprovacao(thread.id, sobre),
171
+ ? `a sessao ${sessionId.slice(0, 8)} do bloco ainda esta trabalhando no runtime: a pausa chega quando ela terminar`
172
+ : sessaoEstado === 'blocked'
173
+ ? `a sessao ${sessionId.slice(0, 8)} do bloco esta BLOQUEADA no runtime esperando acao humana (prompt, permissao ou credencial): veja \`ork sessions hitl\``
174
+ : `bloco fechado em ${fase ?? '?'}: espera o veredito humano sobre ${sobre || 'a pausa do bloco'}`,
175
+ evidencia: `ledger ${ledger_1.TIPOS_DE_EVENTO.pausaHumana} (${ocupacao_1.PAUSA_PREVISTA})` +
176
+ `${sessionId ? `, sessao ${sessionId.slice(0, 8)}` : ''}` +
177
+ `${sessaoEstado ? ` em state=${sessaoEstado}` : ''}`,
178
+ correcao: sessaoEstado === 'blocked'
179
+ ? `ork sessions logs ${sessionId.slice(0, 8)} para ver o que a sessao pede, e claude attach ${sessionId} para responder`
180
+ : comandoDeAprovacao(thread.id, sobre),
193
181
  desdeEm: e.ts,
194
182
  sessaoViva,
183
+ sessaoEstado,
195
184
  fonte: 'ledger',
196
185
  }, quando));
197
186
  });
@@ -203,7 +192,7 @@ function pausasAbertas(thread, eventos, vivas, quando) {
203
192
  return;
204
193
  const resolvido = eventos
205
194
  .slice(i + 1)
206
- .some((p) => EVENTOS_QUE_DESTRAVAM.includes(p.tipo) || ehAprovacaoHumana(p));
195
+ .some((p) => ocupacao_1.EVENTOS_QUE_DESTRAVAM.includes(p.tipo) || (0, ocupacao_1.ehAprovacaoHumana)(p));
207
196
  if (resolvido)
208
197
  return;
209
198
  const fase = faseDoEvento(thread, e);
@@ -232,7 +221,7 @@ function pausasAbertas(thread, eventos, vivas, quando) {
232
221
  // Fonte 3: `status: pausada` carimbado no proprio `thread.json`. E a fonte mais fraca
233
222
  // (nao diz sobre o que) e a mais duravel (sobrevive a ledger truncado), entao ela so
234
223
  // entra quando a fase atual ainda nao virou linha.
235
- if (thread.status === 'pausada' && !porFase.has(thread.faseAtual)) {
224
+ if (thread.status === 'pausada' && (0, ocupacao_1.faseTemPausaPrevista)(thread) && !porFase.has(thread.faseAtual)) {
236
225
  const { bloco, pausaSobre } = blocoDaFase(thread, thread.faseAtual);
237
226
  porFase.set(thread.faseAtual, parada({
238
227
  natureza: 'pausa-humana',
@@ -285,7 +274,7 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
285
274
  bloco: blocoDaFase(thread, p.fase).bloco,
286
275
  pausaSobre: '',
287
276
  detalhe: `pedido ${p.id} na fila de rate limit, libera ${(0, ratelimit_1.faltaPara)(p, quando)} ` +
288
- `(${p.liberaEm.replace('T', ' ').slice(0, 16)}, ${p.janelaEstimada ? 'janela estimada' : 'hora dita pelo runtime'})`,
277
+ `(${p.liberaEm}, ${p.janelaEstimada ? 'janela estimada' : 'hora dita pelo runtime'})`,
289
278
  evidencia: `.orkastery/retry/fila.jsonl (${p.id}, ${p.sinal.fonte})`,
290
279
  correcao: `ork retry resume --id ${p.id}`,
291
280
  desdeEm: p.criadoEm,
@@ -296,7 +285,7 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
296
285
  // 3. Gates tipados reprovados que ninguem destravou. `human.pending` sai daqui porque
297
286
  // ele ja e pausa humana, e `claims.unverifiable` avisa mas nao bloqueia.
298
287
  eventos.forEach((e, i) => {
299
- if (e.tipo !== ledger_1.TIPOS_DE_EVENTO.gateBloqueado)
288
+ if (e.tipo !== ledger_1.TIPOS_DE_EVENTO.gateBloqueado && e.tipo !== 'phase_wait')
300
289
  return;
301
290
  const motivo = e.motivo;
302
291
  if (motivo === 'human.pending' || motivo === 'claims.unverifiable')
@@ -304,11 +293,12 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
304
293
  if (!(motivo in gates_1.DESCRICAO_DO_MOTIVO))
305
294
  return;
306
295
  // Lease e rate limit ja tem fila propria em disco, que e a fonte mais fresca.
307
- if (motivo === 'lease.busy' || motivo === 'runtime.rate-limited')
296
+ if ((motivo === 'lease.busy' || motivo === 'runtime.rate-limited') &&
297
+ saida.some(p => p.motivo === motivo))
308
298
  return;
309
299
  const resolvido = eventos
310
300
  .slice(i + 1)
311
- .some((p) => EVENTOS_QUE_DESTRAVAM.includes(p.tipo) || ehAprovacaoHumana(p));
301
+ .some((p) => ocupacao_1.EVENTOS_QUE_DESTRAVAM.includes(p.tipo) || (0, ocupacao_1.ehAprovacaoHumana)(p));
312
302
  if (resolvido)
313
303
  return;
314
304
  const fase = faseDoEvento(thread, e);
@@ -321,7 +311,7 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
321
311
  detalhe: typeof e.detalhe === 'string' && e.detalhe !== ''
322
312
  ? e.detalhe
323
313
  : gates_1.DESCRICAO_DO_MOTIVO[motivo],
324
- evidencia: `ledger ${ledger_1.TIPOS_DE_EVENTO.gateBloqueado} (gate ${String(e.gate ?? '?')})`,
314
+ evidencia: `ledger ${e.tipo} (gate ${String(e.gate ?? '?')})`,
325
315
  correcao: typeof e.correcao === 'string' && e.correcao !== ''
326
316
  ? e.correcao
327
317
  : `ork retry plan ${thread.id} --motivo ${motivo}`,
@@ -336,7 +326,7 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
336
326
  function situacaoDerivada(item, temPausa) {
337
327
  if (item.thread.status === 'fechada')
338
328
  return 'fechada';
339
- if (item.thread.status === 'pausada' || temPausa)
329
+ if ((item.thread.status === 'pausada' && (0, ocupacao_1.faseTemPausaPrevista)(item.thread)) || temPausa)
340
330
  return 'pausada';
341
331
  if (item.leases.length > 0)
342
332
  return 'em-andamento';
@@ -374,11 +364,18 @@ function montarMonitor(carregado, opcoes = {}) {
374
364
  const itens = (0, board_1.threadsDeTodosOsPerfis)(carregado, todos);
375
365
  // O runtime e a unica fonte que sabe se a sessao do bloco ainda trabalha. Sem ele, a
376
366
  // pausa prevista e reportada como valendo: avisar a mais e a postura correta aqui.
377
- let vivas = null;
367
+ let estados = null;
378
368
  let runtimeDetalhe = 'runtime nao consultado por --sem-runtime';
379
- if (opcoes.semRuntime !== true) {
369
+ if (opcoes.estados !== undefined) {
370
+ estados = opcoes.estados;
371
+ runtimeDetalhe = estados === null ? 'consulta de runtime indisponível' : '';
372
+ }
373
+ else if (opcoes.semRuntime !== true) {
380
374
  if (adapter.disponivel()) {
381
- vivas = new Set(adapter.listarSessoes().map((s) => s.sessionId).filter((s) => !!s));
375
+ estados = new Map(adapter
376
+ .listarSessoes()
377
+ .filter((s) => !!s.sessionId)
378
+ .map((s) => [s.sessionId, (0, hitl_1.estadoBruto)(s)]));
382
379
  runtimeDetalhe = '';
383
380
  }
384
381
  else {
@@ -386,15 +383,31 @@ function montarMonitor(carregado, opcoes = {}) {
386
383
  }
387
384
  }
388
385
  // O escalonador so conhece o perfil do manifesto; os demais caem na situacao derivada.
389
- const vagas = new Map((0, board_1.planejar)(carregado).vagas.map((v) => [v.thread, v]));
386
+ // Os estados de sessao ja consultados vao junto: uma chamada ao runtime, nao duas.
387
+ const vagas = new Map((0, board_1.planejar)(carregado, { agora: quando, estados }).vagas.map((v) => [v.thread, v]));
390
388
  const linhas = [];
391
389
  for (const item of itens) {
392
390
  const { thread } = item;
393
391
  const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(item.raiz, thread.id));
394
- const pausas = pausasAbertas(thread, eventos, vivas, quando);
392
+ const pausas = pausasAbertas(thread, eventos, estados, quando);
395
393
  const impedimentos = impedimentosAbertos(item, eventos, item.raiz, quando);
396
394
  // O limite de paralelismo da maquina tambem trava, e o escalonador ja o calculou.
397
395
  const vaga = item.raiz === carregado.raiz ? vagas.get(thread.id) : undefined;
396
+ if (vaga && vaga.motivo === 'vaga.stale') {
397
+ impedimentos.push(parada({
398
+ natureza: 'impedimento',
399
+ motivo: 'vaga.stale',
400
+ fase: thread.faseAtual,
401
+ bloco: blocoDaFase(thread, thread.faseAtual).bloco,
402
+ pausaSobre: '',
403
+ detalhe: vaga.detalhe,
404
+ evidencia: 'ork board plan (concurrency.stale_after_min)',
405
+ correcao: vaga.correcao,
406
+ desdeEm: thread.atualizadaEm,
407
+ sessaoViva: null,
408
+ fonte: 'escalonador',
409
+ }, quando));
410
+ }
398
411
  if (vaga && vaga.motivo === 'concurrency.limite') {
399
412
  impedimentos.push(parada({
400
413
  natureza: 'impedimento',
@@ -434,6 +447,7 @@ function montarMonitor(carregado, opcoes = {}) {
434
447
  precisaDeHumano,
435
448
  temImpedimento: impedimentos.length > 0,
436
449
  acimaDoLimite: paradaHaMin !== null && paradaHaMin >= atencaoMin,
450
+ conducao: (0, conducao_1.conducaoDaThread)(item.raiz, thread.id),
437
451
  });
438
452
  }
439
453
  // Ordem da tabela: quem espera humano primeiro, depois quem tem impedimento, e dentro
@@ -455,7 +469,7 @@ function montarMonitor(carregado, opcoes = {}) {
455
469
  projeto: carregado.manifesto.project.name,
456
470
  consultadoEm: quando,
457
471
  atencaoMin,
458
- runtimeConsultado: vivas !== null,
472
+ runtimeConsultado: estados !== null,
459
473
  runtimeDetalhe,
460
474
  perfis,
461
475
  linhas: visiveis,
@@ -470,15 +484,19 @@ function montarMonitor(carregado, opcoes = {}) {
470
484
  },
471
485
  };
472
486
  }
473
- /** Uma parada em uma linha, para os blocos de detalhe abaixo da tabela. */
474
- function linhaDaParada(p) {
487
+ /**
488
+ * Uma parada em uma linha, para os blocos de detalhe abaixo da tabela. I-35: o dado guarda
489
+ * ISO (o `--json` e o ledger nao mudam); aqui o horario sai no fuso do dono.
490
+ */
491
+ function linhaDaParada(p, agora) {
492
+ const local = (texto) => (0, horario_1.localizarTexto)(texto, { agora });
475
493
  const L = [];
476
- L.push(` [${p.motivo}] parada ha ${duracaoCurta(p.paradaHaMin)} (desde ${p.desdeEm.replace('T', ' ').slice(0, 16)})`);
494
+ L.push(` [${p.motivo}] parada ha ${(0, horario_1.duracaoRelativa)(p.paradaHaMin)} (desde ${(0, horario_1.formatarHora)(p.desdeEm, { agora })})`);
477
495
  if (p.pausaSobre)
478
496
  L.push(` o humano decide: ${p.pausaSobre}`);
479
- L.push(` detalhe : ${p.detalhe}`);
480
- L.push(` evidencia: ${p.evidencia}`);
481
- L.push(` correcao : ${p.correcao}`);
497
+ L.push(` detalhe : ${local(p.detalhe)}`);
498
+ L.push(` evidencia: ${local(p.evidencia)}`);
499
+ L.push(` correcao : ${local(p.correcao)}`);
482
500
  return L;
483
501
  }
484
502
  /** Texto de `ork orquestracao status`. */
@@ -490,10 +508,19 @@ function textoDoMonitor(m) {
490
508
  `em andamento: ${m.resumo.emAndamento} | podem avancar: ${m.resumo.podemAvancar} | ` +
491
509
  `fechadas: ${m.resumo.fechadas}`);
492
510
  L.push(` limite de atencao: ${m.atencaoMin} min (${m.resumo.acimaDoLimite} parada(s) acima, marcadas com !)`);
511
+ L.push(` ${(0, horario_1.legendaDoFuso)(undefined, m.consultadoEm)}`);
493
512
  if (!m.runtimeConsultado) {
494
513
  L.push(` [warn] ${m.runtimeDetalhe}: pausa prevista e reportada como valendo`);
495
514
  }
496
515
  L.push('');
516
+ // I-36 (T17): conducao em andamento nao e parada; ela aparece antes, com a linha unica.
517
+ const conduzidas = m.linhas.filter((l) => l.conducao);
518
+ if (conduzidas.length > 0) {
519
+ L.push('Conduzidas agora:');
520
+ for (const l of conduzidas)
521
+ L.push(` ${l.thread}: ${(0, conducao_texto_1.linhaDeConducao)(l.conducao, { agora: m.consultadoEm })}`);
522
+ L.push('');
523
+ }
497
524
  if (m.linhas.length === 0) {
498
525
  L.push(' Nenhuma thread parada: ninguem esperando veredito humano nem impedido.');
499
526
  return L.join('\n');
@@ -519,7 +546,7 @@ function textoDoMonitor(m) {
519
546
  l.ultimoEvento ? l.ultimoEvento.tipo : '(sem ledger)',
520
547
  l.paradaHaMin === null
521
548
  ? '-'
522
- : `${duracaoCurta(l.paradaHaMin)}${l.acimaDoLimite ? ' !' : ''}`,
549
+ : `${(0, horario_1.duracaoRelativa)(l.paradaHaMin)}${l.acimaDoLimite ? ' !' : ''}`,
523
550
  ])));
524
551
  const hitl = m.linhas.filter((l) => l.precisaDeHumano);
525
552
  if (hitl.length > 0) {
@@ -528,7 +555,7 @@ function textoDoMonitor(m) {
528
555
  for (const l of hitl) {
529
556
  L.push(` ${l.thread} (${l.tag}, ${l.nome})`);
530
557
  for (const p of l.pausas.filter((x) => x.sessaoViva !== true))
531
- L.push(...linhaDaParada(p));
558
+ L.push(...linhaDaParada(p, m.consultadoEm));
532
559
  }
533
560
  }
534
561
  const impedidas = m.linhas.filter((l) => l.temImpedimento);
@@ -538,7 +565,7 @@ function textoDoMonitor(m) {
538
565
  for (const l of impedidas) {
539
566
  L.push(` ${l.thread} (${l.tag}, ${l.nome})`);
540
567
  for (const p of l.impedimentos)
541
- L.push(...linhaDaParada(p));
568
+ L.push(...linhaDaParada(p, m.consultadoEm));
542
569
  }
543
570
  }
544
571
  const emCurso = m.linhas.filter((l) => l.pausas.some((p) => p.sessaoViva === true));