@danceiny/gotry 0.0.1-rc.9 → 0.2.0-rc.28

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 (533) hide show
  1. package/README.md +172 -219
  2. package/README.zh-CN.md +222 -0
  3. package/bin/gotry-backend.js +53 -0
  4. package/bin/gotry-booking-copilot.js +53 -0
  5. package/bin/gotry-bootstrap.js +1788 -0
  6. package/bin/gotry-inner.js +733 -83
  7. package/bin/gotry-process-liveness.d.ts +27 -0
  8. package/bin/gotry-process-liveness.js +97 -0
  9. package/bin/gotry-runtime-resolution.d.ts +27 -0
  10. package/bin/gotry-runtime-resolution.js +49 -0
  11. package/bin/gotry.js +1 -1
  12. package/client/client.js +203 -0
  13. package/cordis.gotry-patch.yml +80 -56
  14. package/data/airline-airports.json +39 -0
  15. package/data/stations-12306-verify.json +524 -0
  16. package/dist/capabilities/agent-reach-deep.js +45 -122
  17. package/dist/capabilities/agent-reach.js +101 -146
  18. package/dist/capabilities/anything.js +161 -94
  19. package/dist/capabilities/artifacts.js +370 -0
  20. package/dist/capabilities/channel-health.js +131 -0
  21. package/dist/capabilities/channel-registry.js +256 -0
  22. package/dist/capabilities/doctor.js +553 -0
  23. package/dist/capabilities/effect.js +394 -0
  24. package/dist/capabilities/external-event.js +149 -0
  25. package/dist/capabilities/fact-log.js +55 -0
  26. package/dist/capabilities/flyai-config.js +337 -0
  27. package/dist/capabilities/flyai.js +947 -110
  28. package/dist/capabilities/fx-contract.js +293 -0
  29. package/dist/capabilities/geo-atlas.js +246 -0
  30. package/dist/capabilities/ground-transfer.js +676 -0
  31. package/dist/capabilities/hbcli.js +260 -123
  32. package/dist/capabilities/hotelbyte-transaction.js +194 -0
  33. package/dist/capabilities/incident-log.js +131 -61
  34. package/dist/capabilities/itinerary-artifact.js +190 -0
  35. package/dist/capabilities/itinerary-deck-artifact.js +194 -0
  36. package/dist/capabilities/itinerary-deck-export.js +339 -0
  37. package/dist/capabilities/lavish-local.js +924 -0
  38. package/dist/capabilities/model-override.js +38 -0
  39. package/dist/capabilities/opensky.js +54 -43
  40. package/dist/capabilities/provider-detail-sanitize.js +64 -0
  41. package/dist/capabilities/resilience.js +191 -0
  42. package/dist/capabilities/route-provider-conformance.js +341 -0
  43. package/dist/capabilities/session/action-cache.js +50 -44
  44. package/dist/capabilities/session/adapters/ctrip-flight.js +120 -62
  45. package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
  46. package/dist/capabilities/session/adapters/dida-portal.js +274 -0
  47. package/dist/capabilities/session/adapters/meituan-local.js +35 -54
  48. package/dist/capabilities/session/adapters/rail-12306.js +342 -0
  49. package/dist/capabilities/session/benchmark.js +189 -0
  50. package/dist/capabilities/session/bridge-ledger.js +224 -0
  51. package/dist/capabilities/session/extension-bridge.js +636 -0
  52. package/dist/capabilities/session/extension-channel.js +109 -0
  53. package/dist/capabilities/session/extension-distribution.js +230 -0
  54. package/dist/capabilities/session/extract.js +31 -21
  55. package/dist/capabilities/session/golden-score.js +114 -0
  56. package/dist/capabilities/session/health-watch.js +215 -0
  57. package/dist/capabilities/session/read-guard.js +75 -24
  58. package/dist/capabilities/session/static-flight-golden.js +150 -0
  59. package/dist/capabilities/session/transport.js +97 -83
  60. package/dist/capabilities/session/wizard.js +117 -0
  61. package/dist/capabilities/session-consent.js +178 -0
  62. package/dist/capabilities/session-login.js +170 -0
  63. package/dist/capabilities/session-search.js +635 -44
  64. package/dist/capabilities/spawn-bounded.js +203 -0
  65. package/dist/capabilities/sponsor-plugin.js +341 -0
  66. package/dist/capabilities/visa-policy.js +140 -0
  67. package/dist/capabilities/weather.js +243 -138
  68. package/dist/data/session-golden-20.json +25 -0
  69. package/dist/data/sf-golden-manifest.json +103 -0
  70. package/dist/data/sf-static-routes.json +91 -0
  71. package/dist/scripts/action-cache-tests.js +24 -59
  72. package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
  73. package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
  74. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  75. package/dist/scripts/agent-reach-error-tests.js +354 -0
  76. package/dist/scripts/agent-reach-tests.js +26 -18
  77. package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
  78. package/dist/scripts/anything-path-measure-tests.js +133 -0
  79. package/dist/scripts/anything-path-measure.js +150 -0
  80. package/dist/scripts/anything-tests.js +250 -60
  81. package/dist/scripts/artifact-client-contract-tests.js +220 -0
  82. package/dist/scripts/artifacts-capability-tests.js +727 -0
  83. package/dist/scripts/async-collect.js +50 -11
  84. package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
  85. package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
  86. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
  87. package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
  88. package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
  89. package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
  90. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
  91. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
  92. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
  93. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
  94. package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
  95. package/dist/scripts/booking-copilot-dsh-warmer-proof.js +126 -0
  96. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
  97. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
  98. package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
  99. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
  100. package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
  101. package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
  102. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
  103. package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
  104. package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
  105. package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
  106. package/dist/scripts/booking-executor-tests.js +80 -0
  107. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  108. package/dist/scripts/booking-saga-tests.js +125 -0
  109. package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
  110. package/dist/scripts/bootstrap-tests.js +1549 -0
  111. package/dist/scripts/bridge-events-tests.js +239 -0
  112. package/dist/scripts/bridge-ledger-tests.js +428 -0
  113. package/dist/scripts/build-changelog.js +238 -0
  114. package/dist/scripts/build-metrics-report.js +331 -0
  115. package/dist/scripts/changelog-tests.js +118 -0
  116. package/dist/scripts/channel-probe-tests.js +103 -0
  117. package/dist/scripts/channel-probe.js +169 -0
  118. package/dist/scripts/channel-registry-tests.js +208 -0
  119. package/dist/scripts/city-scenario-tier-tests.js +234 -0
  120. package/dist/scripts/companion-tests.js +25 -70
  121. package/dist/scripts/dida-cookie-probe.js +87 -0
  122. package/dist/scripts/dida-runner-stop-tests.js +311 -0
  123. package/dist/scripts/dida-sw-probe.js +114 -0
  124. package/dist/scripts/diff-test.js +17 -12
  125. package/dist/scripts/doctor-tests.js +600 -0
  126. package/dist/scripts/drill-multiuser-ledger-tests.js +1076 -0
  127. package/dist/scripts/drill-sdk-descendant-cleanup-tests.js +606 -0
  128. package/dist/scripts/drill-w2a-sensor-tests.js +788 -0
  129. package/dist/scripts/dsh-artifact-e2e.js +279 -0
  130. package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
  131. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  132. package/dist/scripts/dsh-llm-tests.js +437 -0
  133. package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
  134. package/dist/scripts/dsh-runtime-closure.js +162 -0
  135. package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
  136. package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
  137. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  138. package/dist/scripts/effect-tests.js +539 -0
  139. package/dist/scripts/engine-run.js +1 -3
  140. package/dist/scripts/engine-tests.js +16 -10
  141. package/dist/scripts/evaluation-cadence-tests.js +174 -0
  142. package/dist/scripts/evaluation-contract-tests.js +268 -0
  143. package/dist/scripts/extension-distribution-cli.js +39 -0
  144. package/dist/scripts/extension-distribution-tests.js +443 -0
  145. package/dist/scripts/extension-tests.js +988 -0
  146. package/dist/scripts/external-event-tests.js +350 -0
  147. package/dist/scripts/fact-gate-tests.js +869 -0
  148. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  149. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  150. package/dist/scripts/flight-malformed-tests.js +159 -0
  151. package/dist/scripts/flyai-setup-tests.js +228 -0
  152. package/dist/scripts/flyai-setup-tool-tests.js +54 -0
  153. package/dist/scripts/flyai-tests.js +692 -0
  154. package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
  155. package/dist/scripts/fx-contract-tests.js +201 -0
  156. package/dist/scripts/g5-guard-tests.js +150 -0
  157. package/dist/scripts/g5-guard.js +193 -0
  158. package/dist/scripts/gen-lunar-anchors.js +106 -0
  159. package/dist/scripts/geo-atlas-tests.js +283 -0
  160. package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
  161. package/dist/scripts/gotry-try-demo-tests.js +79 -0
  162. package/dist/scripts/gotry-try-demo.js +49 -0
  163. package/dist/scripts/ground-transfer-tests.js +956 -0
  164. package/dist/scripts/hbcli-e2e-tests.js +159 -0
  165. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  166. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  167. package/dist/scripts/hbcli-tests.js +121 -69
  168. package/dist/scripts/health-watch-cli.js +73 -0
  169. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  170. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  171. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  172. package/dist/scripts/i18n-tests.js +41 -0
  173. package/dist/scripts/incident-tests.js +281 -87
  174. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  175. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  176. package/dist/scripts/issue-271-liveness-tests.js +569 -0
  177. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  178. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  179. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  180. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  181. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  182. package/dist/scripts/issue436-persisted-routing-e2e.js +247 -0
  183. package/dist/scripts/itinerary-artifact-tests.js +368 -0
  184. package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
  185. package/dist/scripts/itinerary-deck-export-tests.js +552 -0
  186. package/dist/scripts/itinerary-deck-tests.js +435 -0
  187. package/dist/scripts/itinerary-html-tests.js +426 -0
  188. package/dist/scripts/journey-tests.js +22 -27
  189. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  190. package/dist/scripts/kernel-manifest-gate.js +126 -0
  191. package/dist/scripts/kernel-manifest-tests.js +212 -0
  192. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  193. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  194. package/dist/scripts/kernel-manifest.js +369 -0
  195. package/dist/scripts/lavish-local-tests.js +1226 -0
  196. package/dist/scripts/lavish-product-tools-tests.js +537 -0
  197. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  198. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  199. package/dist/scripts/ledger-tests.js +382 -246
  200. package/dist/scripts/ledger-workflow-crash.js +10 -20
  201. package/dist/scripts/m3-cohort-tests.js +714 -0
  202. package/dist/scripts/m3-cohort.js +310 -0
  203. package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
  204. package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
  205. package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
  206. package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
  207. package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
  208. package/dist/scripts/memory-capture-tests.js +242 -61
  209. package/dist/scripts/memory-decay-tests.js +18 -52
  210. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  211. package/dist/scripts/memory-lifecycle.js +196 -0
  212. package/dist/scripts/memory-metrics.js +24 -12
  213. package/dist/scripts/memory-value-report.js +631 -0
  214. package/dist/scripts/memory-value-tests.js +328 -0
  215. package/dist/scripts/metrics-report-tests.js +151 -0
  216. package/dist/scripts/model-override-e2e.js +137 -0
  217. package/dist/scripts/nightly-evidence-tests.js +203 -0
  218. package/dist/scripts/nightly-evidence.js +303 -0
  219. package/dist/scripts/nudge-digest.js +39 -28
  220. package/dist/scripts/observability-tests.js +381 -0
  221. package/dist/scripts/onboarding-tests.js +161 -0
  222. package/dist/scripts/opensky-check.js +18 -13
  223. package/dist/scripts/opensky-tests.js +28 -28
  224. package/dist/scripts/outcome-projection-tests.js +427 -0
  225. package/dist/scripts/persona-sim-tests.js +603 -0
  226. package/dist/scripts/persona-sim.js +1081 -0
  227. package/dist/scripts/persona-surface-guard-tests.js +49 -0
  228. package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
  229. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  230. package/dist/scripts/price-drift-tests.js +340 -0
  231. package/dist/scripts/price-drift-watch.js +447 -0
  232. package/dist/scripts/probe-poi-tests.js +53 -45
  233. package/dist/scripts/product-metrics.js +483 -0
  234. package/dist/scripts/publish-preverify.js +110 -0
  235. package/dist/scripts/realtime-pricing-tests.js +76 -0
  236. package/dist/scripts/recall-tests.js +513 -0
  237. package/dist/scripts/replay-async.js +22 -18
  238. package/dist/scripts/replay-real.js +18 -18
  239. package/dist/scripts/replay.js +54 -82
  240. package/dist/scripts/route-provider-conformance-tests.js +391 -0
  241. package/dist/scripts/session-attach-diagnose.js +20 -20
  242. package/dist/scripts/session-attach-poc.js +34 -37
  243. package/dist/scripts/session-benchmark.js +180 -0
  244. package/dist/scripts/session-dida-live-e2e.js +199 -0
  245. package/dist/scripts/session-extract-tests.js +14 -35
  246. package/dist/scripts/session-link-tests.js +478 -0
  247. package/dist/scripts/session-login.js +27 -46
  248. package/dist/scripts/session-tests.js +796 -96
  249. package/dist/scripts/session-zone-crash.js +49 -0
  250. package/dist/scripts/session-zone-ledger-tests.js +432 -0
  251. package/dist/scripts/session-zone-observation-tests.js +492 -0
  252. package/dist/scripts/session-zone-observe.js +135 -0
  253. package/dist/scripts/session-zone-wiring-tests.js +566 -0
  254. package/dist/scripts/session-zones-tests.js +374 -0
  255. package/dist/scripts/sf-live-benchmark.js +367 -0
  256. package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
  257. package/dist/scripts/sf-live-cli-tests.js +92 -0
  258. package/dist/scripts/sf-live-options.js +46 -0
  259. package/dist/scripts/sf-manifest-tests.js +30 -0
  260. package/dist/scripts/sf-manifest.js +33 -0
  261. package/dist/scripts/sf-soft-score-tests.js +67 -0
  262. package/dist/scripts/sf-summary-tests.js +324 -0
  263. package/dist/scripts/sf-summary.js +525 -0
  264. package/dist/scripts/share-tests.js +432 -0
  265. package/dist/scripts/skeleton-check.js +16 -14
  266. package/dist/scripts/skeleton-integration-test.js +28 -11
  267. package/dist/scripts/skills-contract-tests.js +51 -46
  268. package/dist/scripts/smoke-session-gate-tests.js +21 -0
  269. package/dist/scripts/smoke.js +690 -246
  270. package/dist/scripts/spawn-bounded-abort-tests.js +244 -0
  271. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  272. package/dist/scripts/state-cli-tests.js +226 -101
  273. package/dist/scripts/state-cli.js +565 -198
  274. package/dist/scripts/state-repair-cli.js +66 -0
  275. package/dist/scripts/state-repair-tests.js +140 -0
  276. package/dist/scripts/static-golden-tests.js +165 -0
  277. package/dist/scripts/time-eval-tests.js +212 -192
  278. package/dist/scripts/travel-timeline-tests.js +29 -93
  279. package/dist/scripts/turn-handoff-collect-tests.js +169 -0
  280. package/dist/scripts/turn-handoff-collect.js +161 -0
  281. package/dist/scripts/turn-policy-tests.js +55 -0
  282. package/dist/scripts/typed-contract-canary.js +176 -0
  283. package/dist/scripts/tz-resolver-sanity.js +50 -0
  284. package/dist/scripts/tz-resolver-tests.js +584 -0
  285. package/dist/scripts/unified-tests.js +60 -20
  286. package/dist/scripts/visa-policy-tests.js +62 -0
  287. package/dist/scripts/weather-tests.js +276 -41
  288. package/dist/scripts/wish-channel-gate-tests.js +54 -0
  289. package/dist/scripts/write-gate-tests.js +522 -0
  290. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  291. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  292. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  293. package/dist/scripts/z3-race-tests.js +46 -0
  294. package/dist/src/artifact-gate.js +829 -0
  295. package/dist/src/backend/kernel.js +91 -0
  296. package/dist/src/backend/modules/booking-copilot.js +92 -0
  297. package/dist/src/backend/modules/booking-executor.js +124 -0
  298. package/dist/src/backend/modules/session-search.js +551 -0
  299. package/dist/src/benchmark-agent-conformance.js +578 -0
  300. package/dist/src/benchmark-environment-bridge.js +515 -0
  301. package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
  302. package/dist/src/benchmark-tool-isolation.js +151 -0
  303. package/dist/src/bookable-facts.js +533 -0
  304. package/dist/src/booking-saga.js +97 -0
  305. package/dist/src/booking-surface/availability-policy.js +697 -0
  306. package/dist/src/booking-surface/booking-intent.js +43 -0
  307. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  308. package/dist/src/booking-surface/canonical-schema.js +116 -0
  309. package/dist/src/booking-surface/contracts.js +75 -0
  310. package/dist/src/booking-surface/dsh-planner.js +1854 -0
  311. package/dist/src/booking-surface/dsh-plugin.js +378 -0
  312. package/dist/src/booking-surface/dsh-worker.js +98 -0
  313. package/dist/src/booking-surface/error-codes.js +231 -0
  314. package/dist/src/booking-surface/index.js +9 -0
  315. package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
  316. package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
  317. package/dist/src/booking-surface/profile.js +24 -0
  318. package/dist/src/booking-surface/recovery-chain.js +367 -0
  319. package/dist/src/booking-surface/runtime.js +1968 -0
  320. package/dist/src/booking-surface/server.js +674 -0
  321. package/dist/src/booking-surface/startup.js +168 -0
  322. package/dist/src/booking-surface/validation.js +261 -0
  323. package/dist/src/bridge.js +20 -13
  324. package/dist/src/city-scenario-tier.js +378 -0
  325. package/dist/src/companions.js +48 -74
  326. package/dist/src/contracts.js +21 -43
  327. package/dist/src/dsh-llm.js +171 -115
  328. package/dist/src/engine.js +276 -193
  329. package/dist/src/evaluation-cadence.js +97 -0
  330. package/dist/src/evaluation-contracts.js +283 -0
  331. package/dist/src/flight-pack-adapter.js +54 -0
  332. package/dist/src/flight-pack-contract.js +2 -0
  333. package/dist/src/flyai-setup-tool.js +70 -0
  334. package/dist/src/gotry-backend.js +125 -0
  335. package/dist/src/hotel-date-gate.js +118 -0
  336. package/dist/src/i18n.js +88 -0
  337. package/dist/src/index.js +2385 -881
  338. package/dist/src/itinerary-deck.js +139 -0
  339. package/dist/src/itinerary-doc-shared.js +661 -0
  340. package/dist/src/itinerary-html.js +131 -0
  341. package/dist/src/journey.js +155 -108
  342. package/dist/src/lavish-tools.js +400 -0
  343. package/dist/src/ledger-repair-apply.js +538 -0
  344. package/dist/src/ledger-repair-plan.js +463 -0
  345. package/dist/src/loop.js +331 -161
  346. package/dist/src/m3-cohort.js +1577 -0
  347. package/dist/src/memory-capture.js +180 -32
  348. package/dist/src/memory-decay.js +30 -14
  349. package/dist/src/memory-lifecycle.js +1310 -0
  350. package/dist/src/memory-utility.js +27 -40
  351. package/dist/src/mock-llm.js +36 -61
  352. package/dist/src/model.js +81 -36
  353. package/dist/src/outcome-projection.js +746 -0
  354. package/dist/src/realtime-pricing.js +103 -0
  355. package/dist/src/recall/card.js +74 -0
  356. package/dist/src/recall/evaluator.js +140 -0
  357. package/dist/src/recall/integration.js +17 -0
  358. package/dist/src/recall/tick.js +166 -0
  359. package/dist/src/session-link/plan-it-action.js +48 -0
  360. package/dist/src/session-link/session-link.js +248 -0
  361. package/dist/src/session-zone-ledger.js +312 -0
  362. package/dist/src/session-zone-observation.js +354 -0
  363. package/dist/src/session-zone-wiring.js +658 -0
  364. package/dist/src/session-zones.js +510 -0
  365. package/dist/src/share/adapters.js +51 -0
  366. package/dist/src/share/share-consent.js +76 -0
  367. package/dist/src/share/share-deck.js +58 -0
  368. package/dist/src/share/share-token.js +146 -0
  369. package/dist/src/slot-spec.js +84 -106
  370. package/dist/src/state-ledger.js +696 -524
  371. package/dist/src/state-repair.js +299 -0
  372. package/dist/src/subagent-job-id-guard.js +58 -0
  373. package/dist/src/time-anchor.js +231 -33
  374. package/dist/src/tool-packet.js +20 -8
  375. package/dist/src/travel-slots.js +58 -35
  376. package/dist/src/travel-timeline.js +44 -63
  377. package/dist/src/turn-deadline.js +287 -0
  378. package/dist/src/turn-policy.js +118 -0
  379. package/dist/src/tz-resolver.js +143 -0
  380. package/dist/src/unified.js +600 -360
  381. package/dist/src/wish-pool.js +42 -12
  382. package/dist/src/write-gate.js +495 -0
  383. package/dist/src/z3-shared.js +284 -0
  384. package/extension/README.md +21 -0
  385. package/extension/README.zh-CN.md +21 -0
  386. package/extension/background.js +463 -0
  387. package/extension/content-bridge.js +270 -0
  388. package/extension/content-main.js +111 -0
  389. package/extension/manifest.json +60 -0
  390. package/package.json +407 -14
  391. package/schemas/booking.intent.schema.json +193 -0
  392. package/schemas/booking.surface.schema.json +2622 -0
  393. package/ts/capabilities/agent-reach-deep.ts +114 -0
  394. package/ts/capabilities/agent-reach.ts +198 -0
  395. package/ts/capabilities/anything.ts +282 -0
  396. package/ts/capabilities/artifacts.ts +428 -0
  397. package/ts/capabilities/fact-log.ts +54 -0
  398. package/ts/capabilities/flyai-config.ts +388 -0
  399. package/ts/capabilities/flyai.ts +1274 -0
  400. package/ts/capabilities/hbcli.ts +253 -71
  401. package/ts/capabilities/incident-log.ts +88 -59
  402. package/ts/capabilities/itinerary-artifact.ts +214 -0
  403. package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
  404. package/ts/capabilities/itinerary-deck-export.ts +378 -0
  405. package/ts/capabilities/opensky.ts +121 -0
  406. package/ts/capabilities/session/action-cache.ts +148 -0
  407. package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
  408. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  409. package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
  410. package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
  411. package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
  412. package/ts/capabilities/session/benchmark.ts +276 -0
  413. package/ts/capabilities/session/bridge-ledger.ts +333 -0
  414. package/ts/capabilities/session/extension-bridge.ts +794 -0
  415. package/ts/capabilities/session/extension-channel.ts +144 -0
  416. package/ts/capabilities/session/extension-distribution.ts +266 -0
  417. package/ts/capabilities/session/extract.ts +54 -0
  418. package/ts/capabilities/session/golden-score.ts +139 -0
  419. package/ts/capabilities/session/health-watch.ts +264 -0
  420. package/ts/capabilities/session/read-guard.ts +141 -0
  421. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  422. package/ts/capabilities/session/transport.ts +146 -0
  423. package/ts/capabilities/session/wizard.ts +140 -0
  424. package/ts/capabilities/session-consent.ts +211 -0
  425. package/ts/capabilities/session-login.ts +208 -0
  426. package/ts/capabilities/session-search.ts +893 -0
  427. package/ts/capabilities/weather.ts +330 -0
  428. package/ts/dsh-runtime/vendor/README.md +68 -0
  429. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  430. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
  431. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
  432. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
  433. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  434. package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
  435. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
  436. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  437. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
  438. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  439. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  440. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
  441. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  442. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
  443. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
  444. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
  445. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
  446. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  447. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  448. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
  449. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
  450. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  451. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  452. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  453. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  454. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
  455. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  456. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
  457. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  458. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  459. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
  460. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  461. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  462. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
  463. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
  464. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  465. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
  466. package/ts/package.json +293 -3
  467. package/ts/scripts/async-collect.ts +91 -0
  468. package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
  469. package/ts/scripts/skeleton-check.ts +1 -1
  470. package/ts/scripts/skeleton-integration-test.ts +23 -1
  471. package/ts/scripts/state-cli.ts +586 -0
  472. package/ts/scripts/turn-handoff-collect.ts +178 -0
  473. package/ts/src/artifact-gate.ts +991 -0
  474. package/ts/src/benchmark-agent-conformance.ts +619 -0
  475. package/ts/src/benchmark-environment-bridge.ts +538 -0
  476. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  477. package/ts/src/benchmark-tool-isolation.ts +166 -0
  478. package/ts/src/bookable-facts.ts +837 -0
  479. package/ts/src/booking-saga.ts +133 -0
  480. package/ts/src/booking-surface/availability-policy.ts +522 -0
  481. package/ts/src/booking-surface/booking-intent.ts +86 -0
  482. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  483. package/ts/src/booking-surface/canonical-schema.js +116 -0
  484. package/ts/src/booking-surface/contracts.ts +475 -0
  485. package/ts/src/booking-surface/dsh-planner.ts +1949 -0
  486. package/ts/src/booking-surface/dsh-plugin.js +378 -0
  487. package/ts/src/booking-surface/dsh-worker.ts +110 -0
  488. package/ts/src/booking-surface/error-codes.ts +241 -0
  489. package/ts/src/booking-surface/index.ts +9 -0
  490. package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
  491. package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
  492. package/ts/src/booking-surface/profile.ts +42 -0
  493. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  494. package/ts/src/booking-surface/runtime.ts +1793 -0
  495. package/ts/src/booking-surface/server.ts +733 -0
  496. package/ts/src/booking-surface/startup.ts +201 -0
  497. package/ts/src/booking-surface/validation.ts +217 -0
  498. package/ts/src/companions.ts +113 -0
  499. package/ts/src/contracts.ts +17 -3
  500. package/ts/src/dsh-llm.ts +152 -17
  501. package/ts/src/flyai-setup-tool.ts +77 -0
  502. package/ts/src/index.ts +2123 -200
  503. package/ts/src/itinerary-deck.ts +189 -0
  504. package/ts/src/itinerary-doc-shared.ts +741 -0
  505. package/ts/src/itinerary-html.ts +171 -0
  506. package/ts/src/loop.ts +234 -26
  507. package/ts/src/memory-capture.ts +283 -0
  508. package/ts/src/memory-decay.ts +55 -0
  509. package/ts/src/memory-utility.ts +70 -0
  510. package/ts/src/mock-llm.ts +4 -8
  511. package/ts/src/model.ts +88 -2
  512. package/ts/src/recall/card.ts +106 -0
  513. package/ts/src/recall/evaluator.ts +170 -0
  514. package/ts/src/recall/integration.ts +35 -0
  515. package/ts/src/recall/tick.ts +213 -0
  516. package/ts/src/session-link/plan-it-action.ts +78 -0
  517. package/ts/src/session-link/session-link.ts +275 -0
  518. package/ts/src/share/adapters.ts +93 -0
  519. package/ts/src/share/share-consent.ts +105 -0
  520. package/ts/src/share/share-deck.ts +85 -0
  521. package/ts/src/share/share-token.ts +166 -0
  522. package/ts/src/slot-spec.ts +172 -0
  523. package/ts/src/state-ledger.ts +1166 -0
  524. package/ts/src/subagent-job-id-guard.ts +72 -0
  525. package/ts/src/time-anchor.ts +338 -0
  526. package/ts/src/tool-packet.ts +32 -0
  527. package/ts/src/travel-slots.ts +219 -0
  528. package/ts/src/travel-timeline.ts +83 -0
  529. package/ts/src/turn-deadline.ts +366 -0
  530. package/ts/src/turn-policy.ts +154 -0
  531. package/ts/src/unified.ts +444 -105
  532. package/ts/src/wish-pool.ts +79 -0
  533. package/dist/scripts/session-attach-wait.js +0 -41
@@ -0,0 +1,241 @@
1
+ /** Closed, non-sensitive error vocabulary for planner/runtime boundaries. */
2
+ export const BOOKING_TYPED_ERROR_CODES = [
3
+ 'PAYLOAD_TOO_LARGE',
4
+ 'TASK_NOT_FOUND',
5
+ 'TASK_TERMINAL',
6
+ 'RECEIPT_REQUIRED',
7
+ 'RECEIPT_CONFLICT',
8
+ 'UNSUPPORTED_ACTION',
9
+ 'PLANNER_SURFACE_ACTION_UNSUPPORTED',
10
+ 'PLANNER_NO_DECISION',
11
+ 'PLANNER_TYPED_DECISION_REQUIRED',
12
+ 'PLANNER_PROVIDER_AUTH_FAILED',
13
+ 'PLANNER_PROVIDER_QUOTA_EXHAUSTED',
14
+ 'PLANNER_PROVIDER_RATE_LIMITED',
15
+ 'PLANNER_PROVIDER_UNAVAILABLE',
16
+ 'PLANNER_PROVIDER_REQUEST_REJECTED',
17
+ 'PLANNER_PROVIDER_RESPONSE_INVALID',
18
+ 'PLANNER_PROVIDER_TIMEOUT',
19
+ 'PLANNER_BOOT_TIMEOUT',
20
+ 'PLANNER_CONFIGURATION_INVALID',
21
+ 'PLANNER_FAILED',
22
+ 'INVALID_ACTION',
23
+ 'INVALID_EVENT',
24
+ 'CONTEXT_MISMATCH',
25
+ 'WORKSPACE_MISMATCH',
26
+ 'ACTION_CONFLICT',
27
+ 'STALE_REVISION',
28
+ 'OPERATION_LIMIT_REACHED',
29
+ 'AVAILABILITY_TERMINAL_POLICY_OWNED',
30
+ 'TRUSTED_INGRESS_BINDING_REQUIRED',
31
+ 'INVALID_INGRESS_BINDING',
32
+ 'BOOKING_SURFACE_SCHEMA_MISMATCH',
33
+ 'UNAUTHORIZED',
34
+ 'NOT_FOUND',
35
+ ] as const
36
+
37
+ export type BookingTypedErrorCode = typeof BOOKING_TYPED_ERROR_CODES[number]
38
+
39
+ /** Exact, closed reasons safe to expose in dispatch diagnostics. */
40
+ export const BOOKING_DISPATCH_REJECTION_REASONS = [
41
+ 'approval_expired',
42
+ 'approval_mismatch',
43
+ 'approval_not_awaiting',
44
+ 'approval_not_presented',
45
+ 'approval_replayed',
46
+ 'approval_required',
47
+ 'availability_attempt_mismatch',
48
+ 'availability_attempt_unknown',
49
+ 'availability_criteria_changed',
50
+ 'availability_criteria_invalid',
51
+ 'availability_criteria_mismatch',
52
+ 'availability_criteria_required',
53
+ 'availability_duplicate_offer_ref',
54
+ 'availability_duplicate_offer_version_ref',
55
+ 'availability_expected_revision_missing',
56
+ 'availability_generation_mismatch',
57
+ 'availability_hotel_limit_exceeded',
58
+ 'availability_hotel_not_active',
59
+ 'availability_hotel_unknown',
60
+ 'availability_observation_required',
61
+ 'availability_offer_limit_exceeded',
62
+ 'availability_offers_count_mismatch',
63
+ 'availability_offers_hotel_mismatch',
64
+ 'availability_offers_observation_required',
65
+ 'availability_offers_receipt_incoherent',
66
+ 'availability_offers_unreported',
67
+ 'availability_offers_workspace_mismatch',
68
+ 'availability_query_not_reserved',
69
+ 'availability_query_provenance_mismatch',
70
+ 'availability_query_receipt_mismatch',
71
+ 'availability_receipt_digest_mismatch',
72
+ 'availability_receipt_incoherent',
73
+ 'availability_stale_receipt',
74
+ 'availability_terminal',
75
+ 'booking_malformed_workspace',
76
+ 'context_mismatch',
77
+ 'invalid_task_id',
78
+ 'receipt_action_mismatch',
79
+ 'receipt_conflict',
80
+ 'receipt_observation_action_mismatch',
81
+ 'receipt_relaxation_unauthorized',
82
+ 'receipt_required',
83
+ 'receipt_source_action_mismatch',
84
+ 'receipt_source_digest_mismatch',
85
+ 'receipt_target_mismatch',
86
+ 'receipt_verified_offer_expired',
87
+ 'reanchor_turn_required',
88
+ 'request_conflict',
89
+ 'request_key_invalidated',
90
+ 'revision_mismatch',
91
+ 'revision_regression',
92
+ 'task_not_found',
93
+ 'task_terminal',
94
+ 'turn_conflict',
95
+ 'unexpected_receipt',
96
+ 'unsafe_opaque_ref',
97
+ 'workspace_mismatch',
98
+ ] as const
99
+
100
+ export type BookingDispatchRejectionReason = typeof BOOKING_DISPATCH_REJECTION_REASONS[number]
101
+ export const BOOKING_DISPATCH_UNKNOWN_REASON = 'UNCLASSIFIED' as const
102
+ export type BookingDispatchLogReason = BookingDispatchRejectionReason | typeof BOOKING_DISPATCH_UNKNOWN_REASON
103
+
104
+ const DISPATCH_REJECTION_REASON_SET = new Set<string>(BOOKING_DISPATCH_REJECTION_REASONS)
105
+
106
+ /** Returns a reason only when the complete boundary error is one known token. */
107
+ export function extractBookingDispatchReason(error: unknown): BookingDispatchLogReason {
108
+ const message = typeof error === 'string' ? error : error instanceof Error ? error.message : undefined
109
+ return message !== undefined && DISPATCH_REJECTION_REASON_SET.has(message)
110
+ ? message as BookingDispatchRejectionReason
111
+ : BOOKING_DISPATCH_UNKNOWN_REASON
112
+ }
113
+
114
+ const ALIASES: Record<string, BookingTypedErrorCode> = {
115
+ payload_too_large: 'PAYLOAD_TOO_LARGE',
116
+ task_not_found: 'TASK_NOT_FOUND',
117
+ task_terminal: 'TASK_TERMINAL',
118
+ receipt_required: 'RECEIPT_REQUIRED',
119
+ receipt_conflict: 'RECEIPT_CONFLICT',
120
+ unsupported_action: 'UNSUPPORTED_ACTION',
121
+ planner_surface_action_unsupported: 'PLANNER_SURFACE_ACTION_UNSUPPORTED',
122
+ planner_no_decision: 'PLANNER_NO_DECISION',
123
+ planner_typed_decision_required: 'PLANNER_TYPED_DECISION_REQUIRED',
124
+ planner_provider_auth_failed: 'PLANNER_PROVIDER_AUTH_FAILED',
125
+ planner_provider_quota_exhausted: 'PLANNER_PROVIDER_QUOTA_EXHAUSTED',
126
+ planner_provider_rate_limited: 'PLANNER_PROVIDER_RATE_LIMITED',
127
+ planner_provider_unavailable: 'PLANNER_PROVIDER_UNAVAILABLE',
128
+ planner_provider_request_rejected: 'PLANNER_PROVIDER_REQUEST_REJECTED',
129
+ planner_provider_response_invalid: 'PLANNER_PROVIDER_RESPONSE_INVALID',
130
+ planner_provider_timeout: 'PLANNER_PROVIDER_TIMEOUT',
131
+ planner_boot_timeout: 'PLANNER_BOOT_TIMEOUT',
132
+ planner_configuration_invalid: 'PLANNER_CONFIGURATION_INVALID',
133
+ planner_failed: 'PLANNER_FAILED',
134
+ planner_invalid_tool_arguments: 'PLANNER_PROVIDER_RESPONSE_INVALID',
135
+ planner_invalid_typed_decision: 'PLANNER_PROVIDER_RESPONSE_INVALID',
136
+ planner_invalid_action: 'PLANNER_PROVIDER_RESPONSE_INVALID',
137
+ planner_booking_intent_required: 'PLANNER_PROVIDER_RESPONSE_INVALID',
138
+ planner_invalid_booking_intent: 'PLANNER_PROVIDER_RESPONSE_INVALID',
139
+ planner_ambiguous_booking_intent: 'PLANNER_PROVIDER_RESPONSE_INVALID',
140
+ planner_multiple_typed_decisions: 'PLANNER_PROVIDER_RESPONSE_INVALID',
141
+ planner_typed_decision_after_candidate: 'PLANNER_PROVIDER_RESPONSE_INVALID',
142
+ planner_typed_decision_missing: 'PLANNER_PROVIDER_RESPONSE_INVALID',
143
+ planner_unresolved_tool_call_before_candidate: 'PLANNER_PROVIDER_RESPONSE_INVALID',
144
+ planner_tool_call_duplicate_call_id: 'PLANNER_PROVIDER_RESPONSE_INVALID',
145
+ planner_tool_call_missing_call_id: 'PLANNER_PROVIDER_RESPONSE_INVALID',
146
+ planner_tool_call_rejected: 'PLANNER_PROVIDER_RESPONSE_INVALID',
147
+ planner_tool_result_malformed: 'PLANNER_PROVIDER_RESPONSE_INVALID',
148
+ planner_tool_result_out_of_order: 'PLANNER_PROVIDER_RESPONSE_INVALID',
149
+ planner_tool_result_unmatched: 'PLANNER_PROVIDER_RESPONSE_INVALID',
150
+ planner_terminal_checkpoint_mismatch: 'PLANNER_PROVIDER_RESPONSE_INVALID',
151
+ planner_terminal_checkpoint_unavailable: 'PLANNER_PROVIDER_RESPONSE_INVALID',
152
+ planner_terminal_intent_criteria_unachieved: 'PLANNER_PROVIDER_RESPONSE_INVALID',
153
+ planner_terminal_intent_target_unachieved: 'PLANNER_PROVIDER_RESPONSE_INVALID',
154
+ planner_terminal_intent_unjustified: 'PLANNER_PROVIDER_RESPONSE_INVALID',
155
+ planner_terminal_search_checkpoint_mismatch: 'PLANNER_PROVIDER_RESPONSE_INVALID',
156
+ planner_terminal_search_patch_not_ready: 'PLANNER_PROVIDER_RESPONSE_INVALID',
157
+ planner_terminal_search_results_not_ready: 'PLANNER_PROVIDER_RESPONSE_INVALID',
158
+ planner_terminal_search_workspace_mismatch: 'PLANNER_PROVIDER_RESPONSE_INVALID',
159
+ planner_forbidden_action: 'UNSUPPORTED_ACTION',
160
+ planner_forbidden_tool: 'UNSUPPORTED_ACTION',
161
+ planner_capability_action_mismatch: 'UNSUPPORTED_ACTION',
162
+ planner_intent_target_unsupported: 'PLANNER_SURFACE_ACTION_UNSUPPORTED',
163
+ planner_context_mismatch: 'CONTEXT_MISMATCH',
164
+ planner_revision_mismatch: 'STALE_REVISION',
165
+ booking_intent_required: 'INVALID_ACTION',
166
+ invalid_booking_intent: 'INVALID_ACTION',
167
+ action_intent_mismatch: 'INVALID_ACTION',
168
+ intent_mutation_forbidden: 'INVALID_ACTION',
169
+ invalid_action: 'INVALID_ACTION',
170
+ invalid_event: 'INVALID_EVENT',
171
+ context_mismatch: 'CONTEXT_MISMATCH',
172
+ workspace_mismatch: 'WORKSPACE_MISMATCH',
173
+ action_conflict: 'ACTION_CONFLICT',
174
+ approval_replayed: 'ACTION_CONFLICT',
175
+ request_conflict: 'ACTION_CONFLICT',
176
+ turn_conflict: 'ACTION_CONFLICT',
177
+ stale_revision: 'STALE_REVISION',
178
+ operation_limit_reached: 'OPERATION_LIMIT_REACHED',
179
+ availability_terminal_policy_owned: 'AVAILABILITY_TERMINAL_POLICY_OWNED',
180
+ trusted_ingress_binding_required: 'TRUSTED_INGRESS_BINDING_REQUIRED',
181
+ invalid_ingress_binding: 'INVALID_INGRESS_BINDING',
182
+ booking_surface_schema_mismatch: 'BOOKING_SURFACE_SCHEMA_MISMATCH',
183
+ unauthorized: 'UNAUTHORIZED',
184
+ not_found: 'NOT_FOUND',
185
+ }
186
+
187
+ const SAFE_MESSAGES: Record<BookingTypedErrorCode, string> = {
188
+ PAYLOAD_TOO_LARGE: 'Request payload exceeds the configured limit.',
189
+ TASK_NOT_FOUND: 'The requested task was not found.',
190
+ TASK_TERMINAL: 'The task is already terminal.',
191
+ RECEIPT_REQUIRED: 'A matching receipt is required before another action.',
192
+ RECEIPT_CONFLICT: 'The receipt conflicts with the durable task record.',
193
+ UNSUPPORTED_ACTION: 'The requested action is outside the trusted action policy.',
194
+ PLANNER_SURFACE_ACTION_UNSUPPORTED: 'The planner action is outside the trusted surface policy.',
195
+ PLANNER_NO_DECISION: 'The planner returned no typed decision.',
196
+ PLANNER_TYPED_DECISION_REQUIRED: 'The planner returned no typed capability decision.',
197
+ PLANNER_PROVIDER_AUTH_FAILED: 'The planner provider rejected authentication.',
198
+ PLANNER_PROVIDER_QUOTA_EXHAUSTED: 'The planner provider quota is exhausted.',
199
+ PLANNER_PROVIDER_RATE_LIMITED: 'The planner provider rate-limited the request.',
200
+ PLANNER_PROVIDER_UNAVAILABLE: 'The planner provider is temporarily unavailable.',
201
+ PLANNER_PROVIDER_REQUEST_REJECTED: 'The planner provider rejected the model request.',
202
+ PLANNER_PROVIDER_RESPONSE_INVALID: 'The planner provider returned an invalid response.',
203
+ PLANNER_PROVIDER_TIMEOUT: 'The planner did not respond within the booking turn deadline.',
204
+ PLANNER_BOOT_TIMEOUT: 'The planner runtime did not finish starting within its local boot budget.',
205
+ PLANNER_CONFIGURATION_INVALID: 'The planner provider configuration is invalid.',
206
+ PLANNER_FAILED: 'The planner stopped unexpectedly before producing a usable action.',
207
+ INVALID_ACTION: 'The planner action failed contract validation.',
208
+ INVALID_EVENT: 'The planner event failed contract validation.',
209
+ CONTEXT_MISMATCH: 'The request context does not match the trusted task.',
210
+ WORKSPACE_MISMATCH: 'The request workspace does not match the trusted task.',
211
+ ACTION_CONFLICT: 'The request conflicts with the durable action checkpoint.',
212
+ STALE_REVISION: 'The request revision is stale.',
213
+ OPERATION_LIMIT_REACHED: 'The task operation limit has been reached.',
214
+ AVAILABILITY_TERMINAL_POLICY_OWNED: 'Availability policy owns the terminal decision.',
215
+ TRUSTED_INGRESS_BINDING_REQUIRED: 'A trusted ingress binding is required.',
216
+ INVALID_INGRESS_BINDING: 'The trusted ingress binding is invalid.',
217
+ BOOKING_SURFACE_SCHEMA_MISMATCH: 'The booking surface schema is not supported.',
218
+ UNAUTHORIZED: 'The request is not authorized.',
219
+ NOT_FOUND: 'The requested resource was not found.',
220
+ }
221
+
222
+ function rawCode(error: unknown): string {
223
+ if (typeof error === 'string') return error.split(':', 1)[0]!
224
+ if (error instanceof Error && error.message) return error.message.split(':', 1)[0]!
225
+ return 'planner_failed'
226
+ }
227
+
228
+ export function normalizeBookingErrorCode(error: unknown): BookingTypedErrorCode {
229
+ const raw = rawCode(error)
230
+ const normalized = raw.trim().toLowerCase()
231
+ const aliased = ALIASES[normalized]
232
+ if (aliased) return aliased
233
+ const uppercase = raw.trim().replace(/[^A-Za-z0-9]+/g, '_').toUpperCase()
234
+ return (BOOKING_TYPED_ERROR_CODES as readonly string[]).includes(uppercase)
235
+ ? uppercase as BookingTypedErrorCode
236
+ : 'PLANNER_FAILED'
237
+ }
238
+
239
+ export function safeBookingErrorMessage(code: string): string {
240
+ return SAFE_MESSAGES[(BOOKING_TYPED_ERROR_CODES as readonly string[]).includes(code) ? code as BookingTypedErrorCode : 'PLANNER_FAILED']
241
+ }
@@ -0,0 +1,9 @@
1
+ export * from './contracts.ts'
2
+ export * from './dsh-planner.ts'
3
+ export * from './profile.ts'
4
+ export * from './runtime.ts'
5
+ export * from './server.ts'
6
+ export * from './startup.ts'
7
+ export * from './validation.ts'
8
+ export * from './availability-policy.ts'
9
+ export * from './booking-intent.ts'
@@ -0,0 +1,151 @@
1
+ import { execFile } from 'node:child_process'
2
+
3
+ export type ManagedDshWorkerOutcome =
4
+ | { state: 'pending' }
5
+ | { state: 'exited'; exitCode: number | null; signal: string | null }
6
+ | { state: 'failed' }
7
+
8
+ export interface ManagedDshGroupMember {
9
+ pid: number
10
+ ppid: number
11
+ pgid: number
12
+ state: string
13
+ /** Read-only `ps lstart` identity evidence; zombies keep their original start time. */
14
+ startedAt: string | null
15
+ zombie: boolean
16
+ }
17
+
18
+ /**
19
+ * `has-live-members`: at least one non-zombie member remains. `zombie-only`:
20
+ * every remaining member is a dead-but-unreaped zombie. `empty`: the group has
21
+ * no visible member. On Darwin the detached-fallback observation
22
+ * (`kill(-pgid, 0)`) cannot distinguish these: it returns EPERM for
23
+ * zombie-only groups, which the runtime maps to "alive".
24
+ */
25
+ export type ManagedDshGroupClassification = 'empty' | 'zombie-only' | 'has-live-members'
26
+
27
+ export interface ManagedDshProcessGroupSnapshot {
28
+ status: 'observed' | 'unavailable' | 'unsupported' | 'unknown_worker'
29
+ expectedPgid: number | null
30
+ members: ManagedDshGroupMember[]
31
+ truncated: boolean
32
+ classification: ManagedDshGroupClassification | null
33
+ liveMemberCount: number | null
34
+ zombieMemberCount: number | null
35
+ /** Start-time anchor captured while the worker was alive, for identity comparison. */
36
+ workerStartedAt: string | null
37
+ workerIdentity: 'match' | 'mismatch' | 'worker-absent' | 'unknown' | null
38
+ }
39
+
40
+ export interface ManagedDshCleanupDiagnostic {
41
+ schemaVersion: 'managed-dsh-cleanup.v2'
42
+ role: 'task' | 'warmer' | 'unspecified'
43
+ workerPid: number | null
44
+ elapsedMs: number
45
+ deadlineMs: number
46
+ graceMs: number
47
+ workerOutcome: ManagedDshWorkerOutcome
48
+ processGroup: ManagedDshProcessGroupSnapshot
49
+ }
50
+
51
+ /** Diagnostics never include argv, environment, provider output or request data. */
52
+ export class ManagedDshCleanupError extends Error {
53
+ constructor(message: string, readonly diagnostic: ManagedDshCleanupDiagnostic) {
54
+ // Keep the safe snapshot visible even when nested AggregateError inspection
55
+ // collapses custom object properties in an uncaught-error log.
56
+ super(`${message}; diagnostic=${JSON.stringify(diagnostic)}`)
57
+ this.name = 'ManagedDshCleanupError'
58
+ }
59
+ }
60
+
61
+ const MEMBER_LINE = /^(\d+)\s+(\d+)\s+(\d+)\s+([A-Za-z+<NsLlEWXU-]+)\s+(.+?)\s*$/
62
+ const MAX_MEMBERS = 32
63
+
64
+ /**
65
+ * Classify one `ps -axo pid=,ppid=,pgid=,stat=,lstart=` table for the owned
66
+ * group. Pure so proofs can feed crafted tables without signalling anything.
67
+ */
68
+ export function parseManagedDshGroupSnapshot(
69
+ stdout: string,
70
+ expectedPgid: number | null,
71
+ workerStartedAt: string | null = null,
72
+ ): ManagedDshProcessGroupSnapshot {
73
+ const empty = {
74
+ status: 'unknown_worker', expectedPgid, members: [], truncated: false, classification: null,
75
+ liveMemberCount: null, zombieMemberCount: null, workerStartedAt, workerIdentity: null,
76
+ } as ManagedDshProcessGroupSnapshot
77
+ if (expectedPgid === null) return { ...empty, status: 'unknown_worker' }
78
+ const members: ManagedDshGroupMember[] = []
79
+ for (const line of stdout.split('\n')) {
80
+ const match = line.trim().match(MEMBER_LINE)
81
+ if (!match || Number(match[3]) !== expectedPgid) continue
82
+ members.push({
83
+ pid: Number(match[1]), ppid: Number(match[2]), pgid: Number(match[3]),
84
+ state: match[4], startedAt: match[5] ?? null, zombie: match[4].startsWith('Z'),
85
+ })
86
+ }
87
+ const liveMemberCount = members.filter((member) => !member.zombie).length
88
+ const zombieMemberCount = members.length - liveMemberCount
89
+ const classification: ManagedDshGroupClassification =
90
+ members.length === 0 ? 'empty' : liveMemberCount === 0 ? 'zombie-only' : 'has-live-members'
91
+ let workerIdentity: ManagedDshProcessGroupSnapshot['workerIdentity'] = 'unknown'
92
+ if (workerStartedAt !== null) {
93
+ const workerRow = members.find((member) => member.pid === expectedPgid)
94
+ workerIdentity = workerRow === undefined
95
+ ? 'worker-absent'
96
+ : workerRow.startedAt === workerStartedAt ? 'match' : 'mismatch'
97
+ }
98
+ return {
99
+ status: 'observed', expectedPgid,
100
+ members: members.slice(0, MAX_MEMBERS), truncated: members.length > MAX_MEMBERS,
101
+ classification, liveMemberCount, zombieMemberCount,
102
+ workerStartedAt, workerIdentity,
103
+ }
104
+ }
105
+
106
+ /** Whether the snapshot proves the owned group holds no live member. */
107
+ export function managedDshGroupIsQuiescent(group: ManagedDshProcessGroupSnapshot): boolean {
108
+ return group.status === 'observed' && (group.classification === 'empty' || group.classification === 'zombie-only')
109
+ }
110
+
111
+ /** Read-only one-shot start-time anchor for the live worker (Darwin only). */
112
+ export function readManagedDshWorkerStart(pid: number): Promise<string | null> {
113
+ if (process.platform !== 'darwin') return Promise.resolve(null)
114
+ return new Promise((resolve) => {
115
+ execFile('/bin/ps', ['-p', String(pid), '-o', 'lstart='], {
116
+ encoding: 'utf8', timeout: 250, maxBuffer: 4096,
117
+ env: { PATH: '/usr/bin:/bin', LC_ALL: 'C' },
118
+ }, (error, stdout) => resolve(error ? null : stdout.trim() || null))
119
+ })
120
+ }
121
+
122
+ /**
123
+ * Observe only the detached worker's group, without signalling any process.
124
+ * Snapshot fields are limited to pid/ppid/pgid/state/start time — never argv,
125
+ * environment, or request content.
126
+ */
127
+ export async function snapshotManagedDshGroup(
128
+ workerPid: number | null,
129
+ workerStartedAt: string | null = null,
130
+ ): Promise<ManagedDshProcessGroupSnapshot> {
131
+ const empty = {
132
+ status: 'unknown_worker', expectedPgid: null, members: [], truncated: false, classification: null,
133
+ liveMemberCount: null, zombieMemberCount: null, workerStartedAt, workerIdentity: null,
134
+ } as ManagedDshProcessGroupSnapshot
135
+ if (workerPid === null) return { ...empty, status: 'unknown_worker' }
136
+ // Only Darwin's installed detached fallback establishes PID == PGID here.
137
+ // Linux native scopes and Windows Jobs require a provider range identity,
138
+ // so an unsupported platform claims no expected group at all.
139
+ if (process.platform !== 'darwin') return { ...empty, status: 'unsupported' }
140
+ return new Promise((resolve) => {
141
+ // A separate, bounded failure-only observation; it does not extend the
142
+ // provider's cleanup deadline or change its success/failure verdict.
143
+ execFile('/bin/ps', ['-axo', 'pid=,ppid=,pgid=,stat=,lstart='], {
144
+ encoding: 'utf8', timeout: 250, maxBuffer: 1024 * 1024,
145
+ env: { PATH: '/usr/bin:/bin', LC_ALL: 'C' },
146
+ }, (error, stdout) => {
147
+ if (error) return resolve({ ...empty, expectedPgid: workerPid, status: 'unavailable' })
148
+ resolve(parseManagedDshGroupSnapshot(stdout, workerPid, workerStartedAt))
149
+ })
150
+ })
151
+ }
@@ -0,0 +1,273 @@
1
+ import { existsSync } from 'node:fs'
2
+ import { fileURLToPath } from 'node:url'
3
+ import { dirname, join } from 'node:path'
4
+ import { createRequire } from 'node:module'
5
+ import { Context } from '@deepseek-ai/cordis'
6
+ import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local'
7
+ import type { SubprocessHandle } from '@deepseek-ai/dsh-subprocess'
8
+ import type { DshBootObservation, DshPlannerRunPort, DshPlannerRunResult } from './dsh-planner.ts'
9
+ import {
10
+ ManagedDshCleanupError,
11
+ managedDshGroupIsQuiescent,
12
+ readManagedDshWorkerStart,
13
+ snapshotManagedDshGroup,
14
+ type ManagedDshProcessGroupSnapshot,
15
+ type ManagedDshWorkerOutcome,
16
+ } from './managed-dsh-cleanup-diagnostic.ts'
17
+
18
+ export interface ManagedDshRunPortOptions {
19
+ cwd?: string
20
+ workerPath?: string
21
+ graceMs?: number
22
+ cleanupRole?: 'task' | 'warmer'
23
+ env?: NodeJS.ProcessEnv
24
+ /** Test seam overriding the failure-path group snapshot; production uses the safe ps snapshot. */
25
+ groupObserver?: typeof snapshotManagedDshGroup
26
+ /**
27
+ * Boot-marker channel (#511): receives one `HARNESS_BOOT_STAGE …` line per
28
+ * completed initialize handshake and one `HARNESS_BOOT_TIMEOUT …` line when
29
+ * the worker's own handshake deadline expires. Defaults to process stderr —
30
+ * the serving process log surface these markers were missing from.
31
+ */
32
+ bootLog?: (line: string) => void
33
+ [key: string]: unknown
34
+ }
35
+
36
+ /** The only worker failure classifications allowed to cross the process boundary. */
37
+ const WORKER_FAILURE_CODES = new Set(['HARNESS_BOOT_TIMEOUT', 'HARNESS_START_FAILED', 'HARNESS_RUN_FAILED'])
38
+
39
+ const requireFromModule = createRequire(import.meta.url)
40
+
41
+ function workerLaunch(path: string): readonly string[] {
42
+ // The worker cwd is the isolated booking state root, so a bare `tsx/esm`
43
+ // loader would resolve from the wrong dependency tree and exit before the
44
+ // first request. Resolve the loader from this package once and pass its
45
+ // absolute installed path to Node.
46
+ return path.endsWith('.ts')
47
+ ? [process.execPath, '--import', requireFromModule.resolve('tsx/esm'), path]
48
+ : [process.execPath, path]
49
+ }
50
+
51
+ /** Run DeepSeekHarness in a child tree owned by dsh-subprocess-local. */
52
+ export class ManagedDshRunPort implements DshPlannerRunPort {
53
+ private readonly handle: SubprocessHandle
54
+ private readonly runtime: LocalSubprocessRuntime
55
+ private readonly pending = new Map<number, { ok: (value?: DshPlannerRunResult) => void; fail: (error: Error) => void; progress?: () => void }>()
56
+ private sequence = 0
57
+ private closePromise: Promise<void> | undefined
58
+ private terminalError: Error | undefined
59
+ private inputBuffer = ''
60
+ private workerPid: number | null = null
61
+ private workerStartedAt: string | null = null
62
+ private workerOutcome: ManagedDshWorkerOutcome = { state: 'pending' }
63
+ private readonly cleanupRole: 'task' | 'warmer' | 'unspecified'
64
+ private readonly graceMs: number
65
+
66
+ constructor(options: ManagedDshRunPortOptions = {}) {
67
+ const defaultWorker = join(dirname(fileURLToPath(import.meta.url)), 'dsh-worker.js')
68
+ const workerPath = options.workerPath ?? (existsSync(defaultWorker) ? defaultWorker : defaultWorker.replace(/\.js$/, '.ts'))
69
+ const { workerPath: _worker, graceMs = 500, cleanupRole, env, groupObserver, bootLog, ...harnessOptions } = options
70
+ this.cleanupRole = cleanupRole ?? 'unspecified'
71
+ this.graceMs = graceMs
72
+ this.groupObserver = groupObserver ?? snapshotManagedDshGroup
73
+ this.bootLog = bootLog ?? ((line: string) => { process.stderr.write(`${line}\n`) })
74
+ this.constructedAtMs = Date.now()
75
+ this.runtime = new LocalSubprocessRuntime(new Context())
76
+ this.handle = this.runtime.spawn({
77
+ argv: workerLaunch(workerPath),
78
+ cwd: options.cwd ?? process.cwd(),
79
+ // Provider diagnostics may contain request fragments. Keep a bounded
80
+ // private tail for ownership without inheriting it into service logs.
81
+ stdio: { stdin: 'pipe', stdout: 'pipe', stderr: { maxBytes: 64 * 1024 } },
82
+ graceMs,
83
+ env,
84
+ })
85
+ this.handle.stdout!.setEncoding('utf8')
86
+ this.handle.stdout!.on('data', (chunk: string) => this.consume(chunk))
87
+ this.handle.done.then(
88
+ (outcome) => {
89
+ this.workerOutcome = { state: 'exited', exitCode: outcome.exitCode, signal: outcome.signal }
90
+ this.markTerminal('managed DSH worker exited')
91
+ },
92
+ () => {
93
+ this.workerOutcome = { state: 'failed' }
94
+ this.markTerminal('managed DSH worker failed')
95
+ },
96
+ )
97
+ // Credentials are already in the managed worker environment. Never copy
98
+ // them into the JSON-lines protocol or a thrown worker error.
99
+ this.harnessOptions = harnessOptions
100
+ this.cleanupDeadlineMs = Math.max(1_000, graceMs * 4)
101
+ }
102
+
103
+ private readonly harnessOptions: Record<string, unknown>
104
+ private readonly cleanupDeadlineMs: number
105
+ private readonly groupObserver: typeof snapshotManagedDshGroup
106
+ private readonly bootLog: (line: string) => void
107
+ private readonly constructedAtMs: number
108
+ private booted: DshBootObservation | undefined
109
+
110
+ /**
111
+ * #511: surface the boot markers in the serving process. The four startup
112
+ * marker families previously existed only in build-time proof output, so a
113
+ * recurrence in service runtime left nothing to grep. Payloads are closed
114
+ * shapes only — role, timings; never prompts, provider fragments, or
115
+ * credentials.
116
+ */
117
+ private emitBootLog(line: string): void {
118
+ try {
119
+ this.bootLog(line)
120
+ } catch { /* boot markers must never break the worker protocol */ }
121
+ }
122
+
123
+ /**
124
+ * What the most recent worker request paid for the initialize handshake: the
125
+ * measured wall time when that request started the runtime, and zero when an
126
+ * earlier request in the same worker already had. Read by the planner to keep
127
+ * our own boot cost separate from the provider budget it must not consume.
128
+ */
129
+ bootObservation(): DshBootObservation | undefined {
130
+ return this.booted
131
+ }
132
+
133
+ private consume(chunk: string): void {
134
+ this.inputBuffer += chunk
135
+ for (;;) {
136
+ const newline = this.inputBuffer.indexOf('\n')
137
+ if (newline < 0) return
138
+ const line = this.inputBuffer.slice(0, newline); this.inputBuffer = this.inputBuffer.slice(newline + 1)
139
+ try {
140
+ const message = JSON.parse(line) as { id: number; ok?: boolean; progress?: boolean; result?: DshPlannerRunResult; error?: string; lifecycle?: string; workerPid?: number; parentPid?: number; boot?: DshBootObservation }
141
+ if (message.lifecycle === 'worker_started') {
142
+ if (this.workerPid === null && Number.isSafeInteger(message.workerPid) && message.workerPid! > 0 && message.parentPid === process.pid) {
143
+ this.workerPid = message.workerPid!
144
+ // One bounded read-only start-time anchor, captured while the worker
145
+ // is alive, so a later failure snapshot can disprove PID reuse.
146
+ void readManagedDshWorkerStart(this.workerPid).then((startedAt) => {
147
+ if (this.workerStartedAt === null) this.workerStartedAt = startedAt
148
+ })
149
+ }
150
+ continue
151
+ }
152
+ if (message.progress) {
153
+ this.pending.get(message.id)?.progress?.()
154
+ continue
155
+ }
156
+ // A boot checkpoint carries the initialize handshake the worker already
157
+ // completed; the terminal reply for the same request still follows, and
158
+ // a request killed after booting has left this measurement behind.
159
+ if (message.boot) {
160
+ this.booted = message.boot
161
+ // One line per real subprocess boot (#511): only a 'started'
162
+ // handshake measured an initialize; 'reused' rode an earlier one.
163
+ if (message.boot.mode === 'started') {
164
+ this.emitBootLog(`HARNESS_BOOT_STAGE ${JSON.stringify({ role: this.cleanupRole, initializeMs: message.boot.initializeMs, mode: 'started' })}`)
165
+ }
166
+ if (message.ok === undefined) continue
167
+ }
168
+ const waiter = this.pending.get(message.id); if (!waiter) continue
169
+ this.pending.delete(message.id)
170
+ if (message.ok) waiter.ok(message.result)
171
+ // Worker stdout is a process boundary: an arbitrary payload must never
172
+ // become the error the planner classifies on.
173
+ else if (typeof message.error === 'string' && WORKER_FAILURE_CODES.has(message.error)) {
174
+ if (message.error === 'HARNESS_BOOT_TIMEOUT') {
175
+ // The worker's own initialize deadline expired before any handshake
176
+ // completed; record the closed classification plus what this port
177
+ // observable spent on it (closeMs belongs to cleanup diagnostics).
178
+ this.emitBootLog(`HARNESS_BOOT_TIMEOUT ${JSON.stringify({
179
+ role: this.cleanupRole,
180
+ elapsedMs: Date.now() - this.constructedAtMs,
181
+ initializeMs: this.booted?.initializeMs ?? null,
182
+ })}`)
183
+ }
184
+ waiter.fail(new Error(message.error))
185
+ }
186
+ else waiter.fail(new Error('HARNESS_RUN_FAILED'))
187
+ } catch (error) { this.failPending(error instanceof Error ? error : new Error(String(error))) }
188
+ }
189
+ }
190
+
191
+ private failPending(error: Error): void {
192
+ for (const waiter of this.pending.values()) waiter.fail(error)
193
+ this.pending.clear()
194
+ }
195
+
196
+ private markTerminal(message: string): void {
197
+ // Retain a safe terminal outcome before rejecting existing waiters: their
198
+ // continuations may immediately submit another request to this same port.
199
+ this.terminalError ??= new Error(message)
200
+ this.failPending(this.terminalError)
201
+ }
202
+
203
+ run(prompt: string, options: { sessionId: string; onProgress?: () => void }): Promise<DshPlannerRunResult> {
204
+ if (this.closePromise) return Promise.reject(new Error('managed DSH run port is closed'))
205
+ if (this.terminalError) return Promise.reject(this.terminalError)
206
+ const id = ++this.sequence
207
+ return new Promise((resolve, reject) => {
208
+ this.pending.set(id, { ok: (value) => resolve(value as DshPlannerRunResult), fail: reject, progress: options.onProgress })
209
+ this.handle.stdin!.write(`${JSON.stringify({ id, prompt, sessionId: options.sessionId, options: this.harnessOptions })}\n`)
210
+ })
211
+ }
212
+
213
+ /** Boot the in-worker harness without consuming a provider call. */
214
+ warmup(): Promise<void> {
215
+ if (this.closePromise) return Promise.reject(new Error('managed DSH run port is closed'))
216
+ if (this.terminalError) return Promise.reject(this.terminalError)
217
+ const id = ++this.sequence
218
+ return new Promise((resolve, reject) => {
219
+ this.pending.set(id, { ok: () => resolve(), fail: reject })
220
+ this.handle.stdin!.write(`${JSON.stringify({ id, warmup: true, options: this.harnessOptions })}\n`)
221
+ })
222
+ }
223
+
224
+ close(): Promise<void> {
225
+ if (this.closePromise) return this.closePromise
226
+ this.closePromise = (async () => {
227
+ const started = performance.now()
228
+ this.failPending(new Error('managed DSH run port closed'))
229
+ this.handle.terminate()
230
+ // Observe worker failure even if range observation rejects or times out
231
+ // first. This derived promise must never become an unhandled rejection.
232
+ const outcome = this.handle.done.then(
233
+ () => undefined,
234
+ () => new Error('managed DSH worker failed'),
235
+ )
236
+ let rangeEmpty: boolean
237
+ try {
238
+ rangeEmpty = await this.handle.waitForExit(AbortSignal.timeout(this.cleanupDeadlineMs))
239
+ } catch {
240
+ throw await this.cleanupError('managed DSH process tree observation failed', started)
241
+ }
242
+ if (!rangeEmpty) {
243
+ // On Darwin the installed detached fallback observes the group through
244
+ // kill(-pgid, 0): a zombie-only group yields EPERM, which the runtime
245
+ // maps to "alive", and zombies only disappear when their owner reaps
246
+ // them — no signal can accelerate that. The deadline has not moved;
247
+ // verify through the safe process table whether a live member actually
248
+ // remains before converting the observation deadline into a failure.
249
+ const processGroup = await this.groupObserver(this.workerPid, this.workerStartedAt)
250
+ if (!managedDshGroupIsQuiescent(processGroup)) {
251
+ throw await this.cleanupError('managed DSH process tree cleanup timeout', started, processGroup)
252
+ }
253
+ }
254
+ if (await outcome) throw await this.cleanupError('managed DSH worker failed', started)
255
+ })()
256
+ return this.closePromise
257
+ }
258
+
259
+ private async cleanupError(message: string, started: number, processGroup?: ManagedDshProcessGroupSnapshot): Promise<ManagedDshCleanupError> {
260
+ const elapsedMs = Math.round(performance.now() - started)
261
+ const workerOutcome = { ...this.workerOutcome }
262
+ const group = processGroup ?? await this.groupObserver(this.workerPid, this.workerStartedAt)
263
+ return new ManagedDshCleanupError(message, {
264
+ schemaVersion: 'managed-dsh-cleanup.v2', role: this.cleanupRole,
265
+ workerPid: this.workerPid, elapsedMs, deadlineMs: this.cleanupDeadlineMs,
266
+ graceMs: this.graceMs, workerOutcome, processGroup: group,
267
+ })
268
+ }
269
+ }
270
+
271
+ export function createManagedDshRunPort(options?: ManagedDshRunPortOptions): DshPlannerRunPort {
272
+ return new ManagedDshRunPort(options)
273
+ }