@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
@@ -0,0 +1,152 @@
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.requireSessionReviewRuntime = requireSessionReviewRuntime;
37
+ exports.parseSessionReviewBinding = parseSessionReviewBinding;
38
+ exports.verifySessionReview = verifySessionReview;
39
+ exports.verifyCompletedSessionReview = verifyCompletedSessionReview;
40
+ /** Independência vem do despacho persistido, nunca do nome do runtime ou do relato. */
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ const node_crypto_1 = require("node:crypto");
44
+ const zod_1 = require("zod");
45
+ const thread_1 = require("./thread");
46
+ const ledger_1 = require("./ledger");
47
+ /** Stop do Claude prova fim de turno, não um resultado CHECK autenticado. */
48
+ function requireSessionReviewRuntime(runtime) {
49
+ if (runtime !== 'codex')
50
+ throw Error('maestro.authority.runtime-unsupported: independence=sessions exige revisor codex; ' +
51
+ `runtime ${runtime} ainda não fornece recibo autenticado de conclusão CHECK`);
52
+ }
53
+ const referenceSchema = zod_1.z.object({
54
+ threadId: zod_1.z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/),
55
+ sessionId: zod_1.z.string().min(1).max(160).regex(/^[a-zA-Z0-9._-]+$/),
56
+ worktree: zod_1.z.string().min(1).max(4096).refine(path.isAbsolute),
57
+ }).strict();
58
+ function parseSessionReviewBinding(input) {
59
+ const result = zod_1.z.object({ conductor: referenceSchema, executor: referenceSchema, reviewer: referenceSchema }).strict().safeParse(input);
60
+ if (!result.success)
61
+ throw Error('maestro.authority.binding');
62
+ return result.data;
63
+ }
64
+ /** Todos os caminhos são derivados da thread; referências recebidas são apenas seletores. */
65
+ function verifySessionReview(root, binding) {
66
+ if (!binding || !binding.conductor || !binding.executor || !binding.reviewer)
67
+ throw Error('maestro.authority.unproven');
68
+ binding = parseSessionReviewBinding(binding);
69
+ const refs = [binding.conductor, binding.executor, binding.reviewer];
70
+ if (new Set(refs.map(r => r.sessionId)).size !== 3)
71
+ throw Error('maestro.authority.self-review');
72
+ const allowedPhases = [['GOAL', 'PLAN'], ['GO'], ['CHECK']];
73
+ const records = refs.map((ref, index) => {
74
+ const thread = (0, thread_1.lerThread)(root, ref.threadId);
75
+ if (!thread.worktree || !path.isAbsolute(ref.worktree) || thread.worktree !== ref.worktree ||
76
+ fs.realpathSync(ref.worktree) !== ref.worktree)
77
+ throw Error('maestro.authority.scope');
78
+ const matches = thread.sessoes.filter(s => s.sessionId === ref.sessionId);
79
+ if (matches.length !== 1)
80
+ throw Error('maestro.authority.unproven');
81
+ const session = matches[0];
82
+ if (!session?.verificada || !session.runtime || !allowedPhases[index].includes(session.fase))
83
+ throw Error('maestro.authority.unproven');
84
+ const events = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(root, thread.id));
85
+ const dispatch = events.filter(e => e.tipo === 'phase_dispatch' && e.sessionId === session.sessionId).at(-1);
86
+ if (!dispatch || !(dispatch.fase === session.fase && dispatch.runtime === session.runtime && dispatch.cwd === ref.worktree &&
87
+ dispatch.promptSha256 === session.promptSha256 && dispatch.slug === session.slug))
88
+ throw Error('maestro.authority.unproven');
89
+ const verified = events.find(e => e.tipo === 'phase_dispatch_verified' && e.sessionId === session.sessionId &&
90
+ e.slug === session.slug && e.encontrada === true && typeof e.fonte === 'string' && e.fonte.length > 0);
91
+ if (!session.promptPath)
92
+ throw Error('maestro.authority.unproven');
93
+ const prompt = path.resolve(root, session.promptPath);
94
+ const scope = fs.realpathSync((0, thread_1.dirThread)(root, thread.id)) + path.sep;
95
+ if (!dispatch?.eventId || !verified?.eventId || !fs.realpathSync(prompt).startsWith(scope) ||
96
+ (0, node_crypto_1.createHash)('sha256').update(fs.readFileSync(prompt)).digest('hex') !== session.promptSha256)
97
+ throw Error('maestro.authority.unproven');
98
+ return { session, dispatch, verified };
99
+ });
100
+ if (binding.executor.threadId !== binding.reviewer.threadId ||
101
+ binding.executor.worktree !== binding.reviewer.worktree)
102
+ throw Error('maestro.authority.scope');
103
+ return { ...binding, schema: 'ork.session-review/v1', runtime: records[2].session.runtime,
104
+ dispatchEvents: records.flatMap(r => [String(r.dispatch.eventId), String(r.verified.eventId)]) };
105
+ }
106
+ /** Despachar CHECK não equivale a concluí-lo. Só o resultado observado pelo núcleo conta. */
107
+ function verifyCompletedSessionReview(root, binding, envelope, verdict = 'approved') {
108
+ const proof = verifySessionReview(root, binding);
109
+ const thread = (0, thread_1.lerThread)(root, proof.reviewer.threadId);
110
+ const session = thread.sessoes.find(s => s.sessionId === proof.reviewer.sessionId);
111
+ requireSessionReviewRuntime(session.runtime);
112
+ const events = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(root, thread.id));
113
+ const executor = thread.sessoes.filter(s => s.fase === 'GO').at(-1);
114
+ const executionIndex = events.findIndex(e => e.eventId === proof.dispatchEvents[2]);
115
+ const reviewIndex = events.findIndex(e => e.eventId === proof.dispatchEvents[4]);
116
+ const executionTime = Date.parse(executor?.despachadaEm ?? '');
117
+ const reviewTime = Date.parse(session.despachadaEm ?? '');
118
+ // CHECK antigo não pode validar GO novo, mesmo na mesma thread/worktree.
119
+ if (executor?.sessionId !== proof.executor.sessionId || executionIndex < 0 || reviewIndex <= executionIndex ||
120
+ !Number.isFinite(executionTime) || !Number.isFinite(reviewTime) || reviewTime < executionTime ||
121
+ events.slice(executionIndex + 1).some(e => e.tipo === 'phase_dispatch' && e.fase === 'GO'))
122
+ throw Error('maestro.authority.review-stale');
123
+ const approval = envelope ? events.filter(e => e.tipo === 'objective_envelope_approved' && e.objectiveId === envelope.objectiveId).at(-1) : undefined;
124
+ if (envelope && (!approval?.eventId || approval.envelopeHash !== envelope.hash || approval.version !== envelope.version ||
125
+ approval.approvedAt !== envelope.approvedAt || events.indexOf(approval) >= executionIndex ||
126
+ !/^[a-f0-9]{64}$/.test(envelope.hash) || !Number.isSafeInteger(envelope.version) || envelope.version < 1 ||
127
+ !Number.isFinite(Date.parse(envelope.approvedAt)) || executionTime < Date.parse(envelope.approvedAt) ||
128
+ Date.parse(events[executionIndex].ts) < Date.parse(envelope.approvedAt)))
129
+ throw Error('maestro.authority.envelope-stale');
130
+ const result = events.filter(e => e.tipo === 'phase_result' && e.sessionId === session.sessionId).at(-1);
131
+ const completed = result?.classificacao === 'fase_concluida' && result.ok === true;
132
+ // Falha de qualidade pode concluir CHECK com parecer negativo. Transporte interrompido,
133
+ // espera humana e precondições ausentes não são revisão, mesmo com verdict=rejected.
134
+ // Política sem retry (ci.failed) preserva o bloqueio, mas não equivale a fase concluída:
135
+ // todo parecer negativo exige o terminal nativo do controller correlacionado pelo watcher.
136
+ const rejected = verdict === 'rejected' && result?.classificacao === 'gate_blocked' && result.ok === false &&
137
+ ['claims.failed', 'claims.unverifiable', 'verify.regression', 'verify.failed', 'ci.failed'].includes(String(result.motivo)) &&
138
+ result.conclusaoNativa === true && result.conclusaoNativaAusente === null &&
139
+ result.exitCode === 0 && result.signal === null &&
140
+ result.exitCodeFonte === 'controller.close' && result.fonteVencedora === 'rollout';
141
+ if (typeof result?.eventId !== 'string' || !result.eventId || result.fase !== 'CHECK' || result.runtime !== session.runtime ||
142
+ result.despachoEm !== session.despachadaEm || result.origem !== 'sessions.watch' ||
143
+ (!completed && !rejected) ||
144
+ typeof result.sensorResultId !== 'string' || !result.sensorResultId ||
145
+ typeof session.despachadaEm !== 'string' || !Number.isFinite(Date.parse(session.despachadaEm)) ||
146
+ !Number.isFinite(Date.parse(result.ts)) || Date.parse(result.ts) < Date.parse(session.despachadaEm))
147
+ throw Error('maestro.authority.review-incomplete');
148
+ if (events.indexOf(result) <= reviewIndex)
149
+ throw Error('maestro.authority.review-stale');
150
+ return { ...proof, executionEvent: String(events[executionIndex].eventId), reviewResultEvent: result.eventId,
151
+ ...(envelope ? { envelope: { ...envelope }, envelopeApprovalEvent: String(approval.eventId) } : {}) };
152
+ }
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readMaestro = readMaestro;
4
+ exports.maestroText = maestroText;
5
+ exports.runMaestroCli = runMaestroCli;
6
+ const maestro_discovery_1 = require("./maestro-discovery");
7
+ const maestro_contract_1 = require("./maestro-contract");
8
+ const maestro_snapshot_1 = require("./maestro-snapshot");
9
+ const maestro_sources_1 = require("./maestro-sources");
10
+ const maestro_actions_1 = require("./maestro-actions");
11
+ const maestro_runtime_1 = require("./maestro-runtime");
12
+ const horario_1 = require("./horario");
13
+ function readMaestro(context, options) {
14
+ const observations = options.native && options.threadId ? (0, maestro_runtime_1.nativeForThread)(context.root, options.threadId) : [];
15
+ return (0, maestro_snapshot_1.maestroSnapshot)(context, { ...options, collect: ctx => {
16
+ const sources = (0, maestro_sources_1.collectMaestroSources)(ctx, { threadId: options.threadId, native: observations });
17
+ if (options.host.child && sources.sections.portfolio) {
18
+ const ids = new Set((sources.sections.demands?.items ?? []).flatMap(d => d.refs.filter(r => r.kind === 'project').map(r => r.id)));
19
+ const visible = sources.sections.portfolio.items.filter(p => ids.has(p.id));
20
+ const parents = new Set(visible.flatMap(p => p.refs.map(r => r.id)));
21
+ sources.sections.portfolio.items = sources.sections.portfolio.items.filter(p => ids.has(p.id) || parents.has(p.id));
22
+ sources.gaps = sources.gaps.filter(g => !g.startsWith('portfolio.'));
23
+ sources.conflicts = sources.conflicts.filter(c => !c.startsWith('entity.') || visible.some(p => c.endsWith(':' + p.id)));
24
+ }
25
+ sources.sections.nextActions = (0, maestro_actions_1.proposeMaestroActions)(sources.sections.threads?.items ?? [], options.host);
26
+ if (sources.sections.threads?.state === 'unavailable') {
27
+ sources.sections.nextActions.state = 'unavailable';
28
+ sources.sections.nextActions.gaps.push('threads.unavailable');
29
+ }
30
+ sources.fingerprint = (0, maestro_sources_1.digest)([sources.fingerprint, sources.sections]);
31
+ return sources;
32
+ } });
33
+ }
34
+ function maestroText(snapshot) {
35
+ return [`${snapshot.project.name} · panorama Maestro`,
36
+ // I-35: o snapshot guarda ISO; o texto ao dono diz quando consultou, no fuso dele.
37
+ `• Consulta: ${(0, horario_1.formatarDataHoraRotulada)(snapshot.observedAt, { agora: snapshot.observedAt })}`,
38
+ ...maestro_contract_1.SECTION_NAMES.map(name => {
39
+ const s = snapshot.sections[name];
40
+ return `• ${name}: ${s.state} · ${s.coverage.returned}/${s.coverage.total ?? '?'}${s.coverage.omitted ? ' · mais itens disponíveis' : ''}`;
41
+ }),
42
+ ...snapshot.sections.threads.items.slice(0, 8).map(t => ` ${t.title}: ${t.facts.phase} · ${t.status}`),
43
+ `• Recomendo: ${snapshot.conflicts.length ? 'reler as fontes em conflito' : snapshot.gaps.length ? 'conferir as lacunas antes de agir' : 'escolher uma thread para ver o detalhe'}.`,
44
+ 'Use ork maestro --json para cobertura e ações; --thread ID consulta o detalhe nativo.',
45
+ ].join('\n');
46
+ }
47
+ function runMaestroCli(argv, cwd = process.cwd(), trusted = {}, io = { out: (v) => console.log(v), err: (v) => console.error(v) }) {
48
+ if (argv.length === 1 && argv[0] === '--help') {
49
+ io.out('ork maestro [--json] [--thread ID] [--section NOME --offset N]\nConsulta sem criar ou despachar trabalho. Na conversa, diga: orkastery maestro.');
50
+ return 0;
51
+ }
52
+ try {
53
+ let json = false, threadId, section, offset;
54
+ const seen = new Set();
55
+ for (let i = 0; i < argv.length; i++) {
56
+ const arg = argv[i];
57
+ if (seen.has(arg))
58
+ throw Error('maestro.arguments.invalid');
59
+ seen.add(arg);
60
+ if (arg === '--json')
61
+ json = true;
62
+ else if (arg === '--thread') {
63
+ threadId = argv[++i];
64
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$/.test(threadId ?? ''))
65
+ throw Error('maestro.arguments.invalid');
66
+ }
67
+ else if (arg === '--section') {
68
+ section = argv[++i];
69
+ if (!maestro_contract_1.SECTION_NAMES.includes(section))
70
+ throw Error('maestro.arguments.invalid');
71
+ }
72
+ else if (arg === '--offset') {
73
+ const raw = argv[++i];
74
+ if (!/^\d+$/.test(raw ?? ''))
75
+ throw Error('maestro.arguments.invalid');
76
+ offset = Number(raw);
77
+ if (!Number.isSafeInteger(offset))
78
+ throw Error('maestro.arguments.invalid');
79
+ }
80
+ else
81
+ throw Error('maestro.arguments.invalid');
82
+ }
83
+ if ((section === undefined) !== (offset === undefined))
84
+ throw Error('maestro.arguments.invalid');
85
+ const context = (0, maestro_discovery_1.discoverMaestro)({ cwd, ...trusted });
86
+ const snapshot = readMaestro(context, { threadId, offsets: section ? { [section]: offset } : undefined, native: true,
87
+ host: { tools: ['ork_thread_status', 'ork_observe', 'ork_git_status'], child: false } });
88
+ io.out(json ? JSON.stringify(snapshot) : maestroText(snapshot));
89
+ return 0;
90
+ }
91
+ catch (e) {
92
+ const message = e.message;
93
+ const code = /^maestro\.[a-z_.]+$/.test(message) ? message : 'maestro.source.unavailable';
94
+ io.err(JSON.stringify({ error: code }));
95
+ return code === 'maestro.arguments.invalid' ? 2 : 1;
96
+ }
97
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maestroSnapshotSchema = exports.maestroSectionSchema = exports.maestroItemSchema = exports.maestroActionSchema = exports.MAESTRO_ERRORS = exports.SECTION_NAMES = exports.MAESTRO_LIMITS = exports.MAESTRO_SCHEMA = void 0;
4
+ exports.validateMaestroSnapshot = validateMaestroSnapshot;
5
+ /** Projeção pública, sem autoridade para executar operações. */
6
+ const zod_1 = require("zod");
7
+ exports.MAESTRO_SCHEMA = 'ork.maestro-snapshot/v1';
8
+ exports.MAESTRO_LIMITS = { items: 50, bytes: 65536, sourceMs: 2000, totalMs: 10000 };
9
+ exports.SECTION_NAMES = ['portfolio', 'demands', 'threads', 'sessions', 'blockers', 'leases', 'retries', 'hitl', 'ship', 'master', 'nextActions'];
10
+ exports.MAESTRO_ERRORS = ['maestro.project.missing', 'maestro.project.ambiguous', 'maestro.project.scope', 'maestro.source.unavailable', 'maestro.snapshot.stale'];
11
+ const text = zod_1.z.string().max(512);
12
+ const identity = zod_1.z.string().min(1).max(160);
13
+ const fingerprint = zod_1.z.string().regex(/^[a-f0-9]{64}$/);
14
+ exports.maestroActionSchema = zod_1.z.object({
15
+ operation: zod_1.z.enum(['thread.status', 'thread.observe', 'hitl.decide', 'git.status', 'git.commit', 'verify', 'ship', 'retry', 'master', 'phase', 'creation']),
16
+ available: zod_1.z.boolean(), reason: text, preconditions: zod_1.z.array(text).max(10), readback: text,
17
+ }).strict();
18
+ exports.maestroItemSchema = zod_1.z.object({
19
+ id: identity, title: text, status: text,
20
+ refs: zod_1.z.array(zod_1.z.object({ kind: identity, id: identity }).strict()).max(16),
21
+ facts: zod_1.z.record(zod_1.z.union([text, zod_1.z.number().finite(), zod_1.z.boolean(), zod_1.z.null()])),
22
+ action: exports.maestroActionSchema.optional(),
23
+ }).strict();
24
+ exports.maestroSectionSchema = zod_1.z.object({
25
+ state: zod_1.z.enum(['available', 'empty', 'unavailable', 'stale', 'conflict']),
26
+ source: identity, observedAt: zod_1.z.string().datetime(), fingerprint: fingerprint.nullable(),
27
+ coverage: zod_1.z.object({ total: zod_1.z.number().int().nonnegative().nullable(), offset: zod_1.z.number().int().nonnegative(),
28
+ returned: zod_1.z.number().int().min(0).max(50), omitted: zod_1.z.number().int().nonnegative().nullable(),
29
+ nextOffset: zod_1.z.number().int().nonnegative().nullable(), limit: zod_1.z.literal(50) }).strict(),
30
+ items: zod_1.z.array(exports.maestroItemSchema).max(50), gaps: zod_1.z.array(text).max(50),
31
+ }).strict();
32
+ exports.maestroSnapshotSchema = zod_1.z.object({
33
+ schema: zod_1.z.literal(exports.MAESTRO_SCHEMA), observedAt: zod_1.z.string().datetime(), fingerprint,
34
+ project: zod_1.z.object({ id: identity, name: text, origin: zod_1.z.enum(['installation', 'cwd', 'worktree', 'selection']), fingerprint }).strict(),
35
+ limits: zod_1.z.object({ items: zod_1.z.literal(50), bytes: zod_1.z.literal(65536), sourceMs: zod_1.z.literal(2000), totalMs: zod_1.z.literal(10000) }).strict(),
36
+ sections: zod_1.z.object(Object.fromEntries(exports.SECTION_NAMES.map(name => [name, exports.maestroSectionSchema]))).strict(),
37
+ gaps: zod_1.z.array(text).max(100), conflicts: zod_1.z.array(text).max(100),
38
+ }).strict();
39
+ function validateMaestroSnapshot(input) {
40
+ const value = exports.maestroSnapshotSchema.parse(input);
41
+ if (Buffer.byteLength(JSON.stringify(value)) > exports.MAESTRO_LIMITS.bytes)
42
+ throw Error('maestro.snapshot.size');
43
+ for (const name of exports.SECTION_NAMES) {
44
+ const s = value.sections[name], c = s.coverage;
45
+ if (c.returned !== s.items.length || (c.total !== null && (c.offset + c.returned + (c.omitted ?? 0) !== c.total)) ||
46
+ (s.state === 'empty' && (c.total !== 0 || s.items.length)) ||
47
+ // Fonte parcial pode paginar itens observados sem inventar total/omissões.
48
+ (c.nextOffset !== null && (c.nextOffset !== c.offset + c.returned || c.returned === 0 ||
49
+ (c.omitted === null ? c.total !== null : c.omitted === 0))))
50
+ throw Error('maestro.coverage.invalid');
51
+ if (name === 'nextActions' && s.items.some(item => !item.action))
52
+ throw Error('maestro.action.invalid');
53
+ }
54
+ return value;
55
+ }
@@ -0,0 +1,132 @@
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.discoverMaestro = discoverMaestro;
37
+ exports.revalidateMaestroContext = revalidateMaestroContext;
38
+ /** Descoberta somente entre raízes permitidas. Nenhuma mutação ou busca na home. */
39
+ const fs = __importStar(require("node:fs"));
40
+ const path = __importStar(require("node:path"));
41
+ const node_crypto_1 = require("node:crypto");
42
+ const manifest_1 = require("./manifest");
43
+ const estado_thread_1 = require("./estado-thread");
44
+ const thread_1 = require("./thread");
45
+ const inside = (root, file) => file === root || file.startsWith(root + path.sep);
46
+ function physical(file) {
47
+ const absolute = path.resolve(file);
48
+ if (fs.realpathSync(absolute) !== absolute)
49
+ throw Error('maestro.project.scope');
50
+ return absolute;
51
+ }
52
+ function context(root, origin) {
53
+ const real = physical(root);
54
+ const manifest = ['orkastery.yaml', 'devmaster.yaml'].map(f => path.join(real, f)).find(f => fs.existsSync(f));
55
+ if (!manifest)
56
+ throw Error('maestro.project.missing');
57
+ physical(manifest);
58
+ const stat = fs.statSync(manifest);
59
+ if (!stat.isFile() || stat.size > 16384)
60
+ throw Error('maestro.project.scope');
61
+ for (const name of ['.orkastery', '.orkastery/threads', '.orkastery/objectives']) {
62
+ const file = path.join(real, name);
63
+ if (fs.existsSync(file) && !inside(real, fs.realpathSync(file)))
64
+ throw Error('maestro.project.scope');
65
+ }
66
+ const loaded = (0, manifest_1.carregarManifesto)(real);
67
+ if (!loaded || loaded.raiz !== real || loaded.erros.length)
68
+ throw Error('maestro.project.scope');
69
+ const fingerprint = (0, node_crypto_1.createHash)('sha256').update(real).update(fs.readFileSync(manifest))
70
+ .update(`${fs.statSync(real).dev}:${fs.statSync(real).ino}:${stat.ino}`).digest('hex');
71
+ return { root: real, manifest, fingerprint, project: { id: loaded.manifesto.project.abbrev,
72
+ name: loaded.manifesto.project.name, origin, fingerprint } };
73
+ }
74
+ function localRoot(cwd) {
75
+ let current = cwd;
76
+ for (;;) {
77
+ if (['orkastery.yaml', 'devmaster.yaml'].some(f => fs.existsSync(path.join(current, f))))
78
+ return current;
79
+ const parent = path.dirname(current);
80
+ if (parent === current)
81
+ return undefined;
82
+ current = parent;
83
+ }
84
+ }
85
+ function discoverMaestro(options) {
86
+ const cwd = physical(options.cwd), nearest = localRoot(cwd);
87
+ const candidates = [...new Set(options.pinned ? [options.pinned] : options.allowedRoots ?? (nearest ? [nearest] : []))].map(physical);
88
+ if (!candidates.length)
89
+ throw Error('maestro.project.missing');
90
+ if (options.selected && !candidates.includes(path.resolve(options.selected)))
91
+ throw Error('maestro.project.scope');
92
+ const chosen = options.selected ? path.resolve(options.selected) : candidates.length === 1 ? candidates[0] : undefined;
93
+ if (!chosen)
94
+ throw Error('maestro.project.ambiguous');
95
+ const origin = options.selected ? 'selection' : options.pinned ? 'installation' : 'cwd';
96
+ // Pin/seleção limitam candidatos; não dispensam o vínculo com o estado canônico.
97
+ const canonical = (0, estado_thread_1.raizDoEstado)(chosen);
98
+ if (canonical !== chosen) {
99
+ const git = path.join(chosen, '.git');
100
+ physical(git);
101
+ const match = /^gitdir: (.+)\s*$/.exec(fs.readFileSync(git, 'utf8'));
102
+ if (!match)
103
+ throw Error('maestro.project.scope');
104
+ const gitdir = physical(path.resolve(chosen, match[1].trim()));
105
+ const common = physical(path.join(canonical, '.git'));
106
+ const worktrees = physical(path.join(common, 'worktrees'));
107
+ if (path.dirname(gitdir) !== worktrees ||
108
+ path.resolve(gitdir, fs.readFileSync(physical(path.join(gitdir, 'commondir')), 'utf8').trim()) !== common ||
109
+ path.resolve(gitdir, fs.readFileSync(physical(path.join(gitdir, 'gitdir')), 'utf8').trim()) !== git)
110
+ throw Error('maestro.project.scope');
111
+ const localState = physical(path.join(chosen, '.orkastery/threads'));
112
+ const bindings = (0, thread_1.listarIds)(canonical).filter(id => (0, thread_1.lerThread)(canonical, id).worktree === chosen);
113
+ if (bindings.length !== 1)
114
+ throw Error('maestro.project.scope');
115
+ const bound = path.join(localState, bindings[0]);
116
+ if (!fs.existsSync(bound) || fs.realpathSync(bound) !== path.join(canonical, '.orkastery/threads', bindings[0]))
117
+ throw Error('maestro.project.scope');
118
+ if (fs.existsSync(localState))
119
+ for (const name of fs.readdirSync(localState)) {
120
+ const file = path.join(localState, name), target = path.join(canonical, '.orkastery/threads', name);
121
+ if (fs.lstatSync(file).isSymbolicLink() && fs.realpathSync(file) !== target)
122
+ throw Error('maestro.project.scope');
123
+ }
124
+ return context(canonical, 'worktree');
125
+ }
126
+ return context(chosen, origin);
127
+ }
128
+ function revalidateMaestroContext(value) {
129
+ const current = context(value.root, value.project.origin);
130
+ if (current.fingerprint !== value.fingerprint || current.manifest !== value.manifest)
131
+ throw Error('maestro.snapshot.stale');
132
+ }