@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,306 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createHash, randomUUID } from "node:crypto";
3
+ import { link, mkdir, open, readFile, unlink } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { isDeepStrictEqual } from "node:util";
6
+ import { reportedFailure } from "./process-json.mjs";
7
+ import { errorRecord, reportedError } from "./operation-errors.mjs";
8
+ import { writeJsonAtomic } from "./runner-events.mjs";
9
+ import { parseLifecycleCommand } from "./lifecycle-command.mjs";
10
+
11
+ export function isStandaloneWorkStart(command) {
12
+ if (typeof command !== "string") return false;
13
+ const parsed = parseLifecycleCommand(command);
14
+ return parsed.kind === "standalone" && parsed.supported !== false && !parsed.invocation.wrapped && parsed.invocation.operation === "work_start";
15
+ }
16
+
17
+ /** Record a native callback, not a grant and not a claim about its creator
18
+ * prompt. The CLI must match an issued command and ask the owning daemon to
19
+ * verify physical ancestry before its existing Work CAS can admit execution. */
20
+ export async function retainNativeWorkStart(stateDir, binding, observer, retained) {
21
+ if (!observer?.operationId || typeof observer.guard !== "function") return null;
22
+ observer.guard();
23
+ const prior = [...retained.values()].find(value => value.binding?.provider_session_id === binding.provider_session_id
24
+ && value.binding.tool_call_id === binding.tool_call_id && value.binding.event === binding.event);
25
+ if (prior) {
26
+ if (prior.binding.daemon_id !== binding.daemon_id || prior.binding.root_provider_session_id !== binding.root_provider_session_id
27
+ || prior.binding.native_command !== binding.native_command || prior.binding.native_cwd !== binding.native_cwd)
28
+ throw Object.assign(new Error("Native Work callback identity was reused with different input"), { code: "native_hook_identity_conflict" });
29
+ prior.guard(); return prior.binding;
30
+ }
31
+ if (!isStandaloneWorkStart(binding.native_command)) return null;
32
+ observer.requests ??= new Map();
33
+ const accepted = await acceptNativeHookRequest(stateDir, { ...binding, operation_id: observer.operationId,
34
+ turn_generation: observer.generation, native_creator: "unconfirmed", native_admission: "assigned_work_start",
35
+ native_ancestry: "pending", command_sha256: createHash("sha256").update(binding.native_command).digest("hex") }, observer);
36
+ observer.guard();
37
+ observer.requests.set(accepted.request_id, { current: observer, binding: accepted });
38
+ retained.set(accepted.request_id, { binding: accepted, guard: observer.guard });
39
+ return accepted;
40
+ }
41
+
42
+ /** Retain accepted native requests in the existing operation hook ledger. */
43
+ export async function acceptNativeHookRequest(stateDir, binding, current = null) {
44
+ if (["operation_id", "daemon_id", "tool_call_id", "root_provider_session_id", "provider_session_id"].some(key => typeof binding[key] !== "string" || !binding[key])
45
+ || !Number.isSafeInteger(binding.turn_generation) || binding.turn_generation < 0
46
+ || !/^[a-f0-9]{64}$/.test(binding.command_sha256 ?? "")) throw Object.assign(new Error("Native hook has no current owned operation"), { code: "native_hook_unproven" });
47
+ const key = JSON.stringify([binding.provider_session_id, binding.tool_call_id, binding.event]);
48
+ const existing = current && [...current.requests.values()].find(value => JSON.stringify([value.binding.provider_session_id, value.binding.tool_call_id, value.binding.event]) === key)?.binding;
49
+ const same = value => {
50
+ if (value.command_sha256 !== binding.command_sha256 || value.native_cwd !== binding.native_cwd) throw Object.assign(new Error("Native tool identity was reused with changed hook input"), { code: "native_hook_identity_conflict" });
51
+ return value;
52
+ };
53
+ if (existing) return same(existing);
54
+ current && (current.accepting ??= new Map());
55
+ if (current?.accepting.has(key)) return same(await current.accepting.get(key));
56
+ const accepted = (async () => {
57
+ const directory = path.join(stateDir, "operations", createHash("sha256").update(binding.operation_id).digest("hex"));
58
+ const requested = JSON.parse(await readFile(path.join(directory, "requested.json"), "utf8"));
59
+ if (requested.operation_id !== binding.operation_id || requested.daemon_id !== binding.daemon_id || !["session.prompt", "session.create", "session.start"].includes(requested.operation)
60
+ || requested.operation === "session.prompt" && requested.session_id && requested.session_id !== binding.root_provider_session_id) throw Object.assign(new Error("Native hook operation does not match its retained owner"), { code: "native_hook_unproven" });
61
+ // The retained in-memory proof must be the same JSON value the CLI reads,
62
+ // including optional native fields omitted by JSON serialization.
63
+ const receipt = JSON.parse(JSON.stringify({ ...binding, schema_id: "dd-flow/hook-request@1", request_id: randomUUID() }));
64
+ await writeJsonAtomic(path.join(directory, "hooks", `${receipt.request_id}.json`), receipt);
65
+ return receipt;
66
+ })();
67
+ current?.accepting.set(key, accepted);
68
+ try { return await accepted; } finally { current?.accepting.delete(key); }
69
+ }
70
+
71
+ export async function writeNativeHookFailure(stateDir, binding, error) {
72
+ if (!binding?.request_id || !/^[A-Za-z0-9-]{1,128}$/.test(binding.request_id)) return;
73
+ // The observation budget may already have expired. It cannot also govern
74
+ // the single atomic write that records why that observation failed.
75
+ const directory = path.join(stateDir, "hook-failures"), file = path.join(directory, `${binding.request_id}.json`);
76
+ const value = {
77
+ ...errorRecord(error), request_id: binding.request_id, observed_at: new Date().toISOString(), native_hook_binding: binding,
78
+ };
79
+ await mkdir(directory, { recursive: true });
80
+ const temporary = `${file}.${randomUUID()}.tmp`;
81
+ try {
82
+ const handle = await open(temporary, "wx", 0o600);
83
+ try { await handle.writeFile(`${JSON.stringify(value)}\n`); await handle.sync(); }
84
+ finally { await handle.close(); }
85
+ try { await link(temporary, file); }
86
+ catch (cause) {
87
+ if (cause.code !== "EEXIST") throw cause;
88
+ const retained = JSON.parse(await readFile(file, "utf8"));
89
+ if (retained.request_id !== binding.request_id || !isDeepStrictEqual(retained.native_hook_binding, binding))
90
+ throw Object.assign(new Error("Native hook failure receipt conflicts with its retained binding"), { code: "native_hook_identity_conflict" });
91
+ return; // The first bound failure remains authoritative on retry.
92
+ }
93
+ const handleDirectory = await open(directory, "r");
94
+ try { await handleDirectory.sync(); } finally { await handleDirectory.close(); }
95
+ } finally { await unlink(temporary).catch(cause => { if (cause.code !== "ENOENT") throw cause; }); }
96
+ }
97
+
98
+ /** Read only requests accepted for this exact live operation, never scan a mailbox. */
99
+ export async function readNativeHookFailures(stateDir, requests, current, reject) {
100
+ for (const [id, accepted] of requests) {
101
+ if (accepted.current !== current) continue;
102
+ let value;
103
+ try { value = JSON.parse(await readFile(path.join(stateDir, "hook-failures", `${id}.json`), "utf8")); }
104
+ catch (error) { if (error.code === "ENOENT") continue; value = { code: "native_hook_receipt_invalid", message: error.message }; }
105
+ if (value.request_id !== id || !value.native_hook_binding || JSON.stringify(value.native_hook_binding) !== JSON.stringify(accepted.binding) || typeof value.code !== "string" || typeof value.message !== "string") {
106
+ if (!accepted.diagnostic) {
107
+ accepted.diagnostic = { code: "native_hook_receipt_invalid", message: "Accepted hook request has an unreadable or unbound failure receipt", request_id: id, operation_id: accepted.binding.operation_id, effect: "unknown", receipt_bound: false };
108
+ process.stderr.write(`${JSON.stringify({ native_hook_diagnostic: accepted.diagnostic })}\n`);
109
+ }
110
+ continue;
111
+ }
112
+ const error = reportedError(value, "Native hook failed");
113
+ error.details = { ...error.details, native_hook_binding: accepted.binding };
114
+ await reject(error);
115
+ requests.delete(id);
116
+ }
117
+ }
118
+
119
+ /** The caller supplies its qualified native limit; phases share that deadline. */
120
+ export function hookBudget(timeoutMs = 25_000, deadlineAt = process.env.DD_FLOW_HOOK_DEADLINE_AT ? Number(process.env.DD_FLOW_HOOK_DEADLINE_AT) : null) {
121
+ if (deadlineAt !== null && (!Number.isSafeInteger(deadlineAt) || deadlineAt < 0)) throw Object.assign(new Error("Invalid native hook deadline"), { code: "hook_deadline_invalid", details: { effect: "unknown" } });
122
+ const started = performance.now();
123
+ const duration = Math.max(0, Math.min(timeoutMs, Number.isFinite(deadlineAt) ? deadlineAt - Date.now() : timeoutMs));
124
+ const remaining = (phase, maximum = duration) => {
125
+ const value = duration - (performance.now() - started);
126
+ if (value <= 0) throw Object.assign(new Error(`Native hook deadline exceeded during ${phase}`), { code: "native_hook_timeout", details: { phase, elapsed_ms: Math.round(performance.now() - started), effect: "unknown" } });
127
+ return Math.max(1, Math.floor(Math.min(maximum, value)));
128
+ };
129
+ return { deadlineAt: Math.floor(Date.now() + duration), remaining, async run(action, phase) {
130
+ const timeoutMs = remaining(phase);
131
+ let timer;
132
+ try { return await Promise.race([Promise.resolve().then(() => { remaining(phase); return action(); }), new Promise((_, reject) => { timer = setTimeout(() => reject(Object.assign(new Error(`Native hook deadline exceeded during ${phase}`), { code: "native_hook_timeout", details: { phase, effect: "unknown" } })), timeoutMs); })]); }
133
+ finally { clearTimeout(timer); }
134
+ } };
135
+ }
136
+
137
+ /** Bound native hook ingress before parsing or opening adapter state. */
138
+ export function readNativeHookInput(stream, budget, maxBytes = 1_048_576) {
139
+ return new Promise((resolve, reject) => {
140
+ const chunks = []; let bytes = 0, done = false;
141
+ const cleanup = () => { clearTimeout(timer); stream.off("data", onData); stream.off("end", onEnd); stream.off("error", onError); };
142
+ const finish = (error, value) => { if (done) return; done = true; cleanup(); if (error) { stream.destroy(); reject(error); } else resolve(value); };
143
+ const onData = chunk => {
144
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
145
+ bytes += buffer.length;
146
+ if (bytes > maxBytes) finish(Object.assign(new Error("Native hook input exceeds 1 MiB"), { code: "native_hook_input_too_large" }));
147
+ else chunks.push(buffer);
148
+ };
149
+ const onEnd = () => finish(null, Buffer.concat(chunks).toString("utf8"));
150
+ const onError = error => finish(error);
151
+ let timeoutMs;
152
+ try { timeoutMs = budget.remaining("input"); } catch (error) { reject(error); return; }
153
+ const timer = setTimeout(() => finish(Object.assign(new Error("Native hook deadline exceeded during input"), { code: "native_hook_timeout", details: { phase: "input", effect: "unknown" } })), timeoutMs);
154
+ stream.on("data", onData).once("end", onEnd).once("error", onError);
155
+ stream.resume();
156
+ });
157
+ }
158
+
159
+ export async function terminateCommandTree(child, { platform = process.platform, launch = spawn, timeoutMs = 400 } = {}) {
160
+ if (!child.pid) return;
161
+ if (platform !== "win32") { process.kill(-child.pid, "SIGKILL"); return; }
162
+ // Node's child.kill on Windows only terminates the leader. taskkill is the
163
+ // native subtree primitive; bound its own lifetime as well as the request.
164
+ await new Promise((resolve, reject) => {
165
+ const killer = launch("taskkill", ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, stdio: "ignore" });
166
+ let settled = false, timer;
167
+ const finish = error => { if (settled) return; settled = true; clearTimeout(timer); error ? reject(error) : resolve(); };
168
+ timer = setTimeout(() => { killer.kill("SIGKILL"); killer.unref(); finish(Object.assign(new Error("Windows subtree cleanup timed out"), { code: "process_cleanup_timeout" })); }, timeoutMs);
169
+ killer.once("error", finish);
170
+ killer.once("close", code => finish(code === 0 ? null : Object.assign(new Error(`taskkill exited ${code}`), { code: "process_cleanup_failed" })));
171
+ });
172
+ }
173
+
174
+ /** Preserve the native hook protocol across the CLI process boundary. */
175
+ export async function runBoundedCommand({ bin, args, nodeBin = process.execPath, input = null, cwd, env = {}, timeoutMs = 15_000, timeoutCode = "native_hook_timeout", inheritDeadline = true, cleanupWithinBudget = false, maintenanceProgress = null, signal }) {
176
+ if (signal?.aborted) throw Object.assign(new Error("Bounded CLI request cancelled before launch"), { code: "process_maintenance_cancelled", details: { effect: "no_effect" } });
177
+ const inherited = inheritDeadline ? env.DD_FLOW_HOOK_DEADLINE_AT ?? process.env.DD_FLOW_HOOK_DEADLINE_AT : undefined;
178
+ if (inherited !== undefined) {
179
+ const deadline = Number(inherited);
180
+ if (!Number.isSafeInteger(deadline) || deadline < 0) throw Object.assign(new Error("Invalid native hook deadline"), { code: "hook_deadline_invalid", details: { effect: "no_effect" } });
181
+ timeoutMs = Math.min(timeoutMs, deadline - Date.now());
182
+ }
183
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) throw Object.assign(new Error("Native hook budget exhausted before subprocess launch"), { code: timeoutCode, details: { phase: "subprocess", effect: "no_effect" } });
184
+ if (maintenanceProgress && (!Number.isFinite(maintenanceProgress.inactivityMs) || maintenanceProgress.inactivityMs <= 0
185
+ || maintenanceProgress.startupMs !== undefined && (!Number.isFinite(maintenanceProgress.startupMs) || maintenanceProgress.startupMs <= 0)
186
+ || typeof maintenanceProgress.action !== "string" || !(maintenanceProgress.processId === null || typeof maintenanceProgress.processId === "string")))
187
+ throw Object.assign(new Error("Invalid maintenance progress budget"), { code: "process_maintenance_timeout", details: { effect: "no_effect", native_dispatch_started: false } });
188
+ const started = performance.now();
189
+ // Transport/physical cleanup has its own small tail inside the outer limit.
190
+ const cleanupMs = Math.min(500, timeoutMs / 5);
191
+ const commandMs = cleanupWithinBudget ? Math.max(1, timeoutMs - cleanupMs) : timeoutMs;
192
+ const deadlineAt = Math.floor(Date.now() + Math.max(0, commandMs - Math.min(250, commandMs / 10)));
193
+ const script = /\.[cm]?js$/.test(bin);
194
+ const output = await new Promise((resolve, reject) => {
195
+ const child = spawn(script ? nodeBin : bin, [...(script ? [bin] : []), ...args], {
196
+ cwd, env: { ...process.env, ...env, DD_FLOW_HOOK_DEADLINE_AT: String(deadlineAt) }, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"]
197
+ });
198
+ let stdout = "", stderr = "", failure, cleanupTimer, settled = false, termination;
199
+ let timer, phaseBuffer = "", lastProgress = started;
200
+ const progressPhases = new Set();
201
+ let importsReady = maintenanceProgress?.startupMs === undefined;
202
+ const silenceMs = () => importsReady ? maintenanceProgress?.inactivityMs : maintenanceProgress.startupMs;
203
+ const commandDeadline = started + commandMs;
204
+ const finish = (error, value) => {
205
+ if (settled) return;
206
+ settled = true; clearTimeout(timer); clearTimeout(cleanupTimer); signal?.removeEventListener("abort", abort);
207
+ if (error) {
208
+ const diagnostics = hookDiagnostics(stderr);
209
+ if (diagnostics.length) error.details = { ...error.details, hook_diagnostics: diagnostics };
210
+ reject(error);
211
+ } else resolve(value);
212
+ };
213
+ const stop = error => {
214
+ if (termination || settled) return;
215
+ failure ??= error;
216
+ clearTimeout(timer);
217
+ failure.details = { ...failure.details, failure_at: new Date().toISOString(), elapsed_ms: Math.round(performance.now() - started), effect: "unknown", subprocess_pid: child.pid ?? null };
218
+ termination = terminateCommandTree(child).catch(cleanup => {
219
+ if (cleanup.code === "ESRCH") return;
220
+ failure.details.cleanup_error = { code: cleanup.code, message: cleanup.message };
221
+ failure.details.cleanup_unconfirmed = true;
222
+ child.kill("SIGKILL");
223
+ });
224
+ cleanupTimer ??= setTimeout(() => {
225
+ failure.details.cleanup_unconfirmed = true;
226
+ child.stdin.destroy(); child.stdout.destroy(); child.stderr.destroy(); child.unref();
227
+ finish(failure);
228
+ }, cleanupWithinBudget ? cleanupMs : 500);
229
+ };
230
+ // A useful, request-bound phase advances the silence window, not ownership
231
+ // authority. The child storage deadline and parent uncertainty horizon stay
232
+ // fixed; repeated phases, logging and polling cannot keep a writer alive.
233
+ const arm = () => {
234
+ clearTimeout(timer);
235
+ const now = performance.now();
236
+ const remaining = Math.min(commandDeadline - now, maintenanceProgress ? lastProgress + silenceMs() - now : Infinity);
237
+ if (remaining <= 0) { stop(Object.assign(new Error("Bounded CLI request timed out"), { code: timeoutCode,
238
+ details: maintenanceProgress ? { phase: importsReady ? "storage" : "startup", inactivity_ms: silenceMs(),
239
+ ownership_horizon_ms: commandMs } : {} })); return; }
240
+ timer = setTimeout(arm, Math.ceil(remaining));
241
+ };
242
+ arm();
243
+ const abort = () => stop(Object.assign(new Error("Bounded CLI request cancelled"), { code: "process_maintenance_cancelled" }));
244
+ signal?.addEventListener("abort", abort, { once: true });
245
+ if (signal?.aborted) abort();
246
+ child.stdout.setEncoding("utf8").on("data", chunk => { stdout += chunk; });
247
+ // Match the existing response bound: a legal bounded error tree may exceed
248
+ // 64KiB when pretty-printed, plus maintenance phases preceding the receipt.
249
+ child.stderr.setEncoding("utf8").on("data", chunk => {
250
+ stderr = (stderr + chunk).slice(-1_048_576);
251
+ if (!maintenanceProgress || termination || settled) return;
252
+ phaseBuffer += chunk;
253
+ const lines = phaseBuffer.split("\n"); phaseBuffer = lines.pop().slice(-16_384);
254
+ for (const line of lines) {
255
+ if (line.length > 16_384) continue;
256
+ let phase; try { phase = JSON.parse(line); } catch { continue; }
257
+ if (phase?.kind !== "process_maintenance_phase" || phase.action !== maintenanceProgress.action
258
+ || (phase.process_id ?? null) !== maintenanceProgress.processId || phase.native_dispatch_started !== false
259
+ || !["request", "imports_ready", "store_open", "store_validation", "lookup", "writer_reservation", "writer_reserved", "write", "commit", "committed", "ack"].includes(phase.phase)
260
+ || phase.store_kind !== undefined && !["run", "resource"].includes(phase.store_kind)) continue;
261
+ const key = `${phase.store_kind ?? ""}:${phase.phase}`;
262
+ if (progressPhases.has(key)) continue;
263
+ // Delayed observation cannot revive an already-expired silence window.
264
+ const now = performance.now();
265
+ if (now >= commandDeadline || now - lastProgress >= silenceMs()) { arm(); return; }
266
+ // Cold imports are not a stalled storage operation. Readiness is an
267
+ // actual boundary, never a timer heartbeat; the ownership horizon stays fixed.
268
+ if (["imports_ready", "store_open"].includes(phase.phase)) importsReady = true;
269
+ progressPhases.add(key); lastProgress = now; arm();
270
+ }
271
+ });
272
+ child.stdin.on("error", error => { failure ??= error; });
273
+ child.on("error", error => finish(failure ?? error));
274
+ child.on("close", code => {
275
+ if (failure) { void (termination ?? Promise.resolve()).then(() => finish(failure)); return; }
276
+ if (code !== 0) {
277
+ return finish(reportedFailure(stdout, stderr, "Native hook admission failed", "native_hook_failed"));
278
+ }
279
+ finish(null, stdout);
280
+ });
281
+ child.stdin.end(input);
282
+ });
283
+ return output;
284
+ }
285
+
286
+ /** Only our structured phase allowlist crosses a timeout, never raw stderr/env. */
287
+ function hookDiagnostics(stderr) {
288
+ return stderr.split("\n").flatMap(line => {
289
+ try {
290
+ const value = JSON.parse(line);
291
+ if (!["native_hook_phase", "process_maintenance_phase"].includes(value?.kind)) return [];
292
+ const phase = typeof value.phase === "string" && /^[a-z_]{1,48}$/.test(value.phase) ? value.phase : null;
293
+ if (!phase) return [];
294
+ return [{ phase, ...Object.fromEntries(["elapsed_ms", "remaining_ms", "sqlite_extended_code"].filter(key => Number.isFinite(value[key])).map(key => [key, value[key]])), ...(value.kind === "process_maintenance_phase" ? { ...Object.fromEntries(["action", "process_id", "operation_id", "lease_expires_at", "store_kind", "maintenance_effect", "attempt_kind", "role"].filter(key => typeof value[key] === "string" && /^[A-Za-z0-9:._-]{1,128}$/.test(value[key])).map(key => [key, value[key]])), ...(typeof value.native_dispatch_started === "boolean" ? { native_dispatch_started: value.native_dispatch_started } : {}) } : {}) }];
295
+ } catch { return []; }
296
+ }).slice(-16);
297
+ }
298
+
299
+ export async function invokeNativeHook({ bin, args, nodeBin, payload, home, cwd, env, timeoutMs = 25_000 }) {
300
+ const output = await runBoundedCommand({ bin, args, nodeBin, input: `${JSON.stringify(payload)}\n`, cwd, env: { ...env, DD_FLOW_HOME: home }, timeoutMs, cleanupWithinBudget: true });
301
+ let result;
302
+ try { result = JSON.parse(output); } catch { throw Object.assign(new Error("Invalid native hook JSON response"), { code: "native_hook_response_invalid" }); }
303
+ if (result?.ok === false && typeof result.error?.code === "string") throw Object.assign(new Error(result.error.message ?? "Native hook failed"), { code: result.error.code, details: result.error.details });
304
+ if (!result || typeof result !== "object" || Array.isArray(result) || result.ok === false) throw Object.assign(new Error("Native hook did not return a successful protocol object"), { code: "native_hook_response_invalid" });
305
+ return result;
306
+ }
@@ -0,0 +1,2 @@
1
+ export function nativeCommandFingerprint(input: { executable: string; args: string[]; cwd: string; env: Record<string, string | undefined>; operationId: string }): string;
2
+ export function prepareDaemonRequest<T extends { id: string; operation: string; params?: Record<string, unknown> }>(request: T): T & { invocation_sha256?: string };
@@ -0,0 +1,65 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import process from 'node:process';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { hashJson } from './runner-events.mjs';
6
+
7
+ const environmentKeys = ['HOME', 'CODEX_HOME', 'DD_FLOW_CONFIG_HOME', 'DD_FLOW_RESOURCE_HOME', 'DD_FLOW_HOME', 'DD_FLOW_BIN', 'DD_FLOW_ENGINE_HOME'];
8
+ const fail = reason => { throw Object.assign(new Error('Native request proof does not match its prepared command'), {
9
+ code: 'native_request_proof_conflict', details: { reason, effect: 'no_effect' }
10
+ }); };
11
+
12
+ /** Independent transport identity: prepared by the caller before launching
13
+ * the adapter, and recomputed by the adapter's shared request builder. */
14
+ export function nativeCommandFingerprint({ executable, args, cwd, env, operationId }) {
15
+ return hashJson({ executable, args, cwd, operation_id: operationId,
16
+ environment: Object.fromEntries([...environmentKeys, ...(env.PLAYWRIGHT_BROWSERS_PATH === undefined ? [] : ['PLAYWRIGHT_BROWSERS_PATH'])].map(key => [key, env[key] ?? null])) });
17
+ }
18
+
19
+ /** Called after the adapter's own argument preparation but before its RPC or
20
+ * daemon-start action. No provider response can supply this fingerprint. */
21
+ export function prepareDaemonRequest(request) {
22
+ const file = process.env.DD_FLOW_NATIVE_REQUEST_PROOF_FILE;
23
+ const expected = process.env.DD_FLOW_NATIVE_COMMAND_SHA256;
24
+ const operation = process.env.DD_FLOW_NATIVE_REQUEST_OPERATION;
25
+ if (file === undefined && expected === undefined) return request;
26
+ // Control helpers may inspect status before their owned stop RPC. Status
27
+ // cannot consume the productive/control request's independently bound proof.
28
+ if (operation && request.operation !== operation) {
29
+ if (request.operation === 'daemon.status' && operation === 'daemon.stop') return request;
30
+ fail('operation_changed');
31
+ }
32
+ const ownerText = process.env.DD_FLOW_NATIVE_REQUEST_PROOF_OWNER;
33
+ // Never forward caller proof authority into the daemon/provider process.
34
+ delete process.env.DD_FLOW_NATIVE_REQUEST_PROOF_FILE;
35
+ delete process.env.DD_FLOW_NATIVE_COMMAND_SHA256;
36
+ delete process.env.DD_FLOW_NATIVE_REQUEST_OPERATION;
37
+ delete process.env.DD_FLOW_NATIVE_REQUEST_PROOF_OWNER;
38
+ if (!file || !path.isAbsolute(file) || !/^[a-f0-9]{64}$/.test(expected ?? '')
39
+ || typeof request.id !== 'string' || !request.id || typeof request.operation !== 'string' || request.operation !== operation) fail('invalid_owner');
40
+ const command = nativeCommandFingerprint({ executable: process.argv[1], args: process.argv.slice(2),
41
+ cwd: process.cwd(), env: process.env, operationId: request.id });
42
+ if (command !== expected || fs.realpathSync(path.dirname(file)) !== path.dirname(file)) fail('command_changed');
43
+ let owner;
44
+ try { owner = JSON.parse(ownerText ?? 'null'); } catch { fail('invalid_parent_owner'); }
45
+ const parent = fs.lstatSync(path.dirname(file));
46
+ if (!parent.isDirectory() || parent.dev !== owner?.dev || parent.ino !== owner?.ino) fail('proof_parent_changed');
47
+ const proof = { schema_id: 'dd-flow/native-request-proof@1', operation_id: request.id, operation: request.operation,
48
+ command_sha256: command, params_sha256: hashJson({ operation: request.operation, params: request.params ?? {} }),
49
+ session_id: request.params?.sessionId ?? null };
50
+ const temporary = `${file}.${randomUUID()}.tmp`;
51
+ const fd = fs.openSync(temporary, 'wx', 0o600);
52
+ try {
53
+ fs.writeFileSync(fd, JSON.stringify(proof)); fs.fsyncSync(fd);
54
+ const current = fs.lstatSync(path.dirname(file));
55
+ if (parent.dev !== current.dev || parent.ino !== current.ino || !current.isDirectory()) fail('proof_parent_changed');
56
+ try { fs.linkSync(temporary, file); }
57
+ catch (error) {
58
+ if (error.code !== 'EEXIST') throw error;
59
+ const stat = fs.lstatSync(file);
60
+ if (!stat.isFile() || stat.nlink !== 1 || stat.size > 16 * 1024
61
+ || hashJson(JSON.parse(fs.readFileSync(file, 'utf8'))) !== hashJson(proof)) fail('retained_request_changed');
62
+ }
63
+ } finally { fs.closeSync(fd); fs.unlinkSync(temporary); }
64
+ return { ...request, invocation_sha256: command };
65
+ }
@@ -0,0 +1,38 @@
1
+ // Async iteration backpressures the native pipe while its existing evidence
2
+ // sink drains. The input limit applies to requests, not owned replies.
3
+ export const MAX_NATIVE_LINE_BYTES = 8 * 1024 * 1024;
4
+ export async function readNativeLines(stream, onLine, onError) {
5
+ let buffer = "";
6
+ stream.setEncoding("utf8");
7
+ try {
8
+ for await (const chunk of stream.iterator({ destroyOnReturn: false })) {
9
+ buffer += chunk;
10
+ let at;
11
+ while ((at = buffer.indexOf("\n")) >= 0) {
12
+ const line = buffer.slice(0, at); buffer = buffer.slice(at + 1);
13
+ if (line.trim()) await onLine(line);
14
+ }
15
+ }
16
+ if (buffer.trim()) await onLine(buffer);
17
+ } catch (cause) { stream.pause(); await observationFailure(cause, onError); }
18
+ }
19
+ export function assertNativeLine(line, phase = "reply") {
20
+ if (phase === "request" && Buffer.byteLength(line) > MAX_NATIVE_LINE_BYTES) throw Object.assign(new Error("Native JSON request exceeds the bounded input limit"), { code: "native_request_limit", details: { reason: "native_request_limit", limit_bytes: MAX_NATIVE_LINE_BYTES, effect: "no_effect" } });
21
+ }
22
+ export function admitNativeRequestBuffer(buffer, socket, schema) {
23
+ try { assertNativeLine(buffer, "request"); return true; }
24
+ catch (error) { socket.pause(); socket.end(`${JSON.stringify({ schema_id: schema, id: null, ok: false, error: { code: error.code, message: error.message, details: error.details } })}\n`, () => socket.destroy()); return false; }
25
+ }
26
+ export async function streamNativeDiagnostics(stream, onChunk, onError) {
27
+ stream.setEncoding("utf8");
28
+ try { for await (const chunk of stream.iterator({ destroyOnReturn: false })) await onChunk(String(chunk)); }
29
+ catch (cause) { stream.pause(); await observationFailure(cause, onError); }
30
+ }
31
+ async function observationFailure(cause, onError) {
32
+ const error = nativeObservationError(cause);
33
+ try { await onError(error); }
34
+ catch (publication) { error.cleanup_error ??= { code: publication.code ?? null, message: publication.message }; }
35
+ }
36
+ export function nativeObservationError(cause, details = {}) {
37
+ return !cause.code || /^[A-Z_]+$/.test(cause.code) ? Object.assign(new Error("Native evidence reader failed", { cause }), { code: "operation_observation_lost", details: { native_outcome: "unknown", observation_error: { code: cause.code ?? null, message: cause.message }, ...details } }) : cause;
38
+ }
@@ -0,0 +1,18 @@
1
+ export const OBSERVATION_CLOCK_CONTRACT_VERSION: "operation-progress@1";
2
+ export function validateObservationDuration(value: number, label?: string): number;
3
+ export interface ObservationState {
4
+ policy: string; timeout_ms: number; started_at: number; cursor?: unknown;
5
+ observed_at: number | null; elapsed_ms: number; uncertainty_elapsed_ms: number;
6
+ gaps: number; uncertain?: boolean; observation_lost: boolean;
7
+ }
8
+ export class ObservationClock {
9
+ constructor(options: { timeoutMs: number; gapMs?: number; uncertaintyMs?: number;
10
+ wall?: () => number; monotonic?: () => number; onGap?: (value: Record<string, unknown>) => void;
11
+ saved?: ObservationState | null; snapshotIsLive?: boolean });
12
+ observationLost: boolean;
13
+ sample(progress?: unknown, progressAt?: number): boolean;
14
+ state(): ObservationState;
15
+ }
16
+ export function observedTimeout(callback: (clock: ObservationClock) => void, timeoutMs: number,
17
+ options?: { gapMs?: number; uncertaintyMs?: number; wall?: () => number; monotonic?: () => number;
18
+ onGap?: (value: Record<string, unknown>) => void; progress?: () => unknown; saved?: ObservationState | null }): ReturnType<typeof setInterval>;
@@ -0,0 +1,95 @@
1
+ export const OBSERVATION_CLOCK_CONTRACT_VERSION = "operation-progress@1";
2
+ export function validateObservationDuration(value, label = "observation duration") {
3
+ if (!Number.isSafeInteger(value) || value < 1 || value > 2_147_483_647)
4
+ throw new RangeError(`${label} must be integer milliseconds in 1..2147483647`);
5
+ return value;
6
+ }
7
+
8
+ /** Only observed monotonic time is silence. A clock gap is uncertainty, never
9
+ * progress or proof of provider failure. Durable snapshots retain that episode. */
10
+ export class ObservationClock {
11
+ constructor({ timeoutMs, gapMs = 60_000, uncertaintyMs = 120_000, wall = Date.now,
12
+ monotonic = () => performance.now(), onGap = () => {}, saved = null, snapshotIsLive = false }) {
13
+ validateObservationDuration(timeoutMs); validateObservationDuration(gapMs, "gap duration");
14
+ validateObservationDuration(uncertaintyMs, "observation recovery duration");
15
+ Object.assign(this, { timeoutMs, gapMs, uncertaintyMs, wall, monotonic, onGap });
16
+ this.lastWall = wall(); this.lastMono = monotonic(); this.startedWall = this.lastWall;
17
+ this.elapsed = 0; this.progress = undefined; this.progressAt = null;
18
+ this.uncertain = false; this.uncertaintyElapsed = 0; this.gaps = 0; this.observationLost = false;
19
+ if (saved) {
20
+ if (saved.policy !== OBSERVATION_CLOCK_CONTRACT_VERSION || saved.timeout_ms !== timeoutMs
21
+ || !Number.isFinite(saved.started_at) || !Number.isSafeInteger(saved.gaps) || saved.gaps < 0
22
+ || saved.observed_at !== null && !Number.isFinite(saved.observed_at)
23
+ || typeof saved.observation_lost !== "boolean"
24
+ || saved.uncertain !== undefined && typeof saved.uncertain !== "boolean"
25
+ || !Number.isFinite(saved.elapsed_ms) || saved.elapsed_ms < 0
26
+ || !Number.isFinite(saved.uncertainty_elapsed_ms) || saved.uncertainty_elapsed_ms < 0)
27
+ throw new RangeError("invalid retained observation clock");
28
+ this.startedWall = saved.started_at; this.elapsed = saved.elapsed_ms;
29
+ this.progress = saved.cursor; this.progressAt = saved.observed_at;
30
+ // Durable reconstruction has an observation gap. Transferring a freshly
31
+ // observed producer clock is not a second restart of that same producer.
32
+ this.uncertain = snapshotIsLive ? saved.uncertain ?? true : true;
33
+ this.gaps = saved.gaps + (snapshotIsLive ? 0 : 1);
34
+ this.uncertaintyElapsed = saved.uncertainty_elapsed_ms;
35
+ this.observationLost = saved.observation_lost || this.gaps > 1 || this.uncertaintyElapsed >= uncertaintyMs;
36
+ }
37
+ }
38
+ sample(progress, progressAt) {
39
+ if (progress && typeof progress === "object" && Object.hasOwn(progress, "cursor")) {
40
+ progressAt = progress.observed_at; progress = progress.cursor;
41
+ }
42
+ const wall = this.wall(), mono = this.monotonic();
43
+ const delta = mono - this.lastMono, wallDelta = wall - this.lastWall;
44
+ const gap = !Number.isFinite(delta) || !Number.isFinite(wallDelta)
45
+ || delta > this.gapMs || wallDelta > this.gapMs || delta < 0 || wallDelta < 0;
46
+ if (gap) {
47
+ this.uncertain = true; this.gaps++;
48
+ this.onGap({ source: "observer_clock", classification: "observation_gap", confirmed_sleep: false,
49
+ started_at: Number.isFinite(this.lastWall) ? this.lastWall : null, observed_at: Number.isFinite(wall) ? wall : null,
50
+ wall_delta_ms: wallDelta, monotonic_delta_ms: delta });
51
+ } else {
52
+ this.elapsed += delta;
53
+ if (this.uncertain) this.uncertaintyElapsed += delta;
54
+ }
55
+ this.lastWall = wall; this.lastMono = mono;
56
+ const validCursor = typeof progress === "string" || typeof progress === "boolean"
57
+ || typeof progress === "number" && Number.isFinite(progress);
58
+ const changed = validCursor && progress !== this.progress;
59
+ const timestamped = progressAt !== undefined;
60
+ const validTime = !timestamped ? wall >= this.startedWall && (this.progressAt === null || wall >= this.progressAt)
61
+ : Number.isFinite(progressAt) && progressAt >= this.startedWall
62
+ && progressAt <= wall && (this.progressAt === null || progressAt >= this.progressAt);
63
+ if (changed && validTime && !this.observationLost) {
64
+ const eventAt = timestamped ? progressAt : wall;
65
+ // A delayed pre-gap event cannot establish that observation has recovered.
66
+ const recovers = !this.uncertain || eventAt >= wall - Math.max(0, gap ? 0 : delta);
67
+ this.progress = progress; this.progressAt = eventAt;
68
+ this.elapsed = Math.max(0, wall - eventAt);
69
+ if (recovers) { this.uncertain = false; this.gaps = 0; this.uncertaintyElapsed = 0; }
70
+ }
71
+ if (changed && timestamped && Number.isFinite(progressAt) && !validTime && progressAt > wall) {
72
+ if (!this.uncertain) this.onGap({ source: "observer_clock", classification: "clock_skew",
73
+ confirmed_sleep: false, observed_at: wall, signal_at: progressAt });
74
+ this.uncertain = true;
75
+ }
76
+ if (this.uncertain && (this.gaps > 1 || this.uncertaintyElapsed >= this.uncertaintyMs)) this.observationLost = true;
77
+ return this.observationLost || !this.uncertain && this.elapsed >= this.timeoutMs;
78
+ }
79
+ state() {
80
+ return { policy: OBSERVATION_CLOCK_CONTRACT_VERSION, timeout_ms: this.timeoutMs,
81
+ started_at: this.startedWall, cursor: this.progress, observed_at: this.progressAt,
82
+ elapsed_ms: this.elapsed, uncertainty_elapsed_ms: this.uncertaintyElapsed,
83
+ gaps: this.gaps, uncertain: this.uncertain, observation_lost: this.observationLost };
84
+ }
85
+ }
86
+
87
+ /** Node timer handle, compatible with existing clearTimeout cleanup. */
88
+ export function observedTimeout(callback, timeoutMs, options = {}) {
89
+ const clock = new ObservationClock({ timeoutMs, ...options });
90
+ const timer = setInterval(() => {
91
+ const snapshot = options.progress?.();
92
+ if (clock.sample(snapshot)) { clearInterval(timer); callback(clock); }
93
+ }, Math.max(1, Math.min(1_000, timeoutMs / 4)));
94
+ return timer;
95
+ }