@deksden-com/dd-flow-cli 0.9.0-beta.16 → 0.9.0-beta.161

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 (670) hide show
  1. package/CHANGELOG.md +965 -0
  2. package/README.md +139 -10
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +417 -0
  6. package/dist/cli/command-metadata.js +303 -0
  7. package/dist/cli/command-option-descriptions.js +192 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/delivery.js +108 -0
  11. package/dist/cli/diagnostic-invocation.js +62 -0
  12. package/dist/cli/diagnostic.js +131 -0
  13. package/dist/cli/error-output.js +62 -0
  14. package/dist/cli/executor-onboarding.js +76 -0
  15. package/dist/cli/flows.js +29 -0
  16. package/dist/cli/harnesses.js +84 -0
  17. package/dist/cli/help.js +521 -19
  18. package/dist/cli/hook-ingress.js +89 -0
  19. package/dist/cli/input-preparation.js +193 -0
  20. package/dist/cli/interactive-invocation.js +33 -0
  21. package/dist/cli/interactive.js +114 -0
  22. package/dist/cli/memory-fix-invocation.js +52 -0
  23. package/dist/cli/memory-fix.js +100 -0
  24. package/dist/cli/memory-flow-admission.js +54 -0
  25. package/dist/cli/memory-init-invocation.js +85 -0
  26. package/dist/cli/memory-init.js +250 -0
  27. package/dist/cli/memory-storage-admission.js +54 -0
  28. package/dist/cli/memory-storage-qualification.js +105 -0
  29. package/dist/cli/memory-storage-transition.js +123 -0
  30. package/dist/cli/memory-upgrade.js +189 -0
  31. package/dist/cli/models.js +39 -0
  32. package/dist/cli/native-hook-ingress.js +94 -0
  33. package/dist/cli/native-hook-preparation.js +82 -0
  34. package/dist/cli/operator-profiles.js +61 -0
  35. package/dist/cli/output-options.js +35 -0
  36. package/dist/cli/response-file.js +72 -0
  37. package/dist/cli/run-cli.js +2020 -555
  38. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  39. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  40. package/dist/cli/runtime-process.js +153 -0
  41. package/dist/cli/setup.js +150 -0
  42. package/dist/cli.js +103 -2
  43. package/dist/domain/delivery-flows.js +8 -0
  44. package/dist/domain/diagnostic-aspects.js +103 -0
  45. package/dist/domain/diagnostic-flows.js +8 -0
  46. package/dist/domain/distill-flow.js +20 -0
  47. package/dist/domain/interactive-flow.js +1 -0
  48. package/dist/domain/memory-fix-flow.js +2 -0
  49. package/dist/domain/review-fix-flow.js +2 -0
  50. package/dist/domain/source-snapshot-flows.js +4 -0
  51. package/dist/domain/stage-catalog.js +1 -1
  52. package/dist/domain/stage-handler-identities.js +28 -0
  53. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  54. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  55. package/dist/harness-runtime/bin/dd-agy.mjs +71 -0
  56. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  57. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  58. package/dist/harness-runtime/bin/dd-grok.mjs +50 -0
  59. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  60. package/dist/harness-runtime/bin/dd-zcode.mjs +95 -0
  61. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  62. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  63. package/dist/harness-runtime/lib/agy-error-boundary.mjs +87 -0
  64. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  65. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  66. package/dist/harness-runtime/lib/agy-native-inspection.mjs +225 -0
  67. package/dist/harness-runtime/lib/agy-native-inventory.mjs +19 -0
  68. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  69. package/dist/harness-runtime/lib/agy-terminal-envelope.mjs +74 -0
  70. package/dist/harness-runtime/lib/agy-transcript-stream.mjs +54 -0
  71. package/dist/harness-runtime/lib/daemon-observation.d.mts +3 -0
  72. package/dist/harness-runtime/lib/daemon-observation.mjs +171 -0
  73. package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
  74. package/dist/harness-runtime/lib/daemon-operations.mjs +512 -0
  75. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +7 -0
  76. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1362 -0
  77. package/dist/harness-runtime/lib/dd-agy.mjs +105 -0
  78. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  79. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +271 -0
  80. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  81. package/dist/harness-runtime/lib/dd-codex.mjs +986 -0
  82. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +155 -0
  83. package/dist/harness-runtime/lib/dd-droid.mjs +739 -0
  84. package/dist/harness-runtime/lib/dd-grok-daemon.d.mts +1 -0
  85. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +667 -0
  86. package/dist/harness-runtime/lib/dd-grok.mjs +182 -0
  87. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +772 -0
  88. package/dist/harness-runtime/lib/dd-opencode.mjs +411 -0
  89. package/dist/harness-runtime/lib/dd-zcode-daemon.d.mts +1 -0
  90. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +845 -0
  91. package/dist/harness-runtime/lib/dd-zcode.mjs +1239 -0
  92. package/dist/harness-runtime/lib/delegation-instructions.d.mts +16 -0
  93. package/dist/harness-runtime/lib/delegation-instructions.mjs +179 -0
  94. package/dist/harness-runtime/lib/delivery-command.mjs +84 -0
  95. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  96. package/dist/harness-runtime/lib/driver-recovery.mjs +121 -0
  97. package/dist/harness-runtime/lib/droid-observation.mjs +70 -0
  98. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  99. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  100. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  101. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  102. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  103. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  104. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +11 -0
  105. package/dist/harness-runtime/lib/lifecycle-contract.mjs +20 -0
  106. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  107. package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
  108. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  109. package/dist/harness-runtime/lib/model-observations.mjs +113 -0
  110. package/dist/harness-runtime/lib/native-children.d.mts +34 -0
  111. package/dist/harness-runtime/lib/native-children.mjs +265 -0
  112. package/dist/harness-runtime/lib/native-hook-command.d.mts +8 -0
  113. package/dist/harness-runtime/lib/native-hook-command.mjs +306 -0
  114. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  115. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  116. package/dist/harness-runtime/lib/native-streams.mjs +38 -0
  117. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  118. package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
  119. package/dist/harness-runtime/lib/opencode-plugin.mjs +112 -0
  120. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  121. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  122. package/dist/harness-runtime/lib/operation-errors.mjs +140 -0
  123. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  124. package/dist/harness-runtime/lib/operation-progress.mjs +118 -0
  125. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  126. package/dist/harness-runtime/lib/process-json.mjs +200 -0
  127. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  128. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +23 -0
  129. package/dist/harness-runtime/lib/provider-overload-policy.mjs +242 -0
  130. package/dist/harness-runtime/lib/runner-events.mjs +202 -0
  131. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  132. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  133. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  134. package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
  135. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  136. package/dist/harness-runtime/lib/tool-observations.mjs +238 -0
  137. package/dist/harness-runtime/lib/zcode-native-hook-ownership.mjs +109 -0
  138. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  139. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  140. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  141. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  142. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  143. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  144. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  145. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  146. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  147. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  148. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  149. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  150. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  151. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  152. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  153. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  154. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  155. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  156. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  157. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  158. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  159. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  160. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  161. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  162. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  163. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  164. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  165. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  166. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  167. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  168. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  169. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  170. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  171. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  172. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  173. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  174. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  175. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  176. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  177. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  178. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  179. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  180. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  181. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  182. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  183. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  184. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  185. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  186. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  187. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  188. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  189. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  190. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  191. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  192. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  193. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  194. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  195. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  196. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  197. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  198. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  199. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  200. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  201. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  202. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  203. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  204. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  205. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  206. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  207. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  208. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  209. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  210. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  211. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  212. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  213. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  214. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  215. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  216. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  217. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  218. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  219. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  220. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  221. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  222. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  223. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  224. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  225. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  226. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  227. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  228. package/dist/protocol/local-files.js +18 -9
  229. package/dist/runtime/context.js +8 -4
  230. package/dist/schemas/agent-profile.schema.json +1 -1
  231. package/dist/schemas/code-review-decision.schema.json +9 -0
  232. package/dist/schemas/code-review-result.schema.json +1 -1
  233. package/dist/schemas/code-verification.schema.json +7 -5
  234. package/dist/schemas/code-work-batch.schema.json +2 -2
  235. package/dist/schemas/code-work-result.schema.json +2 -1
  236. package/dist/schemas/delivery-stage-result.schema.json +286 -0
  237. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  238. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  239. package/dist/schemas/discovery-result.schema.json +184 -0
  240. package/dist/schemas/distill-stage-result.schema.json +667 -0
  241. package/dist/schemas/distill-work-result.schema.json +428 -0
  242. package/dist/schemas/execution-bundle.schema.json +215 -0
  243. package/dist/schemas/execution-settings.schema.json +162 -0
  244. package/dist/schemas/flow-descriptor.schema.json +54 -0
  245. package/dist/schemas/flow-run.schema.json +29 -0
  246. package/dist/schemas/harness-catalog.schema.json +80 -0
  247. package/dist/schemas/interactive-stage-result.schema.json +47 -0
  248. package/dist/schemas/interactive-work-result.schema.json +63 -0
  249. package/dist/schemas/mb-fix-stage-result.schema.json +93 -0
  250. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  251. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  252. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  253. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  254. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  255. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  256. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  257. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  258. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  259. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  260. package/dist/schemas/memory-repair-work-result.schema.json +56 -0
  261. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  262. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  263. package/dist/schemas/model-catalog.schema.json +153 -0
  264. package/dist/schemas/plan-review-decision.schema.json +12 -3
  265. package/dist/schemas/plan-review-result.schema.json +2 -2
  266. package/dist/schemas/profile-settings.schema.json +122 -0
  267. package/dist/schemas/project-flow-pack-manifest.schema.json +2 -2
  268. package/dist/schemas/release-impact.schema.json +3 -3
  269. package/dist/schemas/release-manifest.schema.json +291 -0
  270. package/dist/schemas/review-fix-stage-result.schema.json +210 -0
  271. package/dist/schemas/run-control-receipt.schema.json +119 -0
  272. package/dist/schemas/run-control-request.schema.json +36 -0
  273. package/dist/schemas/run-engine-binding.schema.json +1 -1
  274. package/dist/schemas/stage-start-response.schema.json +4 -0
  275. package/dist/schemas/vnext-protocol-plan.schema.json +3 -3
  276. package/dist/services/accepted-intent.js +139 -0
  277. package/dist/services/assigned-lifecycle.js +382 -0
  278. package/dist/services/branch-context.js +3 -3
  279. package/dist/services/canon.js +54 -15
  280. package/dist/services/check-environment.js +21 -0
  281. package/dist/services/check-runner-evidence.js +344 -0
  282. package/dist/services/check-runner-proof.js +373 -0
  283. package/dist/services/cleanup.js +133 -40
  284. package/dist/services/cli-operation-classifier.js +32 -64
  285. package/dist/services/cli-upgrade-allowlist.js +27 -0
  286. package/dist/services/code-checks.js +1426 -121
  287. package/dist/services/codex-capacity.js +367 -0
  288. package/dist/services/codex-hook-delivery.js +41 -0
  289. package/dist/services/command-context.js +80 -0
  290. package/dist/services/compatibility-preflight.js +16 -3
  291. package/dist/services/config.js +11 -8
  292. package/dist/services/continuation-outcome.js +25 -0
  293. package/dist/services/controller-child-capacity.js +71 -0
  294. package/dist/services/controller-child-observer.js +121 -0
  295. package/dist/services/controller-child-repair.js +117 -0
  296. package/dist/services/controller-execution.js +97 -0
  297. package/dist/services/controller-fanout.js +277 -0
  298. package/dist/services/controller-memory-task.js +45 -0
  299. package/dist/services/controller-memory-worker.js +51 -0
  300. package/dist/services/controller-result-authority.js +127 -0
  301. package/dist/services/controller-work-failure.js +198 -0
  302. package/dist/services/dashboard.js +145 -58
  303. package/dist/services/delivery-access.js +123 -0
  304. package/dist/services/delivery-approval.js +68 -0
  305. package/dist/services/delivery-artifact.js +86 -0
  306. package/dist/services/delivery-checks.js +178 -0
  307. package/dist/services/delivery-execution.js +181 -0
  308. package/dist/services/delivery-intents.js +212 -0
  309. package/dist/services/delivery-operation.js +81 -0
  310. package/dist/services/delivery-policy.js +91 -0
  311. package/dist/services/delivery-procedures.js +43 -0
  312. package/dist/services/delivery-request.js +99 -0
  313. package/dist/services/delivery-result.js +144 -0
  314. package/dist/services/delivery-stage-commands.js +26 -0
  315. package/dist/services/delivery-stage-entry.js +56 -0
  316. package/dist/services/delivery-stage-handlers.js +135 -0
  317. package/dist/services/delivery-stage-results.js +94 -0
  318. package/dist/services/descriptor-coordinator-session.js +37 -0
  319. package/dist/services/descriptor-root-work.js +53 -0
  320. package/dist/services/descriptor-run-settlement.js +107 -0
  321. package/dist/services/descriptor-run-start.js +495 -0
  322. package/dist/services/descriptor-stage-coordinator.js +318 -0
  323. package/dist/services/descriptor-stage-settlement.js +268 -0
  324. package/dist/services/descriptor-stage-start.js +175 -0
  325. package/dist/services/diagnostic-evidence.js +73 -0
  326. package/dist/services/diagnostic-repair-intake.js +123 -0
  327. package/dist/services/diagnostic-repair-source-intake.js +102 -0
  328. package/dist/services/diagnostic-report-publication.js +72 -0
  329. package/dist/services/diagnostic-report.js +97 -0
  330. package/dist/services/diagnostic-run-bundle.js +113 -0
  331. package/dist/services/diagnostic-snapshot.js +159 -0
  332. package/dist/services/diagnostic-stage-handlers.js +109 -0
  333. package/dist/services/diagnostic-stage-results.js +158 -0
  334. package/dist/services/diagnostic-start.js +134 -0
  335. package/dist/services/diagnostic-work-batch.js +34 -0
  336. package/dist/services/diagnostic-work-collection.js +97 -0
  337. package/dist/services/diagnostic-work-registration.js +101 -0
  338. package/dist/services/diagnostic-work-results.js +93 -0
  339. package/dist/services/discovery/agy-discovery.js +2 -0
  340. package/dist/services/discovery/codex-discovery.js +2 -0
  341. package/dist/services/discovery/droid-discovery.js +2 -0
  342. package/dist/services/discovery/grok-discovery.js +2 -0
  343. package/dist/services/discovery/opencode-discovery.js +2 -0
  344. package/dist/services/discovery/static.js +31 -0
  345. package/dist/services/discovery/zcode-discovery.js +2 -0
  346. package/dist/services/distill-document-publication.js +280 -0
  347. package/dist/services/distill-promotion.js +197 -0
  348. package/dist/services/distill-publication-custody.js +162 -0
  349. package/dist/services/distill-stage-handlers.js +249 -0
  350. package/dist/services/distill-stage-results.js +105 -0
  351. package/dist/services/distill-user-inputs.js +4 -0
  352. package/dist/services/distill-work-batch.js +42 -0
  353. package/dist/services/distill-work-collection.js +74 -0
  354. package/dist/services/distill-work-registration.js +93 -0
  355. package/dist/services/distill-work-results.js +98 -0
  356. package/dist/services/engines.js +354 -163
  357. package/dist/services/eval-snapshots.js +1326 -150
  358. package/dist/services/execution-bundles.js +275 -0
  359. package/dist/services/execution-policy.js +185 -0
  360. package/dist/services/executor-onboarding.js +56 -0
  361. package/dist/services/external-work-launch.js +316 -0
  362. package/dist/services/flow-catalog.js +54 -0
  363. package/dist/services/flow-descriptors.js +82 -0
  364. package/dist/services/frozen-engine.js +404 -0
  365. package/dist/services/generic-execution.js +165 -0
  366. package/dist/services/harness-adapter.js +342 -35
  367. package/dist/services/harness-config.js +2 -0
  368. package/dist/services/harness-discovery.js +29 -0
  369. package/dist/services/harness-doctor.js +75 -0
  370. package/dist/services/harness-probe-effects.js +51 -0
  371. package/dist/services/harness-version-probe.js +100 -0
  372. package/dist/services/hook-memory-routing.js +188 -0
  373. package/dist/services/hook-recovery-guard.js +14 -0
  374. package/dist/services/hook-session-observation.js +24 -0
  375. package/dist/services/hooks.js +813 -327
  376. package/dist/services/hybrid-contracts.js +479 -0
  377. package/dist/services/hybrid-digest.js +14 -0
  378. package/dist/services/ids.js +29 -1
  379. package/dist/services/installation-lock.js +95 -0
  380. package/dist/services/installed-flow-source.js +261 -0
  381. package/dist/services/interactive-attached-session.js +215 -0
  382. package/dist/services/interactive-baseline-custody.js +54 -0
  383. package/dist/services/interactive-before-versions.js +148 -0
  384. package/dist/services/interactive-bundle-data.js +85 -0
  385. package/dist/services/interactive-checks.js +179 -0
  386. package/dist/services/interactive-execution.js +33 -0
  387. package/dist/services/interactive-finish-integration.js +236 -0
  388. package/dist/services/interactive-git-baseline.js +230 -0
  389. package/dist/services/interactive-git-dispatch.js +278 -0
  390. package/dist/services/interactive-input-delivery.js +82 -0
  391. package/dist/services/interactive-mutation-scope.js +231 -0
  392. package/dist/services/interactive-request.js +287 -0
  393. package/dist/services/interactive-run-bundle.js +109 -0
  394. package/dist/services/interactive-stage-entry.js +41 -0
  395. package/dist/services/interactive-stage-handlers.js +289 -0
  396. package/dist/services/interactive-stage-observation.js +136 -0
  397. package/dist/services/interactive-stage-results.js +111 -0
  398. package/dist/services/interactive-user-inputs.js +142 -0
  399. package/dist/services/interactive-work-batch.js +43 -0
  400. package/dist/services/interactive-work-collection.js +119 -0
  401. package/dist/services/interactive-work-completion.js +180 -0
  402. package/dist/services/interactive-work-context.js +249 -0
  403. package/dist/services/interactive-work-history.js +112 -0
  404. package/dist/services/interactive-work-registration.js +124 -0
  405. package/dist/services/interactive-work-results.js +115 -0
  406. package/dist/services/interactive-work-start.js +155 -0
  407. package/dist/services/lanes.js +78 -65
  408. package/dist/services/lifecycle-command.js +1 -288
  409. package/dist/services/lifecycle-contract.js +1 -0
  410. package/dist/services/lifecycle-invocations.js +2549 -0
  411. package/dist/services/managed-daemon-binding.js +129 -0
  412. package/dist/services/managed-lease-monitor.js +133 -0
  413. package/dist/services/managed-processes.js +449 -69
  414. package/dist/services/memory-accepted-composition.js +78 -0
  415. package/dist/services/memory-baseline-preservation.js +65 -0
  416. package/dist/services/memory-completed-correction-wave.js +328 -0
  417. package/dist/services/memory-compose-handler.js +380 -0
  418. package/dist/services/memory-composition-acceptance.js +375 -0
  419. package/dist/services/memory-composition-graph.js +165 -0
  420. package/dist/services/memory-composition-registration.js +161 -0
  421. package/dist/services/memory-composition-work-custody.js +156 -0
  422. package/dist/services/memory-composition-work-results.js +108 -0
  423. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  424. package/dist/services/memory-corrected-review-batch.js +37 -0
  425. package/dist/services/memory-corrected-review-findings.js +108 -0
  426. package/dist/services/memory-corrected-review-inputs.js +215 -0
  427. package/dist/services/memory-corrected-review-projection.js +78 -0
  428. package/dist/services/memory-corrected-review-receipt.js +178 -0
  429. package/dist/services/memory-corrected-review-registration.js +192 -0
  430. package/dist/services/memory-correction-check-receipt.js +235 -0
  431. package/dist/services/memory-correction-input-owner.js +6 -0
  432. package/dist/services/memory-custody-snapshot.js +36 -0
  433. package/dist/services/memory-discover-handler.js +104 -0
  434. package/dist/services/memory-finish-evidence.js +457 -0
  435. package/dist/services/memory-finish-handler.js +229 -0
  436. package/dist/services/memory-finish-integration.js +491 -0
  437. package/dist/services/memory-finish-readiness.js +169 -0
  438. package/dist/services/memory-fix-finish-integration.js +129 -0
  439. package/dist/services/memory-fix-git-dispatch.js +139 -0
  440. package/dist/services/memory-fix-intake-custody.js +11 -0
  441. package/dist/services/memory-fix-intake-settlement.js +127 -0
  442. package/dist/services/memory-fix-publication.js +196 -0
  443. package/dist/services/memory-fix-repair-admission.js +116 -0
  444. package/dist/services/memory-fix-request.js +141 -0
  445. package/dist/services/memory-fix-run-bundle.js +83 -0
  446. package/dist/services/memory-fix-scope.js +78 -0
  447. package/dist/services/memory-fix-sources.js +85 -0
  448. package/dist/services/memory-fix-stage-entry.js +24 -0
  449. package/dist/services/memory-fix-stage-handlers.js +282 -0
  450. package/dist/services/memory-fix-stage-results.js +106 -0
  451. package/dist/services/memory-fix-workspace.js +127 -0
  452. package/dist/services/memory-flow-user-inputs.js +88 -0
  453. package/dist/services/memory-git-integration.js +220 -0
  454. package/dist/services/memory-historical-corrected-review.js +212 -0
  455. package/dist/services/memory-historical-original-review.js +143 -0
  456. package/dist/services/memory-historical-repair-registration.js +105 -0
  457. package/dist/services/memory-historical-second-review.js +147 -0
  458. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  459. package/dist/services/memory-init-contexts.js +181 -0
  460. package/dist/services/memory-init-controller-start.js +119 -0
  461. package/dist/services/memory-init-engine-release.js +223 -0
  462. package/dist/services/memory-init-git-policy.js +165 -0
  463. package/dist/services/memory-init-lint-capability.js +203 -0
  464. package/dist/services/memory-init-native-capacity.js +309 -0
  465. package/dist/services/memory-init-preflight.js +334 -0
  466. package/dist/services/memory-init-project-bootstrap.js +599 -0
  467. package/dist/services/memory-init-request-candidate.js +213 -0
  468. package/dist/services/memory-init-request-input.js +82 -0
  469. package/dist/services/memory-init-resource-storage.js +125 -0
  470. package/dist/services/memory-init-run-allocation.js +81 -0
  471. package/dist/services/memory-init-run-bundle.js +135 -0
  472. package/dist/services/memory-init-start.js +181 -0
  473. package/dist/services/memory-init-startup-custody.js +80 -0
  474. package/dist/services/memory-init-startup-input.js +240 -0
  475. package/dist/services/memory-init-storage.js +91 -0
  476. package/dist/services/memory-init-stores.js +359 -0
  477. package/dist/services/memory-init-worktrunk-capability.js +174 -0
  478. package/dist/services/memory-layer-publication.js +611 -0
  479. package/dist/services/memory-layer.js +225 -0
  480. package/dist/services/memory-lint-config.js +194 -0
  481. package/dist/services/memory-native-review-copy.js +127 -0
  482. package/dist/services/memory-normal-flow-entry.js +87 -0
  483. package/dist/services/memory-ordinary-defaults.js +129 -0
  484. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  485. package/dist/services/memory-preflight-handler.js +274 -0
  486. package/dist/services/memory-repair-current-view.js +299 -0
  487. package/dist/services/memory-repair-document-delta.js +489 -0
  488. package/dist/services/memory-repair-history.js +496 -0
  489. package/dist/services/memory-repair-physical-binding.js +194 -0
  490. package/dist/services/memory-repair-publication-files.js +152 -0
  491. package/dist/services/memory-repair-publication-intent.js +27 -0
  492. package/dist/services/memory-repair-publication-plan.js +162 -0
  493. package/dist/services/memory-repair-publication-source.js +225 -0
  494. package/dist/services/memory-repair-publication.js +795 -0
  495. package/dist/services/memory-repair-registration.js +240 -0
  496. package/dist/services/memory-repair-work-baseline.js +415 -0
  497. package/dist/services/memory-repair-work-completion.js +117 -0
  498. package/dist/services/memory-repair-work-custody.js +73 -0
  499. package/dist/services/memory-repair-work-results.js +108 -0
  500. package/dist/services/memory-repair-workspace.js +261 -0
  501. package/dist/services/memory-repair-writer-copy.js +736 -0
  502. package/dist/services/memory-result-binding.js +239 -0
  503. package/dist/services/memory-retained-review-authority.js +138 -0
  504. package/dist/services/memory-retained-review-results.js +70 -0
  505. package/dist/services/memory-retained-second-baseline.js +102 -0
  506. package/dist/services/memory-retained-second-repairs.js +162 -0
  507. package/dist/services/memory-review-acceptance.js +214 -0
  508. package/dist/services/memory-review-correction-plan.js +206 -0
  509. package/dist/services/memory-review-handler.js +585 -0
  510. package/dist/services/memory-review-inputs.js +246 -0
  511. package/dist/services/memory-review-limits.js +10 -0
  512. package/dist/services/memory-review-receipt.js +180 -0
  513. package/dist/services/memory-review-registration.js +117 -0
  514. package/dist/services/memory-review-work-custody.js +126 -0
  515. package/dist/services/memory-review-work-input.js +91 -0
  516. package/dist/services/memory-review-work-results.js +95 -0
  517. package/dist/services/memory-second-corrected-review-inputs.js +167 -0
  518. package/dist/services/memory-second-correction-plan.js +77 -0
  519. package/dist/services/memory-second-repair-baseline.js +91 -0
  520. package/dist/services/memory-second-repair-launch.js +614 -0
  521. package/dist/services/memory-second-repair-registration.js +88 -0
  522. package/dist/services/memory-second-repair-source.js +187 -0
  523. package/dist/services/memory-second-review-acceptance.js +115 -0
  524. package/dist/services/memory-source-observations.js +117 -0
  525. package/dist/services/memory-stage-dispatch.js +65 -0
  526. package/dist/services/memory-stage-results.js +290 -0
  527. package/dist/services/memory-tool-probe.js +25 -0
  528. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  529. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  530. package/dist/services/memory-upgrade-evidence.js +100 -0
  531. package/dist/services/memory-upgrade-inventory.js +442 -0
  532. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  533. package/dist/services/memory-upgrade-publication.js +413 -0
  534. package/dist/services/memory-upgrade-selection.js +430 -0
  535. package/dist/services/memory-upgrade-start.js +60 -0
  536. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  537. package/dist/services/memory-verification-acceptance.js +156 -0
  538. package/dist/services/memory-verification-checks.js +317 -0
  539. package/dist/services/memory-verification-receipt.js +160 -0
  540. package/dist/services/memory-verify-handler.js +137 -0
  541. package/dist/services/memory-work-result-json.js +12 -0
  542. package/dist/services/memory-work-result-preparation.js +64 -0
  543. package/dist/services/merge-queue.js +228 -149
  544. package/dist/services/merge-server.js +163 -35
  545. package/dist/services/migrations.js +164 -114
  546. package/dist/services/model-catalog.js +109 -0
  547. package/dist/services/model-discovery.js +46 -0
  548. package/dist/services/native-daemon-history.js +50 -0
  549. package/dist/services/native-session-control.js +39 -0
  550. package/dist/services/operator-profiles.js +236 -0
  551. package/dist/services/physical-startup.js +45 -0
  552. package/dist/services/plan-runtime.js +26 -11
  553. package/dist/services/plans.js +28 -25
  554. package/dist/services/project-flow-source.js +195 -0
  555. package/dist/services/project-git-integration.js +92 -0
  556. package/dist/services/project-registry.js +97 -0
  557. package/dist/services/project-summary.js +1 -1
  558. package/dist/services/projects.js +17 -87
  559. package/dist/services/prompt-delivery.js +71 -0
  560. package/dist/services/prompts.js +28 -17
  561. package/dist/services/protocols.js +163 -87
  562. package/dist/services/provider-capacity.js +463 -0
  563. package/dist/services/recovery-observation-budget.js +121 -0
  564. package/dist/services/recovery-snapshot-database.js +588 -0
  565. package/dist/services/release-archive-producer.js +52 -0
  566. package/dist/services/release-archive.js +143 -0
  567. package/dist/services/release-cache.js +150 -0
  568. package/dist/services/release-compatibility.js +18 -0
  569. package/dist/services/release-download.js +67 -0
  570. package/dist/services/release-envelope.js +104 -0
  571. package/dist/services/release-manifest.js +45 -0
  572. package/dist/services/release-payload.js +114 -0
  573. package/dist/services/release-producer.js +63 -0
  574. package/dist/services/release-provenance.js +160 -0
  575. package/dist/services/release-registry.js +66 -0
  576. package/dist/services/release-source.js +194 -0
  577. package/dist/services/repair-intents.js +29 -0
  578. package/dist/services/repair-receipt.js +13 -0
  579. package/dist/services/retained-native-hook.js +274 -0
  580. package/dist/services/review-copy.js +165 -0
  581. package/dist/services/review-deferral.js +23 -0
  582. package/dist/services/review-fix-handoff.js +82 -0
  583. package/dist/services/review-fix-intake-custody.js +17 -0
  584. package/dist/services/review-fix-stage-entry.js +43 -0
  585. package/dist/services/review-fix-stage-handlers.js +176 -0
  586. package/dist/services/review-fix-stage-results.js +86 -0
  587. package/dist/services/run-control-receipt.js +56 -0
  588. package/dist/services/run-control-worker.js +469 -0
  589. package/dist/services/run-control.js +1109 -0
  590. package/dist/services/run-controller-adapter.js +434 -0
  591. package/dist/services/run-controller-capture.js +186 -0
  592. package/dist/services/run-controller-process.js +226 -0
  593. package/dist/services/run-controller-recovery.js +335 -0
  594. package/dist/services/run-controller-state.js +106 -0
  595. package/dist/services/run-controller.js +1717 -0
  596. package/dist/services/run-engine-bindings.js +1 -1
  597. package/dist/services/run-fork.js +147 -0
  598. package/dist/services/run-health.js +149 -0
  599. package/dist/services/run-observations.js +152 -0
  600. package/dist/services/run-projection.js +22 -64
  601. package/dist/services/run-recovery-guard.js +107 -0
  602. package/dist/services/run-recovery-runtime.js +112 -0
  603. package/dist/services/run-recovery.js +485 -0
  604. package/dist/services/run-start-custody.js +189 -0
  605. package/dist/services/run-timeline.js +59 -0
  606. package/dist/services/runs.js +996 -271
  607. package/dist/services/runtime-budget.js +446 -0
  608. package/dist/services/runtime-command.js +43 -0
  609. package/dist/services/runtime-scope-capture.js +52 -0
  610. package/dist/services/runtime-scope-control.js +468 -0
  611. package/dist/services/runtime-scope-resume.js +605 -0
  612. package/dist/services/runtime-scope-stop.js +211 -0
  613. package/dist/services/runtime-scope-worker.js +314 -0
  614. package/dist/services/runtime-service.js +19 -14
  615. package/dist/services/schema-validation.js +10 -8
  616. package/dist/services/scope-writer-cleanup.js +27 -0
  617. package/dist/services/sessions.js +37 -91
  618. package/dist/services/setup.js +427 -0
  619. package/dist/services/stage-blocker.js +17 -7
  620. package/dist/services/stage-context.js +240 -18
  621. package/dist/services/stage-handlers.js +141 -0
  622. package/dist/services/stage-lifecycle.js +156 -119
  623. package/dist/services/stage-pause.js +222 -94
  624. package/dist/services/stage-report-renderer.js +230 -6
  625. package/dist/services/stage-work-graph.js +52 -0
  626. package/dist/services/technical-notes.js +31 -0
  627. package/dist/services/tooling.js +111 -44
  628. package/dist/services/usage.js +49 -101
  629. package/dist/services/verification-matrix.js +393 -0
  630. package/dist/services/version-status.js +1 -1
  631. package/dist/services/vnext-code-review.js +302 -91
  632. package/dist/services/vnext-code.js +325 -251
  633. package/dist/services/vnext-contracts.js +10 -1
  634. package/dist/services/vnext-execution-profile.js +80 -5
  635. package/dist/services/vnext-fanout.js +399 -20
  636. package/dist/services/vnext-merge.js +336 -114
  637. package/dist/services/vnext-plan-review.js +288 -133
  638. package/dist/services/vnext-plan.js +257 -110
  639. package/dist/services/vnext-protocolize.js +534 -96
  640. package/dist/services/vnext-specify.js +131 -84
  641. package/dist/services/vnext-workspace-policy.js +7 -2
  642. package/dist/services/work-registry.js +1950 -215
  643. package/dist/services/work-retry-context.js +55 -0
  644. package/dist/services/workspace-bootstrap.js +53 -15
  645. package/dist/services/workspace-files.js +85 -0
  646. package/dist/services/worktrees.js +108 -48
  647. package/dist/shared/entity-references.js +1 -0
  648. package/dist/shared/errors.js +27 -0
  649. package/dist/storage/agent-output.js +26 -0
  650. package/dist/storage/data-preservation.js +65 -0
  651. package/dist/storage/database.js +931 -40
  652. package/dist/storage/foreign-key-transaction.js +39 -0
  653. package/dist/storage/immutable-input.js +45 -0
  654. package/dist/storage/import-guard.js +159 -0
  655. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  656. package/dist/storage/native-cleanup.js +52 -0
  657. package/dist/storage/paired-writer-migration.js +424 -0
  658. package/dist/storage/paths.js +17 -4
  659. package/dist/storage/projection-lock.js +73 -0
  660. package/dist/storage/work-references.js +23 -0
  661. package/dist/storage/writer-contract.js +96 -0
  662. package/dist/storage/writer-migration.js +346 -0
  663. package/dist/storage/writer-restore.js +217 -0
  664. package/dist/verification-components.json +384 -0
  665. package/package.json +52 -13
  666. package/tools/create-canon-release.mjs +33 -0
  667. package/tools/probe-codex-history.mjs +37 -0
  668. package/tools/produce-hybrid-release.mjs +41 -0
  669. package/tools/repair-paused-run-status.mjs +84 -0
  670. package/tools/verification-jobs.mjs +342 -0
@@ -0,0 +1,23 @@
1
+ export const CAPACITY_POLICY: "provider-overload-episode@1";
2
+ export const RECOVERY_POLICY: "provider-recovery-episode@1";
3
+ export function classifyRecoveryError(native: unknown): string;
4
+ export function recoveryRetryAfter(native: unknown, now?: number): number;
5
+ export const normalizeRecoveryFailure: typeof normalizeProviderFailure;
6
+ export const terminalProviderRecovery: typeof terminalProviderOverload;
7
+ export const recoveryBackoff: typeof capacityBackoff;
8
+ export const recoveryRefusal: typeof refusalObservation;
9
+ export const recoveryExhausted: typeof overloadExhausted;
10
+ export const MAX_OVERLOAD_RETRIES: 3;
11
+ export const MAX_RETRY_AFTER_MS: 30000;
12
+ export function classifyProviderError(native: unknown): string;
13
+ export function safeProviderError(native: unknown): Record<string, unknown>;
14
+ export type RequestProof = { kind: "native_turn"; session_id: string; turn_id: string } | { kind: "stream_request"; daemon_instance: string; connection_id: string; operation_id: string; turn_generation: number; session_id: string; outbound_position: number; terminal_position: number };
15
+ export function streamRequestKey(proof: unknown): string | null;
16
+ export type CapacityRefusal = { policy: string; ordinal: number; session_id: string; turn_id: string; category?: string; request_key?: string; request_proof?: RequestProof; first_observed_at: string; native_terminal_at?: string; native_terminal_basis?: string };
17
+ export function parseCapacityOperation(id: string): { root: string; ordinal: number };
18
+ export function normalizeProviderFailure(error: unknown, sessionId?: string, turnId?: string): null | { code: string; session_id: string; turn_id: string; request_key: string; request_proof: RequestProof; native_error: Record<string, unknown>; observed_at: unknown; terminal_at: unknown; native_turn_items: unknown; primary_error: { details?: Record<string, unknown> } };
19
+ export function terminalProviderOverload(error: unknown, sessionId?: string, turnId?: string): boolean;
20
+ export function nativeItemsSettled(items: unknown): boolean;
21
+ export function capacityBackoff(error: unknown, ordinal: number, now?: number, random?: () => number): number;
22
+ export function refusalObservation(error: unknown, ordinal: number, firstObservedAt: string): CapacityRefusal;
23
+ export function overloadExhausted(refusals: CapacityRefusal[], maxRetries?: number): null | { policy: string; reason: string; attempts: number; refusals: CapacityRefusal[] };
@@ -0,0 +1,242 @@
1
+ /** Pure policy shared by the controller and pinned-engine EVAL consumers. */
2
+ export const CAPACITY_POLICY = "provider-overload-episode@1";
3
+ export const MAX_OVERLOAD_RETRIES = 3;
4
+ export const MAX_RETRY_AFTER_MS = 30_000;
5
+ export const RECOVERY_POLICY = "provider-recovery-episode@1";
6
+
7
+ function policyError(code, message, details = {}) { return Object.assign(new Error(message), { code, details }); }
8
+
9
+ /** Only call on a native error envelope, never prompt or tool output. */
10
+ export function classifyProviderError(native) {
11
+ if (!native || typeof native !== "object") return "provider_failed";
12
+ const code = [native.code, native.type, native.codexErrorInfo?.code ?? native.codexErrorInfo].filter(value => typeof value === "string").join(" ");
13
+ const message = String(native.message ?? "");
14
+ const text = `${code} ${message}`;
15
+ const status = Number(native.status ?? native.statusCode ?? native.status_code ?? native.http_status ?? /\(code (\d{3})\)/i.exec(message)?.[1]);
16
+ if (status === 402 || /quota|usageLimitExceeded|sessionBudgetExceeded|billing|payment.required|balance.exhausted|insufficient.credit|resource_exhausted.*limit/i.test(text)) return "provider_quota_exhausted";
17
+ if (status === 401 || status === 403 || /provider_auth_failed|invalid.api.key|authentication|unauthorized|eligib|forbidden|access.denied|rejected.this.account/i.test(text)) return "provider_auth_failed";
18
+ if (/provider_capacity_transient|serverOverloaded|model.?capacity|at capacity|no capacity available for model|server.overload|model.overload|server.?busy/i.test(text) || /(?:^|\s)overloaded_error(?:\s|$)/i.test(code) || status === 503 || status === 529) return "provider_capacity_transient";
19
+ if (/rateLimitExceeded|rate.limit/i.test(text) && (native.retryAfter !== undefined || native.retry_after !== undefined || Object.keys(native.headers ?? {}).some(key => key.toLowerCase() === "retry-after"))) return "provider_rate_limited";
20
+ return status === 429 || /provider_limit_unknown|\b429\b|rateLimitExceeded|rate.limit/i.test(text) ? "provider_limit_unknown" : "provider_failed";
21
+ }
22
+
23
+ /** Public retry evidence excludes response bodies, credentials and other headers. */
24
+ export function safeProviderError(native) {
25
+ const result = { code: classifyProviderError(native) };
26
+ if (!native || typeof native !== "object") return result;
27
+ const status = native.status ?? native.statusCode ?? native.status_code ?? native.http_status;
28
+ if (Number.isInteger(Number(status))) result.status = Number(status);
29
+ const retryHeaders = Object.entries(native.headers ?? {}).filter(([key]) => key.toLowerCase() === "retry-after");
30
+ const header = retryHeaders[0]?.[1];
31
+ const retry = native.retryAfter ?? native.retry_after ?? header;
32
+ if (retry !== undefined && retry !== null) result.retryAfter = typeof retry === "string" && retry.length <= 128 || typeof retry === "number" && Number.isFinite(retry) ? retry : "invalid-retry-after";
33
+ if (native.retry_after !== undefined && native.retry_after !== null) result.retry_after = typeof native.retry_after === "string" && native.retry_after.length <= 128 || typeof native.retry_after === "number" && Number.isFinite(native.retry_after) ? native.retry_after : "invalid-retry-after";
34
+ if (header !== undefined && header !== null && (native.retryAfter !== undefined || native.retry_after !== undefined || retryHeaders.length > 1)) result.headers = Object.fromEntries(retryHeaders.map(([key, value]) => [key, typeof value === "string" && value.length <= 128 || typeof value === "number" && Number.isFinite(value) ? value : "invalid-retry-after"]));
35
+ if (typeof native.willRetry === "boolean") result.willRetry = native.willRetry;
36
+ for (const key of ["type", "source", "reason", "errorPhase", "exceptionKind", "transport", "retryable", "retryAfterMs"]) {
37
+ const value = native[key];
38
+ if (typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.length <= 128) result[key] = value;
39
+ }
40
+ if (!result.type && /^(model_request_failed|ECONNRESET|EPIPE|ETIMEDOUT|EAI_AGAIN|UND_ERR_SOCKET|UND_ERR_CONNECT_TIMEOUT|UND_ERR_HEADERS_TIMEOUT|UND_ERR_BODY_TIMEOUT)$/.test(native.code ?? "")) result.type = native.code;
41
+ if (Object.hasOwn(native, "retryAfterMs") && native.retryAfterMs !== null) result.retryAfterMs = typeof native.retryAfterMs === "number" && Number.isFinite(native.retryAfterMs) || typeof native.retryAfterMs === "string" && native.retryAfterMs.length <= 128 ? native.retryAfterMs : "invalid-retry-after";
42
+ if (native.attribution && typeof native.attribution === "object") {
43
+ const attribution = {};
44
+ for (const key of ["source", "reason", "errorPhase", "exceptionKind", "transport", "retryable", "retryAfterMs"]) {
45
+ const value = native.attribution[key];
46
+ if (typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.length <= 128) attribution[key] = value;
47
+ }
48
+ if (Object.hasOwn(native.attribution, "retryAfterMs") && native.attribution.retryAfterMs !== null) attribution.retryAfterMs = typeof native.attribution.retryAfterMs === "number" && Number.isFinite(native.attribution.retryAfterMs) || typeof native.attribution.retryAfterMs === "string" && native.attribution.retryAfterMs.length <= 128 ? native.attribution.retryAfterMs : "invalid-retry-after";
49
+ if (Object.keys(attribution).length) result.attribution = attribution;
50
+ }
51
+ for (const key of ["reset_at", "resets_at", "resetAt", "resetsAt", "reset_time"]) {
52
+ const value = native[key];
53
+ if (typeof value === "string" && value.length <= 128 || typeof value === "number" && Number.isFinite(value)) result[key] = value;
54
+ }
55
+ return result;
56
+ }
57
+
58
+ /** New native-recovery ABI; the overload-only exports below retain their scope. */
59
+ export function classifyRecoveryError(native) {
60
+ const legacy = classifyProviderError(native);
61
+ if (["provider_quota_exhausted", "provider_auth_failed"].includes(legacy)) return legacy;
62
+ if (!native || typeof native !== "object") return legacy;
63
+ const facts = [native, native.attribution].filter(value => value && typeof value === "object");
64
+ const text = [native.code, native.type, native.message, ...facts.flatMap(value => [value.reason, value.exceptionKind])].filter(value => typeof value === "string").join(" ");
65
+ if (facts.some(value => value.retryable === false) || /cancel|CERT_|certificate|permission|configuration/i.test(text)) return "provider_failed";
66
+ if (legacy === "provider_capacity_transient") return legacy;
67
+ if (["provider_rate_limited", "provider_limit_unknown"].includes(legacy) && facts.some(value => value.retryAfterMs !== undefined)) return "provider_rate_limited";
68
+ if (legacy === "provider_rate_limited") return legacy;
69
+ const structuredNetwork = [native.type, native.code].includes("model_request_failed") && facts.some(value => value.source === "network" && value.reason === "network_error" && value.errorPhase === "stream" && value.exceptionKind === "transport");
70
+ const networkSource = facts.some(value => ["network", "provider", "transport"].includes(value.source));
71
+ const code = [native.code, native.type, native.transport, ...facts.map(value => value.transport)].filter(value => typeof value === "string");
72
+ const knownCode = code.some(value => /^(ECONNRESET|EPIPE|ETIMEDOUT|EAI_AGAIN|UND_ERR_SOCKET|UND_ERR_CONNECT_TIMEOUT|UND_ERR_HEADERS_TIMEOUT|UND_ERR_BODY_TIMEOUT)$/.test(value));
73
+ const status = Number(native.status ?? native.statusCode ?? native.status_code ?? native.http_status);
74
+ return structuredNetwork || networkSource && (knownCode || [408, 502, 504].includes(status)) ? "provider_network_transient" : legacy;
75
+ }
76
+
77
+ /** All delay representations must agree; no units guessing and no moving deadline. */
78
+ export function recoveryRetryAfter(native, now = Date.now()) {
79
+ if (!Number.isFinite(now)) throw policyError("capacity_retry_metadata_invalid", "Invalid recovery observation time");
80
+ if (!native || typeof native !== "object") return 0;
81
+ const values = [];
82
+ for (const source of [native, native.attribution].filter(value => value && typeof value === "object")) {
83
+ for (const key of ["retryAfterMs", "retryAfter", "retry_after"]) if (source[key] !== undefined && source[key] !== null) values.push([source[key], key === "retryAfterMs"]);
84
+ for (const [key, value] of Object.entries(source.headers ?? {})) if (key.toLowerCase() === "retry-after") values.push([value, false]);
85
+ }
86
+ const parsed = values.map(([value, milliseconds]) => {
87
+ const numeric = typeof value === "number" || typeof value === "string" && /^\d+(?:\.\d+)?$/.test(value.trim());
88
+ const duration = numeric ? Number(value) * (milliseconds ? 1 : 1000) : !milliseconds && typeof value === "string" && /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/.test(value.trim()) ? Math.max(0, Date.parse(value) - now) : NaN;
89
+ if (!numeric && Number.isFinite(duration) && new Date(Date.parse(value)).toUTCString() !== value.trim()) throw policyError("capacity_retry_metadata_invalid", "Invalid recovery HTTP date");
90
+ if (!Number.isFinite(duration) || duration < 0 || !Number.isFinite(now + duration) || now + duration > 8.64e15) throw policyError("capacity_retry_metadata_invalid", "Invalid recovery Retry-After metadata");
91
+ return duration;
92
+ });
93
+ if (parsed.some(value => value !== parsed[0])) throw policyError("capacity_retry_metadata_invalid", "Conflicting recovery Retry-After metadata");
94
+ return parsed[0] ?? 0;
95
+ }
96
+
97
+ export function normalizeRecoveryFailure(error, expectedSessionId, expectedTurnId) {
98
+ const normalized = normalizeNativeFailure(error, expectedSessionId, expectedTurnId, true);
99
+ if (!normalized) return null;
100
+ const category = classifyRecoveryError(normalized.native_error);
101
+ if (!["provider_capacity_transient", "provider_rate_limited", "provider_network_transient"].includes(category)) return null;
102
+ const nativeCode = typeof normalized.native_error.codexErrorInfo === "string" ? normalized.native_error.codexErrorInfo : normalized.native_error.codexErrorInfo?.code;
103
+ return { ...normalized, code: nativeCode ?? category, category };
104
+ }
105
+
106
+ export function terminalProviderRecovery(error, sessionId, turnId) { return normalizeRecoveryFailure(error, sessionId, turnId) !== null; }
107
+ export function recoveryBackoff(error, ordinal, now = Date.now(), random = Math.random) {
108
+ const native = normalizeRecoveryFailure(error)?.native_error ?? error?.details?.provider_error ?? error;
109
+ try { return capacityBackoff({ retryAfter: recoveryRetryAfter(native, now) / 1000 }, ordinal, now, random); }
110
+ catch (failure) { if (failure.details?.policy === CAPACITY_POLICY) failure.details = { ...failure.details, policy: RECOVERY_POLICY }; throw failure; }
111
+ }
112
+ export function recoveryRefusal(error, ordinal, firstObservedAt) {
113
+ const failure = normalizeRecoveryFailure(error);
114
+ return { ...observedRefusal(failure, ordinal, firstObservedAt, RECOVERY_POLICY), category: failure.category };
115
+ }
116
+ export function recoveryExhausted(refusals, maxRetries = MAX_OVERLOAD_RETRIES) {
117
+ if (refusals.some(value => value.policy !== RECOVERY_POLICY)) throw policyError("capacity_policy_mismatch", "Retained episode uses another recovery policy");
118
+ const exhausted = overloadExhausted(refusals.map(value => ({ ...value, policy: CAPACITY_POLICY })), maxRetries);
119
+ return exhausted ? { ...exhausted, policy: RECOVERY_POLICY, reason: "provider_retries_exhausted", refusals } : null;
120
+ }
121
+
122
+ export function parseCapacityOperation(id) {
123
+ if (typeof id !== "string" || !id) throw policyError("capacity_continuation_conflict", "Missing capacity operation identity");
124
+ const match = /^(.*):capacity:(\d+):session\.prompt$/.exec(id);
125
+ if (!match) return { root: id, ordinal: 0 };
126
+ const ordinal = Number(match[2]);
127
+ if (!Number.isSafeInteger(ordinal) || ordinal < 1 || String(ordinal) !== match[2]) throw policyError("capacity_continuation_conflict", "Capacity ordinal is not a canonical positive safe integer", { operation_id: id });
128
+ return { root: match[1], ordinal };
129
+ }
130
+
131
+ /** Local ordered-stream identity is not a native Turn ID. */
132
+ export function streamRequestKey(proof) {
133
+ if (proof?.kind !== "stream_request" || ![proof.daemon_instance, proof.connection_id, proof.operation_id, proof.session_id].every(value => typeof value === "string" && value)
134
+ || !Number.isSafeInteger(proof.turn_generation) || proof.turn_generation < 1
135
+ || !Number.isSafeInteger(proof.outbound_position) || proof.outbound_position < 1
136
+ || !Number.isSafeInteger(proof.terminal_position) || proof.terminal_position <= proof.outbound_position) return null;
137
+ return JSON.stringify(["stream_request", proof.daemon_instance, proof.connection_id, proof.operation_id, proof.session_id, proof.turn_generation, proof.outbound_position, proof.terminal_position]);
138
+ }
139
+
140
+ export function normalizeProviderFailure(error, expectedSessionId, expectedTurnId) {
141
+ return normalizeNativeFailure(error, expectedSessionId, expectedTurnId, false);
142
+ }
143
+ function normalizeNativeFailure(error, expectedSessionId, expectedTurnId, recovery) {
144
+ let current = error;
145
+ for (let depth = 0; depth < 4 && current && typeof current === "object"; depth++) {
146
+ // The same continuation authority applies to a proven v2 execution
147
+ // refusal. Never classify transport loss or an active native retry here.
148
+ if (current.code === "provider_capacity_transient" || current.code === "provider_rate_limited" || recovery && current.code === "provider_network_transient") {
149
+ const details = current.details ?? {};
150
+ const streamKey = details.native_source === "agy.result" && details.turn_id === undefined && details.native_turn_id === undefined ? streamRequestKey(details.request_proof) : null;
151
+ const turnKey = streamKey ?? details.turn_id;
152
+ const sources = ["opencode.v2.session.execution", "agy.result", "acp.error_response", "droid.agent_turn_outcome", "grok.subagent.event", ...(recovery ? ["zcode.retained-terminal"] : [])];
153
+ const categories = ["provider_capacity_transient", "provider_rate_limited", ...(recovery ? ["provider_network_transient"] : [])];
154
+ if (!sources.includes(details.native_source) || details.terminal_status !== "failed"
155
+ || details.will_retry === true || details.native_retry_active === true || details.provider_error?.willRetry === true
156
+ || details.provider_error && !categories.includes((recovery ? classifyRecoveryError : classifyProviderError)(details.provider_error))
157
+ || typeof details.provider_session_id !== "string" || !details.provider_session_id
158
+ || typeof turnKey !== "string" || !turnKey || (streamKey ? details.request_proof.session_id !== details.provider_session_id || details.native_turn_id !== undefined : details.native_turn_id !== details.turn_id)
159
+ || expectedSessionId !== undefined && details.provider_session_id !== expectedSessionId
160
+ || expectedTurnId !== undefined && turnKey !== expectedTurnId) return null;
161
+ return { code: "serverOverloaded", session_id: details.provider_session_id, turn_id: turnKey, request_key: turnKey,
162
+ request_proof: streamKey ? details.request_proof : { kind: "native_turn", session_id: details.provider_session_id, turn_id: details.turn_id },
163
+ native_error: details.provider_error ?? { type: details.native_error_type, status: details.http_status }, observed_at: details.observed_at ?? null,
164
+ terminal_at: null, terminal_basis: null, native_turn_items: details.native_turn_items ?? null, primary_error: current };
165
+ }
166
+ if (current.code === "turn_interrupted") {
167
+ const details = current.details ?? {}, native = details.provider_error;
168
+ const code = typeof native?.codexErrorInfo === "string" ? native.codexErrorInfo : native?.codexErrorInfo?.code;
169
+ if (native?.willRetry === true || details.terminal_status !== "failed" || typeof details.provider_session_id !== "string" || !details.provider_session_id
170
+ || expectedSessionId !== undefined && details.provider_session_id !== expectedSessionId
171
+ || typeof details.turn_id !== "string" || !details.turn_id || details.native_turn_id !== details.turn_id
172
+ || expectedTurnId !== undefined && details.turn_id !== expectedTurnId || typeof code !== "string") return null;
173
+ return { code, session_id: details.provider_session_id, turn_id: details.turn_id, request_key: details.turn_id, request_proof: { kind: "native_turn", session_id: details.provider_session_id, turn_id: details.turn_id }, native_error: native,
174
+ observed_at: details.observed_at ?? null, terminal_at: details.terminal_at ?? null, terminal_basis: details.terminal_basis ?? null,
175
+ native_turn_items: details.native_turn_items ?? null, primary_error: current };
176
+ }
177
+ // No arbitrary recursive cause search: an ownership/hook/lifecycle error wins.
178
+ if (current.code !== "harness_adapter_failed") return null;
179
+ current = current.details?.cause ?? current.cause;
180
+ }
181
+ return null;
182
+ }
183
+
184
+ export function terminalProviderOverload(error, expectedSessionId, expectedTurnId) {
185
+ const normalized = normalizeProviderFailure(error, expectedSessionId, expectedTurnId);
186
+ return normalized !== null && ["provider_capacity_transient", "provider_rate_limited"].includes(classifyProviderError(normalized.native_error));
187
+ }
188
+
189
+ export function nativeItemsSettled(items) {
190
+ return items?.observed === true && typeof items.possible_effects === "boolean" && items.pending !== true
191
+ && (items.possible_effects === false || items.pending === false);
192
+ }
193
+
194
+ export function capacityBackoff(error, ordinal, now = Date.now(), random = Math.random) {
195
+ if (!Number.isSafeInteger(ordinal) || ordinal < 1 || !Number.isFinite(now)) throw policyError("capacity_continuation_conflict", "Invalid capacity timing identity");
196
+ const native = normalizeProviderFailure(error)?.native_error ?? error?.details?.provider_error ?? error;
197
+ const header = Object.entries(native?.headers ?? {}).find(([key]) => key.toLowerCase() === "retry-after")?.[1];
198
+ const value = header ?? native?.retryAfter ?? native?.retry_after;
199
+ let retry = 0;
200
+ if (value !== undefined && value !== null) {
201
+ retry = typeof value === "number" || typeof value === "string" && /^\d+(\.\d+)?$/.test(value.trim()) ? Number(value) * 1000 : typeof value === "string" && /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/.test(value.trim()) ? Math.max(0, Date.parse(value) - now) : NaN;
202
+ if (!Number.isFinite(retry) || retry < 0 || !Number.isFinite(now + retry) || now + retry > 8.64e15)
203
+ throw policyError("capacity_retry_metadata_invalid", "Retry-After cannot be represented safely", { retry_after: value });
204
+ }
205
+ const jitter = random();
206
+ if (!Number.isFinite(jitter) || jitter < 0 || jitter >= 1) throw policyError("capacity_retry_metadata_invalid", "Invalid retry jitter");
207
+ const wait = Math.max((ordinal === 1 ? 5_000 : 15_000) + Math.floor(jitter * 251), retry);
208
+ if (wait > MAX_RETRY_AFTER_MS) throw policyError("provider_unavailable", "Provider requested a delay beyond the retry budget", { policy: CAPACITY_POLICY, reason: "retry_after_exceeds_budget", retry_after_ms: retry, suggested_retry_at: new Date(now + retry).toISOString() });
209
+ return wait;
210
+ }
211
+
212
+ export function refusalObservation(error, ordinal, firstObservedAt) {
213
+ const failure = normalizeProviderFailure(error);
214
+ return observedRefusal(failure, ordinal, firstObservedAt, CAPACITY_POLICY);
215
+ }
216
+ function observedRefusal(failure, ordinal, firstObservedAt, policy) {
217
+ const observed = Date.parse(firstObservedAt);
218
+ if (!failure || !Number.isSafeInteger(ordinal) || ordinal < 0 || !Number.isFinite(observed))
219
+ throw policyError("capacity_continuation_conflict", "Refusal lacks an immutable native identity/time");
220
+ if (failure.observed_at !== null && (typeof failure.observed_at !== "string" || !Number.isFinite(Date.parse(failure.observed_at)) || Date.parse(failure.observed_at) !== observed))
221
+ throw policyError("capacity_continuation_conflict", "Native refusal observation time is invalid or changed");
222
+ const native = failure.terminal_at && Date.parse(failure.terminal_at);
223
+ return { policy, ordinal, session_id: failure.session_id, turn_id: failure.turn_id,
224
+ request_key: failure.request_key, request_proof: failure.request_proof,
225
+ first_observed_at: firstObservedAt, ...(Number.isFinite(native) && typeof failure.terminal_basis === "string" && failure.terminal_basis ? { native_terminal_at: failure.terminal_at, native_terminal_basis: failure.terminal_basis } : {}) };
226
+ }
227
+
228
+ export function overloadExhausted(refusals, maxRetries = MAX_OVERLOAD_RETRIES) {
229
+ if (!Number.isSafeInteger(maxRetries) || maxRetries < 0 || maxRetries > MAX_OVERLOAD_RETRIES) throw policyError("capacity_continuation_conflict", "Invalid retry budget");
230
+ for (const [index, refusal] of refusals.entries()) {
231
+ const previous = refusals[index - 1];
232
+ if (typeof refusal.first_observed_at !== "string" || !Number.isFinite(Date.parse(refusal.first_observed_at))
233
+ || previous && Date.parse(refusal.first_observed_at) < Date.parse(previous.first_observed_at))
234
+ throw policyError("capacity_continuation_conflict", "Refusal observation clock reversed or is invalid");
235
+ }
236
+ for (const [index, refusal] of refusals.entries()) {
237
+ if (refusal.policy !== CAPACITY_POLICY) throw policyError("capacity_policy_mismatch", "Retained episode uses another retry policy");
238
+ const previous = refusals[index - 1];
239
+ if (refusal.ordinal !== index || previous && (refusal.session_id !== previous.session_id || refusals.slice(0, index).some(item => item.turn_id === refusal.turn_id))) throw policyError("capacity_continuation_conflict", "Refusal chain identity is inconsistent");
240
+ }
241
+ return refusals.length > maxRetries ? { policy: CAPACITY_POLICY, reason: "overload_retries_exhausted", attempts: refusals.length, refusals } : null;
242
+ }
@@ -0,0 +1,202 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { mkdir, open, readFile, rename, unlink } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { withRunnerLock as withLock } from "./runner-lock.mjs";
5
+ import { isObservationLoss, errorRecord } from "./operation-errors.mjs";
6
+ import { operationContext } from "./operation-context.mjs";
7
+
8
+ const appendQueues = new Map();
9
+
10
+ export function canonicalJson(value) {
11
+ const normalize = (item) => {
12
+ if (Array.isArray(item)) return item.map(normalize);
13
+ if (item && typeof item === "object") return Object.fromEntries(Object.keys(item).sort().map((key) => [key, normalize(item[key])]));
14
+ return item;
15
+ };
16
+ return `${JSON.stringify(normalize(value))}\n`;
17
+ }
18
+
19
+ export function sha256(value) {
20
+ return createHash("sha256").update(value).digest("hex");
21
+ }
22
+
23
+ export function hashJson(value) { return sha256(canonicalJson(value)); }
24
+
25
+ export async function writeJsonAtomic(file, value, beforeCommit = () => {}) {
26
+ beforeCommit();
27
+ await mkdir(path.dirname(file), { recursive: true });
28
+ const temporary = `${file}.${process.pid}.${randomUUID()}.tmp`;
29
+ try {
30
+ const payload = await open(temporary, "wx", 0o600);
31
+ try { await payload.writeFile(`${JSON.stringify(value, null, 2)}\n`); await payload.sync(); }
32
+ finally { await payload.close(); }
33
+ beforeCommit();
34
+ await rename(temporary, file);
35
+ const directory = await open(path.dirname(file), "r");
36
+ try { await directory.sync(); }
37
+ finally { await directory.close(); }
38
+ } finally { await unlink(temporary).catch(error => { if (error.code !== "ENOENT") throw error; }); }
39
+ }
40
+
41
+ export async function readJsonLines(file, label = "JSONL") {
42
+ try {
43
+ const source = await readFile(file, "utf8");
44
+ return source.split("\n").filter(Boolean).map((line, index) => {
45
+ try { return JSON.parse(line); }
46
+ catch { throw new Error(`invalid ${label} record at ${file}:${index + 1}`); }
47
+ });
48
+ } catch (error) {
49
+ if (error?.code === "ENOENT") return [];
50
+ throw error;
51
+ }
52
+ }
53
+
54
+ export async function readEvents(file) {
55
+ const records = await readJsonLines(file, "runner event");
56
+ return records.map((record, index) => {
57
+ try { return validateRunnerEvent(record); }
58
+ catch { throw new Error(`invalid runner event at ${file}:${index + 1}`); }
59
+ });
60
+ }
61
+
62
+ export function validateRunnerEvent(value) {
63
+ if (!value || typeof value !== "object" || Array.isArray(value) || value.specversion !== "1.0" || typeof value.id !== "string" || typeof value.source !== "string" || typeof value.type !== "string" || typeof value.time !== "string" || !value.data || typeof value.data !== "object" || !Number.isInteger(value.data.sequence) || value.data.sequence < 1) {
64
+ throw new Error("invalid normalized runner event");
65
+ }
66
+ return value;
67
+ }
68
+
69
+ export async function appendEvent(file, input) {
70
+ const prior = appendQueues.get(file) ?? Promise.resolve();
71
+ const current = prior.then(() => withLock(file, async () => {
72
+ const events = await readEvents(file);
73
+ // Internal callers can validate a dispatch or bind its generation under
74
+ // the same cross-process lock that orders cancellation and completion.
75
+ if (input.deduplicate && input.id) { const existing = events.find(event => event.id === input.id); if (existing) return existing; }
76
+ if (input.beforeAppend?.(events) === false) return null;
77
+ const sequence = events.length + 1;
78
+ const event = {
79
+ specversion: "1.0",
80
+ id: input.id ?? `EVT-${randomUUID()}`,
81
+ source: input.source,
82
+ type: input.type,
83
+ time: input.time ?? new Date().toISOString(),
84
+ subject: input.subject ?? "runner",
85
+ datacontenttype: "application/json",
86
+ runid: input.runId,
87
+ executionid: input.executionId,
88
+ traceid: input.traceId,
89
+ spanid: input.spanId ?? randomUUID(),
90
+ ...(input.parentSpanId ? { parentspanid: input.parentSpanId } : {}),
91
+ data: { sequence, ...input.data }
92
+ };
93
+ const context = operationContext.getStore();
94
+ if (context?.eventsFile === file && context.executionId === input.executionId && context.operationId && input.executionId) {
95
+ event.data.execution_operation_id ??= context.operationId;
96
+ }
97
+ validateRunnerEvent(event);
98
+ await mkdir(path.dirname(file), { recursive: true });
99
+ const handle = await open(file, "a");
100
+ try { await handle.write(`${JSON.stringify(event)}\n`); await handle.sync(); }
101
+ finally { await handle.close(); }
102
+ return event;
103
+ }));
104
+ const tail = current.catch(() => {}); appendQueues.set(file, tail);
105
+ try { return await current; }
106
+ finally { if (appendQueues.get(file) === tail) appendQueues.delete(file); }
107
+ }
108
+
109
+ export function reduceEvents(events) {
110
+ const operations = new Map();
111
+ let state = "planned";
112
+ for (const event of events) {
113
+ const data = event?.data ?? {};
114
+ if (["dev.dd.eval.planned", "dev.dd.eval.completed"].includes(event.type) && typeof data.state === "string") state = data.state;
115
+ if (typeof data.operation_id !== "string") continue;
116
+ const prior = operations.get(data.operation_id) ?? { id: data.operation_id, requested: false, started: false, terminal: null };
117
+ if (event.type.endsWith(".requested")) prior.requested = true;
118
+ if (event.type.endsWith(".started")) prior.started = true;
119
+ if (event.type.endsWith(".observation_lost")) prior.observation_lost = data.error ?? { code: "observation_lost" };
120
+ if (event.type.endsWith(".completed") || event.type.endsWith(".failed") || event.type.endsWith(".cancelled")) {
121
+ const terminal = event.type.split(".").at(-1);
122
+ const result = terminal === "completed" ? data.result : { error: data.error ?? null };
123
+ const resultHash = hashJson({ terminal, result });
124
+ if (prior.terminal && (prior.terminal !== terminal || prior.result_hash !== resultHash)) {
125
+ throw Object.assign(new Error(`runner operation ${data.operation_id} has conflicting terminal events`), { code: "journal_conflict", operation_id: data.operation_id });
126
+ }
127
+ prior.terminal = terminal;
128
+ prior.result = result;
129
+ prior.result_hash = resultHash;
130
+ }
131
+ operations.set(data.operation_id, prior);
132
+ }
133
+ return { state, operations: Object.fromEntries([...operations].map(([id, value]) => [id, value])) };
134
+ }
135
+
136
+ export async function recordOperation({ eventsFile, source, runId, executionId, traceId, operationId, operation, subject = "runner", action }) {
137
+ const existing = await withLock(`${eventsFile}.${operationId.replace(/[^a-zA-Z0-9._-]/g, "_")}`, async () => {
138
+ const current = reduceEvents(await readEvents(eventsFile)).operations[operationId];
139
+ if (current?.terminal === "completed") return current;
140
+ if (current?.terminal) throw Object.assign(new Error(`operation ${operationId} is already ${current.terminal}; use explicit recovery instead of replaying it`), { code: "operation_terminal", operation_id: operationId, terminal: current.terminal });
141
+ if (current?.started && !current.terminal) {
142
+ const error = new Error(current.observation_lost
143
+ ? `operation ${operationId} has no confirmed outcome; reconcile its provider state before retrying`
144
+ : `operation ${operationId} is already in progress; reconcile before retrying`);
145
+ error.code = current.observation_lost ? "operation_observation_lost" : "operation_in_progress";
146
+ error.operation_id = operationId;
147
+ throw error;
148
+ }
149
+ await appendEvent(eventsFile, { source, runId, executionId, traceId, subject, type: "dev.dd.eval.operation.requested", data: { operation_id: operationId, operation, status: "requested" } });
150
+ await appendEvent(eventsFile, { source, runId, executionId, traceId, subject, type: "dev.dd.eval.operation.started", data: { operation_id: operationId, operation, status: "started" } });
151
+ return null;
152
+ });
153
+ if (existing) return { reused: true, operation_id: operationId, result: existing.result };
154
+ try {
155
+ const result = await operationContext.run({ operationId, eventsFile, runId, executionId }, action);
156
+ await completeOperation({ eventsFile, source, runId, executionId, traceId, subject, operationId, operation, result });
157
+ return { reused: false, operation_id: operationId, result };
158
+ } catch (error) {
159
+ if (isObservationLoss(error)) await observationLost({ eventsFile, source, runId, executionId, traceId, subject, operationId, operation, error });
160
+ else await failOperation({ eventsFile, source, runId, executionId, traceId, subject, operationId, operation, error });
161
+ throw error;
162
+ }
163
+ }
164
+
165
+ export async function completeOperation({ eventsFile, source, runId, executionId, traceId, subject = "runner", operationId, operation, result }) {
166
+ return await settleOperation({ eventsFile, source, runId, executionId, traceId, subject, operationId, operation, terminal: "completed", result });
167
+ }
168
+
169
+ export async function failOperation({ eventsFile, source, runId, executionId, traceId, subject = "runner", operationId, operation, error }) {
170
+ return await settleOperation({ eventsFile, source, runId, executionId, traceId, subject, operationId, operation, terminal: "failed", result: { error: errorRecord(error) } });
171
+ }
172
+
173
+ /** A lost observer response is deliberately non-terminal: replay could duplicate a provider Turn. */
174
+ export async function observationLost({ eventsFile, source, runId, executionId, traceId, subject = "runner", operationId, operation, error }) {
175
+ return await withLock(`${eventsFile}.${operationId.replace(/[^a-zA-Z0-9._-]/g, "_")}`, async () => {
176
+ const existing = reduceEvents(await readEvents(eventsFile)).operations[operationId];
177
+ if (existing?.terminal) return { reused: true, operation_id: operationId, result: existing.result };
178
+ if (!existing?.started) throw Object.assign(new Error(`operation ${operationId} has no started receipt`), { code: "operation_not_started" });
179
+ if (existing.observation_lost) return { reused: true, operation_id: operationId, observation_lost: existing.observation_lost };
180
+ const recorded = errorRecord(error);
181
+ await appendEvent(eventsFile, { source, runId, executionId, traceId, subject, type: "dev.dd.eval.operation.observation_lost", data: { operation_id: operationId, operation, status: "observation_lost", error: recorded } });
182
+ return { reused: false, operation_id: operationId, observation_lost: recorded };
183
+ });
184
+ }
185
+
186
+ async function settleOperation({ eventsFile, source, runId, executionId, traceId, subject, operationId, operation, terminal, result }) {
187
+ return await withLock(`${eventsFile}.${operationId.replace(/[^a-zA-Z0-9._-]/g, "_")}`, async () => {
188
+ const existing = reduceEvents(await readEvents(eventsFile)).operations[operationId];
189
+ const expectedHash = hashJson({ terminal, result });
190
+ if (existing?.terminal) {
191
+ if (existing.terminal === terminal && existing.result_hash === expectedHash) return { reused: true, operation_id: operationId, result: existing.result };
192
+ throw Object.assign(new Error(`runner operation ${operationId} has conflicting terminal result`), { code: "journal_conflict", operation_id: operationId });
193
+ }
194
+ if (!existing?.started) throw Object.assign(new Error(`operation ${operationId} has no started receipt`), { code: "operation_not_started" });
195
+ const type = terminal === "completed" ? "dev.dd.eval.operation.completed" : "dev.dd.eval.operation.failed";
196
+ const data = terminal === "completed"
197
+ ? { operation_id: operationId, operation, status: terminal, result }
198
+ : { operation_id: operationId, operation, status: terminal, error: result.error };
199
+ await appendEvent(eventsFile, { source, runId, executionId, traceId, subject, type, data });
200
+ return { reused: false, operation_id: operationId, result };
201
+ });
202
+ }
@@ -0,0 +1,42 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync, rmdirSync } from "node:fs";
3
+ import path from "node:path";
4
+
5
+ function release(lock, owner) {
6
+ try { unlinkSync(path.join(lock, owner)); } catch (error) { if (error.code === "ENOENT") return; throw error; }
7
+ // Never recursively remove a directory: another owner may already have acquired it.
8
+ try { rmdirSync(lock); } catch (error) { if (!["ENOENT", "ENOTEMPTY", "EEXIST"].includes(error.code)) throw error; }
9
+ }
10
+
11
+ function reclaimDeadOwner(lock) {
12
+ let entries;
13
+ try { entries = readdirSync(lock); } catch (error) { if (error.code === "ENOENT") return; throw error; }
14
+ if (entries.length !== 1 || !/^owner-.*\.json$/.test(entries[0])) return;
15
+ let owner;
16
+ try { owner = JSON.parse(readFileSync(path.join(lock, entries[0]), "utf8")); } catch { return; }
17
+ if (!Number.isInteger(owner.pid) || owner.pid <= 0) return;
18
+ try { process.kill(owner.pid, 0); }
19
+ catch (error) { if (error.code === "ESRCH") release(lock, entries[0]); }
20
+ // A live/reused PID or unknown owner is conservative: age never proves death.
21
+ }
22
+
23
+ export async function withRunnerLock(file, action, { timeoutMs = 30_000 } = {}) {
24
+ const lock = `${file}.lock`;
25
+ const owner = `owner-${process.pid}-${randomUUID()}.json`;
26
+ const deadline = performance.now() + timeoutMs;
27
+ for (;;) {
28
+ let acquired = false;
29
+ try { mkdirSync(lock); acquired = true; }
30
+ catch (error) { if (error.code !== "EEXIST") throw error; }
31
+ if (acquired) {
32
+ // No await between acquisition and identifying the owner.
33
+ try { writeFileSync(path.join(lock, owner), JSON.stringify({ pid: process.pid }), { flag: "wx" }); }
34
+ catch (error) { release(lock, owner); throw error; }
35
+ try { return await action(); }
36
+ finally { release(lock, owner); }
37
+ }
38
+ reclaimDeadOwner(lock);
39
+ if (performance.now() >= deadline) throw Object.assign(new Error(`runner lock has a live or unconfirmed owner: ${lock}; inspect its owner before recovery`), { code: "runner_lock_timeout" });
40
+ await new Promise((resolve) => setTimeout(resolve, 10));
41
+ }
42
+ }
@@ -0,0 +1,30 @@
1
+ import { errorRecord } from "./operation-errors.mjs";
2
+
3
+ /** Diagnostic failure never prevents cancellation of already owned Sessions.
4
+ * Only a fresh successful observation can establish settlement. */
5
+ export async function waitForSettlement({ observe, cancel, knownSessions = () => [], timeoutMs = 5_000 }) {
6
+ const deadline = performance.now() + timeoutMs;
7
+ const cancelled = new Set(), errors = [];
8
+ if (cancel) for (const id of knownSessions()) {
9
+ cancelled.add(id);
10
+ try { await cancel(id); } catch (error) { errors.push({ phase: "cancel", session_id: id, ...errorRecord(error) }); }
11
+ }
12
+ for (;;) {
13
+ let state;
14
+ try { state = await observe(); }
15
+ catch (error) {
16
+ if (!cancel) throw error;
17
+ errors.push({ phase: "observe", ...errorRecord(error) });
18
+ state = { sessions: knownSessions(), active: true, observation_error: errorRecord(error) };
19
+ }
20
+ if (!state.active && state.sessions.length === 0) return { ...state, cleanup_errors: errors };
21
+ // The observation budget must not skip a newly discovered owned target.
22
+ // Attempt its cancellation once, then leave physical settlement pending.
23
+ for (const id of state.sessions) if (cancel && !cancelled.has(id)) {
24
+ cancelled.add(id);
25
+ try { await cancel(id); } catch (error) { errors.push({ phase: "cancel", session_id: id, ...errorRecord(error) }); }
26
+ }
27
+ if (!cancel || performance.now() >= deadline) throw Object.assign(new Error("daemon still owns an unsettled Session tree"), { code: "tree_not_settled", details: { ...state, cleanup_errors: errors } });
28
+ await new Promise(resolve => setTimeout(resolve, 50));
29
+ }
30
+ }
@@ -0,0 +1,9 @@
1
+ export const SETUP_STARTUP_MS: number;
2
+ export const SETUP_QUIET_MS: number;
3
+ export const setupPhases: Set<string>;
4
+ export function setupReporter(operationId?: string): (phase: string, step?: string | number | null) => void;
5
+ export const publishSetup: ReturnType<typeof setupReporter>;
6
+ export function isSetupPhase(value: unknown): boolean;
7
+ export function startupObserver(stateDir: string, daemonId: string): () => Promise<number>;
8
+ export function setupObserver(operationId: string): (value: unknown) => boolean;
9
+ export function observationDetails(clock: import('./observation-clock.mjs').ObservationClock, phase: string | null, pid: number | undefined): Record<string, unknown>;
@@ -0,0 +1,53 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ export const SETUP_STARTUP_MS = 120_000;
5
+ export const SETUP_QUIET_MS = 30_000;
6
+ export const setupPhases = new Set(['ingress_entered', 'imports_ready', 'probe_started', 'probe_completed', 'dependency_check_completed', 'transfer_progress', 'identity_digest_progress', 'identity_digest_completed', 'native_initialized', 'ready']);
7
+ export function setupReporter(operationId = process.env.DD_EVAL_OPERATION_ID) {
8
+ if (!operationId) return () => {};
9
+ let sequence = 0; const producerId = randomUUID();
10
+ return (phase, step = null) => {
11
+ if (!setupPhases.has(phase)) throw new Error('Invalid setup phase');
12
+ process.stderr.write(JSON.stringify({ kind: 'setup_phase', operation_id: operationId, producer_id: producerId, phase, step, sequence: ++sequence, observed_at: new Date().toISOString() }) + '\n');
13
+ };
14
+ }
15
+ export const publishSetup = setupReporter();
16
+ export function isSetupPhase(value) {
17
+ return value?.kind === 'setup_phase' && typeof value.operation_id === 'string' && value.operation_id.length > 0 && setupPhases.has(value.phase)
18
+ && (!Object.hasOwn(value, 'producer_id') || typeof value.producer_id === 'string' && value.producer_id.length > 0 && value.producer_id.length <= 128)
19
+ && Number.isSafeInteger(value.sequence) && value.sequence > 0 && value.sequence <= 1_000_000
20
+ && (value.step === null || typeof value.step === 'string' && value.step.length <= 4096 || Number.isSafeInteger(value.step) && value.step >= 0)
21
+ && typeof value.observed_at === 'string' && Number.isFinite(Date.parse(value.observed_at))
22
+ && !Object.hasOwn(value, 'error') && !Object.hasOwn(value, 'code');
23
+ }
24
+ export function startupObserver(stateDir, daemonId) {
25
+ const seen = new Set(); let sequence = 0, binding;
26
+ return async () => {
27
+ let state;
28
+ try { state = JSON.parse(await readFile(path.join(stateDir, 'daemon.json'), 'utf8')); }
29
+ catch (error) { if (error.code === 'ENOENT') return sequence; throw error; }
30
+ if (state.daemon_id !== daemonId) throw Object.assign(new Error('Startup daemon identity changed'), { code: 'operation_binding_conflict' });
31
+ const owner = state.config?.runtime_owner;
32
+ const identity = JSON.stringify([state.started_at ?? null, owner?.owner_id ?? null, owner?.operation_id ?? null, state.generation ?? null]);
33
+ binding ??= identity;
34
+ if (identity !== binding) throw Object.assign(new Error('Startup ownership binding changed'), { code: 'operation_binding_conflict' });
35
+ const marker = JSON.stringify([state.pid ?? null, state.provider_pid ?? null, state.shutdown_state ?? null, state.startup_phase ?? null]);
36
+ if (!seen.has(marker)) { seen.add(marker); sequence++; publishSetup(state.shutdown_state === 'running' ? 'native_initialized' : 'probe_started', `${daemonId}:${sequence}`); }
37
+ return sequence;
38
+ };
39
+ }
40
+ export function setupObserver(operationId) {
41
+ const startedAt = Date.now(); const sequences = new Map(), markers = new Set();
42
+ return value => {
43
+ if (typeof operationId !== 'string' || markers.size >= 4096 || !isSetupPhase(value) || value.operation_id !== operationId
44
+ || value.sequence <= (sequences.get(value.producer_id ?? null) ?? 0) || Date.parse(value.observed_at) < startedAt || Date.parse(value.observed_at) > Date.now()) return false;
45
+ const marker = JSON.stringify([value.producer_id ?? null, value.phase, value.step]);
46
+ if (markers.has(marker)) return false;
47
+ markers.add(marker); sequences.set(value.producer_id ?? null, value.sequence); return true;
48
+ };
49
+ }
50
+ export function observationDetails(clock, phase, pid) {
51
+ return { reason: clock.observationLost ? 'observation_gap' : 'inactivity', phase, pid,
52
+ timeout_ms: clock.timeoutMs, observation_lost: clock.observationLost, observation_clock: clock.state(), ...(clock.setupProgress ? { last_setup: clock.setupProgress } : {}), effect: 'unknown' };
53
+ }