@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
package/dist/manifest.js CHANGED
@@ -40,14 +40,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.LIMITE_MANIFESTO_BYTES = exports.DIR_ESTADO = exports.NOME_MANIFESTO_LEGADO = exports.NOME_MANIFESTO = void 0;
41
41
  exports.acharRaiz = acharRaiz;
42
42
  exports.dirEstado = dirEstado;
43
+ exports.validarOptInPlaybook = validarOptInPlaybook;
43
44
  exports.carregarManifesto = carregarManifesto;
44
45
  exports.exigirManifesto = exigirManifesto;
45
46
  const fs = __importStar(require("node:fs"));
46
47
  const path = __importStar(require("node:path"));
47
48
  const yaml_1 = require("./yaml");
48
49
  const modos_1 = require("./modos");
50
+ const runtimes_1 = require("./runtimes");
51
+ const codex_1 = require("./adapters/codex");
49
52
  const slug_1 = require("./slug");
50
53
  const util_1 = require("./util");
54
+ const delegation_1 = require("./delegation");
55
+ const horario_1 = require("./horario");
51
56
  exports.NOME_MANIFESTO = 'orkastery.yaml';
52
57
  exports.NOME_MANIFESTO_LEGADO = 'devmaster.yaml';
53
58
  exports.DIR_ESTADO = '.orkastery';
@@ -76,12 +81,70 @@ function texto(v, padrao) {
76
81
  function numero(v, padrao) {
77
82
  return typeof v === 'number' ? v : typeof v === 'string' && v.trim() !== '' && !isNaN(Number(v)) ? Number(v) : padrao;
78
83
  }
84
+ /**
85
+ * I-37 (D2): `verify.timeout_ms` e `verify.timeout_ms_por_comando`. Prazo so vale inteiro
86
+ * positivo em milissegundos, entre 1 s e 24 h; o resto e erro do manifesto, porque um prazo
87
+ * mal escrito que caisse no default em silencio mudaria o veredito sem ninguem saber.
88
+ */
89
+ function prazosDoVerify(verify, erros) {
90
+ const prazo = (chave, v) => {
91
+ if (v === undefined || v === null)
92
+ return undefined;
93
+ const n = typeof v === 'number' ? v : typeof v === 'string' && v.trim() !== '' ? Number(v) : NaN;
94
+ if (!Number.isInteger(n) || n < 1_000 || n > 86_400_000) {
95
+ erros.push(`${chave} precisa ser um inteiro em ms entre 1000 e 86400000 (recebido ${JSON.stringify(v)})`);
96
+ return undefined;
97
+ }
98
+ return n;
99
+ };
100
+ const saida = {};
101
+ const geral = prazo('verify.timeout_ms', verify.timeout_ms);
102
+ if (geral !== undefined)
103
+ saida.timeout_ms = geral;
104
+ const brutos = mapa(verify.timeout_ms_por_comando);
105
+ const porComando = {};
106
+ for (const nome of Object.keys(brutos)) {
107
+ if (!['build', 'test', 'typecheck'].includes(nome)) {
108
+ erros.push(`verify.timeout_ms_por_comando.${nome}: so build, test e typecheck tem prazo proprio`);
109
+ continue;
110
+ }
111
+ const n = prazo(`verify.timeout_ms_por_comando.${nome}`, brutos[nome]);
112
+ if (n !== undefined)
113
+ porComando[nome] = n;
114
+ }
115
+ if (Object.keys(porComando).length > 0)
116
+ saida.timeout_ms_por_comando = porComando;
117
+ return saida;
118
+ }
79
119
  function booleano(v, padrao) {
80
120
  return typeof v === 'boolean' ? v : padrao;
81
121
  }
82
122
  function mapa(v) {
83
123
  return v && typeof v === 'object' && !Array.isArray(v) ? v : {};
84
124
  }
125
+ /** Mesmo contrato na leitura do YAML e nos consumidores de manifesto em memoria. */
126
+ function validarOptInPlaybook(valor) {
127
+ if (valor === undefined)
128
+ return false;
129
+ if (!valor || typeof valor !== 'object' || Array.isArray(valor) ||
130
+ Object.keys(valor).length !== 1 || !Object.hasOwn(valor, 'ativo') ||
131
+ typeof valor.ativo !== 'boolean') {
132
+ throw new Error('playbook deve conter somente ativo booleano explicito');
133
+ }
134
+ return valor.ativo;
135
+ }
136
+ /** I-33 (N2): texto e numero que dizem sim ou nao sem ambiguidade; o resto nao e reconhecido. */
137
+ const BOOLEANOS_RECONHECIVEIS = new Map([
138
+ ['true', true], ['yes', true], ['on', true], ['sim', true], ['1', true],
139
+ ['false', false], ['no', false], ['off', false], ['nao', false], ['n\u00e3o', false], ['0', false],
140
+ ]);
141
+ function booleanoReconhecivel(v) {
142
+ if (typeof v === 'number')
143
+ return v === 1 ? true : v === 0 ? false : null;
144
+ if (typeof v !== 'string')
145
+ return null;
146
+ return BOOLEANOS_RECONHECIVEIS.get(v.trim().toLowerCase()) ?? null;
147
+ }
85
148
  /** Le e valida o manifesto. Nunca lanca: erros e avisos voltam na estrutura. */
86
149
  function carregarManifesto(dirInicial = process.cwd()) {
87
150
  const raiz = acharRaiz(dirInicial);
@@ -103,16 +166,56 @@ function carregarManifesto(dirInicial = process.cwd()) {
103
166
  erros.push(e.message);
104
167
  }
105
168
  const project = mapa(dados.project);
169
+ // I-35: fonte unica do fuso do dono. Valor invalido nao reprova o manifesto: avisa e cai
170
+ // no fuso do sistema, porque um horario com rotulo certo vale mais que um comando parado.
171
+ const fusoDoDono = (0, horario_1.lerFusoDoDono)(mapa(dados.owner).timezone);
172
+ if (fusoDoDono.aviso)
173
+ avisos.push(fusoDoDono.aviso);
106
174
  const board = mapa(dados.board);
107
175
  const runtime = mapa(dados.runtime);
108
176
  const conduction = mapa(dados.conduction);
177
+ if (conduction.delegation !== undefined && !(0, delegation_1.validarDelegacao)(conduction.delegation)) {
178
+ erros.push('conduction.delegation exige thread, escopo premissas, prazo ISO, evidencia e delegado');
179
+ }
109
180
  const worktree = mapa(dados.worktree);
110
181
  const verify = mapa(dados.verify);
182
+ const ci = mapa(dados.ci);
111
183
  const concurrency = mapa(dados.concurrency);
112
184
  const handoff = mapa(dados.handoff);
113
185
  const retry = mapa(dados.retry);
186
+ // I-33 (D14, N2): so booleano liga ou desliga a troca. Texto ou numero reconhecivel (`off`, "false", 0,
187
+ // "no") vale o booleano que diz, com aviso; o resto vale o padrao documentado, tambem com aviso.
188
+ const perfisDeRuntime = mapa(dados.runtime_profiles);
189
+ const chaveDeRotacao = (nome, padrao) => {
190
+ const v = perfisDeRuntime[nome];
191
+ if (v === undefined || v === null)
192
+ return padrao;
193
+ if (typeof v === 'boolean')
194
+ return v;
195
+ const lido = booleanoReconhecivel(v);
196
+ if (lido !== null) {
197
+ avisos.push(`runtime_profiles.${nome} deve ser true ou false; ${JSON.stringify(v)} lido como ${lido}`);
198
+ return lido;
199
+ }
200
+ avisos.push(`runtime_profiles.${nome} deve ser true ou false; vale o padrao ${padrao} (${JSON.stringify(v)} nao reconhecido)`);
201
+ return padrao;
202
+ };
203
+ const liveness = mapa(dados.liveness);
204
+ const silencioMaxMin = numero(liveness.silencio_max_min, 10);
205
+ if (!Number.isFinite(silencioMaxMin) || silencioMaxMin <= 0)
206
+ erros.push('liveness.silencio_max_min deve ser positivo e finito');
114
207
  const memory = mapa(dados.memory);
115
208
  const audit = mapa(dados.audit);
209
+ const fabrica = mapa(dados.fabrica);
210
+ let playbook;
211
+ try {
212
+ const ativo = validarOptInPlaybook(dados.playbook);
213
+ if (dados.playbook !== undefined)
214
+ playbook = { ativo };
215
+ }
216
+ catch (e) {
217
+ erros.push(e.message);
218
+ }
116
219
  const abbrev = texto(project.abbrev, '');
117
220
  const checkAbbrev = (0, slug_1.validarAbbrev)(abbrev);
118
221
  if (!checkAbbrev.ok)
@@ -120,9 +223,26 @@ function carregarManifesto(dirInicial = process.cwd()) {
120
223
  const nomeProjeto = texto(project.name, '');
121
224
  if (!nomeProjeto)
122
225
  erros.push('project.name ausente no manifesto');
123
- const defaultModo = (0, modos_1.parseModo)(texto(conduction.default_mode, 'classic'));
226
+ /**
227
+ * I-43 (D6): o manifesto e a unica peca com motivo para DISTINGUIR modo aposentado
228
+ * de modo inexistente, e por isso a distincao mora so aqui.
229
+ *
230
+ * `parseModo` continua estrito de proposito: ele e o portao de ESCRITA, e afrouxa-lo
231
+ * deixaria `#Look` ser escrito de novo. Mas um `orkastery.yaml` que lista `look` estava
232
+ * CERTO quando foi escrito, e existe assim nos quatro arquivos deste VPS. Tratar isso
233
+ * como erro pintaria `ork doctor` de vermelho nos tres projetos no dia um, com uma
234
+ * mensagem que culpa o usuario por um arquivo que ele nao errou.
235
+ *
236
+ * Entao: modo aposentado vira AVISO e sai da lista de permitidos; so valor
237
+ * genuinamente desconhecido continua ERRO.
238
+ */
239
+ const brutoDefault = texto(conduction.default_mode, 'classic');
240
+ const defaultModo = (0, modos_1.parseModo)(brutoDefault);
124
241
  if (!defaultModo) {
125
- erros.push(`conduction.default_mode invalido: "${texto(conduction.default_mode, '')}"`);
242
+ const substitutos = (0, modos_1.substitutosVivos)().join(' ou ');
243
+ erros.push((0, modos_1.modoAposentado)(brutoDefault.trim().toLowerCase())
244
+ ? `conduction.default_mode aposentado: "${brutoDefault}" (use ${substitutos})`
245
+ : `conduction.default_mode invalido: "${brutoDefault}"`);
126
246
  }
127
247
  const brutosPermitidos = Array.isArray(conduction.allowed_modes)
128
248
  ? conduction.allowed_modes.map((m) => texto(m, ''))
@@ -130,10 +250,15 @@ function carregarManifesto(dirInicial = process.cwd()) {
130
250
  const permitidos = [];
131
251
  for (const b of brutosPermitidos) {
132
252
  const m = (0, modos_1.parseModo)(b);
133
- if (!m)
134
- erros.push(`conduction.allowed_modes contem modo invalido: "${b}"`);
135
- else
253
+ if (m) {
136
254
  permitidos.push(m);
255
+ continue;
256
+ }
257
+ if ((0, modos_1.modoAposentado)(b.trim().toLowerCase())) {
258
+ avisos.push(`conduction.allowed_modes ignora modo aposentado "${b}"; use ${(0, modos_1.substitutosVivos)().join(' ou ')}`);
259
+ continue;
260
+ }
261
+ erros.push(`conduction.allowed_modes contem modo invalido: "${b}"`);
137
262
  }
138
263
  if (permitidos.length === 0)
139
264
  permitidos.push(...modos_1.ORDEM_DOS_MODOS);
@@ -144,6 +269,16 @@ function carregarManifesto(dirInicial = process.cwd()) {
144
269
  if (providerPolicy !== 'subscription-only' && providerPolicy !== 'any') {
145
270
  avisos.push(`runtime.provider_policy desconhecida: "${providerPolicy}"`);
146
271
  }
272
+ // Runtime de despacho: so os homologados passam. Um typo aqui viraria erro apenas na
273
+ // hora do despacho, com a thread ja aberta; reprovar no manifesto e mais barato.
274
+ const adapterDeRuntime = texto(runtime.adapter, runtimes_1.RUNTIME_PADRAO);
275
+ if (!(0, runtimes_1.runtimeConhecido)(adapterDeRuntime)) {
276
+ erros.push(`runtime.adapter desconhecido: "${adapterDeRuntime}" (homologados: ${runtimes_1.ORDEM_DOS_RUNTIMES.join(', ')})`);
277
+ }
278
+ const sandboxDoRuntime = texto(runtime.sandbox, codex_1.SANDBOX_PADRAO);
279
+ if (!codex_1.SANDBOXES_DO_CODEX.includes(sandboxDoRuntime)) {
280
+ erros.push(`runtime.sandbox invalido: "${sandboxDoRuntime}" (aceitos: ${codex_1.SANDBOXES_DO_CODEX.join(', ')})`);
281
+ }
147
282
  // Bloco B6, isolamento por tenant (precedente do incidente memory-orkmind):
148
283
  // `database_url_env` recebe o NOME da variavel de ambiente, nunca a string de conexao.
149
284
  // Uma DSN colada aqui e exatamente o defeito que fez a memoria de um produto escrever
@@ -178,20 +313,24 @@ function carregarManifesto(dirInicial = process.cwd()) {
178
313
  stage: texto(project.stage, 'nascente') ?? 'nascente',
179
314
  repo_root: texto(project.repo_root, raiz),
180
315
  },
316
+ ...(fusoDoDono.origem === 'manifesto' ? { owner: { timezone: fusoDoDono.fuso } } : {}),
181
317
  board: {
182
318
  adapter: texto(board.adapter, 'hermes-kanban'),
183
319
  default: texto(board.default, 'default'),
184
320
  },
185
321
  runtime: {
186
- adapter: texto(runtime.adapter, 'claude-bg'),
322
+ adapter: adapterDeRuntime,
187
323
  model: texto(runtime.model, 'opus'),
188
324
  effort: texto(runtime.effort, 'high'),
189
325
  provider_policy: providerPolicy,
326
+ sandbox: sandboxDoRuntime,
190
327
  },
191
328
  conduction: {
192
329
  default_mode: defaultModo ?? 'classic',
193
330
  allowed_modes: permitidos,
331
+ ...((0, delegation_1.validarDelegacao)(conduction.delegation) ? { delegation: conduction.delegation } : {}),
194
332
  },
333
+ ...(playbook === undefined ? {} : { playbook }),
195
334
  worktree: {
196
335
  base_branch: texto(worktree.base_branch, 'main'),
197
336
  dir: texto(worktree.dir, '.claude/worktrees'),
@@ -200,17 +339,32 @@ function carregarManifesto(dirInicial = process.cwd()) {
200
339
  verify: {
201
340
  build: verify.build === null || verify.build === undefined ? undefined : texto(verify.build, ''),
202
341
  test: verify.test === null || verify.test === undefined ? undefined : texto(verify.test, ''),
342
+ ...prazosDoVerify(verify, erros),
203
343
  typecheck: verify.typecheck === null || verify.typecheck === undefined
204
344
  ? undefined
205
345
  : texto(verify.typecheck, ''),
346
+ // I-54 (RM-037, D10): o preparo unico da rodada de verify, quando declarado.
347
+ ...(typeof verify.preparo === 'string' && verify.preparo.trim() ? { preparo: verify.preparo.trim() } : {}),
348
+ },
349
+ ci: {
350
+ required_for_ship: booleano(ci.required_for_ship, false),
351
+ context: texto(ci.context, 'ork-verify'),
352
+ command: ci.command === null || ci.command === undefined ? undefined : texto(ci.command, ''),
206
353
  },
207
354
  concurrency: {
208
355
  max_parallel_threads: numero(concurrency.max_parallel_threads, 3),
356
+ stale_after_min: Math.max(1, Math.trunc(numero(concurrency.stale_after_min, 240))),
209
357
  },
358
+ liveness: { silencio_max_min: silencioMaxMin },
210
359
  handoff: {
211
360
  rotate_above: numero(handoff.rotate_above, 0.7),
212
361
  force_rotate_above: numero(handoff.force_rotate_above, 0.85),
213
362
  },
363
+ // I-33 (D16): troca por cota ligada por padrao, decisao do dono em 19/09/2026; o operador desliga aqui.
364
+ runtime_profiles: {
365
+ rotate_same_runtime_on_quota: chaveDeRotacao('rotate_same_runtime_on_quota', true),
366
+ rotate_same_runtime_on_auth: chaveDeRotacao('rotate_same_runtime_on_auth', true),
367
+ },
214
368
  // Bloco B3: o limite de escalacao tem padrao, e o padrao e conservador. Manifesto
215
369
  // sem bloco `retry:` continua andando com 3 tentativas e janela estimada de 60 min,
216
370
  // que e exatamente o que o B3 promete, nao um "sem limite" implicito.
@@ -238,6 +392,11 @@ function carregarManifesto(dirInicial = process.cwd()) {
238
392
  since_padrao: texto(audit.since_padrao, '7d'),
239
393
  graphify: texto(audit.graphify, 'auto'),
240
394
  },
395
+ // I-51 (RM-047): publicar o estado da fabrica empurra para o remoto, entao so com opt-in.
396
+ fabrica: {
397
+ compartilhada: booleano(fabrica.compartilhada, false),
398
+ remoto: texto(fabrica.remoto, 'origin'),
399
+ },
241
400
  policies: Object.fromEntries(Object.entries(mapa(dados.policies)).map(([k, v]) => [k, texto(v, '')])),
242
401
  };
243
402
  return { caminho: achado.caminho, raiz, legado: achado.legado, bytes, manifesto, erros, avisos };
@@ -0,0 +1,102 @@
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.CONTRATO_CONFIG_DA_MAQUINA = void 0;
37
+ exports.pastaDoUsuario = pastaDoUsuario;
38
+ exports.lerConfigDaMaquina = lerConfigDaMaquina;
39
+ exports.gravarConfigDaMaquina = gravarConfigDaMaquina;
40
+ exports.nomeDaMaquina = nomeDaMaquina;
41
+ exports.fabricaCompartilhada = fabricaCompartilhada;
42
+ /**
43
+ * I-51 (RM-047): esta maquina na fabrica.
44
+ *
45
+ * O nome e a adesao a fabrica compartilhada sao da MAQUINA, nao do projeto: o repositorio vai a
46
+ * outras pessoas, e o clone de um contribuidor nao pode sair publicando estado no remoto. Por isso
47
+ * os dois moram num arquivo do usuario, `~/.orkastery/maquina.json` (contrato `ork.maquina/v1`),
48
+ * gravado por `ork fabrica entrar`. Arquivo e nao variavel de ambiente porque o cron e os gateways
49
+ * nao carregam o perfil do shell, e a mesma maquina apareceria com dois nomes.
50
+ *
51
+ * Precedencia do nome: `--maquina`, `ORK_MAQUINA`, o arquivo, o hostname.
52
+ * Precedencia da adesao: `ORK_FABRICA_COMPARTILHADA` (1 liga, 0 desliga), senao o manifesto do
53
+ * projeto (`fabrica.compartilhada`, para o time que quer em todas as maquinas) ou o arquivo.
54
+ */
55
+ const fs = __importStar(require("node:fs"));
56
+ const os = __importStar(require("node:os"));
57
+ const path = __importStar(require("node:path"));
58
+ exports.CONTRATO_CONFIG_DA_MAQUINA = 'ork.maquina/v1';
59
+ const ARQUIVO = 'maquina.json';
60
+ /** A pasta do usuario (`~/.orkastery`). `ORK_USUARIO_DIR` isola testes e `ork eval`. */
61
+ function pastaDoUsuario() {
62
+ return (process.env.ORK_USUARIO_DIR ?? '').trim() || path.join(os.homedir(), '.orkastery');
63
+ }
64
+ function lerConfigDaMaquina() {
65
+ try {
66
+ const bruto = JSON.parse(fs.readFileSync(path.join(pastaDoUsuario(), ARQUIVO), 'utf8'));
67
+ if (bruto.contrato !== exports.CONTRATO_CONFIG_DA_MAQUINA)
68
+ return null;
69
+ return { ...bruto, nome: typeof bruto.nome === 'string' && bruto.nome.trim() ? bruto.nome.trim() : null,
70
+ fabricaCompartilhada: bruto.fabricaCompartilhada === true };
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ function gravarConfigDaMaquina(mudanca) {
77
+ const atual = lerConfigDaMaquina();
78
+ const nome = mudanca.nome !== undefined ? (mudanca.nome ?? '').trim() || null : atual?.nome ?? null;
79
+ if (nome !== null && !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(nome)) {
80
+ throw new Error(`fabrica.maquina: nome de maquina invalido ("${nome}"); use letras, numeros, ponto, _ ou -`);
81
+ }
82
+ const config = { contrato: exports.CONTRATO_CONFIG_DA_MAQUINA, nome,
83
+ fabricaCompartilhada: mudanca.fabricaCompartilhada ?? atual?.fabricaCompartilhada ?? false, atualizadoEm: new Date().toISOString() };
84
+ const dir = pastaDoUsuario();
85
+ fs.mkdirSync(dir, { recursive: true });
86
+ const temp = path.join(dir, `.${ARQUIVO}.${process.pid}.tmp`);
87
+ fs.writeFileSync(temp, JSON.stringify(config, null, 2) + '\n', { mode: 0o644 });
88
+ fs.renameSync(temp, path.join(dir, ARQUIVO));
89
+ return config;
90
+ }
91
+ function nomeDaMaquina(explicito) {
92
+ return (explicito ?? '').trim() || (process.env.ORK_MAQUINA ?? '').trim() || lerConfigDaMaquina()?.nome || os.hostname();
93
+ }
94
+ /** Esta maquina publica o estado da fabrica deste projeto? */
95
+ function fabricaCompartilhada(manifesto) {
96
+ const env = (process.env.ORK_FABRICA_COMPARTILHADA ?? '').trim();
97
+ if (env === '1')
98
+ return true;
99
+ if (env === '0')
100
+ return false;
101
+ return manifesto.fabrica?.compartilhada === true || lerConfigDaMaquina()?.fabricaCompartilhada === true;
102
+ }
@@ -0,0 +1,101 @@
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.reciboSemanalValido = reciboSemanalValido;
37
+ exports.auditarMaster = auditarMaster;
38
+ /** Indicadores operacionais: ausência de evidência nunca conta como aprovação. */
39
+ const fs = __importStar(require("node:fs"));
40
+ const node_crypto_1 = require("node:crypto");
41
+ const thread_1 = require("./thread");
42
+ const ledger_1 = require("./ledger");
43
+ const master_1 = require("./master");
44
+ const master_digest_1 = require("./master-digest");
45
+ function reciboSemanalValido(job) {
46
+ if (!job.concluidoEm || (0, master_digest_1.sextaLocal)(job.concluidoEm) !== job.semana || !job.paginas.length ||
47
+ job.recibos.length !== job.paginas.length || new Set(job.recibos.map(r => r.pagina)).size !== job.paginas.length)
48
+ return false;
49
+ return job.paginas.every((p, pagina) => {
50
+ const r = job.recibos.find(r => r.pagina === pagina);
51
+ return !!r && r.sha256 === (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(p)).digest('hex') &&
52
+ r.host.success === true && Number.isInteger(r.host.message_id) && r.host.message_id > 0 &&
53
+ typeof r.host.platform === 'string' && !!r.host.platform.trim() &&
54
+ Number.isFinite(Date.parse(r.confirmadoEm)) && Date.parse(r.confirmadoEm) >= Date.parse(job.criadoEm) &&
55
+ Date.parse(r.confirmadoEm) <= Date.parse(job.concluidoEm);
56
+ });
57
+ }
58
+ function auditarMaster(raiz, quando = new Date().toISOString()) {
59
+ const fim = Date.parse(quando), inicio = fim - 30 * 86400000;
60
+ if (!Number.isFinite(fim))
61
+ throw new Error('data de auditoria inválida');
62
+ const fechadas = [], classes = new Set();
63
+ for (const id of (0, thread_1.listarIds)(raiz)) {
64
+ const t = (0, thread_1.lerThread)(raiz, id);
65
+ if (t.status !== 'fechada')
66
+ continue;
67
+ const data = Date.parse(t.atualizadaEm);
68
+ if (Number.isFinite(data) && (data < inicio || data > fim))
69
+ continue;
70
+ const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, id));
71
+ const admin = t.fechamentoAdmin && !t.score && eventos.some(e => e.tipo === 'thread_closed_admin' &&
72
+ e.motivo === t.fechamentoAdmin.motivo && e.por === t.fechamentoAdmin.por && e.fechadoEm === t.fechamentoAdmin.fechadoEm);
73
+ const log = (0, master_1.masterRatificado)(raiz, id) ? (0, master_1.lerMasterLog)(raiz, id) : null;
74
+ const ok = Number.isFinite(data) && !!(admin || log);
75
+ fechadas.push({ thread: id, ok, tipo: admin ? 'administrativo' : log ? 'ratificado' : 'sem-prova' });
76
+ if (ok && log)
77
+ log.classesDeFalha.forEach(c => classes.add(c));
78
+ }
79
+ let sexta = null, referencia = fim;
80
+ for (let n = 0; n < 7 && !sexta; n++, referencia -= 86400000)
81
+ sexta = (0, master_digest_1.sextaLocal)(new Date(referencia).toISOString());
82
+ const semanas = [21, 14, 7, 0].map(dias => new Date(Date.parse(`${sexta}T12:00:00Z`) - dias * 86400000).toISOString().slice(0, 10));
83
+ const recibos = semanas.map(semana => {
84
+ try {
85
+ const job = (0, master_digest_1.lerDigest)(raiz, semana);
86
+ return { semana, ok: reciboSemanalValido(job) && Date.parse(job.concluidoEm) <= fim, paginas: job.paginas.length };
87
+ }
88
+ catch {
89
+ return { semana, ok: false, paginas: 0 };
90
+ }
91
+ });
92
+ const conformes = fechadas.filter(f => f.ok).length;
93
+ const cobertura = { ok: fechadas.length > 0 && conformes === fechadas.length, total: fechadas.length, conformes,
94
+ percentual: fechadas.length ? 100 * conformes / fechadas.length : null, threads: fechadas };
95
+ const distribuicao = { ok: classes.size >= 3, minimo: 3, classes: [...classes].sort() };
96
+ const digest = { ok: recibos.every(r => r.ok), semanas: recibos,
97
+ arquivosObservados: fs.existsSync((0, master_digest_1.dirDigest)(raiz)) ? fs.readdirSync((0, master_digest_1.dirDigest)(raiz)).filter(f => /^\d{4}-\d{2}-\d{2}\.json$/.test(f)).length : 0 };
98
+ return { contrato: 'ork.master-audit/v1', consultadoEm: quando, janelaDias: 30,
99
+ ok: cobertura.ok && distribuicao.ok && digest.ok, cobertura, distribuicao, digest,
100
+ limite: 'Testes controlados provam o mecanismo; somente estado e recibos operacionais satisfazem estes KPIs.' };
101
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assinaturaProposta = assinaturaProposta;
4
+ exports.listarBatch = listarBatch;
5
+ exports.ratificarBatch = ratificarBatch;
6
+ /**
7
+ * Seleção humana vinculada ao conteúdo exato da proposta apresentada.
8
+ *
9
+ * I-43 (T8): a FILA saiu daqui. O que era `textoDoBatch` ("Fila de score: N esperando
10
+ * o humano") deixou de existir, porque era exatamente o mecanismo que acumulava e não
11
+ * convertia: 13 entradas esperando nota que ninguém dava.
12
+ *
13
+ * O que FICA é outra coisa, e a distinção importa: ratificar uma PROPOSTA explícita de
14
+ * agente (`score_proposto`), com assinatura do conteúdo apresentado, é o caminho que o
15
+ * digest semanal e o HITL usam quando o dono responde. Isso não é fila, é resposta a
16
+ * um pedido específico, e a I-43 não mexe nele.
17
+ */
18
+ const node_crypto_1 = require("node:crypto");
19
+ const master_1 = require("./master");
20
+ function assinaturaProposta(p) {
21
+ return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(p)).digest('hex');
22
+ }
23
+ function listarBatch(raiz, todas = false) {
24
+ return (0, master_1.pendentesDeScore)(raiz, todas).map(p => ({ thread: p.thread.id, nome: p.thread.nome, entregue: p.entregou,
25
+ proposta: p.thread.score_proposto ?? null, assinatura: p.thread.score_proposto ? assinaturaProposta(p.thread.score_proposto) : null }));
26
+ }
27
+ function ratificarBatch(raiz, selecao, por) {
28
+ (0, master_1.exigirAutoriaHumana)(por);
29
+ if (!selecao.length || new Set(selecao.map(s => s.thread)).size !== selecao.length)
30
+ throw new Error('selecione threads distintas explicitamente');
31
+ const disponiveis = listarBatch(raiz);
32
+ const planos = selecao.map(s => {
33
+ const item = disponiveis.find(i => i.thread === s.thread);
34
+ if (!item?.proposta || item.assinatura !== s.assinatura)
35
+ throw new Error(`proposta ausente ou alterada: ${s.thread}; revise o batch`);
36
+ const p = item.proposta;
37
+ const opcoes = { score: p.valor, justificativa: p.justificativa, classes: s.classe ? [s.classe] : p.classes, resumo: p.resumo, por };
38
+ (0, master_1.preflightMaster)(raiz, s.thread, opcoes);
39
+ return { id: s.thread, opcoes };
40
+ });
41
+ // Todo erro de seleção, prova, autoria, score e classe foi verificado antes de gravar.
42
+ return planos.map(p => (0, master_1.registrarMaster)(raiz, p.id, p.opcoes));
43
+ }