@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,171 @@
1
+ /**
2
+ * 行程 HTML 渲染器(issue #442,父 #438;共享契约层抽取见 issue #564)。
3
+ *
4
+ * 纯有界渲染器:拒绝畸形输入,产出单文件自包含 HTML。本模块不执行 IO、
5
+ * 不启动服务、不解析 Markdown、不做夜数/预算/时间运算——只把显式行程结构
6
+ * 与已注册事实投影成可导航、可展开的安全文档。
7
+ *
8
+ * 输入校验、事实归一化与证据卡渲染的单一事实源在 `itinerary-doc-shared.ts`
9
+ * (两个文档投影共用,防第二实现漂移);本模块只保留单页文档的排版与组装。
10
+ *
11
+ * 两条永不合流的证据面:
12
+ * 1. 计划面(planner:trip_start/trip_end/stays/od_segments)——用户排期意图;
13
+ * 2. 证据面(facts:调用方从注册表选出的 BookableFact)——exact-date 查询结论,
14
+ * 逐条保留 tier/bookability/source/query_id/fetched_at/as_of。
15
+ * 目的地级酒店库存绝不宣称「某家酒店有房/可订」;无任何整体 verified 徽章。
16
+ *
17
+ * 渲染闸锚点纪律:本模块不嵌入 `<!-- fact:<id> -->` 锚点(那属 Markdown 产物闸),
18
+ * 事实 id 只作为可见文本展示,避免整篇 HTML 被当作锚点行解析。
19
+ */
20
+
21
+ import {
22
+ DOC_BASE_CSS,
23
+ DOC_NARROW_CSS,
24
+ EVIDENCE_BOUNDARY_NOTICE,
25
+ MODE_LABEL,
26
+ TWO_PLANE_STATEMENT,
27
+ buildDateIndex,
28
+ docBytesError,
29
+ escapeHtml,
30
+ factIdSlug,
31
+ hotelFactsForStay,
32
+ leftoverFacts,
33
+ normalizeDocInput,
34
+ renderDateList,
35
+ renderFact,
36
+ renderFactCountsLine,
37
+ renderHotelEvidenceSection,
38
+ renderHotelNote,
39
+ renderLeftoverBlock,
40
+ renderPlannedStay,
41
+ renderPolicyNote,
42
+ renderSegment,
43
+ routeFactsFor,
44
+ timeEl,
45
+ type ItineraryDocResult,
46
+ type NormalizedFact,
47
+ type NormalizedFlight,
48
+ type NormalizedHotel,
49
+ type NormalizedItinerary,
50
+ type NormalizedPolicy,
51
+ } from './itinerary-doc-shared.ts'
52
+
53
+ // API 面稳定性:既有消费方(itinerary-artifact.ts / 测试)继续从本模块导入
54
+ export { ITINERARY_DOC_LIMITS as ITINERARY_HTML_LIMITS } from './itinerary-doc-shared.ts'
55
+ export type { ItineraryDocInput as ItineraryHtmlInput, ItineraryDocResult as ItineraryHtmlResult } from './itinerary-doc-shared.ts'
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // 单页文档排版(组装共享层的内容原语;CSS 为本形态私有)
59
+ // ---------------------------------------------------------------------------
60
+
61
+ const CSS = DOC_BASE_CSS + `
62
+ .wrap{max-width:64rem;margin:0 auto;padding:1rem}
63
+ header.doc{border-bottom:1px solid var(--line);padding-bottom:.75rem}
64
+ nav.toc{border:1px solid var(--line);border-radius:6px;padding:.6rem .8rem;margin:1rem 0;background:var(--card)}
65
+ nav.toc h2{font-size:1rem}
66
+ nav.toc ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.35rem .9rem}
67
+ nav.toc ul ul{margin-left:.9rem;font-size:.92rem;display:block}
68
+ section{margin:1.75rem 0}
69
+ ` + DOC_NARROW_CSS + `
70
+ @media (max-width:480px){
71
+ .wrap{padding:.6rem}
72
+ }`
73
+
74
+ function render(input: { title: string; itinerary: NormalizedItinerary; facts: NormalizedFact[] }): string {
75
+ const { title, itinerary, facts } = input
76
+ const stays = itinerary.stays
77
+ const segs = itinerary.od_segments
78
+ const hotelFacts = facts.filter((f): f is NormalizedHotel => f.kind === 'hotel')
79
+ const policyFacts = facts.filter((f): f is NormalizedPolicy => f.kind === 'policy')
80
+ const flightFacts = facts.filter((f): f is NormalizedFlight => f.kind === 'flight' || f.kind === 'train')
81
+
82
+ const stayBlocks = stays.map((stay, i) => renderPlannedStay(stay, `stay-${i + 1}`, hotelFactsForStay(hotelFacts, stay)))
83
+ const segBlocks = segs.map((seg, i) => renderSegment(seg, `seg-${i + 1}`, routeFactsFor(facts, seg), itinerary.trip_start))
84
+
85
+ const stayDateItems = stays.filter((s, i) => stays.findIndex(x => x.check_in === s.check_in) === i)
86
+ .map(s => `<li>${timeEl(s.check_in)} — <a href="#stay-${stays.indexOf(s) + 1}">计划住宿 ${escapeHtml(s.place)}</a></li>`)
87
+ .join('')
88
+ const segDateItems = [...new Set(segs.map(s => s.date))].sort()
89
+ .map(d => `<li>${timeEl(d)} — <a href="#segments">交通段</a></li>`)
90
+ .join('')
91
+
92
+ const dateList = renderDateList(buildDateIndex(itinerary))
93
+ const leftovers = leftoverFacts(facts, itinerary)
94
+ const leftoverBlock = renderLeftoverBlock(leftovers, itinerary.trip_start)
95
+ const hotelNote = renderHotelNote(hotelFacts)
96
+ const policyNote = renderPolicyNote(policyFacts)
97
+
98
+ return `<!DOCTYPE html>
99
+ <html lang="zh-CN">
100
+ <head>
101
+ <meta charset="utf-8">
102
+ <meta name="viewport" content="width=device-width, initial-scale=1">
103
+ <meta name="referrer" content="no-referrer">
104
+ <title>${escapeHtml(title)}</title>
105
+ <style>${CSS}</style>
106
+ </head>
107
+ <body>
108
+ <a class="skip" href="#main">跳到主要内容</a>
109
+ <div class="wrap">
110
+ <header class="doc">
111
+ <h1>${escapeHtml(title)}</h1>
112
+ <p>行程 ${timeEl(itinerary.trip_start)} → ${timeEl(itinerary.trip_end)}</p>
113
+ ${TWO_PLANE_STATEMENT}
114
+ </header>
115
+ <main id="main">
116
+ ${EVIDENCE_BOUNDARY_NOTICE}
117
+ <nav class="toc" aria-label="行程导航">
118
+ <h2>导航</h2>
119
+ <ul>
120
+ <li><a href="#dates">按日期</a><ul>${dateList.startsWith('<p') ? '<li class="muted">无</li>' : ''}</ul></li>
121
+ <li><a href="#segments">航班/交通段</a><ul>${segDateItems || '<li class="muted">无</li>'}</ul></li>
122
+ <li><a href="#stays">住宿</a><ul>${stayDateItems || '<li class="muted">无</li>'}</ul></li>
123
+ <li><a href="#facts">事实与证据</a></li>
124
+ </ul>
125
+ </nav>
126
+ <section id="dates"><h2>按日期行程</h2>
127
+ ${dateList}
128
+ </section>
129
+ <section id="segments"><h2>航班/交通段</h2>
130
+ <p class="muted">下列条目是计划段(用户排期意图);每段内另列可回溯到该 route + date 的已注册事实。计划段不因存在事实而变成可下单。</p>
131
+ ${segBlocks.join('') || '<p class="muted missing">没有显式交通段。</p>'}
132
+ </section>
133
+ <section id="stays"><h2>住宿</h2>
134
+ ${hotelNote}
135
+ ${stayBlocks.join('') || '<p class="muted missing">没有显式住宿段。</p>'}
136
+ ${renderHotelEvidenceSection(hotelFacts, itinerary.trip_start)}
137
+ </section>
138
+ <section id="facts"><h2>事实与证据</h2>
139
+ ${renderFactCountsLine(facts)}
140
+ ${policyFacts.map(f => renderFact(f, `policy-${factIdSlug(f.fact.fact_id)}`, itinerary.trip_start)).join('')}
141
+ ${policyNote}
142
+ ${leftoverBlock}
143
+ <h3>全部航班/车次事实(含负事实与冲突)</h3>
144
+ ${flightFacts.map(f => renderFact(f, `flight-${factIdSlug(f.fact.fact_id)}`, itinerary.trip_start)).join('') || '<p class="muted missing">本次输入没有航班/车次事实。</p>'}
145
+ </section>
146
+ </main>
147
+ </div>
148
+ </body>
149
+ </html>
150
+ `
151
+ }
152
+
153
+ // ---------------------------------------------------------------------------
154
+ // 入口
155
+ // ---------------------------------------------------------------------------
156
+
157
+ /**
158
+ * 纯渲染入口。`input` 是任意运行时数据:结构、枚举、真实日历日期、有限数值、
159
+ * 容量与文档大小全部现场校验;任何一项不合法即返回 `ok:false` + 结构化 errors,
160
+ * 绝不静默丢弃核心行程后仍返回「成功」。校验与归一化的单一事实源在
161
+ * `itinerary-doc-shared.ts`,与 deck 投影共用同一拒绝语义。
162
+ */
163
+ export function renderItineraryHtml(input: unknown): ItineraryDocResult {
164
+ const normalized = normalizeDocInput(input)
165
+ if (!normalized.ok) return normalized
166
+ const html = render(normalized)
167
+ // 输出大小硬上限:超限即整体失败(检查实现于共享层)
168
+ const bytesError = docBytesError(html)
169
+ if (bytesError !== undefined) return { ok: false, errors: bytesError }
170
+ return { ok: true, html }
171
+ }
package/ts/src/loop.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Stage 1 对话循环(S2 段1,docs/stage1-top-down-design.md §2.3)。
2
+ * Stage 1 对话循环(S2 段1,docs/design/stage1-top-down-design.md §2.3)。
3
3
  *
4
4
  * 自顶向下:循环只依赖两个端口——LlmPort(mock/真)与确定性工具(interview_next)。
5
5
  * 求解/渲染接线是 S2 后续段;本段验收:重放用户开场白,系统一轮内完成
@@ -8,6 +8,7 @@
8
8
 
9
9
  import type { InterviewQuestion, TripState, TravelerProfile, Turn, CalendarState, SolveResult } from './contracts.ts'
10
10
  import type { JourneySpecTS } from './unified.ts'
11
+ import { buildTimeAnchor, isRealIsoDate, planningWindowBounds, parsePlanningWindow, type PlanningWindow, type TimeAnchor } from './time-anchor.ts'
11
12
  import type { TravelSlotExtraction } from './travel-slots.ts'
12
13
  import { anythingSearch } from '../capabilities/anything.ts'
13
14
 
@@ -95,6 +96,98 @@ export function validateSpec(spec: JourneySpecTS): string | null {
95
96
  return null
96
97
  }
97
98
 
99
+ export interface PlanningWindowRejection {
100
+ segmentId: string
101
+ optionId: string
102
+ date: string
103
+ }
104
+
105
+ export interface PlanningWindowCheck {
106
+ spec: JourneySpecTS
107
+ rejected: PlanningWindowRejection[]
108
+ error?: string
109
+ }
110
+
111
+ export interface PlanningWindowOptions {
112
+ /** Registered feasibility tool opts into the dated-candidate default future floor. */
113
+ defaultDatedFuture?: boolean
114
+ }
115
+
116
+ function isoDateInBounds(date: string, bounds: { start: string; end: string }): boolean {
117
+ const m = date.match(/^(\d{4})-(\d{2})-(\d{2})$/)
118
+ if (!m || !isRealIsoDate(Number(m[1]), Number(m[2]), Number(m[3]))) return false
119
+ return date >= bounds.start && date <= bounds.end
120
+ }
121
+
122
+ function hasDatedCandidates(spec: JourneySpecTS): boolean {
123
+ return spec.segments.some(segment => segment.date !== undefined || segment.options.some(option => option.date !== undefined))
124
+ }
125
+
126
+ /**
127
+ * Enforce a named-year future window at the planner boundary. Historical
128
+ * lookup/backtesting remains an explicit bypass; an expired named year fails
129
+ * instead of being silently rolled into a different year.
130
+ */
131
+ export function applyPlanningWindow(
132
+ spec: JourneySpecTS,
133
+ window: PlanningWindow | null,
134
+ anchor: TimeAnchor,
135
+ options: PlanningWindowOptions = {},
136
+ ): PlanningWindowCheck {
137
+ // Dated recommendations are future-oriented even without optional named-year context.
138
+ // Fully dateless legacy calculations remain untouched; historical bypass is explicit.
139
+ if (window?.intent === 'historical') return { spec, rejected: [] }
140
+ const implicitFutureFloor = !window && options.defaultDatedFuture === true && hasDatedCandidates(spec)
141
+ if (!window && !implicitFutureFloor) return { spec, rejected: [] }
142
+
143
+ const currentYear = Number(anchor.today.slice(0, 4))
144
+ if (window && window.requestedYear < currentYear) {
145
+ return {
146
+ spec,
147
+ rejected: [],
148
+ error: `${window.requestedYear} 年已结束(当前规划参考日 ${anchor.today}),不会自动改用其他年份;如需历史查询请明确说明“历史/回测”。`,
149
+ }
150
+ }
151
+
152
+ const bounds = window
153
+ ? planningWindowBounds(window, anchor)
154
+ : { start: anchor.today, end: '9999-12-31' }
155
+ if (!bounds) return { spec, rejected: [], error: `无法建立 ${window!.requestedYear} 年的未来规划窗口。` }
156
+
157
+ const rejected: PlanningWindowRejection[] = []
158
+ const guardedSegments = spec.segments.map(segment => ({
159
+ ...segment,
160
+ options: segment.options.filter(option => {
161
+ const date = option.date ?? segment.date
162
+ if (date && isoDateInBounds(date, bounds)) return true
163
+ rejected.push({ segmentId: segment.id, optionId: option.id, date: date ?? '未提供明确日期' })
164
+ return false
165
+ }),
166
+ }))
167
+
168
+ if (guardedSegments.some(segment => segment.options.length === 0)) {
169
+ return {
170
+ spec: { ...spec, segments: guardedSegments },
171
+ rejected,
172
+ error: implicitFutureFloor
173
+ ? `带日期的未来推荐必须不早于当前规划参考日 ${bounds.start};没有带明确日期且在未来窗口内的可接受方案。`
174
+ : `${window!.requestedYear} 年未来规划窗口为 ${bounds.start} 至 ${bounds.end};没有带明确日期且落在窗口内的可接受方案。`,
175
+ }
176
+ }
177
+ return { spec: { ...spec, segments: guardedSegments }, rejected }
178
+ }
179
+
180
+ function latestPlanningWindow(history: Turn[], userMsg: string, anchor: TimeAnchor): PlanningWindow | null {
181
+ const turns = [...history, { role: 'user' as const, text: userMsg }]
182
+ for (let i = turns.length - 1; i >= 0; i--) {
183
+ const turn = turns[i]
184
+ if (turn?.role !== 'user') continue
185
+ const parsed = parsePlanningWindow(turn.text, anchor)
186
+ if (parsed) return parsed
187
+ }
188
+ return null
189
+ }
190
+
98
191
  /** 求解端口:S3 起由 unified 求解器实现;循环只认此签名(确定性责任)。 */
99
192
  export type SolvePort = (spec: JourneySpecTS) => Promise<SolveResult>
100
193
 
@@ -110,6 +203,56 @@ export interface AsyncTicket {
110
203
  etaLabel: string
111
204
  }
112
205
 
206
+ export const ASYNC_TERMINAL_SCHEMA = 'gotry_async_terminal.v1' as const
207
+
208
+ export interface AsyncTerminalOutcome {
209
+ schema: typeof ASYNC_TERMINAL_SCHEMA
210
+ ticket_id: string
211
+ status: 'succeeded' | 'failed'
212
+ passed: number
213
+ total: 4
214
+ checks: Record<string, boolean>
215
+ failed_checks: string[]
216
+ }
217
+
218
+ function asyncTerminalOutcome(ticketId: string, checks: Record<string, boolean>): AsyncTerminalOutcome {
219
+ const failedChecks = Object.entries(checks).filter(([, passed]) => !passed).map(([name]) => name)
220
+ return {
221
+ schema: ASYNC_TERMINAL_SCHEMA,
222
+ ticket_id: ticketId,
223
+ status: failedChecks.length === 0 ? 'succeeded' : 'failed',
224
+ passed: Object.values(checks).filter(Boolean).length,
225
+ total: 4,
226
+ checks,
227
+ failed_checks: failedChecks,
228
+ }
229
+ }
230
+
231
+ function terminalOutcomeFromState(ticketId: string, state: TripState): AsyncTerminalOutcome {
232
+ if (!state.spec || !state.solve) {
233
+ return asyncTerminalOutcome(ticketId, {
234
+ '1_承诺时间后必有明确产物': false,
235
+ '2_产物通过自检清单': false,
236
+ '3_待决问题全部是简单选择题': false,
237
+ '4_做不到的诚实说': false,
238
+ })
239
+ }
240
+
241
+ // issue #620:求解器自身失败时既没有产物也没有判定——2 条不成立;但「做不到诚实说」
242
+ // 恰恰成立(我们明说了是引擎故障而非不可行),不靠 unsat_core 冒充自检通过。
243
+ const solverFailed = Boolean(state.solve.solver_error)
244
+ return asyncTerminalOutcome(ticketId, {
245
+ '1_承诺时间后必有明确产物': Boolean(state.solve.legs?.length || state.solve.verdicts?.length),
246
+ '2_产物通过自检清单': solverFailed
247
+ ? false
248
+ : state.solve.feasible
249
+ ? (state.solve.legs?.every(l => (l as Record<string, unknown>)['energy_pct'] !== undefined) ?? false)
250
+ : Boolean(state.solve.unsat_core?.length),
251
+ '3_待决问题全部是简单选择题': state.gates.every(g => g.id === 'budget' || g.options.length >= 2),
252
+ '4_做不到的诚实说': solverFailed || state.solve.feasible || Boolean(state.solve.suggestions?.length),
253
+ })
254
+ }
255
+
113
256
  export function isComplex(state: TripState): boolean {
114
257
  /** 复杂度判据(架构占位,后续可细化):多段或多约束即深规划 */
115
258
  const p = state.profile
@@ -134,21 +277,19 @@ export async function collectDeepPlanning(
134
277
  state: TripState,
135
278
  ticket: AsyncTicket,
136
279
  solve: SolvePort,
137
- ): Promise<{ reply: string; state: TripState }> {
280
+ ): Promise<{ reply: string; state: TripState; outcome: AsyncTerminalOutcome }> {
138
281
  const spec = state.spec
139
- if (!spec) return { reply: '(内部状态缺失 spec——深度规划未就绪,这是不应发生的路径)', state }
282
+ if (!spec) {
283
+ const outcome = terminalOutcomeFromState(ticket.id, state)
284
+ return { reply: '(内部状态缺失 spec——深度规划未就绪,这是不应发生的路径)', state, outcome }
285
+ }
140
286
  state.solve = await solve(spec)
141
287
  state.gates = state.gates.filter(g => !g.id.startsWith('async-'))
142
288
 
143
289
  // 不失望四条自检(交付物自带,总纲 3.6)
144
- const checks = {
145
- '1_承诺时间后必有明确产物': Boolean(state.solve.legs?.length || state.solve.verdicts?.length),
146
- '2_产物通过自检清单': state.solve.feasible ? (state.solve.legs?.every(l => (l as Record<string, unknown>)['energy_pct'] !== undefined) ?? false) : Boolean(state.solve.unsat_core?.length),
147
- '3_待决问题全部是简单选择题': state.gates.every(g => g.id === 'budget' || g.options.length >= 2),
148
- '4_做不到的诚实说': state.solve.feasible || Boolean(state.solve.suggestions?.length),
149
- }
150
- const head = `# 回访交付:${ticket.objective}\n(工单 ${ticket.id},不失望四条:${Object.values(checks).every(Boolean) ? '4/4 ✅' : '有未达项 ❌'})`
151
- return { reply: `${head}\n\n${renderSolve(state)}`, state }
290
+ const outcome = terminalOutcomeFromState(ticket.id, state)
291
+ const head = `# 回访交付:${ticket.objective}\n(工单 ${ticket.id},不失望四条:${outcome.status === 'succeeded' ? '4/4 ✅' : '有未达项 ❌'})`
292
+ return { reply: `${head}\n\n${renderSolve(state)}`, state, outcome }
152
293
  }
153
294
 
154
295
  /** 求解结果 → 人话(模板;S4 可由 LLM 润色,数字与判定不可改) */
@@ -156,15 +297,27 @@ export function renderSolve(state: TripState): string {
156
297
  const s = state.solve
157
298
  if (!s) return '(无求解结果)'
158
299
  const lines: string[] = []
159
- if (s.feasible) {
300
+ if (s.solver_error) {
301
+ // issue #620:求解器自己失败 ≠ 行程不可行。这里**不**说「不可行」、不列「冲突」,
302
+ // 也不把机器 token(solver_error.code)渲染给用户——它只在日志/证据里。
303
+ lines.push('**这轮没算出结论——求解器自身出错了,不是你的行程不可行**')
304
+ lines.push('- 我不把引擎故障说成「不可行」:这条已记录,修好或换候选形态(枚举)后重算')
305
+ } else if (s.feasible) {
160
306
  lines.push(`**方案可行,机票合计 ¥${s.money_cny}**`)
161
- for (const lg of s.legs ?? []) {
162
- const l = lg as Record<string, string | number>
163
- lines.push(`- ${l['leg']} ${l['service']}:${l['dep']} 起飞,${l['wake']} 出发,${l['arrive_stay']} 到,`
164
- + `门到门 ${l['door_to_door']},落地精力 ${l['energy_pct']}%,¥${l['price_cny']}`)
307
+ // §7-1 issue #559 卡点 4:从 s.skeleton_notes 字符串编码里推断 unscaffolded 的 seg.id,
308
+ // 不动 unified.ts/journey.ts(内核冻结面 #234),用户面给 ⚠ 前缀与「枢纽对未在骨架覆盖」补充。
309
+ // skeleton_notes 单条形态:`<seg.id>: [骨架:openflights] ❌ ...` 或 `<seg.id>: [骨架:openflights] ✅ ...`
310
+ const unscaffoldedSegIds = new Set<string>()
311
+ for (const n of s.skeleton_notes ?? []) {
312
+ const m = /^([^:]+):\s*\[骨架:openflights\]\s*❌/.exec(n)
313
+ if (m) unscaffoldedSegIds.add(m[1])
165
314
  }
166
- for (const e of s.work_window_exclusions ?? []) {
167
- lines.push(`- 已排除 ${e.option}(工作窗口):${e.reason}`)
315
+ for (const lg of s.legs ?? []) {
316
+ const l = lg as Record<string, string | number | boolean>
317
+ const unscaffoldedFlag = unscaffoldedSegIds.has(String(l['leg'])) ? '⚠ ' : ''
318
+ const unscaffoldedNote = unscaffoldedSegIds.has(String(l['leg'])) ? '(枢纽对未在骨架覆盖,实时源以新航线为准)' : ''
319
+ lines.push(`- ${unscaffoldedFlag}${l['leg']} ${l['service']}:${l['dep']} 起飞,${l['wake']} 出发,${l['arrive_stay']} 到,`
320
+ + `门到门 ${l['door_to_door']},落地精力 ${l['energy_pct']}%,¥${l['price_cny']}${unscaffoldedNote ? ` ${unscaffoldedNote}` : ''}`)
168
321
  }
169
322
  for (const n of s.skeleton_notes ?? []) lines.push(`- ${n}`)
170
323
  for (const f of s.red_flags ?? []) lines.push(`- ⚠️ ${f}`)
@@ -172,6 +325,9 @@ export function renderSolve(state: TripState): string {
172
325
  lines.push(`**当前约束下不可行——冲突:${(s.unsat_core ?? []).join('、')}`)
173
326
  for (const sg of s.suggestions ?? []) lines.push(`- 放宽「${sg.relax}」可解(约 ¥${sg.money_cny})`)
174
327
  }
328
+ for (const e of s.work_window_exclusions ?? []) {
329
+ lines.push(`- 已排除 ${e.option}(工作窗口):${e.reason}`)
330
+ }
175
331
  if (state.gates.length) {
176
332
  lines.push('', '**待你决定(选择题)**')
177
333
  for (const g of state.gates) {
@@ -188,7 +344,9 @@ export async function runTurn(
188
344
  llm: LlmPort,
189
345
  history: Turn[] = [],
190
346
  solve: SolvePort | null = null,
347
+ now: Date = new Date(),
191
348
  ): Promise<{ reply: string; state: TripState }> {
349
+ const anchor = buildTimeAnchor(now)
192
350
  const facts = await llm.extractFacts([...history, { role: 'user', text: userMsg }], state)
193
351
 
194
352
  const conflicts: string[] = []
@@ -236,7 +394,10 @@ export async function runTurn(
236
394
  } else if (ar.verdict === 'miss') {
237
395
  parts.push(`**${poiProbe} → miss** (酒店-be Anything 一切正常但无候选)\n${ar.evidence}`)
238
396
  } else {
239
- parts.push(`**${poiProbe} → unavailable** (${ar.error ?? 'hbcli 不可达'})\n${ar.evidence}`)
397
+ // 用户面只给人话原因 + 来源 tag:evidence 里的上游原话是溯源契约(能力层测试锁),
398
+ // 其中的进程噪音(如 `(exit null)`)不该渲染进回复。
399
+ const sourceTag = ar.evidence.match(/^\[[^\]]+\]/)?.[0]
400
+ parts.push(`**${poiProbe} → 实时查询不可用**(${ar.error ?? 'hbcli 不可达'})——这条不阻塞本轮规划,只影响实时数据源,其余结论照常带来源标注${sourceTag ? `\n${sourceTag}` : ''}`)
240
401
  }
241
402
  }
242
403
 
@@ -244,7 +405,22 @@ export async function runTurn(
244
405
 
245
406
  // 约束齐备(无阻塞问题)→ 翻译 spec → **校验闸 + 日期一致性闸** → 求解 → 渲染
246
407
  if (blocking.length === 0 && solve) {
247
- const spec = await llm.extractSpec([...history, { role: 'user', text: userMsg }], state)
408
+ const extractedSpec = await llm.extractSpec([...history, { role: 'user', text: userMsg }], state)
409
+ const planning = latestPlanningWindow(history, userMsg, anchor)
410
+ const planningCheck = extractedSpec ? applyPlanningWindow(extractedSpec, planning, anchor) : null
411
+ if (planningCheck?.error) {
412
+ state.spec = undefined
413
+ state.solve = undefined
414
+ parts.push(`⚠️ ${planningCheck.error}`)
415
+ return { reply: parts.join('\n\n'), state }
416
+ }
417
+ if (planningCheck?.rejected.length) {
418
+ const rejected = planningCheck.rejected
419
+ .map(r => `${r.segmentId}/${r.optionId}(${r.date})`)
420
+ .join('、')
421
+ parts.push(`已排除规划窗口外的候选:${rejected}`)
422
+ }
423
+ const spec = planningCheck?.spec ?? extractedSpec
248
424
  // 场景路由:erhai 候选标记 → 候选求解(洱海金标准的引擎判定)——纯 TS unify 路径
249
425
  if (spec && (spec as unknown as { note?: string }).note === 'erhai-candidates') {
250
426
  const { readFile } = await import('node:fs/promises')
@@ -268,11 +444,10 @@ export async function runTurn(
268
444
  // D-10 切片 C:spec↔槽位日期一致性闸(ADR-10 翻译≠造数的执行点)。
269
445
  // LLM 翻译的 spec 日期与代码层换算的槽位日期分歧时不求解、不猜,追问确认——
270
446
  // 日期是求解关键输入,错日期 = 错判决。槽位缺失/unresolved 不参与(不造假阳性)。
271
- const ext = await llm.extractSlots([...history, { role: 'user', text: userMsg }])
447
+ const ext = await llm.extractSlots([...history, { role: 'user', text: userMsg }], now)
272
448
  if (ext) {
273
449
  const { resolveSlots, specDateMismatches } = await import('./slot-spec.ts')
274
- const { buildTimeAnchor } = await import('./time-anchor.ts')
275
- const mismatches = specDateMismatches(spec, resolveSlots(ext, buildTimeAnchor()))
450
+ const mismatches = specDateMismatches(spec, resolveSlots(ext, anchor))
276
451
  if (mismatches.length > 0) {
277
452
  const lines = mismatches.map(m => `- ${m.specAt}:翻译说 ${m.specDate},你的原话换算是 ${m.slotDate}(${m.field})`)
278
453
  parts.push(`⚠️ 日期分歧,确认后我再算(以你为准):\n${lines.join('\n')}`)
@@ -341,14 +516,44 @@ export async function loadAsyncTicket(ticketId: string, stateRoot = '.'): Promis
341
516
  }
342
517
  }
343
518
 
344
- export async function settleAsyncTicket(ticketId: string, reply: string, stateRoot = '.'): Promise<string> {
345
- openLedgerIfExists(stateRoot)?.settleWorkflowRun(ticketId, reply)
519
+ export async function settleAsyncTicket(
520
+ ticketId: string,
521
+ reply: string,
522
+ stateRoot = '.',
523
+ outcome?: AsyncTerminalOutcome,
524
+ ): Promise<string> {
525
+ const ledger = openLedgerIfExists(stateRoot)
526
+ const terminalOutcome = outcome ?? recoverAsyncTerminalOutcome(ledger, ticketId)
527
+ if (ledger && !terminalOutcome) {
528
+ throw new Error(`workflow ${ticketId} 缺少可恢复的 ${ASYNC_TERMINAL_SCHEMA},拒绝误结算`)
529
+ }
530
+ if (terminalOutcome?.status === 'failed') ledger?.failWorkflowRun(ticketId, reply, terminalOutcome)
531
+ else ledger?.settleWorkflowRun(ticketId, reply, terminalOutcome)
346
532
  const dir = await asyncDir(stateRoot)
347
533
  const p = join(dir, `${ticketId}.deliverable.md`)
348
534
  await atomicWrite(p, reply)
349
535
  return p
350
536
  }
351
537
 
538
+ function recoverAsyncTerminalOutcome(ledger: StateLedger | null, ticketId: string): AsyncTerminalOutcome | undefined {
539
+ if (!ledger) return undefined
540
+ const run = ledger.getWorkflowRun(ticketId)
541
+ if (!run) return undefined
542
+
543
+ try {
544
+ const state = JSON.parse(run.state_json) as TripState
545
+ if (!state.spec) return terminalOutcomeFromState(ticketId, state)
546
+
547
+ const solveStep = ledger.getWorkflowStep(ticketId, 'solve')
548
+ if (solveStep?.status !== 'done' || !solveStep.result) return undefined
549
+ state.solve = JSON.parse(solveStep.result) as SolveResult
550
+ state.gates = state.gates.filter(g => !g.id.startsWith('async-'))
551
+ return terminalOutcomeFromState(ticketId, state)
552
+ } catch {
553
+ return undefined
554
+ }
555
+ }
556
+
352
557
  /**
353
558
  * 可日志化 solve 端口(ADR-15 步骤日志,intent-before-execute):
354
559
  * 先记 intent 再执行,done 后结果落账本——任意进程恢复时 done 的步骤直接复用
@@ -380,6 +585,9 @@ export function makeJournaledSolvePort(ledger: StateLedger, runId: string, solve
380
585
  * 2026-08-28 巡检收紧:旧版 ≤24 直通把访谈答案整句当关键词,垃圾 hbcli 调用+证据噪音)。
381
586
  * 不是意图(改求解器),只是 datasources 编排层的"提早调 anything"提示。
382
587
  */
588
+ /** 住宿名称段上界:路径 2 已要求含拉丁/数字且被标点截断,旧 24 字会把
589
+ * 「The Title East Wing Rawai」这类真实酒店名截残后回显给用户(2026-09-22)。 */
590
+ const POI_NAME_MAX = 48
383
591
  export function probePoi(msg: string): string | null {
384
592
  const trimmed = msg.trim()
385
593
  if (!trimmed) return null
@@ -395,7 +603,7 @@ export function probePoi(msg: string): string | null {
395
603
  if (/(酒店|民宿|客栈|饭店)/.test(trimmed)) {
396
604
  const parts = trimmed.split(/(酒店|民宿|客栈|饭店)/)
397
605
  const after = cutAtPunct((parts[2] ?? '').replace(/^[的::\s]+/, ''))
398
- if (after.length >= 2 && /[A-Za-z0-9]/.test(after)) return after.slice(0, 24)
606
+ if (after.length >= 2 && /[A-Za-z0-9]/.test(after)) return after.length > POI_NAME_MAX ? `${after.slice(0, POI_NAME_MAX - 1)}…` : after
399
607
  const nounAt = trimmed.search(/(酒店|民宿|客栈|饭店)/)
400
608
  const pre = trimmed.slice(Math.max(0, nounAt - 6), nounAt).match(/[一-龥]{2,6}$/)
401
609
  if (pre && !/(机票|车票|和|做|订|的)$/.test(pre[0])) return pre[0]