@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.
- package/README.md +102 -194
- package/README.zh-CN.md +115 -210
- package/bin/gotry-backend.js +53 -0
- package/bin/gotry-bootstrap.js +466 -35
- package/bin/gotry-inner.js +255 -36
- package/bin/gotry-process-liveness.d.ts +27 -0
- package/bin/gotry-process-liveness.js +97 -0
- package/bin/gotry-runtime-resolution.d.ts +1 -1
- package/bin/gotry-runtime-resolution.js +2 -2
- package/client/client.js +174 -0
- package/cordis.gotry-patch.yml +70 -93
- package/dist/capabilities/agent-reach-deep.js +45 -122
- package/dist/capabilities/agent-reach.js +63 -148
- package/dist/capabilities/anything.js +89 -75
- package/dist/capabilities/artifacts.js +123 -104
- package/dist/capabilities/channel-health.js +65 -45
- package/dist/capabilities/channel-registry.js +108 -87
- package/dist/capabilities/doctor.js +357 -235
- package/dist/capabilities/effect.js +223 -309
- package/dist/capabilities/fact-log.js +28 -14
- package/dist/capabilities/flyai.js +245 -156
- package/dist/capabilities/ground-transfer.js +509 -0
- package/dist/capabilities/hbcli.js +144 -148
- package/dist/capabilities/hotelbyte-transaction.js +194 -0
- package/dist/capabilities/incident-log.js +131 -61
- package/dist/capabilities/model-override.js +30 -10
- package/dist/capabilities/opensky.js +54 -43
- package/dist/capabilities/resilience.js +50 -32
- package/dist/capabilities/session/action-cache.js +50 -44
- package/dist/capabilities/session/adapters/ctrip-flight.js +119 -62
- package/dist/capabilities/session/adapters/ctrip-hotel.js +125 -110
- package/dist/capabilities/session/adapters/dida-portal.js +206 -0
- package/dist/capabilities/session/adapters/meituan-local.js +35 -54
- package/dist/capabilities/session/adapters/rail-12306.js +169 -112
- package/dist/capabilities/session/benchmark.js +85 -149
- package/dist/capabilities/session/extension-bridge.js +320 -259
- package/dist/capabilities/session/extension-channel.js +57 -76
- package/dist/capabilities/session/extension-distribution.js +115 -119
- package/dist/capabilities/session/extract.js +31 -21
- package/dist/capabilities/session/golden-score.js +55 -33
- package/dist/capabilities/session/health-watch.js +146 -154
- package/dist/capabilities/session/read-guard.js +55 -47
- package/dist/capabilities/session/static-flight-golden.js +49 -36
- package/dist/capabilities/session/transport.js +54 -61
- package/dist/capabilities/session/wizard.js +63 -93
- package/dist/capabilities/session-consent.js +143 -47
- package/dist/capabilities/session-login.js +95 -126
- package/dist/capabilities/session-search.js +391 -253
- package/dist/capabilities/sponsor-plugin.js +341 -0
- package/dist/capabilities/visa-policy.js +87 -73
- package/dist/capabilities/weather.js +163 -235
- package/dist/scripts/action-cache-tests.js +24 -59
- package/dist/scripts/agent-planning-turn-deadline-e2e.js +91 -142
- package/dist/scripts/agent-planning-turn-deadline-tests.js +80 -176
- package/dist/scripts/agent-reach-deep-tests.js +30 -40
- package/dist/scripts/agent-reach-tests.js +26 -18
- package/dist/scripts/agent-reach-wrapper-tests.js +46 -50
- package/dist/scripts/anything-tests.js +58 -62
- package/dist/scripts/artifact-client-contract-tests.js +69 -0
- package/dist/scripts/artifacts-capability-tests.js +235 -0
- package/dist/scripts/async-collect.js +26 -15
- package/dist/scripts/benchmark-environment-bridge-e2e.js +287 -684
- package/dist/scripts/benchmark-environment-bridge-tests.js +818 -3123
- package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +66 -279
- package/dist/scripts/booking-copilot-availability-policy-tests.js +153 -1257
- package/dist/scripts/booking-copilot-bin-proof-tests.js +22 -45
- package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +64 -76
- package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +69 -199
- package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +393 -759
- package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +33 -75
- package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +60 -110
- package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +28 -66
- package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +72 -271
- package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +73 -275
- package/dist/scripts/booking-copilot-runtime-proof-tests.js +784 -3398
- package/dist/scripts/booking-copilot-server-proof-tests.js +63 -168
- package/dist/scripts/booking-copilot-startup-proof-tests.js +38 -124
- package/dist/scripts/booking-executor-tests.js +80 -0
- package/dist/scripts/booking-recovery-chain-tests.js +182 -0
- package/dist/scripts/booking-saga-tests.js +61 -123
- package/dist/scripts/booking-surface-contract-proof-tests.js +152 -1167
- package/dist/scripts/bootstrap-tests.js +1383 -128
- package/dist/scripts/build-changelog.js +89 -130
- package/dist/scripts/build-metrics-report.js +135 -143
- package/dist/scripts/changelog-tests.js +35 -82
- package/dist/scripts/channel-probe-tests.js +44 -116
- package/dist/scripts/channel-probe.js +84 -167
- package/dist/scripts/channel-registry-tests.js +97 -185
- package/dist/scripts/companion-tests.js +25 -70
- package/dist/scripts/dida-cookie-probe.js +87 -0
- package/dist/scripts/dida-sw-probe.js +114 -0
- package/dist/scripts/diff-test.js +17 -12
- package/dist/scripts/doctor-tests.js +428 -120
- package/dist/scripts/dsh-artifact-e2e.js +150 -0
- package/dist/scripts/dsh-artifact-web-e2e.js +443 -0
- package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
- package/dist/scripts/dsh-runtime-closure-tests.js +110 -153
- package/dist/scripts/dsh-runtime-closure.js +75 -63
- package/dist/scripts/dsh-session-v3-migration-proof.js +106 -0
- package/dist/scripts/dsh-subprocess-local-proof.js +149 -0
- package/dist/scripts/dsh-target-closure-proof.js +178 -0
- package/dist/scripts/effect-tests.js +165 -552
- package/dist/scripts/engine-run.js +1 -3
- package/dist/scripts/engine-tests.js +16 -10
- package/dist/scripts/evaluation-cadence-tests.js +69 -242
- package/dist/scripts/evaluation-contract-tests.js +193 -499
- package/dist/scripts/extension-distribution-cli.js +19 -15
- package/dist/scripts/extension-distribution-tests.js +98 -211
- package/dist/scripts/extension-tests.js +366 -389
- package/dist/scripts/fact-gate-tests.js +725 -263
- package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
- package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
- package/dist/scripts/flight-malformed-tests.js +159 -0
- package/dist/scripts/flyai-tests.js +325 -68
- package/dist/scripts/g5-guard-tests.js +131 -0
- package/dist/scripts/g5-guard.js +189 -0
- package/dist/scripts/gen-lunar-anchors.js +106 -0
- package/dist/scripts/gotry-backend-kernel-tests.js +79 -0
- package/dist/scripts/ground-transfer-tests.js +956 -0
- package/dist/scripts/hbcli-e2e-tests.js +71 -90
- package/dist/scripts/hbcli-live-optin-tests.js +96 -0
- package/dist/scripts/hbcli-release-contract-tests.js +122 -0
- package/dist/scripts/hbcli-tests.js +41 -115
- package/dist/scripts/health-watch-cli.js +42 -28
- package/dist/scripts/hotel-date-gate-tests.js +496 -0
- package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
- package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
- package/dist/scripts/i18n-tests.js +16 -9
- package/dist/scripts/incident-tests.js +281 -87
- package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
- package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
- package/dist/scripts/issue-271-liveness-tests.js +547 -0
- package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
- package/dist/scripts/issue-289-model-retry-tests.js +441 -0
- package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
- package/dist/scripts/issue-338-home-city-e2e.js +577 -0
- package/dist/scripts/issue343-real-entry-e2e.js +160 -0
- package/dist/scripts/journey-tests.js +22 -27
- package/dist/scripts/kernel-manifest-evidence.js +109 -0
- package/dist/scripts/kernel-manifest-gate.js +126 -0
- package/dist/scripts/kernel-manifest-tests.js +212 -0
- package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
- package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
- package/dist/scripts/kernel-manifest.js +369 -0
- package/dist/scripts/ledger-repair-apply-tests.js +316 -0
- package/dist/scripts/ledger-repair-plan-tests.js +375 -0
- package/dist/scripts/ledger-tests.js +325 -340
- package/dist/scripts/ledger-workflow-crash.js +10 -20
- package/dist/scripts/map-tools-vendor-package-proof.js +206 -134
- package/dist/scripts/memory-capture-tests.js +242 -61
- package/dist/scripts/memory-decay-tests.js +18 -52
- package/dist/scripts/memory-lifecycle-tests.js +657 -0
- package/dist/scripts/memory-lifecycle.js +196 -0
- package/dist/scripts/memory-metrics.js +24 -12
- package/dist/scripts/memory-value-report.js +474 -222
- package/dist/scripts/memory-value-tests.js +328 -0
- package/dist/scripts/metrics-report-tests.js +62 -199
- package/dist/scripts/model-override-e2e.js +66 -105
- package/dist/scripts/nightly-evidence-tests.js +64 -89
- package/dist/scripts/nightly-evidence.js +108 -111
- package/dist/scripts/nudge-digest.js +39 -28
- package/dist/scripts/onboarding-tests.js +63 -88
- package/dist/scripts/opensky-check.js +18 -13
- package/dist/scripts/opensky-tests.js +28 -28
- package/dist/scripts/persona-surface-guard-tests.js +37 -12
- package/dist/scripts/pnpm-dsh-closure-proof.js +2 -5
- package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
- package/dist/scripts/price-drift-tests.js +126 -227
- package/dist/scripts/price-drift-watch.js +209 -253
- package/dist/scripts/probe-poi-tests.js +52 -45
- package/dist/scripts/product-metrics.js +187 -273
- package/dist/scripts/publish-preverify.js +47 -41
- package/dist/scripts/realtime-pricing-tests.js +37 -76
- package/dist/scripts/replay-async.js +20 -18
- package/dist/scripts/replay-real.js +16 -18
- package/dist/scripts/replay.js +52 -82
- package/dist/scripts/session-attach-diagnose.js +16 -12
- package/dist/scripts/session-attach-poc.js +34 -37
- package/dist/scripts/session-benchmark.js +66 -147
- package/dist/scripts/session-dida-live-e2e.js +151 -0
- package/dist/scripts/session-extract-tests.js +14 -35
- package/dist/scripts/session-login.js +14 -13
- package/dist/scripts/session-tests.js +545 -583
- package/dist/scripts/sf-live-benchmark.js +92 -110
- package/dist/scripts/sf-live-cli-tests.js +2 -9
- package/dist/scripts/sf-soft-score-tests.js +19 -60
- package/dist/scripts/sf-summary-tests.js +149 -0
- package/dist/scripts/sf-summary.js +466 -84
- package/dist/scripts/skeleton-check.js +16 -14
- package/dist/scripts/skeleton-integration-test.js +11 -10
- package/dist/scripts/skills-contract-tests.js +51 -46
- package/dist/scripts/smoke-session-gate-tests.js +12 -20
- package/dist/scripts/smoke.js +541 -422
- package/dist/scripts/sponsor-reuse-tests.js +262 -0
- package/dist/scripts/state-cli-tests.js +226 -101
- package/dist/scripts/state-cli.js +549 -212
- package/dist/scripts/static-golden-tests.js +46 -180
- package/dist/scripts/time-eval-tests.js +210 -192
- package/dist/scripts/travel-timeline-tests.js +29 -93
- package/dist/scripts/turn-handoff-collect-tests.js +46 -93
- package/dist/scripts/turn-handoff-collect.js +71 -99
- package/dist/scripts/turn-policy-tests.js +28 -29
- package/dist/scripts/typed-contract-canary.js +77 -162
- package/dist/scripts/tz-resolver-sanity.js +50 -0
- package/dist/scripts/tz-resolver-tests.js +584 -0
- package/dist/scripts/unified-tests.js +23 -19
- package/dist/scripts/visa-policy-tests.js +31 -44
- package/dist/scripts/weather-tests.js +121 -543
- package/dist/scripts/wish-channel-gate-tests.js +29 -86
- package/dist/scripts/write-gate-tests.js +522 -0
- package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
- package/dist/scripts/z3-lifecycle-tests.js +170 -0
- package/dist/scripts/z3-race-repeat-tests.js +39 -0
- package/dist/scripts/z3-race-tests.js +18 -12
- package/dist/src/artifact-gate.js +652 -221
- package/dist/src/backend/kernel.js +91 -0
- package/dist/src/backend/modules/booking-copilot.js +55 -0
- package/dist/src/backend/modules/booking-executor.js +124 -0
- package/dist/src/backend/modules/session-search.js +194 -0
- package/dist/src/benchmark-agent-conformance.js +296 -262
- package/dist/src/benchmark-environment-bridge.js +298 -413
- package/dist/src/benchmark-headless-child-diagnostics.js +93 -100
- package/dist/src/benchmark-tool-isolation.js +94 -67
- package/dist/src/bookable-facts.js +299 -174
- package/dist/src/booking-saga.js +64 -120
- package/dist/src/booking-surface/availability-policy.js +443 -576
- package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
- package/dist/src/booking-surface/contracts.js +24 -80
- package/dist/src/booking-surface/dsh-planner.js +510 -281
- package/dist/src/booking-surface/dsh-plugin.js +17 -1
- package/dist/src/booking-surface/error-codes.js +82 -10
- package/dist/src/booking-surface/index.js +0 -3
- package/dist/src/booking-surface/profile.js +10 -54
- package/dist/src/booking-surface/recovery-chain.js +367 -0
- package/dist/src/booking-surface/runtime.js +765 -891
- package/dist/src/booking-surface/server.js +200 -251
- package/dist/src/booking-surface/startup.js +58 -54
- package/dist/src/booking-surface/validation.js +150 -218
- package/dist/src/bridge.js +20 -13
- package/dist/src/companions.js +48 -74
- package/dist/src/contracts.js +21 -43
- package/dist/src/dsh-llm.js +82 -120
- package/dist/src/engine.js +253 -239
- package/dist/src/evaluation-cadence.js +72 -209
- package/dist/src/evaluation-contracts.js +220 -843
- package/dist/src/flight-pack-adapter.js +54 -0
- package/dist/src/flight-pack-contract.js +2 -0
- package/dist/src/gotry-backend.js +70 -0
- package/dist/src/hotel-date-gate.js +118 -0
- package/dist/src/i18n.js +18 -7
- package/dist/src/index.js +1425 -1629
- package/dist/src/journey.js +132 -81
- package/dist/src/ledger-repair-apply.js +538 -0
- package/dist/src/ledger-repair-plan.js +463 -0
- package/dist/src/loop.js +257 -166
- package/dist/src/memory-capture.js +180 -32
- package/dist/src/memory-decay.js +30 -14
- package/dist/src/memory-lifecycle.js +1310 -0
- package/dist/src/memory-utility.js +27 -40
- package/dist/src/mock-llm.js +36 -61
- package/dist/src/model.js +81 -36
- package/dist/src/realtime-pricing.js +63 -72
- package/dist/src/slot-spec.js +84 -106
- package/dist/src/state-ledger.js +310 -471
- package/dist/src/subagent-job-id-guard.js +58 -0
- package/dist/src/time-anchor.js +231 -33
- package/dist/src/tool-packet.js +20 -8
- package/dist/src/travel-slots.js +58 -35
- package/dist/src/travel-timeline.js +44 -63
- package/dist/src/turn-deadline.js +121 -127
- package/dist/src/turn-policy.js +61 -89
- package/dist/src/tz-resolver.js +143 -0
- package/dist/src/unified.js +504 -381
- package/dist/src/wish-pool.js +39 -14
- package/dist/src/write-gate.js +495 -0
- package/dist/src/z3-shared.js +273 -7
- package/extension/README.md +4 -3
- package/extension/background.js +125 -14
- package/extension/content-bridge.js +23 -1
- package/extension/content-main.js +15 -4
- package/extension/manifest.json +16 -8
- package/package.json +251 -220
- package/ts/capabilities/agent-reach.ts +4 -4
- package/ts/capabilities/anything.ts +1 -1
- package/ts/capabilities/artifacts.ts +46 -9
- package/ts/capabilities/flyai.ts +156 -37
- package/ts/capabilities/hbcli.ts +1 -1
- package/ts/capabilities/incident-log.ts +88 -59
- package/ts/capabilities/session/adapters/ctrip-flight.ts +99 -36
- package/ts/capabilities/session/adapters/dida-portal.ts +250 -0
- package/ts/capabilities/session/adapters/rail-12306.ts +123 -24
- package/ts/capabilities/session/extension-bridge.ts +226 -101
- package/ts/capabilities/session/extension-channel.ts +22 -9
- package/ts/capabilities/session/wizard.ts +2 -2
- package/ts/capabilities/session-consent.ts +98 -14
- package/ts/capabilities/session-login.ts +1 -0
- package/ts/capabilities/session-search.ts +315 -31
- package/ts/dsh-runtime/vendor/README.md +8 -4
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +7 -1
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +5 -3
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +1 -1
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +1 -1
- package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +6 -6
- package/ts/package.json +236 -16
- package/ts/scripts/map-tools-vendor-package-proof.ts +152 -31
- package/ts/scripts/state-cli.ts +418 -51
- package/ts/src/artifact-gate.ts +561 -15
- package/ts/src/benchmark-environment-bridge.ts +37 -20
- package/ts/src/bookable-facts.ts +183 -7
- package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
- package/ts/src/booking-surface/dsh-planner.ts +240 -32
- package/ts/src/booking-surface/dsh-plugin.js +17 -1
- package/ts/src/booking-surface/error-codes.ts +75 -0
- package/ts/src/booking-surface/recovery-chain.ts +409 -0
- package/ts/src/booking-surface/server.ts +84 -51
- package/ts/src/booking-surface/validation.ts +2 -0
- package/ts/src/contracts.ts +12 -2
- package/ts/src/dsh-llm.ts +4 -8
- package/ts/src/index.ts +609 -90
- package/ts/src/loop.ts +116 -7
- package/ts/src/memory-capture.ts +227 -3
- package/ts/src/mock-llm.ts +4 -8
- package/ts/src/model.ts +88 -2
- package/ts/src/state-ledger.ts +47 -29
- package/ts/src/subagent-job-id-guard.ts +72 -0
- package/ts/src/time-anchor.ts +217 -13
- 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();
|