@deksden-com/dd-flow-cli 0.9.0-beta.14 → 0.9.0-beta.141

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 (493) hide show
  1. package/CHANGELOG.md +740 -0
  2. package/README.md +143 -1
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +376 -0
  6. package/dist/cli/command-metadata.js +197 -0
  7. package/dist/cli/command-option-descriptions.js +191 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/error-output.js +52 -0
  11. package/dist/cli/executor-onboarding.js +76 -0
  12. package/dist/cli/flows.js +29 -0
  13. package/dist/cli/harnesses.js +84 -0
  14. package/dist/cli/help.js +328 -18
  15. package/dist/cli/hook-ingress.js +78 -0
  16. package/dist/cli/input-preparation.js +165 -0
  17. package/dist/cli/memory-flow-admission.js +44 -0
  18. package/dist/cli/memory-init-invocation.js +78 -0
  19. package/dist/cli/memory-init.js +240 -0
  20. package/dist/cli/memory-storage-admission.js +53 -0
  21. package/dist/cli/models.js +39 -0
  22. package/dist/cli/native-hook-ingress.js +80 -0
  23. package/dist/cli/operator-profiles.js +61 -0
  24. package/dist/cli/output-options.js +35 -0
  25. package/dist/cli/response-file.js +71 -0
  26. package/dist/cli/run-cli.js +1689 -545
  27. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  28. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  29. package/dist/cli/runtime-process.js +153 -0
  30. package/dist/cli/setup.js +149 -0
  31. package/dist/cli.js +71 -2
  32. package/dist/domain/stage-catalog.js +1 -1
  33. package/dist/domain/stage-handler-identities.js +20 -0
  34. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  35. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  36. package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
  37. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  38. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  39. package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
  40. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  41. package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
  42. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  43. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  44. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  45. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  46. package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
  47. package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
  48. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  49. package/dist/harness-runtime/lib/daemon-operations.mjs +371 -0
  50. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
  51. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +728 -0
  52. package/dist/harness-runtime/lib/dd-agy.mjs +70 -0
  53. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  54. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +196 -0
  55. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  56. package/dist/harness-runtime/lib/dd-codex.mjs +817 -0
  57. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +140 -0
  58. package/dist/harness-runtime/lib/dd-droid.mjs +584 -0
  59. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +498 -0
  60. package/dist/harness-runtime/lib/dd-grok.mjs +177 -0
  61. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +557 -0
  62. package/dist/harness-runtime/lib/dd-opencode.mjs +363 -0
  63. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +751 -0
  64. package/dist/harness-runtime/lib/dd-zcode.mjs +1145 -0
  65. package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
  66. package/dist/harness-runtime/lib/delegation-instructions.mjs +157 -0
  67. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  68. package/dist/harness-runtime/lib/driver-recovery.mjs +139 -0
  69. package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
  70. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  71. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  72. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  73. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  74. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
  75. package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
  76. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  77. package/dist/harness-runtime/lib/managed-daemon.mjs +683 -0
  78. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  79. package/dist/harness-runtime/lib/model-observations.mjs +101 -0
  80. package/dist/harness-runtime/lib/native-children.d.mts +16 -0
  81. package/dist/harness-runtime/lib/native-children.mjs +113 -0
  82. package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
  83. package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
  84. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  85. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  86. package/dist/harness-runtime/lib/native-streams.mjs +45 -0
  87. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  88. package/dist/harness-runtime/lib/observation-clock.mjs +92 -0
  89. package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
  90. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  91. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  92. package/dist/harness-runtime/lib/operation-errors.mjs +127 -0
  93. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  94. package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
  95. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  96. package/dist/harness-runtime/lib/process-json.mjs +201 -0
  97. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  98. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +13 -0
  99. package/dist/harness-runtime/lib/provider-overload-policy.mjs +138 -0
  100. package/dist/harness-runtime/lib/runner-events.mjs +200 -0
  101. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  102. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  103. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  104. package/dist/harness-runtime/lib/setup-progress.mjs +51 -0
  105. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  106. package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
  107. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  108. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  109. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  110. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  111. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  112. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  113. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  114. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  115. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  116. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  117. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  118. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  119. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  120. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  121. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  122. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  123. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  124. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  125. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  126. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  127. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  128. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  129. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  130. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  131. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  132. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  133. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  134. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  135. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  136. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  137. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  138. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  139. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  140. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  141. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  142. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  143. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  144. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  145. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  146. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  147. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  148. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  149. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  150. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  151. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  152. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  153. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  154. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  155. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  156. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  157. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  158. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  159. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  160. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  161. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  162. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  163. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  164. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  165. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  166. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  167. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  168. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  169. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  170. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  171. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  172. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  173. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  174. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  175. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  176. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  177. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  178. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  179. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  180. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  181. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  182. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  183. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  184. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  185. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  186. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  187. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  188. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  189. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  190. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  191. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  192. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  193. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  194. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  195. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  196. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  197. package/dist/protocol/local-files.js +18 -9
  198. package/dist/runtime/context.js +8 -4
  199. package/dist/schemas/agent-profile.schema.json +1 -1
  200. package/dist/schemas/code-review-result.schema.json +1 -1
  201. package/dist/schemas/code-verification.schema.json +7 -5
  202. package/dist/schemas/code-work-batch.schema.json +2 -2
  203. package/dist/schemas/discovery-result.schema.json +184 -0
  204. package/dist/schemas/execution-bundle.schema.json +205 -0
  205. package/dist/schemas/execution-settings.schema.json +162 -0
  206. package/dist/schemas/flow-descriptor.schema.json +54 -0
  207. package/dist/schemas/flow-run.schema.json +28 -0
  208. package/dist/schemas/harness-catalog.schema.json +80 -0
  209. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  210. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  211. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  212. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  213. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  214. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  215. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  216. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  217. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  218. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  219. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  220. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  221. package/dist/schemas/model-catalog.schema.json +153 -0
  222. package/dist/schemas/plan-review-decision.schema.json +3 -3
  223. package/dist/schemas/plan-review-result.schema.json +2 -2
  224. package/dist/schemas/profile-settings.schema.json +122 -0
  225. package/dist/schemas/release-manifest.schema.json +291 -0
  226. package/dist/schemas/run-control-receipt.schema.json +118 -0
  227. package/dist/schemas/run-control-request.schema.json +36 -0
  228. package/dist/schemas/run-engine-binding.schema.json +1 -1
  229. package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
  230. package/dist/services/branch-context.js +3 -3
  231. package/dist/services/canon.js +11 -8
  232. package/dist/services/check-runner-evidence.js +250 -0
  233. package/dist/services/cleanup.js +133 -40
  234. package/dist/services/cli-operation-classifier.js +25 -62
  235. package/dist/services/cli-upgrade-allowlist.js +27 -0
  236. package/dist/services/code-checks.js +1168 -107
  237. package/dist/services/codex-hook-delivery.js +32 -0
  238. package/dist/services/command-context.js +80 -0
  239. package/dist/services/compatibility-preflight.js +13 -3
  240. package/dist/services/config.js +11 -8
  241. package/dist/services/continuation-outcome.js +20 -0
  242. package/dist/services/controller-child-capacity.js +13 -0
  243. package/dist/services/controller-child-observer.js +115 -0
  244. package/dist/services/controller-execution.js +88 -0
  245. package/dist/services/controller-fanout.js +202 -0
  246. package/dist/services/dashboard.js +143 -58
  247. package/dist/services/descriptor-coordinator-session.js +35 -0
  248. package/dist/services/descriptor-root-work.js +53 -0
  249. package/dist/services/descriptor-run-settlement.js +105 -0
  250. package/dist/services/descriptor-run-start.js +449 -0
  251. package/dist/services/descriptor-stage-coordinator.js +197 -0
  252. package/dist/services/descriptor-stage-settlement.js +222 -0
  253. package/dist/services/descriptor-stage-start.js +139 -0
  254. package/dist/services/discovery/agy-discovery.js +2 -0
  255. package/dist/services/discovery/codex-discovery.js +2 -0
  256. package/dist/services/discovery/droid-discovery.js +2 -0
  257. package/dist/services/discovery/grok-discovery.js +2 -0
  258. package/dist/services/discovery/opencode-discovery.js +2 -0
  259. package/dist/services/discovery/static.js +31 -0
  260. package/dist/services/discovery/zcode-discovery.js +2 -0
  261. package/dist/services/engines.js +294 -153
  262. package/dist/services/eval-snapshots.js +1215 -116
  263. package/dist/services/execution-bundles.js +263 -0
  264. package/dist/services/execution-policy.js +185 -0
  265. package/dist/services/executor-onboarding.js +56 -0
  266. package/dist/services/external-work-launch.js +308 -0
  267. package/dist/services/flow-catalog.js +21 -0
  268. package/dist/services/flow-descriptors.js +82 -0
  269. package/dist/services/frozen-engine.js +250 -0
  270. package/dist/services/generic-execution.js +164 -0
  271. package/dist/services/harness-adapter.js +355 -36
  272. package/dist/services/harness-config.js +2 -0
  273. package/dist/services/harness-discovery.js +29 -0
  274. package/dist/services/harness-doctor.js +75 -0
  275. package/dist/services/harness-probe-effects.js +51 -0
  276. package/dist/services/harness-version-probe.js +100 -0
  277. package/dist/services/hooks.js +771 -325
  278. package/dist/services/hybrid-contracts.js +483 -0
  279. package/dist/services/ids.js +29 -1
  280. package/dist/services/installation-lock.js +95 -0
  281. package/dist/services/installed-flow-source.js +183 -0
  282. package/dist/services/lanes.js +78 -65
  283. package/dist/services/lifecycle-command.js +1 -288
  284. package/dist/services/lifecycle-contract.js +1 -0
  285. package/dist/services/lifecycle-invocations.js +2007 -0
  286. package/dist/services/managed-daemon-binding.js +38 -0
  287. package/dist/services/managed-lease-monitor.js +133 -0
  288. package/dist/services/managed-processes.js +475 -55
  289. package/dist/services/memory-accepted-composition.js +77 -0
  290. package/dist/services/memory-baseline-preservation.js +65 -0
  291. package/dist/services/memory-completed-correction-wave.js +320 -0
  292. package/dist/services/memory-compose-handler.js +258 -0
  293. package/dist/services/memory-composition-acceptance.js +199 -0
  294. package/dist/services/memory-composition-graph.js +134 -0
  295. package/dist/services/memory-composition-registration.js +146 -0
  296. package/dist/services/memory-composition-work-custody.js +151 -0
  297. package/dist/services/memory-composition-work-results.js +96 -0
  298. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  299. package/dist/services/memory-corrected-review-batch.js +30 -0
  300. package/dist/services/memory-corrected-review-findings.js +106 -0
  301. package/dist/services/memory-corrected-review-inputs.js +210 -0
  302. package/dist/services/memory-corrected-review-projection.js +78 -0
  303. package/dist/services/memory-corrected-review-receipt.js +170 -0
  304. package/dist/services/memory-corrected-review-registration.js +191 -0
  305. package/dist/services/memory-correction-check-receipt.js +219 -0
  306. package/dist/services/memory-correction-input-owner.js +6 -0
  307. package/dist/services/memory-discover-handler.js +104 -0
  308. package/dist/services/memory-finish-evidence.js +435 -0
  309. package/dist/services/memory-finish-handler.js +215 -0
  310. package/dist/services/memory-finish-integration.js +280 -0
  311. package/dist/services/memory-finish-readiness.js +122 -0
  312. package/dist/services/memory-git-integration.js +151 -0
  313. package/dist/services/memory-historical-corrected-review.js +206 -0
  314. package/dist/services/memory-historical-original-review.js +130 -0
  315. package/dist/services/memory-historical-repair-registration.js +99 -0
  316. package/dist/services/memory-historical-second-review.js +128 -0
  317. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  318. package/dist/services/memory-init-contexts.js +89 -0
  319. package/dist/services/memory-init-controller-start.js +84 -0
  320. package/dist/services/memory-init-engine-release.js +223 -0
  321. package/dist/services/memory-init-git-policy.js +136 -0
  322. package/dist/services/memory-init-lint-capability.js +185 -0
  323. package/dist/services/memory-init-native-capacity.js +296 -0
  324. package/dist/services/memory-init-preflight.js +330 -0
  325. package/dist/services/memory-init-project-bootstrap.js +599 -0
  326. package/dist/services/memory-init-request-candidate.js +157 -0
  327. package/dist/services/memory-init-request-input.js +66 -0
  328. package/dist/services/memory-init-resource-storage.js +125 -0
  329. package/dist/services/memory-init-run-allocation.js +81 -0
  330. package/dist/services/memory-init-run-bundle.js +98 -0
  331. package/dist/services/memory-init-start.js +181 -0
  332. package/dist/services/memory-init-startup-custody.js +80 -0
  333. package/dist/services/memory-init-startup-input.js +240 -0
  334. package/dist/services/memory-init-storage.js +81 -0
  335. package/dist/services/memory-init-stores.js +359 -0
  336. package/dist/services/memory-init-worktrunk-capability.js +178 -0
  337. package/dist/services/memory-layer-publication.js +611 -0
  338. package/dist/services/memory-layer.js +156 -0
  339. package/dist/services/memory-lint-config.js +85 -0
  340. package/dist/services/memory-native-review-copy.js +165 -0
  341. package/dist/services/memory-normal-flow-entry.js +75 -0
  342. package/dist/services/memory-ordinary-defaults.js +112 -0
  343. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  344. package/dist/services/memory-preflight-handler.js +259 -0
  345. package/dist/services/memory-repair-current-view.js +299 -0
  346. package/dist/services/memory-repair-document-delta.js +451 -0
  347. package/dist/services/memory-repair-history.js +491 -0
  348. package/dist/services/memory-repair-physical-binding.js +312 -0
  349. package/dist/services/memory-repair-publication-files.js +152 -0
  350. package/dist/services/memory-repair-publication-intent.js +27 -0
  351. package/dist/services/memory-repair-publication-plan.js +160 -0
  352. package/dist/services/memory-repair-publication-source.js +225 -0
  353. package/dist/services/memory-repair-publication.js +794 -0
  354. package/dist/services/memory-repair-registration.js +239 -0
  355. package/dist/services/memory-repair-work-baseline.js +413 -0
  356. package/dist/services/memory-repair-work-completion.js +97 -0
  357. package/dist/services/memory-repair-work-custody.js +73 -0
  358. package/dist/services/memory-repair-work-results.js +89 -0
  359. package/dist/services/memory-repair-workspace.js +252 -0
  360. package/dist/services/memory-repair-writer-copy.js +735 -0
  361. package/dist/services/memory-result-binding.js +173 -0
  362. package/dist/services/memory-retained-review-authority.js +129 -0
  363. package/dist/services/memory-retained-review-results.js +70 -0
  364. package/dist/services/memory-retained-second-baseline.js +102 -0
  365. package/dist/services/memory-retained-second-repairs.js +156 -0
  366. package/dist/services/memory-review-acceptance.js +214 -0
  367. package/dist/services/memory-review-correction-plan.js +171 -0
  368. package/dist/services/memory-review-handler.js +585 -0
  369. package/dist/services/memory-review-inputs.js +200 -0
  370. package/dist/services/memory-review-receipt.js +180 -0
  371. package/dist/services/memory-review-registration.js +108 -0
  372. package/dist/services/memory-review-work-custody.js +124 -0
  373. package/dist/services/memory-review-work-input.js +72 -0
  374. package/dist/services/memory-review-work-results.js +73 -0
  375. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  376. package/dist/services/memory-second-correction-plan.js +76 -0
  377. package/dist/services/memory-second-repair-baseline.js +91 -0
  378. package/dist/services/memory-second-repair-launch.js +614 -0
  379. package/dist/services/memory-second-repair-registration.js +88 -0
  380. package/dist/services/memory-second-repair-source.js +187 -0
  381. package/dist/services/memory-second-review-acceptance.js +115 -0
  382. package/dist/services/memory-source-observations.js +117 -0
  383. package/dist/services/memory-stage-dispatch.js +28 -0
  384. package/dist/services/memory-stage-results.js +199 -0
  385. package/dist/services/memory-verification-acceptance.js +135 -0
  386. package/dist/services/memory-verification-checks.js +252 -0
  387. package/dist/services/memory-verification-receipt.js +159 -0
  388. package/dist/services/memory-verify-handler.js +135 -0
  389. package/dist/services/memory-work-result-preparation.js +63 -0
  390. package/dist/services/merge-queue.js +228 -149
  391. package/dist/services/merge-server.js +161 -35
  392. package/dist/services/migrations.js +37 -16
  393. package/dist/services/model-catalog.js +109 -0
  394. package/dist/services/model-discovery.js +46 -0
  395. package/dist/services/native-daemon-history.js +49 -0
  396. package/dist/services/native-session-control.js +39 -0
  397. package/dist/services/operator-profiles.js +236 -0
  398. package/dist/services/plan-runtime.js +26 -11
  399. package/dist/services/plans.js +28 -25
  400. package/dist/services/projects.js +37 -17
  401. package/dist/services/prompts.js +28 -17
  402. package/dist/services/protocols.js +163 -87
  403. package/dist/services/provider-capacity.js +385 -0
  404. package/dist/services/recovery-observation-budget.js +121 -0
  405. package/dist/services/recovery-snapshot-database.js +560 -0
  406. package/dist/services/release-archive-producer.js +52 -0
  407. package/dist/services/release-archive.js +143 -0
  408. package/dist/services/release-cache.js +142 -0
  409. package/dist/services/release-compatibility.js +18 -0
  410. package/dist/services/release-download.js +67 -0
  411. package/dist/services/release-envelope.js +104 -0
  412. package/dist/services/release-manifest.js +45 -0
  413. package/dist/services/release-payload.js +114 -0
  414. package/dist/services/release-producer.js +63 -0
  415. package/dist/services/release-provenance.js +160 -0
  416. package/dist/services/release-registry.js +66 -0
  417. package/dist/services/release-source.js +194 -0
  418. package/dist/services/repair-intents.js +42 -0
  419. package/dist/services/review-copy.js +165 -0
  420. package/dist/services/review-deferral.js +23 -0
  421. package/dist/services/run-control-receipt.js +56 -0
  422. package/dist/services/run-control-worker.js +411 -0
  423. package/dist/services/run-control.js +1056 -0
  424. package/dist/services/run-controller-adapter.js +399 -0
  425. package/dist/services/run-controller-capture.js +186 -0
  426. package/dist/services/run-controller-process.js +208 -0
  427. package/dist/services/run-controller-recovery.js +289 -0
  428. package/dist/services/run-controller-state.js +97 -0
  429. package/dist/services/run-controller.js +1205 -0
  430. package/dist/services/run-engine-bindings.js +1 -1
  431. package/dist/services/run-fork.js +147 -0
  432. package/dist/services/run-health.js +149 -0
  433. package/dist/services/run-observations.js +152 -0
  434. package/dist/services/run-projection.js +22 -64
  435. package/dist/services/run-recovery-guard.js +77 -0
  436. package/dist/services/run-recovery-runtime.js +112 -0
  437. package/dist/services/run-recovery.js +489 -0
  438. package/dist/services/run-start-custody.js +177 -0
  439. package/dist/services/runs.js +1019 -247
  440. package/dist/services/runtime-budget.js +430 -0
  441. package/dist/services/runtime-command.js +43 -0
  442. package/dist/services/runtime-scope-capture.js +52 -0
  443. package/dist/services/runtime-scope-control.js +468 -0
  444. package/dist/services/runtime-scope-resume.js +599 -0
  445. package/dist/services/runtime-scope-stop.js +210 -0
  446. package/dist/services/runtime-scope-worker.js +287 -0
  447. package/dist/services/runtime-service.js +96 -0
  448. package/dist/services/schema-validation.js +10 -8
  449. package/dist/services/scope-writer-cleanup.js +27 -0
  450. package/dist/services/sessions.js +35 -69
  451. package/dist/services/setup.js +377 -0
  452. package/dist/services/stage-blocker.js +17 -7
  453. package/dist/services/stage-context.js +193 -19
  454. package/dist/services/stage-handlers.js +74 -0
  455. package/dist/services/stage-lifecycle.js +152 -116
  456. package/dist/services/stage-pause.js +89 -75
  457. package/dist/services/stage-report-renderer.js +234 -6
  458. package/dist/services/stage-work-graph.js +52 -0
  459. package/dist/services/tooling.js +41 -30
  460. package/dist/services/usage.js +49 -101
  461. package/dist/services/verification-matrix.js +375 -0
  462. package/dist/services/vnext-code-review.js +223 -88
  463. package/dist/services/vnext-code.js +327 -226
  464. package/dist/services/vnext-contracts.js +10 -1
  465. package/dist/services/vnext-execution-profile.js +80 -5
  466. package/dist/services/vnext-fanout.js +311 -19
  467. package/dist/services/vnext-merge.js +332 -111
  468. package/dist/services/vnext-plan-review.js +279 -127
  469. package/dist/services/vnext-plan.js +228 -104
  470. package/dist/services/vnext-protocolize.js +531 -95
  471. package/dist/services/vnext-specify.js +119 -81
  472. package/dist/services/vnext-workspace-policy.js +7 -2
  473. package/dist/services/work-registry.js +1627 -199
  474. package/dist/services/workspace-bootstrap.js +52 -15
  475. package/dist/services/workspace-files.js +85 -0
  476. package/dist/services/worktrees.js +105 -48
  477. package/dist/shared/entity-references.js +8 -0
  478. package/dist/shared/errors.js +27 -0
  479. package/dist/storage/agent-output.js +26 -0
  480. package/dist/storage/database.js +891 -39
  481. package/dist/storage/foreign-key-transaction.js +39 -0
  482. package/dist/storage/immutable-input.js +45 -0
  483. package/dist/storage/import-guard.js +102 -0
  484. package/dist/storage/native-cleanup.js +52 -0
  485. package/dist/storage/paths.js +17 -4
  486. package/dist/storage/projection-lock.js +73 -0
  487. package/dist/storage/work-references.js +23 -0
  488. package/dist/storage/writer-contract.js +89 -0
  489. package/dist/storage/writer-migration.js +85 -0
  490. package/package.json +43 -13
  491. package/tools/create-canon-release.mjs +33 -0
  492. package/tools/produce-hybrid-release.mjs +41 -0
  493. package/tools/repair-paused-run-status.mjs +84 -0
@@ -0,0 +1,435 @@
1
+ import path from "node:path";
2
+ import fs from "node:fs";
3
+ import { createHash } from "node:crypto";
4
+ import { AppError } from "../shared/errors.js";
5
+ import { RetainedExecutionBundle } from "./execution-bundles.js";
6
+ import { PreparedMemoryFinishReview } from "./memory-finish-handler.js";
7
+ import { PreparedMemoryFinishReadiness } from "./memory-finish-readiness.js";
8
+ import { readDescriptorStageInput } from "./descriptor-stage-coordinator.js";
9
+ import { appendAudit } from "./audit.js";
10
+ import { hybridDigest } from "./hybrid-contracts.js";
11
+ import { prepareStagePacket, acceptStagePacket, publishStagePacket, resolveStagePublicationPath, readAcceptedStageData } from "./stage-report-renderer.js";
12
+ import { ObservedMemorySources } from "./memory-source-observations.js";
13
+ import { memorySourceKey, PreparedMemoryStageResult } from "./memory-stage-results.js";
14
+ import { PreparedDescriptorStageSettlement } from "./descriptor-stage-settlement.js";
15
+ import { assertPreparedRunBundleSqlAuthority } from "./runs.js";
16
+ import { readMemoryInitBootstrapReadiness } from "./memory-init-bootstrap-readiness.js";
17
+ import { readMemoryInitGitPolicy } from "./memory-init-git-policy.js";
18
+ import { reviewedMemoryGitFiles } from "./memory-git-integration.js";
19
+ const token = Symbol("memory-finish-evidence"), event = "memory.finish_evidence";
20
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
21
+ function refuse(reason) {
22
+ throw new AppError("memory_finish_evidence_invalid", "Finish evidence lacks independently prepared acceptance custody", 2, { reason, effect: "no_effect" });
23
+ }
24
+ /** Terminal inventory and receipts belong to the accepted review/evidence
25
+ * owners. Optional echoes cannot introduce new references or semantic claims. */
26
+ export function projectMemoryFinishResult(value, owner, resultSha256) {
27
+ if (!value || typeof value !== "object" || Array.isArray(value))
28
+ return value;
29
+ const candidate = value;
30
+ function reject() {
31
+ if (resultSha256 === undefined)
32
+ refuse("terminal_result_projection_changed");
33
+ throw new AppError("memory_finish_evidence_invalid", "Omit units, findings and details: the CLI preserves accepted review coverage and its finish evidence. Put the completion assessment in summary; correct this proposal without rerunning integration or settled checks", 2, { reason: "terminal_result_projection_changed", phase: "prepare", effect: "no_effect", recoverable: true, result_sha256: resultSha256 });
34
+ }
35
+ const subset = (provided, accepted) => Array.isArray(provided)
36
+ && provided.every(item => accepted.some(original => hybridDigest(item) === hybridDigest(original)));
37
+ if (candidate.units !== undefined) {
38
+ if (!Array.isArray(candidate.units))
39
+ reject();
40
+ const seen = new Set();
41
+ for (const unit of candidate.units) {
42
+ if (!unit || typeof unit !== "object" || Array.isArray(unit))
43
+ reject();
44
+ const selected = owner.units.find(original => original.id === unit.id);
45
+ if (!selected || seen.has(unit.id))
46
+ reject();
47
+ seen.add(unit.id);
48
+ for (const [key, claim] of Object.entries(unit)) {
49
+ if (!Object.hasOwn(selected, key) || (["artifacts", "evidence"].includes(key)
50
+ ? !subset(claim, selected[key]) : hybridDigest(claim) !== hybridDigest(selected[key])))
51
+ reject();
52
+ }
53
+ }
54
+ }
55
+ if (candidate.findings !== undefined && !subset(candidate.findings, owner.findings))
56
+ reject();
57
+ if (candidate.details !== undefined) {
58
+ if (!candidate.details || typeof candidate.details !== "object" || Array.isArray(candidate.details))
59
+ reject();
60
+ for (const [key, claim] of Object.entries(candidate.details)) {
61
+ if (!Object.hasOwn(owner.details, key) || (key === "checks" ? !subset(claim, owner.details.checks)
62
+ : hybridDigest(claim) !== hybridDigest(owner.details[key])))
63
+ reject();
64
+ }
65
+ }
66
+ return { ...candidate, units: owner.units, findings: owner.findings, details: owner.details };
67
+ }
68
+ function records(context, scope) {
69
+ const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type=? AND json_extract(payload_json,'$.run_id')=? LIMIT 2", [scope.projectId, event, scope.runId]);
70
+ if (rows.length > 1 || rows.some(row => Buffer.byteLength(row.payload_json) > 2 * 1024 * 1024))
71
+ refuse("ambiguous_evidence_receipt");
72
+ return rows[0] ? JSON.parse(rows[0].payload_json) : null;
73
+ }
74
+ function acceptance(context, scope) {
75
+ const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='memory.finish_acceptance' AND json_extract(payload_json,'$.run_id')=? LIMIT 2", [scope.projectId, scope.runId]);
76
+ if (rows.length > 1 || rows.some(row => Buffer.byteLength(row.payload_json) > 2 * 1024 * 1024))
77
+ refuse("ambiguous_finish_acceptance");
78
+ return rows[0] ? JSON.parse(rows[0].payload_json) : null;
79
+ }
80
+ /** SQL-only historical byte/projection custody. Callers must independently
81
+ * prepare the genuine accepted review owner outside their writer. This does
82
+ * not re-observe today's integration checkout or grant RUN closure. */
83
+ export function readAcceptedMemoryFinishEvidence(context, input) {
84
+ if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id !== "mb-init"
85
+ || !PreparedMemoryFinishReview.isPrepared(input.review))
86
+ refuse("registered_memory_review_required");
87
+ const scope = { ...input.scope, stage: "finish" };
88
+ input.review.assertCustody(context);
89
+ const run = assertPreparedRunBundleSqlAuthority(context, scope, input.bundle), index = JSON.parse(run.index_json);
90
+ const stage = index.stage_runs.find((item) => item.stage === "finish");
91
+ const evidence = records(context, scope), accepted = acceptance(context, scope);
92
+ const data = readAcceptedStageData(context, scope), reviewData = readAcceptedStageData(context, { ...scope, stage: "review" });
93
+ if (!stage || stage.status !== "done" || !evidence || !accepted
94
+ || evidence.schema_id !== "dd-flow/memory-finish-evidence@1"
95
+ || evidence.project_id !== scope.projectId || evidence.run_id !== scope.runId || evidence.stage !== "finish"
96
+ || evidence.attempt !== stage.attempt || evidence.input_sha256 !== stage.input_sha256
97
+ || evidence.bundle_sha256 !== input.bundle.sha256 || evidence.review_sha256 !== reviewData.result.sha256
98
+ || !input.review.bytes().equals(reviewData.bytes)
99
+ || data.data_schema_id !== "dd-flow/mb-init-finish-result@1" || data.input_sha256 !== stage.input_sha256
100
+ || hybridDigest(evidence.checks) !== hybridDigest(input.review.finalChecks(context)))
101
+ refuse("accepted_finish_evidence_changed");
102
+ const expectedAcceptance = { schema_id: "dd-flow/memory-finish-acceptance@1", project_id: scope.projectId, run_id: scope.runId,
103
+ stage: "finish", attempt: stage.attempt, input_sha256: stage.input_sha256, bundle_sha256: input.bundle.sha256,
104
+ evidence_sha256: hybridDigest(evidence), result_sha256: data.result.sha256 };
105
+ if (hybridDigest(accepted) !== hybridDigest(expectedAcceptance))
106
+ refuse("accepted_finish_receipt_changed");
107
+ const root = run.run_root ?? run.run_dir;
108
+ const packet = (ref, name) => {
109
+ if (!ref || typeof ref.path !== "string" || typeof ref.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(ref.sha256)
110
+ || ref.path !== `${input.bundle.descriptor.stage("finish").directory}/evidence/${name}.json`)
111
+ refuse("historical_evidence_reference_changed");
112
+ const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='flow_run.stage_packet' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.stage')='finish' AND json_extract(payload_json,'$.sha256')=? LIMIT 2", [scope.projectId, scope.runId, ref.sha256]);
113
+ if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 4 * 1024 * 1024)
114
+ refuse("historical_evidence_packet_missing");
115
+ const value = JSON.parse(rows[0].payload_json);
116
+ if (value.attempt !== stage.attempt || typeof value.base64 !== "string" || typeof value.file !== "string"
117
+ || resolveStagePublicationPath(context, scope.projectId, scope.runId, value.file) !== path.join(root, ref.path))
118
+ refuse("historical_evidence_packet_changed");
119
+ const bytes = Buffer.from(value.base64, "base64");
120
+ if (!bytes.length || bytes.length > 2 * 1024 * 1024 || bytes.toString("base64") !== value.base64 || hash(bytes) !== ref.sha256)
121
+ refuse("historical_evidence_bytes_changed");
122
+ return { bytes, value: JSON.parse(bytes.toString("utf8")) };
123
+ };
124
+ const coverage = packet(evidence.coverage, "coverage"), integration = packet(evidence.integration, "integration"), readiness = packet(evidence.normal_flow_readiness, "normal-flow-readiness");
125
+ const reviewed = JSON.parse(input.review.bytes().toString("utf8"));
126
+ if (hybridDigest(coverage.value) !== hybridDigest({ schema_id: "dd-flow/memory-finish-coverage@1", project_id: scope.projectId,
127
+ run_id: scope.runId, bundle_sha256: input.bundle.sha256, review_sha256: reviewData.result.sha256,
128
+ units: reviewed.units, findings: reviewed.findings }) || hybridDigest(readiness.value) !== evidence.readiness_sha256
129
+ || hybridDigest(readiness.value.integration) !== hybridDigest(integration.value)
130
+ || readiness.value.schema_id !== "dd-flow/memory-finish-readiness-observation@1"
131
+ || hybridDigest(readiness.value.scope) !== hybridDigest(input.scope)
132
+ || readiness.value.bundle_sha256 !== input.bundle.sha256 || readiness.value.execution_sha256 !== input.bundle.execution.sha256
133
+ || readiness.value.readiness !== "entry_prepared" || readiness.value.model_access !== "unknown")
134
+ refuse("historical_evidence_projection_changed");
135
+ const frozen = input.bundle.execution.snapshot().scope;
136
+ const request = { requestId: frozen.requestId, projectRoot: frozen.projectRoot, workspaceRoot: frozen.workspace };
137
+ const bootstrap = readMemoryInitBootstrapReadiness(context, request), policy = readMemoryInitGitPolicy(context, request);
138
+ if (!bootstrap || !policy || bootstrap.projectId !== scope.projectId
139
+ || bootstrap.authority.binding.execution_sha256 !== input.bundle.execution.sha256
140
+ || bootstrap.authority.binding.git_policy_sha256 !== hybridDigest(policy)
141
+ || policy.target_sha256 !== hybridDigest(bootstrap.authority.binding.target)
142
+ || readiness.value.bootstrap_authority_sha256 !== hybridDigest(bootstrap.authority)
143
+ || readiness.value.pack_sha256 !== bootstrap.authority.binding.pack_sha256)
144
+ refuse("historical_terminal_bootstrap_policy_changed");
145
+ const integrated = integration.value;
146
+ const reviewedFiles = reviewedMemoryGitFiles(input.review.reviewedSources(context));
147
+ if (integrated.schema_id !== "dd-flow/memory-git-integration-observation@1"
148
+ || integrated.project_root !== request.projectRoot || integrated.workspace_root !== request.workspaceRoot
149
+ || integrated.repository !== policy.repository || integrated.workspace_branch !== policy.workspace_branch
150
+ || integrated.integration_ref !== `refs/heads/${policy.integration_branch}`
151
+ || integrated.reviewed_files_sha256 !== hybridDigest(reviewedFiles)
152
+ || !reviewedFiles.some(ref => ref.path === ".memory-bank/index.md")
153
+ || [integrated.workspace_head, integrated.integration_head, integrated.memory_tree]
154
+ .some(value => typeof value !== "string" || !/^[a-f0-9]{40,64}$/.test(value))
155
+ || [integrated.tracked_index_entry_sha256, integrated.memory_index_visibility_sha256, integrated.memory_status_sha256]
156
+ .some(value => typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)))
157
+ refuse("historical_terminal_integration_policy_changed");
158
+ const sources = new Map();
159
+ for (const ref of input.review.reviewedSources(context)) {
160
+ sources.set(memorySourceKey(ref.root, ref.path), ref.sha256);
161
+ if (ref.root === "workspace")
162
+ sources.set(memorySourceKey("project", ref.path), ref.sha256);
163
+ }
164
+ for (const ref of [evidence.coverage, evidence.integration, evidence.normal_flow_readiness, ...evidence.checks])
165
+ sources.set(memorySourceKey("run", ref.path), ref.sha256);
166
+ const result = PreparedMemoryStageResult.prepare(data.bytes, input.bundle.descriptor, {
167
+ runId: scope.runId, stage: "finish", inputSha256: stage.input_sha256,
168
+ predecessors: [{ stage: "review", result: reviewData.result, input_sha256: reviewData.input_sha256 }],
169
+ unitIds: reviewed.units.map((unit) => unit.id), sources,
170
+ historicalEvidence: new Set(reviewed.units.flatMap((unit) => unit.evidence.map(ref => `${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)))
171
+ });
172
+ const value = result.value(), references = { coverage: evidence.coverage,
173
+ checks: evidence.checks.map(({ path, sha256 }) => ({ path, sha256 })),
174
+ integration: evidence.integration, normal_flow_readiness: evidence.normal_flow_readiness };
175
+ if (value.outcome !== "accepted" || hybridDigest(value.units) !== hybridDigest(reviewed.units)
176
+ || hybridDigest(value.findings) !== hybridDigest(reviewed.findings) || hybridDigest(value.details) !== hybridDigest(references))
177
+ refuse("historical_finish_result_projection_changed");
178
+ input.review.assertCustody(context);
179
+ return { receipt: structuredClone(accepted), evidence: structuredClone(evidence), result: data,
180
+ packets: [coverage, integration, readiness].map((item, i) => ({ ...item,
181
+ reference: structuredClone([evidence.coverage, evidence.integration, evidence.normal_flow_readiness][i]) })) };
182
+ }
183
+ /** Independently constructed terminal artifacts, retained atomically and
184
+ * published by the existing Stage packet mechanism. This is not a Stage/RUN
185
+ * acceptance receipt: publication can be pending after the SQL commit. */
186
+ export class PreparedMemoryFinishEvidence {
187
+ static isPrepared(value) {
188
+ return typeof value === "object" && value !== null && #review in value;
189
+ }
190
+ #scope;
191
+ #bundle;
192
+ #review;
193
+ #readiness;
194
+ #input;
195
+ #packets;
196
+ #receipt;
197
+ #registered;
198
+ constructor(key, scope, bundle, review, readiness, input, packets, receipt, registered) {
199
+ if (key !== token)
200
+ refuse("evidence_token_required");
201
+ this.#scope = scope;
202
+ this.#bundle = bundle;
203
+ this.#review = review;
204
+ this.#readiness = readiness;
205
+ this.#input = input;
206
+ this.#packets = packets;
207
+ this.#receipt = structuredClone(receipt);
208
+ this.#registered = registered;
209
+ Object.freeze(this);
210
+ }
211
+ static prepare(context, input) {
212
+ if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id !== "mb-init")
213
+ refuse("registered_memory_bundle_required");
214
+ if (context.db.isOwnedWriteTransaction?.())
215
+ refuse("preparation_outside_writer_required");
216
+ const scope = { ...input.scope, stage: "finish" }, selected = context.db.readSnapshot(() => readDescriptorStageInput(context, scope, input.bundle));
217
+ const prior = context.db.readSnapshot(() => records(context, scope));
218
+ const review = PreparedMemoryFinishReview.prepare(context, input), readiness = PreparedMemoryFinishReadiness.prepare(context, input);
219
+ const value = JSON.parse(review.bytes().toString("utf8")), ready = readiness.value(), checks = review.finalChecks(context);
220
+ const materials = [
221
+ { name: "coverage", value: { schema_id: "dd-flow/memory-finish-coverage@1", project_id: scope.projectId, run_id: scope.runId,
222
+ bundle_sha256: input.bundle.sha256, review_sha256: hash(review.bytes()), units: value.units, findings: value.findings } },
223
+ { name: "integration", value: ready.integration }, { name: "normal-flow-readiness", value: ready }
224
+ ];
225
+ const packets = materials.map(item => {
226
+ const bytes = Buffer.from(`${JSON.stringify(item.value, null, 2)}\n`);
227
+ if (bytes.length > 2 * 1024 * 1024)
228
+ refuse("evidence_artifact_exceeds_bound");
229
+ const file = path.join(selected.runRoot, input.bundle.descriptor.stage("finish").directory, "evidence", `${item.name}.json`);
230
+ if (!prior) {
231
+ try {
232
+ fs.lstatSync(file);
233
+ refuse("evidence_custody_missing");
234
+ }
235
+ catch (error) {
236
+ if (error.code !== "ENOENT")
237
+ throw error;
238
+ }
239
+ if (context.db.get("SELECT 1 FROM audit_events WHERE project_id=? AND event_type='flow_run.stage_packet' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.stage')='finish' AND json_extract(payload_json,'$.sha256')=? LIMIT 1", [scope.projectId, scope.runId, hash(bytes)]))
240
+ refuse("evidence_custody_missing");
241
+ }
242
+ return prepareStagePacket(file, bytes);
243
+ });
244
+ const reference = (index) => ({ path: path.relative(selected.runRoot, packets[index].file).split(path.sep).join("/"), sha256: packets[index].sha256 });
245
+ const receipt = { schema_id: "dd-flow/memory-finish-evidence@1", project_id: scope.projectId, run_id: scope.runId, stage: "finish",
246
+ attempt: selected.attempt, input_sha256: selected.inputSha256, bundle_sha256: input.bundle.sha256,
247
+ review_sha256: hash(review.bytes()), readiness_sha256: hybridDigest(ready), coverage: reference(0), checks,
248
+ integration: reference(1), normal_flow_readiness: reference(2) };
249
+ if (Buffer.byteLength(JSON.stringify(receipt)) > 2 * 1024 * 1024)
250
+ refuse("evidence_receipt_exceeds_bound");
251
+ if (prior && hybridDigest(prior) !== hybridDigest(receipt))
252
+ refuse("evidence_request_conflict");
253
+ const prepared = new PreparedMemoryFinishEvidence(token, scope, input.bundle, review, readiness, selected, packets, receipt, !!prior);
254
+ prepared.assertCustody(context);
255
+ return prepared;
256
+ }
257
+ receipt() { return structuredClone(this.#receipt); }
258
+ references() {
259
+ const value = this.#receipt;
260
+ return { coverage: { ...value.coverage }, checks: value.checks.map(({ path, sha256 }) => ({ path, sha256 })),
261
+ integration: { ...value.integration }, normal_flow_readiness: { ...value.normal_flow_readiness } };
262
+ }
263
+ /** Fresh terminal result preparation, never a historical replay reader.
264
+ * The proposal cannot replace accepted review coverage or CLI evidence. */
265
+ prepareResult(context, bytes) {
266
+ const bundle = this.#bundle;
267
+ if (!(bytes instanceof Uint8Array) || !bytes.length || bytes.length > 1024 * 1024)
268
+ refuse("invalid_result_bytes");
269
+ if (context.db.isOwnedWriteTransaction?.())
270
+ refuse("physical_preparation_outside_writer_required");
271
+ this.revalidate(context);
272
+ const sources = this.captureSources(context);
273
+ const review = readAcceptedStageData(context, { ...this.#scope, stage: "review" });
274
+ if (typeof review.input_sha256 !== "string")
275
+ refuse("accepted_review_input_missing");
276
+ const reviewed = JSON.parse(this.#review.bytes().toString("utf8"));
277
+ let proposal;
278
+ try {
279
+ proposal = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
280
+ }
281
+ catch {
282
+ refuse("invalid_result_bytes");
283
+ }
284
+ const canonical = projectMemoryFinishResult(proposal, { units: reviewed.units, findings: reviewed.findings, details: this.references() }, hash(bytes));
285
+ const result = PreparedMemoryStageResult.prepare(Buffer.from(JSON.stringify(canonical)), bundle.descriptor, {
286
+ runId: this.#scope.runId, stage: "finish", inputSha256: this.#input.inputSha256,
287
+ predecessors: [{ stage: "review", result: review.result, input_sha256: review.input_sha256 }],
288
+ unitIds: reviewed.units.map((unit) => unit.id), sources: sources.hashes(),
289
+ historicalEvidence: new Set(reviewed.units.flatMap((unit) => unit.evidence.map(ref => `${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)))
290
+ });
291
+ const value = result.value();
292
+ if (value.outcome !== "accepted" || hybridDigest(value.units) !== hybridDigest(reviewed.units)
293
+ || hybridDigest(value.findings) !== hybridDigest(reviewed.findings)
294
+ || hybridDigest(value.details) !== hybridDigest(this.references()))
295
+ refuse("terminal_result_projection_changed");
296
+ sources.revalidate();
297
+ this.revalidate(context);
298
+ this.assertRegisteredCustody(context);
299
+ return result;
300
+ }
301
+ /** Fresh Stage acceptance only. RUN closure and accepted historical replay
302
+ * require their independent terminal readers; neither is granted here. */
303
+ settleFresh(context, input) {
304
+ const scope = this.#scope;
305
+ if (context.db.isOwnedWriteTransaction?.())
306
+ refuse("settlement_preparation_outside_writer_required");
307
+ if (acceptance(context, scope))
308
+ refuse("use_accepted_finish_replay");
309
+ const result = this.prepareResult(context, input.bytes);
310
+ const receipt = { schema_id: "dd-flow/memory-finish-acceptance@1", project_id: scope.projectId, run_id: scope.runId,
311
+ stage: "finish", attempt: this.#input.attempt, input_sha256: this.#input.inputSha256,
312
+ bundle_sha256: this.#bundle.sha256, evidence_sha256: hybridDigest(this.#receipt), result_sha256: result.sha256 };
313
+ const settlement = PreparedDescriptorStageSettlement.prepare(context, {
314
+ projectRoot: this.#bundle.execution.snapshot().scope.projectRoot, runId: scope.runId, stage: "finish",
315
+ hookEventId: input.hookEventId, bytes: result.bytes()
316
+ });
317
+ this.revalidate(context);
318
+ try {
319
+ return settlement.apply(context, writer => {
320
+ this.assertRegisteredCustody(writer);
321
+ if (!writer.db.isOwnedWriteTransaction?.())
322
+ refuse("owned_acceptance_writer_required");
323
+ if (acceptance(writer, scope))
324
+ refuse("fresh_acceptance_already_exists");
325
+ appendAudit(writer, { projectId: scope.projectId, eventType: "memory.finish_acceptance", payload: receipt });
326
+ if (hybridDigest(acceptance(writer, scope)) !== hybridDigest(receipt))
327
+ refuse("finish_acceptance_readback_failed");
328
+ });
329
+ }
330
+ catch (error) {
331
+ if (hybridDigest(acceptance(context, scope)) === hybridDigest(receipt))
332
+ throw new AppError("memory_finish_acceptance_pending", "Finish acceptance committed; terminal recovery remains required", 1, { effect: "committed", run_id: scope.runId, result_sha256: result.sha256,
333
+ next_action: "reconcile_accepted_finish", cause: error instanceof AppError ? error.code : "finish_settlement_failure" });
334
+ throw error;
335
+ }
336
+ }
337
+ assertCustody(context) {
338
+ this.#review.assertCustody(context);
339
+ this.#readiness.assertCustody(context);
340
+ if (hybridDigest(readDescriptorStageInput(context, this.#scope, this.#bundle)) !== hybridDigest(this.#input))
341
+ refuse("finish_input_changed");
342
+ const prior = records(context, this.#scope);
343
+ if (this.#registered && !prior || prior && hybridDigest(prior) !== hybridDigest(this.#receipt))
344
+ refuse("evidence_receipt_changed");
345
+ if (prior)
346
+ for (const packet of this.#packets) {
347
+ const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type='flow_run.stage_packet' AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.stage')='finish' AND json_extract(payload_json,'$.sha256')=? LIMIT 2", [this.#scope.projectId, this.#scope.runId, packet.sha256]);
348
+ if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 4 * 1024 * 1024)
349
+ refuse("evidence_packet_custody_missing");
350
+ const stored = JSON.parse(rows[0].payload_json);
351
+ if (stored.attempt !== this.#input.attempt || stored.base64 !== packet.bytes.toString("base64")
352
+ || resolveStagePublicationPath(context, this.#scope.projectId, this.#scope.runId, stored.file) !== packet.file)
353
+ refuse("evidence_packet_changed");
354
+ }
355
+ }
356
+ assertRegisteredCustody(context) {
357
+ if (!this.#registered)
358
+ refuse("registered_evidence_required");
359
+ this.assertCustody(context);
360
+ }
361
+ /** Only independently selected final sources may bind terminal result bytes. */
362
+ captureSources(context) {
363
+ const bundle = this.#bundle;
364
+ if (context.db.isOwnedWriteTransaction?.())
365
+ refuse("physical_preparation_outside_writer_required");
366
+ this.assertRegisteredCustody(context);
367
+ const expected = new Map();
368
+ const add = (location, sha256) => {
369
+ const key = memorySourceKey(location.root, location.path), prior = expected.get(key);
370
+ if (prior && prior.sha256 !== sha256)
371
+ refuse("conflicting_terminal_sources");
372
+ expected.set(key, { location, sha256 });
373
+ };
374
+ for (const ref of this.#review.reviewedSources(context)) {
375
+ add({ root: ref.root, path: ref.path }, ref.sha256);
376
+ if (ref.root === "workspace")
377
+ add({ root: "project", path: ref.path }, ref.sha256);
378
+ }
379
+ for (const ref of [this.#receipt.coverage, this.#receipt.integration, this.#receipt.normal_flow_readiness, ...this.#receipt.checks])
380
+ add({ root: "run", path: ref.path }, ref.sha256);
381
+ const frozen = bundle.execution.snapshot().scope;
382
+ const observed = ObservedMemorySources.capture({ run: this.#input.runRoot, project: frozen.projectRoot, workspace: frozen.workspace }, [...expected.values()].map(item => item.location));
383
+ const hashes = observed.hashes();
384
+ for (const [key, item] of expected)
385
+ if (hashes.get(key) !== item.sha256)
386
+ refuse("terminal_source_bytes_changed");
387
+ this.assertRegisteredCustody(context);
388
+ return observed;
389
+ }
390
+ revalidate(context) {
391
+ const readiness = this.#readiness;
392
+ if (context.db.isOwnedWriteTransaction?.())
393
+ refuse("physical_revalidation_outside_writer_required");
394
+ this.#review.revalidate(context);
395
+ readiness.revalidate(context);
396
+ this.assertCustody(context);
397
+ }
398
+ register(context) {
399
+ const scope = this.#scope;
400
+ if (context.db.isOwnedWriteTransaction?.())
401
+ refuse("registration_outside_writer_required");
402
+ try {
403
+ this.revalidate(context);
404
+ const replay = context.db.writeTransaction(() => {
405
+ this.assertCustody(context);
406
+ if (records(context, this.#scope))
407
+ return true;
408
+ for (const packet of this.#packets)
409
+ acceptStagePacket(context, { ...this.#scope, prepared: packet });
410
+ appendAudit(context, { projectId: this.#scope.projectId, eventType: event, payload: this.#receipt });
411
+ this.assertCustody(context);
412
+ return false;
413
+ }, "memory.registerFinishEvidence");
414
+ this.#registered = true;
415
+ for (const packet of this.#packets)
416
+ publishStagePacket(context, this.#scope.projectId, this.#scope.runId, "finish", packet.file);
417
+ const observed = ObservedMemorySources.capture({ run: this.#input.runRoot }, this.#packets.map(packet => ({ root: "run", path: path.relative(this.#input.runRoot, packet.file).split(path.sep).join("/") })));
418
+ const hashes = observed.hashes();
419
+ for (const ref of [this.#receipt.coverage, this.#receipt.integration, this.#receipt.normal_flow_readiness])
420
+ if (hashes.get(memorySourceKey("run", ref.path)) !== ref.sha256)
421
+ refuse("published_evidence_changed");
422
+ this.revalidate(context);
423
+ return { receipt: this.receipt(), references: this.references(), replay };
424
+ }
425
+ catch (error) {
426
+ const retained = records(context, scope);
427
+ if (retained && hybridDigest(retained) === hybridDigest(this.#receipt)) {
428
+ this.#registered = true;
429
+ throw new AppError("memory_finish_evidence_pending", "Finish evidence retained; publication or revalidation requires recovery", 1, { effect: "committed", run_id: this.#scope.runId, receipt_sha256: hybridDigest(this.#receipt),
430
+ next_action: "reconcile_exact_finish_evidence", cause: error instanceof AppError ? error.code : "evidence_publication_failure" });
431
+ }
432
+ throw error;
433
+ }
434
+ }
435
+ }
@@ -0,0 +1,215 @@
1
+ import { AppError } from "../shared/errors.js";
2
+ import { RetainedExecutionBundle } from "./execution-bundles.js";
3
+ import { readAcceptedStageData } from "./stage-report-renderer.js";
4
+ import { PreparedAcceptedMemoryInitialReview } from "./memory-review-receipt.js";
5
+ import { PreparedAcceptedMemoryCorrectedReview } from "./memory-corrected-review-receipt.js";
6
+ import { PreparedDescriptorStageStart } from "./descriptor-stage-start.js";
7
+ import { PreparedDescriptorStageCoordinator } from "./descriptor-stage-coordinator.js";
8
+ import { assertPreparedRunBundleSqlAuthority, readFlowRunExecutionBundle } from "./runs.js";
9
+ import { requireProjectByRoot } from "./projects.js";
10
+ import { resolveProjectRoot } from "../storage/paths.js";
11
+ import path from "node:path";
12
+ import { hybridDigest } from "./hybrid-contracts.js";
13
+ import { readAcceptedMemoryFinishEvidence, PreparedMemoryFinishEvidence, projectMemoryFinishResult } from "./memory-finish-evidence.js";
14
+ import { PreparedDescriptorStageSettlement } from "./descriptor-stage-settlement.js";
15
+ import { publishStagePacket } from "./stage-report-renderer.js";
16
+ import { PreparedDescriptorRunSettlement } from "./descriptor-run-settlement.js";
17
+ import { integrateMemoryFinish } from "./memory-finish-integration.js";
18
+ const token = Symbol("memory-finish-review-predecessor");
19
+ function refuse(reason) {
20
+ throw new AppError("memory_finish_handler_invalid", "Memory finish lacks independently accepted predecessor custody", 2, { reason, effect: "no_effect" });
21
+ }
22
+ function selected(context, scope) {
23
+ const data = readAcceptedStageData(context, { ...scope, stage: "review" });
24
+ // A missing corrected acceptance receipt must never reopen initial review.
25
+ // Existing repair registration independently selects the corrected branch.
26
+ const corrected = !!context.db.get(`SELECT 1 FROM audit_events WHERE project_id=?
27
+ AND event_type IN ('memory.repair_registration','memory.second_repair_registration','memory.corrected_review_acceptance')
28
+ AND json_extract(payload_json,'$.run_id')=?
29
+ AND (json_extract(payload_json,'$.scope.input_sha256')=? OR json_extract(payload_json,'$.input_sha256')=?) LIMIT 1`, [scope.projectId, scope.runId, data.input_sha256, data.input_sha256]);
30
+ return { data, corrected };
31
+ }
32
+ /** Closed review predecessor proof only. It does not establish integration,
33
+ * normal-flow readiness, terminal Stage acceptance or RUN completion. */
34
+ export class PreparedMemoryFinishReview {
35
+ static isPrepared(value) {
36
+ return typeof value === "object" && value !== null && #review in value;
37
+ }
38
+ #scope;
39
+ #review;
40
+ #authority;
41
+ #corrected;
42
+ #bytes;
43
+ constructor(key, scope, review, data) {
44
+ if (key !== token)
45
+ refuse("finish_review_token_required");
46
+ this.#scope = { ...scope };
47
+ this.#review = review;
48
+ this.#authority = data.data.authority_sha256;
49
+ this.#corrected = data.corrected;
50
+ this.#bytes = Buffer.from(data.data.bytes);
51
+ Object.freeze(this);
52
+ }
53
+ static prepare(context, input) {
54
+ if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id !== "mb-init"
55
+ || input.bundle.descriptor.successor("review", "accepted") !== "finish")
56
+ refuse("registered_memory_bundle_required");
57
+ if (context.db.isOwnedWriteTransaction?.())
58
+ refuse("preparation_outside_writer_required");
59
+ assertPreparedRunBundleSqlAuthority(context, input.scope, input.bundle);
60
+ const data = context.db.readSnapshot(() => selected(context, input.scope));
61
+ const review = data.corrected
62
+ ? PreparedAcceptedMemoryCorrectedReview.prepare(context, { ...input, bytes: data.data.bytes })
63
+ : PreparedAcceptedMemoryInitialReview.prepare(context, { ...input, bytes: data.data.bytes });
64
+ const prepared = new PreparedMemoryFinishReview(token, input.scope, review, data);
65
+ prepared.revalidate(context);
66
+ return prepared;
67
+ }
68
+ bytes() { return Buffer.from(this.#bytes); }
69
+ reviewedSources(context) { this.assertCustody(context); return this.#review.reviewedSources(context); }
70
+ finalChecks(context) { this.assertCustody(context); return this.#review.finalChecks(context); }
71
+ assertCustody(context) {
72
+ this.#review.assertCustody(context);
73
+ const data = selected(context, this.#scope);
74
+ if (data.corrected !== this.#corrected || data.data.authority_sha256 !== this.#authority
75
+ || !data.data.bytes.equals(this.#bytes))
76
+ refuse("accepted_review_changed");
77
+ }
78
+ revalidate(context) { this.#review.revalidate(context); this.assertCustody(context); }
79
+ }
80
+ /** Productive terminal entry awaiting the complete six-stage registry. Opens
81
+ * only after historical review proof; no provider dispatch or Git mutation.
82
+ * Terminal settlement must separately prove integration and readiness. */
83
+ export function startMemoryFinish(context, input) {
84
+ if (!(input.bytes instanceof Uint8Array) || input.bytes.length > 1024 * 1024)
85
+ refuse("invalid_input_bytes");
86
+ const bundle = readFlowRunExecutionBundle(context, input);
87
+ if (!bundle || bundle.descriptor.descriptor.id !== "mb-init" || !bundle.descriptor.descriptor.terminal_stages.includes("finish")
88
+ || bundle.descriptor.successor("review", "accepted") !== "finish")
89
+ refuse("registered_memory_bundle_required");
90
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
91
+ const run = assertPreparedRunBundleSqlAuthority(context, scope, bundle);
92
+ if (JSON.parse(run.index_json).stage_runs.some((stage) => stage.stage === "finish" && stage.status === "done"))
93
+ refuse("use_accepted_finish_replay");
94
+ const review = PreparedMemoryFinishReview.prepare(context, { scope, bundle });
95
+ const start = PreparedDescriptorStageStart.prepare(context, { ...input, stage: "finish" });
96
+ review.revalidate(context);
97
+ const stage = start.apply(context, writer => review.assertCustody(writer));
98
+ const coordinator = PreparedDescriptorStageCoordinator.prepare(context, { ...input, stage: "finish" });
99
+ review.revalidate(context);
100
+ return { ...stage, ...coordinator.apply(context, writer => review.assertCustody(writer)) };
101
+ }
102
+ /** Restore accepted finish projections using historical custody only. This
103
+ * never re-admits current project bytes or closes the root Work/RUN. */
104
+ export function replayAcceptedMemoryFinish(context, input) {
105
+ if (!(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
106
+ refuse("invalid_input_bytes");
107
+ if (context.db.isOwnedWriteTransaction?.())
108
+ refuse("preparation_outside_writer_required");
109
+ const bundle = readFlowRunExecutionBundle(context, input);
110
+ if (!bundle || bundle.descriptor.descriptor.id !== "mb-init")
111
+ refuse("registered_memory_bundle_required");
112
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
113
+ const review = PreparedMemoryFinishReview.prepare(context, { scope, bundle });
114
+ const retained = context.db.readSnapshot(() => readAcceptedMemoryFinishEvidence(context, { scope, bundle, review }));
115
+ let proposal;
116
+ try {
117
+ proposal = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(input.bytes));
118
+ }
119
+ catch {
120
+ refuse("invalid_input_bytes");
121
+ }
122
+ const canonical = JSON.parse(retained.result.bytes.toString("utf8"));
123
+ if (hybridDigest(projectMemoryFinishResult(proposal, canonical)) !== hybridDigest(canonical))
124
+ refuse("accepted_finish_bytes_changed");
125
+ const authority = hybridDigest(retained);
126
+ const settlement = PreparedDescriptorStageSettlement.prepare(context, { ...input, stage: "finish", bytes: retained.result.bytes });
127
+ review.revalidate(context);
128
+ try {
129
+ const result = settlement.apply(context, writer => {
130
+ if (hybridDigest(readAcceptedMemoryFinishEvidence(writer, { scope, bundle, review })) !== authority)
131
+ refuse("accepted_finish_custody_changed");
132
+ });
133
+ const run = assertPreparedRunBundleSqlAuthority(context, scope, bundle), root = run.run_root ?? run.run_dir;
134
+ for (const packet of retained.packets)
135
+ publishStagePacket(context, scope.projectId, scope.runId, "finish", path.join(root, packet.reference.path));
136
+ review.revalidate(context);
137
+ if (hybridDigest(context.db.readSnapshot(() => readAcceptedMemoryFinishEvidence(context, { scope, bundle, review }))) !== authority)
138
+ refuse("accepted_finish_custody_changed");
139
+ return result;
140
+ }
141
+ catch (error) {
142
+ throw new AppError("memory_finish_replay_pending", "Accepted finish remains retained; projection recovery is incomplete", 1, { effect: "committed", run_id: scope.runId, next_action: "reconcile_accepted_finish",
143
+ cause: error instanceof AppError ? error.code : "finish_replay_failure" });
144
+ }
145
+ }
146
+ /** Close only the independently accepted terminal RUN. This does not perform
147
+ * Git integration, create evidence or accept a fresh finish proposal. */
148
+ export function settleAcceptedMemoryRun(context, input) {
149
+ if (context.db.isOwnedWriteTransaction?.())
150
+ refuse("preparation_outside_writer_required");
151
+ const bundle = readFlowRunExecutionBundle(context, input);
152
+ if (!bundle || bundle.descriptor.descriptor.id !== "mb-init"
153
+ || !bundle.descriptor.descriptor.terminal_stages.includes("finish"))
154
+ refuse("registered_memory_bundle_required");
155
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
156
+ const review = PreparedMemoryFinishReview.prepare(context, { scope, bundle });
157
+ const retained = context.db.readSnapshot(() => readAcceptedMemoryFinishEvidence(context, { scope, bundle, review }));
158
+ const authority = hybridDigest(retained);
159
+ const settlement = PreparedDescriptorRunSettlement.prepare(context, { ...input, stage: "finish" });
160
+ review.revalidate(context);
161
+ try {
162
+ return settlement.apply(context, writer => {
163
+ if (hybridDigest(readAcceptedMemoryFinishEvidence(writer, { scope, bundle, review })) !== authority)
164
+ refuse("accepted_finish_custody_changed");
165
+ });
166
+ }
167
+ catch (error) {
168
+ if (context.db.get("SELECT status FROM runs WHERE project_id=? AND id=?", [scope.projectId, scope.runId])?.status === "done")
169
+ throw new AppError("memory_run_settlement_pending", "Accepted memory RUN committed; projection recovery remains required", 1, { effect: "committed", run_id: scope.runId, next_action: "reconcile_accepted_memory_run",
170
+ cause: error instanceof AppError ? error.code : "run_settlement_failure" });
171
+ throw error;
172
+ }
173
+ }
174
+ /** CLI-owned evidence publication before the coordinator proposes its result.
175
+ * Publication has its own exact receipt and does not accept the Stage. */
176
+ export function registerMemoryFinishEvidenceFromStage(context, input) {
177
+ const bundle = readFlowRunExecutionBundle(context, input);
178
+ if (!bundle || bundle.descriptor.descriptor.id !== "mb-init")
179
+ refuse("registered_memory_bundle_required");
180
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
181
+ return PreparedMemoryFinishEvidence.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle }).register(context);
182
+ }
183
+ export function integrateMemoryFinishFromStage(context, input) {
184
+ const bundle = readFlowRunExecutionBundle(context, input);
185
+ if (!bundle || bundle.descriptor.descriptor.id !== "mb-init")
186
+ refuse("registered_memory_bundle_required");
187
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
188
+ return integrateMemoryFinish(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
189
+ }
190
+ /** Complete the actual terminal handler, with separately published evidence.
191
+ * A lost accepted receipt cannot fall back to fresh acceptance or regenerate
192
+ * terminal artifacts. Stage success precedes independently fenced RUN closure. */
193
+ export function finishMemoryFinish(context, input) {
194
+ if (!(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
195
+ refuse("invalid_input_bytes");
196
+ if (context.db.isOwnedWriteTransaction?.())
197
+ refuse("preparation_outside_writer_required");
198
+ const bundle = readFlowRunExecutionBundle(context, input);
199
+ if (!bundle || bundle.descriptor.descriptor.id !== "mb-init")
200
+ refuse("registered_memory_bundle_required");
201
+ const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
202
+ const run = assertPreparedRunBundleSqlAuthority(context, scope, bundle);
203
+ const stage = JSON.parse(run.index_json).stage_runs.find((item) => item.stage === "finish");
204
+ const accepted = stage?.status === "done";
205
+ const result = accepted ? replayAcceptedMemoryFinish(context, input)
206
+ : PreparedMemoryFinishEvidence.prepare(context, { scope, bundle }).settleFresh(context, input);
207
+ try {
208
+ const terminal = settleAcceptedMemoryRun(context, input);
209
+ return { ...result, run_id: terminal.run_id, terminal };
210
+ }
211
+ catch (error) {
212
+ throw new AppError("memory_finish_terminal_pending", "Finish Stage accepted; terminal RUN closure remains incomplete", 1, { effect: "committed", run_id: scope.runId, next_action: "reconcile_accepted_memory_run",
213
+ cause: error instanceof AppError ? error.code : "terminal_closure_failure" });
214
+ }
215
+ }