@deksden-com/dd-flow-cli 0.9.0-beta.15 → 0.9.0-beta.150

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 (557) hide show
  1. package/CHANGELOG.md +895 -0
  2. package/README.md +140 -6
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +386 -0
  6. package/dist/cli/command-metadata.js +232 -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/diagnostic-invocation.js +46 -0
  11. package/dist/cli/diagnostic.js +120 -0
  12. package/dist/cli/error-output.js +52 -0
  13. package/dist/cli/executor-onboarding.js +76 -0
  14. package/dist/cli/flows.js +29 -0
  15. package/dist/cli/harnesses.js +84 -0
  16. package/dist/cli/help.js +396 -19
  17. package/dist/cli/hook-ingress.js +102 -0
  18. package/dist/cli/input-preparation.js +165 -0
  19. package/dist/cli/memory-flow-admission.js +50 -0
  20. package/dist/cli/memory-init-invocation.js +85 -0
  21. package/dist/cli/memory-init.js +249 -0
  22. package/dist/cli/memory-storage-admission.js +54 -0
  23. package/dist/cli/memory-storage-qualification.js +105 -0
  24. package/dist/cli/memory-storage-transition.js +123 -0
  25. package/dist/cli/memory-upgrade.js +189 -0
  26. package/dist/cli/models.js +39 -0
  27. package/dist/cli/native-hook-ingress.js +90 -0
  28. package/dist/cli/native-hook-preparation.js +55 -0
  29. package/dist/cli/operator-profiles.js +61 -0
  30. package/dist/cli/output-options.js +35 -0
  31. package/dist/cli/response-file.js +72 -0
  32. package/dist/cli/run-cli.js +1734 -550
  33. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  34. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  35. package/dist/cli/runtime-process.js +153 -0
  36. package/dist/cli/setup.js +150 -0
  37. package/dist/cli.js +89 -2
  38. package/dist/domain/diagnostic-aspects.js +103 -0
  39. package/dist/domain/diagnostic-flows.js +8 -0
  40. package/dist/domain/stage-catalog.js +1 -1
  41. package/dist/domain/stage-handler-identities.js +28 -0
  42. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  43. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  44. package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
  45. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  46. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  47. package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
  48. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  49. package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
  50. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  51. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  52. package/dist/harness-runtime/lib/agy-error-boundary.mjs +58 -0
  53. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  54. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  55. package/dist/harness-runtime/lib/agy-native-inspection.mjs +216 -0
  56. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  57. package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
  58. package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
  59. package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
  60. package/dist/harness-runtime/lib/daemon-operations.mjs +462 -0
  61. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
  62. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1096 -0
  63. package/dist/harness-runtime/lib/dd-agy.mjs +86 -0
  64. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  65. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +231 -0
  66. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  67. package/dist/harness-runtime/lib/dd-codex.mjs +954 -0
  68. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +141 -0
  69. package/dist/harness-runtime/lib/dd-droid.mjs +626 -0
  70. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +555 -0
  71. package/dist/harness-runtime/lib/dd-grok.mjs +180 -0
  72. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +622 -0
  73. package/dist/harness-runtime/lib/dd-opencode.mjs +390 -0
  74. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +752 -0
  75. package/dist/harness-runtime/lib/dd-zcode.mjs +1175 -0
  76. package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
  77. package/dist/harness-runtime/lib/delegation-instructions.mjs +157 -0
  78. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  79. package/dist/harness-runtime/lib/driver-recovery.mjs +140 -0
  80. package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
  81. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  82. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  83. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  84. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  85. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  86. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  87. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
  88. package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
  89. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  90. package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
  91. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  92. package/dist/harness-runtime/lib/model-observations.mjs +101 -0
  93. package/dist/harness-runtime/lib/native-children.d.mts +23 -0
  94. package/dist/harness-runtime/lib/native-children.mjs +219 -0
  95. package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
  96. package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
  97. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  98. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  99. package/dist/harness-runtime/lib/native-streams.mjs +45 -0
  100. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  101. package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
  102. package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
  103. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  104. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  105. package/dist/harness-runtime/lib/operation-errors.mjs +127 -0
  106. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  107. package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
  108. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  109. package/dist/harness-runtime/lib/process-json.mjs +201 -0
  110. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  111. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +15 -0
  112. package/dist/harness-runtime/lib/provider-overload-policy.mjs +151 -0
  113. package/dist/harness-runtime/lib/runner-events.mjs +202 -0
  114. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  115. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  116. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  117. package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
  118. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  119. package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
  120. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  121. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  122. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  123. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  124. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  125. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  126. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  127. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  128. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  129. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  130. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  131. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  132. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  133. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  134. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  135. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  136. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  137. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  138. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  139. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  140. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  141. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  142. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  143. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  144. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  145. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  146. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  147. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  148. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  149. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  150. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  151. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  152. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  153. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  154. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  155. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  156. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  157. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  158. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  159. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  160. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  161. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  162. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  163. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  164. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  165. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  166. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  167. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  168. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  169. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  170. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  171. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  172. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  173. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  174. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  175. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  176. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  177. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  178. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  179. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  180. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  181. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  182. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  183. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  184. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  185. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  186. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  187. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  188. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  189. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  190. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  191. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  192. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  193. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  194. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  195. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  196. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  197. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  198. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  199. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  200. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  201. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  202. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  203. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  204. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  205. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  206. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  207. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  208. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  209. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  210. package/dist/protocol/local-files.js +18 -9
  211. package/dist/runtime/context.js +8 -4
  212. package/dist/schemas/agent-profile.schema.json +1 -1
  213. package/dist/schemas/code-review-decision.schema.json +9 -0
  214. package/dist/schemas/code-review-result.schema.json +1 -1
  215. package/dist/schemas/code-verification.schema.json +7 -5
  216. package/dist/schemas/code-work-batch.schema.json +2 -2
  217. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  218. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  219. package/dist/schemas/discovery-result.schema.json +184 -0
  220. package/dist/schemas/execution-bundle.schema.json +211 -0
  221. package/dist/schemas/execution-settings.schema.json +162 -0
  222. package/dist/schemas/flow-descriptor.schema.json +54 -0
  223. package/dist/schemas/flow-run.schema.json +29 -0
  224. package/dist/schemas/harness-catalog.schema.json +80 -0
  225. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  226. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  227. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  228. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  229. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  230. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  231. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  232. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  233. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  234. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  235. package/dist/schemas/memory-repair-work-result.schema.json +56 -0
  236. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  237. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  238. package/dist/schemas/model-catalog.schema.json +153 -0
  239. package/dist/schemas/plan-review-decision.schema.json +12 -3
  240. package/dist/schemas/plan-review-result.schema.json +2 -2
  241. package/dist/schemas/profile-settings.schema.json +122 -0
  242. package/dist/schemas/project-flow-pack-manifest.schema.json +1 -1
  243. package/dist/schemas/release-impact.schema.json +3 -3
  244. package/dist/schemas/release-manifest.schema.json +291 -0
  245. package/dist/schemas/run-control-receipt.schema.json +118 -0
  246. package/dist/schemas/run-control-request.schema.json +36 -0
  247. package/dist/schemas/run-engine-binding.schema.json +1 -1
  248. package/dist/schemas/stage-start-response.schema.json +4 -0
  249. package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
  250. package/dist/services/accepted-intent.js +139 -0
  251. package/dist/services/branch-context.js +3 -3
  252. package/dist/services/canon.js +54 -15
  253. package/dist/services/check-environment.js +21 -0
  254. package/dist/services/check-runner-evidence.js +562 -0
  255. package/dist/services/cleanup.js +133 -40
  256. package/dist/services/cli-operation-classifier.js +26 -63
  257. package/dist/services/cli-upgrade-allowlist.js +27 -0
  258. package/dist/services/code-checks.js +1398 -119
  259. package/dist/services/codex-hook-delivery.js +32 -0
  260. package/dist/services/command-context.js +80 -0
  261. package/dist/services/compatibility-preflight.js +16 -3
  262. package/dist/services/config.js +11 -8
  263. package/dist/services/continuation-outcome.js +20 -0
  264. package/dist/services/controller-child-capacity.js +13 -0
  265. package/dist/services/controller-child-observer.js +115 -0
  266. package/dist/services/controller-execution.js +94 -0
  267. package/dist/services/controller-fanout.js +226 -0
  268. package/dist/services/controller-memory-task.js +45 -0
  269. package/dist/services/controller-memory-worker.js +49 -0
  270. package/dist/services/dashboard.js +143 -58
  271. package/dist/services/descriptor-coordinator-session.js +35 -0
  272. package/dist/services/descriptor-root-work.js +53 -0
  273. package/dist/services/descriptor-run-settlement.js +107 -0
  274. package/dist/services/descriptor-run-start.js +475 -0
  275. package/dist/services/descriptor-stage-coordinator.js +250 -0
  276. package/dist/services/descriptor-stage-settlement.js +223 -0
  277. package/dist/services/descriptor-stage-start.js +175 -0
  278. package/dist/services/diagnostic-evidence.js +73 -0
  279. package/dist/services/diagnostic-report-publication.js +72 -0
  280. package/dist/services/diagnostic-report.js +67 -0
  281. package/dist/services/diagnostic-run-bundle.js +74 -0
  282. package/dist/services/diagnostic-snapshot.js +159 -0
  283. package/dist/services/diagnostic-stage-handlers.js +108 -0
  284. package/dist/services/diagnostic-stage-results.js +132 -0
  285. package/dist/services/diagnostic-start.js +84 -0
  286. package/dist/services/diagnostic-work-batch.js +34 -0
  287. package/dist/services/diagnostic-work-collection.js +97 -0
  288. package/dist/services/diagnostic-work-registration.js +101 -0
  289. package/dist/services/diagnostic-work-results.js +93 -0
  290. package/dist/services/discovery/agy-discovery.js +2 -0
  291. package/dist/services/discovery/codex-discovery.js +2 -0
  292. package/dist/services/discovery/droid-discovery.js +2 -0
  293. package/dist/services/discovery/grok-discovery.js +2 -0
  294. package/dist/services/discovery/opencode-discovery.js +2 -0
  295. package/dist/services/discovery/static.js +31 -0
  296. package/dist/services/discovery/zcode-discovery.js +2 -0
  297. package/dist/services/engines.js +354 -163
  298. package/dist/services/eval-snapshots.js +1316 -150
  299. package/dist/services/execution-bundles.js +275 -0
  300. package/dist/services/execution-policy.js +185 -0
  301. package/dist/services/executor-onboarding.js +56 -0
  302. package/dist/services/external-work-launch.js +310 -0
  303. package/dist/services/flow-catalog.js +30 -0
  304. package/dist/services/flow-descriptors.js +82 -0
  305. package/dist/services/frozen-engine.js +387 -0
  306. package/dist/services/generic-execution.js +164 -0
  307. package/dist/services/harness-adapter.js +355 -36
  308. package/dist/services/harness-config.js +2 -0
  309. package/dist/services/harness-discovery.js +29 -0
  310. package/dist/services/harness-doctor.js +75 -0
  311. package/dist/services/harness-probe-effects.js +51 -0
  312. package/dist/services/harness-version-probe.js +100 -0
  313. package/dist/services/hook-memory-routing.js +188 -0
  314. package/dist/services/hook-recovery-guard.js +14 -0
  315. package/dist/services/hook-session-observation.js +24 -0
  316. package/dist/services/hooks.js +791 -326
  317. package/dist/services/hybrid-contracts.js +474 -0
  318. package/dist/services/hybrid-digest.js +14 -0
  319. package/dist/services/ids.js +29 -1
  320. package/dist/services/installation-lock.js +95 -0
  321. package/dist/services/installed-flow-source.js +226 -0
  322. package/dist/services/lanes.js +78 -65
  323. package/dist/services/lifecycle-command.js +1 -288
  324. package/dist/services/lifecycle-contract.js +1 -0
  325. package/dist/services/lifecycle-invocations.js +2148 -0
  326. package/dist/services/managed-daemon-binding.js +38 -0
  327. package/dist/services/managed-lease-monitor.js +133 -0
  328. package/dist/services/managed-processes.js +449 -69
  329. package/dist/services/memory-accepted-composition.js +78 -0
  330. package/dist/services/memory-baseline-preservation.js +65 -0
  331. package/dist/services/memory-completed-correction-wave.js +328 -0
  332. package/dist/services/memory-compose-handler.js +400 -0
  333. package/dist/services/memory-composition-acceptance.js +375 -0
  334. package/dist/services/memory-composition-graph.js +165 -0
  335. package/dist/services/memory-composition-registration.js +161 -0
  336. package/dist/services/memory-composition-work-custody.js +156 -0
  337. package/dist/services/memory-composition-work-results.js +108 -0
  338. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  339. package/dist/services/memory-corrected-review-batch.js +37 -0
  340. package/dist/services/memory-corrected-review-findings.js +108 -0
  341. package/dist/services/memory-corrected-review-inputs.js +215 -0
  342. package/dist/services/memory-corrected-review-projection.js +78 -0
  343. package/dist/services/memory-corrected-review-receipt.js +178 -0
  344. package/dist/services/memory-corrected-review-registration.js +192 -0
  345. package/dist/services/memory-correction-check-receipt.js +235 -0
  346. package/dist/services/memory-correction-input-owner.js +6 -0
  347. package/dist/services/memory-custody-snapshot.js +36 -0
  348. package/dist/services/memory-discover-handler.js +104 -0
  349. package/dist/services/memory-finish-evidence.js +457 -0
  350. package/dist/services/memory-finish-handler.js +229 -0
  351. package/dist/services/memory-finish-integration.js +450 -0
  352. package/dist/services/memory-finish-readiness.js +169 -0
  353. package/dist/services/memory-git-integration.js +220 -0
  354. package/dist/services/memory-historical-corrected-review.js +212 -0
  355. package/dist/services/memory-historical-original-review.js +143 -0
  356. package/dist/services/memory-historical-repair-registration.js +105 -0
  357. package/dist/services/memory-historical-second-review.js +147 -0
  358. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  359. package/dist/services/memory-init-contexts.js +131 -0
  360. package/dist/services/memory-init-controller-start.js +103 -0
  361. package/dist/services/memory-init-engine-release.js +223 -0
  362. package/dist/services/memory-init-git-policy.js +165 -0
  363. package/dist/services/memory-init-lint-capability.js +203 -0
  364. package/dist/services/memory-init-native-capacity.js +309 -0
  365. package/dist/services/memory-init-preflight.js +334 -0
  366. package/dist/services/memory-init-project-bootstrap.js +599 -0
  367. package/dist/services/memory-init-request-candidate.js +213 -0
  368. package/dist/services/memory-init-request-input.js +82 -0
  369. package/dist/services/memory-init-resource-storage.js +125 -0
  370. package/dist/services/memory-init-run-allocation.js +81 -0
  371. package/dist/services/memory-init-run-bundle.js +135 -0
  372. package/dist/services/memory-init-start.js +181 -0
  373. package/dist/services/memory-init-startup-custody.js +80 -0
  374. package/dist/services/memory-init-startup-input.js +240 -0
  375. package/dist/services/memory-init-storage.js +91 -0
  376. package/dist/services/memory-init-stores.js +359 -0
  377. package/dist/services/memory-init-worktrunk-capability.js +174 -0
  378. package/dist/services/memory-layer-publication.js +611 -0
  379. package/dist/services/memory-layer.js +221 -0
  380. package/dist/services/memory-lint-config.js +194 -0
  381. package/dist/services/memory-native-review-copy.js +103 -0
  382. package/dist/services/memory-normal-flow-entry.js +87 -0
  383. package/dist/services/memory-ordinary-defaults.js +129 -0
  384. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  385. package/dist/services/memory-preflight-handler.js +274 -0
  386. package/dist/services/memory-repair-current-view.js +299 -0
  387. package/dist/services/memory-repair-document-delta.js +488 -0
  388. package/dist/services/memory-repair-history.js +496 -0
  389. package/dist/services/memory-repair-physical-binding.js +194 -0
  390. package/dist/services/memory-repair-publication-files.js +152 -0
  391. package/dist/services/memory-repair-publication-intent.js +27 -0
  392. package/dist/services/memory-repair-publication-plan.js +162 -0
  393. package/dist/services/memory-repair-publication-source.js +225 -0
  394. package/dist/services/memory-repair-publication.js +795 -0
  395. package/dist/services/memory-repair-registration.js +240 -0
  396. package/dist/services/memory-repair-work-baseline.js +415 -0
  397. package/dist/services/memory-repair-work-completion.js +117 -0
  398. package/dist/services/memory-repair-work-custody.js +73 -0
  399. package/dist/services/memory-repair-work-results.js +108 -0
  400. package/dist/services/memory-repair-workspace.js +261 -0
  401. package/dist/services/memory-repair-writer-copy.js +736 -0
  402. package/dist/services/memory-result-binding.js +239 -0
  403. package/dist/services/memory-retained-review-authority.js +138 -0
  404. package/dist/services/memory-retained-review-results.js +70 -0
  405. package/dist/services/memory-retained-second-baseline.js +102 -0
  406. package/dist/services/memory-retained-second-repairs.js +162 -0
  407. package/dist/services/memory-review-acceptance.js +214 -0
  408. package/dist/services/memory-review-correction-plan.js +206 -0
  409. package/dist/services/memory-review-handler.js +585 -0
  410. package/dist/services/memory-review-inputs.js +246 -0
  411. package/dist/services/memory-review-limits.js +10 -0
  412. package/dist/services/memory-review-receipt.js +180 -0
  413. package/dist/services/memory-review-registration.js +117 -0
  414. package/dist/services/memory-review-work-custody.js +126 -0
  415. package/dist/services/memory-review-work-input.js +91 -0
  416. package/dist/services/memory-review-work-results.js +95 -0
  417. package/dist/services/memory-second-corrected-review-inputs.js +167 -0
  418. package/dist/services/memory-second-correction-plan.js +77 -0
  419. package/dist/services/memory-second-repair-baseline.js +91 -0
  420. package/dist/services/memory-second-repair-launch.js +614 -0
  421. package/dist/services/memory-second-repair-registration.js +88 -0
  422. package/dist/services/memory-second-repair-source.js +187 -0
  423. package/dist/services/memory-second-review-acceptance.js +115 -0
  424. package/dist/services/memory-source-observations.js +117 -0
  425. package/dist/services/memory-stage-dispatch.js +65 -0
  426. package/dist/services/memory-stage-results.js +290 -0
  427. package/dist/services/memory-tool-probe.js +25 -0
  428. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  429. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  430. package/dist/services/memory-upgrade-evidence.js +100 -0
  431. package/dist/services/memory-upgrade-inventory.js +442 -0
  432. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  433. package/dist/services/memory-upgrade-publication.js +413 -0
  434. package/dist/services/memory-upgrade-selection.js +430 -0
  435. package/dist/services/memory-upgrade-start.js +60 -0
  436. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  437. package/dist/services/memory-verification-acceptance.js +156 -0
  438. package/dist/services/memory-verification-checks.js +317 -0
  439. package/dist/services/memory-verification-receipt.js +160 -0
  440. package/dist/services/memory-verify-handler.js +137 -0
  441. package/dist/services/memory-work-result-json.js +12 -0
  442. package/dist/services/memory-work-result-preparation.js +64 -0
  443. package/dist/services/merge-queue.js +228 -149
  444. package/dist/services/merge-server.js +163 -35
  445. package/dist/services/migrations.js +164 -114
  446. package/dist/services/model-catalog.js +109 -0
  447. package/dist/services/model-discovery.js +46 -0
  448. package/dist/services/native-daemon-history.js +50 -0
  449. package/dist/services/native-session-control.js +39 -0
  450. package/dist/services/operator-profiles.js +236 -0
  451. package/dist/services/physical-startup.js +45 -0
  452. package/dist/services/plan-runtime.js +26 -11
  453. package/dist/services/plans.js +28 -25
  454. package/dist/services/project-registry.js +97 -0
  455. package/dist/services/project-summary.js +1 -1
  456. package/dist/services/projects.js +17 -87
  457. package/dist/services/prompt-delivery.js +71 -0
  458. package/dist/services/prompts.js +28 -17
  459. package/dist/services/protocols.js +163 -87
  460. package/dist/services/provider-capacity.js +455 -0
  461. package/dist/services/recovery-observation-budget.js +121 -0
  462. package/dist/services/recovery-snapshot-database.js +588 -0
  463. package/dist/services/release-archive-producer.js +52 -0
  464. package/dist/services/release-archive.js +143 -0
  465. package/dist/services/release-cache.js +150 -0
  466. package/dist/services/release-compatibility.js +18 -0
  467. package/dist/services/release-download.js +67 -0
  468. package/dist/services/release-envelope.js +104 -0
  469. package/dist/services/release-manifest.js +45 -0
  470. package/dist/services/release-payload.js +114 -0
  471. package/dist/services/release-producer.js +63 -0
  472. package/dist/services/release-provenance.js +160 -0
  473. package/dist/services/release-registry.js +66 -0
  474. package/dist/services/release-source.js +194 -0
  475. package/dist/services/repair-intents.js +31 -0
  476. package/dist/services/repair-receipt.js +13 -0
  477. package/dist/services/review-copy.js +165 -0
  478. package/dist/services/review-deferral.js +23 -0
  479. package/dist/services/run-control-receipt.js +56 -0
  480. package/dist/services/run-control-worker.js +428 -0
  481. package/dist/services/run-control.js +1092 -0
  482. package/dist/services/run-controller-adapter.js +400 -0
  483. package/dist/services/run-controller-capture.js +186 -0
  484. package/dist/services/run-controller-process.js +205 -0
  485. package/dist/services/run-controller-recovery.js +295 -0
  486. package/dist/services/run-controller-state.js +97 -0
  487. package/dist/services/run-controller.js +1326 -0
  488. package/dist/services/run-engine-bindings.js +1 -1
  489. package/dist/services/run-fork.js +147 -0
  490. package/dist/services/run-health.js +149 -0
  491. package/dist/services/run-observations.js +152 -0
  492. package/dist/services/run-projection.js +22 -64
  493. package/dist/services/run-recovery-guard.js +107 -0
  494. package/dist/services/run-recovery-runtime.js +112 -0
  495. package/dist/services/run-recovery.js +456 -0
  496. package/dist/services/run-start-custody.js +189 -0
  497. package/dist/services/runs.js +1023 -246
  498. package/dist/services/runtime-budget.js +446 -0
  499. package/dist/services/runtime-command.js +43 -0
  500. package/dist/services/runtime-scope-capture.js +52 -0
  501. package/dist/services/runtime-scope-control.js +468 -0
  502. package/dist/services/runtime-scope-resume.js +605 -0
  503. package/dist/services/runtime-scope-stop.js +211 -0
  504. package/dist/services/runtime-scope-worker.js +314 -0
  505. package/dist/services/runtime-service.js +19 -14
  506. package/dist/services/schema-validation.js +10 -8
  507. package/dist/services/scope-writer-cleanup.js +27 -0
  508. package/dist/services/sessions.js +36 -91
  509. package/dist/services/setup.js +427 -0
  510. package/dist/services/stage-blocker.js +17 -7
  511. package/dist/services/stage-context.js +193 -19
  512. package/dist/services/stage-handlers.js +89 -0
  513. package/dist/services/stage-lifecycle.js +152 -116
  514. package/dist/services/stage-pause.js +202 -91
  515. package/dist/services/stage-report-renderer.js +234 -6
  516. package/dist/services/stage-work-graph.js +52 -0
  517. package/dist/services/tooling.js +41 -30
  518. package/dist/services/usage.js +49 -101
  519. package/dist/services/verification-matrix.js +393 -0
  520. package/dist/services/version-status.js +1 -1
  521. package/dist/services/vnext-code-review.js +235 -88
  522. package/dist/services/vnext-code.js +327 -226
  523. package/dist/services/vnext-contracts.js +10 -1
  524. package/dist/services/vnext-execution-profile.js +80 -5
  525. package/dist/services/vnext-fanout.js +355 -21
  526. package/dist/services/vnext-merge.js +332 -111
  527. package/dist/services/vnext-plan-review.js +287 -132
  528. package/dist/services/vnext-plan.js +228 -104
  529. package/dist/services/vnext-protocolize.js +533 -95
  530. package/dist/services/vnext-specify.js +123 -81
  531. package/dist/services/vnext-workspace-policy.js +7 -2
  532. package/dist/services/work-registry.js +1706 -200
  533. package/dist/services/workspace-bootstrap.js +53 -15
  534. package/dist/services/workspace-files.js +85 -0
  535. package/dist/services/worktrees.js +105 -48
  536. package/dist/shared/entity-references.js +1 -0
  537. package/dist/shared/errors.js +27 -0
  538. package/dist/storage/agent-output.js +26 -0
  539. package/dist/storage/data-preservation.js +65 -0
  540. package/dist/storage/database.js +930 -40
  541. package/dist/storage/foreign-key-transaction.js +39 -0
  542. package/dist/storage/immutable-input.js +45 -0
  543. package/dist/storage/import-guard.js +159 -0
  544. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  545. package/dist/storage/native-cleanup.js +52 -0
  546. package/dist/storage/paired-writer-migration.js +424 -0
  547. package/dist/storage/paths.js +17 -4
  548. package/dist/storage/projection-lock.js +73 -0
  549. package/dist/storage/work-references.js +23 -0
  550. package/dist/storage/writer-contract.js +96 -0
  551. package/dist/storage/writer-migration.js +346 -0
  552. package/dist/storage/writer-restore.js +217 -0
  553. package/package.json +50 -13
  554. package/tools/create-canon-release.mjs +33 -0
  555. package/tools/probe-codex-history.mjs +37 -0
  556. package/tools/produce-hybrid-release.mjs +41 -0
  557. package/tools/repair-paused-run-status.mjs +84 -0
@@ -0,0 +1,127 @@
1
+ // An observer losing its response does not establish that a provider Turn failed.
2
+ export const OPERATION_ERROR_CONTRACT_VERSION = "operation-errors@2";
3
+ export function redactDiagnostic(value) {
4
+ return value.replace(/\b(Bearer|Basic)\s+[^\s"']+/gi, "$1 <redacted>")
5
+ .replace(/(^|[^\w-])([\w-]+)(["']?\s*[=:]\s*["']?)([^\s"',;&}]+)/g,
6
+ (whole, prefix, key, separator) => /token|secret|password|api[_-]?key|authorization/i.test(key)
7
+ ? `${prefix}${key}${separator}<redacted>` : whole)
8
+ .replace(/(\b[A-Za-z][A-Za-z0-9+.-]{0,31}:\/\/)[^\s/:@]+:[^\s/@]+@/g, "$1<redacted>@");
9
+ }
10
+ export function diagnosticJson(value) {
11
+ return JSON.stringify(value, (key, item) => /token|secret|password|api[_-]?key|authorization/i.test(key)
12
+ ? "<redacted>" : typeof item === "string" ? redactDiagnostic(item) : item, 2);
13
+ }
14
+ // Only use after the native delivery/operation owner has been verified.
15
+ export function isProvenShellCorrection(error) {
16
+ const details = error?.details;
17
+ return error?.code === "lifecycle_shell_syntax_invalid" && details?.phase === "prepare"
18
+ && details.effect === "no_effect" && details.recoverable === true
19
+ && details.disposition === "pre_cli_shell_refusal" && details.cli_admission_barrier === true
20
+ && typeof details.issued_invocation_id === "string" && details.issued_invocation_id.trim().length > 0
21
+ && typeof details.event_key === "string" && details.event_key.trim().length > 0;
22
+ }
23
+ export function isObservationLoss(error) {
24
+ return ["rpc_timeout", "native_timeout", "native_outcome_unknown", "native_backend_dead", "native_backend_pipe_broken", "bridge_exited", "bridge_pipe_broken", "daemon_timeout", "turn_timeout", "operation_observation_lost", "daemon_connection_closed", "harness_adapter_timeout", "harness_adapter_output_limit", "harness_adapter_invalid", "subject_liveness_timeout", "command_observation_lost", "command_output_limit", "operation_output_limit"].includes(error?.code);
25
+ }
26
+
27
+ function field(value, key) { try { return value?.[key]; } catch { return "[unreadable]"; } }
28
+ function text(value) { try { return String(value); } catch { return "[unreadable]"; } }
29
+ function boundedText(value, budget, limit = 16000) {
30
+ let result = value.slice(0, limit);
31
+ if (Buffer.byteLength(JSON.stringify(result)) > budget.remaining) result = result.slice(0, Math.max(0, Math.floor(budget.remaining / 6)));
32
+ budget.remaining -= Buffer.byteLength(JSON.stringify(result));
33
+ return result;
34
+ }
35
+ // Lifecycle controls are not optional diagnostics. Reserve them before bulk
36
+ // messages/details, including nested typed causes, without copying authority
37
+ // that was truncated into a different command or continuation receipt.
38
+ const operationalDetailKeys = ["phase", "effect", "recoverable", "retryable_no_effect", "handoff_required", "storage_retry", "repeated_without_progress", "cleanup_unconfirmed", "native_dispatch_started", "disposition", "cli_admission_barrier", "native_pre_cli_refusal", "issued_invocation_id", "invocation_id", "event_key", "refusal_event_key", "hook_event_id", "work_id", "hook_retry_signature", "rejection_signature", "retry_command", "repair_command", "continuation", "retry_instruction", "correction_instruction", "recovery_instruction", "authority_truncated"];
39
+ function operationalDetails(value, budget) {
40
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
41
+ const entries = [];
42
+ let authorityTruncated = false;
43
+ for (const key of operationalDetailKeys) {
44
+ try { if (!Object.hasOwn(value, key)) continue; } catch { continue; }
45
+ const raw = field(value, key), reserved = { ...budget };
46
+ const name = boundedText(key, reserved), result = jsonDiagnostic(raw, 0, new Set(), reserved);
47
+ if (name !== key || typeof raw === "string" && result !== raw
48
+ || key === "continuation" && JSON.stringify(result).includes("[truncated]")) {
49
+ authorityTruncated ||= ["retry_command", "repair_command", "continuation"].includes(key);
50
+ continue;
51
+ }
52
+ Object.assign(budget, reserved);
53
+ entries.push([key, result]);
54
+ }
55
+ return { ...Object.fromEntries(entries), ...(authorityTruncated ? { recoverable: false, authority_truncated: true } : {}) };
56
+ }
57
+ function jsonDiagnostic(value, depth, seen, budget, excludedKeys = []) {
58
+ if (depth >= 12 || budget.remaining <= 0 || budget.nodes-- <= 0) return "[truncated]";
59
+ if (typeof value === "string") { const result = boundedText(value, budget); return result.length === value.length ? result : `${result}[truncated]`; }
60
+ if (value === null || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) { budget.remaining -= String(value).length + 1; return value; }
61
+ if (typeof value !== "object") return "[unavailable]";
62
+ if (seen.has(value)) return "[circular]";
63
+ seen.add(value); budget.remaining -= 2;
64
+ let result;
65
+ try {
66
+ if (Array.isArray(value)) {
67
+ result = [];
68
+ for (let i = 0; i < Math.min(value.length, 256); i++) {
69
+ if (budget.remaining <= 0 || budget.nodes <= 0) { result.push("[truncated]"); break; }
70
+ result.push(jsonDiagnostic(field(value, i), depth + 1, seen, budget));
71
+ }
72
+ if (value.length > 256) result.push("[truncated]");
73
+ } else {
74
+ const entries = [];
75
+ // Error.message and the standard Error.cause are non-enumerable.
76
+ // Keep the original identity and shared bounds for nested diagnostics.
77
+ const errorFields = value instanceof Error ? ["message", "cause"].filter(key => field(value, key) !== undefined) : [];
78
+ for (const key of errorFields) {
79
+ if (budget.remaining <= 0 || budget.nodes <= 0) { entries.push(["[truncated]", true]); break; }
80
+ entries.push([boundedText(key, budget), jsonDiagnostic(field(value, key), depth + 1, seen, budget)]);
81
+ }
82
+ for (const key in value) {
83
+ if (!Object.hasOwn(value, key) || errorFields.includes(key) || excludedKeys.includes(key)) continue;
84
+ if (entries.length >= 256 || budget.remaining <= 0 || budget.nodes <= 0) { entries.push(["[truncated]", true]); break; }
85
+ const name = boundedText(key, budget);
86
+ entries.push([name, jsonDiagnostic(field(value, key), depth + 1, seen, budget)]);
87
+ }
88
+ result = Object.fromEntries(entries);
89
+ }
90
+ } catch { result = "[unreadable]"; }
91
+ seen.delete(value); return result;
92
+ }
93
+
94
+ function record(error, depth, seen, budget, pending) {
95
+ if (error && typeof error === "object") {
96
+ if (seen.has(error)) return { code: "diagnostic_cycle", message: "[circular]" };
97
+ seen.add(error);
98
+ }
99
+ const value = Object.fromEntries(["code", "message", "retryable", "exitCode", "details", "cause", "cleanup_error"].map(key => [key, field(error, key)]));
100
+ const result = {
101
+ code: boundedText(typeof value.code === "string" ? value.code : "operation_failed", budget),
102
+ ...(typeof value.retryable === "boolean" ? { retryable: value.retryable } : {}),
103
+ ...(typeof value.exitCode === "number" && Number.isFinite(value.exitCode) ? { exitCode: value.exitCode } : {}),
104
+ };
105
+ pending.push([result, typeof value.message === "string" ? value.message : text(error), value.details]);
106
+ if (value.cause && value.cause !== "[unreadable]" && depth < 3) result.cause = record(value.cause, depth + 1, new Set(seen), budget, pending);
107
+ if (value.cleanup_error && value.cleanup_error !== "[unreadable]" && depth < 3) result.cleanup_error = record(value.cleanup_error, depth + 1, new Set(seen), budget, pending);
108
+ return result;
109
+ }
110
+
111
+ export function errorRecord(error, depth = 0, seen = new Set()) {
112
+ const budget = { remaining: 65536, nodes: 2048 }, pending = [];
113
+ // Reserve every typed code before messages and optional bulk details.
114
+ const result = record(error, depth, seen, budget, pending);
115
+ const controls = pending.map(([, , value]) => operationalDetails(value, budget));
116
+ for (const [target, message] of pending) target.message = boundedText(message, budget);
117
+ for (const [index, [target, , value]] of pending.entries()) if (value !== undefined) {
118
+ const details = jsonDiagnostic(value, 0, new Set(), budget, controls[index] ? operationalDetailKeys : []);
119
+ target.details = controls[index] ? { ...controls[index], ...(details && typeof details === "object" ? details : { "[truncated]": true }) } : details;
120
+ }
121
+ return result;
122
+ }
123
+
124
+ export function reportedError(value, fallback) {
125
+ const record = errorRecord({ ...value, message: value.message ?? fallback });
126
+ return Object.assign(new Error(record.message), record);
127
+ }
@@ -0,0 +1,7 @@
1
+ export const OPERATION_PROGRESS_CONTRACT: "dd-flow/operation-progress@1";
2
+ export function operationDirectory(root: string, id: string): string;
3
+ export function withOperationProgress<T>(root: string, id: string, action: () => T): T;
4
+ export function readOperationRecord(root: string, id: string, name: string): Promise<Record<string, any> | null>;
5
+ export function readOperationProgress(root: string, id: string, expected?: Record<string, unknown>): Promise<(Record<string, unknown> & { sequence: number; observed_at: string }) | null>;
6
+ export function readOperationWaiting(root: string, id: string, expected?: Record<string, unknown>): Promise<boolean>;
7
+ export function suspendOperationClock(clock: import("./observation-clock.mjs").ObservationClock): void;
@@ -0,0 +1,114 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { createHash } from 'node:crypto';
3
+ import { open, readFile } from 'node:fs/promises';
4
+ import { constants } from 'node:fs';
5
+ import path from 'node:path';
6
+ import { writeJsonAtomic } from './runner-events.mjs';
7
+
8
+ export const OPERATION_PROGRESS_CONTRACT = 'dd-flow/operation-progress@1';
9
+ const context = new AsyncLocalStorage(), flights = new Map();
10
+ const fields = ['operation_id', 'daemon_id', 'operation', 'params_sha256', 'owner_id', 'generation'];
11
+ const phases = new Set(['accepted','ownership_confirmed','admission_confirmed','native_dispatched','native_progress','native_outcome_retained','settlement_started','settlement_completed','settlement_pending']);
12
+ export function operationDirectory(root,id) {
13
+ if (typeof root!=='string' || !path.isAbsolute(root) || typeof id!=='string' || !id || id.length>1_024) throw Object.assign(new Error('invalid operation observation binding'),{code:'operation_progress_invalid'});
14
+ return path.join(root, 'operations', createHash('sha256').update(id).digest('hex'));
15
+ }
16
+ export async function readOperationRecord(root, id, name) {
17
+ try {
18
+ const handle = await open(path.join(operationDirectory(root, id), name), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
19
+ try {
20
+ const stat = await handle.stat();
21
+ if (!stat.isFile() || name === 'progress.json' && stat.size > 16_384) throw Object.assign(new Error('invalid operation record file'), {code:'operation_progress_invalid'});
22
+ const bytes = name === 'progress.json'
23
+ ? await handle.read({buffer:Buffer.alloc(16_385),position:0}).then(({buffer,bytesRead})=>buffer.subarray(0,bytesRead))
24
+ : await handle.readFile();
25
+ if (name === 'progress.json' && bytes.length > 16_384) throw Object.assign(new Error('invalid operation record file'), {code:'operation_progress_invalid'});
26
+ try {
27
+ const value = JSON.parse(bytes.toString('utf8'));
28
+ if (name === 'progress.json' && (!value || typeof value !== 'object' || Array.isArray(value))) throw new Error('operation progress must be an object');
29
+ return value;
30
+ }
31
+ catch (cause) { if (name !== 'progress.json') throw cause; throw Object.assign(new Error('invalid operation progress JSON'), {code:'operation_progress_invalid',cause}); }
32
+ } finally { await handle.close(); }
33
+ } catch (error) { if (error.code === 'ENOENT') return null; throw error; }
34
+ }
35
+ export async function readOperationProgress(root, id, expected = {}) {
36
+ const requested = await readOperationRecord(root, id, 'requested.json');
37
+ const progress = await readOperationRecord(root, id, 'progress.json');
38
+ if (!progress) return null;
39
+ const invalid = () => Object.assign(new Error('operation progress binding is invalid'), { code: 'operation_progress_invalid', details: { operation_id: id } });
40
+ if (!requested || progress.schema_id !== OPERATION_PROGRESS_CONTRACT || progress.operation_id !== id
41
+ || typeof progress.operation!=='string' || !progress.operation || progress.operation.length>128
42
+ || !/^[a-f0-9]{64}$/.test(progress.params_sha256 ?? '')
43
+ || ['daemon_id','owner_id'].some(field=>progress[field]!==null && (typeof progress[field]!=='string' || !progress[field] || progress[field].length>1_024))
44
+ || progress.generation!==null && (!Number.isSafeInteger(progress.generation) || progress.generation<0)
45
+ || !Number.isSafeInteger(progress.sequence) || progress.sequence < 1 || !phases.has(progress.phase)
46
+ || !Number.isFinite(Date.parse(requested.requested_at))
47
+ || !Number.isFinite(Date.parse(progress.observed_at)) || Date.parse(progress.observed_at) > Date.now()
48
+ || Date.parse(progress.observed_at) < Date.parse(requested.requested_at)
49
+ || fields.some(field => (progress[field] ?? null) !== (requested[field] ?? null))) throw invalid();
50
+ assertExpectedBinding(requested, expected, id);
51
+ return progress;
52
+ }
53
+ function assertExpectedBinding(requested, expected, id) {
54
+ if (fields.some(field => Object.hasOwn(expected, field) && (expected[field] ?? null) !== (requested[field] ?? null))) {
55
+ throw Object.assign(new Error('retained operation differs from dispatched request'), {code:'operation_conflict',details:{operation_id:id}});
56
+ }
57
+ }
58
+ export function publishOperationProgress(root, id, phase, metadata = {}) {
59
+ if (!phases.has(phase)) return Promise.reject(Object.assign(new Error('unknown operation progress phase'), {code:'operation_progress_invalid'}));
60
+ const key = `${root}\0${id}`;
61
+ const next = (flights.get(key) ?? Promise.resolve()).catch(() => {}).then(async () => {
62
+ const requested = await readOperationRecord(root, id, 'requested.json');
63
+ if (!requested) return null;
64
+ const prior = await readOperationProgress(root, id);
65
+ const observedAt = metadata.observed_at ?? new Date().toISOString();
66
+ if (prior && Date.parse(observedAt)<Date.parse(prior.observed_at)) return prior;
67
+ // A later successful ownership gate is fresh liveness evidence while admission waits.
68
+ if (prior && phase === prior.phase && phase !== 'native_progress'
69
+ && (phase !== 'ownership_confirmed' || Date.parse(observedAt) <= Date.parse(prior.observed_at))) return prior;
70
+ if (prior && phase === 'native_progress' && Date.parse(observedAt) - Date.parse(prior.observed_at) < 1_000) return prior;
71
+ const value = { schema_id: OPERATION_PROGRESS_CONTRACT,
72
+ ...Object.fromEntries(fields.map(field => [field, requested[field] ?? null])),
73
+ sequence: (prior?.sequence ?? 0) + 1, phase, observed_at: observedAt,
74
+ ...Object.fromEntries(['native_request_id', 'session_id'].filter(field => typeof metadata[field] === 'string').map(field => [field, metadata[field].slice(0, 256)])) };
75
+ if (!Number.isFinite(Date.parse(observedAt)) || Date.parse(observedAt) > Date.now() || Date.parse(observedAt) < Date.parse(requested.requested_at)) throw Object.assign(new Error('invalid progress event timestamp'), { code: 'operation_progress_invalid' });
76
+ await writeJsonAtomic(path.join(operationDirectory(root, id), 'progress.json'), value);
77
+ return value;
78
+ });
79
+ flights.set(key, next);
80
+ void next.finally(() => { if (flights.get(key) === next) flights.delete(key); }).catch(() => {});
81
+ return next;
82
+ }
83
+ export const withOperationProgress = (root, id, action) => context.run({ root, id }, action);
84
+ export function operationProgressReporter() {
85
+ const binding = context.getStore();
86
+ return (phase, metadata) => binding ? publishOperationProgress(binding.root, binding.id, phase, metadata) : Promise.resolve(null);
87
+ }
88
+ export const noteOperationProgress = (phase, metadata) => operationProgressReporter()(phase, metadata);
89
+
90
+ /** Confirmed admission waiting is ownership evidence, not native activity. */
91
+ export async function publishOperationWaiting(root,id,receipt) {
92
+ const requested = await readOperationRecord(root,id,'requested.json');
93
+ if (!requested) return;
94
+ const prior = await readOperationRecord(root,id,'admission-wait.json');
95
+ if (prior?.state === (receipt.admitted ? 'admitted' : 'provider_capacity') && Date.now()-Date.parse(prior.observed_at)<1_000) return;
96
+ const value = { schema_id:'dd-flow/operation-waiting@1', ...Object.fromEntries(fields.map(field=>[field,requested[field] ?? null])), observed_at:new Date().toISOString(), lease_expires_at:receipt.lease_expires_at, process_id:receipt.process_id, state:receipt.admitted ? 'admitted' : 'provider_capacity' };
97
+ await writeJsonAtomic(path.join(operationDirectory(root,id),'admission-wait.json'),value);
98
+ }
99
+ export async function readOperationWaiting(root,id,expected={}) {
100
+ const requested = await readOperationRecord(root,id,'requested.json'), waiting = await readOperationRecord(root,id,'admission-wait.json');
101
+ if (!waiting || waiting.state!=='provider_capacity') return false;
102
+ if (!requested || waiting.schema_id!=='dd-flow/operation-waiting@1' || fields.some(field=>(waiting[field] ?? null)!==(requested[field] ?? null))) throw Object.assign(new Error('admission waiting binding differs'),{code:'operation_progress_invalid'});
103
+ assertExpectedBinding(requested, expected, id);
104
+ if (!Number.isFinite(Date.parse(waiting.observed_at)) || Date.parse(waiting.observed_at)>Date.now() || Date.parse(waiting.observed_at)<Date.parse(requested.requested_at) || typeof waiting.process_id!=='string' || !waiting.process_id) throw Object.assign(new Error('invalid admission observation'),{code:'operation_progress_invalid'});
105
+ if (Date.now()-Date.parse(waiting.observed_at)>30_000) return false;
106
+ if (!Number.isFinite(Date.parse(waiting.lease_expires_at)) || Date.parse(waiting.lease_expires_at)<=Date.now()) return false;
107
+ const daemon = JSON.parse(await readFile(path.join(root,'daemon.json'),'utf8'));
108
+ if ((daemon.daemon_id ?? daemon.config?.daemonId)!==waiting.daemon_id || daemon.config?.runtime_owner?.owner_id!==waiting.owner_id || ['stopping','clean','unclean','cleanup_failed','failed'].includes(daemon.shutdown_state)) return false;
109
+ if (waiting.process_id !== daemon.resource_process?.id) return false;
110
+ try { const fence = JSON.parse(await readFile(path.join(root,'operation-fence.json'),'utf8')); if (fence.daemon_id===waiting.daemon_id && fence.generation>waiting.generation) return false; } catch(error) { if(error.code!=='ENOENT') throw error; }
111
+ try { process.kill(daemon.pid,0); } catch { return false; }
112
+ return true;
113
+ }
114
+ export function suspendOperationClock(clock) { clock.lastWall = clock.wall(); clock.lastMono = clock.monotonic(); }
@@ -0,0 +1,5 @@
1
+ type Options = { cwd?: string; env?: NodeJS.ProcessEnv; input?: string | null; onProgress?: (value: unknown) => void; progress?: () => number; startupMs?: number | null; timeoutMs?: number | null; phase?: string; signal?: AbortSignal; onDiagnostic?: (data: string, stream: string) => void };
2
+ export function reportedFailure(stdout: string, stderr: string, fallback: string, fallbackCode?: string, retainedError?: Record<string, unknown> | null): Error & import('./operation-errors.mjs').ErrorRecord;
3
+ export function commandJson(bin: string, args: string[], options?: Options): Promise<Record<string, unknown>>;
4
+ export function commandText(bin: string, args: string[], options?: Options): Promise<string>;
5
+ export function commandResult(bin: string, args: string[], options?: Options): Promise<{exit_code: number | null; signal: string | null; stdout: string; stderr: string}>;
@@ -0,0 +1,201 @@
1
+ import { spawn } from "node:child_process";
2
+ import { errorRecord, reportedError } from "./operation-errors.mjs";
3
+ import { ObservationClock, validateObservationDuration } from "./observation-clock.mjs";
4
+ import { terminateCommandTree } from "./native-hook-command.mjs";
5
+ import { SETUP_STARTUP_MS, publishSetup, setupObserver, observationDetails, isSetupPhase } from './setup-progress.mjs';
6
+ let probeSequence = 0;
7
+
8
+ function failure(message, code) {
9
+ return Object.assign(new Error(message), { code });
10
+ }
11
+ const phaseDiagnostic = value => isSetupPhase(value) || ["native_hook_phase", "process_maintenance_phase"].includes(value?.kind);
12
+
13
+ export function reportedFailure(stdout, stderr, fallback, fallbackCode = "flow_reconciliation_failed", retainedError = null) {
14
+ for (const text of [stdout, stderr]) {
15
+ // Bounded CLI transport may prepend JSONL phase records to the usual
16
+ // pretty-printed error envelope. Remove only our diagnostics, not arbitrary
17
+ // text or a substring that might masquerade as an authoritative receipt.
18
+ const envelope = text.split(/\n/).filter(line => {
19
+ try { return !phaseDiagnostic(JSON.parse(line)); }
20
+ catch { return true; }
21
+ }).join("\n").trim();
22
+ for (const line of [text.trim(), envelope, ...text.trim().split(/\n/).reverse()]) {
23
+ try {
24
+ const value = JSON.parse(line);
25
+ if (phaseDiagnostic(value)) continue;
26
+ const error = value?.error;
27
+ if (typeof error?.code === "string" && error.code) return reportedError(error, fallback);
28
+ if (typeof value?.code === "string" && value.code) return reportedError({ ...value, message: typeof error === "string" ? error : value.message }, fallback);
29
+ } catch { /* Not a structured CLI error line. */ }
30
+ }
31
+ }
32
+ if (retainedError) return reportedError(retainedError, fallback);
33
+ return failure(stderr.trim() || stdout.trim() || fallback, fallbackCode);
34
+ }
35
+
36
+ function processTarget(executable, args) {
37
+ return /\.[cm]?js$/.test(executable) ? { command: process.execPath, args: [executable, ...args] } : { command: executable, args };
38
+ }
39
+
40
+ // These are utility/transport children, never a second productive-work owner.
41
+ async function command(bin, args, json, { cwd, env = {}, input = null, onProgress = null,
42
+ timeoutMs = 30_000, startupMs = null, phase = "utility", signal = null, onDiagnostic = null, result = false, progress = null } = {}) {
43
+ if (startupMs !== null) validateObservationDuration(startupMs);
44
+ if (timeoutMs !== null) validateObservationDuration(timeoutMs);
45
+ if (timeoutMs === null && phase !== "native-work") throw new RangeError("only native-work may omit the utility quiet timeout");
46
+ if (signal?.aborted) throw signal.reason ?? failure("command aborted", "command_aborted");
47
+ const setupProbe = ['native-version', 'native-doctor'].includes(phase);
48
+ const step = setupProbe ? `version-${++probeSequence}` : null;
49
+ if (setupProbe) publishSetup('probe_started', step);
50
+ const executable = bin === "dd-flow" && typeof env.DD_FLOW_BIN === "string" ? env.DD_FLOW_BIN : bin;
51
+ const target = processTarget(executable, json ? [...args, "--json"] : args);
52
+ return await new Promise((resolve, reject) => {
53
+ const child = spawn(target.command, target.args, { cwd, env: { ...process.env, ...env },
54
+ detached: process.platform !== "win32", stdio: [input === null ? "ignore" : "pipe", "pipe", "pipe"] });
55
+ const maxOutput = 8 * 1024 * 1024, maxTail = 64 * 1024, maxLine = 1024 * 1024;
56
+ let stdout = "", stderr = "", pendingStderr = "", settled = false, primary = null, cursor = 0, droppingStructured = false;
57
+ let outputBytes = 0, cleanupTimer = null, inputError = null, termination = null, retainedError = null, prettyError = "";
58
+ const phases = new Set();
59
+ const clock = timeoutMs === null ? null : new ObservationClock({ timeoutMs: startupMs ?? timeoutMs });
60
+ const observeSetup = setupObserver(env.DD_EVAL_OPERATION_ID ?? process.env.DD_EVAL_OPERATION_ID);
61
+ const productive = () => { cursor++; clock?.sample(cursor, Date.now()); };
62
+ const finish = (error, value) => {
63
+ if (settled) return; settled = true;
64
+ clearInterval(timer); clearTimeout(cleanupTimer); signal?.removeEventListener("abort", abort);
65
+ if (!error && setupProbe) publishSetup('probe_completed', step);
66
+ error ? reject(error) : resolve(value);
67
+ };
68
+ const stop = error => {
69
+ if (primary || settled) return;
70
+ primary = error;
71
+ termination = terminateCommandTree(child).catch(cause => { if (cause.code !== "ESRCH") primary.cleanup_error = cause; });
72
+ // A missing close after owned SIGKILL is cleanup uncertainty, not success.
73
+ cleanupTimer = setTimeout(() => {
74
+ primary.cleanup_error ??= failure("owned utility child did not close", "command_cleanup_unconfirmed");
75
+ finish(primary);
76
+ }, 5_000);
77
+ };
78
+ const abort = () => stop(signal.reason ?? failure("command aborted", "command_aborted"));
79
+ const deliverProgress = line => {
80
+ let value;
81
+ // Parse a bounded whole pretty envelope before its diagnostic bytes leave
82
+ // the tail. An oversized envelope cannot become plain-text keepalive.
83
+ if (prettyError === null) { if (line.trimEnd() === "}") prettyError = ""; return; }
84
+ const candidate = prettyError ? `${prettyError}\n${line}` : line;
85
+ if (prettyError && candidate.length > maxTail) { prettyError = null; return; }
86
+ try { value = JSON.parse(candidate); prettyError = ""; }
87
+ catch {
88
+ if (!prettyError && !line.trimStart().startsWith("{")) { productive(); return; }
89
+ prettyError = candidate.length > maxTail ? null : candidate; return;
90
+ }
91
+ const kind = value?.kind;
92
+ if (kind === 'setup_phase') {
93
+ if (observeSetup(value)) {
94
+ if (clock) clock.setupProgress = { phase: value.phase, sequence: value.sequence, step: value.step, operation_id: value.operation_id };
95
+ if (clock) clock.timeoutMs = ['ingress_entered', 'probe_started'].includes(value.phase) ? startupMs ?? timeoutMs : timeoutMs;
96
+ productive();
97
+ if (setupProbe || phase === 'engine-probe') publishSetup(value.phase, `${step ?? 'engine'}:${value.sequence}:${value.step ?? ''}`);
98
+ }
99
+ return;
100
+ }
101
+ const passive = ["heartbeat", "poll", "status", "elapsed", "wait", "waiting"].some(marker => [kind, value?.phase, value?.action].includes(marker));
102
+ if (!["native_hook_phase", "process_maintenance_phase"].includes(kind)) {
103
+ const error = typeof value?.error?.code === "string" && value.error.code ? value.error
104
+ : typeof value?.code === "string" && value.code ? { ...value, message: typeof value.error === "string" ? value.error : value.message } : null;
105
+ // Retain one bounded typed summary independently of the diagnostic tail.
106
+ // It is consulted only on failed exit, after authoritative stdout.
107
+ if (error) retainedError = errorRecord(error);
108
+ }
109
+ if (["native_hook_phase", "process_maintenance_phase"].includes(kind)) {
110
+ const marker = JSON.stringify([kind, value.phase, value.operation_id ?? value.process_id]);
111
+ if (typeof value.phase === "string" && !passive && !phases.has(marker)) { phases.add(marker); productive(); }
112
+ } else if (!passive) productive();
113
+ if (typeof onProgress !== "function" || primary) return;
114
+ try {
115
+ const returned = onProgress(value);
116
+ if (returned && typeof returned.then === "function") {
117
+ Promise.resolve(returned).catch(() => {});
118
+ throw failure("command onProgress must be synchronous", "progress_callback_async");
119
+ }
120
+ } catch (error) { stop(error); }
121
+ };
122
+ const diagnostic = (data, stream) => {
123
+ try {
124
+ const returned = onDiagnostic?.(data, stream);
125
+ if (returned && typeof returned.then === "function") {
126
+ Promise.resolve(returned).catch(() => {});
127
+ throw failure("command onDiagnostic must be synchronous", "progress_callback_async");
128
+ }
129
+ } catch (error) { stop(error); }
130
+ };
131
+ let observedProgress = 0;
132
+ const timer = clock ? setInterval(() => {
133
+ if (progress) {
134
+ try {
135
+ const next = progress();
136
+ if (!Number.isSafeInteger(next) || next < 0) throw new RangeError('progress must be a non-negative integer');
137
+ if (next > observedProgress) { observedProgress = next; productive(); }
138
+ } catch (error) { stop(error); return; }
139
+ }
140
+ if (clock.sample(cursor)) stop(Object.assign(failure("command observation became quiet", "command_observation_lost"),
141
+ { details: observationDetails(clock, phase, child.pid) }));
142
+ }, Math.max(1, Math.min(1_000, timeoutMs / 4))) : null;
143
+ clock?.sample(cursor);
144
+ signal?.addEventListener("abort", abort, { once: true });
145
+ child.stdout.setEncoding("utf8").on("data", data => {
146
+ productive();
147
+ diagnostic(data, "stdout"); outputBytes += Buffer.byteLength(data);
148
+ if (outputBytes > maxOutput) stop(failure("command final output exceeds 8 MiB", "command_output_limit"));
149
+ else stdout += data;
150
+ });
151
+ child.stderr.setEncoding("utf8").on("data", data => {
152
+ diagnostic(data, "stderr"); stderr = (stderr + data).slice(-maxTail);
153
+ if (droppingStructured) {
154
+ const end = data.indexOf("\n");
155
+ if (end < 0) return;
156
+ data = data.slice(end + 1); droppingStructured = false;
157
+ }
158
+ pendingStderr += data;
159
+ for (;;) {
160
+ const end = pendingStderr.indexOf("\n"); if (end < 0) break;
161
+ const line = pendingStderr.slice(0, end); pendingStderr = pendingStderr.slice(end + 1);
162
+ if (line.length <= maxLine) deliverProgress(line);
163
+ }
164
+ if (pendingStderr && prettyError === "" && !pendingStderr.trimStart().startsWith("{")) productive();
165
+ // Plain streaming diagnostics are not the final reply and cannot kill a
166
+ // productive operation merely because their cumulative size is large.
167
+ if (pendingStderr.length > maxLine) {
168
+ droppingStructured = prettyError !== "" || pendingStderr.trimStart().startsWith("{");
169
+ pendingStderr = droppingStructured ? "" : pendingStderr.slice(-maxTail);
170
+ }
171
+ });
172
+ child.once("error", error => { if (!child.pid) finish(primary ?? error); else stop(error); });
173
+ if (input !== null) {
174
+ child.stdin.on("error", error => { inputError = error; if (error.code !== "EPIPE") stop(error); });
175
+ child.stdin.end(input);
176
+ }
177
+ child.once("close", (status, signal) => {
178
+ if (pendingStderr) deliverProgress(pendingStderr);
179
+ if (primary) { void (termination ?? Promise.resolve()).then(() => finish(primary)); return; }
180
+ if (result) return finish(inputError, { exit_code: status, signal, stdout: stdout.trim(), stderr });
181
+ if (status !== 0) {
182
+ const error = reportedFailure(stdout, stderr, `${executable} exited ${status}`, json ? "flow_reconciliation_failed" : "command_failed", retainedError);
183
+ error.details = { reason: 'child_exit', exit_code: status, signal, phase, pid: child.pid, ...error.details };
184
+ return finish(error);
185
+ }
186
+ if (!json) return finish(inputError, stdout.trim());
187
+ try {
188
+ const value = JSON.parse(stdout.trim());
189
+ if (value?.ok === false) {
190
+ const error = value.error && typeof value.error === "object" ? value.error : value;
191
+ return finish(reportedError(error, `${bin} returned an error envelope`));
192
+ }
193
+ if (inputError) return finish(inputError);
194
+ finish(null, value);
195
+ } catch (error) { finish(failure(`${bin} returned invalid JSON: ${error.message}`, "flow_reconciliation_failed")); }
196
+ });
197
+ });
198
+ }
199
+ export async function commandJson(bin, args, options = {}) { return await command(bin, args, true, { startupMs: options.timeoutMs ?? SETUP_STARTUP_MS, ...options }); }
200
+ export async function commandText(bin, args, options = {}) { return await command(bin, args, false, { startupMs: options.timeoutMs ?? SETUP_STARTUP_MS, ...options }); }
201
+ export async function commandResult(bin, args, options = {}) { return await command(bin, args, false, { startupMs: options.timeoutMs ?? SETUP_STARTUP_MS, ...options, result: true }); }
@@ -0,0 +1,10 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const run = promisify(execFile);
4
+
5
+ /** Inspect OS descendants without using process names as ownership. A start-time
6
+ * identity prevents a later unrelated process with a recycled PID being killed. */
7
+ export async function processSnapshot() {
8
+ const { stdout } = await run("ps", ["-axo", "pid=,ppid=,pgid=,lstart=,stat="], { timeout: 5_000 });
9
+ return stdout.trim().split("\n").flatMap(line => { const parts = line.trim().split(/\s+/); return parts.length >= 9 ? [{ pid: Number(parts[0]), ppid: Number(parts[1]), pgid: Number(parts[2]), started: parts.slice(3, 8).join(" "), zombie: parts[8].startsWith("Z") }] : []; });
10
+ }
@@ -0,0 +1,15 @@
1
+ export const CAPACITY_POLICY: "provider-overload-episode@1";
2
+ export const MAX_OVERLOAD_RETRIES: 3;
3
+ export const MAX_RETRY_AFTER_MS: 30000;
4
+ export function classifyProviderError(native: unknown): string;
5
+ export function safeProviderError(native: unknown): Record<string, unknown>;
6
+ 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 };
7
+ export function streamRequestKey(proof: unknown): string | null;
8
+ export type CapacityRefusal = { policy: string; ordinal: number; session_id: string; turn_id: string; request_key?: string; request_proof?: RequestProof; first_observed_at: string; native_terminal_at?: string; native_terminal_basis?: string };
9
+ export function parseCapacityOperation(id: string): { root: string; ordinal: number };
10
+ 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> } };
11
+ export function terminalProviderOverload(error: unknown, sessionId?: string, turnId?: string): boolean;
12
+ export function nativeItemsSettled(items: unknown): boolean;
13
+ export function capacityBackoff(error: unknown, ordinal: number, now?: number, random?: () => number): number;
14
+ export function refusalObservation(error: unknown, ordinal: number, firstObservedAt: string): CapacityRefusal;
15
+ export function overloadExhausted(refusals: CapacityRefusal[], maxRetries?: number): null | { policy: string; reason: string; attempts: number; refusals: CapacityRefusal[] };