open-multi-agent-kit 0.98.4 → 0.99.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 (357) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +4 -2
  3. package/dist/cli/help.d.ts.map +1 -1
  4. package/dist/cli/help.js +1 -0
  5. package/dist/cli/help.js.map +1 -1
  6. package/dist/commands/run-command.d.ts +2 -1
  7. package/dist/commands/run-command.d.ts.map +1 -1
  8. package/dist/commands/run-command.js +9 -1
  9. package/dist/commands/run-command.js.map +1 -1
  10. package/dist/commands/verified-run-cli.d.ts +6 -0
  11. package/dist/commands/verified-run-cli.d.ts.map +1 -0
  12. package/dist/commands/verified-run-cli.js +190 -0
  13. package/dist/commands/verified-run-cli.js.map +1 -0
  14. package/dist/core/agent-session-services.d.ts +8 -1
  15. package/dist/core/agent-session-services.d.ts.map +1 -1
  16. package/dist/core/agent-session-services.js +41 -0
  17. package/dist/core/agent-session-services.js.map +1 -1
  18. package/dist/core/agent-session.d.ts +7 -8
  19. package/dist/core/agent-session.d.ts.map +1 -1
  20. package/dist/core/agent-session.js +80 -43
  21. package/dist/core/agent-session.js.map +1 -1
  22. package/dist/core/devin-harness-dispatch.d.ts +12 -0
  23. package/dist/core/devin-harness-dispatch.d.ts.map +1 -0
  24. package/dist/core/devin-harness-dispatch.js +12 -0
  25. package/dist/core/devin-harness-dispatch.js.map +1 -0
  26. package/dist/core/devin-harness.d.ts +53 -0
  27. package/dist/core/devin-harness.d.ts.map +1 -0
  28. package/dist/core/devin-harness.js +112 -0
  29. package/dist/core/devin-harness.js.map +1 -0
  30. package/dist/core/domain-dispatch.d.ts +4 -1
  31. package/dist/core/domain-dispatch.d.ts.map +1 -1
  32. package/dist/core/domain-dispatch.js +5 -0
  33. package/dist/core/domain-dispatch.js.map +1 -1
  34. package/dist/core/domain-loadouts-provider-harness.d.ts +12 -0
  35. package/dist/core/domain-loadouts-provider-harness.d.ts.map +1 -0
  36. package/dist/core/domain-loadouts-provider-harness.js +122 -0
  37. package/dist/core/domain-loadouts-provider-harness.js.map +1 -0
  38. package/dist/core/domain-loadouts.d.ts +2 -33
  39. package/dist/core/domain-loadouts.d.ts.map +1 -1
  40. package/dist/core/domain-loadouts.js +3 -56
  41. package/dist/core/domain-loadouts.js.map +1 -1
  42. package/dist/core/domain-profile.d.ts +40 -0
  43. package/dist/core/domain-profile.d.ts.map +1 -0
  44. package/dist/core/domain-profile.js +7 -0
  45. package/dist/core/domain-profile.js.map +1 -0
  46. package/dist/core/grok-harness-dispatch.d.ts +6 -20
  47. package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
  48. package/dist/core/grok-harness-dispatch.js +6 -55
  49. package/dist/core/grok-harness-dispatch.js.map +1 -1
  50. package/dist/core/grok-harness.d.ts +7 -9
  51. package/dist/core/grok-harness.d.ts.map +1 -1
  52. package/dist/core/grok-harness.js +9 -23
  53. package/dist/core/grok-harness.js.map +1 -1
  54. package/dist/core/harness-skills.d.ts +20 -0
  55. package/dist/core/harness-skills.d.ts.map +1 -0
  56. package/dist/core/harness-skills.js +36 -0
  57. package/dist/core/harness-skills.js.map +1 -0
  58. package/dist/core/loadout-runtime-state.d.ts +25 -0
  59. package/dist/core/loadout-runtime-state.d.ts.map +1 -0
  60. package/dist/core/loadout-runtime-state.js +39 -0
  61. package/dist/core/loadout-runtime-state.js.map +1 -0
  62. package/dist/core/loadout-runtime.d.ts +2 -12
  63. package/dist/core/loadout-runtime.d.ts.map +1 -1
  64. package/dist/core/loadout-runtime.js +6 -13
  65. package/dist/core/loadout-runtime.js.map +1 -1
  66. package/dist/core/model-resolver.d.ts +1 -41
  67. package/dist/core/model-resolver.d.ts.map +1 -1
  68. package/dist/core/model-resolver.js +2 -49
  69. package/dist/core/model-resolver.js.map +1 -1
  70. package/dist/core/prompt-settlement.d.ts +4 -3
  71. package/dist/core/prompt-settlement.d.ts.map +1 -1
  72. package/dist/core/prompt-settlement.js.map +1 -1
  73. package/dist/core/provider-default-models.d.ts +42 -0
  74. package/dist/core/provider-default-models.d.ts.map +1 -0
  75. package/dist/core/provider-default-models.js +50 -0
  76. package/dist/core/provider-default-models.js.map +1 -0
  77. package/dist/core/provider-display-names.d.ts.map +1 -1
  78. package/dist/core/provider-display-names.js +1 -0
  79. package/dist/core/provider-display-names.js.map +1 -1
  80. package/dist/core/provider-harness-dispatch.d.ts +63 -0
  81. package/dist/core/provider-harness-dispatch.d.ts.map +1 -0
  82. package/dist/core/provider-harness-dispatch.js +60 -0
  83. package/dist/core/provider-harness-dispatch.js.map +1 -0
  84. package/dist/core/provider-usage-devin.d.ts +16 -0
  85. package/dist/core/provider-usage-devin.d.ts.map +1 -0
  86. package/dist/core/provider-usage-devin.js +61 -0
  87. package/dist/core/provider-usage-devin.js.map +1 -0
  88. package/dist/core/provider-usage-text.d.ts +5 -0
  89. package/dist/core/provider-usage-text.d.ts.map +1 -0
  90. package/dist/core/provider-usage-text.js +15 -0
  91. package/dist/core/provider-usage-text.js.map +1 -0
  92. package/dist/core/provider-usage-types.d.ts +2 -1
  93. package/dist/core/provider-usage-types.d.ts.map +1 -1
  94. package/dist/core/provider-usage-types.js.map +1 -1
  95. package/dist/core/provider-usage.d.ts +1 -2
  96. package/dist/core/provider-usage.d.ts.map +1 -1
  97. package/dist/core/provider-usage.js +12 -7
  98. package/dist/core/provider-usage.js.map +1 -1
  99. package/dist/core/run-budget-policy.d.ts +18 -0
  100. package/dist/core/run-budget-policy.d.ts.map +1 -0
  101. package/dist/core/run-budget-policy.js +52 -0
  102. package/dist/core/run-budget-policy.js.map +1 -0
  103. package/dist/core/run-budget.d.ts +33 -0
  104. package/dist/core/run-budget.d.ts.map +1 -0
  105. package/dist/core/run-budget.js +89 -0
  106. package/dist/core/run-budget.js.map +1 -0
  107. package/dist/core/run-execution-api.d.ts +15 -0
  108. package/dist/core/run-execution-api.d.ts.map +1 -0
  109. package/dist/core/run-execution-api.js +7 -0
  110. package/dist/core/run-execution-api.js.map +1 -0
  111. package/dist/core/run-journal.d.ts.map +1 -1
  112. package/dist/core/run-journal.js +30 -208
  113. package/dist/core/run-journal.js.map +1 -1
  114. package/dist/core/sdk.d.ts.map +1 -1
  115. package/dist/core/sdk.js +23 -18
  116. package/dist/core/sdk.js.map +1 -1
  117. package/dist/core/session-bash-service.d.ts +2 -2
  118. package/dist/core/session-bash-service.d.ts.map +1 -1
  119. package/dist/core/session-bash-service.js +21 -9
  120. package/dist/core/session-bash-service.js.map +1 -1
  121. package/dist/core/session-failure-cause.d.ts.map +1 -1
  122. package/dist/core/session-failure-cause.js +5 -0
  123. package/dist/core/session-failure-cause.js.map +1 -1
  124. package/dist/core/session-prompt-lifecycle.d.ts +25 -0
  125. package/dist/core/session-prompt-lifecycle.d.ts.map +1 -0
  126. package/dist/core/session-prompt-lifecycle.js +87 -0
  127. package/dist/core/session-prompt-lifecycle.js.map +1 -0
  128. package/dist/core/session-run-budget.d.ts +28 -0
  129. package/dist/core/session-run-budget.d.ts.map +1 -0
  130. package/dist/core/session-run-budget.js +127 -0
  131. package/dist/core/session-run-budget.js.map +1 -0
  132. package/dist/core/session-run-termination.d.ts.map +1 -1
  133. package/dist/core/session-run-termination.js +14 -3
  134. package/dist/core/session-run-termination.js.map +1 -1
  135. package/dist/core/session-termination-types.d.ts +97 -0
  136. package/dist/core/session-termination-types.d.ts.map +1 -0
  137. package/dist/core/session-termination-types.js +26 -0
  138. package/dist/core/session-termination-types.js.map +1 -0
  139. package/dist/core/session-termination.d.ts +3 -97
  140. package/dist/core/session-termination.d.ts.map +1 -1
  141. package/dist/core/session-termination.js +24 -28
  142. package/dist/core/session-termination.js.map +1 -1
  143. package/dist/core/slash-commands.d.ts.map +1 -1
  144. package/dist/core/slash-commands.js +1 -0
  145. package/dist/core/slash-commands.js.map +1 -1
  146. package/dist/core/subagent-lane-launcher.d.ts +3 -2
  147. package/dist/core/subagent-lane-launcher.d.ts.map +1 -1
  148. package/dist/core/subagent-lane-launcher.js +24 -13
  149. package/dist/core/subagent-lane-launcher.js.map +1 -1
  150. package/dist/core/verified-run/broker.d.ts +26 -0
  151. package/dist/core/verified-run/broker.d.ts.map +1 -0
  152. package/dist/core/verified-run/broker.js +210 -0
  153. package/dist/core/verified-run/broker.js.map +1 -0
  154. package/dist/core/verified-run/candidate.d.ts +24 -0
  155. package/dist/core/verified-run/candidate.d.ts.map +1 -0
  156. package/dist/core/verified-run/candidate.js +167 -0
  157. package/dist/core/verified-run/candidate.js.map +1 -0
  158. package/dist/core/verified-run/check-receipt.d.ts +18 -0
  159. package/dist/core/verified-run/check-receipt.d.ts.map +1 -0
  160. package/dist/core/verified-run/check-receipt.js +92 -0
  161. package/dist/core/verified-run/check-receipt.js.map +1 -0
  162. package/dist/core/verified-run/coordinator.d.ts +39 -0
  163. package/dist/core/verified-run/coordinator.d.ts.map +1 -0
  164. package/dist/core/verified-run/coordinator.js +190 -0
  165. package/dist/core/verified-run/coordinator.js.map +1 -0
  166. package/dist/core/verified-run/dag-candidates.d.ts +8 -0
  167. package/dist/core/verified-run/dag-candidates.d.ts.map +1 -0
  168. package/dist/core/verified-run/dag-candidates.js +65 -0
  169. package/dist/core/verified-run/dag-candidates.js.map +1 -0
  170. package/dist/core/verified-run/dag-phase.d.ts +7 -0
  171. package/dist/core/verified-run/dag-phase.d.ts.map +1 -0
  172. package/dist/core/verified-run/dag-phase.js +130 -0
  173. package/dist/core/verified-run/dag-phase.js.map +1 -0
  174. package/dist/core/verified-run/dag-projection.d.ts +7 -0
  175. package/dist/core/verified-run/dag-projection.d.ts.map +1 -0
  176. package/dist/core/verified-run/dag-projection.js +103 -0
  177. package/dist/core/verified-run/dag-projection.js.map +1 -0
  178. package/dist/core/verified-run/dag-recovery.d.ts +13 -0
  179. package/dist/core/verified-run/dag-recovery.d.ts.map +1 -0
  180. package/dist/core/verified-run/dag-recovery.js +98 -0
  181. package/dist/core/verified-run/dag-recovery.js.map +1 -0
  182. package/dist/core/verified-run/dag-retry-projection.d.ts +9 -0
  183. package/dist/core/verified-run/dag-retry-projection.d.ts.map +1 -0
  184. package/dist/core/verified-run/dag-retry-projection.js +43 -0
  185. package/dist/core/verified-run/dag-retry-projection.js.map +1 -0
  186. package/dist/core/verified-run/dag-types.d.ts +58 -0
  187. package/dist/core/verified-run/dag-types.d.ts.map +1 -0
  188. package/dist/core/verified-run/dag-types.js +2 -0
  189. package/dist/core/verified-run/dag-types.js.map +1 -0
  190. package/dist/core/verified-run/event-parser.d.ts +3 -0
  191. package/dist/core/verified-run/event-parser.d.ts.map +1 -0
  192. package/dist/core/verified-run/event-parser.js +154 -0
  193. package/dist/core/verified-run/event-parser.js.map +1 -0
  194. package/dist/core/verified-run/events.d.ts +4 -0
  195. package/dist/core/verified-run/events.d.ts.map +1 -0
  196. package/dist/core/verified-run/events.js +3 -0
  197. package/dist/core/verified-run/events.js.map +1 -0
  198. package/dist/core/verified-run/evidence-binding.d.ts +18 -0
  199. package/dist/core/verified-run/evidence-binding.d.ts.map +1 -0
  200. package/dist/core/verified-run/evidence-binding.js +81 -0
  201. package/dist/core/verified-run/evidence-binding.js.map +1 -0
  202. package/dist/core/verified-run/evidence.d.ts +27 -0
  203. package/dist/core/verified-run/evidence.d.ts.map +1 -0
  204. package/dist/core/verified-run/evidence.js +100 -0
  205. package/dist/core/verified-run/evidence.js.map +1 -0
  206. package/dist/core/verified-run/journal.d.ts +32 -0
  207. package/dist/core/verified-run/journal.d.ts.map +1 -0
  208. package/dist/core/verified-run/journal.js +103 -0
  209. package/dist/core/verified-run/journal.js.map +1 -0
  210. package/dist/core/verified-run/namespace-identity.d.ts +11 -0
  211. package/dist/core/verified-run/namespace-identity.d.ts.map +1 -0
  212. package/dist/core/verified-run/namespace-identity.js +77 -0
  213. package/dist/core/verified-run/namespace-identity.js.map +1 -0
  214. package/dist/core/verified-run/owned-execution.d.ts +22 -0
  215. package/dist/core/verified-run/owned-execution.d.ts.map +1 -0
  216. package/dist/core/verified-run/owned-execution.js +49 -0
  217. package/dist/core/verified-run/owned-execution.js.map +1 -0
  218. package/dist/core/verified-run/phase-context.d.ts +9 -0
  219. package/dist/core/verified-run/phase-context.d.ts.map +1 -0
  220. package/dist/core/verified-run/phase-context.js +2 -0
  221. package/dist/core/verified-run/phase-context.js.map +1 -0
  222. package/dist/core/verified-run/process-gate.d.ts +5 -0
  223. package/dist/core/verified-run/process-gate.d.ts.map +1 -0
  224. package/dist/core/verified-run/process-gate.js +31 -0
  225. package/dist/core/verified-run/process-gate.js.map +1 -0
  226. package/dist/core/verified-run/process-projection.d.ts +13 -0
  227. package/dist/core/verified-run/process-projection.d.ts.map +1 -0
  228. package/dist/core/verified-run/process-projection.js +82 -0
  229. package/dist/core/verified-run/process-projection.js.map +1 -0
  230. package/dist/core/verified-run/projection.d.ts +4 -0
  231. package/dist/core/verified-run/projection.d.ts.map +1 -0
  232. package/dist/core/verified-run/projection.js +175 -0
  233. package/dist/core/verified-run/projection.js.map +1 -0
  234. package/dist/core/verified-run/recovery-clock.d.ts +19 -0
  235. package/dist/core/verified-run/recovery-clock.d.ts.map +1 -0
  236. package/dist/core/verified-run/recovery-clock.js +69 -0
  237. package/dist/core/verified-run/recovery-clock.js.map +1 -0
  238. package/dist/core/verified-run/recovery-command.d.ts +11 -0
  239. package/dist/core/verified-run/recovery-command.d.ts.map +1 -0
  240. package/dist/core/verified-run/recovery-command.js +73 -0
  241. package/dist/core/verified-run/recovery-command.js.map +1 -0
  242. package/dist/core/verified-run/recovery-projection.d.ts +12 -0
  243. package/dist/core/verified-run/recovery-projection.d.ts.map +1 -0
  244. package/dist/core/verified-run/recovery-projection.js +88 -0
  245. package/dist/core/verified-run/recovery-projection.js.map +1 -0
  246. package/dist/core/verified-run/recovery.d.ts +12 -0
  247. package/dist/core/verified-run/recovery.d.ts.map +1 -0
  248. package/dist/core/verified-run/recovery.js +115 -0
  249. package/dist/core/verified-run/recovery.js.map +1 -0
  250. package/dist/core/verified-run/run-types.d.ts +104 -0
  251. package/dist/core/verified-run/run-types.d.ts.map +1 -0
  252. package/dist/core/verified-run/run-types.js +2 -0
  253. package/dist/core/verified-run/run-types.js.map +1 -0
  254. package/dist/core/verified-run/scripted-writer.d.ts +15 -0
  255. package/dist/core/verified-run/scripted-writer.d.ts.map +1 -0
  256. package/dist/core/verified-run/scripted-writer.js +94 -0
  257. package/dist/core/verified-run/scripted-writer.js.map +1 -0
  258. package/dist/core/verified-run/session-port.d.ts +27 -0
  259. package/dist/core/verified-run/session-port.d.ts.map +1 -0
  260. package/dist/core/verified-run/session-port.js +2 -0
  261. package/dist/core/verified-run/session-port.js.map +1 -0
  262. package/dist/core/verified-run/storage.d.ts +15 -0
  263. package/dist/core/verified-run/storage.d.ts.map +1 -0
  264. package/dist/core/verified-run/storage.js +96 -0
  265. package/dist/core/verified-run/storage.js.map +1 -0
  266. package/dist/core/verified-run/task-execution.d.ts +9 -0
  267. package/dist/core/verified-run/task-execution.d.ts.map +1 -0
  268. package/dist/core/verified-run/task-execution.js +29 -0
  269. package/dist/core/verified-run/task-execution.js.map +1 -0
  270. package/dist/core/verified-run/verification-phase.d.ts +5 -0
  271. package/dist/core/verified-run/verification-phase.d.ts.map +1 -0
  272. package/dist/core/verified-run/verification-phase.js +56 -0
  273. package/dist/core/verified-run/verification-phase.js.map +1 -0
  274. package/dist/core/verified-run/work-recovery.d.ts +8 -0
  275. package/dist/core/verified-run/work-recovery.d.ts.map +1 -0
  276. package/dist/core/verified-run/work-recovery.js +44 -0
  277. package/dist/core/verified-run/work-recovery.js.map +1 -0
  278. package/dist/core/verified-run/writer-completion.d.ts +4 -0
  279. package/dist/core/verified-run/writer-completion.d.ts.map +1 -0
  280. package/dist/core/verified-run/writer-completion.js +27 -0
  281. package/dist/core/verified-run/writer-completion.js.map +1 -0
  282. package/dist/core/verified-run/writer-phase.d.ts +8 -0
  283. package/dist/core/verified-run/writer-phase.d.ts.map +1 -0
  284. package/dist/core/verified-run/writer-phase.js +76 -0
  285. package/dist/core/verified-run/writer-phase.js.map +1 -0
  286. package/dist/core/verified-run/writer-projection.d.ts +11 -0
  287. package/dist/core/verified-run/writer-projection.d.ts.map +1 -0
  288. package/dist/core/verified-run/writer-projection.js +71 -0
  289. package/dist/core/verified-run/writer-projection.js.map +1 -0
  290. package/dist/core/verified-run/writer-recovery.d.ts +16 -0
  291. package/dist/core/verified-run/writer-recovery.d.ts.map +1 -0
  292. package/dist/core/verified-run/writer-recovery.js +107 -0
  293. package/dist/core/verified-run/writer-recovery.js.map +1 -0
  294. package/dist/core/workload-permit-pool.d.ts +1 -3
  295. package/dist/core/workload-permit-pool.d.ts.map +1 -1
  296. package/dist/core/workload-permit-pool.js +11 -11
  297. package/dist/core/workload-permit-pool.js.map +1 -1
  298. package/dist/index.d.ts +3 -2
  299. package/dist/index.d.ts.map +1 -1
  300. package/dist/index.js +2 -2
  301. package/dist/index.js.map +1 -1
  302. package/dist/main.d.ts.map +1 -1
  303. package/dist/main.js +2 -8
  304. package/dist/main.js.map +1 -1
  305. package/dist/modes/interactive/components/session-failure.d.ts +13 -0
  306. package/dist/modes/interactive/components/session-failure.d.ts.map +1 -0
  307. package/dist/modes/interactive/components/session-failure.js +81 -0
  308. package/dist/modes/interactive/components/session-failure.js.map +1 -0
  309. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  310. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  311. package/dist/modes/interactive/interactive-mode.js +47 -36
  312. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  313. package/dist/modes/interactive/resource-description.d.ts +3 -0
  314. package/dist/modes/interactive/resource-description.d.ts.map +1 -0
  315. package/dist/modes/interactive/resource-description.js +15 -0
  316. package/dist/modes/interactive/resource-description.js.map +1 -0
  317. package/dist/modes/interactive/tui-diagnostics.d.ts +36 -0
  318. package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -0
  319. package/dist/modes/interactive/tui-diagnostics.js +105 -0
  320. package/dist/modes/interactive/tui-diagnostics.js.map +1 -0
  321. package/dist/modes/interactive/tui-runtime-info.d.ts +20 -0
  322. package/dist/modes/interactive/tui-runtime-info.d.ts.map +1 -0
  323. package/dist/modes/interactive/tui-runtime-info.js +76 -0
  324. package/dist/modes/interactive/tui-runtime-info.js.map +1 -0
  325. package/docs/development.md +10 -0
  326. package/docs/devin-harness.md +121 -0
  327. package/docs/docs.json +4 -0
  328. package/docs/environment-variables.md +2 -1
  329. package/docs/index.md +1 -0
  330. package/docs/keybindings.md +1 -1
  331. package/docs/loadout-domains/README.md +2 -1
  332. package/docs/loadout-domains/devin-harness.md +72 -0
  333. package/docs/metrics.md +57 -16
  334. package/docs/providers.md +76 -0
  335. package/docs/release-audit-0.98.5.md +101 -0
  336. package/docs/release-audit-0.99.0.md +68 -0
  337. package/docs/run-protocol.md +34 -1
  338. package/docs/runtime-algorithms.md +30 -1
  339. package/docs/sdk.md +198 -1
  340. package/docs/settings.md +1 -1
  341. package/docs/startup-resource-labels-testing.md +47 -0
  342. package/docs/tb21-audit.md +18 -4
  343. package/docs/usage.md +59 -0
  344. package/docs/verified-run-remaining-design.md +881 -0
  345. package/docs/verified-run-testing.md +508 -0
  346. package/docs/verified-run.md +409 -0
  347. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  348. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  349. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  350. package/examples/extensions/gondolin/package-lock.json +2 -2
  351. package/examples/extensions/gondolin/package.json +1 -1
  352. package/examples/extensions/sandbox/package-lock.json +2 -2
  353. package/examples/extensions/sandbox/package.json +1 -1
  354. package/examples/extensions/with-deps/package-lock.json +2 -2
  355. package/examples/extensions/with-deps/package.json +1 -1
  356. package/npm-shrinkwrap.json +18 -18
  357. package/package.json +6 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../../src/core/verified-run/coordinator.ts"],"names":[],"mappings":"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","sourcesContent":["import { join, resolve } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport {\n\tparseRunContract,\n\tparseRunResumeCommand,\n\tparseRunStartCommand,\n\tparseRunTaskRetryCommand,\n\tparseRunWriterRestartCommand,\n\ttype RunContract,\n} from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { acquireSessionOwnerLeaseSync } from \"../session-owner-lease.ts\";\nimport { commandEnvironmentDigest, probeVerifiedSandbox } from \"./broker.ts\";\nimport { captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { inspectTaskRecovery, retryDagTasks, type TaskRecoveryInspection } from \"./dag-recovery.ts\";\nimport { createRunIssuer, readRunEvidence, type VerifiedRunEvidence } from \"./evidence.ts\";\nimport { journalPath, readRunJournal, VerifiedRunJournal } from \"./journal.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { inspectRunRecovery, type RecoveryInspection, resumeFrozenCandidate } from \"./recovery.ts\";\nimport { anchorRunBudget, readRunClock } from \"./recovery-clock.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport type { VerifiedRunRuntime } from \"./session-port.ts\";\nimport {\n\tassertStateOutsideWorkspace,\n\tdigestBytes,\n\tdigestObject,\n\treadRegularFile,\n\tstateRunPath,\n\tVerifiedRunError,\n} from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\nimport { executeWriter } from \"./writer-phase.ts\";\nimport { inspectWriterRecovery, restartIsolatedWriter, type WriterRecoveryInspection } from \"./writer-recovery.ts\";\n\nexport interface VerifiedRunApproval {\n\t/** Trusted host grant, not a JSON field in the model-authored contract or command. */\n\treadonly approvedContractDigest: string;\n\treadonly signal?: AbortSignal;\n}\nexport interface VerifiedRunPlan {\n\treadonly profile: RunContract[\"profile\"];\n\treadonly contractDigest: string;\n\treadonly baseDigest: string;\n\treadonly baseMatches: boolean;\n\treadonly environmentDigest: string;\n\treadonly checks: readonly string[];\n\treadonly executionRequested: false;\n}\n\nexport function planVerifiedRun(input: unknown): VerifiedRunPlan {\n\tconst contract = parseRunContract(input);\n\tconst snapshot = captureCandidate(contract.workspace.root, contract.budget);\n\treturn Object.freeze({\n\t\tprofile: contract.profile,\n\t\tcontractDigest: digestObject(contract),\n\t\tbaseDigest: snapshot.digest,\n\t\tbaseMatches: snapshot.digest === contract.workspace.baseDigest,\n\t\tenvironmentDigest: commandEnvironmentDigest(contract, \"gated-v1\"),\n\t\tchecks: Object.freeze(contract.checks.map((check) => check.claimId)),\n\t\texecutionRequested: false,\n\t});\n}\n\n/** Owns the opt-in single-host run; session capabilities come only from trusted host composition. */\nexport class RunCoordinator {\n\tprivate readonly stateRoot: string;\n\tprivate readonly runtime: VerifiedRunRuntime | undefined;\n\tconstructor(stateRoot: string, runtime?: VerifiedRunRuntime) {\n\t\tthis.stateRoot = resolve(stateRoot);\n\t\tthis.runtime = runtime;\n\t}\n\n\tinspect(runId: string): RunProjection {\n\t\tconst journal = readRunJournal(stateRunPath(this.stateRoot, runId));\n\t\tif (!journal || journal.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (journal.state.receiptDigest) this.evidence(runId);\n\t\treturn journal.state;\n\t}\n\n\tinspectRecovery(runId: string): RecoveryInspection {\n\t\tconst report = inspectRunRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectWriterRecovery(runId: string): WriterRecoveryInspection {\n\t\tconst report = inspectWriterRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tinspectTaskRecovery(runId: string): TaskRecoveryInspection {\n\t\tconst report = inspectTaskRecovery(stateRunPath(this.stateRoot, runId));\n\t\tif (report.state.runId !== runId) throw new VerifiedRunError(\"missing_run\");\n\t\tif (report.state.receiptDigest) this.evidence(runId);\n\t\treturn report;\n\t}\n\n\tasync retryTasks(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunTaskRetryCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait retryDagTasks(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tevidence(runId: string): VerifiedRunEvidence {\n\t\tconst runPath = stateRunPath(this.stateRoot, runId);\n\t\tconst journal = readRunJournal(runPath);\n\t\tconst first = journal?.records[0]?.event;\n\t\tif (!journal || first?.kind !== \"created\" || first.contract.runId !== runId)\n\t\t\tthrow new VerifiedRunError(\"missing_run\");\n\t\treturn readRunEvidence(\n\t\t\trunPath,\n\t\t\tjournal,\n\t\t\tcommandEnvironmentDigest(first.contract, journal.state.budget ? \"gated-v1\" : \"legacy\"),\n\t\t);\n\t}\n\n\tartifact(runId: string, candidateDigest: string, path: string): Buffer {\n\t\tconst evidence = this.evidence(runId);\n\t\tif (!evidence.verified || candidateDigest !== evidence.candidateDigest)\n\t\t\tthrow new VerifiedRunError(\"candidate_mismatch\");\n\t\tconst file = evidence.manifest.files.find((entry) => entry.path === path);\n\t\tif (!file) throw new VerifiedRunError(\"artifact_scope\");\n\t\tconst bytes = readRegularFile(join(stateRunPath(this.stateRoot, runId), \"blobs\", file.digest), file.size);\n\t\tif (digestBytes(bytes) !== file.digest || bytes.length !== file.size) throw new VerifiedRunError(\"integrity\");\n\t\treturn bytes;\n\t}\n\n\tasync resume(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunResumeCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait resumeFrozenCandidate(stateRunPath(this.stateRoot, command.runId), command, approval.signal);\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync restartWriter(input: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst command = parseRunWriterRestartCommand(input);\n\t\tif (approval.approvedContractDigest !== command.contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tawait restartIsolatedWriter(stateRunPath(this.stateRoot, command.runId), command, {\n\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t});\n\t\treturn this.inspect(command.runId);\n\t}\n\n\tasync start(input: unknown, request: unknown, approval: VerifiedRunApproval): Promise<RunProjection> {\n\t\tconst began = performance.now();\n\t\tconst clock = readRunClock();\n\t\tconst contract = parseRunContract(input);\n\t\tconst command = parseRunStartCommand(request);\n\t\tconst contractDigest = digestObject(contract);\n\t\tif (approval.approvedContractDigest !== contractDigest) throw new VerifiedRunError(\"approval\");\n\t\tif (command.contractDigest !== contractDigest || command.runId !== contract.runId)\n\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\tif (approval.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tassertStateOutsideWorkspace(this.stateRoot, contract.workspace.root);\n\t\tconst runPath = stateRunPath(this.stateRoot, contract.runId);\n\t\tconst existing = readRunJournal(runPath);\n\t\tif (existing) {\n\t\t\tconst first = existing.records[0]?.event;\n\t\t\tif (\n\t\t\t\tfirst?.kind !== \"created\" ||\n\t\t\t\tdigestObject(first.command) !== digestObject(command) ||\n\t\t\t\tdigestObject(first.contract) !== contractDigest\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"command_conflict\");\n\t\t\treturn this.inspect(contract.runId);\n\t\t}\n\t\tconst base = captureCandidate(contract.workspace.root, contract.budget);\n\t\tif (base.digest !== contract.workspace.baseDigest) throw new VerifiedRunError(\"base_conflict\");\n\t\tconst environmentDigest = commandEnvironmentDigest(contract, \"gated-v1\");\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tensureDurableDirectorySync(runPath);\n\t\tconst owner = acquireSessionOwnerLeaseSync(journalPath(runPath));\n\t\ttry {\n\t\t\tif (readRunJournal(runPath)) throw new VerifiedRunError(\"command_conflict\");\n\t\t\tconst journal = new VerifiedRunJournal(runPath, owner);\n\t\t\tjournal.append({ kind: \"created\", contract, command });\n\t\t\tconst budget = anchorRunBudget(contract.budget, clock);\n\t\t\tjournal.append({ kind: \"budget_anchored\", budget, environmentDigest, driver: \"linux-pidns-gate-v1\" });\n\t\t\tconst context: RunPhaseContext = {\n\t\t\t\trunPath,\n\t\t\t\tcontract,\n\t\t\t\tjournal,\n\t\t\t\t...(approval.signal ? { signal: approval.signal } : {}),\n\t\t\t};\n\t\t\ttry {\n\t\t\t\tcreateRunIssuer(runPath);\n\t\t\t\tstoreCandidate(base, runPath);\n\t\t\t\tjournal.append({ kind: \"input_checkpoint\", digest: base.digest });\n\t\t\t\tconst work = join(runPath, \"writer\");\n\t\t\t\tif (contract.profile !== \"linux-command-dag-v1\") materializeCandidate(base, work);\n\t\t\t\tconst workDeadline = began + contract.budget.workMs;\n\t\t\t\tawait executeWriter(context, {\n\t\t\t\t\tworkspace: work,\n\t\t\t\t\tdeadline: workDeadline,\n\t\t\t\t\t...(this.runtime ? { runtime: this.runtime } : {}),\n\t\t\t\t});\n\t\t\t\tif (journal.state.execution === \"paused\") return this.inspect(contract.runId);\n\t\t\t\tpublishWriterCandidate(context, work, workDeadline);\n\t\t\t\tawait verifyCandidate(context);\n\t\t\t\treturn this.inspect(contract.runId);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof VerifiedRunError && !journal.state.receiptDigest)\n\t\t\t\t\treturn journal.append({ kind: \"failed\", code: error.code });\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t} finally {\n\t\t\towner.release();\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { RunDagTask } from "omk-protocol";
2
+ import { type CandidateSnapshot } from "./candidate.ts";
3
+ import type { RunPhaseContext } from "./phase-context.ts";
4
+ /** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */
5
+ export declare function composeDagCandidate(context: Pick<RunPhaseContext, "runPath" | "contract"> & {
6
+ readonly journal: Pick<RunPhaseContext["journal"], "state">;
7
+ }, selected: readonly RunDagTask[]): CandidateSnapshot;
8
+ //# sourceMappingURL=dag-candidates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-candidates.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-candidates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAsB,KAAK,iBAAiB,EAAiB,MAAM,gBAAgB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAa1D,mGAAmG;AACnG,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG;IACxD,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;CAC5D,EACD,QAAQ,EAAE,SAAS,UAAU,EAAE,GAC7B,iBAAiB,CA0CnB","sourcesContent":["import type { RunDagTask } from \"omk-protocol\";\nimport { type CandidateFile, type CandidateSnapshot, loadCandidate } from \"./candidate.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { digestObject, VerifiedRunError } from \"./storage.ts\";\n\n// Match captureCandidate's depth-first, per-directory code-unit ordering (not locale ordering).\nfunction treeOrder(left: string, right: string): number {\n\tconst a = left.split(\"/\");\n\tconst b = right.split(\"/\");\n\tfor (let index = 0; index < Math.min(a.length, b.length); index++) {\n\t\tif (a[index] !== b[index]) return a[index] < b[index] ? -1 : 1;\n\t}\n\treturn a.length - b.length;\n}\n\n/** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */\nexport function composeDagCandidate(\n\tcontext: Pick<RunPhaseContext, \"runPath\" | \"contract\"> & {\n\t\treadonly journal: Pick<RunPhaseContext[\"journal\"], \"state\">;\n\t},\n\tselected: readonly RunDagTask[],\n): CandidateSnapshot {\n\tconst { contract, journal, runPath } = context;\n\tif (!journal.state.inputDigest) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst base = loadCandidate(runPath, journal.state.inputDigest, contract.budget);\n\tconst files = new Map<string, CandidateFile>(base.manifest.files.map((file) => [file.path, file]));\n\tconst directories = new Set(base.manifest.directories);\n\tconst blobs = new Map(base.contents);\n\tfor (const definition of selected) {\n\t\tconst task = journal.state.tasks.find((task) => task.taskId === definition.id);\n\t\tif (task?.status !== \"succeeded\") throw new VerifiedRunError(\"task_not_ready\");\n\t\tconst output = loadCandidate(runPath, task.outputDigest, contract.budget);\n\t\tconst owned = (path: string): boolean =>\n\t\t\tdefinition.writablePaths.some((scope) => path === scope || path.startsWith(`${scope}/`));\n\t\tfor (const path of files.keys()) if (owned(path)) files.delete(path);\n\t\tfor (const path of directories) if (owned(path)) directories.delete(path);\n\t\tfor (const path of output.manifest.directories) if (owned(path)) directories.add(path);\n\t\tfor (const file of output.manifest.files) {\n\t\t\tif (!owned(file.path)) continue;\n\t\t\tconst bytes = output.contents.get(file.digest);\n\t\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\t\tfiles.set(file.path, file);\n\t\t\tblobs.set(file.digest, bytes);\n\t\t}\n\t}\n\tconst entries = [...files.values()].sort((a, b) => treeOrder(a.path, b.path));\n\tif (\n\t\tentries.length + directories.size > contract.budget.maxFiles ||\n\t\tentries.reduce((sum, file) => sum + file.size, 0) > contract.budget.maxBytes\n\t)\n\t\tthrow new VerifiedRunError(\"storage_limit\");\n\tconst manifest = Object.freeze({\n\t\tversion: 1 as const,\n\t\tdirectories: Object.freeze([...directories].sort(treeOrder)),\n\t\tfiles: Object.freeze(entries),\n\t});\n\tconst contents = new Map<string, Buffer>();\n\tfor (const file of entries) {\n\t\tconst bytes = blobs.get(file.digest);\n\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\tcontents.set(file.digest, bytes);\n\t}\n\treturn { manifest, digest: digestObject(manifest), contents };\n}\n"]}
@@ -0,0 +1,65 @@
1
+ import { loadCandidate } from "./candidate.js";
2
+ import { digestObject, VerifiedRunError } from "./storage.js";
3
+ // Match captureCandidate's depth-first, per-directory code-unit ordering (not locale ordering).
4
+ function treeOrder(left, right) {
5
+ const a = left.split("/");
6
+ const b = right.split("/");
7
+ for (let index = 0; index < Math.min(a.length, b.length); index++) {
8
+ if (a[index] !== b[index])
9
+ return a[index] < b[index] ? -1 : 1;
10
+ }
11
+ return a.length - b.length;
12
+ }
13
+ /** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */
14
+ export function composeDagCandidate(context, selected) {
15
+ const { contract, journal, runPath } = context;
16
+ if (!journal.state.inputDigest)
17
+ throw new VerifiedRunError("input_checkpoint_missing");
18
+ const base = loadCandidate(runPath, journal.state.inputDigest, contract.budget);
19
+ const files = new Map(base.manifest.files.map((file) => [file.path, file]));
20
+ const directories = new Set(base.manifest.directories);
21
+ const blobs = new Map(base.contents);
22
+ for (const definition of selected) {
23
+ const task = journal.state.tasks.find((task) => task.taskId === definition.id);
24
+ if (task?.status !== "succeeded")
25
+ throw new VerifiedRunError("task_not_ready");
26
+ const output = loadCandidate(runPath, task.outputDigest, contract.budget);
27
+ const owned = (path) => definition.writablePaths.some((scope) => path === scope || path.startsWith(`${scope}/`));
28
+ for (const path of files.keys())
29
+ if (owned(path))
30
+ files.delete(path);
31
+ for (const path of directories)
32
+ if (owned(path))
33
+ directories.delete(path);
34
+ for (const path of output.manifest.directories)
35
+ if (owned(path))
36
+ directories.add(path);
37
+ for (const file of output.manifest.files) {
38
+ if (!owned(file.path))
39
+ continue;
40
+ const bytes = output.contents.get(file.digest);
41
+ if (!bytes)
42
+ throw new VerifiedRunError("integrity");
43
+ files.set(file.path, file);
44
+ blobs.set(file.digest, bytes);
45
+ }
46
+ }
47
+ const entries = [...files.values()].sort((a, b) => treeOrder(a.path, b.path));
48
+ if (entries.length + directories.size > contract.budget.maxFiles ||
49
+ entries.reduce((sum, file) => sum + file.size, 0) > contract.budget.maxBytes)
50
+ throw new VerifiedRunError("storage_limit");
51
+ const manifest = Object.freeze({
52
+ version: 1,
53
+ directories: Object.freeze([...directories].sort(treeOrder)),
54
+ files: Object.freeze(entries),
55
+ });
56
+ const contents = new Map();
57
+ for (const file of entries) {
58
+ const bytes = blobs.get(file.digest);
59
+ if (!bytes)
60
+ throw new VerifiedRunError("integrity");
61
+ contents.set(file.digest, bytes);
62
+ }
63
+ return { manifest, digest: digestObject(manifest), contents };
64
+ }
65
+ //# sourceMappingURL=dag-candidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-candidates.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-candidates.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RunDagTask } from \"omk-protocol\";\nimport { type CandidateFile, type CandidateSnapshot, loadCandidate } from \"./candidate.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { digestObject, VerifiedRunError } from \"./storage.ts\";\n\n// Match captureCandidate's depth-first, per-directory code-unit ordering (not locale ordering).\nfunction treeOrder(left: string, right: string): number {\n\tconst a = left.split(\"/\");\n\tconst b = right.split(\"/\");\n\tfor (let index = 0; index < Math.min(a.length, b.length); index++) {\n\t\tif (a[index] !== b[index]) return a[index] < b[index] ? -1 : 1;\n\t}\n\treturn a.length - b.length;\n}\n\n/** Compose only the declared ancestors' disjoint output scopes, over the pinned original input. */\nexport function composeDagCandidate(\n\tcontext: Pick<RunPhaseContext, \"runPath\" | \"contract\"> & {\n\t\treadonly journal: Pick<RunPhaseContext[\"journal\"], \"state\">;\n\t},\n\tselected: readonly RunDagTask[],\n): CandidateSnapshot {\n\tconst { contract, journal, runPath } = context;\n\tif (!journal.state.inputDigest) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst base = loadCandidate(runPath, journal.state.inputDigest, contract.budget);\n\tconst files = new Map<string, CandidateFile>(base.manifest.files.map((file) => [file.path, file]));\n\tconst directories = new Set(base.manifest.directories);\n\tconst blobs = new Map(base.contents);\n\tfor (const definition of selected) {\n\t\tconst task = journal.state.tasks.find((task) => task.taskId === definition.id);\n\t\tif (task?.status !== \"succeeded\") throw new VerifiedRunError(\"task_not_ready\");\n\t\tconst output = loadCandidate(runPath, task.outputDigest, contract.budget);\n\t\tconst owned = (path: string): boolean =>\n\t\t\tdefinition.writablePaths.some((scope) => path === scope || path.startsWith(`${scope}/`));\n\t\tfor (const path of files.keys()) if (owned(path)) files.delete(path);\n\t\tfor (const path of directories) if (owned(path)) directories.delete(path);\n\t\tfor (const path of output.manifest.directories) if (owned(path)) directories.add(path);\n\t\tfor (const file of output.manifest.files) {\n\t\t\tif (!owned(file.path)) continue;\n\t\t\tconst bytes = output.contents.get(file.digest);\n\t\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\t\tfiles.set(file.path, file);\n\t\t\tblobs.set(file.digest, bytes);\n\t\t}\n\t}\n\tconst entries = [...files.values()].sort((a, b) => treeOrder(a.path, b.path));\n\tif (\n\t\tentries.length + directories.size > contract.budget.maxFiles ||\n\t\tentries.reduce((sum, file) => sum + file.size, 0) > contract.budget.maxBytes\n\t)\n\t\tthrow new VerifiedRunError(\"storage_limit\");\n\tconst manifest = Object.freeze({\n\t\tversion: 1 as const,\n\t\tdirectories: Object.freeze([...directories].sort(treeOrder)),\n\t\tfiles: Object.freeze(entries),\n\t});\n\tconst contents = new Map<string, Buffer>();\n\tfor (const file of entries) {\n\t\tconst bytes = blobs.get(file.digest);\n\t\tif (!bytes) throw new VerifiedRunError(\"integrity\");\n\t\tcontents.set(file.digest, bytes);\n\t}\n\treturn { manifest, digest: digestObject(manifest), contents };\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { RunPhaseContext } from "./phase-context.ts";
2
+ /** Bounded ready frontier; every started task is drained before this phase returns or throws. */
3
+ export declare function executeDag(context: RunPhaseContext, options: {
4
+ readonly workspace: string;
5
+ readonly deadline: number;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=dag-phase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-phase.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-phase.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAqE1D,iGAAiG;AACjG,wBAAsB,UAAU,CAC/B,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,IAAI,CAAC,CAuDf","sourcesContent":["import { join } from \"node:path\";\nimport { orderRunDag, type RunDagTask, runDagAncestors } from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { assertCandidateScope, captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { readyDagTasks } from \"./dag-projection.ts\";\nimport { executeRunCommand } from \"./owned-execution.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nfunction observeWork(context: RunPhaseContext): number {\n\tconst budget = context.journal.state.budget;\n\tif (!budget) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst clock = readRunClock();\n\tif (remainingRunTime(budget, budget.workDeadlineMs, clock) <= 0) throw new VerifiedRunError(\"deadline\");\n\treturn clock.nowMs;\n}\n\nasync function executeTask(context: RunPhaseContext, task: RunDagTask, deadline: number): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tif (context.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\tconst previous = journal.state.tasks.find((item) => item.taskId === task.id);\n\tif (previous?.status !== \"pending\") throw new VerifiedRunError(\"task_not_ready\");\n\tconst attempt = previous.attempt + 1;\n\tconst argv = task.attempts[previous.attempt];\n\tif (!argv) throw new VerifiedRunError(\"task_attempt_limit\");\n\tconst input = composeDagCandidate(context, runDagAncestors(contract.writer.tasks, task.id));\n\tstoreCandidate(input, runPath);\n\tconst workspace = join(runPath, \"tasks\", `${task.id}-${attempt}-g${journal.state.generation}`);\n\tmaterializeCandidate(input, workspace);\n\tjournal.append({\n\t\tkind: \"task_started\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\tinputDigest: input.digest,\n\t\tobservedMs: observeWork(context),\n\t});\n\tconst { result } = await executeRunCommand(\n\t\tjournal,\n\t\t{ role: \"writer\", argv, workspace, deadline, claimId: null, taskId: task.id },\n\t\t{ ...contract.budget, ...(context.signal ? { signal: context.signal } : {}) },\n\t);\n\tif (result.failure === \"deadline\" || result.failure === \"cancelled\") throw new VerifiedRunError(result.failure);\n\tlet outputDigest: string | null = null;\n\tlet failure = result.failure;\n\tif (!failure) {\n\t\ttry {\n\t\t\tconst output = captureCandidate(workspace, contract.budget);\n\t\t\tassertCandidateScope(input.manifest, output.manifest, task.writablePaths);\n\t\t\tstoreCandidate(output, runPath);\n\t\t\toutputDigest = output.digest;\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\t!(error instanceof VerifiedRunError) ||\n\t\t\t\t![\"scope_changed\", \"file_type\", \"storage_limit\"].includes(error.code)\n\t\t\t)\n\t\t\t\tthrow error;\n\t\t\tfailure = error.code;\n\t\t}\n\t}\n\tjournal.append({\n\t\tkind: \"task_finished\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\toutputDigest,\n\t\tfailure,\n\t\tobservedMs: observeWork(context),\n\t});\n}\n\ntype TaskCompletion =\n\t| { readonly kind: \"done\"; readonly taskId: string }\n\t| { readonly kind: \"failed\"; readonly taskId: string; readonly error: unknown };\n\n/** Bounded ready frontier; every started task is drained before this phase returns or throws. */\nexport async function executeDag(\n\tcontext: RunPhaseContext,\n\toptions: { readonly workspace: string; readonly deadline: number },\n): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tensureDurableDirectorySync(join(runPath, \"tasks\"));\n\tconst order = orderRunDag(contract.writer.tasks);\n\tconst limit = contract.writer.maxConcurrentTasks ?? 1;\n\tconst stop = new AbortController();\n\tconst signal = context.signal ? AbortSignal.any([context.signal, stop.signal]) : stop.signal;\n\tconst work = { ...context, signal };\n\tconst inFlight = new Map<string, Promise<TaskCompletion>>();\n\tlet firstFailure: { readonly error: unknown } | undefined;\n\ttry {\n\t\tfor (;;) {\n\t\t\tif (firstFailure) throw firstFailure.error;\n\t\t\tif (signal.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\t\tconst ready = new Set(readyDagTasks(contract.writer, journal.state).map((task) => task.id));\n\t\t\tfor (const task of order) {\n\t\t\t\tif (inFlight.size >= limit) break;\n\t\t\t\tif (!ready.has(task.id) || inFlight.has(task.id)) continue;\n\t\t\t\tconst completion = executeTask(work, task, options.deadline).then<TaskCompletion, TaskCompletion>(\n\t\t\t\t\t() => ({ kind: \"done\", taskId: task.id }),\n\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\tfirstFailure ??= { error };\n\t\t\t\t\t\tstop.abort();\n\t\t\t\t\t\treturn { kind: \"failed\", taskId: task.id, error };\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tinFlight.set(task.id, completion);\n\t\t\t}\n\t\t\tif (!inFlight.size) break;\n\t\t\tconst completed = await Promise.race(inFlight.values());\n\t\t\tinFlight.delete(completed.taskId);\n\t\t\tswitch (completed.kind) {\n\t\t\t\tcase \"failed\":\n\t\t\t\t\tthrow completed.error;\n\t\t\t\tcase \"done\":\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: {\n\t\t\t\t\tconst exhaustive: never = completed;\n\t\t\t\t\tthrow new VerifiedRunError(String(exhaustive));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tstop.abort();\n\t\tawait Promise.all(inFlight.values());\n\t}\n\tif (\n\t\tjournal.state.tasks.some((task) => task.status !== \"succeeded\" || task.generation !== journal.state.generation)\n\t) {\n\t\tjournal.append({ kind: \"tasks_paused\" });\n\t\treturn;\n\t}\n\tobserveWork(context);\n\tmaterializeCandidate(composeDagCandidate(context, order), options.workspace);\n}\n"]}
@@ -0,0 +1,130 @@
1
+ import { join } from "node:path";
2
+ import { orderRunDag, runDagAncestors } from "omk-protocol";
3
+ import { ensureDurableDirectorySync } from "../durable-file-io.js";
4
+ import { assertCandidateScope, captureCandidate, materializeCandidate, storeCandidate } from "./candidate.js";
5
+ import { composeDagCandidate } from "./dag-candidates.js";
6
+ import { readyDagTasks } from "./dag-projection.js";
7
+ import { executeRunCommand } from "./owned-execution.js";
8
+ import { readRunClock, remainingRunTime } from "./recovery-clock.js";
9
+ import { VerifiedRunError } from "./storage.js";
10
+ function observeWork(context) {
11
+ const budget = context.journal.state.budget;
12
+ if (!budget)
13
+ throw new VerifiedRunError("input_checkpoint_missing");
14
+ const clock = readRunClock();
15
+ if (remainingRunTime(budget, budget.workDeadlineMs, clock) <= 0)
16
+ throw new VerifiedRunError("deadline");
17
+ return clock.nowMs;
18
+ }
19
+ async function executeTask(context, task, deadline) {
20
+ const { contract, journal, runPath } = context;
21
+ if (contract.profile !== "linux-command-dag-v1")
22
+ throw new VerifiedRunError("unsupported");
23
+ if (context.signal?.aborted)
24
+ throw new VerifiedRunError("cancelled");
25
+ const previous = journal.state.tasks.find((item) => item.taskId === task.id);
26
+ if (previous?.status !== "pending")
27
+ throw new VerifiedRunError("task_not_ready");
28
+ const attempt = previous.attempt + 1;
29
+ const argv = task.attempts[previous.attempt];
30
+ if (!argv)
31
+ throw new VerifiedRunError("task_attempt_limit");
32
+ const input = composeDagCandidate(context, runDagAncestors(contract.writer.tasks, task.id));
33
+ storeCandidate(input, runPath);
34
+ const workspace = join(runPath, "tasks", `${task.id}-${attempt}-g${journal.state.generation}`);
35
+ materializeCandidate(input, workspace);
36
+ journal.append({
37
+ kind: "task_started",
38
+ taskId: task.id,
39
+ attempt,
40
+ inputDigest: input.digest,
41
+ observedMs: observeWork(context),
42
+ });
43
+ const { result } = await executeRunCommand(journal, { role: "writer", argv, workspace, deadline, claimId: null, taskId: task.id }, { ...contract.budget, ...(context.signal ? { signal: context.signal } : {}) });
44
+ if (result.failure === "deadline" || result.failure === "cancelled")
45
+ throw new VerifiedRunError(result.failure);
46
+ let outputDigest = null;
47
+ let failure = result.failure;
48
+ if (!failure) {
49
+ try {
50
+ const output = captureCandidate(workspace, contract.budget);
51
+ assertCandidateScope(input.manifest, output.manifest, task.writablePaths);
52
+ storeCandidate(output, runPath);
53
+ outputDigest = output.digest;
54
+ }
55
+ catch (error) {
56
+ if (!(error instanceof VerifiedRunError) ||
57
+ !["scope_changed", "file_type", "storage_limit"].includes(error.code))
58
+ throw error;
59
+ failure = error.code;
60
+ }
61
+ }
62
+ journal.append({
63
+ kind: "task_finished",
64
+ taskId: task.id,
65
+ attempt,
66
+ outputDigest,
67
+ failure,
68
+ observedMs: observeWork(context),
69
+ });
70
+ }
71
+ /** Bounded ready frontier; every started task is drained before this phase returns or throws. */
72
+ export async function executeDag(context, options) {
73
+ const { contract, journal, runPath } = context;
74
+ if (contract.profile !== "linux-command-dag-v1")
75
+ throw new VerifiedRunError("unsupported");
76
+ ensureDurableDirectorySync(join(runPath, "tasks"));
77
+ const order = orderRunDag(contract.writer.tasks);
78
+ const limit = contract.writer.maxConcurrentTasks ?? 1;
79
+ const stop = new AbortController();
80
+ const signal = context.signal ? AbortSignal.any([context.signal, stop.signal]) : stop.signal;
81
+ const work = { ...context, signal };
82
+ const inFlight = new Map();
83
+ let firstFailure;
84
+ try {
85
+ for (;;) {
86
+ if (firstFailure)
87
+ throw firstFailure.error;
88
+ if (signal.aborted)
89
+ throw new VerifiedRunError("cancelled");
90
+ const ready = new Set(readyDagTasks(contract.writer, journal.state).map((task) => task.id));
91
+ for (const task of order) {
92
+ if (inFlight.size >= limit)
93
+ break;
94
+ if (!ready.has(task.id) || inFlight.has(task.id))
95
+ continue;
96
+ const completion = executeTask(work, task, options.deadline).then(() => ({ kind: "done", taskId: task.id }), (error) => {
97
+ firstFailure ??= { error };
98
+ stop.abort();
99
+ return { kind: "failed", taskId: task.id, error };
100
+ });
101
+ inFlight.set(task.id, completion);
102
+ }
103
+ if (!inFlight.size)
104
+ break;
105
+ const completed = await Promise.race(inFlight.values());
106
+ inFlight.delete(completed.taskId);
107
+ switch (completed.kind) {
108
+ case "failed":
109
+ throw completed.error;
110
+ case "done":
111
+ break;
112
+ default: {
113
+ const exhaustive = completed;
114
+ throw new VerifiedRunError(String(exhaustive));
115
+ }
116
+ }
117
+ }
118
+ }
119
+ finally {
120
+ stop.abort();
121
+ await Promise.all(inFlight.values());
122
+ }
123
+ if (journal.state.tasks.some((task) => task.status !== "succeeded" || task.generation !== journal.state.generation)) {
124
+ journal.append({ kind: "tasks_paused" });
125
+ return;
126
+ }
127
+ observeWork(context);
128
+ materializeCandidate(composeDagCandidate(context, order), options.workspace);
129
+ }
130
+ //# sourceMappingURL=dag-phase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-phase.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-phase.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { orderRunDag, type RunDagTask, runDagAncestors } from \"omk-protocol\";\nimport { ensureDurableDirectorySync } from \"../durable-file-io.ts\";\nimport { assertCandidateScope, captureCandidate, materializeCandidate, storeCandidate } from \"./candidate.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { readyDagTasks } from \"./dag-projection.ts\";\nimport { executeRunCommand } from \"./owned-execution.ts\";\nimport type { RunPhaseContext } from \"./phase-context.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nfunction observeWork(context: RunPhaseContext): number {\n\tconst budget = context.journal.state.budget;\n\tif (!budget) throw new VerifiedRunError(\"input_checkpoint_missing\");\n\tconst clock = readRunClock();\n\tif (remainingRunTime(budget, budget.workDeadlineMs, clock) <= 0) throw new VerifiedRunError(\"deadline\");\n\treturn clock.nowMs;\n}\n\nasync function executeTask(context: RunPhaseContext, task: RunDagTask, deadline: number): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tif (context.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\tconst previous = journal.state.tasks.find((item) => item.taskId === task.id);\n\tif (previous?.status !== \"pending\") throw new VerifiedRunError(\"task_not_ready\");\n\tconst attempt = previous.attempt + 1;\n\tconst argv = task.attempts[previous.attempt];\n\tif (!argv) throw new VerifiedRunError(\"task_attempt_limit\");\n\tconst input = composeDagCandidate(context, runDagAncestors(contract.writer.tasks, task.id));\n\tstoreCandidate(input, runPath);\n\tconst workspace = join(runPath, \"tasks\", `${task.id}-${attempt}-g${journal.state.generation}`);\n\tmaterializeCandidate(input, workspace);\n\tjournal.append({\n\t\tkind: \"task_started\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\tinputDigest: input.digest,\n\t\tobservedMs: observeWork(context),\n\t});\n\tconst { result } = await executeRunCommand(\n\t\tjournal,\n\t\t{ role: \"writer\", argv, workspace, deadline, claimId: null, taskId: task.id },\n\t\t{ ...contract.budget, ...(context.signal ? { signal: context.signal } : {}) },\n\t);\n\tif (result.failure === \"deadline\" || result.failure === \"cancelled\") throw new VerifiedRunError(result.failure);\n\tlet outputDigest: string | null = null;\n\tlet failure = result.failure;\n\tif (!failure) {\n\t\ttry {\n\t\t\tconst output = captureCandidate(workspace, contract.budget);\n\t\t\tassertCandidateScope(input.manifest, output.manifest, task.writablePaths);\n\t\t\tstoreCandidate(output, runPath);\n\t\t\toutputDigest = output.digest;\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\t!(error instanceof VerifiedRunError) ||\n\t\t\t\t![\"scope_changed\", \"file_type\", \"storage_limit\"].includes(error.code)\n\t\t\t)\n\t\t\t\tthrow error;\n\t\t\tfailure = error.code;\n\t\t}\n\t}\n\tjournal.append({\n\t\tkind: \"task_finished\",\n\t\ttaskId: task.id,\n\t\tattempt,\n\t\toutputDigest,\n\t\tfailure,\n\t\tobservedMs: observeWork(context),\n\t});\n}\n\ntype TaskCompletion =\n\t| { readonly kind: \"done\"; readonly taskId: string }\n\t| { readonly kind: \"failed\"; readonly taskId: string; readonly error: unknown };\n\n/** Bounded ready frontier; every started task is drained before this phase returns or throws. */\nexport async function executeDag(\n\tcontext: RunPhaseContext,\n\toptions: { readonly workspace: string; readonly deadline: number },\n): Promise<void> {\n\tconst { contract, journal, runPath } = context;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"unsupported\");\n\tensureDurableDirectorySync(join(runPath, \"tasks\"));\n\tconst order = orderRunDag(contract.writer.tasks);\n\tconst limit = contract.writer.maxConcurrentTasks ?? 1;\n\tconst stop = new AbortController();\n\tconst signal = context.signal ? AbortSignal.any([context.signal, stop.signal]) : stop.signal;\n\tconst work = { ...context, signal };\n\tconst inFlight = new Map<string, Promise<TaskCompletion>>();\n\tlet firstFailure: { readonly error: unknown } | undefined;\n\ttry {\n\t\tfor (;;) {\n\t\t\tif (firstFailure) throw firstFailure.error;\n\t\t\tif (signal.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\t\tconst ready = new Set(readyDagTasks(contract.writer, journal.state).map((task) => task.id));\n\t\t\tfor (const task of order) {\n\t\t\t\tif (inFlight.size >= limit) break;\n\t\t\t\tif (!ready.has(task.id) || inFlight.has(task.id)) continue;\n\t\t\t\tconst completion = executeTask(work, task, options.deadline).then<TaskCompletion, TaskCompletion>(\n\t\t\t\t\t() => ({ kind: \"done\", taskId: task.id }),\n\t\t\t\t\t(error: unknown) => {\n\t\t\t\t\t\tfirstFailure ??= { error };\n\t\t\t\t\t\tstop.abort();\n\t\t\t\t\t\treturn { kind: \"failed\", taskId: task.id, error };\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tinFlight.set(task.id, completion);\n\t\t\t}\n\t\t\tif (!inFlight.size) break;\n\t\t\tconst completed = await Promise.race(inFlight.values());\n\t\t\tinFlight.delete(completed.taskId);\n\t\t\tswitch (completed.kind) {\n\t\t\t\tcase \"failed\":\n\t\t\t\t\tthrow completed.error;\n\t\t\t\tcase \"done\":\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: {\n\t\t\t\t\tconst exhaustive: never = completed;\n\t\t\t\t\tthrow new VerifiedRunError(String(exhaustive));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tstop.abort();\n\t\tawait Promise.all(inFlight.values());\n\t}\n\tif (\n\t\tjournal.state.tasks.some((task) => task.status !== \"succeeded\" || task.generation !== journal.state.generation)\n\t) {\n\t\tjournal.append({ kind: \"tasks_paused\" });\n\t\treturn;\n\t}\n\tobserveWork(context);\n\tmaterializeCandidate(composeDagCandidate(context, order), options.workspace);\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { RunDagTask, RunDagWriter } from "omk-protocol";
2
+ import type { DagEvent } from "./dag-types.ts";
3
+ import type { RunProjection, WriterReduction } from "./run-types.ts";
4
+ export declare function readyDagTasks(writer: RunDagWriter, state: RunProjection): readonly RunDagTask[];
5
+ /** Task outputs are execution checkpoints, never verifier receipts or completion authority. */
6
+ export declare function reduceDagEvent(context: WriterReduction, event: DagEvent): void;
7
+ //# sourceMappingURL=dag-projection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-projection.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGrE,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,UAAU,EAAE,CAU/F;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,GAAG,IAAI,CAgG9E","sourcesContent":["import type { RunDagTask, RunDagWriter } from \"omk-protocol\";\nimport type { DagEvent, RunTaskProjection } from \"./dag-types.ts\";\nimport type { RunProjection, WriterReduction } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport function readyDagTasks(writer: RunDagWriter, state: RunProjection): readonly RunDagTask[] {\n\tconst states = new Map(state.tasks.map((task) => [task.taskId, task]));\n\treturn writer.tasks.filter(\n\t\t(task) =>\n\t\t\tstates.get(task.id)?.status === \"pending\" &&\n\t\t\ttask.dependsOn.every((id) => {\n\t\t\t\tconst dependency = states.get(id);\n\t\t\t\treturn dependency?.status === \"succeeded\" && dependency.generation === state.generation;\n\t\t\t}),\n\t);\n}\n\n/** Task outputs are execution checkpoints, never verifier receipts or completion authority. */\nexport function reduceDagEvent(context: WriterReduction, event: DagEvent): void {\n\tconst { state, contract } = context;\n\tif (\n\t\tcontract.profile !== \"linux-command-dag-v1\" ||\n\t\t!state.inputDigest ||\n\t\t!state.budget ||\n\t\tstate.candidateDigest ||\n\t\tstate.writerOpen ||\n\t\tstate.execution === \"paused\"\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (event.kind === \"tasks_paused\") {\n\t\tif (\n\t\t\tstate.activeExecutionIds.length ||\n\t\t\tstate.tasks.some((task) => task.status === \"running\") ||\n\t\t\t!state.tasks.some((task) => task.status === \"failed\") ||\n\t\t\treadyDagTasks(contract.writer, state).length\n\t\t)\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\tcontext.state = { ...state, execution: \"paused\", settlement: \"settled\" };\n\t\treturn;\n\t}\n\tif (\n\t\tevent.observedMs < (state.lastClockMs ?? state.budget.startedMs) ||\n\t\tevent.observedMs >= state.budget.workDeadlineMs\n\t)\n\t\tthrow new VerifiedRunError(\"deadline\");\n\tconst task = state.tasks.find((task) => task.taskId === event.taskId);\n\tconst definition = contract.writer.tasks.find((task) => task.id === event.taskId);\n\tif (!task || !definition) throw new VerifiedRunError(\"integrity\");\n\tlet next: RunTaskProjection;\n\tswitch (event.kind) {\n\t\tcase \"task_started\":\n\t\t\tif (\n\t\t\t\ttask.status !== \"pending\" ||\n\t\t\t\tstate.tasks.filter((task) => task.status === \"running\").length >=\n\t\t\t\t\t(contract.writer.maxConcurrentTasks ?? 1) ||\n\t\t\t\tevent.attempt !== task.attempt + 1 ||\n\t\t\t\tevent.attempt > definition.attempts.length ||\n\t\t\t\t!readyDagTasks(contract.writer, state).some((task) => task.id === event.taskId)\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"task_not_ready\");\n\t\t\tnext = {\n\t\t\t\ttaskId: task.taskId,\n\t\t\t\tgeneration: state.generation,\n\t\t\t\tattempt: event.attempt,\n\t\t\t\tstatus: \"running\",\n\t\t\t\texecution: Object.freeze({ kind: \"ready\" }),\n\t\t\t\tinputDigest: event.inputDigest,\n\t\t\t\toutputDigest: null,\n\t\t\t\tfailure: null,\n\t\t\t};\n\t\t\tbreak;\n\t\tcase \"task_finished\": {\n\t\t\tif (\n\t\t\t\ttask.status !== \"running\" ||\n\t\t\t\ttask.generation !== state.generation ||\n\t\t\t\ttask.attempt !== event.attempt ||\n\t\t\t\ttask.execution.kind !== \"exited\"\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t// Keep checkpoint shape stable: process state belongs only to an in-flight task.\n\t\t\tconst checkpoint = {\n\t\t\t\ttaskId: task.taskId,\n\t\t\t\tgeneration: task.generation,\n\t\t\t\tattempt: task.attempt,\n\t\t\t\tinputDigest: task.inputDigest,\n\t\t\t};\n\t\t\tif (event.outputDigest !== null) {\n\t\t\t\tif (event.failure !== null || task.execution.failure) throw new VerifiedRunError(\"integrity\");\n\t\t\t\tnext = { ...checkpoint, status: \"succeeded\", outputDigest: event.outputDigest, failure: null };\n\t\t\t} else {\n\t\t\t\tif (!event.failure || (task.execution.failure && event.failure !== task.execution.failure))\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tnext = { ...checkpoint, status: \"failed\", outputDigest: null, failure: event.failure };\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tconst exhaustive: never = event;\n\t\t\tthrow new VerifiedRunError(String(exhaustive));\n\t\t}\n\t}\n\tconst tasks = state.tasks.map((task) => (task.taskId === next.taskId ? next : task));\n\tcontext.writerFinished = tasks.every((task) => task.status === \"succeeded\" && task.generation === state.generation);\n\tlet settlement: RunProjection[\"settlement\"] = \"settled\";\n\tif (tasks.some((task) => task.status === \"running\")) settlement = \"open\";\n\tif (state.activeExecutionIds.length) settlement = \"draining\";\n\tcontext.state = {\n\t\t...state,\n\t\ttasks,\n\t\texecution: \"running\",\n\t\tsettlement,\n\t\tfailure: null,\n\t\tlastClockMs: event.observedMs,\n\t};\n}\n"]}
@@ -0,0 +1,103 @@
1
+ import { VerifiedRunError } from "./storage.js";
2
+ export function readyDagTasks(writer, state) {
3
+ const states = new Map(state.tasks.map((task) => [task.taskId, task]));
4
+ return writer.tasks.filter((task) => states.get(task.id)?.status === "pending" &&
5
+ task.dependsOn.every((id) => {
6
+ const dependency = states.get(id);
7
+ return dependency?.status === "succeeded" && dependency.generation === state.generation;
8
+ }));
9
+ }
10
+ /** Task outputs are execution checkpoints, never verifier receipts or completion authority. */
11
+ export function reduceDagEvent(context, event) {
12
+ const { state, contract } = context;
13
+ if (contract.profile !== "linux-command-dag-v1" ||
14
+ !state.inputDigest ||
15
+ !state.budget ||
16
+ state.candidateDigest ||
17
+ state.writerOpen ||
18
+ state.execution === "paused")
19
+ throw new VerifiedRunError("integrity");
20
+ if (event.kind === "tasks_paused") {
21
+ if (state.activeExecutionIds.length ||
22
+ state.tasks.some((task) => task.status === "running") ||
23
+ !state.tasks.some((task) => task.status === "failed") ||
24
+ readyDagTasks(contract.writer, state).length)
25
+ throw new VerifiedRunError("integrity");
26
+ context.state = { ...state, execution: "paused", settlement: "settled" };
27
+ return;
28
+ }
29
+ if (event.observedMs < (state.lastClockMs ?? state.budget.startedMs) ||
30
+ event.observedMs >= state.budget.workDeadlineMs)
31
+ throw new VerifiedRunError("deadline");
32
+ const task = state.tasks.find((task) => task.taskId === event.taskId);
33
+ const definition = contract.writer.tasks.find((task) => task.id === event.taskId);
34
+ if (!task || !definition)
35
+ throw new VerifiedRunError("integrity");
36
+ let next;
37
+ switch (event.kind) {
38
+ case "task_started":
39
+ if (task.status !== "pending" ||
40
+ state.tasks.filter((task) => task.status === "running").length >=
41
+ (contract.writer.maxConcurrentTasks ?? 1) ||
42
+ event.attempt !== task.attempt + 1 ||
43
+ event.attempt > definition.attempts.length ||
44
+ !readyDagTasks(contract.writer, state).some((task) => task.id === event.taskId))
45
+ throw new VerifiedRunError("task_not_ready");
46
+ next = {
47
+ taskId: task.taskId,
48
+ generation: state.generation,
49
+ attempt: event.attempt,
50
+ status: "running",
51
+ execution: Object.freeze({ kind: "ready" }),
52
+ inputDigest: event.inputDigest,
53
+ outputDigest: null,
54
+ failure: null,
55
+ };
56
+ break;
57
+ case "task_finished": {
58
+ if (task.status !== "running" ||
59
+ task.generation !== state.generation ||
60
+ task.attempt !== event.attempt ||
61
+ task.execution.kind !== "exited")
62
+ throw new VerifiedRunError("integrity");
63
+ // Keep checkpoint shape stable: process state belongs only to an in-flight task.
64
+ const checkpoint = {
65
+ taskId: task.taskId,
66
+ generation: task.generation,
67
+ attempt: task.attempt,
68
+ inputDigest: task.inputDigest,
69
+ };
70
+ if (event.outputDigest !== null) {
71
+ if (event.failure !== null || task.execution.failure)
72
+ throw new VerifiedRunError("integrity");
73
+ next = { ...checkpoint, status: "succeeded", outputDigest: event.outputDigest, failure: null };
74
+ }
75
+ else {
76
+ if (!event.failure || (task.execution.failure && event.failure !== task.execution.failure))
77
+ throw new VerifiedRunError("integrity");
78
+ next = { ...checkpoint, status: "failed", outputDigest: null, failure: event.failure };
79
+ }
80
+ break;
81
+ }
82
+ default: {
83
+ const exhaustive = event;
84
+ throw new VerifiedRunError(String(exhaustive));
85
+ }
86
+ }
87
+ const tasks = state.tasks.map((task) => (task.taskId === next.taskId ? next : task));
88
+ context.writerFinished = tasks.every((task) => task.status === "succeeded" && task.generation === state.generation);
89
+ let settlement = "settled";
90
+ if (tasks.some((task) => task.status === "running"))
91
+ settlement = "open";
92
+ if (state.activeExecutionIds.length)
93
+ settlement = "draining";
94
+ context.state = {
95
+ ...state,
96
+ tasks,
97
+ execution: "running",
98
+ settlement,
99
+ failure: null,
100
+ lastClockMs: event.observedMs,
101
+ };
102
+ }
103
+ //# sourceMappingURL=dag-projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-projection.js","sourceRoot":"","sources":["../../../src/core/verified-run/dag-projection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RunDagTask, RunDagWriter } from \"omk-protocol\";\nimport type { DagEvent, RunTaskProjection } from \"./dag-types.ts\";\nimport type { RunProjection, WriterReduction } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nexport function readyDagTasks(writer: RunDagWriter, state: RunProjection): readonly RunDagTask[] {\n\tconst states = new Map(state.tasks.map((task) => [task.taskId, task]));\n\treturn writer.tasks.filter(\n\t\t(task) =>\n\t\t\tstates.get(task.id)?.status === \"pending\" &&\n\t\t\ttask.dependsOn.every((id) => {\n\t\t\t\tconst dependency = states.get(id);\n\t\t\t\treturn dependency?.status === \"succeeded\" && dependency.generation === state.generation;\n\t\t\t}),\n\t);\n}\n\n/** Task outputs are execution checkpoints, never verifier receipts or completion authority. */\nexport function reduceDagEvent(context: WriterReduction, event: DagEvent): void {\n\tconst { state, contract } = context;\n\tif (\n\t\tcontract.profile !== \"linux-command-dag-v1\" ||\n\t\t!state.inputDigest ||\n\t\t!state.budget ||\n\t\tstate.candidateDigest ||\n\t\tstate.writerOpen ||\n\t\tstate.execution === \"paused\"\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (event.kind === \"tasks_paused\") {\n\t\tif (\n\t\t\tstate.activeExecutionIds.length ||\n\t\t\tstate.tasks.some((task) => task.status === \"running\") ||\n\t\t\t!state.tasks.some((task) => task.status === \"failed\") ||\n\t\t\treadyDagTasks(contract.writer, state).length\n\t\t)\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\tcontext.state = { ...state, execution: \"paused\", settlement: \"settled\" };\n\t\treturn;\n\t}\n\tif (\n\t\tevent.observedMs < (state.lastClockMs ?? state.budget.startedMs) ||\n\t\tevent.observedMs >= state.budget.workDeadlineMs\n\t)\n\t\tthrow new VerifiedRunError(\"deadline\");\n\tconst task = state.tasks.find((task) => task.taskId === event.taskId);\n\tconst definition = contract.writer.tasks.find((task) => task.id === event.taskId);\n\tif (!task || !definition) throw new VerifiedRunError(\"integrity\");\n\tlet next: RunTaskProjection;\n\tswitch (event.kind) {\n\t\tcase \"task_started\":\n\t\t\tif (\n\t\t\t\ttask.status !== \"pending\" ||\n\t\t\t\tstate.tasks.filter((task) => task.status === \"running\").length >=\n\t\t\t\t\t(contract.writer.maxConcurrentTasks ?? 1) ||\n\t\t\t\tevent.attempt !== task.attempt + 1 ||\n\t\t\t\tevent.attempt > definition.attempts.length ||\n\t\t\t\t!readyDagTasks(contract.writer, state).some((task) => task.id === event.taskId)\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"task_not_ready\");\n\t\t\tnext = {\n\t\t\t\ttaskId: task.taskId,\n\t\t\t\tgeneration: state.generation,\n\t\t\t\tattempt: event.attempt,\n\t\t\t\tstatus: \"running\",\n\t\t\t\texecution: Object.freeze({ kind: \"ready\" }),\n\t\t\t\tinputDigest: event.inputDigest,\n\t\t\t\toutputDigest: null,\n\t\t\t\tfailure: null,\n\t\t\t};\n\t\t\tbreak;\n\t\tcase \"task_finished\": {\n\t\t\tif (\n\t\t\t\ttask.status !== \"running\" ||\n\t\t\t\ttask.generation !== state.generation ||\n\t\t\t\ttask.attempt !== event.attempt ||\n\t\t\t\ttask.execution.kind !== \"exited\"\n\t\t\t)\n\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t// Keep checkpoint shape stable: process state belongs only to an in-flight task.\n\t\t\tconst checkpoint = {\n\t\t\t\ttaskId: task.taskId,\n\t\t\t\tgeneration: task.generation,\n\t\t\t\tattempt: task.attempt,\n\t\t\t\tinputDigest: task.inputDigest,\n\t\t\t};\n\t\t\tif (event.outputDigest !== null) {\n\t\t\t\tif (event.failure !== null || task.execution.failure) throw new VerifiedRunError(\"integrity\");\n\t\t\t\tnext = { ...checkpoint, status: \"succeeded\", outputDigest: event.outputDigest, failure: null };\n\t\t\t} else {\n\t\t\t\tif (!event.failure || (task.execution.failure && event.failure !== task.execution.failure))\n\t\t\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t\t\t\tnext = { ...checkpoint, status: \"failed\", outputDigest: null, failure: event.failure };\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault: {\n\t\t\tconst exhaustive: never = event;\n\t\t\tthrow new VerifiedRunError(String(exhaustive));\n\t\t}\n\t}\n\tconst tasks = state.tasks.map((task) => (task.taskId === next.taskId ? next : task));\n\tcontext.writerFinished = tasks.every((task) => task.status === \"succeeded\" && task.generation === state.generation);\n\tlet settlement: RunProjection[\"settlement\"] = \"settled\";\n\tif (tasks.some((task) => task.status === \"running\")) settlement = \"open\";\n\tif (state.activeExecutionIds.length) settlement = \"draining\";\n\tcontext.state = {\n\t\t...state,\n\t\ttasks,\n\t\texecution: \"running\",\n\t\tsettlement,\n\t\tfailure: null,\n\t\tlastClockMs: event.observedMs,\n\t};\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import { type RunTaskRetryCommand } from "omk-protocol";
2
+ import type { RunProjection } from "./run-types.ts";
3
+ export interface TaskRecoveryInspection {
4
+ readonly state: RunProjection;
5
+ readonly readiness: "ready" | "blocked";
6
+ readonly reason: string | null;
7
+ readonly retryableTaskIds: readonly string[];
8
+ readonly remainingWorkMs: number | null;
9
+ readonly ownership: "lease_required";
10
+ }
11
+ export declare function inspectTaskRecovery(runPath: string): TaskRecoveryInspection;
12
+ export declare function retryDagTasks(runPath: string, command: RunTaskRetryCommand, signal?: AbortSignal): Promise<RunProjection>;
13
+ //# sourceMappingURL=dag-recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dag-recovery.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/dag-recovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAAmB,MAAM,cAAc,CAAC;AAUzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAMpD,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;CACrC;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,sBAAsB,CA+B3E;AAED,wBAAsB,aAAa,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,MAAM,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,aAAa,CAAC,CA0BxB","sourcesContent":["import { join } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport { type RunTaskRetryCommand, runDagAncestors } from \"omk-protocol\";\nimport { probeVerifiedSandbox } from \"./broker.ts\";\nimport { assertCandidateScope, loadCandidate } from \"./candidate.ts\";\nimport { preflightCheckReceipts } from \"./check-receipt.ts\";\nimport { composeDagCandidate } from \"./dag-candidates.ts\";\nimport { executeDag } from \"./dag-phase.ts\";\nimport { assertTaskSelection, taskCheckpoints } from \"./dag-retry-projection.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { readRunClock, remainingRunTime } from \"./recovery-clock.ts\";\nimport { requireRunJournal, withRecoveryLease } from \"./recovery-command.ts\";\nimport type { RunProjection } from \"./run-types.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\nimport { verifyCandidate } from \"./verification-phase.ts\";\nimport { assertWorkRecoverable } from \"./work-recovery.ts\";\nimport { publishWriterCandidate } from \"./writer-completion.ts\";\n\nexport interface TaskRecoveryInspection {\n\treadonly state: RunProjection;\n\treadonly readiness: \"ready\" | \"blocked\";\n\treadonly reason: string | null;\n\treadonly retryableTaskIds: readonly string[];\n\treadonly remainingWorkMs: number | null;\n\treadonly ownership: \"lease_required\";\n}\n\nfunction assertDagRecoverable(runPath: string, snapshot: JournalSnapshot) {\n\tconst recovery = assertWorkRecoverable(runPath, snapshot);\n\tconst { contract } = recovery;\n\tif (contract.profile !== \"linux-command-dag-v1\") throw new VerifiedRunError(\"task_recovery_unavailable\");\n\tfor (const task of snapshot.state.tasks) {\n\t\tif (task.status === \"pending\") continue;\n\t\tconst definition = contract.writer.tasks.find((item) => item.id === task.taskId);\n\t\tif (!definition) throw new VerifiedRunError(\"integrity\");\n\t\tconst expected = composeDagCandidate(\n\t\t\t{ runPath, contract, journal: snapshot },\n\t\t\trunDagAncestors(contract.writer.tasks, task.taskId),\n\t\t);\n\t\tconst input = loadCandidate(runPath, task.inputDigest, contract.budget);\n\t\tif (input.digest !== expected.digest) throw new VerifiedRunError(\"task_checkpoint_mismatch\");\n\t\tif (task.status === \"succeeded\")\n\t\t\tassertCandidateScope(\n\t\t\t\tinput.manifest,\n\t\t\t\tloadCandidate(runPath, task.outputDigest, contract.budget).manifest,\n\t\t\t\tdefinition.writablePaths,\n\t\t\t);\n\t}\n\treturn { contract, remainingMs: recovery.remainingMs };\n}\n\nexport function inspectTaskRecovery(runPath: string): TaskRecoveryInspection {\n\tconst snapshot = requireRunJournal(runPath);\n\ttry {\n\t\tconst { contract, remainingMs } = assertDagRecoverable(runPath, snapshot);\n\t\tconst taskIds = snapshot.state.tasks\n\t\t\t.filter(\n\t\t\t\t(task) =>\n\t\t\t\t\t(task.status === \"failed\" || task.status === \"running\") &&\n\t\t\t\t\ttask.attempt < (contract.writer.tasks.find((item) => item.id === task.taskId)?.attempts.length ?? 0),\n\t\t\t)\n\t\t\t.map((task) => task.taskId);\n\t\tassertTaskSelection(contract, snapshot.state, taskIds);\n\t\treturn Object.freeze({\n\t\t\tstate: snapshot.state,\n\t\t\treadiness: \"ready\",\n\t\t\treason: null,\n\t\t\tretryableTaskIds: Object.freeze(taskIds),\n\t\t\tremainingWorkMs: remainingMs,\n\t\t\townership: \"lease_required\",\n\t\t});\n\t} catch (error) {\n\t\tif (!(error instanceof Error)) throw error;\n\t\treturn Object.freeze({\n\t\t\tstate: snapshot.state,\n\t\t\treadiness: \"blocked\",\n\t\t\treason: error instanceof VerifiedRunError ? error.code : \"integrity\",\n\t\t\tretryableTaskIds: Object.freeze([]),\n\t\t\tremainingWorkMs: null,\n\t\t\townership: \"lease_required\",\n\t\t});\n\t}\n}\n\nexport async function retryDagTasks(\n\trunPath: string,\n\tcommand: RunTaskRetryCommand,\n\tsignal?: AbortSignal,\n): Promise<RunProjection> {\n\tif (signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\treturn withRecoveryLease(runPath, command, async ({ snapshot, journal }) => {\n\t\tconst { contract } = assertDagRecoverable(runPath, snapshot);\n\t\tassertTaskSelection(contract, snapshot.state, command.taskIds);\n\t\tpreflightCheckReceipts(contract);\n\t\tprobeVerifiedSandbox();\n\t\tassertDagRecoverable(runPath, snapshot);\n\t\tif (signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tjournal.append({\n\t\t\tkind: \"tasks_retried\",\n\t\t\tcommand,\n\t\t\tobservedMs: readRunClock().nowMs,\n\t\t\treconciledExecutionIds: snapshot.state.activeExecutionIds,\n\t\t\tadopted: taskCheckpoints(snapshot.state),\n\t\t});\n\t\tconst budget = journal.state.budget;\n\t\tif (!budget) throw new VerifiedRunError(\"integrity\");\n\t\tconst deadline = performance.now() + remainingRunTime(budget, budget.workDeadlineMs);\n\t\tconst workspace = join(runPath, `writer-${journal.state.generation}`);\n\t\tconst context = { runPath, contract, journal, ...(signal ? { signal } : {}) };\n\t\tawait executeDag(context, { workspace, deadline });\n\t\tif (journal.state.execution === \"paused\") return journal.state;\n\t\tpublishWriterCandidate(context, workspace, deadline);\n\t\treturn verifyCandidate(context);\n\t});\n}\n"]}
@@ -0,0 +1,98 @@
1
+ import { join } from "node:path";
2
+ import { performance } from "node:perf_hooks";
3
+ import { runDagAncestors } from "omk-protocol";
4
+ import { probeVerifiedSandbox } from "./broker.js";
5
+ import { assertCandidateScope, loadCandidate } from "./candidate.js";
6
+ import { preflightCheckReceipts } from "./check-receipt.js";
7
+ import { composeDagCandidate } from "./dag-candidates.js";
8
+ import { executeDag } from "./dag-phase.js";
9
+ import { assertTaskSelection, taskCheckpoints } from "./dag-retry-projection.js";
10
+ import { readRunClock, remainingRunTime } from "./recovery-clock.js";
11
+ import { requireRunJournal, withRecoveryLease } from "./recovery-command.js";
12
+ import { VerifiedRunError } from "./storage.js";
13
+ import { verifyCandidate } from "./verification-phase.js";
14
+ import { assertWorkRecoverable } from "./work-recovery.js";
15
+ import { publishWriterCandidate } from "./writer-completion.js";
16
+ function assertDagRecoverable(runPath, snapshot) {
17
+ const recovery = assertWorkRecoverable(runPath, snapshot);
18
+ const { contract } = recovery;
19
+ if (contract.profile !== "linux-command-dag-v1")
20
+ throw new VerifiedRunError("task_recovery_unavailable");
21
+ for (const task of snapshot.state.tasks) {
22
+ if (task.status === "pending")
23
+ continue;
24
+ const definition = contract.writer.tasks.find((item) => item.id === task.taskId);
25
+ if (!definition)
26
+ throw new VerifiedRunError("integrity");
27
+ const expected = composeDagCandidate({ runPath, contract, journal: snapshot }, runDagAncestors(contract.writer.tasks, task.taskId));
28
+ const input = loadCandidate(runPath, task.inputDigest, contract.budget);
29
+ if (input.digest !== expected.digest)
30
+ throw new VerifiedRunError("task_checkpoint_mismatch");
31
+ if (task.status === "succeeded")
32
+ assertCandidateScope(input.manifest, loadCandidate(runPath, task.outputDigest, contract.budget).manifest, definition.writablePaths);
33
+ }
34
+ return { contract, remainingMs: recovery.remainingMs };
35
+ }
36
+ export function inspectTaskRecovery(runPath) {
37
+ const snapshot = requireRunJournal(runPath);
38
+ try {
39
+ const { contract, remainingMs } = assertDagRecoverable(runPath, snapshot);
40
+ const taskIds = snapshot.state.tasks
41
+ .filter((task) => (task.status === "failed" || task.status === "running") &&
42
+ task.attempt < (contract.writer.tasks.find((item) => item.id === task.taskId)?.attempts.length ?? 0))
43
+ .map((task) => task.taskId);
44
+ assertTaskSelection(contract, snapshot.state, taskIds);
45
+ return Object.freeze({
46
+ state: snapshot.state,
47
+ readiness: "ready",
48
+ reason: null,
49
+ retryableTaskIds: Object.freeze(taskIds),
50
+ remainingWorkMs: remainingMs,
51
+ ownership: "lease_required",
52
+ });
53
+ }
54
+ catch (error) {
55
+ if (!(error instanceof Error))
56
+ throw error;
57
+ return Object.freeze({
58
+ state: snapshot.state,
59
+ readiness: "blocked",
60
+ reason: error instanceof VerifiedRunError ? error.code : "integrity",
61
+ retryableTaskIds: Object.freeze([]),
62
+ remainingWorkMs: null,
63
+ ownership: "lease_required",
64
+ });
65
+ }
66
+ }
67
+ export async function retryDagTasks(runPath, command, signal) {
68
+ if (signal?.aborted)
69
+ throw new VerifiedRunError("cancelled");
70
+ return withRecoveryLease(runPath, command, async ({ snapshot, journal }) => {
71
+ const { contract } = assertDagRecoverable(runPath, snapshot);
72
+ assertTaskSelection(contract, snapshot.state, command.taskIds);
73
+ preflightCheckReceipts(contract);
74
+ probeVerifiedSandbox();
75
+ assertDagRecoverable(runPath, snapshot);
76
+ if (signal?.aborted)
77
+ throw new VerifiedRunError("cancelled");
78
+ journal.append({
79
+ kind: "tasks_retried",
80
+ command,
81
+ observedMs: readRunClock().nowMs,
82
+ reconciledExecutionIds: snapshot.state.activeExecutionIds,
83
+ adopted: taskCheckpoints(snapshot.state),
84
+ });
85
+ const budget = journal.state.budget;
86
+ if (!budget)
87
+ throw new VerifiedRunError("integrity");
88
+ const deadline = performance.now() + remainingRunTime(budget, budget.workDeadlineMs);
89
+ const workspace = join(runPath, `writer-${journal.state.generation}`);
90
+ const context = { runPath, contract, journal, ...(signal ? { signal } : {}) };
91
+ await executeDag(context, { workspace, deadline });
92
+ if (journal.state.execution === "paused")
93
+ return journal.state;
94
+ publishWriterCandidate(context, workspace, deadline);
95
+ return verifyCandidate(context);
96
+ });
97
+ }
98
+ //# sourceMappingURL=dag-recovery.js.map