@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,3 +1,18 @@
1
+ /**
2
+ * Offline headless E2E for the agent turn boundary (ADR-24 v2).
3
+ *
4
+ * Exercises a clean installed-package binary on the PRODUCT path:
5
+ * bin/gotry-inner.js -> dist/src/index.js -> dsh headless -> local SSE relay
6
+ *
7
+ * 场景是失败轨迹的合成重放:deep-planning 类用户消息(10.3 婚礼 + 十几天
8
+ * + 请假 + IRW)进入路由,relay 把首个 planner 响应拖过硬阈(阈值经 env
9
+ * 压到秒级,exit 仍由路由决定为 handoff)→ 首个工具派发被拒并落
10
+ * `gotry_turn_handoff.v1` 工单 → 工具 schema 同步抑制 → 下一请求
11
+ * text-only → 二进制以含 ETA 语义的 final 收尾。工单落盘走
12
+ * GOTRY_TURN_HANDOFF_ROOT 钉死的隔离根,不触碰真实 gotry-state
13
+ * (巡检状态纪律);DSH_HOME 与 child cwd 均为临时目录,唯一模型端点
14
+ * 是 loopback。
15
+ */
1
16
  import assert from 'node:assert/strict';
2
17
  import { createServer } from 'node:http';
3
18
  import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from 'node:fs';
@@ -13,7 +28,9 @@ const HARD_MS = 10_000;
13
28
  const RELAY_STALL_MS = HARD_MS + 1_000;
14
29
  const HANDOFF = 'TURN_DEADLINE_HANDOFF';
15
30
  const HANDOFF_SCHEMA = 'gotry_turn_handoff.v1';
16
- const DEEP_MESSAGE = '2026年我还有6天IRW额度,我准备再请几天假,在国内待个十几天。' + '其中10.3要去湖南衡阳参加同学婚礼。请根据我的实际情况和偏好,给我安排行程';
31
+ /** 失败轨迹的合成等价消息:必须命中 deep-planning 路由。 */
32
+ const DEEP_MESSAGE = '2026年我还有6天IRW额度,我准备再请几天假,在国内待个十几天。'
33
+ + '其中10.3要去湖南衡阳参加同学婚礼。请根据我的实际情况和偏好,给我安排行程';
17
34
  function sse(data) {
18
35
  return `data: ${JSON.stringify(data)}\n\n`;
19
36
  }
@@ -22,156 +39,117 @@ function toolResponse(idSuffix) {
22
39
  index: 0,
23
40
  id: `deadline-call-${idSuffix}`,
24
41
  type: 'function',
25
- function: {
26
- name: TOOL,
27
- arguments: JSON.stringify({
28
- query: {
29
- limit: 1
30
- }
31
- })
32
- }
42
+ function: { name: TOOL, arguments: JSON.stringify({ query: { limit: 1 } }) },
33
43
  };
34
44
  return sse({
35
45
  id: `deadline-${idSuffix}`,
36
46
  object: 'chat.completion.chunk',
37
47
  created: 1,
38
48
  model: 'synthetic-deadline-model',
39
- choices: [
40
- {
41
- index: 0,
42
- delta: {
43
- role: 'assistant',
44
- tool_calls: [
45
- call
46
- ]
47
- },
48
- finish_reason: null
49
- }
50
- ]
49
+ choices: [{ index: 0, delta: { role: 'assistant', tool_calls: [call] }, finish_reason: null }],
51
50
  }) + sse({
52
51
  id: `deadline-${idSuffix}-finish`,
53
52
  object: 'chat.completion.chunk',
54
53
  created: 1,
55
54
  model: 'synthetic-deadline-model',
56
- choices: [
57
- {
58
- index: 0,
59
- delta: {},
60
- finish_reason: 'tool_calls'
61
- }
62
- ]
55
+ choices: [{ index: 0, delta: {}, finish_reason: 'tool_calls' }],
63
56
  }) + 'data: [DONE]\n\n';
64
57
  }
65
58
  function textResponse(text, id = 'deadline-final') {
66
59
  return sse({
67
- id,
68
- object: 'chat.completion.chunk',
69
- created: 1,
60
+ id, object: 'chat.completion.chunk', created: 1,
70
61
  model: 'synthetic-deadline-model',
71
- choices: [
72
- {
73
- index: 0,
74
- delta: {
75
- role: 'assistant',
76
- content: text
77
- },
78
- finish_reason: null
79
- }
80
- ]
62
+ choices: [{ index: 0, delta: { role: 'assistant', content: text }, finish_reason: null }],
81
63
  }) + sse({
82
- id: `${id}-finish`,
83
- object: 'chat.completion.chunk',
84
- created: 1,
85
- model: 'synthetic-deadline-model',
86
- choices: [
87
- {
88
- index: 0,
89
- delta: {},
90
- finish_reason: 'stop'
91
- }
92
- ]
64
+ id: `${id}-finish`, object: 'chat.completion.chunk', created: 1,
65
+ model: 'synthetic-deadline-model', choices: [{ index: 0, delta: {}, finish_reason: 'stop' }],
93
66
  }) + 'data: [DONE]\n\n';
94
67
  }
95
68
  async function startRelay() {
96
69
  const bodies = [];
97
70
  const plannerBodies = [];
98
- const server = createServer((req, res)=>{
71
+ const server = createServer((req, res) => {
99
72
  if (req.method !== 'POST' || !req.url?.endsWith('/chat/completions')) {
100
73
  res.writeHead(404).end('not found');
101
74
  return;
102
75
  }
103
76
  const chunks = [];
104
- req.on('data', (chunk)=>chunks.push(Buffer.from(chunk)));
105
- req.on('end', ()=>{
77
+ req.on('data', chunk => chunks.push(Buffer.from(chunk)));
78
+ req.on('end', () => {
106
79
  let body;
107
80
  try {
108
81
  body = JSON.parse(Buffer.concat(chunks).toString('utf8'));
109
- } catch {
82
+ }
83
+ catch {
110
84
  body = {};
111
85
  }
112
86
  bodies.push(body);
113
- res.writeHead(200, {
114
- 'content-type': 'text/event-stream',
115
- 'cache-control': 'no-cache'
116
- });
87
+ res.writeHead(200, { 'content-type': 'text/event-stream', 'cache-control': 'no-cache' });
117
88
  if (toolNames(body).includes(TOOL)) {
118
89
  plannerBodies.push(body);
119
90
  const plannerIndex = plannerBodies.length;
120
- const realToolMessages = (body.messages ?? []).filter((message)=>message.role === 'tool');
121
- const alreadyHandedOff = realToolMessages.some((message)=>JSON.stringify(message).includes(HANDOFF));
91
+ // issue #205:已交接判定只认真实 role=tool 消息(persona (21)
92
+ // TURN_DEADLINE_HANDOFF 字面量也在 system 文本里,整包扫描会首轮误判
93
+ // 已交接 → 永不派发工具 → handoff 语义测试退化为纯文本收尾)。
94
+ const realToolMessages = (body.messages ?? []).filter(message => message.role === 'tool');
95
+ const alreadyHandedOff = realToolMessages.some(message => JSON.stringify(message).includes(HANDOFF));
96
+ // 首个 planner 响应拖过硬阈:首个工具派发必然越过 wall-clock 边界。
97
+ // handoff 发生后,后续 planner 请求一律回 text-only final,收敛回路。
122
98
  const stall = !alreadyHandedOff && plannerIndex === 1 ? RELAY_STALL_MS : 0;
123
- setTimeout(()=>{
99
+ setTimeout(() => {
124
100
  if (!alreadyHandedOff && plannerIndex === 1) {
125
101
  res.end(toolResponse(String(plannerIndex)));
126
- } else {
102
+ }
103
+ else {
127
104
  res.end(textResponse('deadline E2E final answer'));
128
105
  }
129
106
  }, stall);
130
- } else {
107
+ }
108
+ else {
109
+ // Session-title and other auxiliary calls deliberately carry no tool
110
+ // schemas. Keep them out of the planner-call budget and answer text.
131
111
  res.end(textResponse('deadline E2E final answer', 'deadline-auxiliary'));
132
112
  }
133
113
  });
134
114
  });
135
- await new Promise((resolve)=>server.listen(0, '127.0.0.1', resolve));
115
+ await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
136
116
  return {
137
117
  port: server.address().port,
138
118
  bodies,
139
119
  plannerBodies,
140
- close: ()=>new Promise((resolve)=>server.close(()=>resolve()))
120
+ close: () => new Promise(resolve => server.close(() => resolve())),
141
121
  };
142
122
  }
143
123
  function allToolMessages(bodies) {
144
- return bodies.flatMap((body)=>(body.messages ?? []).filter((message)=>message.role === 'tool'));
124
+ return bodies.flatMap(body => (body.messages ?? []).filter(message => message.role === 'tool'));
145
125
  }
146
126
  function toolNames(body) {
147
- return (body.tools ?? []).map((tool)=>{
127
+ return (body.tools ?? []).map(tool => {
148
128
  const fn = tool.function;
149
129
  return String(fn?.name ?? tool.name ?? '');
150
130
  }).filter(Boolean);
151
131
  }
152
132
  async function main() {
153
- for (const file of [
154
- 'dist/src/index.js',
155
- 'dist/capabilities/artifacts.js'
156
- ]){
133
+ for (const file of ['dist/src/index.js', 'dist/capabilities/artifacts.js']) {
157
134
  assert.ok(existsSync(join(ROOT, file)), `missing ${file}; run node scripts/build-dist.mjs first`);
158
135
  }
159
136
  const relay = await startRelay();
160
137
  const dshHome = mkdtempSync(join(tmpdir(), 'gotry-deadline-dsh-home-'));
161
138
  const childCwd = mkdtempSync(join(tmpdir(), 'gotry-deadline-cwd-'));
139
+ // 巡检状态纪律:handoff 工单只落隔离根(source 模式 dsh cwd 是创始人真实
140
+ // 数据目录 ts/dsh-runtime,绝不让 E2E 往那里写)。
162
141
  const handoffRoot = mkdtempSync(join(tmpdir(), 'gotry-deadline-handoff-'));
163
142
  let exitCode = null;
164
143
  let output = '';
165
144
  const configuredBin = process.env.GOTRY_DEADLINE_E2E_BIN;
166
145
  assert.ok(configuredBin && existsSync(configuredBin), 'GOTRY_DEADLINE_E2E_BIN must point to the clean installed-package binary');
167
146
  try {
168
- const executableArgs = [
169
- DEEP_MESSAGE
170
- ];
171
- const childEnv = {
172
- ...process.env
173
- };
147
+ const executableArgs = [DEEP_MESSAGE];
148
+ const childEnv = { ...process.env };
174
149
  childEnv.DSH_HOME = dshHome;
150
+ // 可选宿主插件(calendar)挂载与否由 setup 状态面(~/.gotry/calendar.json)决定,
151
+ // 不吃 env(D-9 founder 纠偏)——E2E 隔离手段=HOME 指到临时目录(os.homedir()
152
+ // 尊重 $HOME),子进程看不到真实机器的 setup 态;dsh 配置面已由 DSH_HOME 单独隔离。
175
153
  childEnv.HOME = dshHome;
176
154
  childEnv.LLM_API_KEY = 'synthetic-e2e-key';
177
155
  childEnv.LLM_BASE_URL = 'http://127.0.0.1:' + relay.port + '/v1';
@@ -185,60 +163,57 @@ async function main() {
185
163
  const child = spawn(configuredBin, executableArgs, {
186
164
  cwd: childCwd,
187
165
  env: childEnv,
188
- stdio: [
189
- 'ignore',
190
- 'pipe',
191
- 'pipe'
192
- ]
193
- });
194
- child.stdout.on('data', (chunk)=>{
195
- output += chunk.toString();
166
+ stdio: ['ignore', 'pipe', 'pipe'],
196
167
  });
197
- child.stderr.on('data', (chunk)=>{
198
- output += chunk.toString();
168
+ child.stdout.on('data', chunk => { output += chunk.toString(); });
169
+ child.stderr.on('data', chunk => { output += chunk.toString(); });
170
+ exitCode = await new Promise(resolve => {
171
+ const timer = setTimeout(() => { child.kill('SIGKILL'); resolve(null); }, TIMEOUT_MS);
172
+ child.once('exit', code => { clearTimeout(timer); resolve(code); });
199
173
  });
200
- exitCode = await new Promise((resolve)=>{
201
- const timer = setTimeout(()=>{
202
- child.kill('SIGKILL');
203
- resolve(null);
204
- }, TIMEOUT_MS);
205
- child.once('exit', (code)=>{
206
- clearTimeout(timer);
207
- resolve(code);
208
- });
209
- });
210
- } finally{
211
- await new Promise((resolve)=>setTimeout(resolve, 200));
174
+ }
175
+ finally {
176
+ // relay 故意不在此关闭:收集闭环段还要以同一 relay 做模型端点。
177
+ // Give the spawned binary a brief moment to release its temp files
178
+ // before we recursively remove the tmpdir.
179
+ await new Promise(resolve => setTimeout(resolve, 200));
212
180
  }
213
181
  assert.equal(exitCode, 0, `headless exit=${exitCode}; output tail=${output.slice(-1200)}`);
214
182
  assert.ok(relay.plannerBodies.length >= 1, `expected at least one tool-enabled planner request, got ${relay.plannerBodies.length}; output tail=${output.slice(-12_000)}`);
183
+ // 首个工具派发越过硬阈:必须得到 handoff 语义的结构化拒绝,且没有任何
184
+ // 工具 body 真正执行。
215
185
  const toolMessages = allToolMessages(relay.bodies);
216
186
  const toolMessageDiagnostic = JSON.stringify(toolMessages).slice(-12_000);
217
- const handoffResults = toolMessages.filter((message)=>JSON.stringify(message).includes(HANDOFF));
218
- const successfulResults = toolMessages.filter((message)=>!JSON.stringify(message).includes(HANDOFF));
187
+ const handoffResults = toolMessages.filter(message => JSON.stringify(message).includes(HANDOFF));
188
+ const successfulResults = toolMessages.filter(message => !JSON.stringify(message).includes(HANDOFF));
219
189
  assert.ok(handoffResults.length >= 1, `expected at least one handoff result; messages=${toolMessageDiagnostic}`);
220
190
  assert.equal(successfulResults.length, 0, `no tool body should run past the hard deadline; messages=${toolMessageDiagnostic}`);
221
191
  assert.match(JSON.stringify(handoffResults[0]), /th-/, 'handoff result carries the ticket id');
192
+ // handoff 工单已落隔离根,字段完整(含用户原文与 ETA 承诺)。
222
193
  const ticketDir = join(handoffRoot, 'gotry-state', 'turn-handoffs');
223
194
  assert.ok(existsSync(ticketDir), `ticket dir missing: ${ticketDir}`);
224
- const ticketFiles = readdirSync(ticketDir).filter((name)=>name.endsWith('.json'));
195
+ const ticketFiles = readdirSync(ticketDir).filter(name => name.endsWith('.json'));
225
196
  assert.equal(ticketFiles.length, 1, `expected exactly one handoff ticket, got ${ticketFiles.join(', ')}`);
226
197
  const ticket = JSON.parse(readFileSync(join(ticketDir, ticketFiles[0]), 'utf8'));
227
198
  assert.equal(ticket['schema'], HANDOFF_SCHEMA);
228
199
  assert.equal(ticket['status'], 'open');
229
200
  assert.ok(String(ticket['userMessage']).includes('婚礼'), 'ticket carries the verbatim deep-planning ask');
230
201
  assert.ok(String(ticket['etaLabel']).includes('约 1 小时'));
202
+ // 回路收敛:最终请求不带任何继承工具 schema,二进制输出 final。
231
203
  const finalRequest = relay.bodies.at(-1);
232
204
  const finalNames = toolNames(finalRequest);
233
205
  assert.ok(!finalNames.includes(TOOL), `final request inherited GoTry tool: ${finalNames.join(', ')}`);
234
206
  assert.match(output, /deadline E2E final answer/);
207
+ // ---- 收集闭环:collector 以真打包二进制为 planner 回收这单工单。------
208
+ // 子会话(GOTRY_HANDOFF_CHILD=1)带满工具面打到 relay;relay 的全局
209
+ // plannerIndex 已 >1,立即回 text-only final → 子会话 converge 退出,
210
+ // collector 把最终答复结算为交付物。工单 open→settled,交付物可复访。
235
211
  {
236
212
  const ticketId = String(ticket['id']);
237
213
  const collector = spawn(process.execPath, [
238
214
  join(TS_DIR, 'node_modules', 'tsx', 'dist', 'cli.mjs'),
239
215
  join(TS_DIR, 'scripts', 'turn-handoff-collect.ts'),
240
- ticketId,
241
- handoffRoot
216
+ ticketId, handoffRoot,
242
217
  ], {
243
218
  cwd: TS_DIR,
244
219
  env: {
@@ -247,31 +222,17 @@ async function main() {
247
222
  LLM_API_KEY: 'synthetic-e2e-key',
248
223
  LLM_BASE_URL: 'http://127.0.0.1:' + relay.port + '/v1',
249
224
  LLM_MODEL: 'synthetic-deadline-model',
250
- GOTRY_LOCALE: 'zh-CN'
225
+ GOTRY_LOCALE: 'zh-CN',
251
226
  },
252
- stdio: [
253
- 'ignore',
254
- 'pipe',
255
- 'pipe'
256
- ]
227
+ stdio: ['ignore', 'pipe', 'pipe'],
257
228
  });
258
229
  let collectorOut = '';
259
230
  let collectorErr = '';
260
- collector.stdout.on('data', (chunk)=>{
261
- collectorOut += chunk.toString();
262
- });
263
- collector.stderr.on('data', (chunk)=>{
264
- collectorErr += chunk.toString();
265
- });
266
- const collectorCode = await new Promise((resolve)=>{
267
- const timer = setTimeout(()=>{
268
- collector.kill('SIGKILL');
269
- resolve(null);
270
- }, 90_000);
271
- collector.once('exit', (code)=>{
272
- clearTimeout(timer);
273
- resolve(code);
274
- });
231
+ collector.stdout.on('data', chunk => { collectorOut += chunk.toString(); });
232
+ collector.stderr.on('data', chunk => { collectorErr += chunk.toString(); });
233
+ const collectorCode = await new Promise(resolve => {
234
+ const timer = setTimeout(() => { collector.kill('SIGKILL'); resolve(null); }, 90_000);
235
+ collector.once('exit', code => { clearTimeout(timer); resolve(code); });
275
236
  });
276
237
  assert.equal(collectorCode, 0, `collector exit=${collectorCode}; stderr tail=${collectorErr.slice(-800)}; stdout tail=${collectorOut.slice(-400)}`);
277
238
  const terminal = JSON.parse(collectorOut.trim().split('\n').at(-1));
@@ -286,20 +247,8 @@ async function main() {
286
247
  }
287
248
  console.log(`agent turn deadline E2E: OK (exit=${exitCode}, plannerRequests=${relay.plannerBodies.length}, handoffResults=${handoffResults.length}, ticket=${ticketFiles[0]}, collected=settled)`);
288
249
  await relay.close();
289
- rmSync(dshHome, {
290
- recursive: true,
291
- force: true
292
- });
293
- rmSync(childCwd, {
294
- recursive: true,
295
- force: true
296
- });
297
- rmSync(handoffRoot, {
298
- recursive: true,
299
- force: true
300
- });
250
+ rmSync(dshHome, { recursive: true, force: true });
251
+ rmSync(childCwd, { recursive: true, force: true });
252
+ rmSync(handoffRoot, { recursive: true, force: true });
301
253
  }
302
254
  await main();
303
-
304
-
305
- //# sourceURL=ts/scripts/agent-planning-turn-deadline-e2e.ts