@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,216 @@
1
+ import * as grpc from '@grpc/grpc-js';
2
+ import { create, toBinary, fromBinary } from '@bufbuild/protobuf';
3
+ import { WaitForConversationFullyIdleRequestSchema, WaitForConversationFullyIdleResponseSchema, GetConversationMetadataRequestSchema, GetConversationMetadataResponseSchema, ForceStopCascadeTreeRequestSchema, ForceStopCascadeTreeResponseSchema, StreamAgentStateUpdatesRequestSchema, StreamAgentStateUpdatesResponseSchema } from './agy-native_pb.js';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { readFile, lstat, realpath, open } from 'node:fs/promises';
6
+ import { createReadStream, constants } from 'node:fs';
7
+ import { createHash } from 'node:crypto';
8
+ import { execFile } from 'node:child_process';
9
+ import { promisify } from 'node:util';
10
+ import { fileURLToPath } from 'node:url';
11
+ import path from 'node:path';
12
+ import { processSnapshot } from './process-snapshot.mjs';
13
+
14
+ export const AGY_NATIVE_INSPECTION_CONTRACT = 'agy-native-inspection@2';
15
+ export const AGY_NATIVE_LIVE_CASES = ['root_child_running', 'child_background_running', 'grandchild_running', 'completion_delivery', 'fully_idle', 'timer_delivery', 'daemon_excluded_from_required_execution', 'owned_daemon_retirement'];
16
+ export const AGY_NATIVE_SAFETY_CASES = ['executor_error', 'timeout', 'late_activity_cancel_restart'];
17
+ export const AGY_NATIVE_QUALIFICATION_CASES = [...AGY_NATIVE_LIVE_CASES, ...AGY_NATIVE_SAFETY_CASES];
18
+ export const AGY_NATIVE_EVIDENCE_CONTRACT = 'agy-native-inspection-evidence@2';
19
+ /** Operator-retained native observations, not a bag of manually asserted PASSes.
20
+ * This validates evidence structure/meaning, not its authenticity: the operator
21
+ * still owns capture and review, as with every local qualification receipt. */
22
+ export function validateAgyNativeEvidence(evidence, identity) {
23
+ const checks = Object.fromEntries(AGY_NATIVE_QUALIFICATION_CASES.map(name => [name, false]));
24
+ const failed = new Set();
25
+ const fencedChanges = new Set();
26
+ const liveServices = new Map(), retiredServices = [];
27
+ if (evidence?.schema_id !== AGY_NATIVE_EVIDENCE_CONTRACT || evidence.binary_sha256 !== identity.sha256 || evidence.client_contract_sha256 !== identity.client_contract_sha256 || !['self', 'empty_self'].includes(evidence.root_relation) || !Array.isArray(evidence.observations)) return { qualified: false, checks };
28
+ for (const item of evidence.observations) {
29
+ if (!item || !AGY_NATIVE_QUALIFICATION_CASES.includes(item.case)) continue;
30
+ if (AGY_NATIVE_LIVE_CASES.includes(item.case) && item.evidence_kind !== 'live' || AGY_NATIVE_SAFETY_CASES.includes(item.case) && !['live', 'deterministic'].includes(item.evidence_kind)) { failed.add(item.case); continue; }
31
+ if (item.source !== 'agy.native' || typeof item.session_id !== 'string' || !item.session_id || typeof item.locator !== 'string' || !item.locator || !Number.isFinite(Date.parse(item.observed_at))) { failed.add(item.case); continue; }
32
+ const before = item.before, after = item.after, wait = item.wait;
33
+ // Observation itself must not create a user/model turn; background model
34
+ // work may continue, hence the explicit inspection-attributed counters.
35
+ if (!before || !after || !['user_turns', 'model_requests'].every(key => Number.isSafeInteger(before[key]) && before[key] >= 0 && after[key] === before[key]) || !wait || !Number.isInteger(wait.grpc_code) || wait.grpc_code < 0 || wait.grpc_code > 16 || typeof item.idle_granted !== 'boolean') { failed.add(item.case); continue; }
36
+ const idle = wait.grpc_code === 0 && wait.timed_out === false;
37
+ const busy = wait.grpc_code === 4 || wait.grpc_code === 0 && wait.timed_out === true;
38
+ const noGrant = item.idle_granted === false;
39
+ const work = Array.isArray(item.work) ? item.work : [];
40
+ const has = (kind, status) => work.some(record => record?.kind === kind && record.status === status && typeof record.id === 'string' && record.id && record.root_session_id === item.session_id);
41
+ const prior = checks[item.case]; checks[item.case] = false;
42
+ if (item.case === 'root_child_running' && item.root_status === 'terminal' && has('child', 'running') && busy && noGrant) checks[item.case] = true;
43
+ if (item.case === 'child_background_running' && has('child', 'terminal') && has('background', 'running') && busy && noGrant) checks[item.case] = true;
44
+ if (item.case === 'grandchild_running' && item.root_status === 'terminal' && item.inventory_complete === true && has('child', 'terminal') && has('grandchild', 'running') && work.every(record => record?.kind === 'grandchild' || record?.status === 'terminal') && busy && noGrant) checks[item.case] = true;
45
+ if (item.case === 'completion_delivery' && has('completion', 'pending') && busy && noGrant) checks[item.case] = true;
46
+ if (item.case === 'timer_delivery' && has('timer', 'terminal') && has('completion', 'terminal') && item.inventory_complete === true && work.every(record => record?.status === 'terminal' && record.root_session_id === item.session_id) && item.root_status === 'terminal' && idle && item.idle_granted === true) checks[item.case] = true;
47
+ if (item.case === 'fully_idle' && item.root_status === 'terminal' && item.inventory_complete === true && work.every(record => record?.status === 'terminal' && typeof record.id === 'string' && record.id && record.root_session_id === item.session_id) && idle && item.idle_granted === true) checks[item.case] = true;
48
+ if (item.case === 'executor_error' && typeof item.executor_error === 'string' && item.executor_error && noGrant && (busy || wait.grpc_code !== 0)) checks[item.case] = true;
49
+ if (item.case === 'timeout' && busy && noGrant) checks[item.case] = true;
50
+ if (item.case === 'late_activity_cancel_restart' && ['activity', 'cancel', 'restart'].includes(item.fence?.change) && typeof item.fence.before === 'string' && item.fence.before && typeof item.fence.after === 'string' && item.fence.after && item.fence.after !== item.fence.before && idle && noGrant) { checks[item.case] = true; fencedChanges.add(item.fence.change); }
51
+ const service = work.find(record => record?.kind === 'persistent' && record.native_tool === 'run_command' && record.native_is_daemon === true && record.root_session_id === item.session_id && typeof record.id === 'string' && record.id && Number.isSafeInteger(record.process?.pid) && record.process.pid > 0 && typeof record.process.birth === 'string' && record.process.birth && record.process.owned === true);
52
+ const serviceKey = service && JSON.stringify([item.session_id, service.id, service.process.pid, service.process.birth]);
53
+ if (item.case === 'daemon_excluded_from_required_execution' && service?.status === 'running' && service.process.live === true && item.root_status === 'terminal' && item.native_result_status === 'SUCCESS' && item.inventory_complete === true && work.every(record => record === service || record?.status === 'terminal' && typeof record.id === 'string' && record.id && record.root_session_id === item.session_id) && idle && item.idle_granted === true) { checks[item.case] = true; liveServices.set(serviceKey, Date.parse(item.observed_at)); }
54
+ if (item.case === 'owned_daemon_retirement' && service?.status === 'terminal' && service.process.live === false && item.cleanup?.coverage === 'complete' && item.cleanup.provider_stopped === true && typeof item.cleanup.snapshot_locator === 'string' && item.cleanup.snapshot_locator && noGrant) { checks[item.case] = true; retiredServices.push([serviceKey, Date.parse(item.observed_at)]); }
55
+ if (!checks[item.case]) failed.add(item.case);
56
+ checks[item.case] ||= prior;
57
+ }
58
+ checks.late_activity_cancel_restart &&= fencedChanges.size === 3;
59
+ checks.owned_daemon_retirement &&= liveServices.size > 0 && [...liveServices].every(([key, started]) => retiredServices.some(([retiredKey, at]) => retiredKey === key && at >= started));
60
+ for (const name of failed) checks[name] = false;
61
+ return { qualified: Object.values(checks).every(Boolean), checks };
62
+ }
63
+ const run = promisify(execFile);
64
+ const invalid = reason => Object.assign(new Error(`AGY native inspection unavailable: ${reason}`), { code: 'agy_native_inspection_unavailable', details: { reason, capability: AGY_NATIVE_INSPECTION_CONTRACT } });
65
+ const codec = schema => ({ serialize: value => Buffer.from(toBinary(schema, create(schema, value))), deserialize: bytes => fromBinary(schema, bytes) });
66
+ const method = (name, request, response) => ({ path: `/exa.language_server_pb.LanguageServerService/${name}`, requestStream: false, responseStream: false, requestSerialize: codec(request).serialize, requestDeserialize: codec(request).deserialize, responseSerialize: codec(response).serialize, responseDeserialize: codec(response).deserialize });
67
+ export const agyNativeService = {
68
+ wait: method('WaitForConversationFullyIdle', WaitForConversationFullyIdleRequestSchema, WaitForConversationFullyIdleResponseSchema),
69
+ metadata: method('GetConversationMetadata', GetConversationMetadataRequestSchema, GetConversationMetadataResponseSchema),
70
+ stop: method('ForceStopCascadeTree', ForceStopCascadeTreeRequestSchema, ForceStopCascadeTreeResponseSchema),
71
+ state: { ...method('StreamAgentStateUpdates', StreamAgentStateUpdatesRequestSchema, StreamAgentStateUpdatesResponseSchema), responseStream: true }
72
+ };
73
+ const Client = grpc.makeGenericClientConstructor(agyNativeService, 'AgyReadOnlyInspection');
74
+
75
+ async function readRegular(file, maximum, prefix = false) {
76
+ if (!path.isAbsolute(file)) throw invalid('native_file_path_invalid');
77
+ const before = await lstat(file);
78
+ if (!before.isFile() || before.isSymbolicLink() || !prefix && before.size > maximum) throw invalid('native_file_rejected');
79
+ const handle = await open(file, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
80
+ try {
81
+ const stat = await handle.stat();
82
+ if (!stat.isFile() || stat.dev !== before.dev || stat.ino !== before.ino || !prefix && stat.size > maximum) throw invalid('native_file_changed');
83
+ const bytes = Buffer.alloc(prefix ? Math.min(stat.size, maximum) : maximum + 1);
84
+ const { bytesRead } = await handle.read(bytes, 0, bytes.length, 0);
85
+ const after = await lstat(file);
86
+ if (!after.isFile() || after.dev !== stat.dev || after.ino !== stat.ino || !prefix && bytesRead > maximum) throw invalid('native_file_changed');
87
+ return { bytes: bytes.subarray(0, bytesRead), stat };
88
+ } finally { await handle.close(); }
89
+ }
90
+
91
+ export async function agyBinaryIdentity(bin) {
92
+ if (typeof bin !== 'string' || !bin) throw invalid('native_binary_missing');
93
+ const candidate = path.isAbsolute(bin) ? bin : (await Promise.all((process.env.PATH ?? '').split(path.delimiter).map(async dir => {
94
+ const file = path.join(dir, bin); try { return (await lstat(file)).isFile() || (await lstat(file)).isSymbolicLink() ? file : null; } catch { return null; }
95
+ }))).find(Boolean);
96
+ if (!candidate) throw invalid('native_binary_missing');
97
+ const file = await realpath(candidate), hash = createHash('sha256');
98
+ for await (const chunk of createReadStream(file)) hash.update(chunk);
99
+ return { file, sha256: hash.digest('hex') };
100
+ }
101
+ export async function agyInspectionPolicyIdentity() {
102
+ const manifest = JSON.parse(await readFile(new URL('../../../package.json', import.meta.url), 'utf8'));
103
+ const versions = [manifest.dependencies?.['@grpc/grpc-js'], manifest.dependencies?.['@bufbuild/protobuf']];
104
+ if (versions[0] !== '1.14.6' || versions[1] !== '2.16.0') throw invalid('native_protocol_dependency_unqualified');
105
+ return createHash('sha256').update(AGY_NATIVE_INSPECTION_CONTRACT).update(JSON.stringify(versions)).update(await readFile(new URL('./agy-native_pb.js', import.meta.url))).update(await readFile(new URL('./agy-native-inspection.mjs', import.meta.url))).digest('hex');
106
+ }
107
+ export async function readAgyNativeQualification(stateDir, bin, receiptFile = null) {
108
+ const binary = await agyBinaryIdentity(bin);
109
+ const clientContract = await agyInspectionPolicyIdentity();
110
+ let receipt;
111
+ const file = receiptFile ?? path.join(stateDir, 'native-inspection-qualification.json');
112
+ if (!path.isAbsolute(file)) throw invalid('qualification_path_invalid');
113
+ try {
114
+ receipt = JSON.parse((await readRegular(file, 64 * 1024)).bytes.toString('utf8'));
115
+ }
116
+ catch (error) { if (error.code !== 'ENOENT') throw invalid('qualification_receipt_invalid'); }
117
+ let evidenceValid = false;
118
+ if (typeof receipt?.evidence_path === 'string' && path.isAbsolute(receipt.evidence_path)) {
119
+ try {
120
+ const evidence = (await readRegular(receipt.evidence_path, 1024 * 1024)).bytes;
121
+ const parsed = JSON.parse(evidence.toString('utf8'));
122
+ evidenceValid = createHash('sha256').update(evidence).digest('hex') === receipt.evidence_sha256
123
+ && parsed.root_relation === receipt.root_relation
124
+ && validateAgyNativeEvidence(parsed, { ...binary, client_contract_sha256: clientContract }).qualified;
125
+ } catch { /* No retained evidence means no qualification grant. */ }
126
+ }
127
+ const qualified = evidenceValid && receipt?.schema_id === AGY_NATIVE_INSPECTION_CONTRACT && receipt.scope === 'required_execution' && receipt.binary_sha256 === binary.sha256
128
+ && receipt.client_contract_sha256 === clientContract
129
+ && ['self', 'empty_self'].includes(receipt.root_relation)
130
+ && AGY_NATIVE_QUALIFICATION_CASES.every(name => receipt.checks?.[name] === true)
131
+ && typeof receipt.evidence_sha256 === 'string' && /^[a-f0-9]{64}$/.test(receipt.evidence_sha256);
132
+ return { ...binary, client_contract_sha256: clientContract, qualified, rootRelation: qualified ? receipt.root_relation : null };
133
+ }
134
+
135
+ /** Only the log for this physical launch may nominate an endpoint. Its live
136
+ * listener must be this provider or an OS descendant, with retained PID birth. */
137
+ export async function ownedAgyEndpoint({ logFile, providerPid, providerBirth, snapshot = processSnapshot, listeners = async port => {
138
+ const { stdout } = await run('lsof', ['-nP', `-iTCP:${port}`, '-sTCP:LISTEN', '-Fpn'], { timeout: 5_000, maxBuffer: 64 * 1024 });
139
+ let pid; return stdout.trim().split('\n').flatMap(line => line.startsWith('p') ? (pid = Number(line.slice(1)), []) : line.startsWith('n') ? [{ pid, address: line.slice(1) }] : []);
140
+ } }) {
141
+ if (!path.isAbsolute(logFile ?? '') || !Number.isSafeInteger(providerPid) || !providerBirth) throw invalid('provider_binding_missing');
142
+ // Startup prefix only: later log growth is not an expiry or model progress.
143
+ const { bytes, stat } = await readRegular(logFile, 1024 * 1024, true), text = bytes.toString('utf8');
144
+ const ports = [...new Set([...text.matchAll(/Language server listening on random port at (\d+) for HTTP(?:\r?$)/gm)].map(match => Number(match[1])))];
145
+ if (ports.length !== 1 || ports[0] < 1 || ports[0] > 65535) throw invalid('native_endpoint_missing_or_ambiguous');
146
+ const records = await snapshot(), provider = records.find(record => record.pid === providerPid);
147
+ if (!provider || provider.started !== providerBirth || provider.zombie) throw invalid('provider_birth_changed');
148
+ const allowed = new Set([providerPid]); let changed;
149
+ do { changed = false; for (const record of records) if (allowed.has(record.ppid) && !allowed.has(record.pid) && !record.zombie) { allowed.add(record.pid); changed = true; } } while (changed);
150
+ const owners = await listeners(ports[0]);
151
+ if (!owners.length || owners.some(owner => !allowed.has(owner.pid) || !/^(?:127\.0\.0\.1|\[::1\]|localhost):\d+$/.test(owner.address))) throw invalid('native_endpoint_foreign_or_nonloopback');
152
+ const births = owners.map(owner => ({ pid: owner.pid, started: records.find(record => record.pid === owner.pid)?.started }));
153
+ if (births.some(owner => !owner.started)) throw invalid('listener_birth_missing');
154
+ return { target: `127.0.0.1:${ports[0]}`, provider_pid: providerPid, provider_birth: providerBirth, listeners: births, log_identity: `${stat.dev}:${stat.ino}` };
155
+ }
156
+
157
+ /** No model request: metadata read followed by the native idle barrier. The
158
+ * caller owns freshness fencing and qualification; a raw reply is not a grant. */
159
+ async function agyNativeRequest({ endpoint, sessionId, cwd, remainingMs, signal, rootRelation = null, onMetadata = null, csrfToken, rootSessionId = sessionId, parentSessionId = '' }, action = 'wait', ownedSessions = []) {
160
+ if (!/^127\.0\.0\.1:\d+$/.test(endpoint?.target ?? '') || Number(endpoint.target.split(':')[1]) < 1 || Number(endpoint.target.split(':')[1]) > 65535) throw invalid('native_endpoint_nonloopback');
161
+ if (!Number.isFinite(remainingMs) || remainingMs < 1) throw invalid('observation_budget_exhausted');
162
+ const deadline = Date.now() + remainingMs;
163
+ const client = new Client(endpoint.target, grpc.credentials.createInsecure(), { 'grpc.max_receive_message_length': 1024 * 1024, 'grpc.max_send_message_length': 64 * 1024, 'grpc.enable_retries': 0 });
164
+ let active;
165
+ const headers = new grpc.Metadata();
166
+ if (typeof csrfToken === 'string' && csrfToken) headers.set('x-codeium-csrf-token', csrfToken);
167
+ const abort = () => active?.cancel();
168
+ const unary = (name, request) => new Promise((resolve, reject) => {
169
+ if (signal?.aborted) return reject(invalid('inspection_cancelled'));
170
+ active = client[name](request, headers, { deadline }, (error, value) => error ? reject(invalid(`grpc_${error.code ?? 'unknown'}`)) : value ? resolve(value) : reject(invalid('grpc_message_missing')));
171
+ });
172
+ signal?.addEventListener('abort', abort, { once: true });
173
+ try {
174
+ const metadata = await unary('metadata', { conversationId: sessionId });
175
+ onMetadata?.(metadata);
176
+ const relation = metadata.metadata;
177
+ const rootMatches = relation?.rootConversationId === rootSessionId || rootRelation === 'empty_self' && rootSessionId === sessionId && relation?.rootConversationId === '';
178
+ const workspaces = await Promise.all((relation?.workspaceUris ?? []).map(async uri => { try { return await realpath(fileURLToPath(uri)); } catch { return null; } }));
179
+ if (!relation || relation.parentConversationId !== (action === 'state' ? parentSessionId : '') || action !== 'state' && rootSessionId !== sessionId || !rootMatches || !metadata.trajectoryId || !workspaces.includes(await realpath(cwd))) throw invalid('native_metadata_binding_unproven');
180
+ if (action === 'state') {
181
+ return await new Promise((resolve, reject) => {
182
+ if (signal?.aborted) return reject(invalid('inspection_cancelled'));
183
+ active = client.state({ conversationId: sessionId, subscriberId: randomUUID() }, headers, { deadline });
184
+ let done = false;
185
+ active.on('data', value => {
186
+ if (done) return;
187
+ const update = value.update;
188
+ // Every subscription begins with a native full snapshot. Never fold
189
+ // deltas from a previous subscription into a new incarnation.
190
+ if (!update || update.conversationId !== sessionId || update.trajectoryId !== metadata.trajectoryId) return;
191
+ const snapshot = JSON.parse(JSON.stringify(update, (key, value) => key.startsWith('$') ? undefined : value));
192
+ done = true; resolve({ ...snapshot, observed_at: new Date().toISOString(), method: agyNativeService.state.path }); active.cancel();
193
+ });
194
+ active.on('error', error => { if (!done) { done = true; reject(invalid(`grpc_${error.code ?? 'unknown'}`)); } });
195
+ active.on('end', () => { if (!done) { done = true; reject(invalid('native_state_snapshot_missing')); } });
196
+ });
197
+ }
198
+ if (action === 'stop') {
199
+ const reply = await unary('stop', { conversationId: sessionId });
200
+ const stopped = reply.stoppedConversationIds, owned = new Set([sessionId, ...ownedSessions]);
201
+ if (!Array.isArray(stopped) || !stopped.length || new Set(stopped).size !== stopped.length
202
+ || ![...owned].every(id => stopped.includes(id)) || stopped.some(id => !owned.has(id))) {
203
+ const error = invalid('native_stopped_tree_binding_unproven'); error.details.stopped_session_ids = stopped ?? null; throw error;
204
+ }
205
+ return { stopped_session_ids: stopped, trajectory_id: metadata.trajectoryId, method: agyNativeService.stop.path };
206
+ }
207
+ const reply = await unary('wait', { conversationId: sessionId, inactivityTimeoutSeconds: Math.max(1, Math.min(2147483647, Math.ceil((deadline - Date.now()) / 1000))), returnOnExecutorError: false });
208
+ return { idle: reply.timedOut === false, reason: reply.timedOut ? 'native_wait_timed_out' : 'native_wait_fully_idle', method: agyNativeService.wait.path, trajectory_id: metadata.trajectoryId };
209
+ } finally { signal?.removeEventListener('abort', abort); client.close(); }
210
+ }
211
+
212
+ export const inspectAgyNative = input => agyNativeRequest(input);
213
+ /** Read-only per-node native state; no execution/readiness grant. */
214
+ export const inspectAgyNativeState = input => agyNativeRequest(input, 'state');
215
+ /** Scoped control, not an idle/physical grant. Caller must verify retirement. */
216
+ export const stopAgyNativeTree = (input, ownedSessions = []) => agyNativeRequest(input, 'stop', ownedSessions);
@@ -0,0 +1,117 @@
1
+ // @generated by protoc-gen-es v2.16.0 with parameter "target=js"
2
+ // @generated from file agy-native.proto (package exa.language_server_pb, syntax proto3)
3
+ /* eslint-disable */
4
+
5
+ import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2";
6
+
7
+ /**
8
+ * Describes the file agy-native.proto.
9
+ */
10
+ export const file_agy_native = /*@__PURE__*/
11
+ fileDesc("ChBhZ3ktbmF0aXZlLnByb3RvEhZleGEubGFuZ3VhZ2Vfc2VydmVyX3BiIoQBCiNXYWl0Rm9yQ29udmVyc2F0aW9uRnVsbHlJZGxlUmVxdWVzdBIXCg9jb252ZXJzYXRpb25faWQYASABKAkSIgoaaW5hY3Rpdml0eV90aW1lb3V0X3NlY29uZHMYAiABKAUSIAoYcmV0dXJuX29uX2V4ZWN1dG9yX2Vycm9yGAQgASgIIjkKJFdhaXRGb3JDb252ZXJzYXRpb25GdWxseUlkbGVSZXNwb25zZRIRCgl0aW1lZF9vdXQYASABKAgiOQoeR2V0Q29udmVyc2F0aW9uTWV0YWRhdGFSZXF1ZXN0EhcKD2NvbnZlcnNhdGlvbl9pZBgBIAEoCSJsChRDb252ZXJzYXRpb25NZXRhZGF0YRIeChZwYXJlbnRfY29udmVyc2F0aW9uX2lkGAUgASgJEhwKFHJvb3RfY29udmVyc2F0aW9uX2lkGAYgASgJEhYKDndvcmtzcGFjZV91cmlzGAcgAygJIosBCh9HZXRDb252ZXJzYXRpb25NZXRhZGF0YVJlc3BvbnNlEj4KCG1ldGFkYXRhGAEgASgLMiwuZXhhLmxhbmd1YWdlX3NlcnZlcl9wYi5Db252ZXJzYXRpb25NZXRhZGF0YRIRCgludW1fc3RlcHMYAiABKA0SFQoNdHJhamVjdG9yeV9pZBgDIAEoCSI2ChtGb3JjZVN0b3BDYXNjYWRlVHJlZVJlcXVlc3QSFwoPY29udmVyc2F0aW9uX2lkGAEgASgJIkAKHEZvcmNlU3RvcENhc2NhZGVUcmVlUmVzcG9uc2USIAoYc3RvcHBlZF9jb252ZXJzYXRpb25faWRzGAEgAygJIlAKHlN0cmVhbUFnZW50U3RhdGVVcGRhdGVzUmVxdWVzdBIXCg9jb252ZXJzYXRpb25faWQYASABKAkSFQoNc3Vic2NyaWJlcl9pZBgCIAEoCSJOCgxBZ2VudE1lc3NhZ2USCgoCaWQYASABKAkSEQoJcmVjaXBpZW50GAIgASgJEg4KBnNlbmRlchgDIAEoCRIPCgdjb250ZW50GAQgASgJIokBChpQZW5kaW5nQWdlbnRNZXNzYWdlc1VwZGF0ZRIPCgdpbmRpY2VzGAEgAygNEkQKFnBlbmRpbmdfYWdlbnRfbWVzc2FnZXMYAiADKAsyJC5leGEubGFuZ3VhZ2Vfc2VydmVyX3BiLkFnZW50TWVzc2FnZRIUCgx0b3RhbF9sZW5ndGgYAyABKA0iagoMVGFza1NuYXBzaG90Eg8KB3Rhc2tfaWQYASABKAkSEQoJdG9vbF9uYW1lGAIgASgJEhIKCnN0ZXBfaW5kZXgYBiABKA0SDwoHbG9nX3VyaRgHIAEoCRIRCglpc19kYWVtb24YCCABKAgiTQoOQmFja2dyb3VuZFRhc2sSOwoNdGFza19zbmFwc2hvdBgBIAEoCzIkLmV4YS5sYW5ndWFnZV9zZXJ2ZXJfcGIuVGFza1NuYXBzaG90IoABChVCYWNrZ3JvdW5kVGFza3NVcGRhdGUSDwoHaW5kaWNlcxgBIAMoDRJAChBiYWNrZ3JvdW5kX3Rhc2tzGAIgAygLMiYuZXhhLmxhbmd1YWdlX3NlcnZlcl9wYi5CYWNrZ3JvdW5kVGFzaxIUCgx0b3RhbF9sZW5ndGgYAyABKA0i5wIKEEFnZW50U3RhdGVVcGRhdGUSFwoPY29udmVyc2F0aW9uX2lkGAEgASgJEhUKDXRyYWplY3RvcnlfaWQYAiABKAkSDgoGc3RhdHVzGAMgASgFEhkKEWV4ZWN1dGFibGVfc3RhdHVzGAQgASgFEhwKFGV4ZWN1dG9yX2xvb3Bfc3RhdHVzGAUgASgFEhsKE2hhc19hY3RpdmVfY2hpbGRyZW4YDiABKAgSTgoXYmFja2dyb3VuZF90YXNrc191cGRhdGUYESABKAsyLS5leGEubGFuZ3VhZ2Vfc2VydmVyX3BiLkJhY2tncm91bmRUYXNrc1VwZGF0ZRISCgpmdWxseV9pZGxlGBIgASgIElkKHXBlbmRpbmdfYWdlbnRfbWVzc2FnZXNfdXBkYXRlGBQgASgLMjIuZXhhLmxhbmd1YWdlX3NlcnZlcl9wYi5QZW5kaW5nQWdlbnRNZXNzYWdlc1VwZGF0ZSJbCh9TdHJlYW1BZ2VudFN0YXRlVXBkYXRlc1Jlc3BvbnNlEjgKBnVwZGF0ZRgBIAEoCzIoLmV4YS5sYW5ndWFnZV9zZXJ2ZXJfcGIuQWdlbnRTdGF0ZVVwZGF0ZWIGcHJvdG8z");
12
+
13
+ /**
14
+ * Describes the message exa.language_server_pb.WaitForConversationFullyIdleRequest.
15
+ * Use `create(WaitForConversationFullyIdleRequestSchema)` to create a new message.
16
+ */
17
+ export const WaitForConversationFullyIdleRequestSchema = /*@__PURE__*/
18
+ messageDesc(file_agy_native, 0);
19
+
20
+ /**
21
+ * Describes the message exa.language_server_pb.WaitForConversationFullyIdleResponse.
22
+ * Use `create(WaitForConversationFullyIdleResponseSchema)` to create a new message.
23
+ */
24
+ export const WaitForConversationFullyIdleResponseSchema = /*@__PURE__*/
25
+ messageDesc(file_agy_native, 1);
26
+
27
+ /**
28
+ * Describes the message exa.language_server_pb.GetConversationMetadataRequest.
29
+ * Use `create(GetConversationMetadataRequestSchema)` to create a new message.
30
+ */
31
+ export const GetConversationMetadataRequestSchema = /*@__PURE__*/
32
+ messageDesc(file_agy_native, 2);
33
+
34
+ /**
35
+ * Describes the message exa.language_server_pb.ConversationMetadata.
36
+ * Use `create(ConversationMetadataSchema)` to create a new message.
37
+ */
38
+ export const ConversationMetadataSchema = /*@__PURE__*/
39
+ messageDesc(file_agy_native, 3);
40
+
41
+ /**
42
+ * Describes the message exa.language_server_pb.GetConversationMetadataResponse.
43
+ * Use `create(GetConversationMetadataResponseSchema)` to create a new message.
44
+ */
45
+ export const GetConversationMetadataResponseSchema = /*@__PURE__*/
46
+ messageDesc(file_agy_native, 4);
47
+
48
+ /**
49
+ * Describes the message exa.language_server_pb.ForceStopCascadeTreeRequest.
50
+ * Use `create(ForceStopCascadeTreeRequestSchema)` to create a new message.
51
+ */
52
+ export const ForceStopCascadeTreeRequestSchema = /*@__PURE__*/
53
+ messageDesc(file_agy_native, 5);
54
+
55
+ /**
56
+ * Describes the message exa.language_server_pb.ForceStopCascadeTreeResponse.
57
+ * Use `create(ForceStopCascadeTreeResponseSchema)` to create a new message.
58
+ */
59
+ export const ForceStopCascadeTreeResponseSchema = /*@__PURE__*/
60
+ messageDesc(file_agy_native, 6);
61
+
62
+ /**
63
+ * Describes the message exa.language_server_pb.StreamAgentStateUpdatesRequest.
64
+ * Use `create(StreamAgentStateUpdatesRequestSchema)` to create a new message.
65
+ */
66
+ export const StreamAgentStateUpdatesRequestSchema = /*@__PURE__*/
67
+ messageDesc(file_agy_native, 7);
68
+
69
+ /**
70
+ * Describes the message exa.language_server_pb.AgentMessage.
71
+ * Use `create(AgentMessageSchema)` to create a new message.
72
+ */
73
+ export const AgentMessageSchema = /*@__PURE__*/
74
+ messageDesc(file_agy_native, 8);
75
+
76
+ /**
77
+ * Describes the message exa.language_server_pb.PendingAgentMessagesUpdate.
78
+ * Use `create(PendingAgentMessagesUpdateSchema)` to create a new message.
79
+ */
80
+ export const PendingAgentMessagesUpdateSchema = /*@__PURE__*/
81
+ messageDesc(file_agy_native, 9);
82
+
83
+ /**
84
+ * Describes the message exa.language_server_pb.TaskSnapshot.
85
+ * Use `create(TaskSnapshotSchema)` to create a new message.
86
+ */
87
+ export const TaskSnapshotSchema = /*@__PURE__*/
88
+ messageDesc(file_agy_native, 10);
89
+
90
+ /**
91
+ * Describes the message exa.language_server_pb.BackgroundTask.
92
+ * Use `create(BackgroundTaskSchema)` to create a new message.
93
+ */
94
+ export const BackgroundTaskSchema = /*@__PURE__*/
95
+ messageDesc(file_agy_native, 11);
96
+
97
+ /**
98
+ * Describes the message exa.language_server_pb.BackgroundTasksUpdate.
99
+ * Use `create(BackgroundTasksUpdateSchema)` to create a new message.
100
+ */
101
+ export const BackgroundTasksUpdateSchema = /*@__PURE__*/
102
+ messageDesc(file_agy_native, 12);
103
+
104
+ /**
105
+ * Describes the message exa.language_server_pb.AgentStateUpdate.
106
+ * Use `create(AgentStateUpdateSchema)` to create a new message.
107
+ */
108
+ export const AgentStateUpdateSchema = /*@__PURE__*/
109
+ messageDesc(file_agy_native, 13);
110
+
111
+ /**
112
+ * Describes the message exa.language_server_pb.StreamAgentStateUpdatesResponse.
113
+ * Use `create(StreamAgentStateUpdatesResponseSchema)` to create a new message.
114
+ */
115
+ export const StreamAgentStateUpdatesResponseSchema = /*@__PURE__*/
116
+ messageDesc(file_agy_native, 14);
117
+
@@ -0,0 +1,2 @@
1
+ export function recoverDaemonReply(root: string, id: string, options?: { timeoutMs?: number | null; signal?: AbortSignal; binding?: Record<string, unknown>; onProgress?: (value: Record<string, unknown>) => void; onOutcome?: (value: Record<string, unknown>) => void; onPendingSettlement?: (value: Record<string, unknown>) => Promise<void>; observationClock?: import("./observation-clock.mjs").ObservationClock }): Promise<Record<string, unknown>>;
2
+ export function retainedDaemonReply(root: string, id: string, binding?: Record<string, unknown>): Promise<{ ready: boolean; outcome: unknown; value?: unknown; settlement?: Record<string, unknown> | null; reason?: string } | null>;
@@ -0,0 +1,163 @@
1
+ import net from 'node:net';
2
+ import { readFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { hashJson, writeJsonAtomic } from './runner-events.mjs';
5
+ import { ObservationClock } from './observation-clock.mjs';
6
+ import { canonicalNativeOperation, nativeOperationWait, validateDaemonWait } from './adapter-timeouts.mjs';
7
+ import { assertNativeLine, retainNativeReplyBuffer } from './native-streams.mjs';
8
+ import { operationDirectory, readOperationRecord, readOperationProgress, readOperationWaiting, suspendOperationClock } from './operation-progress.mjs';
9
+
10
+ const productive = new Set(['session.create', 'session.prompt', 'session.start', 'session.fork', 'session.resume']);
11
+ const fault = (code, message, details) => Object.assign(new Error(message), { code, retryable: false, details });
12
+ export async function retainedDaemonReply(root, id, binding = {}) {
13
+ const requested = await readOperationRecord(root, id, 'requested.json');
14
+ if (!requested) return null;
15
+ if (requested.operation_id !== id || Object.entries(binding).some(([key, value]) => (requested[key] ?? null) !== (value ?? null))) throw fault('operation_conflict', 'retained operation differs from dispatched request', { operation_id: id });
16
+ const terminal = await readOperationRecord(root, id, 'result.json');
17
+ if (!terminal) return null;
18
+ if (['operation_id','daemon_id','operation','params_sha256','owner_id','generation'].some(field=>Object.hasOwn(terminal,field)&&(terminal[field] ?? null)!==(requested[field] ?? null))) throw fault('operation_conflict','native outcome binding differs from original operation',{operation_id:id});
19
+ if (terminal.state !== 'completed') throw Object.assign(new Error(terminal.error?.message ?? 'native operation failed'), terminal.error);
20
+ if (Number.isSafeInteger(requested.generation)) try {
21
+ const fence = JSON.parse(await readFile(path.join(root,'operation-fence.json'),'utf8'));
22
+ if (fence.daemon_id === requested.daemon_id && fence.generation > requested.generation) throw fault('operation_cancelled','continuation is fenced by newer control',{operation_id:id,native_result:terminal.result});
23
+ } catch(error) { if (error.code !== 'ENOENT') throw error; }
24
+ const settlement = await readOperationRecord(root, id, 'settlement.json');
25
+ try {
26
+ const daemon = JSON.parse(await readFile(path.join(root,'daemon.json'),'utf8'));
27
+ if ((daemon.daemon_id ?? daemon.config?.daemonId ?? null)!==requested.daemon_id || (daemon.config?.runtime_owner?.owner_id ?? null)!==(requested.owner_id ?? null) || ['stopping','clean','unclean','cleanup_failed','failed'].includes(daemon.shutdown_state)) return {ready:false,outcome:terminal.result,settlement,reason:'daemon_authority_changed'};
28
+ if (requested.owner_id) try { process.kill(daemon.pid,0); } catch { return {ready:false,outcome:terminal.result,settlement,reason:'daemon_owner_dead'}; }
29
+ } catch(error) { if(error.code!=='ENOENT') throw error; if(requested.daemon_id || requested.owner_id) return {ready:false,outcome:terminal.result,settlement,reason:'daemon_absent'}; }
30
+ if (!['settled', 'not_required'].includes(settlement?.state)) return { ready: false, outcome: terminal.result, settlement };
31
+ return { ready: true, outcome: terminal.result, settlement, value: settlement.state === 'not_required' ? terminal.result : { ...terminal.result, settlement } };
32
+ }
33
+ export async function recoverDaemonReply(root, id, { timeoutMs = 30_000, signal, binding = {}, onProgress = () => {}, onOutcome = () => {}, onPendingSettlement, observationClock } = {}) {
34
+ const saved = observationClock ? null : await readOperationRecord(root, id, 'observer-recovery.json') ?? await readOperationRecord(root, id, 'observer-transport.json');
35
+ signal?.throwIfAborted();
36
+ const clock = observationClock ?? new ObservationClock({ timeoutMs: saved?.timeout_ms ?? timeoutMs, saved });
37
+ let lastSequence = clock.progress ?? 0, lastSaved = 0, latestProgress, settlementAttempted = false, settlementError;
38
+ const exhaustedCursor = clock.progress;
39
+ let exhausted = clock.observationLost || clock.elapsed >= clock.timeoutMs;
40
+ for (;;) {
41
+ signal?.throwIfAborted();
42
+ const retained = await retainedDaemonReply(root, id, binding);
43
+ signal?.throwIfAborted();
44
+ if (retained) {
45
+ onOutcome(retained.outcome);
46
+ signal?.throwIfAborted();
47
+ if (retained.ready) return retained.value;
48
+ }
49
+ const progress = await readOperationProgress(root, id, binding);
50
+ signal?.throwIfAborted();
51
+ if (progress && progress.sequence > lastSequence) {
52
+ lastSequence = progress.sequence;
53
+ const observedAt = Date.parse(progress.observed_at);
54
+ // The outer cursor counts diagnostics, not durable sequences. A handoff
55
+ // may recognize a higher sequence with the same already-observed event.
56
+ if (clock.progressAt === null || observedAt > clock.progressAt) {
57
+ latestProgress={cursor:progress.sequence,observed_at:observedAt}; onProgress(progress);
58
+ }
59
+ }
60
+ const waiting = await readOperationWaiting(root,id,binding);
61
+ signal?.throwIfAborted();
62
+ if (waiting) suspendOperationClock(clock);
63
+ const sampled = waiting ? false : clock.sample(latestProgress);
64
+ if (clock.progress !== exhaustedCursor && clock.elapsed < clock.timeoutMs && !clock.observationLost) exhausted = false;
65
+ const expired = !waiting && (exhausted || sampled);
66
+ if ((expired || Date.now() - lastSaved >= 1_000) && await readOperationRecord(root,id,'requested.json')) { await writeJsonAtomic(path.join(operationDirectory(root,id),'observer-recovery.json'),clock.state()); lastSaved = Date.now(); }
67
+ if (expired) {
68
+ const final = await retainedDaemonReply(root, id, binding);
69
+ signal?.throwIfAborted();
70
+ if (final?.ready) return final.value;
71
+ throw fault(final ? 'settlement_reconciliation_required' : 'operation_observation_lost', 'original operation has no dispatch-ready reply', { operation_id: id, native_outcome: final ? 'completed' : 'unknown', native_result: final?.outcome, settlement: final?.settlement, reason:final?.reason, ...(settlementError ? { settlement_error:settlementError } : {}), state_dir: root });
72
+ }
73
+ if (retained && onPendingSettlement && !settlementAttempted && !retained.reason) {
74
+ settlementAttempted = true;
75
+ try { await onPendingSettlement(retained); } catch (error) { settlementError = {code:error.code,message:error.message}; }
76
+ signal?.throwIfAborted();
77
+ continue;
78
+ }
79
+ await new Promise(resolve => setTimeout(resolve, Math.min(100, timeoutMs / 4)));
80
+ }
81
+ }
82
+ export async function callDaemonObserved({ stateDir, socket, request, responseSchema, harness, timeoutMs }) {
83
+ request = { ...request, operation: canonicalNativeOperation(harness, request.operation) };
84
+ validateDaemonWait(harness, request.operation, timeoutMs);
85
+ assertNativeLine(JSON.stringify(request), 'request');
86
+ const durable = productive.has(request.operation);
87
+ const binding = { operation: request.operation, params_sha256: hashJson({ operation: request.operation, params: request.params ?? {} }) };
88
+ let initialDaemon;
89
+ if (durable) try {
90
+ const state = JSON.parse(await readFile(path.join(stateDir,'daemon.json'),'utf8'));
91
+ initialDaemon = state.daemon_id ?? state.config?.daemonId ?? null;
92
+ binding.owner_id = state.config?.runtime_owner?.owner_id ?? null;
93
+ } catch (error) { if (error.code !== 'ENOENT') throw error; }
94
+ // Reject a reused ID with different inputs before opening a transport.
95
+ // Otherwise its retained progress can win the race with the daemon's
96
+ // conflict reply and misclassify a valid old receipt as corrupt progress.
97
+ if (durable) await retainedDaemonReply(stateDir, request.id, {
98
+ ...binding, ...(initialDaemon === undefined ? {} : { daemon_id: initialDaemon })
99
+ });
100
+ const savedClock = durable ? await readOperationRecord(stateDir,request.id,'observer-transport.json') : null;
101
+ return await new Promise((resolve, reject) => {
102
+ const client = net.createConnection(socket);
103
+ let buffer = '', done = false, polling = false, pollFlight, lastSequence = savedClock?.cursor ?? 0, frozenDaemon = initialDaemon, disconnected = false, latestProgress, lastSaved = 0;
104
+ const bound = () => ({ ...binding, ...(frozenDaemon === undefined ? {} : { daemon_id: frozenDaemon }) });
105
+ const nativeWork = nativeOperationWait(harness, request.operation) === 'native-work';
106
+ let clock = nativeWork ? null : new ObservationClock({ timeoutMs, saved: savedClock });
107
+ const finish = (error, result) => { if (done) return; done = true; clearInterval(timer); client.destroy(); void Promise.resolve(pollFlight).then(() => error ? reject(error) : resolve(result)); };
108
+ const reconcile = async error => {
109
+ if (done) return;
110
+ try {
111
+ const reply = durable ? await retainedDaemonReply(stateDir, request.id, bound()) : null;
112
+ if (reply?.ready) return finish(null, reply.value);
113
+ if (reply) error = fault('settlement_reconciliation_required', 'native outcome retained; dispatch readiness is not confirmed', { operation_id: request.id, native_outcome: 'completed', native_result: reply.outcome, settlement: reply.settlement, reason:reply.reason, state_dir: stateDir });
114
+ else if (durable) error = fault(error.code, error.message, { ...error.details, operation_id: request.id, native_outcome: 'unknown', state_dir: stateDir });
115
+ finish(error);
116
+ } catch (cause) { finish(cause); }
117
+ };
118
+ const poll = () => {
119
+ if (done || polling) return pollFlight; polling = true;
120
+ pollFlight = (async () => {
121
+ try {
122
+ const progress = durable ? await readOperationProgress(stateDir, request.id, { ...binding, ...(frozenDaemon === undefined ? {} : { daemon_id: frozenDaemon }) }) : null;
123
+ if (done) return;
124
+ if (progress && progress.sequence > lastSequence) {
125
+ frozenDaemon ??= progress.daemon_id; lastSequence = progress.sequence;
126
+ binding.generation ??= progress.generation;
127
+ latestProgress = {cursor:progress.sequence,observed_at:Date.parse(progress.observed_at)};
128
+ process.stderr.write(`${JSON.stringify({ kind: 'operation_progress', ...progress })}\n`);
129
+ }
130
+ if (durable && disconnected) {
131
+ const reply = await retainedDaemonReply(stateDir, request.id, bound());
132
+ if (reply?.ready) return finish(null, reply.value);
133
+ }
134
+ const waiting = durable && await readOperationWaiting(stateDir,request.id,bound());
135
+ if (done) return;
136
+ if (clock && waiting) suspendOperationClock(clock);
137
+ const expired = !waiting && clock?.sample(latestProgress ?? (durable ? undefined : buffer.length || undefined));
138
+ if (durable && clock && (expired || Date.now()-lastSaved>=1_000) && await readOperationRecord(stateDir,request.id,'requested.json')) { await writeJsonAtomic(path.join(operationDirectory(stateDir,request.id),'observer-transport.json'),clock.state()); lastSaved=Date.now(); }
139
+ if (expired) await reconcile(fault('daemon_timeout', `${request.operation} timed out`));
140
+ } catch (error) { finish(error); } finally { polling = false; }
141
+ })();
142
+ return pollFlight;
143
+ };
144
+ const timer = setInterval(poll, Math.max(1, Math.min(100, (timeoutMs ?? 400) / 4)));
145
+ client.setEncoding('utf8'); client.on('connect', () => client.write(`${JSON.stringify(request)}\n`));
146
+ const lost = error => { if (durable) { disconnected = true; clock ??= new ObservationClock({timeoutMs: timeoutMs ?? 30_000,saved:savedClock}); void poll(); } else void reconcile(error); };
147
+ client.on('error', error => lost(fault('daemon_not_running', error.message)));
148
+ client.on('end', () => lost(fault('daemon_connection_closed', 'daemon closed before reply')));
149
+ client.on('close', () => lost(fault('daemon_connection_closed', 'daemon closed before reply')));
150
+ client.on('data', chunk => { void (async () => {
151
+ buffer += chunk; if (!retainNativeReplyBuffer(buffer, finish)) return;
152
+ const at = buffer.indexOf('\n'); if (at < 0) return;
153
+ try {
154
+ const response = JSON.parse(buffer.slice(0, at));
155
+ if (response.schema_id !== responseSchema || response.id !== request.id) throw fault('operation_observation_lost', 'daemon reply identity mismatch');
156
+ if (!response.ok) return finish(Object.assign(new Error(response.error?.message ?? 'daemon operation failed'), response.error));
157
+ if (durable && (binding.owner_id && !response.result?.settlement || response.result?.settlement && !['settled','not_required'].includes(response.result.settlement.state))) { disconnected = true; clock ??= new ObservationClock({timeoutMs:savedClock?.timeout_ms ?? timeoutMs ?? 30_000,saved:savedClock}); void poll(); return; }
158
+ if (durable) { const retained=await retainedDaemonReply(stateDir,request.id,bound()); if(retained) { if(retained.ready) return finish(null,retained.value); disconnected=true; clock ??= new ObservationClock({timeoutMs:timeoutMs ?? 30_000,saved:savedClock}); void poll(); return; } return void reconcile(fault('operation_observation_lost','productive native reply has no durable original receipt')); }
159
+ finish(null, response.result);
160
+ } catch (error) { void reconcile(error.code ? error : Object.assign(fault('operation_observation_lost', 'daemon reply could not be decoded', {native_outcome:'unknown'}), {cause:error})); }
161
+ })(); });
162
+ });
163
+ }
@@ -0,0 +1,2 @@
1
+ export function inspectDaemonOperation(root: string, id: string): Promise<Record<string, unknown>>;
2
+ export function validateNativeLaunchEnvironment(value: unknown): Record<string, string | null>;