oh-my-super-agent 0.1.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 (461) hide show
  1. package/.agents/agents/advisor.md +15 -0
  2. package/.agents/agents/conductor.md +32 -0
  3. package/.agents/agents/dreamer.md +13 -0
  4. package/.agents/agents/executor.md +17 -0
  5. package/.agents/agents/grader.md +15 -0
  6. package/.agents/config/endurance-policy.json +8 -0
  7. package/.agents/config/oms-config.json +119 -0
  8. package/.agents/config/release-policy.json +12 -0
  9. package/.agents/config/secret-scan-policy.json +7 -0
  10. package/.agents/config/verification-plan.json +33 -0
  11. package/.agents/registry.json +11 -0
  12. package/.agents/rules/constitution.md +7 -0
  13. package/.agents/skills/conductor/SKILL.md +23 -0
  14. package/.agents/skills/dream/SKILL.md +14 -0
  15. package/.agents/skills/executor/SKILL.md +13 -0
  16. package/.agents/skills/oms/SKILL.md +52 -0
  17. package/.agents/skills/quota-aware/SKILL.md +12 -0
  18. package/.agents/skills/schedule/SKILL.md +13 -0
  19. package/.agents/skills/team-protocol/SKILL.md +20 -0
  20. package/LICENSE +21 -0
  21. package/README.md +146 -0
  22. package/dist/src/audit/run-ledger.d.ts +183 -0
  23. package/dist/src/audit/run-ledger.js +1655 -0
  24. package/dist/src/audit/run-ledger.js.map +1 -0
  25. package/dist/src/cli.d.ts +61 -0
  26. package/dist/src/cli.js +2096 -0
  27. package/dist/src/cli.js.map +1 -0
  28. package/dist/src/commands/github-queue-probe.d.ts +26 -0
  29. package/dist/src/commands/github-queue-probe.js +51 -0
  30. package/dist/src/commands/github-queue-probe.js.map +1 -0
  31. package/dist/src/commands/trace-fixture.d.ts +20 -0
  32. package/dist/src/commands/trace-fixture.js +72 -0
  33. package/dist/src/commands/trace-fixture.js.map +1 -0
  34. package/dist/src/conductor/activity.d.ts +46 -0
  35. package/dist/src/conductor/activity.js +224 -0
  36. package/dist/src/conductor/activity.js.map +1 -0
  37. package/dist/src/conductor/bridge.d.ts +53 -0
  38. package/dist/src/conductor/bridge.js +652 -0
  39. package/dist/src/conductor/bridge.js.map +1 -0
  40. package/dist/src/conductor/notifications.d.ts +59 -0
  41. package/dist/src/conductor/notifications.js +381 -0
  42. package/dist/src/conductor/notifications.js.map +1 -0
  43. package/dist/src/conductor/recovery.d.ts +29 -0
  44. package/dist/src/conductor/recovery.js +198 -0
  45. package/dist/src/conductor/recovery.js.map +1 -0
  46. package/dist/src/conductor/start.d.ts +73 -0
  47. package/dist/src/conductor/start.js +519 -0
  48. package/dist/src/conductor/start.js.map +1 -0
  49. package/dist/src/conductor/waiter.d.ts +88 -0
  50. package/dist/src/conductor/waiter.js +427 -0
  51. package/dist/src/conductor/waiter.js.map +1 -0
  52. package/dist/src/config.d.ts +9 -0
  53. package/dist/src/config.js +40 -0
  54. package/dist/src/config.js.map +1 -0
  55. package/dist/src/dispatch/advice-source.d.ts +61 -0
  56. package/dist/src/dispatch/advice-source.js +198 -0
  57. package/dist/src/dispatch/advice-source.js.map +1 -0
  58. package/dist/src/dispatch/advice-store.d.ts +41 -0
  59. package/dist/src/dispatch/advice-store.js +201 -0
  60. package/dist/src/dispatch/advice-store.js.map +1 -0
  61. package/dist/src/dispatch/advice.d.ts +34 -0
  62. package/dist/src/dispatch/advice.js +371 -0
  63. package/dist/src/dispatch/advice.js.map +1 -0
  64. package/dist/src/dispatch/authority.d.ts +124 -0
  65. package/dist/src/dispatch/authority.js +1202 -0
  66. package/dist/src/dispatch/authority.js.map +1 -0
  67. package/dist/src/dispatch/intent.d.ts +66 -0
  68. package/dist/src/dispatch/intent.js +71 -0
  69. package/dist/src/dispatch/intent.js.map +1 -0
  70. package/dist/src/dispatch/runtime-authority.d.ts +42 -0
  71. package/dist/src/dispatch/runtime-authority.js +52 -0
  72. package/dist/src/dispatch/runtime-authority.js.map +1 -0
  73. package/dist/src/doctor.d.ts +20 -0
  74. package/dist/src/doctor.js +85 -0
  75. package/dist/src/doctor.js.map +1 -0
  76. package/dist/src/domain/records.d.ts +44 -0
  77. package/dist/src/domain/records.js +138 -0
  78. package/dist/src/domain/records.js.map +1 -0
  79. package/dist/src/domain/role-policy.d.ts +67 -0
  80. package/dist/src/domain/role-policy.js +547 -0
  81. package/dist/src/domain/role-policy.js.map +1 -0
  82. package/dist/src/events/bus.d.ts +32 -0
  83. package/dist/src/events/bus.js +115 -0
  84. package/dist/src/events/bus.js.map +1 -0
  85. package/dist/src/events/kinds.d.ts +126 -0
  86. package/dist/src/events/kinds.js +14 -0
  87. package/dist/src/events/kinds.js.map +1 -0
  88. package/dist/src/evidence/immutable-file.d.ts +12 -0
  89. package/dist/src/evidence/immutable-file.js +141 -0
  90. package/dist/src/evidence/immutable-file.js.map +1 -0
  91. package/dist/src/evidence/store.d.ts +125 -0
  92. package/dist/src/evidence/store.js +1189 -0
  93. package/dist/src/evidence/store.js.map +1 -0
  94. package/dist/src/evidence/verdict.d.ts +17 -0
  95. package/dist/src/evidence/verdict.js +23 -0
  96. package/dist/src/evidence/verdict.js.map +1 -0
  97. package/dist/src/generation/agent.d.ts +5 -0
  98. package/dist/src/generation/agent.js +34 -0
  99. package/dist/src/generation/agent.js.map +1 -0
  100. package/dist/src/generation/frontmatter.d.ts +7 -0
  101. package/dist/src/generation/frontmatter.js +33 -0
  102. package/dist/src/generation/frontmatter.js.map +1 -0
  103. package/dist/src/github/adapter.d.ts +44 -0
  104. package/dist/src/github/adapter.js +592 -0
  105. package/dist/src/github/adapter.js.map +1 -0
  106. package/dist/src/github/dispatch-eligibility.d.ts +9 -0
  107. package/dist/src/github/dispatch-eligibility.js +94 -0
  108. package/dist/src/github/dispatch-eligibility.js.map +1 -0
  109. package/dist/src/github/projector.d.ts +23 -0
  110. package/dist/src/github/projector.js +181 -0
  111. package/dist/src/github/projector.js.map +1 -0
  112. package/dist/src/github/review.d.ts +39 -0
  113. package/dist/src/github/review.js +1450 -0
  114. package/dist/src/github/review.js.map +1 -0
  115. package/dist/src/github/sync.d.ts +21 -0
  116. package/dist/src/github/sync.js +518 -0
  117. package/dist/src/github/sync.js.map +1 -0
  118. package/dist/src/github/types.d.ts +134 -0
  119. package/dist/src/github/types.js +11 -0
  120. package/dist/src/github/types.js.map +1 -0
  121. package/dist/src/goals/artifact-store.d.ts +31 -0
  122. package/dist/src/goals/artifact-store.js +241 -0
  123. package/dist/src/goals/artifact-store.js.map +1 -0
  124. package/dist/src/goals/authority.d.ts +112 -0
  125. package/dist/src/goals/authority.js +621 -0
  126. package/dist/src/goals/authority.js.map +1 -0
  127. package/dist/src/goals/native-snapshot.d.ts +12 -0
  128. package/dist/src/goals/native-snapshot.js +53 -0
  129. package/dist/src/goals/native-snapshot.js.map +1 -0
  130. package/dist/src/goals/runtime-authority.d.ts +7 -0
  131. package/dist/src/goals/runtime-authority.js +20 -0
  132. package/dist/src/goals/runtime-authority.js.map +1 -0
  133. package/dist/src/health/release-assessment.d.ts +11 -0
  134. package/dist/src/health/release-assessment.js +83 -0
  135. package/dist/src/health/release-assessment.js.map +1 -0
  136. package/dist/src/health/release-policy.d.ts +16 -0
  137. package/dist/src/health/release-policy.js +40 -0
  138. package/dist/src/health/release-policy.js.map +1 -0
  139. package/dist/src/hooks/native.d.ts +30 -0
  140. package/dist/src/hooks/native.js +495 -0
  141. package/dist/src/hooks/native.js.map +1 -0
  142. package/dist/src/hooks/provider-runtime.d.ts +55 -0
  143. package/dist/src/hooks/provider-runtime.js +479 -0
  144. package/dist/src/hooks/provider-runtime.js.map +1 -0
  145. package/dist/src/hooks/provider.d.ts +102 -0
  146. package/dist/src/hooks/provider.js +358 -0
  147. package/dist/src/hooks/provider.js.map +1 -0
  148. package/dist/src/live/contact-journal.d.ts +73 -0
  149. package/dist/src/live/contact-journal.js +439 -0
  150. package/dist/src/live/contact-journal.js.map +1 -0
  151. package/dist/src/live-probes/gh-adapter.d.ts +28 -0
  152. package/dist/src/live-probes/gh-adapter.js +188 -0
  153. package/dist/src/live-probes/gh-adapter.js.map +1 -0
  154. package/dist/src/live-probes/github-queue.d.ts +1 -0
  155. package/dist/src/live-probes/github-queue.js +2 -0
  156. package/dist/src/live-probes/github-queue.js.map +1 -0
  157. package/dist/src/notifications/slack-request.d.ts +13 -0
  158. package/dist/src/notifications/slack-request.js +40 -0
  159. package/dist/src/notifications/slack-request.js.map +1 -0
  160. package/dist/src/outbox/processor.d.ts +27 -0
  161. package/dist/src/outbox/processor.js +63 -0
  162. package/dist/src/outbox/processor.js.map +1 -0
  163. package/dist/src/outbox/store.d.ts +158 -0
  164. package/dist/src/outbox/store.js +834 -0
  165. package/dist/src/outbox/store.js.map +1 -0
  166. package/dist/src/package-root.d.ts +1 -0
  167. package/dist/src/package-root.js +26 -0
  168. package/dist/src/package-root.js.map +1 -0
  169. package/dist/src/project.d.ts +12 -0
  170. package/dist/src/project.js +60 -0
  171. package/dist/src/project.js.map +1 -0
  172. package/dist/src/projection/generated-file.d.ts +15 -0
  173. package/dist/src/projection/generated-file.js +72 -0
  174. package/dist/src/projection/generated-file.js.map +1 -0
  175. package/dist/src/projection/project-workspace.d.ts +11 -0
  176. package/dist/src/projection/project-workspace.js +94 -0
  177. package/dist/src/projection/project-workspace.js.map +1 -0
  178. package/dist/src/projection/registry.d.ts +15 -0
  179. package/dist/src/projection/registry.js +59 -0
  180. package/dist/src/projection/registry.js.map +1 -0
  181. package/dist/src/projection/safe-path.d.ts +4 -0
  182. package/dist/src/projection/safe-path.js +106 -0
  183. package/dist/src/projection/safe-path.js.map +1 -0
  184. package/dist/src/providers/claude-interactive.d.ts +38 -0
  185. package/dist/src/providers/claude-interactive.js +287 -0
  186. package/dist/src/providers/claude-interactive.js.map +1 -0
  187. package/dist/src/providers/claude-structured-bridge.d.ts +32 -0
  188. package/dist/src/providers/claude-structured-bridge.js +215 -0
  189. package/dist/src/providers/claude-structured-bridge.js.map +1 -0
  190. package/dist/src/providers/claude-structured-completion.d.ts +23 -0
  191. package/dist/src/providers/claude-structured-completion.js +229 -0
  192. package/dist/src/providers/claude-structured-completion.js.map +1 -0
  193. package/dist/src/providers/claude-structured-pane.d.ts +23 -0
  194. package/dist/src/providers/claude-structured-pane.js +156 -0
  195. package/dist/src/providers/claude-structured-pane.js.map +1 -0
  196. package/dist/src/providers/claude-structured-store.d.ts +48 -0
  197. package/dist/src/providers/claude-structured-store.js +212 -0
  198. package/dist/src/providers/claude-structured-store.js.map +1 -0
  199. package/dist/src/providers/claude-structured.d.ts +56 -0
  200. package/dist/src/providers/claude-structured.js +250 -0
  201. package/dist/src/providers/claude-structured.js.map +1 -0
  202. package/dist/src/providers/codex-exec.d.ts +29 -0
  203. package/dist/src/providers/codex-exec.js +127 -0
  204. package/dist/src/providers/codex-exec.js.map +1 -0
  205. package/dist/src/providers/grading.d.ts +2 -0
  206. package/dist/src/providers/grading.js +20 -0
  207. package/dist/src/providers/grading.js.map +1 -0
  208. package/dist/src/providers/native-dispatch.d.ts +24 -0
  209. package/dist/src/providers/native-dispatch.js +34 -0
  210. package/dist/src/providers/native-dispatch.js.map +1 -0
  211. package/dist/src/providers/preflight.d.ts +65 -0
  212. package/dist/src/providers/preflight.js +256 -0
  213. package/dist/src/providers/preflight.js.map +1 -0
  214. package/dist/src/providers/process.d.ts +18 -0
  215. package/dist/src/providers/process.js +21 -0
  216. package/dist/src/providers/process.js.map +1 -0
  217. package/dist/src/queue/model.d.ts +37 -0
  218. package/dist/src/queue/model.js +51 -0
  219. package/dist/src/queue/model.js.map +1 -0
  220. package/dist/src/queue/service.d.ts +1 -0
  221. package/dist/src/queue/service.js +2 -0
  222. package/dist/src/queue/service.js.map +1 -0
  223. package/dist/src/reflections/store.d.ts +21 -0
  224. package/dist/src/reflections/store.js +60 -0
  225. package/dist/src/reflections/store.js.map +1 -0
  226. package/dist/src/reports/daily-trust.d.ts +11 -0
  227. package/dist/src/reports/daily-trust.js +98 -0
  228. package/dist/src/reports/daily-trust.js.map +1 -0
  229. package/dist/src/runs/controller.d.ts +187 -0
  230. package/dist/src/runs/controller.js +1182 -0
  231. package/dist/src/runs/controller.js.map +1 -0
  232. package/dist/src/runtime/composition.d.ts +9 -0
  233. package/dist/src/runtime/composition.js +35 -0
  234. package/dist/src/runtime/composition.js.map +1 -0
  235. package/dist/src/runtime/endurance-authorities.d.ts +44 -0
  236. package/dist/src/runtime/endurance-authorities.js +101 -0
  237. package/dist/src/runtime/endurance-authorities.js.map +1 -0
  238. package/dist/src/runtime/endurance-policy.d.ts +12 -0
  239. package/dist/src/runtime/endurance-policy.js +13 -0
  240. package/dist/src/runtime/endurance-policy.js.map +1 -0
  241. package/dist/src/runtime/lock.d.ts +63 -0
  242. package/dist/src/runtime/lock.js +577 -0
  243. package/dist/src/runtime/lock.js.map +1 -0
  244. package/dist/src/runtime/process-identity.d.ts +10 -0
  245. package/dist/src/runtime/process-identity.js +43 -0
  246. package/dist/src/runtime/process-identity.js.map +1 -0
  247. package/dist/src/runtime/quota.d.ts +130 -0
  248. package/dist/src/runtime/quota.js +590 -0
  249. package/dist/src/runtime/quota.js.map +1 -0
  250. package/dist/src/runtime/record-store.d.ts +45 -0
  251. package/dist/src/runtime/record-store.js +272 -0
  252. package/dist/src/runtime/record-store.js.map +1 -0
  253. package/dist/src/runtime/schema.d.ts +28 -0
  254. package/dist/src/runtime/schema.js +194 -0
  255. package/dist/src/runtime/schema.js.map +1 -0
  256. package/dist/src/runtime/stable-id.d.ts +3 -0
  257. package/dist/src/runtime/stable-id.js +27 -0
  258. package/dist/src/runtime/stable-id.js.map +1 -0
  259. package/dist/src/runtime/system-clock.d.ts +8 -0
  260. package/dist/src/runtime/system-clock.js +35 -0
  261. package/dist/src/runtime/system-clock.js.map +1 -0
  262. package/dist/src/schedule/service-plan.d.ts +58 -0
  263. package/dist/src/schedule/service-plan.js +327 -0
  264. package/dist/src/schedule/service-plan.js.map +1 -0
  265. package/dist/src/schedule/user-installation.d.ts +62 -0
  266. package/dist/src/schedule/user-installation.js +701 -0
  267. package/dist/src/schedule/user-installation.js.map +1 -0
  268. package/dist/src/schedule/user-plan.d.ts +47 -0
  269. package/dist/src/schedule/user-plan.js +286 -0
  270. package/dist/src/schedule/user-plan.js.map +1 -0
  271. package/dist/src/scheduler/minute.d.ts +31 -0
  272. package/dist/src/scheduler/minute.js +441 -0
  273. package/dist/src/scheduler/minute.js.map +1 -0
  274. package/dist/src/schemas/registry.d.ts +10 -0
  275. package/dist/src/schemas/registry.js +36 -0
  276. package/dist/src/schemas/registry.js.map +1 -0
  277. package/dist/src/security/secret-scan.d.ts +50 -0
  278. package/dist/src/security/secret-scan.js +384 -0
  279. package/dist/src/security/secret-scan.js.map +1 -0
  280. package/dist/src/sessions/registry.d.ts +89 -0
  281. package/dist/src/sessions/registry.js +443 -0
  282. package/dist/src/sessions/registry.js.map +1 -0
  283. package/dist/src/state.d.ts +27 -0
  284. package/dist/src/state.js +235 -0
  285. package/dist/src/state.js.map +1 -0
  286. package/dist/src/status/hud.d.ts +37 -0
  287. package/dist/src/status/hud.js +88 -0
  288. package/dist/src/status/hud.js.map +1 -0
  289. package/dist/src/team/plan.d.ts +31 -0
  290. package/dist/src/team/plan.js +184 -0
  291. package/dist/src/team/plan.js.map +1 -0
  292. package/dist/src/team/projection.d.ts +24 -0
  293. package/dist/src/team/projection.js +79 -0
  294. package/dist/src/team/projection.js.map +1 -0
  295. package/dist/src/tickets/admission.d.ts +34 -0
  296. package/dist/src/tickets/admission.js +169 -0
  297. package/dist/src/tickets/admission.js.map +1 -0
  298. package/dist/src/tickets/materializer.d.ts +1 -0
  299. package/dist/src/tickets/materializer.js +2 -0
  300. package/dist/src/tickets/materializer.js.map +1 -0
  301. package/dist/src/tickets/runtime-authority.d.ts +32 -0
  302. package/dist/src/tickets/runtime-authority.js +46 -0
  303. package/dist/src/tickets/runtime-authority.js.map +1 -0
  304. package/dist/src/tickets/store.d.ts +221 -0
  305. package/dist/src/tickets/store.js +2025 -0
  306. package/dist/src/tickets/store.js.map +1 -0
  307. package/dist/src/tracer/one-ticket.d.ts +58 -0
  308. package/dist/src/tracer/one-ticket.js +578 -0
  309. package/dist/src/tracer/one-ticket.js.map +1 -0
  310. package/dist/src/trust/assessment.d.ts +24 -0
  311. package/dist/src/trust/assessment.js +124 -0
  312. package/dist/src/trust/assessment.js.map +1 -0
  313. package/dist/src/trust/runs.d.ts +13 -0
  314. package/dist/src/trust/runs.js +46 -0
  315. package/dist/src/trust/runs.js.map +1 -0
  316. package/dist/src/types.d.ts +6 -0
  317. package/dist/src/types.js +2 -0
  318. package/dist/src/types.js.map +1 -0
  319. package/dist/src/utils/fs.d.ts +13 -0
  320. package/dist/src/utils/fs.js +188 -0
  321. package/dist/src/utils/fs.js.map +1 -0
  322. package/dist/src/verification/authority.d.ts +28 -0
  323. package/dist/src/verification/authority.js +153 -0
  324. package/dist/src/verification/authority.js.map +1 -0
  325. package/dist/src/verification/grade-source.d.ts +17 -0
  326. package/dist/src/verification/grade-source.js +30 -0
  327. package/dist/src/verification/grade-source.js.map +1 -0
  328. package/dist/src/verification/plan.d.ts +20 -0
  329. package/dist/src/verification/plan.js +128 -0
  330. package/dist/src/verification/plan.js.map +1 -0
  331. package/dist/src/verification/protected-runner.d.ts +50 -0
  332. package/dist/src/verification/protected-runner.js +171 -0
  333. package/dist/src/verification/protected-runner.js.map +1 -0
  334. package/dist/src/verification/result-gate-store.d.ts +72 -0
  335. package/dist/src/verification/result-gate-store.js +193 -0
  336. package/dist/src/verification/result-gate-store.js.map +1 -0
  337. package/dist/src/verification/result-gate.d.ts +41 -0
  338. package/dist/src/verification/result-gate.js +731 -0
  339. package/dist/src/verification/result-gate.js.map +1 -0
  340. package/dist/src/verification/runner.d.ts +38 -0
  341. package/dist/src/verification/runner.js +143 -0
  342. package/dist/src/verification/runner.js.map +1 -0
  343. package/dist/src/verification/sandbox.d.ts +16 -0
  344. package/dist/src/verification/sandbox.js +199 -0
  345. package/dist/src/verification/sandbox.js.map +1 -0
  346. package/dist/src/verify.d.ts +8 -0
  347. package/dist/src/verify.js +35 -0
  348. package/dist/src/verify.js.map +1 -0
  349. package/dist/src/watchdog/reconcile.d.ts +42 -0
  350. package/dist/src/watchdog/reconcile.js +440 -0
  351. package/dist/src/watchdog/reconcile.js.map +1 -0
  352. package/dist/src/workers/bridge.d.ts +35 -0
  353. package/dist/src/workers/bridge.js +426 -0
  354. package/dist/src/workers/bridge.js.map +1 -0
  355. package/dist/src/workers/delivery.d.ts +31 -0
  356. package/dist/src/workers/delivery.js +876 -0
  357. package/dist/src/workers/delivery.js.map +1 -0
  358. package/dist/src/workers/panes.d.ts +32 -0
  359. package/dist/src/workers/panes.js +212 -0
  360. package/dist/src/workers/panes.js.map +1 -0
  361. package/dist/src/workers/registry.d.ts +80 -0
  362. package/dist/src/workers/registry.js +351 -0
  363. package/dist/src/workers/registry.js.map +1 -0
  364. package/dist/src/workers/runtime.d.ts +44 -0
  365. package/dist/src/workers/runtime.js +21 -0
  366. package/dist/src/workers/runtime.js.map +1 -0
  367. package/dist/src/worktrees/manager.d.ts +35 -0
  368. package/dist/src/worktrees/manager.js +315 -0
  369. package/dist/src/worktrees/manager.js.map +1 -0
  370. package/docs/ARCHITECTURE.md +323 -0
  371. package/docs/PLAN.md +216 -0
  372. package/docs/REFERENCES.md +42 -0
  373. package/docs/ROADMAP.md +327 -0
  374. package/docs/SECURITY.md +242 -0
  375. package/docs/adr/0001-tracer-first-file-backed-certification.md +41 -0
  376. package/docs/adr/0002-conductor-first-typed-dispatch.md +102 -0
  377. package/docs/adr/0003-mandatory-pre-dispatch-advice.md +59 -0
  378. package/docs/compatibility/claude-code-2.1.207.md +25 -0
  379. package/loop/contract.md +102 -0
  380. package/package.json +54 -0
  381. package/schemas/advisor-evidence.schema.json +54 -0
  382. package/schemas/advisor-output.schema.json +31 -0
  383. package/schemas/conductor-activity-payload.schema.json +38 -0
  384. package/schemas/conductor-decision.schema.json +29 -0
  385. package/schemas/conductor-dispatch-intent.schema.json +71 -0
  386. package/schemas/conductor-dispatch-preparation.schema.json +46 -0
  387. package/schemas/conductor-dispatch-proposal.schema.json +82 -0
  388. package/schemas/conductor-goal-proposal.schema.json +30 -0
  389. package/schemas/conductor-manage-worker.schema.json +17 -0
  390. package/schemas/conductor-notification-payload.schema.json +39 -0
  391. package/schemas/conductor-process-result.schema.json +14 -0
  392. package/schemas/conductor-route.schema.json +51 -0
  393. package/schemas/conductor-start-team.schema.json +16 -0
  394. package/schemas/conductor-waiter-payload.schema.json +68 -0
  395. package/schemas/deterministic-check.schema.json +107 -0
  396. package/schemas/dispatch-acknowledgement.schema.json +15 -0
  397. package/schemas/dispatch-advice-payload.schema.json +64 -0
  398. package/schemas/dispatch-payload.schema.json +131 -0
  399. package/schemas/dispatch-result.schema.json +28 -0
  400. package/schemas/endurance-policy.schema.json +16 -0
  401. package/schemas/events/dispatch-delivery-requested.schema.json +17 -0
  402. package/schemas/events/github-observed.schema.json +28 -0
  403. package/schemas/events/native-hook-observed.schema.json +35 -0
  404. package/schemas/events/provider-observed.schema.json +64 -0
  405. package/schemas/events/run-heartbeat-due.schema.json +10 -0
  406. package/schemas/events/slack-notification-requested.schema.json +14 -0
  407. package/schemas/events/structured-role-completed.schema.json +54 -0
  408. package/schemas/events/ticket-resume-due.schema.json +28 -0
  409. package/schemas/events/watchdog-lease-expired.schema.json +14 -0
  410. package/schemas/events/watchdog-outbox-stalled.schema.json +12 -0
  411. package/schemas/events/watchdog-session-stalled.schema.json +11 -0
  412. package/schemas/evidence-record.schema.json +37 -0
  413. package/schemas/executor-result.schema.json +17 -0
  414. package/schemas/github-observation.schema.json +33 -0
  415. package/schemas/github-watermark.schema.json +66 -0
  416. package/schemas/goal-artifact.schema.json +19 -0
  417. package/schemas/goal-create-input.schema.json +14 -0
  418. package/schemas/goal-executor-result.schema.json +18 -0
  419. package/schemas/goal-payload.schema.json +95 -0
  420. package/schemas/grader-output.schema.json +33 -0
  421. package/schemas/lease-expiry.schema.json +19 -0
  422. package/schemas/live-disclosure.schema.json +16 -0
  423. package/schemas/live-outcome.schema.json +52 -0
  424. package/schemas/native-goal-snapshot.schema.json +27 -0
  425. package/schemas/provider-observed.schema.json +64 -0
  426. package/schemas/quota-observation.schema.json +72 -0
  427. package/schemas/reflection-evidence.schema.json +61 -0
  428. package/schemas/reflection.schema.json +13 -0
  429. package/schemas/regression-request.schema.json +54 -0
  430. package/schemas/release-assessment.schema.json +34 -0
  431. package/schemas/release-policy.schema.json +30 -0
  432. package/schemas/result-gate-payload.schema.json +244 -0
  433. package/schemas/review-delivery-payload.schema.json +42 -0
  434. package/schemas/role-policy.schema.json +111 -0
  435. package/schemas/run-abort-input.schema.json +11 -0
  436. package/schemas/run-completion-proof.schema.json +62 -0
  437. package/schemas/run-ledger-entry.schema.json +78 -0
  438. package/schemas/run-manifest.schema.json +74 -0
  439. package/schemas/run-start-intent.schema.json +74 -0
  440. package/schemas/runtime-record.schema.json +111 -0
  441. package/schemas/service-plan.schema.json +35 -0
  442. package/schemas/session-payload.schema.json +80 -0
  443. package/schemas/structured-role-read-request.schema.json +14 -0
  444. package/schemas/structured-role-request.schema.json +44 -0
  445. package/schemas/structured-role-result.schema.json +38 -0
  446. package/schemas/structured-role-submit-result.schema.json +15 -0
  447. package/schemas/team-checkpoint.schema.json +42 -0
  448. package/schemas/team-plan.schema.json +30 -0
  449. package/schemas/ticket-content.schema.json +38 -0
  450. package/schemas/ticket-queue-payload.schema.json +191 -0
  451. package/schemas/trust-report.schema.json +68 -0
  452. package/schemas/trust-run.schema.json +47 -0
  453. package/schemas/ultragoal-checkpoint.schema.json +49 -0
  454. package/schemas/user-schedule-installation-v1.schema.json +32 -0
  455. package/schemas/user-schedule-installation.schema.json +38 -0
  456. package/schemas/user-schedule-plan.schema.json +39 -0
  457. package/schemas/verification-plan-evidence.schema.json +37 -0
  458. package/schemas/worker-acknowledge-dispatch.schema.json +12 -0
  459. package/schemas/worker-payload.schema.json +47 -0
  460. package/schemas/worker-read-dispatch.schema.json +11 -0
  461. package/schemas/worker-record-dispatch-result.schema.json +14 -0
@@ -0,0 +1,1182 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { readdirSync } from "node:fs";
3
+ import { basename, join } from "node:path";
4
+ import { createAuditRunTerminalWriter, createLiveRunLedger, } from "../audit/run-ledger.js";
5
+ import { assertFileInside, openStableDirectory, readImmutableFile, writeImmutableFile, } from "../evidence/immutable-file.js";
6
+ import { createEnduranceAuthorities } from "../runtime/endurance-authorities.js";
7
+ import { acquireDirectoryLock, readLockOwner, recoverDirectoryLock } from "../runtime/lock.js";
8
+ import { currentProcessInstanceId, processIsAlive } from "../runtime/process-identity.js";
9
+ import { assertSchema, loadJsonSchema } from "../runtime/schema.js";
10
+ import { createStableId } from "../runtime/stable-id.js";
11
+ import { systemBootId, systemClockSample } from "../runtime/system-clock.js";
12
+ import { generateServicePlan, persistServicePlan, verifyPersistedServicePlan, } from "../schedule/service-plan.js";
13
+ import { loadTrackedRolePolicyGate } from "../domain/role-policy.js";
14
+ import { isRecord, validateExistingDirectory } from "../utils/fs.js";
15
+ import { freezeTrackedVerificationPlan } from "../verification/plan.js";
16
+ const MAX_CONTROL_BYTES = 1024 * 1024;
17
+ const RUN_TICKET_ADMISSION = Symbol("OMS run ticket admission");
18
+ const RUN_TICKET_ADMISSIONS = new WeakSet();
19
+ const TWELVE_HOURS_MS = 12 * 60 * 60 * 1000;
20
+ const TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1000;
21
+ export function startAuditRun(options) {
22
+ const packageRoot = validateExistingDirectory(options.packageRoot, "package root");
23
+ const configRoot = validateExistingDirectory(options.configRoot, "configuration root");
24
+ const stateRoot = validateExistingDirectory(options.stateRoot, "runtime state root");
25
+ const workspaceRoot = validateExistingDirectory(options.workspaceRoot, "workspace root");
26
+ if (options.runKind !== "12h" && options.runKind !== "24h" && options.runKind !== "until-empty") {
27
+ throw new Error("unsupported audit run kind");
28
+ }
29
+ return withRunControllerAuthority(stateRoot, () => {
30
+ const runtime = createEnduranceAuthorities({ packageRoot, configRoot, stateRoot });
31
+ try {
32
+ const intents = listStartIntents(packageRoot, stateRoot);
33
+ const outstanding = outstandingStartIntents(runtime.auditLedger, intents);
34
+ if (outstanding.length > 1)
35
+ throw new Error("multiple outstanding run intents require operator repair");
36
+ const activeWithoutIntent = runtime.auditLedger.listRunIds().filter((runId) => {
37
+ const head = runtime.auditLedger.head(runId);
38
+ if (!head || runtime.auditLedger.deriveMetrics(head).status !== "running")
39
+ return false;
40
+ return !intents.some((intent) => intent.expected_run_id === runId);
41
+ });
42
+ if (activeWithoutIntent.length > 0)
43
+ throw new Error(`unbound active audit run requires operator repair: ${activeWithoutIntent[0]}`);
44
+ const intent = outstanding[0]
45
+ ? assertStartRequestMatches(outstanding[0], options, runtime.policyGate.digest, configRoot)
46
+ : createStartIntent({
47
+ packageRoot,
48
+ configRoot,
49
+ stateRoot,
50
+ workspaceRoot,
51
+ executablePath: options.executablePath,
52
+ manager: options.manager,
53
+ runKind: options.runKind,
54
+ policyDigest: runtime.policyGate.digest,
55
+ tickets: runtime.tickets.queue.list(),
56
+ });
57
+ const started = runtime.auditLedger.start({
58
+ operationId: intent.operation_id,
59
+ runKind: intent.run_kind,
60
+ policyDigest: intent.policy_digest,
61
+ ticketSetDigest: intent.ticket_set_digest,
62
+ servicePlanDigest: intent.service_plan_digest,
63
+ });
64
+ if (started.entry.run_id !== intent.expected_run_id)
65
+ throw new Error("run start intent derived a different run id");
66
+ const manifest = persistManifest(manifestFromIntent(intent, started.entry.recorded_at), packageRoot, stateRoot);
67
+ return Object.freeze({ status: started.status, manifest });
68
+ }
69
+ finally {
70
+ runtime.close();
71
+ }
72
+ });
73
+ }
74
+ export function conductorNext(options) {
75
+ return withRunControllerAuthority(options.stateRoot, () => {
76
+ const runtime = createEnduranceAuthorities(options);
77
+ try {
78
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, options.runId);
79
+ assertRunCurrentAuthority(manifest, options.configRoot);
80
+ assertActiveManifestRun(runtime.auditLedger, manifest);
81
+ return persistDecision(buildConductorRoute(runtime.tickets.queue.list(), manifest), options.packageRoot, options.stateRoot);
82
+ }
83
+ finally {
84
+ runtime.close();
85
+ }
86
+ });
87
+ }
88
+ export function tickAuditRun(options) {
89
+ return withRunControllerAuthority(options.stateRoot, () => {
90
+ const runtime = createEnduranceAuthorities(options);
91
+ try {
92
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, options.runId);
93
+ assertRunCurrentAuthority(manifest, options.configRoot);
94
+ let metrics = currentMetrics(runtime.auditLedger, manifest);
95
+ if (metrics.status !== "running") {
96
+ validateTerminal(runtime, manifest, metrics, options.packageRoot);
97
+ return Object.freeze({ status: buildStatus(runtime.tickets.queue.list(), manifest, metrics), route: null });
98
+ }
99
+ recordControllerObservation(runtime.auditLedger, manifest, "tick");
100
+ metrics = currentMetrics(runtime.auditLedger, manifest);
101
+ projectTicketStates(runtime.auditLedger, manifest, runtime.tickets.queue.list());
102
+ const route = buildConductorRoute(runtime.tickets.queue.list(), manifest);
103
+ persistDecision(route, options.packageRoot, options.stateRoot);
104
+ if (manifest.run_kind === "until-empty" && route.action === "queue-empty") {
105
+ completeAuditRun(runtime, manifest, "until-empty", 0, options.packageRoot);
106
+ }
107
+ const latest = currentMetrics(runtime.auditLedger, manifest);
108
+ validateTerminal(runtime, manifest, latest, options.packageRoot);
109
+ return Object.freeze({ status: buildStatus(runtime.tickets.queue.list(), manifest, latest), route });
110
+ }
111
+ finally {
112
+ runtime.close();
113
+ }
114
+ });
115
+ }
116
+ export function closeTimedAuditRun(options) {
117
+ return withRunControllerAuthority(options.stateRoot, () => {
118
+ const runtime = createEnduranceAuthorities(options);
119
+ try {
120
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, options.runId);
121
+ assertRunCurrentAuthority(manifest, options.configRoot);
122
+ if (manifest.run_kind === "until-empty")
123
+ throw new Error("until-empty runs close through run tick");
124
+ let metrics = currentMetrics(runtime.auditLedger, manifest);
125
+ if (metrics.status !== "running") {
126
+ validateTerminal(runtime, manifest, metrics, options.packageRoot);
127
+ if (metrics.status === "aborted")
128
+ throw new Error(`aborted audit run cannot be closed: ${manifest.run_id}`);
129
+ return buildStatus(runtime.tickets.queue.list(), manifest, metrics);
130
+ }
131
+ recordControllerObservation(runtime.auditLedger, manifest, "close");
132
+ metrics = currentMetrics(runtime.auditLedger, manifest);
133
+ const minimum = manifest.run_kind === "12h" ? TWELVE_HOURS_MS : TWENTY_FOUR_HOURS_MS;
134
+ if (!metrics.restart_continuity_valid || metrics.monotonic_elapsed_ms < minimum || metrics.elapsed_ms < minimum) {
135
+ throw new Error(`${manifest.run_kind} audit duration has not elapsed with valid continuity`);
136
+ }
137
+ projectTicketStates(runtime.auditLedger, manifest, runtime.tickets.queue.list());
138
+ if (buildConductorRoute(runtime.tickets.queue.list(), manifest).action !== "queue-empty") {
139
+ throw new Error("timed audit run cannot close with unresolved or unadmitted tickets");
140
+ }
141
+ completeAuditRun(runtime, manifest, "elapsed", minimum, options.packageRoot);
142
+ const latest = currentMetrics(runtime.auditLedger, manifest);
143
+ validateTerminal(runtime, manifest, latest, options.packageRoot);
144
+ return buildStatus(runtime.tickets.queue.list(), manifest, latest);
145
+ }
146
+ finally {
147
+ runtime.close();
148
+ }
149
+ });
150
+ }
151
+ export function abortAuditRun(options) {
152
+ return withRunControllerAuthority(options.stateRoot, () => {
153
+ const runtime = createEnduranceAuthorities(options);
154
+ try {
155
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, options.runId);
156
+ const metrics = currentMetrics(runtime.auditLedger, manifest);
157
+ const reason = boundedReason(options.reason);
158
+ if (metrics.status === "running") {
159
+ const reasonSha256 = sha256(reason);
160
+ const reasonFile = `${manifest.run_id}-${reasonSha256}.txt`;
161
+ writeControlFile(join(options.stateRoot, "run-aborts"), reasonFile, Buffer.from(reason, "utf8"), "run aborts root");
162
+ appendRunTerminalEvent(runtime.auditLedger, createAuditRunTerminalWriter(runtime.auditLedger), {
163
+ runId: manifest.run_id,
164
+ operationId: createStableId("run-abort", manifest.run_id, reasonSha256),
165
+ entryKind: "run-aborted",
166
+ payload: {
167
+ manifest_id: manifest.manifest_id,
168
+ reason_sha256: reasonSha256,
169
+ reason_file: reasonFile,
170
+ certifying: false,
171
+ },
172
+ });
173
+ }
174
+ else if (metrics.status === "completed") {
175
+ throw new Error(`completed audit run cannot be aborted: ${manifest.run_id}`);
176
+ }
177
+ else {
178
+ const terminal = runtime.auditLedger.list(manifest.run_id).at(-1);
179
+ if (terminal?.entry_kind !== "run-aborted" || terminal.payload.reason_sha256 !== sha256(reason)) {
180
+ throw new Error(`audit run was already aborted with a different reason: ${manifest.run_id}`);
181
+ }
182
+ }
183
+ const latest = currentMetrics(runtime.auditLedger, manifest);
184
+ validateTerminal(runtime, manifest, latest, options.packageRoot);
185
+ return buildStatus(runtime.tickets.queue.list(), manifest, latest);
186
+ }
187
+ finally {
188
+ runtime.close();
189
+ }
190
+ });
191
+ }
192
+ export function recoverRunControllerAuthority(options) {
193
+ const packageRoot = validateExistingDirectory(options.packageRoot, "package root");
194
+ const stateRoot = validateExistingDirectory(options.stateRoot, "runtime state root");
195
+ const reason = boundedRecoveryReason(options.reason);
196
+ const locksRoot = join(stateRoot, "locks");
197
+ const lockPath = join(locksRoot, "run-controller");
198
+ const owner = readLockOwner(lockPath);
199
+ if (owner) {
200
+ if (owner.created_nonce !== options.expectedGenerationId) {
201
+ throw new Error("expected run controller generation is not active");
202
+ }
203
+ if (owner.boot_id === systemBootId() && processIsAlive(owner.process_id)) {
204
+ throw new Error("refusing to recover a run controller lock whose owner process is alive");
205
+ }
206
+ }
207
+ const recovered = recoverDirectoryLock({
208
+ locksRoot,
209
+ lockId: "run-controller",
210
+ recoveredBy: "oms-run-controller",
211
+ reason,
212
+ expectedGenerationId: options.expectedGenerationId,
213
+ });
214
+ withRunControllerAuthority(stateRoot, () => {
215
+ const ledger = createLiveRunLedger({
216
+ ledgerRoot: join(stateRoot, "audit"),
217
+ locksRoot,
218
+ packageRoot,
219
+ });
220
+ const intents = listStartIntents(packageRoot, stateRoot);
221
+ const activeRunIds = ledger.listRunIds().filter((runId) => {
222
+ const head = ledger.head(runId);
223
+ if (head === undefined || ledger.deriveMetrics(head).status !== "running")
224
+ return false;
225
+ try {
226
+ const manifest = readRunManifest(packageRoot, stateRoot, runId);
227
+ assertRunManifestLedgerBinding(ledger, manifest);
228
+ }
229
+ catch (error) {
230
+ const intent = intents.find((candidate) => candidate.expected_run_id === runId);
231
+ if (!intent)
232
+ throw error;
233
+ assertRunLedgerMatchesStartIntent(ledger, intent);
234
+ }
235
+ return true;
236
+ });
237
+ if (activeRunIds.length > 1)
238
+ throw new Error("multiple active runs block controller recovery audit projection");
239
+ const runId = activeRunIds[0];
240
+ if (runId) {
241
+ appendRunAuditEvent(ledger, {
242
+ runId,
243
+ operationId: createStableId("run-ctl-recov", runId, recovered.generation_id),
244
+ entryKind: "controller-lock-recovered",
245
+ payload: {
246
+ lock_id: recovered.lock_id,
247
+ generation_id: recovered.generation_id,
248
+ recovered_by: recovered.recovered_by,
249
+ recovery_evidence_path: recovered.recoveryEvidencePath,
250
+ },
251
+ });
252
+ }
253
+ });
254
+ return Object.freeze({
255
+ recovered: true,
256
+ lock_id: "run-controller",
257
+ generation_id: recovered.generation_id,
258
+ recovered_by: recovered.recovered_by,
259
+ previous_process_id: recovered.previousOwner.process_id,
260
+ recovery_evidence_path: recovered.recoveryEvidencePath,
261
+ });
262
+ }
263
+ function assertRunLedgerMatchesStartIntent(ledger, intent) {
264
+ const first = ledger.list(intent.expected_run_id)[0];
265
+ if (!first
266
+ || first.entry_kind !== "run-started"
267
+ || first.run_id !== intent.expected_run_id
268
+ || first.operation_id !== intent.operation_id
269
+ || first.run_kind !== intent.run_kind
270
+ || first.policy_sha256 !== intent.policy_digest
271
+ || first.payload.ticket_set_digest !== intent.ticket_set_digest
272
+ || first.payload.service_plan_digest !== intent.service_plan_digest) {
273
+ throw new Error(`active run ledger does not match its outstanding start intent: ${intent.expected_run_id}`);
274
+ }
275
+ }
276
+ export function readRunStatus(options) {
277
+ const runtime = createEnduranceAuthorities(options);
278
+ try {
279
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, options.runId);
280
+ assertRunCurrentAuthority(manifest, options.configRoot);
281
+ const metrics = currentMetrics(runtime.auditLedger, manifest);
282
+ validateTerminal(runtime, manifest, metrics, options.packageRoot);
283
+ return buildStatus(runtime.tickets.queue.list(), manifest, metrics);
284
+ }
285
+ finally {
286
+ runtime.close();
287
+ }
288
+ }
289
+ export function listRunStatuses(options) {
290
+ const root = openStableDirectory(join(options.stateRoot, "run-manifests"), "run manifests root");
291
+ try {
292
+ const runIds = readdirSync(root.path, { withFileTypes: true }).map((entry) => {
293
+ if (!entry.isFile() || !/^run-[a-f0-9]{48}\.json$/.test(entry.name))
294
+ throw new Error(`unsafe run manifest entry: ${entry.name}`);
295
+ return entry.name.slice(0, -5);
296
+ }).sort(compareText);
297
+ root.assertUnchanged();
298
+ return Object.freeze(runIds.map((runId) => readRunStatus({ ...options, runId })));
299
+ }
300
+ finally {
301
+ root.close();
302
+ }
303
+ }
304
+ export function assertRunTicketAdmission(options) {
305
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, options.runId);
306
+ assertRunCurrentAuthority(manifest, options.configRoot);
307
+ const ledger = createLiveRunLedger({
308
+ ledgerRoot: join(options.stateRoot, "audit"),
309
+ locksRoot: join(options.stateRoot, "locks"),
310
+ packageRoot: options.packageRoot,
311
+ });
312
+ assertActiveManifestRun(ledger, manifest);
313
+ const snapshot = snapshotFor(manifest, options.ticket.record_id);
314
+ assertTicketMatchesAdmission(options.ticket, snapshot, manifest);
315
+ const gate = Object.freeze({
316
+ [RUN_TICKET_ADMISSION]: true,
317
+ run_id: manifest.run_id,
318
+ ticket_id: options.ticket.record_id,
319
+ manifest_id: manifest.manifest_id,
320
+ });
321
+ RUN_TICKET_ADMISSIONS.add(gate);
322
+ return gate;
323
+ }
324
+ export function findActiveRunTicketAdmission(options) {
325
+ const root = openStableDirectory(join(options.stateRoot, "run-manifests"), "run manifests root");
326
+ let runIds;
327
+ try {
328
+ runIds = Object.freeze(readdirSync(root.path, { withFileTypes: true }).map((entry) => {
329
+ if (!entry.isFile() || !/^run-[a-f0-9]{48}\.json$/.test(entry.name)) {
330
+ throw new Error(`unsafe run manifest entry: ${entry.name}`);
331
+ }
332
+ return entry.name.slice(0, -5);
333
+ }).sort(compareText));
334
+ root.assertUnchanged();
335
+ }
336
+ finally {
337
+ root.close();
338
+ }
339
+ const ledger = createLiveRunLedger({
340
+ ledgerRoot: join(options.stateRoot, "audit"),
341
+ locksRoot: join(options.stateRoot, "locks"),
342
+ packageRoot: options.packageRoot,
343
+ });
344
+ const active = runIds.filter((runId) => {
345
+ const manifest = readRunManifest(options.packageRoot, options.stateRoot, runId);
346
+ if (!manifest.selected_ticket_ids.includes(options.ticket.record_id))
347
+ return false;
348
+ const head = ledger.head(runId);
349
+ if (!head)
350
+ throw new Error(`run manifest has no audit ledger: ${runId}`);
351
+ return ledger.deriveMetrics(head).status === "running";
352
+ });
353
+ if (active.length > 1)
354
+ throw new Error(`ticket belongs to multiple active audit runs: ${options.ticket.record_id}`);
355
+ const runId = active[0];
356
+ return runId === undefined ? null : assertRunTicketAdmission({ ...options, runId });
357
+ }
358
+ export function assertRunCurrentAuthority(manifest, configRoot) {
359
+ const policyDigest = loadTrackedRolePolicyGate(configRoot).digest;
360
+ const verificationGateDigest = freezeTrackedVerificationPlan(configRoot).digest;
361
+ if (manifest.policy_digest !== policyDigest || manifest.verification_gate_digest !== verificationGateDigest) {
362
+ throw new Error(`audit run authority is stale under the current policy or verification gate: ${manifest.run_id}`);
363
+ }
364
+ }
365
+ export function assertRunTicketAdmissionGate(value) {
366
+ if (typeof value !== "object" || value === null || !RUN_TICKET_ADMISSIONS.has(value)) {
367
+ throw new Error("run-bound ticket work requires a real OMS admission gate");
368
+ }
369
+ if (!Object.isFrozen(value))
370
+ throw new Error("run ticket admission gate lost its boundary");
371
+ }
372
+ /**
373
+ * Appends one audit-only event while preserving process continuity across
374
+ * short-lived CLI invocations. The head compare-and-swap keeps a restart
375
+ * marker adjacent to the first event from its process.
376
+ */
377
+ export function appendRunAuditEvent(ledger, input) {
378
+ const rawEntryKind = input.entryKind;
379
+ if (rawEntryKind === "process-restarted" || rawEntryKind === "run-completed" || rawEntryKind === "run-aborted") {
380
+ throw new Error("run process continuity and terminal entries are controller-managed");
381
+ }
382
+ const processInstanceId = currentProcessInstanceId();
383
+ for (let attempt = 0; attempt < 64; attempt += 1) {
384
+ let head = ledger.head(input.runId);
385
+ if (!head)
386
+ throw new Error(`audit run does not exist: ${input.runId}`);
387
+ let entry = ledger.read(head);
388
+ if (entry.process_instance_id !== processInstanceId) {
389
+ try {
390
+ ledger.appendAtHead({
391
+ runId: input.runId,
392
+ operationId: createStableId("run-process", input.runId, processInstanceId, head.sha256, input.operationId),
393
+ entryKind: "process-restarted",
394
+ payload: {
395
+ previous_process_instance_id: entry.process_instance_id,
396
+ next_operation_id: input.operationId,
397
+ },
398
+ expectedHeadSha256: head.sha256,
399
+ });
400
+ }
401
+ catch (error) {
402
+ if (isHeadRace(error))
403
+ continue;
404
+ throw error;
405
+ }
406
+ }
407
+ head = ledger.head(input.runId);
408
+ if (!head)
409
+ throw new Error(`audit run does not exist: ${input.runId}`);
410
+ entry = ledger.read(head);
411
+ if (entry.process_instance_id !== processInstanceId)
412
+ continue;
413
+ try {
414
+ return ledger.appendAtHead({ ...input, expectedHeadSha256: head.sha256 });
415
+ }
416
+ catch (error) {
417
+ if (isHeadRace(error))
418
+ continue;
419
+ throw error;
420
+ }
421
+ }
422
+ throw new Error(`run audit head remained contended: ${input.runId}`);
423
+ }
424
+ function appendRunTerminalEvent(ledger, writer, input) {
425
+ const processInstanceId = currentProcessInstanceId();
426
+ for (let attempt = 0; attempt < 64; attempt += 1) {
427
+ let head = ledger.head(input.runId);
428
+ if (!head)
429
+ throw new Error(`audit run does not exist: ${input.runId}`);
430
+ let entry = ledger.read(head);
431
+ if (entry.process_instance_id !== processInstanceId) {
432
+ appendRunAuditEvent(ledger, {
433
+ runId: input.runId,
434
+ operationId: createStableId("run-term-bound", input.operationId, String(attempt)),
435
+ entryKind: "heartbeat",
436
+ payload: { terminal_operation_id: input.operationId },
437
+ });
438
+ }
439
+ head = ledger.head(input.runId);
440
+ if (!head)
441
+ throw new Error(`audit run does not exist: ${input.runId}`);
442
+ entry = ledger.read(head);
443
+ if (entry.process_instance_id !== processInstanceId)
444
+ continue;
445
+ try {
446
+ return writer.appendAtHead({ ...input, expectedHeadSha256: head.sha256 });
447
+ }
448
+ catch (error) {
449
+ if (isHeadRace(error))
450
+ continue;
451
+ throw error;
452
+ }
453
+ }
454
+ throw new Error(`run terminal head remained contended: ${input.runId}`);
455
+ }
456
+ export function readRunManifest(packageRoot, stateRoot, runId) {
457
+ if (!/^run-[a-f0-9]{48}$/.test(runId))
458
+ throw new Error("invalid audit run id");
459
+ const manifest = readControlJson(join(stateRoot, "run-manifests"), `${runId}.json`, "run manifests root", (value) => parseManifest(value, packageRoot));
460
+ if (manifest.run_id !== runId || manifest.state_root !== stateRoot)
461
+ throw new Error("run manifest identity mismatch");
462
+ const intent = readStartIntent(packageRoot, stateRoot, manifest.start_intent_id);
463
+ if (!manifestMatchesIntent(manifest, intent))
464
+ throw new Error("run manifest does not match its immutable start intent");
465
+ verifyPersistedServicePlan({
466
+ packageRoot,
467
+ directory: manifest.service_plan_directory,
468
+ expectedDigest: manifest.service_plan_digest,
469
+ stateRoot: manifest.state_root,
470
+ workspaceRoot: manifest.workspace_root,
471
+ executablePath: intent.executable_path,
472
+ manager: intent.manager,
473
+ });
474
+ return manifest;
475
+ }
476
+ function createStartIntent(options) {
477
+ const generated = generateServicePlan({
478
+ manager: options.manager,
479
+ executablePath: options.executablePath,
480
+ stateRoot: options.stateRoot,
481
+ workspaceRoot: options.workspaceRoot,
482
+ packageRoot: options.packageRoot,
483
+ });
484
+ const persisted = persistServicePlan({ generated, outputRoot: join(options.stateRoot, "service-plans") });
485
+ const ticketSnapshot = captureTicketSnapshot(options.tickets);
486
+ const ticketSetDigest = sha256(JSON.stringify(ticketSnapshot));
487
+ const verificationGateDigest = freezeTrackedVerificationPlan(options.configRoot).digest;
488
+ const startNonce = randomUUID().toLowerCase();
489
+ const operationId = createStableId("run-start", startNonce, options.runKind, options.policyDigest, verificationGateDigest, ticketSetDigest, generated.digest);
490
+ const intent = parseStartIntent({
491
+ schema_version: 1,
492
+ intent_id: createStableId("run-intent", operationId),
493
+ operation_id: operationId,
494
+ start_nonce: startNonce,
495
+ expected_run_id: createStableId("run", operationId),
496
+ run_kind: options.runKind,
497
+ manager: options.manager,
498
+ executable_path: options.executablePath,
499
+ created_at: systemClockSample().wallTime,
500
+ policy_digest: options.policyDigest,
501
+ verification_gate_digest: verificationGateDigest,
502
+ ticket_set_digest: ticketSetDigest,
503
+ service_plan_digest: generated.digest,
504
+ service_plan_directory: persisted.directory,
505
+ state_root: options.stateRoot,
506
+ workspace_root: options.workspaceRoot,
507
+ ticket_snapshot: ticketSnapshot,
508
+ }, options.packageRoot);
509
+ writeControlFile(join(options.stateRoot, "run-start-intents"), `${intent.intent_id}.json`, canonicalBytes(intent), "run start intents root");
510
+ return readStartIntent(options.packageRoot, options.stateRoot, intent.intent_id);
511
+ }
512
+ function assertStartRequestMatches(intent, request, policyDigest, configRoot) {
513
+ if (intent.run_kind !== request.runKind
514
+ || intent.manager !== request.manager
515
+ || intent.executable_path !== request.executablePath
516
+ || intent.state_root !== request.stateRoot
517
+ || intent.workspace_root !== request.workspaceRoot) {
518
+ throw new Error(`another audit run is already active or has an outstanding start: ${intent.expected_run_id}`);
519
+ }
520
+ if (intent.policy_digest !== policyDigest || intent.verification_gate_digest !== freezeTrackedVerificationPlan(configRoot).digest) {
521
+ throw new Error("outstanding audit run intent belongs to stale policy");
522
+ }
523
+ return intent;
524
+ }
525
+ function listStartIntents(packageRoot, stateRoot) {
526
+ const root = openStableDirectory(join(stateRoot, "run-start-intents"), "run start intents root");
527
+ try {
528
+ const intents = readdirSync(root.path, { withFileTypes: true }).map((entry) => {
529
+ if (!entry.isFile() || !/^run-intent-[a-f0-9]{48}\.json$/.test(entry.name))
530
+ throw new Error(`unsafe run start intent entry: ${entry.name}`);
531
+ return parseStartIntent(JSON.parse(readImmutableFile(join(root.path, entry.name), MAX_CONTROL_BYTES).toString("utf8")), packageRoot);
532
+ }).sort((left, right) => compareText(left.intent_id, right.intent_id));
533
+ root.assertUnchanged();
534
+ return Object.freeze(intents);
535
+ }
536
+ finally {
537
+ root.close();
538
+ }
539
+ }
540
+ function outstandingStartIntents(ledger, intents) {
541
+ return intents.filter((intent) => {
542
+ const head = ledger.head(intent.expected_run_id);
543
+ return !head || ledger.deriveMetrics(head).status === "running";
544
+ });
545
+ }
546
+ function readStartIntent(packageRoot, stateRoot, intentId) {
547
+ if (!/^run-intent-[a-f0-9]{48}$/.test(intentId))
548
+ throw new Error("invalid run start intent id");
549
+ return readControlJson(join(stateRoot, "run-start-intents"), `${intentId}.json`, "run start intents root", (value) => parseStartIntent(value, packageRoot));
550
+ }
551
+ function parseStartIntent(value, packageRoot) {
552
+ assertSchema(value, loadJsonSchema(join(packageRoot, "schemas", "run-start-intent.schema.json")), "run start intent");
553
+ const intent = structuredClone(value);
554
+ validateTicketSnapshot(intent.ticket_snapshot, intent.ticket_set_digest);
555
+ const expectedOperationId = createStableId("run-start", intent.start_nonce, intent.run_kind, intent.policy_digest, intent.verification_gate_digest, intent.ticket_set_digest, intent.service_plan_digest);
556
+ if (intent.operation_id !== expectedOperationId
557
+ || intent.intent_id !== createStableId("run-intent", intent.operation_id)
558
+ || intent.expected_run_id !== createStableId("run", intent.operation_id))
559
+ throw new Error("run start intent identity is invalid");
560
+ if (basename(intent.service_plan_directory) !== intent.service_plan_digest)
561
+ throw new Error("run start intent service directory is invalid");
562
+ return deepFreeze(intent);
563
+ }
564
+ function manifestFromIntent(intent, createdAt) {
565
+ return deepFreeze({
566
+ schema_version: 1,
567
+ manifest_id: createStableId("manifest", intent.expected_run_id),
568
+ run_id: intent.expected_run_id,
569
+ run_kind: intent.run_kind,
570
+ start_intent_id: intent.intent_id,
571
+ created_at: createdAt,
572
+ policy_digest: intent.policy_digest,
573
+ verification_gate_digest: intent.verification_gate_digest,
574
+ ticket_set_digest: intent.ticket_set_digest,
575
+ service_plan_digest: intent.service_plan_digest,
576
+ service_plan_directory: intent.service_plan_directory,
577
+ state_root: intent.state_root,
578
+ workspace_root: intent.workspace_root,
579
+ selected_ticket_ids: intent.ticket_snapshot.map((ticket) => ticket.ticket_id),
580
+ ticket_snapshot: intent.ticket_snapshot,
581
+ provider_started: false,
582
+ manual_conductor_start_required: true,
583
+ certifying: false,
584
+ release: "not_stable",
585
+ merge_disposition: "human_hold",
586
+ });
587
+ }
588
+ function persistManifest(value, packageRoot, stateRoot) {
589
+ const manifest = parseManifest(value, packageRoot);
590
+ writeControlFile(join(stateRoot, "run-manifests"), `${manifest.run_id}.json`, canonicalBytes(manifest), "run manifests root");
591
+ return readRunManifest(packageRoot, stateRoot, manifest.run_id);
592
+ }
593
+ function parseManifest(value, packageRoot) {
594
+ assertSchema(value, loadJsonSchema(join(packageRoot, "schemas", "run-manifest.schema.json")), "run manifest");
595
+ const manifest = structuredClone(value);
596
+ if (manifest.manifest_id !== createStableId("manifest", manifest.run_id))
597
+ throw new Error("run manifest id is invalid");
598
+ validateTicketSnapshot(manifest.ticket_snapshot, manifest.ticket_set_digest);
599
+ if (manifest.selected_ticket_ids.join("\0") !== manifest.ticket_snapshot.map((ticket) => ticket.ticket_id).join("\0")) {
600
+ throw new Error("run manifest selected tickets do not match its admission snapshot");
601
+ }
602
+ if (basename(manifest.service_plan_directory) !== manifest.service_plan_digest)
603
+ throw new Error("run manifest service directory is invalid");
604
+ return deepFreeze(manifest);
605
+ }
606
+ function manifestMatchesIntent(manifest, intent) {
607
+ return manifest.run_id === intent.expected_run_id
608
+ && manifest.run_kind === intent.run_kind
609
+ && manifest.start_intent_id === intent.intent_id
610
+ && manifest.policy_digest === intent.policy_digest
611
+ && manifest.verification_gate_digest === intent.verification_gate_digest
612
+ && manifest.ticket_set_digest === intent.ticket_set_digest
613
+ && manifest.service_plan_digest === intent.service_plan_digest
614
+ && manifest.service_plan_directory === intent.service_plan_directory
615
+ && manifest.state_root === intent.state_root
616
+ && manifest.workspace_root === intent.workspace_root
617
+ && JSON.stringify(manifest.ticket_snapshot) === JSON.stringify(intent.ticket_snapshot);
618
+ }
619
+ function captureTicketSnapshot(tickets) {
620
+ return Object.freeze(tickets.filter((ticket) => ticket.state !== "completed").sort((left, right) => compareText(left.record_id, right.record_id)).map((ticket) => {
621
+ if (ticket.state === "completed")
622
+ throw new Error("completed ticket escaped run admission filtering");
623
+ return Object.freeze({
624
+ ticket_id: ticket.record_id,
625
+ initial_version: ticket.version,
626
+ initial_attempt: ticket.attempt,
627
+ initial_state: ticket.state,
628
+ source_ref_sha256: ticket.payload.source_ref_sha256,
629
+ content_sha256: ticket.payload.content_sha256,
630
+ policy_version: ticket.payload.policy_version,
631
+ policy_digest: ticket.payload.policy_digest,
632
+ gate_digest: ticket.payload.gate_digest,
633
+ });
634
+ }));
635
+ }
636
+ function validateTicketSnapshot(snapshot, expectedDigest) {
637
+ const ids = snapshot.map((ticket) => ticket.ticket_id);
638
+ if (ids.join("\0") !== [...ids].sort(compareText).join("\0") || new Set(ids).size !== ids.length) {
639
+ throw new Error("run ticket admissions must be sorted and unique");
640
+ }
641
+ if (sha256(JSON.stringify(snapshot)) !== expectedDigest)
642
+ throw new Error("run ticket admission digest is invalid");
643
+ }
644
+ function buildConductorRoute(tickets, manifest) {
645
+ const admitted = new Set(manifest.selected_ticket_ids);
646
+ const outside = tickets.filter((ticket) => ticket.state !== "completed" && !admitted.has(ticket.record_id))
647
+ .sort((left, right) => compareText(left.record_id, right.record_id))[0];
648
+ if (outside)
649
+ return routeForTicket(manifest, outside, "human-hold", "canonical queue contains an unresolved ticket outside the frozen run admission", false);
650
+ const unresolved = manifest.selected_ticket_ids.map((ticketId) => requiredTicket(tickets, ticketId))
651
+ .filter((ticket) => ticket.state !== "completed")
652
+ .sort((left, right) => compareText(left.record_id, right.record_id));
653
+ const ticket = unresolved[0];
654
+ if (!ticket)
655
+ return routeForEmpty(manifest);
656
+ const snapshot = snapshotFor(manifest, ticket.record_id);
657
+ try {
658
+ assertTicketMatchesAdmission(ticket, snapshot, manifest);
659
+ }
660
+ catch {
661
+ return routeForTicket(manifest, ticket, "human-hold", "ticket identity drifted from the frozen run admission", false);
662
+ }
663
+ const action = ticket.state === "blocked"
664
+ ? "human-hold"
665
+ : ticket.state === "parked"
666
+ ? "wait-resume"
667
+ : ticket.state === "pending" || ticket.state === "retryable"
668
+ ? "human-start-required"
669
+ : "await-native-hook";
670
+ const reason = action === "human-hold"
671
+ ? "ticket is blocked and requires operator review"
672
+ : action === "wait-resume"
673
+ ? "ticket is parked until its durable resume gate opens"
674
+ : action === "human-start-required"
675
+ ? "shipped provider roles require an explicit human start"
676
+ : "ticket is active; wait for its native hook or deterministic evidence";
677
+ return routeForTicket(manifest, ticket, action, reason, true);
678
+ }
679
+ function routeForTicket(manifest, ticket, action, reason, admitted) {
680
+ if (ticket.state === "completed")
681
+ throw new Error("completed ticket cannot produce a conductor route");
682
+ const decisionId = createStableId("decision", manifest.run_id, ticket.record_id, String(ticket.version), String(ticket.attempt), ticket.state, action, ticket.payload.content_sha256, ticket.payload.policy_digest, ticket.payload.gate_digest ?? "gate:null");
683
+ return deepFreeze({
684
+ schema_version: 1,
685
+ decision_id: decisionId,
686
+ operation_nonce: createStableId("route", decisionId),
687
+ run_id: manifest.run_id,
688
+ ticket_id: ticket.record_id,
689
+ ticket_version: ticket.version,
690
+ ticket_attempt: ticket.attempt,
691
+ ticket_state: ticket.state,
692
+ policy_digest: ticket.payload.policy_digest,
693
+ gate_digest: ticket.payload.gate_digest,
694
+ action,
695
+ eligible_role_ids: action === "human-start-required" ? ["oms.ticket-executor", "oms.goal-long-executor"] : [],
696
+ evidence_paths: admitted ? evidencePaths(manifest.state_root, ticket) : [],
697
+ manual_start_required: action === "human-start-required",
698
+ provider_started: false,
699
+ reason,
700
+ });
701
+ }
702
+ function routeForEmpty(manifest) {
703
+ const decisionId = createStableId("decision", manifest.run_id, "queue-empty", manifest.ticket_set_digest);
704
+ return deepFreeze({
705
+ schema_version: 1,
706
+ decision_id: decisionId,
707
+ operation_nonce: createStableId("route", decisionId),
708
+ run_id: manifest.run_id,
709
+ ticket_id: null,
710
+ ticket_version: null,
711
+ ticket_attempt: null,
712
+ ticket_state: null,
713
+ policy_digest: manifest.policy_digest,
714
+ gate_digest: null,
715
+ action: "queue-empty",
716
+ eligible_role_ids: [],
717
+ evidence_paths: [],
718
+ manual_start_required: false,
719
+ provider_started: false,
720
+ reason: "the canonical queue is empty for this run admission watermark",
721
+ });
722
+ }
723
+ function assertTicketMatchesAdmission(ticket, snapshot, manifest) {
724
+ const allowedGate = ticket.payload.gate_digest === snapshot.gate_digest
725
+ || (snapshot.gate_digest === null && ticket.payload.gate_digest === manifest.verification_gate_digest);
726
+ if (ticket.record_id !== snapshot.ticket_id
727
+ || ticket.version < snapshot.initial_version
728
+ || ticket.attempt < snapshot.initial_attempt
729
+ || ticket.payload.source_ref_sha256 !== snapshot.source_ref_sha256
730
+ || ticket.payload.content_sha256 !== snapshot.content_sha256
731
+ || ticket.payload.policy_version !== snapshot.policy_version
732
+ || ticket.payload.policy_digest !== snapshot.policy_digest
733
+ || ticket.payload.policy_digest !== manifest.policy_digest
734
+ || !allowedGate)
735
+ throw new Error("ticket no longer matches its run admission snapshot");
736
+ }
737
+ function projectTicketStates(ledger, manifest, tickets) {
738
+ for (const snapshot of manifest.ticket_snapshot) {
739
+ const ticket = requiredTicket(tickets, snapshot.ticket_id);
740
+ try {
741
+ assertTicketMatchesAdmission(ticket, snapshot, manifest);
742
+ }
743
+ catch {
744
+ continue;
745
+ }
746
+ appendRunAuditEvent(ledger, {
747
+ runId: manifest.run_id,
748
+ operationId: createStableId("run-ticket", ticket.record_id, String(ticket.version)),
749
+ entryKind: "ticket-transition",
750
+ payload: {
751
+ ticket_id: ticket.record_id,
752
+ version: ticket.version,
753
+ attempt: ticket.attempt,
754
+ state: ticket.state,
755
+ actor: ticket.actor,
756
+ lease_token: ticket.lease_token,
757
+ executor_evidence: ticket.payload.executor_evidence,
758
+ verification_evidence: ticket.payload.verification_evidence,
759
+ grade_evidence: ticket.payload.grade_evidence,
760
+ },
761
+ });
762
+ }
763
+ }
764
+ function recordControllerObservation(ledger, manifest, purpose) {
765
+ const sample = systemClockSample();
766
+ appendRunAuditEvent(ledger, {
767
+ runId: manifest.run_id,
768
+ operationId: createStableId("run-observe", manifest.run_id, purpose, currentProcessInstanceId(), sample.monotonicNs.toString()),
769
+ entryKind: "heartbeat",
770
+ payload: { manifest_id: manifest.manifest_id, purpose },
771
+ });
772
+ }
773
+ function completeAuditRun(runtime, manifest, mode, minimumDurationMs, packageRoot) {
774
+ const tickets = runtime.tickets.queue.list();
775
+ if (buildConductorRoute(tickets, manifest).action !== "queue-empty")
776
+ throw new Error("run cannot complete while the canonical queue is unresolved");
777
+ const proof = persistCompletionProof(buildCompletionProof(manifest, tickets), runtime.tickets.evidenceStore, manifest, packageRoot, tickets);
778
+ appendRunTerminalEvent(runtime.auditLedger, createAuditRunTerminalWriter(runtime.auditLedger), {
779
+ runId: manifest.run_id,
780
+ operationId: createStableId("run-complete", manifest.run_id, mode),
781
+ entryKind: "run-completed",
782
+ payload: {
783
+ manifest_id: manifest.manifest_id,
784
+ ticket_set_digest: manifest.ticket_set_digest,
785
+ completion_mode: mode,
786
+ minimum_duration_ms: minimumDurationMs,
787
+ completion_proof: proof,
788
+ queue_empty: true,
789
+ certifying: false,
790
+ },
791
+ });
792
+ }
793
+ function buildCompletionProof(manifest, queue) {
794
+ const selected = manifest.selected_ticket_ids.map((ticketId) => requiredTicket(queue, ticketId));
795
+ for (const ticket of selected) {
796
+ const snapshot = snapshotFor(manifest, ticket.record_id);
797
+ assertTicketMatchesAdmission(ticket, snapshot, manifest);
798
+ if (ticket.state !== "completed" || ticket.payload.verification_evidence === null || ticket.payload.grade_evidence === null) {
799
+ throw new Error(`run completion requires terminal deterministic and grader evidence: ${ticket.record_id}`);
800
+ }
801
+ }
802
+ const queueWatermark = queue.map((ticket) => ({
803
+ ticket_id: ticket.record_id,
804
+ version: ticket.version,
805
+ state: ticket.state,
806
+ content_sha256: ticket.payload.content_sha256,
807
+ })).sort((left, right) => compareText(left.ticket_id, right.ticket_id));
808
+ const tickets = selected.map((ticket) => ({
809
+ ticket_id: ticket.record_id,
810
+ version: ticket.version,
811
+ attempt: ticket.attempt,
812
+ verification_evidence: ticket.payload.verification_evidence,
813
+ grade_evidence: ticket.payload.grade_evidence,
814
+ }));
815
+ const completedAt = systemClockSample().wallTime;
816
+ const queueWatermarkSha256 = sha256(JSON.stringify(queueWatermark));
817
+ return deepFreeze({
818
+ schema_version: 1,
819
+ proof_id: createStableId("run-proof", manifest.run_id, manifest.ticket_set_digest, queueWatermarkSha256, JSON.stringify(tickets), completedAt),
820
+ run_id: manifest.run_id,
821
+ manifest_id: manifest.manifest_id,
822
+ completed_at: completedAt,
823
+ ticket_set_digest: manifest.ticket_set_digest,
824
+ queue_watermark_sha256: queueWatermarkSha256,
825
+ tickets,
826
+ certifying: false,
827
+ });
828
+ }
829
+ function persistCompletionProof(proofValue, evidenceStore, manifest, packageRoot, queue) {
830
+ const proof = parseCompletionProof(proofValue, manifest, evidenceStore, packageRoot, queue);
831
+ const bytes = canonicalBytes(proof);
832
+ const ref = Object.freeze({
833
+ proof_id: proof.proof_id,
834
+ sha256: sha256(bytes),
835
+ file_name: `${proof.proof_id}.json`,
836
+ });
837
+ writeControlFile(join(manifest.state_root, "run-completion-proofs"), ref.file_name, bytes, "run completion proofs root");
838
+ readCompletionProof(ref, manifest, evidenceStore, packageRoot, queue);
839
+ return ref;
840
+ }
841
+ function readCompletionProof(referenceValue, manifest, evidenceStore, packageRoot, queue) {
842
+ const reference = parseCompletionProofReference(referenceValue);
843
+ const bytes = readControlBytes(join(manifest.state_root, "run-completion-proofs"), reference.file_name, "run completion proofs root");
844
+ if (sha256(bytes) !== reference.sha256)
845
+ throw new Error("run completion proof digest mismatch");
846
+ const proof = parseCompletionProof(JSON.parse(bytes.toString("utf8")), manifest, evidenceStore, packageRoot, queue);
847
+ if (proof.proof_id !== reference.proof_id)
848
+ throw new Error("run completion proof identity mismatch");
849
+ return proof;
850
+ }
851
+ function parseCompletionProofReference(value) {
852
+ if (!isRecord(value))
853
+ throw new Error("run completion proof reference must be an object");
854
+ assertExactKeys(value, ["proof_id", "sha256", "file_name"], "run completion proof reference");
855
+ if (typeof value.proof_id !== "string"
856
+ || !/^run-proof-[a-f0-9]{48}$/.test(value.proof_id)
857
+ || typeof value.sha256 !== "string"
858
+ || !/^[a-f0-9]{64}$/.test(value.sha256)
859
+ || value.file_name !== `${value.proof_id}.json`) {
860
+ throw new Error("run completion proof reference identity is invalid");
861
+ }
862
+ return Object.freeze({
863
+ proof_id: value.proof_id,
864
+ sha256: value.sha256,
865
+ file_name: value.file_name,
866
+ });
867
+ }
868
+ function parseCompletionProof(value, manifest, evidenceStore, packageRoot, queue) {
869
+ assertSchema(value, loadJsonSchema(join(packageRoot, "schemas", "run-completion-proof.schema.json")), "run completion proof");
870
+ const proof = structuredClone(value);
871
+ if (proof.run_id !== manifest.run_id || proof.manifest_id !== manifest.manifest_id || proof.ticket_set_digest !== manifest.ticket_set_digest) {
872
+ throw new Error("run completion proof belongs to a different manifest");
873
+ }
874
+ if (proof.tickets.map((ticket) => ticket.ticket_id).join("\0") !== manifest.selected_ticket_ids.join("\0")) {
875
+ throw new Error("run completion proof ticket set is invalid");
876
+ }
877
+ const expectedId = createStableId("run-proof", manifest.run_id, manifest.ticket_set_digest, proof.queue_watermark_sha256, JSON.stringify(proof.tickets), proof.completed_at);
878
+ if (proof.proof_id !== expectedId)
879
+ throw new Error("run completion proof id is invalid");
880
+ assertCompletionProofMatchesQueue(proof, manifest, queue, evidenceStore);
881
+ return deepFreeze(proof);
882
+ }
883
+ function assertCompletionProofMatchesQueue(proof, manifest, queue, evidenceStore) {
884
+ const queueWatermark = queue.map((ticket) => ({
885
+ ticket_id: ticket.record_id,
886
+ version: ticket.version,
887
+ state: ticket.state,
888
+ content_sha256: ticket.payload.content_sha256,
889
+ })).sort((left, right) => compareText(left.ticket_id, right.ticket_id));
890
+ if (proof.queue_watermark_sha256 !== sha256(JSON.stringify(queueWatermark))) {
891
+ throw new Error("run completion proof queue watermark is stale");
892
+ }
893
+ for (const proofTicket of proof.tickets) {
894
+ const ticket = requiredTicket(queue, proofTicket.ticket_id);
895
+ if (ticket.state !== "completed"
896
+ || ticket.version !== proofTicket.version
897
+ || ticket.attempt !== proofTicket.attempt
898
+ || ticket.payload.verification_evidence === null
899
+ || ticket.payload.grade_evidence === null
900
+ || !sameEvidenceReference(ticket.payload.verification_evidence, proofTicket.verification_evidence)
901
+ || !sameEvidenceReference(ticket.payload.grade_evidence, proofTicket.grade_evidence)) {
902
+ throw new Error(`run completion proof ticket is not the canonical completed record: ${ticket.record_id}`);
903
+ }
904
+ const verification = evidenceStore.read(ticket.payload.verification_evidence);
905
+ const grade = evidenceStore.read(ticket.payload.grade_evidence);
906
+ const attemptLease = [...ticket.transition_outcomes].reverse()
907
+ .find((outcome) => outcome.attempt === ticket.attempt && outcome.lease_token !== null)?.lease_token;
908
+ if (attemptLease === undefined
909
+ || verification.evidence_kind !== "deterministic-check"
910
+ || verification.ticket_id !== ticket.record_id
911
+ || verification.producer_role !== "oms.verifier"
912
+ || verification.payload.certification !== "non-certifying"
913
+ || verification.payload.passed !== true
914
+ || verification.payload.attempt !== ticket.attempt
915
+ || verification.payload.lease_token !== attemptLease
916
+ || verification.payload.policy_version !== ticket.payload.policy_version
917
+ || verification.payload.policy_digest !== ticket.payload.policy_digest
918
+ || verification.payload.plan_digest !== ticket.payload.gate_digest) {
919
+ throw new Error(`run completion proof deterministic verdict is invalid: ${ticket.record_id}`);
920
+ }
921
+ const executor = ticket.payload.executor_evidence === null
922
+ ? null
923
+ : evidenceStore.read(ticket.payload.executor_evidence);
924
+ const expectedGrader = executor?.evidence_kind === "goal-executor-result"
925
+ ? "oms.grader.claude"
926
+ : "oms.grader.codex";
927
+ if (executor === null
928
+ || grade.evidence_kind !== "grader-output"
929
+ || grade.ticket_id !== ticket.record_id
930
+ || grade.producer_role !== expectedGrader
931
+ || grade.payload.verdict !== "pass"
932
+ || !sameEvidenceReference(grade.payload.deterministic_evidence, ticket.payload.verification_evidence)) {
933
+ throw new Error(`run completion proof grader verdict is invalid: ${ticket.record_id}`);
934
+ }
935
+ }
936
+ if (proof.tickets.map((ticket) => ticket.ticket_id).join("\0") !== manifest.selected_ticket_ids.join("\0")) {
937
+ throw new Error("run completion proof no longer matches the admitted ticket set");
938
+ }
939
+ }
940
+ function sameEvidenceReference(left, right) {
941
+ return left !== null
942
+ && right !== null
943
+ && left.evidence_id === right.evidence_id
944
+ && left.sha256 === right.sha256
945
+ && left.file_name === right.file_name;
946
+ }
947
+ function validateTerminal(runtime, manifest, metrics, packageRoot) {
948
+ if (metrics.status === "running")
949
+ return;
950
+ const terminal = runtime.auditLedger.list(manifest.run_id).at(-1);
951
+ if (!terminal)
952
+ throw new Error("terminal audit run has no terminal entry");
953
+ if (terminal.entry_kind === "run-completed") {
954
+ assertExactKeys(terminal.payload, [
955
+ "manifest_id",
956
+ "ticket_set_digest",
957
+ "completion_mode",
958
+ "minimum_duration_ms",
959
+ "completion_proof",
960
+ "queue_empty",
961
+ "certifying",
962
+ ], "run completion payload");
963
+ if (terminal.payload.manifest_id !== manifest.manifest_id
964
+ || terminal.payload.ticket_set_digest !== manifest.ticket_set_digest
965
+ || terminal.payload.queue_empty !== true
966
+ || terminal.payload.certifying !== false)
967
+ throw new Error("run completion payload is not controller-authorized");
968
+ const mode = terminal.payload.completion_mode;
969
+ const minimum = terminal.payload.minimum_duration_ms;
970
+ if (typeof minimum !== "number" || !Number.isSafeInteger(minimum) || minimum < 0) {
971
+ throw new Error("run completion minimum duration is invalid");
972
+ }
973
+ if ((mode === "until-empty" && (manifest.run_kind !== "until-empty" || minimum !== 0))
974
+ || (mode === "elapsed" && (manifest.run_kind === "until-empty" || minimum !== (manifest.run_kind === "12h" ? TWELVE_HOURS_MS : TWENTY_FOUR_HOURS_MS))))
975
+ throw new Error("run completion mode does not match the manifest");
976
+ if (mode === "until-empty" && buildConductorRoute(runtime.tickets.queue.list(), manifest).action !== "queue-empty") {
977
+ throw new Error("terminal until-empty run no longer has an empty canonical queue");
978
+ }
979
+ if (mode === "elapsed"
980
+ && (metrics.elapsed_ms < minimum || metrics.monotonic_elapsed_ms < minimum)) {
981
+ throw new Error("terminal elapsed run does not satisfy its minimum duration");
982
+ }
983
+ readCompletionProof(terminal.payload.completion_proof, manifest, runtime.tickets.evidenceStore, packageRoot, runtime.tickets.queue.list());
984
+ return;
985
+ }
986
+ if (terminal.entry_kind !== "run-aborted")
987
+ throw new Error("run terminal entry is not controller-authorized");
988
+ assertExactKeys(terminal.payload, ["manifest_id", "reason_sha256", "reason_file", "certifying"], "run abort payload");
989
+ if (terminal.payload.manifest_id !== manifest.manifest_id || terminal.payload.certifying !== false) {
990
+ throw new Error("run abort payload is not controller-authorized");
991
+ }
992
+ const bytes = readControlBytes(join(manifest.state_root, "run-aborts"), String(terminal.payload.reason_file), "run aborts root");
993
+ if (sha256(bytes) !== terminal.payload.reason_sha256)
994
+ throw new Error("run abort reason digest mismatch");
995
+ }
996
+ function buildStatus(tickets, manifest, metrics) {
997
+ const selected = manifest.selected_ticket_ids.map((ticketId) => requiredTicket(tickets, ticketId));
998
+ const counts = {};
999
+ for (const ticket of selected)
1000
+ counts[ticket.state] = (counts[ticket.state] ?? 0) + 1;
1001
+ return deepFreeze({
1002
+ manifest,
1003
+ audit: metrics,
1004
+ ticket_counts: Object.fromEntries(Object.entries(counts).sort(([left], [right]) => compareText(left, right))),
1005
+ provider_started: false,
1006
+ certifying: false,
1007
+ release: "not_stable",
1008
+ human_hold: true,
1009
+ next_action: nextAction(tickets, manifest, metrics),
1010
+ });
1011
+ }
1012
+ function nextAction(tickets, manifest, metrics) {
1013
+ if (metrics.status !== "running")
1014
+ return "none";
1015
+ const action = buildConductorRoute(tickets, manifest).action;
1016
+ if (action === "human-hold")
1017
+ return "human-hold";
1018
+ if (action === "wait-resume")
1019
+ return "wait-resume";
1020
+ if (action === "await-native-hook")
1021
+ return "await-native-hook";
1022
+ if (action === "human-start-required")
1023
+ return "manual-conductor";
1024
+ return manifest.run_kind === "until-empty" ? "run-tick" : "observe";
1025
+ }
1026
+ function currentMetrics(ledger, manifest) {
1027
+ const head = ledger.head(manifest.run_id);
1028
+ if (!head)
1029
+ throw new Error(`audit run does not exist: ${manifest.run_id}`);
1030
+ assertRunManifestLedgerBinding(ledger, manifest);
1031
+ return ledger.deriveMetrics(head);
1032
+ }
1033
+ function assertActiveManifestRun(ledger, manifest) {
1034
+ if (currentMetrics(ledger, manifest).status !== "running")
1035
+ throw new Error(`conductor cannot route a terminal run: ${manifest.run_id}`);
1036
+ }
1037
+ export function assertRunManifestLedgerBinding(ledger, manifest) {
1038
+ const first = ledger.list(manifest.run_id)[0];
1039
+ if (!first
1040
+ || first.entry_kind !== "run-started"
1041
+ || first.provenance_class !== "audit"
1042
+ || first.run_kind !== manifest.run_kind
1043
+ || first.policy_sha256 !== manifest.policy_digest
1044
+ || first.payload.ticket_set_digest !== manifest.ticket_set_digest
1045
+ || first.payload.service_plan_digest !== manifest.service_plan_digest)
1046
+ throw new Error("run manifest does not match its audit ledger authority");
1047
+ }
1048
+ function persistDecision(value, packageRoot, stateRoot) {
1049
+ const decision = parseDecision(value, packageRoot);
1050
+ const bytes = canonicalBytes(decision);
1051
+ const fileName = `${decision.decision_id}.json`;
1052
+ const status = writeControlFile(join(stateRoot, "run-decisions"), fileName, bytes, "run decisions root");
1053
+ const stored = readControlJson(join(stateRoot, "run-decisions"), fileName, "run decisions root", (input) => parseDecision(input, packageRoot));
1054
+ return Object.freeze({ status, decision: stored, absolute_path: join(stateRoot, "run-decisions", fileName) });
1055
+ }
1056
+ function parseDecision(value, packageRoot) {
1057
+ assertSchema(value, loadJsonSchema(join(packageRoot, "schemas", "conductor-route.schema.json")), "conductor route");
1058
+ const decision = structuredClone(value);
1059
+ if (decision.operation_nonce !== createStableId("route", decision.decision_id))
1060
+ throw new Error("conductor route nonce is invalid");
1061
+ const empty = decision.action === "queue-empty";
1062
+ if (empty !== (decision.ticket_id === null && decision.ticket_version === null && decision.ticket_attempt === null && decision.ticket_state === null)) {
1063
+ throw new Error("conductor route ticket identity is inconsistent");
1064
+ }
1065
+ if (decision.manual_start_required !== (decision.action === "human-start-required"))
1066
+ throw new Error("conductor route manual-start flag is inconsistent");
1067
+ if (new Set(decision.eligible_role_ids).size !== decision.eligible_role_ids.length || new Set(decision.evidence_paths).size !== decision.evidence_paths.length) {
1068
+ throw new Error("conductor route arrays must be unique");
1069
+ }
1070
+ return deepFreeze(decision);
1071
+ }
1072
+ function evidencePaths(stateRoot, ticket) {
1073
+ const paths = [join(stateRoot, "tickets", ticket.payload.content_file)];
1074
+ for (const reference of [ticket.payload.verification_plan_ref, ticket.payload.executor_evidence, ticket.payload.verification_evidence, ticket.payload.grade_evidence]) {
1075
+ if (reference)
1076
+ paths.push(join(stateRoot, "evidence", reference.file_name));
1077
+ }
1078
+ return Object.freeze([...new Set(paths)].sort(compareText));
1079
+ }
1080
+ function snapshotFor(manifest, ticketId) {
1081
+ const snapshot = manifest.ticket_snapshot.find((ticket) => ticket.ticket_id === ticketId);
1082
+ if (!snapshot)
1083
+ throw new Error(`ticket is not admitted to run: ${ticketId}`);
1084
+ return snapshot;
1085
+ }
1086
+ function requiredTicket(tickets, ticketId) {
1087
+ const ticket = tickets.find((candidate) => candidate.record_id === ticketId);
1088
+ if (!ticket)
1089
+ throw new Error(`run admission ticket is missing: ${ticketId}`);
1090
+ return ticket;
1091
+ }
1092
+ function readControlJson(rootPath, fileName, label, parse) {
1093
+ return parse(JSON.parse(readControlBytes(rootPath, fileName, label).toString("utf8")));
1094
+ }
1095
+ function readControlBytes(rootPath, fileName, label) {
1096
+ if (!/^[a-z0-9][a-z0-9.-]{0,127}$/.test(fileName))
1097
+ throw new Error(`unsafe ${label} file name`);
1098
+ const root = openStableDirectory(rootPath, label);
1099
+ try {
1100
+ const path = join(root.path, fileName);
1101
+ assertFileInside(root, path);
1102
+ const bytes = readImmutableFile(path, MAX_CONTROL_BYTES);
1103
+ root.assertUnchanged();
1104
+ return bytes;
1105
+ }
1106
+ finally {
1107
+ root.close();
1108
+ }
1109
+ }
1110
+ function writeControlFile(rootPath, fileName, bytes, label) {
1111
+ if (!/^[a-z0-9][a-z0-9.-]{0,127}$/.test(fileName))
1112
+ throw new Error(`unsafe ${label} file name`);
1113
+ const root = openStableDirectory(rootPath, label);
1114
+ try {
1115
+ const path = join(root.path, fileName);
1116
+ assertFileInside(root, path);
1117
+ const status = writeImmutableFile(path, bytes);
1118
+ root.assertUnchanged();
1119
+ return status;
1120
+ }
1121
+ finally {
1122
+ root.close();
1123
+ }
1124
+ }
1125
+ export function withRunControllerAuthority(stateRoot, operation) {
1126
+ if (typeof operation !== "function")
1127
+ throw new Error("run controller operation must be a function");
1128
+ const runtimeStateRoot = validateExistingDirectory(stateRoot, "runtime state root");
1129
+ const lock = acquireDirectoryLock({
1130
+ locksRoot: join(runtimeStateRoot, "locks"),
1131
+ lockId: "run-controller",
1132
+ ownerId: "oms-run-controller",
1133
+ note: "serialize run start, terminal proof, and abort authority",
1134
+ });
1135
+ try {
1136
+ return operation();
1137
+ }
1138
+ finally {
1139
+ lock.release();
1140
+ }
1141
+ }
1142
+ function boundedReason(value) {
1143
+ if (typeof value !== "string")
1144
+ throw new Error("run abort reason must be text");
1145
+ const normalized = value.trim();
1146
+ if (normalized.length < 1 || normalized.length > 4096)
1147
+ throw new Error("run abort reason must contain 1 to 4096 characters");
1148
+ return normalized;
1149
+ }
1150
+ function boundedRecoveryReason(value) {
1151
+ const reason = boundedReason(value);
1152
+ if (reason.length > 512)
1153
+ throw new Error("run controller recovery reason must contain 1 to 512 characters");
1154
+ return reason;
1155
+ }
1156
+ function assertExactKeys(value, keys, label) {
1157
+ const expected = [...keys].sort(compareText);
1158
+ const actual = Object.keys(value).sort(compareText);
1159
+ if (actual.join("\0") !== expected.join("\0"))
1160
+ throw new Error(`${label} fields are invalid`);
1161
+ }
1162
+ function isHeadRace(error) {
1163
+ return error instanceof Error && error.message === "run ledger trusted head advanced concurrently";
1164
+ }
1165
+ function canonicalBytes(value) {
1166
+ return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8");
1167
+ }
1168
+ function sha256(value) {
1169
+ return createHash("sha256").update(value).digest("hex");
1170
+ }
1171
+ function compareText(left, right) {
1172
+ return left < right ? -1 : left > right ? 1 : 0;
1173
+ }
1174
+ function deepFreeze(value, seen = new Set()) {
1175
+ if (typeof value !== "object" || value === null || seen.has(value))
1176
+ return value;
1177
+ seen.add(value);
1178
+ for (const child of Object.values(value))
1179
+ deepFreeze(child, seen);
1180
+ return Object.freeze(value);
1181
+ }
1182
+ //# sourceMappingURL=controller.js.map