@orkastery/cli 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) 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/onboarding.md +21 -0
  7. package/adapters/claude-code/commands/ork.md +99 -27
  8. package/adapters/claude-code/hooks/hooks.json +6 -1
  9. package/adapters/claude-code/hooks/ork-sensor.js +66 -0
  10. package/adapters/codex/skills/ork/SKILL.md +57 -0
  11. package/adapters/hermes/README.md +163 -0
  12. package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
  13. package/adapters/hermes/bin/ork-brain.sh +4 -0
  14. package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
  15. package/adapters/hermes/bin/ork-maestro.sh +6 -0
  16. package/adapters/hermes/bin/ork-master-enviar.py +84 -0
  17. package/adapters/hermes/bin/ork-objective-message.sh +17 -0
  18. package/adapters/hermes/bin/ork-objective-status.sh +12 -0
  19. package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
  20. package/adapters/hermes/hermes.plugin.json +26 -4
  21. package/adapters/hermes/hitl-ingress/__init__.py +356 -0
  22. package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
  23. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
  24. package/adapters/openclaw/README.md +135 -26
  25. package/adapters/openclaw/bin/ork-brain.sh +4 -0
  26. package/adapters/openclaw/construir.sh +19 -0
  27. package/adapters/openclaw/dist/hitl-ingress.js +199 -0
  28. package/adapters/openclaw/dist/index.js +437 -0
  29. package/adapters/openclaw/openclaw.plugin.json +39 -134
  30. package/adapters/openclaw/package.json +26 -0
  31. package/adapters/openclaw/src/hitl-ingress.ts +180 -0
  32. package/adapters/openclaw/src/index.ts +458 -0
  33. package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
  34. package/adapters/openclaw/tsconfig.json +15 -0
  35. package/assets/docs/markdownlint-cli2.jsonc +22 -0
  36. package/assets/docs/padroes/documentacao-de-produto.md +133 -0
  37. package/assets/docs/padroes/roadmap-de-produto.md +98 -0
  38. package/assets/docs/produto/README.md +14 -0
  39. package/assets/docs/produto/_modelo-feature.md +59 -0
  40. package/assets/docs/roadmap/README.md +14 -0
  41. package/assets/docs/roadmap/_modelo-item.md +73 -0
  42. package/assets/orkmind-native-schema.json +32 -0
  43. package/assets/orkmind_bridge.py +357 -0
  44. package/assets/orkmind_fixture.py +67 -0
  45. package/assets/orkmind_prospective.py +138 -0
  46. package/assets/reference-tariffs-i07.json +23 -0
  47. package/dist/adapters/claude-bg.js +488 -39
  48. package/dist/adapters/codex-controller-sensor.js +449 -0
  49. package/dist/adapters/codex-controller-worker.js +361 -0
  50. package/dist/adapters/codex-controller.js +252 -0
  51. package/dist/adapters/codex-events.js +205 -0
  52. package/dist/adapters/codex-question.js +26 -0
  53. package/dist/adapters/codex-runner.js +133 -0
  54. package/dist/adapters/codex.js +394 -0
  55. package/dist/agents-md.js +84 -0
  56. package/dist/auditoria.js +11 -8
  57. package/dist/auditrun.js +5 -4
  58. package/dist/board.js +173 -22
  59. package/dist/branch-de-estado.js +136 -0
  60. package/dist/canarios-hitl.js +177 -0
  61. package/dist/canarios-i43.js +543 -0
  62. package/dist/canarios-pulse.js +147 -0
  63. package/dist/canarios-sensores.js +129 -0
  64. package/dist/canarios.js +111 -2
  65. package/dist/catalogo.js +9 -0
  66. package/dist/ci.js +216 -0
  67. package/dist/ciclos.js +2 -1
  68. package/dist/claim-lint.js +64 -0
  69. package/dist/claims.js +60 -0
  70. package/dist/company-brain-capture.js +195 -0
  71. package/dist/company-brain-cli.js +123 -0
  72. package/dist/company-brain-client.js +61 -0
  73. package/dist/company-brain-contract.js +166 -0
  74. package/dist/company-brain-journal.js +192 -0
  75. package/dist/company-brain-mcp.js +33 -0
  76. package/dist/company-brain-migration.js +60 -0
  77. package/dist/company-brain-source.js +177 -0
  78. package/dist/company-brain-worker.js +18 -0
  79. package/dist/conducao-texto.js +61 -0
  80. package/dist/conducao.js +876 -0
  81. package/dist/contrato-publico.js +39 -0
  82. package/dist/creation-operation-store.js +251 -0
  83. package/dist/creation-operation.js +148 -0
  84. package/dist/decisao-autonoma.js +183 -0
  85. package/dist/delegation.js +79 -0
  86. package/dist/demo.js +120 -0
  87. package/dist/docs.js +828 -0
  88. package/dist/doctor.js +183 -24
  89. package/dist/entrega-pr.js +117 -0
  90. package/dist/escopo-escrita.js +71 -0
  91. package/dist/estado-thread.js +222 -0
  92. package/dist/evalrunner.js +12 -0
  93. package/dist/fabrica-estado.js +329 -0
  94. package/dist/fabrica-publicar.js +76 -0
  95. package/dist/fix.js +21 -0
  96. package/dist/gates.js +55 -9
  97. package/dist/handoff.js +39 -23
  98. package/dist/hitl-canais.js +333 -0
  99. package/dist/hitl-classificacao.js +131 -0
  100. package/dist/hitl-contract.js +465 -0
  101. package/dist/hitl-estado.js +136 -0
  102. package/dist/hitl-gates.js +554 -0
  103. package/dist/hitl-ingress-receipt.js +382 -0
  104. package/dist/hitl-local-atestado.js +57 -0
  105. package/dist/hitl-local-receipt.js +328 -0
  106. package/dist/hitl-local.js +143 -0
  107. package/dist/hitl-lock.js +139 -0
  108. package/dist/hitl-lote.js +223 -0
  109. package/dist/hitl-native-offer.js +97 -0
  110. package/dist/hitl-native.js +65 -0
  111. package/dist/hitl-presentation.js +209 -0
  112. package/dist/hitl-public-receipt.js +176 -0
  113. package/dist/hitl-resumo.js +209 -0
  114. package/dist/hitl-sessions.js +475 -0
  115. package/dist/hitl.js +711 -0
  116. package/dist/horario.js +269 -0
  117. package/dist/hosts.js +198 -22
  118. package/dist/index.js +1736 -93
  119. package/dist/indice.js +99 -0
  120. package/dist/init.js +28 -3
  121. package/dist/integracoes-locais.js +17 -0
  122. package/dist/leases.js +65 -21
  123. package/dist/ledger-stats.js +272 -0
  124. package/dist/ledger.js +107 -2
  125. package/dist/licoes.js +215 -0
  126. package/dist/liveness.js +218 -0
  127. package/dist/maestro-actions.js +51 -0
  128. package/dist/maestro-authority.js +152 -0
  129. package/dist/maestro-cli.js +97 -0
  130. package/dist/maestro-contract.js +55 -0
  131. package/dist/maestro-discovery.js +132 -0
  132. package/dist/maestro-runtime.js +268 -0
  133. package/dist/maestro-snapshot.js +86 -0
  134. package/dist/maestro-sources.js +224 -0
  135. package/dist/manifest.js +165 -6
  136. package/dist/maquina.js +102 -0
  137. package/dist/master-audit.js +101 -0
  138. package/dist/master-batch.js +43 -0
  139. package/dist/master-digest.js +149 -0
  140. package/dist/master-migracao.js +155 -0
  141. package/dist/master.js +361 -77
  142. package/dist/mcp-artifacts.js +234 -0
  143. package/dist/mcp-git.js +433 -0
  144. package/dist/mcp-install.js +310 -0
  145. package/dist/mcp-maestro.js +25 -0
  146. package/dist/mcp-server.js +469 -0
  147. package/dist/mcp-ship.js +436 -0
  148. package/dist/mcp-verify.js +173 -0
  149. package/dist/memoria-humana.js +207 -0
  150. package/dist/memoria.js +314 -78
  151. package/dist/memory-migration.js +279 -0
  152. package/dist/memory-prospective.js +148 -0
  153. package/dist/modos-migracao.js +191 -0
  154. package/dist/modos.js +151 -15
  155. package/dist/monitor-lock.js +110 -0
  156. package/dist/objective.js +449 -0
  157. package/dist/ocupacao.js +267 -0
  158. package/dist/onboarding.js +303 -0
  159. package/dist/orkmind.js +389 -90
  160. package/dist/orquestracao.js +96 -69
  161. package/dist/phase.js +596 -150
  162. package/dist/playbook-capabilities.js +150 -0
  163. package/dist/playbook-contracts.js +188 -0
  164. package/dist/portfolio-context.js +61 -0
  165. package/dist/portfolio.js +180 -0
  166. package/dist/preflight.js +207 -0
  167. package/dist/process-audit.js +112 -0
  168. package/dist/project-state.js +93 -0
  169. package/dist/prompts.js +25 -5
  170. package/dist/prova-minima.js +112 -0
  171. package/dist/pulse-cadencia.js +163 -0
  172. package/dist/pulse-consentimento.js +260 -0
  173. package/dist/pulse-delivery.js +323 -0
  174. package/dist/pulse-resposta.js +542 -0
  175. package/dist/pulse.js +262 -0
  176. package/dist/ratelimit.js +35 -2
  177. package/dist/recall.js +80 -3
  178. package/dist/redacao-saida.js +45 -0
  179. package/dist/redacao-url.js +66 -0
  180. package/dist/retry.js +637 -115
  181. package/dist/roadmap-reservas.js +243 -0
  182. package/dist/runtime-ambiente.js +38 -0
  183. package/dist/runtime-context.js +215 -0
  184. package/dist/runtime-profiles.js +869 -0
  185. package/dist/runtimes.js +103 -0
  186. package/dist/sandbox.js +9 -0
  187. package/dist/session-events.js +203 -0
  188. package/dist/session-watcher-claude.js +637 -0
  189. package/dist/session-watcher.js +683 -0
  190. package/dist/sessoes-adopt.js +154 -0
  191. package/dist/sessoes-inventario.js +159 -0
  192. package/dist/sessoes.js +16 -35
  193. package/dist/setup.js +691 -0
  194. package/dist/ship.js +150 -15
  195. package/dist/slug.js +1 -1
  196. package/dist/thread-close.js +115 -0
  197. package/dist/thread.js +142 -28
  198. package/dist/tokens.js +1 -1
  199. package/dist/util.js +4 -2
  200. package/dist/verify-sandbox.js +265 -0
  201. package/dist/verify.js +270 -25
  202. package/dist/versao.js +60 -0
  203. package/dist/worktree.js +31 -2
  204. package/dist/write-activation.js +291 -0
  205. package/dist/yaml.js +2 -0
  206. package/eval/casos/onboarding.json +102 -0
  207. package/eval/casos/orkastery-bootstrap.json +35 -1
  208. package/eval/casos/scope-check-capability-map.json +45 -7
  209. package/eval/casos/ship-release.json +2 -2
  210. package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
  211. package/eval/fixtures/b2-master-log/caso.json +1 -1
  212. package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
  213. package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
  214. package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
  215. package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
  216. package/eval/fixtures/fx-codex-dry/caso.json +18 -0
  217. package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
  218. package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
  219. package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
  220. package/eval/fixtures/fx-happy/caso.json +6 -4
  221. package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
  222. package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
  223. package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
  224. package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
  225. package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
  226. package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
  227. package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
  228. package/eval/fixtures/fx-omnicanal/caso.json +17 -0
  229. package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
  230. package/monitor/company-brain.cjs +17 -0
  231. package/monitor/pulse-scope.cjs +45 -0
  232. package/monitor/pulse.cron +18 -0
  233. package/monitor/varredura-pulse.sh +27 -0
  234. package/package.json +25 -4
  235. package/schemas/claims.schema.json +25 -0
  236. package/schemas/company-brain.schema.json +1158 -0
  237. package/schemas/creation-operation.schema.json +365 -0
  238. package/schemas/maestro-snapshot.schema.json +2716 -0
  239. package/skills/core/onboarding/SKILL.md +50 -0
  240. package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
  241. package/skills/core/thread-state/SKILL.md +3 -1
  242. package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+ /** Runtime Codex governado pelo controller app-server. Assinatura ChatGPT obrigatória.
3
+ * Helpers exec/rollout permanecem para leitura de histórico; não são fallback de despacho.
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.SANDBOX_PADRAO = exports.SANDBOXES_DO_CODEX = exports.ENVS_REMOVIDAS_DO_DESPACHO = exports.NOME_ADAPTER = void 0;
40
+ exports.ambienteDoDespacho = ambienteDoDespacho;
41
+ exports.disponivel = disponivel;
42
+ exports.versao = versao;
43
+ exports.casaDoCodex = casaDoCodex;
44
+ exports.conferirAuth = conferirAuth;
45
+ exports.consultarRollouts = consultarRollouts;
46
+ exports.sondarSandbox = sondarSandbox;
47
+ exports.montarComando = montarComando;
48
+ exports.extrairThreadId = extrairThreadId;
49
+ exports.acharRollout = acharRollout;
50
+ exports.parseRateLimitCodex = parseRateLimitCodex;
51
+ exports.despachar = despachar;
52
+ exports.logs = logs;
53
+ const codex_controller_1 = require("./codex-controller");
54
+ const runtime_context_1 = require("../runtime-context");
55
+ const fs = __importStar(require("node:fs"));
56
+ const path = __importStar(require("node:path"));
57
+ const util_1 = require("../util");
58
+ const runtime_ambiente_1 = require("../runtime-ambiente");
59
+ const claude_bg_1 = require("./claude-bg");
60
+ const runtime_profiles_1 = require("../runtime-profiles");
61
+ exports.NOME_ADAPTER = 'codex';
62
+ /**
63
+ * Variaveis que REDIRECIONAM o codex para um provider pago por token.
64
+ *
65
+ * O despacho usa a sessao autenticada (`codex login`, plano ChatGPT). Uma OPENAI_API_KEY
66
+ * no ambiente pode virar cobranca por token sem ninguem pedir, o mesmo risco do claude-bg,
67
+ * entao o adapter LIMPA essas variaveis do ambiente do filho em vez de confiar que o CLI
68
+ * vai ignora-las.
69
+ */
70
+ exports.ENVS_REMOVIDAS_DO_DESPACHO = [...runtime_ambiente_1.ENVS_DE_PROVIDER_PAGO, 'CODEX_API_KEY'];
71
+ /**
72
+ * O ambiente do despacho: o do processo, sem as variaveis de provider pago e sem
73
+ * `CODEX_API_KEY`. A lista da higiene de runtime nao cobre a chave especifica do Codex,
74
+ * entao o adapter a remove aqui: a assinatura ChatGPT continua sendo a unica credencial.
75
+ */
76
+ function ambienteDoDespacho(base = process.env, perfil) {
77
+ const env = (0, runtime_ambiente_1.ambienteDeAssinatura)(base);
78
+ for (const nome of exports.ENVS_REMOVIDAS_DO_DESPACHO)
79
+ delete env[nome];
80
+ // I-33 (D2): o `CODEX_HOME` do filho vem do `codexHome` do perfil; sem perfil, o do processo.
81
+ if (perfil && (perfil.runtime !== 'codex' || !perfil.codexHome))
82
+ throw new Error('runtime.profiles.invalid: perfil sem codexHome no despacho codex');
83
+ return (0, runtime_profiles_1.ambienteComPerfil)(env, perfil);
84
+ }
85
+ function exec(cmd, args, cwd, timeoutMs, ambiente = ambienteDoDespacho()) {
86
+ return (0, util_1.exec)(cmd, args, cwd, timeoutMs, ambiente);
87
+ }
88
+ /** Modos de sandbox aceitos pelo `codex exec --sandbox`. */
89
+ exports.SANDBOXES_DO_CODEX = ['read-only', 'workspace-write', 'danger-full-access'];
90
+ /** Sandbox padrao do despacho: escreve no workspace, sem rede para o agente. */
91
+ exports.SANDBOX_PADRAO = 'workspace-write';
92
+ /** O runtime esta disponivel nesta maquina? */
93
+ function disponivel() {
94
+ return (0, util_1.noPath)('codex');
95
+ }
96
+ /** Versao do runtime, para o `ork doctor`. */
97
+ function versao() {
98
+ const r = exec('codex', ['--version'], undefined, 30000);
99
+ return r.ok ? r.stdout.trim() : null;
100
+ }
101
+ /**
102
+ * Raiz do estado do Codex: o `codexHome` do perfil da sessao (I-33, D4) ou, sem perfil, o
103
+ * `CODEX_HOME` do processo com fallback `~/.codex`.
104
+ */
105
+ function casaDoCodex(perfil) {
106
+ return (0, runtime_profiles_1.diretorioEfetivo)('codex', perfil);
107
+ }
108
+ /**
109
+ * I-33 (D7, D13): `codex login status` com o env do perfil. Aprova so o login da ASSINATURA
110
+ * ("Logged in using ChatGPT"); login por API key sai 0 mas cobra por token: `pago`, nunca despacha,
111
+ * e o trecho mascarado da chave nao vai ao detalhe. O `ork` nunca abre nada dentro do
112
+ * `CODEX_HOME`: quem responde e o CLI.
113
+ */
114
+ function conferirAuth(perfil) {
115
+ let ambiente;
116
+ try {
117
+ ambiente = ambienteDoDespacho(process.env, perfil);
118
+ }
119
+ catch (e) {
120
+ return { ok: false, detalhe: e.message };
121
+ }
122
+ const r = exec('codex', ['login', 'status'], undefined, 30000, ambiente);
123
+ // A14: sem codigo de saida (timeout, sinal ou binario ausente), a conferencia e inconclusiva.
124
+ if (r.code === -1)
125
+ return { ok: false, transitorio: true, detalhe: 'codex login status sem resposta (timeout, sinal ou binario ausente)' };
126
+ const linha = (r.stdout + '\n' + r.stderr).split('\n').map(l => l.trim()).find(l => l !== '') ?? '';
127
+ const trecho = linha.replace(/\p{Cc}/gu, '').slice(0, 120);
128
+ if (!r.ok)
129
+ return { ok: false, detalhe: `codex login status saiu ${r.code}${trecho ? `: ${trecho}` : ''}` };
130
+ if (/logged in using chatgpt/i.test(trecho))
131
+ return { ok: true, detalhe: 'codex login status: Logged in using ChatGPT' };
132
+ return { ok: false, pago: true, detalhe: /api key/i.test(trecho) ? 'codex login status: login por API key (provider pago)'
133
+ : 'codex login status: login sem assinatura ChatGPT comprovada (tratado como provider pago)' };
134
+ }
135
+ /** Somente metadados do cabeçalho e eventos terminais; prompts nunca saem do leitor. */
136
+ function consultarRollouts(todas = false, casa = casaDoCodex()) {
137
+ const fontes = [path.join(casa, 'sessions'), ...(todas ? [path.join(casa, 'archived_sessions')] : [])];
138
+ const resultadosFontes = [];
139
+ const sessoes = [];
140
+ const ids = new Set();
141
+ for (const dirFonte of fontes) {
142
+ const fonte = { origem: dirFonte, ok: true, detalhe: '' };
143
+ resultadosFontes.push(fonte);
144
+ const falhar = (origem, detalhe) => {
145
+ fonte.ok = false;
146
+ fonte.detalhe = 'inventário parcial; fonte contém erro de diretório, leitura ou metadados';
147
+ if (origem === dirFonte)
148
+ fonte.detalhe = detalhe;
149
+ else
150
+ resultadosFontes.push({ origem, ok: false, detalhe });
151
+ };
152
+ const visitar = (dir) => {
153
+ let entradas;
154
+ try {
155
+ if (!fs.lstatSync(dir).isDirectory())
156
+ throw new Error('diretório inválido');
157
+ entradas = fs.readdirSync(dir, { withFileTypes: true });
158
+ }
159
+ catch {
160
+ falhar(dir, 'diretório inacessível ou inválido');
161
+ return;
162
+ }
163
+ for (const entrada of entradas) {
164
+ const arquivo = path.join(dir, entrada.name);
165
+ if (entrada.isSymbolicLink()) {
166
+ falhar(arquivo, 'link inesperado');
167
+ continue;
168
+ }
169
+ if (entrada.isDirectory()) {
170
+ visitar(arquivo);
171
+ continue;
172
+ }
173
+ if (!entrada.isFile() || !entrada.name.endsWith('.jsonl'))
174
+ continue;
175
+ try {
176
+ const fd = fs.openSync(arquivo, 'r');
177
+ let primeira, cauda;
178
+ try {
179
+ const tamanho = fs.fstatSync(fd).size;
180
+ const cab = Buffer.alloc(Math.min(tamanho, 65536));
181
+ fs.readSync(fd, cab, 0, cab.length, 0);
182
+ primeira = cab.toString('utf8').split('\n')[0];
183
+ const fim = Buffer.alloc(Math.min(tamanho, 131072));
184
+ fs.readSync(fd, fim, 0, fim.length, tamanho - fim.length);
185
+ cauda = fim.toString('utf8');
186
+ }
187
+ finally {
188
+ fs.closeSync(fd);
189
+ }
190
+ const meta = JSON.parse(primeira);
191
+ const p = meta.payload;
192
+ if (meta.type !== 'session_meta' || !p || typeof p.id !== 'string' ||
193
+ !/^[a-f0-9-]{8,}$/i.test(p.id) || typeof p.cwd !== 'string' || !path.isAbsolute(p.cwd) ||
194
+ ids.has(p.id))
195
+ throw new Error('metadados inválidos ou duplicados');
196
+ ids.add(p.id);
197
+ // Ausência de evento terminal é desconhecimento, não prova de processo vivo.
198
+ let state = 'unknown';
199
+ for (const linha of cauda.split('\n')) {
200
+ try {
201
+ const e = JSON.parse(linha);
202
+ if (e.type === 'event_msg' && e.payload?.type === 'task_started')
203
+ state = 'unknown';
204
+ if (e.type === 'event_msg' && ['task_complete', 'task_aborted'].includes(e.payload?.type))
205
+ state = 'completed';
206
+ }
207
+ catch { /* primeira/última linha do recorte pode estar parcial */ }
208
+ }
209
+ if (todas || state !== 'completed')
210
+ sessoes.push({ sessionId: p.id, cwd: p.cwd, state, kind: 'codex-rollout' });
211
+ }
212
+ catch {
213
+ falhar(arquivo, 'leitura ou metadados inválidos ou duplicados');
214
+ }
215
+ }
216
+ };
217
+ // O runtime é opcional: somente ENOENT antes da consulta prova fonte ausente.
218
+ // Erros durante a visita (inclusive desaparecimento) continuam invalidando a fonte.
219
+ try {
220
+ fs.lstatSync(dirFonte);
221
+ }
222
+ catch (e) {
223
+ if (e.code === 'ENOENT') {
224
+ fonte.detalhe = 'diretório opcional ausente';
225
+ continue;
226
+ }
227
+ falhar(dirFonte, 'diretório inacessível ou inválido');
228
+ continue;
229
+ }
230
+ visitar(dirFonte);
231
+ }
232
+ const ok = resultadosFontes.every(f => f.ok);
233
+ return { ok, sessoes, fontes, resultadosFontes,
234
+ detalhe: ok ? '' : 'inventário Codex incompleto: consulte as fontes com erro' };
235
+ }
236
+ /**
237
+ * A sonda deterministica do sandbox: roda `true` dentro do sandbox do Codex, SEM LLM.
238
+ *
239
+ * Numa maquina sa ela sai 0. Onde o bubblewrap nao consegue criar user namespace
240
+ * (Ubuntu com `apparmor_restrict_unprivileged_userns=1` e sem o pacote bubblewrap do
241
+ * sistema), ela sai != 0 com o erro real do bwrap, e o despacho sandboxado viraria
242
+ * narrativa sem execucao. E por isso que ela e check de `ork doctor`, nao detalhe.
243
+ */
244
+ function sondarSandbox() {
245
+ const r = exec('codex', ['sandbox', 'true'], undefined, 30000);
246
+ const saida = (r.stdout + ' ' + r.stderr).trim();
247
+ return {
248
+ ok: r.ok,
249
+ detalhe: r.ok ? 'codex sandbox true saiu 0' : saida.slice(0, 200) || `exit ${r.code}`,
250
+ };
251
+ }
252
+ /** Monta a linha de comando exata do despacho (usada tambem pelo `--dry-run`). */
253
+ function montarComando(pedido) {
254
+ const args = [
255
+ 'exec',
256
+ '--sandbox',
257
+ pedido.sandbox ?? exports.SANDBOX_PADRAO,
258
+ // Headless de verdade: sem TTY nao ha quem aprove, entao pedir aprovacao e travar.
259
+ '-c',
260
+ 'approval_policy=never',
261
+ '--skip-git-repo-check',
262
+ '-C',
263
+ pedido.cwd,
264
+ '--json',
265
+ ];
266
+ if (pedido.model)
267
+ args.push('-m', pedido.model);
268
+ if (pedido.effort)
269
+ args.push('-c', `model_reasoning_effort=${JSON.stringify(pedido.effort)}`);
270
+ args.push(pedido.prompt);
271
+ return ['codex', ...args];
272
+ }
273
+ /** Extrai o `thread_id` do evento `thread.started` do stream JSONL. */
274
+ function extrairThreadId(saida) {
275
+ for (const linha of saida.split('\n')) {
276
+ if (!linha.includes('thread.started'))
277
+ continue;
278
+ try {
279
+ const evento = JSON.parse(linha);
280
+ if (evento.type === 'thread.started' && typeof evento.thread_id === 'string') {
281
+ return evento.thread_id;
282
+ }
283
+ }
284
+ catch {
285
+ /* linha parcial ainda sendo escrita nao invalida a espera */
286
+ }
287
+ }
288
+ return null;
289
+ }
290
+ /**
291
+ * Procura o rollout da sessao no estado do proprio Codex.
292
+ *
293
+ * O Codex grava `sessions/AAAA/MM/DD/rollout-<ts>-<thread_id>.jsonl` (medido na 0.153.4).
294
+ * So os dias mais recentes sao varridos: um despacho de agora nao mora num rollout de
295
+ * semanas atras, e varrer o historico inteiro pune quem usa o runtime ha meses.
296
+ */
297
+ function acharRollout(threadId, dias = 3, casa = casaDoCodex()) {
298
+ const raiz = path.join(casa, 'sessions');
299
+ if (!fs.existsSync(raiz))
300
+ return null;
301
+ const diasRecentes = [];
302
+ const anos = fs.readdirSync(raiz).sort().reverse();
303
+ for (const ano of anos) {
304
+ const dirAno = path.join(raiz, ano);
305
+ if (!fs.statSync(dirAno).isDirectory())
306
+ continue;
307
+ for (const mes of fs.readdirSync(dirAno).sort().reverse()) {
308
+ const dirMes = path.join(dirAno, mes);
309
+ if (!fs.statSync(dirMes).isDirectory())
310
+ continue;
311
+ for (const dia of fs.readdirSync(dirMes).sort().reverse()) {
312
+ diasRecentes.push(path.join(dirMes, dia));
313
+ if (diasRecentes.length >= dias)
314
+ break;
315
+ }
316
+ if (diasRecentes.length >= dias)
317
+ break;
318
+ }
319
+ if (diasRecentes.length >= dias)
320
+ break;
321
+ }
322
+ for (const dir of diasRecentes) {
323
+ if (!fs.statSync(dir).isDirectory())
324
+ continue;
325
+ const achado = fs.readdirSync(dir).find((f) => f.startsWith('rollout-') && f.endsWith(`-${threadId}.jsonl`));
326
+ if (achado)
327
+ return path.join(dir, achado);
328
+ }
329
+ return null;
330
+ }
331
+ /**
332
+ * Rate limit na saida real do Codex.
333
+ *
334
+ * Reusa o reconhecimento do claude-bg (frases genericas + horario de reset) e acrescenta
335
+ * as frases proprias do plano ChatGPT. Frase reconhecida sem horario volta `sem-horario`:
336
+ * a janela padrao e decisao da fila do B3, nunca chute do adapter.
337
+ */
338
+ const FRASES_DO_CODEX = [
339
+ /hit your usage limit/i,
340
+ /usage limit(?:s)? (?:reached|exceeded)/i,
341
+ /plan limit/i,
342
+ ];
343
+ function parseRateLimitCodex(saida, agoraMs = Date.now()) {
344
+ const generico = (0, claude_bg_1.parseRateLimit)(saida, agoraMs);
345
+ if (generico)
346
+ return generico;
347
+ const frase = FRASES_DO_CODEX.find((r) => r.test(saida ?? ''));
348
+ if (!frase)
349
+ return null;
350
+ const linha = (saida ?? '').split('\n').find((l) => frase.test(l)) ?? saida;
351
+ return { resetEm: null, fonte: 'sem-horario', trecho: linha.trim().slice(0, 200) };
352
+ }
353
+ /** Despacho governado exige vínculo: nenhum fallback implícito para codex exec. */
354
+ function despachar(pedido) {
355
+ if (!pedido.vinculo)
356
+ return { ok: false, comando: [], sessionId: null, verificada: false, stdout: '', stderr: '',
357
+ erro: 'runtime.unavailable: despacho Codex exige vínculo de thread/fase/prompt; transporte legado recusado' };
358
+ if (pedido.contextoRuntime) {
359
+ try {
360
+ if (pedido.contextoRuntime.host !== 'codex')
361
+ throw Error('runtime.context.invalid: host Codex esperado');
362
+ if (pedido.contextoRuntime.threadId !== pedido.vinculo.thread)
363
+ throw Error('runtime.context.scope: thread do contexto difere do despacho');
364
+ (0, runtime_context_1.validarContextoRuntime)(pedido.contextoRuntime, pedido.cwd);
365
+ }
366
+ catch (e) {
367
+ return { ok: false, comando: [], sessionId: null, verificada: false, stdout: '', stderr: '', erro: e.message };
368
+ }
369
+ }
370
+ let ambiente;
371
+ try {
372
+ ambiente = { ...ambienteDoDespacho(process.env, pedido.perfil), ...(pedido.ambienteExtra ?? {}) };
373
+ }
374
+ catch (e) {
375
+ return { ok: false, comando: [], sessionId: null, verificada: false, stdout: '', stderr: '', erro: e.message };
376
+ }
377
+ const r = (0, codex_controller_1.despacharComController)(pedido, ambiente);
378
+ if (r.ok)
379
+ return r;
380
+ // I-33 (D1): o incidente de 18/09 ("Your workspace is out of credits", usage_limit_exceeded)
381
+ // deixa de ser `runtime.unavailable` generico quando a frase aparece na falha do despacho.
382
+ const falhaDeConta = (0, claude_bg_1.parseFalhaDeConta)([r.erro ?? '', r.stderr].join('\n'));
383
+ return falhaDeConta ? { ...r, falhaDeConta, erro: `${falhaDeConta.motivo}: ${falhaDeConta.trecho}` } : r;
384
+ }
385
+ /** Le os eventos ja escritos no log de um despacho (texto cru do stream `--json`). */
386
+ function logs(logPath, linhas = 60) {
387
+ if (!fs.existsSync(logPath))
388
+ return { ok: false, texto: `log nao encontrado: ${logPath}` };
389
+ const uteis = fs
390
+ .readFileSync(logPath, 'utf8')
391
+ .split('\n')
392
+ .filter((l) => l.trim() !== '');
393
+ return { ok: true, texto: uteis.slice(-linhas).join('\n') };
394
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FIM_AGENTS_ORK = exports.INICIO_AGENTS_ORK = void 0;
37
+ exports.blocoAgentsMd = blocoAgentsMd;
38
+ exports.atualizarAgentsMd = atualizarAgentsMd;
39
+ /** Bloco de instrucoes do Orkastery em AGENTS.md, preservando todo texto humano. */
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const util_1 = require("./util");
43
+ exports.INICIO_AGENTS_ORK = '<!-- orkastery:begin -->';
44
+ exports.FIM_AGENTS_ORK = '<!-- orkastery:end -->';
45
+ function seguro(valor) {
46
+ return valor.replace(/[\r\n\0`]+/g, ' ').trim();
47
+ }
48
+ function blocoAgentsMd(manifesto) {
49
+ const comandos = Object.entries(manifesto.verify)
50
+ .filter((item) => typeof item[1] === 'string' && item[1].trim() !== '')
51
+ .map(([nome, comando]) => `- ${seguro(nome)}: \`${seguro(comando)}\``);
52
+ return `${exports.INICIO_AGENTS_ORK}
53
+ ## Orkastery
54
+
55
+ Projeto: **${seguro(manifesto.project.name)}** (${seguro(manifesto.project.abbrev)}). Branch base: \`${seguro(manifesto.worktree.base_branch)}\`.
56
+
57
+ - Comece com \`ork doctor\`, \`ork onboarding\` e \`ork thread status <thread>\`.
58
+ - Conduza o ciclo GOAL → PLAN → GO → CHECK → SHIP → MASTER pelo \`ork\`.
59
+ - Respeite o modo da thread: ${manifesto.conduction.allowed_modes.map(m => `#${m[0].toUpperCase()}${m.slice(1)}`).join(', ')}.
60
+ - Edite produto somente na worktree vinculada; estado em \`.orkastery/\` pertence ao núcleo.
61
+ - PLAN não implementa. GO usa commits atômicos. CHECK não corrige. SHIP acontece por \`ork ship\`.
62
+ - Toda alegação exige claim e comando reproduzível; self-report não é evidência.
63
+ ${comandos.length ? `\nVerificações do manifesto:\n\n${comandos.join('\n')}\n` : ''}
64
+ Este bloco é mantido por \`ork init\`. Edite livremente o restante do arquivo.
65
+ ${exports.FIM_AGENTS_ORK}`;
66
+ }
67
+ /** Cria ou substitui somente o bloco delimitado. Marcadores ambiguos recusam sem escrita. */
68
+ function atualizarAgentsMd(raiz, manifesto) {
69
+ const caminho = path.join(raiz, 'AGENTS.md');
70
+ const anterior = fs.existsSync(caminho) ? fs.readFileSync(caminho, 'utf8') : '';
71
+ const inicios = anterior.split(exports.INICIO_AGENTS_ORK).length - 1;
72
+ const fins = anterior.split(exports.FIM_AGENTS_ORK).length - 1;
73
+ if (inicios !== fins || inicios > 1 || (inicios === 1 && anterior.indexOf(exports.INICIO_AGENTS_ORK) > anterior.indexOf(exports.FIM_AGENTS_ORK))) {
74
+ throw new Error('AGENTS.md possui marcadores Orkastery ambiguos; corrija o bloco antes de rodar ork init');
75
+ }
76
+ const bloco = blocoAgentsMd(manifesto);
77
+ const proximo = inicios === 1
78
+ ? anterior.slice(0, anterior.indexOf(exports.INICIO_AGENTS_ORK)) + bloco + anterior.slice(anterior.indexOf(exports.FIM_AGENTS_ORK) + exports.FIM_AGENTS_ORK.length)
79
+ : anterior === '' ? bloco + '\n' : anterior + (anterior.endsWith('\n') ? '\n' : '\n\n') + bloco + '\n';
80
+ if (proximo === anterior)
81
+ return { caminho, estado: 'inalterado' };
82
+ (0, util_1.gravar)(caminho, proximo);
83
+ return { caminho, estado: anterior === '' ? 'criado' : 'atualizado' };
84
+ }
package/dist/auditoria.js CHANGED
@@ -77,6 +77,7 @@ const path = __importStar(require("node:path"));
77
77
  const gates_1 = require("./gates");
78
78
  const prompts_1 = require("./prompts");
79
79
  const util_1 = require("./util");
80
+ const horario_1 = require("./horario");
80
81
  // ---------------------------------------------------------------------------
81
82
  // Motivos tipados da auditoria
82
83
  // ---------------------------------------------------------------------------
@@ -409,7 +410,7 @@ exports.PACKS = {
409
410
  id: 'process',
410
411
  titulo: 'Processo (meta-auditor)',
411
412
  objetivo: 'O unico pack que audita o METODO e nao o produto: le o ledger, os POSTMORTEMs e os MASTER logs e propoe mudanca no proprio Orkastery.',
412
- estagioMinimo: 'maduro',
413
+ estagioMinimo: 'nascente',
413
414
  fonte: 'ledger',
414
415
  referencias: ['references/definition-of-done.md'],
415
416
  evidencias: [
@@ -425,7 +426,7 @@ exports.PACKS = {
425
426
  {
426
427
  id: 'PR2',
427
428
  regra: 'Thread entregue sem score humano registrado, parada na fila de batch.',
428
- evidencia: 'o thread.json com score null e o ship_done correspondente',
429
+ evidencia: 'thread entregue sem master_done.por humano correspondente ao score',
429
430
  },
430
431
  {
431
432
  id: 'PR3',
@@ -545,9 +546,11 @@ function minutosDoHorario(bruto) {
545
546
  * governando o custo daquela rodada.
546
547
  */
547
548
  function janelaDeCusto(manifesto, quando = new Date()) {
548
- const hh = String(quando.getHours()).padStart(2, '0');
549
- const mm = String(quando.getMinutes()).padStart(2, '0');
550
- const agora = `${hh}:${mm}`;
549
+ // I-35: a janela e o "agora" sao do fuso do dono; sem owner.timezone, o do sistema (como antes).
550
+ const fuso = (0, horario_1.lerFusoDoDono)(manifesto.owner?.timezone).fuso;
551
+ const local = (0, horario_1.partesLocais)(quando, fuso);
552
+ const agora = `${local.hora}:${local.minuto}`;
553
+ const rotulo = (0, horario_1.rotuloDoFuso)(fuso, quando);
551
554
  const bruta = (manifesto.audit?.janela_ociosa ?? '').trim();
552
555
  if (bruta === '') {
553
556
  return {
@@ -572,7 +575,7 @@ function janelaDeCusto(manifesto, quando = new Date()) {
572
575
  detalhe: `audit.janela_ociosa invalida ("${bruta}"): esperado HH:MM-HH:MM`,
573
576
  };
574
577
  }
575
- const minutosAgora = quando.getHours() * 60 + quando.getMinutes();
578
+ const minutosAgora = Number(local.hora) * 60 + Number(local.minuto);
576
579
  const dentro = inicio <= fim
577
580
  ? minutosAgora >= inicio && minutosAgora < fim
578
581
  : minutosAgora >= inicio || minutosAgora < fim;
@@ -583,8 +586,8 @@ function janelaDeCusto(manifesto, quando = new Date()) {
583
586
  dentro,
584
587
  agora,
585
588
  detalhe: dentro
586
- ? `${agora} esta dentro da janela ociosa ${bruta}`
587
- : `${agora} esta FORA da janela ociosa ${bruta}`,
589
+ ? `${agora} (${rotulo}) esta dentro da janela ociosa ${bruta}`
590
+ : `${agora} (${rotulo}) esta FORA da janela ociosa ${bruta}`,
588
591
  };
589
592
  }
590
593
  /** O Graphify existe nesta maquina? Fonte externa, nunca suposicao. */
package/dist/auditrun.js CHANGED
@@ -84,6 +84,7 @@ const superficie_1 = require("./superficie");
84
84
  const thread_1 = require("./thread");
85
85
  const util_1 = require("./util");
86
86
  const verify_1 = require("./verify");
87
+ const horario_1 = require("./horario");
87
88
  /** Versao do formato de `run.json`. */
88
89
  exports.VERSAO_DA_RODADA = 1;
89
90
  /** Diretorio das rodadas de auditoria do projeto. */
@@ -708,7 +709,7 @@ function relatorioDaRodada(carregado, rodadaId, opcoes = {}) {
708
709
  else {
709
710
  const v = rodada.veredito;
710
711
  L.push(`- HEAD real: ${v.commit}`);
711
- L.push(`- verificado em: ${v.verificadoEm}`);
712
+ L.push(`- verificado em: ${(0, horario_1.formatarDataHoraRotulada)(v.verificadoEm)}`);
712
713
  L.push(`- veredito: ${v.ok ? 'ACHADOS SUSTENTADOS' : 'REPROVADO'}`);
713
714
  L.push(`- motivos tipados: ${v.motivos.length > 0 ? v.motivos.join(', ') : '(nenhum)'}`);
714
715
  L.push('');
@@ -831,10 +832,10 @@ function tabelaDoLedgerDaRodada(raiz, id) {
831
832
  if (e.thread && e.thread !== id)
832
833
  detalhe.push(`thread ${String(e.thread)}`);
833
834
  if (e.detalhe)
834
- detalhe.push(String(e.detalhe).slice(0, 90));
835
- return [e.ts.replace('T', ' ').slice(0, 19), e.tipo, detalhe.join(' | ')];
835
+ detalhe.push((0, horario_1.localizarTexto)(String(e.detalhe)).slice(0, 90));
836
+ return [(0, horario_1.formatarDataHora)(e.ts, { segundos: true }), e.tipo, detalhe.join(' | ')];
836
837
  });
837
- return (0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas);
838
+ return `${(0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas)}\n${(0, horario_1.legendaDoFuso)()}`;
838
839
  }
839
840
  /** Quantos achados abertos existem por pack, para o resumo do CLI. */
840
841
  function resumoDoBoard(raiz) {