@danceiny/gotry 0.0.1-rc.21 → 0.0.1-rc.24

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 (327) hide show
  1. package/README.md +102 -194
  2. package/README.zh-CN.md +115 -210
  3. package/bin/gotry-backend.js +53 -0
  4. package/bin/gotry-bootstrap.js +466 -35
  5. package/bin/gotry-inner.js +255 -36
  6. package/bin/gotry-process-liveness.d.ts +27 -0
  7. package/bin/gotry-process-liveness.js +97 -0
  8. package/bin/gotry-runtime-resolution.d.ts +1 -1
  9. package/bin/gotry-runtime-resolution.js +2 -2
  10. package/client/client.js +174 -0
  11. package/cordis.gotry-patch.yml +70 -93
  12. package/dist/capabilities/agent-reach-deep.js +45 -122
  13. package/dist/capabilities/agent-reach.js +63 -148
  14. package/dist/capabilities/anything.js +89 -75
  15. package/dist/capabilities/artifacts.js +123 -104
  16. package/dist/capabilities/channel-health.js +65 -45
  17. package/dist/capabilities/channel-registry.js +108 -87
  18. package/dist/capabilities/doctor.js +357 -235
  19. package/dist/capabilities/effect.js +223 -309
  20. package/dist/capabilities/fact-log.js +28 -14
  21. package/dist/capabilities/flyai.js +245 -156
  22. package/dist/capabilities/ground-transfer.js +509 -0
  23. package/dist/capabilities/hbcli.js +144 -148
  24. package/dist/capabilities/hotelbyte-transaction.js +194 -0
  25. package/dist/capabilities/incident-log.js +131 -61
  26. package/dist/capabilities/model-override.js +30 -10
  27. package/dist/capabilities/opensky.js +54 -43
  28. package/dist/capabilities/resilience.js +50 -32
  29. package/dist/capabilities/session/action-cache.js +50 -44
  30. package/dist/capabilities/session/adapters/ctrip-flight.js +119 -62
  31. package/dist/capabilities/session/adapters/ctrip-hotel.js +125 -110
  32. package/dist/capabilities/session/adapters/dida-portal.js +206 -0
  33. package/dist/capabilities/session/adapters/meituan-local.js +35 -54
  34. package/dist/capabilities/session/adapters/rail-12306.js +169 -112
  35. package/dist/capabilities/session/benchmark.js +85 -149
  36. package/dist/capabilities/session/extension-bridge.js +320 -259
  37. package/dist/capabilities/session/extension-channel.js +57 -76
  38. package/dist/capabilities/session/extension-distribution.js +115 -119
  39. package/dist/capabilities/session/extract.js +31 -21
  40. package/dist/capabilities/session/golden-score.js +55 -33
  41. package/dist/capabilities/session/health-watch.js +146 -154
  42. package/dist/capabilities/session/read-guard.js +55 -47
  43. package/dist/capabilities/session/static-flight-golden.js +49 -36
  44. package/dist/capabilities/session/transport.js +54 -61
  45. package/dist/capabilities/session/wizard.js +63 -93
  46. package/dist/capabilities/session-consent.js +143 -47
  47. package/dist/capabilities/session-login.js +95 -126
  48. package/dist/capabilities/session-search.js +391 -253
  49. package/dist/capabilities/sponsor-plugin.js +341 -0
  50. package/dist/capabilities/visa-policy.js +87 -73
  51. package/dist/capabilities/weather.js +163 -235
  52. package/dist/scripts/action-cache-tests.js +24 -59
  53. package/dist/scripts/agent-planning-turn-deadline-e2e.js +91 -142
  54. package/dist/scripts/agent-planning-turn-deadline-tests.js +80 -176
  55. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  56. package/dist/scripts/agent-reach-tests.js +26 -18
  57. package/dist/scripts/agent-reach-wrapper-tests.js +46 -50
  58. package/dist/scripts/anything-tests.js +58 -62
  59. package/dist/scripts/artifact-client-contract-tests.js +69 -0
  60. package/dist/scripts/artifacts-capability-tests.js +235 -0
  61. package/dist/scripts/async-collect.js +26 -15
  62. package/dist/scripts/benchmark-environment-bridge-e2e.js +287 -684
  63. package/dist/scripts/benchmark-environment-bridge-tests.js +818 -3123
  64. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +66 -279
  65. package/dist/scripts/booking-copilot-availability-policy-tests.js +153 -1257
  66. package/dist/scripts/booking-copilot-bin-proof-tests.js +22 -45
  67. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +64 -76
  68. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +69 -199
  69. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +393 -759
  70. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +33 -75
  71. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +60 -110
  72. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +28 -66
  73. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +72 -271
  74. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +73 -275
  75. package/dist/scripts/booking-copilot-runtime-proof-tests.js +784 -3398
  76. package/dist/scripts/booking-copilot-server-proof-tests.js +63 -168
  77. package/dist/scripts/booking-copilot-startup-proof-tests.js +38 -124
  78. package/dist/scripts/booking-executor-tests.js +80 -0
  79. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  80. package/dist/scripts/booking-saga-tests.js +61 -123
  81. package/dist/scripts/booking-surface-contract-proof-tests.js +152 -1167
  82. package/dist/scripts/bootstrap-tests.js +1383 -128
  83. package/dist/scripts/build-changelog.js +89 -130
  84. package/dist/scripts/build-metrics-report.js +135 -143
  85. package/dist/scripts/changelog-tests.js +35 -82
  86. package/dist/scripts/channel-probe-tests.js +44 -116
  87. package/dist/scripts/channel-probe.js +84 -167
  88. package/dist/scripts/channel-registry-tests.js +97 -185
  89. package/dist/scripts/companion-tests.js +25 -70
  90. package/dist/scripts/dida-cookie-probe.js +87 -0
  91. package/dist/scripts/dida-sw-probe.js +114 -0
  92. package/dist/scripts/diff-test.js +17 -12
  93. package/dist/scripts/doctor-tests.js +428 -120
  94. package/dist/scripts/dsh-artifact-e2e.js +150 -0
  95. package/dist/scripts/dsh-artifact-web-e2e.js +443 -0
  96. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  97. package/dist/scripts/dsh-runtime-closure-tests.js +110 -153
  98. package/dist/scripts/dsh-runtime-closure.js +75 -63
  99. package/dist/scripts/dsh-session-v3-migration-proof.js +106 -0
  100. package/dist/scripts/dsh-subprocess-local-proof.js +149 -0
  101. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  102. package/dist/scripts/effect-tests.js +165 -552
  103. package/dist/scripts/engine-run.js +1 -3
  104. package/dist/scripts/engine-tests.js +16 -10
  105. package/dist/scripts/evaluation-cadence-tests.js +69 -242
  106. package/dist/scripts/evaluation-contract-tests.js +193 -499
  107. package/dist/scripts/extension-distribution-cli.js +19 -15
  108. package/dist/scripts/extension-distribution-tests.js +98 -211
  109. package/dist/scripts/extension-tests.js +366 -389
  110. package/dist/scripts/fact-gate-tests.js +725 -263
  111. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  112. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  113. package/dist/scripts/flight-malformed-tests.js +159 -0
  114. package/dist/scripts/flyai-tests.js +325 -68
  115. package/dist/scripts/g5-guard-tests.js +131 -0
  116. package/dist/scripts/g5-guard.js +189 -0
  117. package/dist/scripts/gen-lunar-anchors.js +106 -0
  118. package/dist/scripts/gotry-backend-kernel-tests.js +79 -0
  119. package/dist/scripts/ground-transfer-tests.js +956 -0
  120. package/dist/scripts/hbcli-e2e-tests.js +71 -90
  121. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  122. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  123. package/dist/scripts/hbcli-tests.js +41 -115
  124. package/dist/scripts/health-watch-cli.js +42 -28
  125. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  126. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  127. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  128. package/dist/scripts/i18n-tests.js +16 -9
  129. package/dist/scripts/incident-tests.js +281 -87
  130. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  131. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  132. package/dist/scripts/issue-271-liveness-tests.js +547 -0
  133. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  134. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  135. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  136. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  137. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  138. package/dist/scripts/journey-tests.js +22 -27
  139. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  140. package/dist/scripts/kernel-manifest-gate.js +126 -0
  141. package/dist/scripts/kernel-manifest-tests.js +212 -0
  142. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  143. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  144. package/dist/scripts/kernel-manifest.js +369 -0
  145. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  146. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  147. package/dist/scripts/ledger-tests.js +325 -340
  148. package/dist/scripts/ledger-workflow-crash.js +10 -20
  149. package/dist/scripts/map-tools-vendor-package-proof.js +206 -134
  150. package/dist/scripts/memory-capture-tests.js +242 -61
  151. package/dist/scripts/memory-decay-tests.js +18 -52
  152. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  153. package/dist/scripts/memory-lifecycle.js +196 -0
  154. package/dist/scripts/memory-metrics.js +24 -12
  155. package/dist/scripts/memory-value-report.js +474 -222
  156. package/dist/scripts/memory-value-tests.js +328 -0
  157. package/dist/scripts/metrics-report-tests.js +62 -199
  158. package/dist/scripts/model-override-e2e.js +66 -105
  159. package/dist/scripts/nightly-evidence-tests.js +64 -89
  160. package/dist/scripts/nightly-evidence.js +108 -111
  161. package/dist/scripts/nudge-digest.js +39 -28
  162. package/dist/scripts/onboarding-tests.js +63 -88
  163. package/dist/scripts/opensky-check.js +18 -13
  164. package/dist/scripts/opensky-tests.js +28 -28
  165. package/dist/scripts/persona-surface-guard-tests.js +37 -12
  166. package/dist/scripts/pnpm-dsh-closure-proof.js +2 -5
  167. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  168. package/dist/scripts/price-drift-tests.js +126 -227
  169. package/dist/scripts/price-drift-watch.js +209 -253
  170. package/dist/scripts/probe-poi-tests.js +52 -45
  171. package/dist/scripts/product-metrics.js +187 -273
  172. package/dist/scripts/publish-preverify.js +47 -41
  173. package/dist/scripts/realtime-pricing-tests.js +37 -76
  174. package/dist/scripts/replay-async.js +20 -18
  175. package/dist/scripts/replay-real.js +16 -18
  176. package/dist/scripts/replay.js +52 -82
  177. package/dist/scripts/session-attach-diagnose.js +16 -12
  178. package/dist/scripts/session-attach-poc.js +34 -37
  179. package/dist/scripts/session-benchmark.js +66 -147
  180. package/dist/scripts/session-dida-live-e2e.js +151 -0
  181. package/dist/scripts/session-extract-tests.js +14 -35
  182. package/dist/scripts/session-login.js +14 -13
  183. package/dist/scripts/session-tests.js +545 -583
  184. package/dist/scripts/sf-live-benchmark.js +92 -110
  185. package/dist/scripts/sf-live-cli-tests.js +2 -9
  186. package/dist/scripts/sf-soft-score-tests.js +19 -60
  187. package/dist/scripts/sf-summary-tests.js +149 -0
  188. package/dist/scripts/sf-summary.js +466 -84
  189. package/dist/scripts/skeleton-check.js +16 -14
  190. package/dist/scripts/skeleton-integration-test.js +11 -10
  191. package/dist/scripts/skills-contract-tests.js +51 -46
  192. package/dist/scripts/smoke-session-gate-tests.js +12 -20
  193. package/dist/scripts/smoke.js +541 -422
  194. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  195. package/dist/scripts/state-cli-tests.js +226 -101
  196. package/dist/scripts/state-cli.js +549 -212
  197. package/dist/scripts/static-golden-tests.js +46 -180
  198. package/dist/scripts/time-eval-tests.js +210 -192
  199. package/dist/scripts/travel-timeline-tests.js +29 -93
  200. package/dist/scripts/turn-handoff-collect-tests.js +46 -93
  201. package/dist/scripts/turn-handoff-collect.js +71 -99
  202. package/dist/scripts/turn-policy-tests.js +28 -29
  203. package/dist/scripts/typed-contract-canary.js +77 -162
  204. package/dist/scripts/tz-resolver-sanity.js +50 -0
  205. package/dist/scripts/tz-resolver-tests.js +584 -0
  206. package/dist/scripts/unified-tests.js +23 -19
  207. package/dist/scripts/visa-policy-tests.js +31 -44
  208. package/dist/scripts/weather-tests.js +121 -543
  209. package/dist/scripts/wish-channel-gate-tests.js +29 -86
  210. package/dist/scripts/write-gate-tests.js +522 -0
  211. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  212. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  213. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  214. package/dist/scripts/z3-race-tests.js +18 -12
  215. package/dist/src/artifact-gate.js +652 -221
  216. package/dist/src/backend/kernel.js +91 -0
  217. package/dist/src/backend/modules/booking-copilot.js +55 -0
  218. package/dist/src/backend/modules/booking-executor.js +124 -0
  219. package/dist/src/backend/modules/session-search.js +194 -0
  220. package/dist/src/benchmark-agent-conformance.js +296 -262
  221. package/dist/src/benchmark-environment-bridge.js +298 -413
  222. package/dist/src/benchmark-headless-child-diagnostics.js +93 -100
  223. package/dist/src/benchmark-tool-isolation.js +94 -67
  224. package/dist/src/bookable-facts.js +299 -174
  225. package/dist/src/booking-saga.js +64 -120
  226. package/dist/src/booking-surface/availability-policy.js +443 -576
  227. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  228. package/dist/src/booking-surface/contracts.js +24 -80
  229. package/dist/src/booking-surface/dsh-planner.js +510 -281
  230. package/dist/src/booking-surface/dsh-plugin.js +17 -1
  231. package/dist/src/booking-surface/error-codes.js +82 -10
  232. package/dist/src/booking-surface/index.js +0 -3
  233. package/dist/src/booking-surface/profile.js +10 -54
  234. package/dist/src/booking-surface/recovery-chain.js +367 -0
  235. package/dist/src/booking-surface/runtime.js +765 -891
  236. package/dist/src/booking-surface/server.js +200 -251
  237. package/dist/src/booking-surface/startup.js +58 -54
  238. package/dist/src/booking-surface/validation.js +150 -218
  239. package/dist/src/bridge.js +20 -13
  240. package/dist/src/companions.js +48 -74
  241. package/dist/src/contracts.js +21 -43
  242. package/dist/src/dsh-llm.js +82 -120
  243. package/dist/src/engine.js +253 -239
  244. package/dist/src/evaluation-cadence.js +72 -209
  245. package/dist/src/evaluation-contracts.js +220 -843
  246. package/dist/src/flight-pack-adapter.js +54 -0
  247. package/dist/src/flight-pack-contract.js +2 -0
  248. package/dist/src/gotry-backend.js +70 -0
  249. package/dist/src/hotel-date-gate.js +118 -0
  250. package/dist/src/i18n.js +18 -7
  251. package/dist/src/index.js +1425 -1629
  252. package/dist/src/journey.js +132 -81
  253. package/dist/src/ledger-repair-apply.js +538 -0
  254. package/dist/src/ledger-repair-plan.js +463 -0
  255. package/dist/src/loop.js +257 -166
  256. package/dist/src/memory-capture.js +180 -32
  257. package/dist/src/memory-decay.js +30 -14
  258. package/dist/src/memory-lifecycle.js +1310 -0
  259. package/dist/src/memory-utility.js +27 -40
  260. package/dist/src/mock-llm.js +36 -61
  261. package/dist/src/model.js +81 -36
  262. package/dist/src/realtime-pricing.js +63 -72
  263. package/dist/src/slot-spec.js +84 -106
  264. package/dist/src/state-ledger.js +310 -471
  265. package/dist/src/subagent-job-id-guard.js +58 -0
  266. package/dist/src/time-anchor.js +231 -33
  267. package/dist/src/tool-packet.js +20 -8
  268. package/dist/src/travel-slots.js +58 -35
  269. package/dist/src/travel-timeline.js +44 -63
  270. package/dist/src/turn-deadline.js +121 -127
  271. package/dist/src/turn-policy.js +61 -89
  272. package/dist/src/tz-resolver.js +143 -0
  273. package/dist/src/unified.js +504 -381
  274. package/dist/src/wish-pool.js +39 -14
  275. package/dist/src/write-gate.js +495 -0
  276. package/dist/src/z3-shared.js +273 -7
  277. package/extension/README.md +4 -3
  278. package/extension/background.js +125 -14
  279. package/extension/content-bridge.js +23 -1
  280. package/extension/content-main.js +15 -4
  281. package/extension/manifest.json +16 -8
  282. package/package.json +251 -220
  283. package/ts/capabilities/agent-reach.ts +4 -4
  284. package/ts/capabilities/anything.ts +1 -1
  285. package/ts/capabilities/artifacts.ts +46 -9
  286. package/ts/capabilities/flyai.ts +156 -37
  287. package/ts/capabilities/hbcli.ts +1 -1
  288. package/ts/capabilities/incident-log.ts +88 -59
  289. package/ts/capabilities/session/adapters/ctrip-flight.ts +99 -36
  290. package/ts/capabilities/session/adapters/dida-portal.ts +250 -0
  291. package/ts/capabilities/session/adapters/rail-12306.ts +123 -24
  292. package/ts/capabilities/session/extension-bridge.ts +226 -101
  293. package/ts/capabilities/session/extension-channel.ts +22 -9
  294. package/ts/capabilities/session/wizard.ts +2 -2
  295. package/ts/capabilities/session-consent.ts +98 -14
  296. package/ts/capabilities/session-login.ts +1 -0
  297. package/ts/capabilities/session-search.ts +315 -31
  298. package/ts/dsh-runtime/vendor/README.md +8 -4
  299. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +7 -1
  300. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +5 -3
  301. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +1 -1
  302. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +1 -1
  303. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +6 -6
  304. package/ts/package.json +236 -16
  305. package/ts/scripts/map-tools-vendor-package-proof.ts +152 -31
  306. package/ts/scripts/state-cli.ts +418 -51
  307. package/ts/src/artifact-gate.ts +561 -15
  308. package/ts/src/benchmark-environment-bridge.ts +37 -20
  309. package/ts/src/bookable-facts.ts +183 -7
  310. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  311. package/ts/src/booking-surface/dsh-planner.ts +240 -32
  312. package/ts/src/booking-surface/dsh-plugin.js +17 -1
  313. package/ts/src/booking-surface/error-codes.ts +75 -0
  314. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  315. package/ts/src/booking-surface/server.ts +84 -51
  316. package/ts/src/booking-surface/validation.ts +2 -0
  317. package/ts/src/contracts.ts +12 -2
  318. package/ts/src/dsh-llm.ts +4 -8
  319. package/ts/src/index.ts +609 -90
  320. package/ts/src/loop.ts +116 -7
  321. package/ts/src/memory-capture.ts +227 -3
  322. package/ts/src/mock-llm.ts +4 -8
  323. package/ts/src/model.ts +88 -2
  324. package/ts/src/state-ledger.ts +47 -29
  325. package/ts/src/subagent-job-id-guard.ts +72 -0
  326. package/ts/src/time-anchor.ts +217 -13
  327. package/ts/src/unified.ts +316 -54
@@ -1,133 +1,110 @@
1
+ /**
2
+ * Per-turn routing & time allocation (ADR-24 v2).
3
+ *
4
+ * 用户主观时间是产品路径唯一的预算:复杂度决定**出口结构**(converge /
5
+ * handoff),时间只是在所选结构内的资源分配。路由在 user/message 落地时
6
+ * 一次完成,纯函数、零 LLM、零 IO——控制面判定必须是确定性组件
7
+ * (stage1 责任铁律;ADR-9 同型先例),且不能花它要分配的资源。
8
+ *
9
+ * Tier 0(消息内禀)是 v1 的全部规则输入;Tier 1(账本读回)只在
10
+ * handoff 落单时用于工单上下文,不参与分类。`loop.ts` 的 isComplex 是
11
+ * S5 循环架构内的访谈后复核,不在产品路径上,不进本层。
12
+ */
13
+ /** v1 阈值表:数据不是代码;评测/部署换表不换执行器。 */
1
14
  export const TURN_POLICIES = {
2
- quick: {
3
- softMs: 120_000,
4
- hardMs: 180_000,
5
- exit: 'converge'
6
- },
7
- 'sync-planning': {
8
- softMs: 300_000,
9
- hardMs: 600_000,
10
- exit: 'converge'
11
- },
12
- 'deep-planning': {
13
- softMs: 120_000,
14
- hardMs: 240_000,
15
- exit: 'handoff'
16
- }
15
+ // quick:实际上限只是安全网——quick 类历史上没有发散记录。
16
+ quick: { softMs: 120_000, hardMs: 180_000, exit: 'converge' },
17
+ 'sync-planning': { softMs: 300_000, hardMs: 600_000, exit: 'converge' },
18
+ // deep-planning:同步窗口只够"摸底 + 落单承诺",到点必须转后台。
19
+ 'deep-planning': { softMs: 120_000, hardMs: 240_000, exit: 'handoff' },
17
20
  };
18
21
  export const TURN_HANDOFF_ETA_LABEL = '约 1 小时';
22
+ /** 约束词表:只作弱信号(命中≥2 才可能推 deep);新增词=加一行+一测。 */
19
23
  export const TURN_CONSTRAINT_LEXICON = [
20
- '婚礼',
21
- '婚宴',
22
- '回门',
23
- '订婚',
24
- 'IRW',
25
- 'irw',
26
- '请假',
27
- '年假',
28
- '调休',
29
- '额度',
30
- '签证',
31
- '同行',
32
- '伴侣',
33
- '亲子',
34
- '带娃',
35
- '父母',
36
- '团建',
37
- '出差',
38
- '红眼',
39
- '中转',
40
- '联程',
41
- '多城'
24
+ '婚礼', '婚宴', '回门', '订婚',
25
+ 'IRW', 'irw',
26
+ '请假', '年假', '调休', '额度',
27
+ '签证', '同行', '伴侣', '亲子', '带娃', '父母', '团建', '出差',
28
+ '红眼', '中转', '联程', '多城',
42
29
  ];
43
30
  const CN_DIGITS = {
44
- 一: 1,
45
- 二: 2,
46
- 两: 2,
47
- 三: 3,
48
- 四: 4,
49
- 五: 5,
50
- 六: 6,
51
- 七: 7,
52
- 八: 8,
53
- 九: 9,
54
- 十: 10
31
+ 一: 1, 二: 2, 两: 2, 三: 3, 四: 4, 五: 5, 六: 6, 七: 7, 八: 8, 九: 9, 十: 10,
55
32
  };
56
33
  function dayCount(year, month, day) {
34
+ // 无年份时按平年锚定:跨度计算只需要差值,月份跨年场景 v1 不覆盖。
57
35
  const y = year ?? 1970;
58
36
  return Date.UTC(y, month - 1, day) / 86_400_000;
59
37
  }
38
+ /** 跨度词 → 估算天数;按声明强度取第一个命中,v1 不做组合。 */
60
39
  function spanWordDays(message) {
61
- if (/十几天/.test(message)) return 12;
62
- if (/半个月/.test(message)) return 15;
63
- if (/一个月/.test(message)) return 30;
40
+ if (/十几天/.test(message))
41
+ return 12;
42
+ if (/半个月/.test(message))
43
+ return 15;
44
+ if (/一个月/.test(message))
45
+ return 30;
64
46
  const week = message.match(/[一两]个?(?:星期|周)/);
65
- if (week) return week[0].startsWith('两') ? 14 : 7;
47
+ if (week)
48
+ return week[0].startsWith('两') ? 14 : 7;
66
49
  const dayMatch = message.match(/([0-9一二两三四五六七八九十]+)\s*天/);
67
50
  if (dayMatch) {
68
51
  const raw = dayMatch[1];
69
- if (/^[0-9]+$/.test(raw)) return Math.min(Number.parseInt(raw, 10), 60);
70
- if (CN_DIGITS[raw] !== undefined) return Math.min(CN_DIGITS[raw], 60);
52
+ if (/^[0-9]+$/.test(raw))
53
+ return Math.min(Number.parseInt(raw, 10), 60);
54
+ if (CN_DIGITS[raw] !== undefined)
55
+ return Math.min(CN_DIGITS[raw], 60);
71
56
  }
72
57
  return null;
73
58
  }
74
59
  export function extractTurnSignals(message) {
75
60
  const absoluteDates = [];
76
- let rest = message.replace(/(?<!\d)(\d{4})[年\-.\/](\d{1,2})[月\-.\/](\d{1,2})日?(?!\d)/g, (_all, y, m, d)=>{
61
+ // 完整日期先摘除,避免 2026-10-03 再被月/日模式重复计数。
62
+ let rest = message.replace(/(?<!\d)(\d{4})[年\-.\/](\d{1,2})[月\-.\/](\d{1,2})日?(?!\d)/g, (_all, y, m, d) => {
77
63
  const month = Number.parseInt(m, 10);
78
64
  const day = Number.parseInt(d, 10);
79
65
  if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
80
- absoluteDates.push({
81
- year: Number.parseInt(y, 10),
82
- month,
83
- day
84
- });
66
+ absoluteDates.push({ year: Number.parseInt(y, 10), month, day });
85
67
  }
86
68
  return ' ';
87
69
  });
88
- rest = rest.replace(/(?<!\d)(\d{1,2})月(\d{1,2})日?(?!\d)/g, (_all, m, d)=>{
70
+ rest = rest.replace(/(?<!\d)(\d{1,2})月(\d{1,2})日?(?!\d)/g, (_all, m, d) => {
89
71
  const month = Number.parseInt(m, 10);
90
72
  const day = Number.parseInt(d, 10);
91
73
  if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
92
- absoluteDates.push({
93
- year: null,
94
- month,
95
- day
96
- });
74
+ absoluteDates.push({ year: null, month, day });
97
75
  }
98
76
  return ' ';
99
77
  });
100
- rest = rest.replace(/(?<!\d)(\d{1,2})[.\/](\d{1,2})(?!\d)/g, (_all, m, d)=>{
78
+ rest = rest.replace(/(?<!\d)(\d{1,2})[.\/](\d{1,2})(?!\d)/g, (_all, m, d) => {
101
79
  const month = Number.parseInt(m, 10);
102
80
  const day = Number.parseInt(d, 10);
103
81
  if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
104
- absoluteDates.push({
105
- year: null,
106
- month,
107
- day
108
- });
82
+ absoluteDates.push({ year: null, month, day });
109
83
  }
110
84
  return ' ';
111
85
  });
112
- const constraintHits = TURN_CONSTRAINT_LEXICON.filter((word)=>message.includes(word));
86
+ const constraintHits = TURN_CONSTRAINT_LEXICON.filter(word => message.includes(word));
113
87
  let spanDays = null;
114
88
  if (absoluteDates.length >= 2) {
115
- const counts = absoluteDates.map((d)=>dayCount(d.year, d.month, d.day));
89
+ const counts = absoluteDates.map(d => dayCount(d.year, d.month, d.day));
116
90
  spanDays = Math.max(...counts) - Math.min(...counts);
117
- } else {
91
+ }
92
+ else {
118
93
  spanDays = spanWordDays(message);
119
94
  }
120
- return {
121
- messageLength: message.length,
122
- absoluteDates,
123
- spanDays,
124
- constraintHits
125
- };
95
+ return { messageLength: message.length, absoluteDates, spanDays, constraintHits };
126
96
  }
97
+ /**
98
+ * 分类规则(有序,可表测):长跨度或多约束 → deep(转后台);无日期无约束
99
+ * 且短 → quick;其余落默认中间档 sync-planning。误分有界:三态出口保证
100
+ * 最坏结局是"本可当面答的被转了后台"(下一轮可救),而非流死掉。
101
+ */
127
102
  export function classifyTurn(message) {
128
103
  const s = extractTurnSignals(message);
129
- if (s.spanDays !== null && s.spanDays >= 7) return 'deep-planning';
130
- if (s.absoluteDates.length >= 2 && s.constraintHits.length >= 1) return 'deep-planning';
104
+ if (s.spanDays !== null && s.spanDays >= 7)
105
+ return 'deep-planning';
106
+ if (s.absoluteDates.length >= 2 && s.constraintHits.length >= 1)
107
+ return 'deep-planning';
131
108
  if (s.constraintHits.length >= 2 && (s.absoluteDates.length >= 1 || s.spanDays !== null)) {
132
109
  return 'deep-planning';
133
110
  }
@@ -137,10 +114,5 @@ export function classifyTurn(message) {
137
114
  return 'sync-planning';
138
115
  }
139
116
  export function turnPolicyFor(taskClass) {
140
- return {
141
- ...TURN_POLICIES[taskClass]
142
- };
117
+ return { ...TURN_POLICIES[taskClass] };
143
118
  }
144
-
145
-
146
- //# sourceURL=ts/src/turn-policy.ts
@@ -0,0 +1,143 @@
1
+ /**
2
+ * tz-resolver(v1):IANA 时区权威路径的统一模型输入(Issue #343)。
3
+ *
4
+ * 设计动机:
5
+ * - `ts/src/unified.ts` 既往消费 `tz_offset_min / origin_tz_offset_min / home_tz_offset_min` 数值,
6
+ * 无法表达 DST/历史/未来规则。中国出境首发已跨区(Asia/Shanghai ↔ Asia/Tokyo),
7
+ * 同一班次在不同时点 offset 不同,数值口径不可持续。
8
+ * - 此模块只做 IANA zone + 当地日期 → 确定性 offset(分)。无网络无新依赖;
9
+ * Node24 内置 `Intl.DateTimeFormat` 已足够,并由其构造结果作为 zone authority。
10
+ * - 不存在的"DST 跳过"墙时(spring forward gap)与"两次出现"的"DST 重复"墙时
11
+ * (fall back overlap)必须**显式拒绝**,不允许静默选边——这是 §acceptance 第 2 条。
12
+ * - 结果不依赖 `Date.now`、机器时区或外部 IO;formatter 仅作 module-local cache,同一输入必给同一输出。
13
+ *
14
+ * 不变量:
15
+ * - `offsetMin` 单位 = 分,正值 = 东向 UTC(Asia/Tokyo = +540)。
16
+ * - 输入校验失败返回结构化失败;调用方显式决定是否拒绝。
17
+ * - unknown zone / gap / overlap 用同名 `string` 字段区分(returned object 形态);
18
+ * 调用方负责转 typed error。
19
+ */
20
+ /**
21
+ * 以同一份 formatter cache 作为 zone authority。
22
+ * `Intl.supportedValuesOf` 不是完整 authority(例如 `US/Pacific` 等 alias 可能不列出),
23
+ * 而 `Intl.DateTimeFormat` 会接受合法 alias 并拒绝 `Foo/Bar`。
24
+ */
25
+ export function isKnownZoneLoose(zone) {
26
+ try {
27
+ wallFormatter(zone);
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ // 每个 zone 缓存一份 Intl.DateTimeFormat(root 要求:不要为每条候选 instant 重造)。
35
+ // Node 的 DateTimeFormat 本身不可缓存结果(因 ms 输入不同),但实例可重用(无外部 IO)。
36
+ const FMT_CACHE = new Map();
37
+ function wallFormatter(zone) {
38
+ let f = FMT_CACHE.get(zone);
39
+ if (f)
40
+ return f;
41
+ f = new Intl.DateTimeFormat('en-US', {
42
+ timeZone: zone,
43
+ year: 'numeric', month: '2-digit', day: '2-digit',
44
+ hour: '2-digit', minute: '2-digit',
45
+ hour12: false,
46
+ });
47
+ FMT_CACHE.set(zone, f);
48
+ return f;
49
+ }
50
+ /** UTC instant → 该 zone 的墙时分量。导出用于 workWindowBlocks 把 depUtcMs 投影到 home zone。 */
51
+ export function readWallParts(zone, ms) {
52
+ const parts = wallFormatter(zone).formatToParts(new Date(ms));
53
+ const out = {};
54
+ for (const p of parts)
55
+ out[p.type] = p.value;
56
+ // Intl en-US hour12:false 在午夜 0:00 有时给 "24";规范化回 "00"
57
+ let hour = Number(out.hour);
58
+ if (hour === 24)
59
+ hour = 0;
60
+ return {
61
+ year: Number(out.year),
62
+ month: Number(out.month),
63
+ day: Number(out.day),
64
+ hour,
65
+ minute: Number(out.minute),
66
+ };
67
+ }
68
+ /** wall 时分量 → ISO yyyy-mm-dd hh:mm 表示(供 parseFlightPackToSpecV2 work window 用)。 */
69
+ export function wallPartsToIso(p) {
70
+ return {
71
+ ymd: `${String(p.year).padStart(4, '0')}-${String(p.month).padStart(2, '0')}-${String(p.day).padStart(2, '0')}`,
72
+ hhmm: `${String(p.hour).padStart(2, '0')}:${String(p.minute).padStart(2, '0')}`,
73
+ };
74
+ }
75
+ function wallEqual(a, b) {
76
+ return a.year === b.year && a.month === b.month && a.day === b.day && a.hour === b.hour && a.minute === b.minute;
77
+ }
78
+ /**
79
+ * IANA zone + 当地日期 + 当地时间 → 确定性 offset(分)与对应 UTC instant。
80
+ *
81
+ * 失败 4 类:
82
+ * unknown_zone — `Intl.DateTimeFormat` 不接受该 zone。
83
+ * malformed_input — ymd / hhmm 解析失败或非法(wall 不存在的月日,如 2-30)。
84
+ * gap_nonexistent — DST spring-forward 跳过该墙时(墙上 02:30 不存在)。
85
+ * overlap_ambiguous — DST fall-back 重复该墙时(墙上 01:30 发生两次)。
86
+ *
87
+ * 实现要点:
88
+ * - 把 ymd/hhmm 当作 UTC 算 epoch 得到候选点 `wallAsUtcMs`;
89
+ * - 计算该候选点 offset 用 longOffset 解析,得到"大概"UTC;
90
+ * - 在 ±14h 内以 1 分步长扫描,统计能映射回同一 wall 的候选数:
91
+ * 0 → gap;1 → 唯一;≥2 → overlap。
92
+ * - 唯一候选 offset 即结果。
93
+ */
94
+ export function resolveOffsetForLocalDate(zone, ymd, hhmm) {
95
+ if (!isKnownZoneLoose(zone))
96
+ return { ok: false, kind: 'unknown_zone', zone };
97
+ const dateMatch = ymd.match(/^(\d{4})-(\d{2})-(\d{2})$/);
98
+ if (!dateMatch)
99
+ return { ok: false, kind: 'malformed_input', zone, reason: `bad date ${ymd}` };
100
+ const timeMatch = hhmm.match(/^(\d{2}):(\d{2})$/);
101
+ if (!timeMatch)
102
+ return { ok: false, kind: 'malformed_input', zone, reason: `bad time ${hhmm}` };
103
+ const y = Number(dateMatch[1]);
104
+ const mo = Number(dateMatch[2]);
105
+ const d = Number(dateMatch[3]);
106
+ const h = Number(timeMatch[1]);
107
+ const mi = Number(timeMatch[2]);
108
+ if (mo < 1 || mo > 12 || d < 1 || d > 31 || h < 0 || h > 23 || mi < 0 || mi > 59) {
109
+ return { ok: false, kind: 'malformed_input', zone, reason: `out-of-range ${ymd} ${hhmm}` };
110
+ }
111
+ const want = { year: y, month: mo, day: d, hour: h, minute: mi };
112
+ const wallAsUtcMs = Date.UTC(y, mo - 1, d, h, mi);
113
+ // ±14h 1-min 步长扫描;此范围覆盖全球 ±14:00 时区(含政治区)+ DST 1-2h 偏移
114
+ const matches = [];
115
+ for (let offMin = -14 * 60; offMin <= 14 * 60; offMin++) {
116
+ // 假 wall 是 UTC,实际 UTC 与 wall 相差 offMin 分钟。
117
+ // wall = UTC + offMin ⇒ UTC = wall - offMin。
118
+ const ms = wallAsUtcMs - offMin * 60_000;
119
+ const local = readWallParts(zone, ms);
120
+ if (wallEqual(local, want)) {
121
+ matches.push({ offsetMin: offMin, utcMs: ms });
122
+ }
123
+ }
124
+ if (matches.length === 0)
125
+ return { ok: false, kind: 'gap_nonexistent', zone, ymd, hhmm };
126
+ if (matches.length > 1)
127
+ return { ok: false, kind: 'overlap_ambiguous', zone, ymd, hhmm };
128
+ return { ok: true, offsetMin: matches[0].offsetMin, utcMs: matches[0].utcMs };
129
+ }
130
+ /**
131
+ * 仅取 offset(分),不返回 utcMs;若失败给出失败描述字符串(便于 wire 到 red_flags / unsat_core)。
132
+ *
133
+ * `unknown != null` 语义在调用方需要的场景(差异日志)很贵,故另开轻 API;
134
+ * 主路径应使用 `resolveOffsetForLocalDate` 的 discriminated union。
135
+ */
136
+ export function describeResolveFailure(f) {
137
+ switch (f.kind) {
138
+ case 'unknown_zone': return `unknown IANA zone: ${f.zone}`;
139
+ case 'malformed_input': return `malformed input (${f.reason}) for zone ${f.zone}`;
140
+ case 'gap_nonexistent': return `DST gap (wall time skipped) in ${f.zone} at ${f.ymd} ${f.hhmm}`;
141
+ case 'overlap_ambiguous': return `DST overlap (wall time ambiguous) in ${f.zone} at ${f.ymd} ${f.hhmm}`;
142
+ }
143
+ }