@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
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Issue #359 — 政策锚点全字段内容指纹(注册 `gotry_fact_gate` 路径 E2E)。
3
+ *
4
+ * 真实执行面:在临时 stateRoot 下装载 gotry-tools 插件,通过 `apply(ctx, config)`
5
+ * 装载注册定义,捕获 `gotry_fact_gate` 的 execute 函数,以 markdown 直接调用——
6
+ * 经注册的 tool definition 走完 `loadFactRegistry(stateRoot)` → `gateArtifact`
7
+ * → `itinerary.trip_start` 桥接(issue #359 finding 2),完整覆盖公开闸侧路径。
8
+ * 不启动 dsh 宿主、不调用真实 ToolRuntime、不触碰供应商 / browser / policy
9
+ * service / 共享状态。
10
+ *
11
+ * 运行(在 ts/ 下):
12
+ * PATH=/opt/homebrew/opt/node@24/bin:$PATH GOTRY_SESSION_LIVE=0 \
13
+ * npx tsx scripts/policy-anchor-359-registered-e2e.ts
14
+ */
15
+ import assert from 'node:assert/strict';
16
+ import { mkdtempSync, rmSync, mkdirSync } from 'node:fs';
17
+ import { tmpdir } from 'node:os';
18
+ import { join } from 'node:path';
19
+ import { apply } from '../src/index.js';
20
+ import { BOOKABLE_FACT_SCHEMA, makeFactId, renderPolicyFact, } from '../src/bookable-facts.js';
21
+ import { appendFacts } from '../capabilities/fact-log.js';
22
+ const FETCHED = '2026-09-10T00:00:00.000Z';
23
+ async function main() {
24
+ const home = mkdtempSync(join(tmpdir(), 'gotry-policy-359-registered-'));
25
+ const stateRoot = join(home, 'state');
26
+ const cwd = join(home, 'workspace');
27
+ mkdirSync(stateRoot, { recursive: true });
28
+ mkdirSync(cwd, { recursive: true });
29
+ const policy = {
30
+ schema: BOOKABLE_FACT_SCHEMA,
31
+ fact_id: makeFactId(['policy-359', 'reg', '泰国免签']),
32
+ kind: 'policy',
33
+ subject: '泰国入境(中国护照)',
34
+ statement: '免签停留(口径以泰方公告为准);UAE 居民返程应优先校验 residence visa / Emirates ID 而非游客免签口径',
35
+ source: 'web:official',
36
+ query_id: 'web:policy:泰国免签',
37
+ fetched_at: FETCHED,
38
+ as_of: '2026-08-29',
39
+ };
40
+ // 走真实事实日志路径(append-only JSONL),与产品 gotry_flyai_search /
41
+ // gotry_session_search 同款事实落账接口;闸侧 loadFactRegistry 直接读这里。
42
+ await appendFacts(stateRoot, [policy]);
43
+ // 装载 gotry-tools 插件 → 捕获 gotry_fact_gate 的真实 execute。
44
+ const registered = [];
45
+ const ctx = {
46
+ tools: { register: (t) => registered.push(t) },
47
+ systemPrompt: { section: () => undefined, variable: () => undefined },
48
+ on: () => () => undefined,
49
+ };
50
+ apply(ctx, {
51
+ stateRoot,
52
+ timeoutMs: 30_000,
53
+ hbcliBin: 'hbcli-not-on-path',
54
+ sessionAccess: 'off',
55
+ });
56
+ const factGate = registered.find(t => t.name === 'gotry_fact_gate');
57
+ if (!factGate)
58
+ throw new Error(`FAIL: 注册定义列表缺少 gotry_fact_gate,实际注册: ${registered.map(t => t.name).join(',')}`);
59
+ const exec = { agent: { session: { header: { cwd } } } };
60
+ // Case 1:canonical no-reminder 行经真实 gotry_fact_gate → pass。
61
+ const canonicalLine = renderPolicyFact(policy);
62
+ const c1Artifact = ['## 政策', canonicalLine].join('\n');
63
+ const r1 = await factGate.execute({ markdown: c1Artifact }, exec);
64
+ assert.equal(r1.verdict, 'pass', `canonical no-reminder 经注册闸应 pass,实际: ${JSON.stringify({ verdict: r1.verdict, summary: r1.summary })}`);
65
+ assert.equal(r1.traceable, 1);
66
+ console.log(` ok - 注册 gotry_fact_gate canonical no-reminder → pass`);
67
+ // Case 2:legitimate review_by(事实自带)— 无 trip_start,canonical body 已含复核提醒。
68
+ const reviewByPolicy = { ...policy, fact_id: makeFactId(['policy-359', 'reg', 'review-by']), review_by: '2027-06-16' };
69
+ await appendFacts(stateRoot, [reviewByPolicy]);
70
+ const reviewByLine = renderPolicyFact(reviewByPolicy);
71
+ const r2 = await factGate.execute({ markdown: ['## 政策', reviewByLine].join('\n') }, exec);
72
+ assert.equal(r2.verdict, 'pass', `legitimate review_by 经注册闸应 pass,实际: ${JSON.stringify({ verdict: r2.verdict, summary: r2.summary })}`);
73
+ console.log(` ok - 注册 gotry_fact_gate legitimate review_by → pass`);
74
+ // Case 3:legitimate tripStart-derived reminder — 通过已加载 itinerary.trip_start 桥接
75
+ // (不要求调用方额外传 opts.tripStart;闸侧自动从 itinerary 派)。
76
+ // itinerary 必须保持自身不变量合法(nights/legs),否则闸会被 itineraryInvariants
77
+ // 单独阻断,影响 policy 收口的可读性。这里给一个合法的同日往返零夜行程。
78
+ const tripStart = '2027-07-16';
79
+ const tripStartLine = renderPolicyFact(policy, tripStart);
80
+ const r3 = await factGate.execute({
81
+ markdown: ['## 政策', tripStartLine].join('\n'),
82
+ itinerary: {
83
+ trip_start: tripStart,
84
+ trip_end: tripStart,
85
+ stays: [],
86
+ onboard_nights: 0,
87
+ od_segments: [],
88
+ budget_items: [],
89
+ },
90
+ }, exec);
91
+ assert.equal(r3.verdict, 'pass', `legitimate tripStart-derived reminder 经注册闸应 pass,实际: ${JSON.stringify({ verdict: r3.verdict, summary: r3.summary })}`);
92
+ console.log(` ok - 注册 gotry_fact_gate legitimate tripStart reminder(经 itinerary.trip_start 桥接)→ pass`);
93
+ // Case 4:trailing-after-anchor 攻击:合法 fact_id + 锚点后追加相反政策正文 → blocked。
94
+ const trailingLine = `${canonicalLine} 反而是落地签,需提前办签证`;
95
+ const r4 = await factGate.execute({ markdown: ['## 政策', trailingLine].join('\n') }, exec);
96
+ assert.equal(r4.verdict, 'blocked', `trailing-after-anchor 经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r4.verdict, summary: r4.summary })}`);
97
+ assert.ok(r4.violations?.some(v => v.kind === 'fact_anchor_unknown'), `trailing-after-anchor 应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r4.violations?.map(v => v.kind))}`);
98
+ console.log(` ok - 注册 gotry_fact_gate trailing-after-anchor 攻击 → blocked/fact_anchor_unknown`);
99
+ // Case 5:subject 篡改(原 main 静默 pass 的反例)。
100
+ const tamperedSubject = canonicalLine.replace('泰国入境(中国护照)', '另一对象的政策');
101
+ const r5 = await factGate.execute({ markdown: ['## 政策', tamperedSubject].join('\n') }, exec);
102
+ assert.equal(r5.verdict, 'blocked', `subject 篡改经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r5.verdict, summary: r5.summary })}`);
103
+ assert.ok(r5.violations?.some(v => v.kind === 'fact_anchor_unknown'), `subject 篡改应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r5.violations?.map(v => v.kind))}`);
104
+ console.log(` ok - 注册 gotry_fact_gate subject 篡改 → blocked/fact_anchor_unknown`);
105
+ // Case 6:opposite statement 篡改 — 现实威胁:沿用合法 fact_id + 锚点改写 statement 方向。
106
+ const oppositeStatement = canonicalLine.replace('免签停留', '不免签,需提前办签证');
107
+ const r6 = await factGate.execute({ markdown: ['## 政策', oppositeStatement].join('\n') }, exec);
108
+ assert.equal(r6.verdict, 'blocked', `opposite statement 篡改经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r6.verdict, summary: r6.summary })}`);
109
+ assert.ok(r6.violations?.some(v => v.kind === 'fact_anchor_unknown'), `opposite statement 应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r6.violations?.map(v => v.kind))}`);
110
+ console.log(` ok - 注册 gotry_fact_gate opposite statement 篡改 → blocked/fact_anchor_unknown`);
111
+ // Case 7:provenance 篡改(source / fetched_at / query_id 任一)→ blocked。
112
+ const tamperedProv = canonicalLine
113
+ .replace('[web:official@', '[synthetic:official@')
114
+ .replace(FETCHED, '2026-09-01T00:00:00.000Z')
115
+ .replace('#web:policy:泰国免签', '#synthetic:policy:泰国免签');
116
+ const r7 = await factGate.execute({ markdown: ['## 政策', tamperedProv].join('\n') }, exec);
117
+ assert.equal(r7.verdict, 'blocked', `provenance 篡改经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r7.verdict, summary: r7.summary })}`);
118
+ assert.ok(r7.violations?.some(v => v.kind === 'fact_anchor_unknown'), `provenance 篡改应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r7.violations?.map(v => v.kind))}`);
119
+ console.log(` ok - 注册 gotry_fact_gate provenance(source/fetched_at/query_id)篡改 → blocked/fact_anchor_unknown`);
120
+ // Compatibility(issue #359 final repair):注册闸侧既不传 itinerary、调用方也不显式
121
+ // opts.tripStart 时,renderer 给的两类合法 canonical form 必须经真实 gotry_fact_gate
122
+ // pass;否则(伪 reminder 日期、body 篡改、review_by 改写、trailing-after-anchor)
123
+ // 必须仍走 fact_anchor_unknown。证明兼容性回退收敛于 renderer 自身的输出空间,
124
+ // 不引入新公共 API,也不放行任意政策文本。
125
+ const compatExec = exec;
126
+ // Case 8:context-free canonical no-reminder 经注册闸 → pass
127
+ // (renderer 不接 tripStart,policy 也无 review_by → 不应出现 reminder 段)
128
+ const r8 = await factGate.execute({ markdown: ['## 政策', canonicalLine].join('\n') }, compatExec);
129
+ assert.equal(r8.verdict, 'pass', `context-free no-reminder 经注册闸应 pass,实际: ${JSON.stringify({ verdict: r8.verdict, summary: r8.summary })}`);
130
+ assert.equal(r8.traceable, 1);
131
+ console.log(` ok - 注册 gotry_fact_gate context-free canonical no-reminder → pass`);
132
+ // Case 9:context-free canonical reminder(renderer 默认 defaultReviewBy(as_of))→ pass
133
+ // 这是 issue #273 已有的历史形态,最终修复必须恢复。
134
+ const compatTripStart = '2027-08-01';
135
+ const compatTripStartLine = renderPolicyFact(policy, compatTripStart);
136
+ const r9 = await factGate.execute({ markdown: ['## 政策', compatTripStartLine].join('\n') }, compatExec);
137
+ assert.equal(r9.verdict, 'pass', `context-free derived reminder(无 itinerary 桥接)经注册闸应 pass,实际: ${JSON.stringify({ verdict: r9.verdict, summary: r9.summary })}`);
138
+ assert.equal(r9.traceable, 1);
139
+ console.log(` ok - 注册 gotry_fact_gate context-free canonical derived reminder(无 itinerary 桥接)→ pass`);
140
+ // Case 10:context-free canonical reminder(review_by 已知)→ pass
141
+ // reviewByPolicy 已在 Case 2 装载;这里只重复调用同一锚定行,证明无 itinerary 仍合法
142
+ const r10 = await factGate.execute({ markdown: ['## 政策', reviewByLine].join('\n') }, compatExec);
143
+ assert.equal(r10.verdict, 'pass', `context-free canonical reminder(review_by 已知)经注册闸应 pass,实际: ${JSON.stringify({ verdict: r10.verdict, summary: r10.summary })}`);
144
+ assert.equal(r10.traceable, 1);
145
+ console.log(` ok - 注册 gotry_fact_gate context-free canonical reminder(review_by 已知)→ pass`);
146
+ // Case 11:context-free reminder 错位(把 reminder 段追加到 provenance 之后,而不是
147
+ // renderer 固定位置 `[provenance]` 之前)→ 重建 `renderPolicyFact({...f, review_by: '1999-01-01'})`
148
+ // 与原行不匹配 → fail-closed。日期 '1999-01-01' 本身合法 ISO 阳历日;此例证伪在于
149
+ // reminder 位置错配,不在日期本身。
150
+ const compatBadDateLine = `${canonicalLine};远期政策须复核——到 1999-01-01 再核验一次 <!-- fact:${policy.fact_id} -->`;
151
+ const r11 = await factGate.execute({ markdown: ['## 政策', compatBadDateLine].join('\n') }, compatExec);
152
+ assert.equal(r11.verdict, 'blocked', `reminder 错位经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r11.verdict, summary: r11.summary })}`);
153
+ assert.ok(r11.violations?.some(v => v.kind === 'fact_anchor_unknown'), `reminder 错位应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r11.violations?.map(v => v.kind))}`);
154
+ console.log(` ok - 注册 gotry_fact_gate context-free reminder 错位 → blocked/fact_anchor_unknown`);
155
+ // Case 12:context-free body 篡改(免签停留 → 不免签停留,保留 fact_id 锚点)→ blocked
156
+ const compatBadBodyLine = canonicalLine.replace('免签停留', '不免签停留');
157
+ const r12 = await factGate.execute({ markdown: ['## 政策', compatBadBodyLine].join('\n') }, compatExec);
158
+ assert.equal(r12.verdict, 'blocked', `body 篡改经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r12.verdict, summary: r12.summary })}`);
159
+ assert.ok(r12.violations?.some(v => v.kind === 'fact_anchor_unknown'), `body 篡改应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r12.violations?.map(v => v.kind))}`);
160
+ console.log(` ok - 注册 gotry_fact_gate context-free body 篡改 → blocked/fact_anchor_unknown`);
161
+ // Case 13:context-free review_by 篡改(事实带 review_by,改 reminder 日期)→ blocked
162
+ // 根 contract 第 2 条:若事实自带 review_by,renderer 优先级 review_by > tripStart,
163
+ // reminder 日期必须 == f.review_by;改了就是伪造。这里注册的是带 review_by 的事实。
164
+ const fReviewBy = { ...policy, fact_id: makeFactId(['policy-359', 'reg', 'review-by-tamper']), review_by: '2027-06-16' };
165
+ await appendFacts(stateRoot, [fReviewBy]);
166
+ const compatReviewByTamperedLine = renderPolicyFact(fReviewBy).replace('2027-06-16', '2027-12-31');
167
+ const r13 = await factGate.execute({ markdown: ['## 政策', compatReviewByTamperedLine].join('\n') }, compatExec);
168
+ assert.equal(r13.verdict, 'blocked', `事实带 review_by 时改 reminder 日期经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r13.verdict, summary: r13.summary })}`);
169
+ assert.ok(r13.violations?.some(v => v.kind === 'fact_anchor_unknown'), `事实带 review_by 时改 reminder 日期应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r13.violations?.map(v => v.kind))}`);
170
+ console.log(` ok - 注册 gotry_fact_gate 事实带 review_by 改 reminder 日期 → blocked/fact_anchor_unknown`);
171
+ // Case 14:context-free trailing-after-anchor(锚点后追加非空)→ blocked
172
+ const compatTrailingLine = `${canonicalLine} 反而是落地签`;
173
+ const r14 = await factGate.execute({ markdown: ['## 政策', compatTrailingLine].join('\n') }, compatExec);
174
+ assert.equal(r14.verdict, 'blocked', `trailing-after-anchor 经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r14.verdict, summary: r14.summary })}`);
175
+ assert.ok(r14.violations?.some(v => v.kind === 'fact_anchor_unknown'), `trailing-after-anchor 应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r14.violations?.map(v => v.kind))}`);
176
+ console.log(` ok - 注册 gotry_fact_gate context-free trailing-after-anchor → blocked/fact_anchor_unknown`);
177
+ // Case 15:itinerary.trip_start 与 renderer reminder 不一致 → blocked
178
+ // 闸侧走 itinerary 派发后不再回退兼容,renderer 给的是 2027-08-01 而 itinerary
179
+ // 给的是 2027-08-15 → 必 fail-closed。
180
+ const r15 = await factGate.execute({
181
+ markdown: ['## 政策', compatTripStartLine].join('\n'),
182
+ itinerary: {
183
+ trip_start: '2027-08-15',
184
+ trip_end: '2027-08-15',
185
+ stays: [],
186
+ onboard_nights: 0,
187
+ od_segments: [],
188
+ budget_items: [],
189
+ },
190
+ }, compatExec);
191
+ assert.equal(r15.verdict, 'blocked', `itinerary 与 reminder 不一致经注册闸应 blocked,实际: ${JSON.stringify({ verdict: r15.verdict, summary: r15.summary })}`);
192
+ assert.ok(r15.violations?.some(v => v.kind === 'fact_anchor_unknown'), `itinerary 与 reminder 不一致应有 fact_anchor_unknown 违例,实际: ${JSON.stringify(r15.violations?.map(v => v.kind))}`);
193
+ console.log(` ok - 注册 gotry_fact_gate itinerary 与 reminder 不一致 → blocked/fact_anchor_unknown`);
194
+ // Case 16:itinerary.trip_start 存在时 canonical no-reminder 仍合法 → pass
195
+ // renderer 没接 tripStart 时,policy 文本里没有 reminder 段,与 itinerary 共存
196
+ // 仍是合法的 canonical body。
197
+ const r16 = await factGate.execute({
198
+ markdown: ['## 政策', canonicalLine].join('\n'),
199
+ itinerary: {
200
+ trip_start: '2027-08-15',
201
+ trip_end: '2027-08-15',
202
+ stays: [],
203
+ onboard_nights: 0,
204
+ od_segments: [],
205
+ budget_items: [],
206
+ },
207
+ }, compatExec);
208
+ assert.equal(r16.verdict, 'pass', `itinerary 存在时 canonical no-reminder 经注册闸应 pass,实际: ${JSON.stringify({ verdict: r16.verdict, summary: r16.summary })}`);
209
+ assert.equal(r16.traceable, 1);
210
+ console.log(` ok - 注册 gotry_fact_gate itinerary 存在时 canonical no-reminder → pass`);
211
+ rmSync(home, { recursive: true, force: true });
212
+ console.log('\nPOLICY ANCHOR #359 REGISTERED E2E: pass (deterministic synthetic, isolated stateRoot, registered gotry_fact_gate execute())');
213
+ }
214
+ await main();