@danceiny/gotry 0.0.1-rc.9 → 0.2.0-rc.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -219
- package/README.zh-CN.md +222 -0
- package/bin/gotry-backend.js +53 -0
- package/bin/gotry-booking-copilot.js +53 -0
- package/bin/gotry-bootstrap.js +1788 -0
- package/bin/gotry-inner.js +733 -83
- package/bin/gotry-process-liveness.d.ts +27 -0
- package/bin/gotry-process-liveness.js +97 -0
- package/bin/gotry-runtime-resolution.d.ts +27 -0
- package/bin/gotry-runtime-resolution.js +49 -0
- package/bin/gotry.js +1 -1
- package/client/client.js +203 -0
- package/cordis.gotry-patch.yml +80 -56
- package/data/airline-airports.json +39 -0
- package/data/stations-12306-verify.json +524 -0
- package/dist/capabilities/agent-reach-deep.js +45 -122
- package/dist/capabilities/agent-reach.js +101 -146
- package/dist/capabilities/anything.js +161 -94
- package/dist/capabilities/artifacts.js +370 -0
- package/dist/capabilities/channel-health.js +131 -0
- package/dist/capabilities/channel-registry.js +256 -0
- package/dist/capabilities/doctor.js +553 -0
- package/dist/capabilities/effect.js +394 -0
- package/dist/capabilities/external-event.js +149 -0
- package/dist/capabilities/fact-log.js +55 -0
- package/dist/capabilities/flyai-config.js +337 -0
- package/dist/capabilities/flyai.js +947 -110
- package/dist/capabilities/fx-contract.js +293 -0
- package/dist/capabilities/geo-atlas.js +246 -0
- package/dist/capabilities/ground-transfer.js +676 -0
- package/dist/capabilities/hbcli.js +260 -123
- package/dist/capabilities/hotelbyte-transaction.js +194 -0
- package/dist/capabilities/incident-log.js +131 -61
- package/dist/capabilities/itinerary-artifact.js +190 -0
- package/dist/capabilities/itinerary-deck-artifact.js +194 -0
- package/dist/capabilities/itinerary-deck-export.js +339 -0
- package/dist/capabilities/lavish-local.js +924 -0
- package/dist/capabilities/model-override.js +38 -0
- package/dist/capabilities/opensky.js +54 -43
- package/dist/capabilities/provider-detail-sanitize.js +64 -0
- package/dist/capabilities/resilience.js +191 -0
- package/dist/capabilities/route-provider-conformance.js +341 -0
- package/dist/capabilities/session/action-cache.js +50 -44
- package/dist/capabilities/session/adapters/ctrip-flight.js +120 -62
- package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
- package/dist/capabilities/session/adapters/dida-portal.js +274 -0
- package/dist/capabilities/session/adapters/meituan-local.js +35 -54
- package/dist/capabilities/session/adapters/rail-12306.js +342 -0
- package/dist/capabilities/session/benchmark.js +189 -0
- package/dist/capabilities/session/bridge-ledger.js +224 -0
- package/dist/capabilities/session/extension-bridge.js +636 -0
- package/dist/capabilities/session/extension-channel.js +109 -0
- package/dist/capabilities/session/extension-distribution.js +230 -0
- package/dist/capabilities/session/extract.js +31 -21
- package/dist/capabilities/session/golden-score.js +114 -0
- package/dist/capabilities/session/health-watch.js +215 -0
- package/dist/capabilities/session/read-guard.js +75 -24
- package/dist/capabilities/session/static-flight-golden.js +150 -0
- package/dist/capabilities/session/transport.js +97 -83
- package/dist/capabilities/session/wizard.js +117 -0
- package/dist/capabilities/session-consent.js +178 -0
- package/dist/capabilities/session-login.js +170 -0
- package/dist/capabilities/session-search.js +635 -44
- package/dist/capabilities/spawn-bounded.js +203 -0
- package/dist/capabilities/sponsor-plugin.js +341 -0
- package/dist/capabilities/visa-policy.js +140 -0
- package/dist/capabilities/weather.js +243 -138
- package/dist/data/session-golden-20.json +25 -0
- package/dist/data/sf-golden-manifest.json +103 -0
- package/dist/data/sf-static-routes.json +91 -0
- package/dist/scripts/action-cache-tests.js +24 -59
- package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
- package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
- package/dist/scripts/agent-reach-deep-tests.js +30 -40
- package/dist/scripts/agent-reach-error-tests.js +354 -0
- package/dist/scripts/agent-reach-tests.js +26 -18
- package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
- package/dist/scripts/anything-path-measure-tests.js +133 -0
- package/dist/scripts/anything-path-measure.js +150 -0
- package/dist/scripts/anything-tests.js +250 -60
- package/dist/scripts/artifact-client-contract-tests.js +220 -0
- package/dist/scripts/artifacts-capability-tests.js +727 -0
- package/dist/scripts/async-collect.js +50 -11
- package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
- package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
- package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
- package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
- package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
- package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
- package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
- package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
- package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
- package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
- package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
- package/dist/scripts/booking-copilot-dsh-warmer-proof.js +126 -0
- package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
- package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
- package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
- package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
- package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
- package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
- package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
- package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
- package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
- package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
- 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 +125 -0
- package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
- package/dist/scripts/bootstrap-tests.js +1549 -0
- package/dist/scripts/bridge-events-tests.js +239 -0
- package/dist/scripts/bridge-ledger-tests.js +428 -0
- package/dist/scripts/build-changelog.js +238 -0
- package/dist/scripts/build-metrics-report.js +331 -0
- package/dist/scripts/changelog-tests.js +118 -0
- package/dist/scripts/channel-probe-tests.js +103 -0
- package/dist/scripts/channel-probe.js +169 -0
- package/dist/scripts/channel-registry-tests.js +208 -0
- package/dist/scripts/city-scenario-tier-tests.js +234 -0
- package/dist/scripts/companion-tests.js +25 -70
- package/dist/scripts/dida-cookie-probe.js +87 -0
- package/dist/scripts/dida-runner-stop-tests.js +311 -0
- package/dist/scripts/dida-sw-probe.js +114 -0
- package/dist/scripts/diff-test.js +17 -12
- package/dist/scripts/doctor-tests.js +600 -0
- package/dist/scripts/drill-multiuser-ledger-tests.js +1076 -0
- package/dist/scripts/drill-sdk-descendant-cleanup-tests.js +606 -0
- package/dist/scripts/drill-w2a-sensor-tests.js +788 -0
- package/dist/scripts/dsh-artifact-e2e.js +279 -0
- package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
- package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
- package/dist/scripts/dsh-llm-tests.js +437 -0
- package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
- package/dist/scripts/dsh-runtime-closure.js +162 -0
- package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
- package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
- package/dist/scripts/dsh-target-closure-proof.js +178 -0
- package/dist/scripts/effect-tests.js +539 -0
- package/dist/scripts/engine-run.js +1 -3
- package/dist/scripts/engine-tests.js +16 -10
- package/dist/scripts/evaluation-cadence-tests.js +174 -0
- package/dist/scripts/evaluation-contract-tests.js +268 -0
- package/dist/scripts/extension-distribution-cli.js +39 -0
- package/dist/scripts/extension-distribution-tests.js +443 -0
- package/dist/scripts/extension-tests.js +988 -0
- package/dist/scripts/external-event-tests.js +350 -0
- package/dist/scripts/fact-gate-tests.js +869 -0
- 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-setup-tests.js +228 -0
- package/dist/scripts/flyai-setup-tool-tests.js +54 -0
- package/dist/scripts/flyai-tests.js +692 -0
- package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
- package/dist/scripts/fx-contract-tests.js +201 -0
- package/dist/scripts/g5-guard-tests.js +150 -0
- package/dist/scripts/g5-guard.js +193 -0
- package/dist/scripts/gen-lunar-anchors.js +106 -0
- package/dist/scripts/geo-atlas-tests.js +283 -0
- package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
- package/dist/scripts/gotry-try-demo-tests.js +79 -0
- package/dist/scripts/gotry-try-demo.js +49 -0
- package/dist/scripts/ground-transfer-tests.js +956 -0
- package/dist/scripts/hbcli-e2e-tests.js +159 -0
- 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 +121 -69
- package/dist/scripts/health-watch-cli.js +73 -0
- 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 +41 -0
- 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 +569 -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/issue436-persisted-routing-e2e.js +247 -0
- package/dist/scripts/itinerary-artifact-tests.js +368 -0
- package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
- package/dist/scripts/itinerary-deck-export-tests.js +552 -0
- package/dist/scripts/itinerary-deck-tests.js +435 -0
- package/dist/scripts/itinerary-html-tests.js +426 -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/lavish-local-tests.js +1226 -0
- package/dist/scripts/lavish-product-tools-tests.js +537 -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 +382 -246
- package/dist/scripts/ledger-workflow-crash.js +10 -20
- package/dist/scripts/m3-cohort-tests.js +714 -0
- package/dist/scripts/m3-cohort.js +310 -0
- package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
- package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
- package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
- package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
- package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
- 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 +631 -0
- package/dist/scripts/memory-value-tests.js +328 -0
- package/dist/scripts/metrics-report-tests.js +151 -0
- package/dist/scripts/model-override-e2e.js +137 -0
- package/dist/scripts/nightly-evidence-tests.js +203 -0
- package/dist/scripts/nightly-evidence.js +303 -0
- package/dist/scripts/nudge-digest.js +39 -28
- package/dist/scripts/observability-tests.js +381 -0
- package/dist/scripts/onboarding-tests.js +161 -0
- package/dist/scripts/opensky-check.js +18 -13
- package/dist/scripts/opensky-tests.js +28 -28
- package/dist/scripts/outcome-projection-tests.js +427 -0
- package/dist/scripts/persona-sim-tests.js +603 -0
- package/dist/scripts/persona-sim.js +1081 -0
- package/dist/scripts/persona-surface-guard-tests.js +49 -0
- package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
- package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
- package/dist/scripts/price-drift-tests.js +340 -0
- package/dist/scripts/price-drift-watch.js +447 -0
- package/dist/scripts/probe-poi-tests.js +53 -45
- package/dist/scripts/product-metrics.js +483 -0
- package/dist/scripts/publish-preverify.js +110 -0
- package/dist/scripts/realtime-pricing-tests.js +76 -0
- package/dist/scripts/recall-tests.js +513 -0
- package/dist/scripts/replay-async.js +22 -18
- package/dist/scripts/replay-real.js +18 -18
- package/dist/scripts/replay.js +54 -82
- package/dist/scripts/route-provider-conformance-tests.js +391 -0
- package/dist/scripts/session-attach-diagnose.js +20 -20
- package/dist/scripts/session-attach-poc.js +34 -37
- package/dist/scripts/session-benchmark.js +180 -0
- package/dist/scripts/session-dida-live-e2e.js +199 -0
- package/dist/scripts/session-extract-tests.js +14 -35
- package/dist/scripts/session-link-tests.js +478 -0
- package/dist/scripts/session-login.js +27 -46
- package/dist/scripts/session-tests.js +796 -96
- package/dist/scripts/session-zone-crash.js +49 -0
- package/dist/scripts/session-zone-ledger-tests.js +432 -0
- package/dist/scripts/session-zone-observation-tests.js +492 -0
- package/dist/scripts/session-zone-observe.js +135 -0
- package/dist/scripts/session-zone-wiring-tests.js +566 -0
- package/dist/scripts/session-zones-tests.js +374 -0
- package/dist/scripts/sf-live-benchmark.js +367 -0
- package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
- package/dist/scripts/sf-live-cli-tests.js +92 -0
- package/dist/scripts/sf-live-options.js +46 -0
- package/dist/scripts/sf-manifest-tests.js +30 -0
- package/dist/scripts/sf-manifest.js +33 -0
- package/dist/scripts/sf-soft-score-tests.js +67 -0
- package/dist/scripts/sf-summary-tests.js +324 -0
- package/dist/scripts/sf-summary.js +525 -0
- package/dist/scripts/share-tests.js +432 -0
- package/dist/scripts/skeleton-check.js +16 -14
- package/dist/scripts/skeleton-integration-test.js +28 -11
- package/dist/scripts/skills-contract-tests.js +51 -46
- package/dist/scripts/smoke-session-gate-tests.js +21 -0
- package/dist/scripts/smoke.js +690 -246
- package/dist/scripts/spawn-bounded-abort-tests.js +244 -0
- package/dist/scripts/sponsor-reuse-tests.js +262 -0
- package/dist/scripts/state-cli-tests.js +226 -101
- package/dist/scripts/state-cli.js +565 -198
- package/dist/scripts/state-repair-cli.js +66 -0
- package/dist/scripts/state-repair-tests.js +140 -0
- package/dist/scripts/static-golden-tests.js +165 -0
- package/dist/scripts/time-eval-tests.js +212 -192
- package/dist/scripts/travel-timeline-tests.js +29 -93
- package/dist/scripts/turn-handoff-collect-tests.js +169 -0
- package/dist/scripts/turn-handoff-collect.js +161 -0
- package/dist/scripts/turn-policy-tests.js +55 -0
- package/dist/scripts/typed-contract-canary.js +176 -0
- package/dist/scripts/tz-resolver-sanity.js +50 -0
- package/dist/scripts/tz-resolver-tests.js +584 -0
- package/dist/scripts/unified-tests.js +60 -20
- package/dist/scripts/visa-policy-tests.js +62 -0
- package/dist/scripts/weather-tests.js +276 -41
- package/dist/scripts/wish-channel-gate-tests.js +54 -0
- 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 +46 -0
- package/dist/src/artifact-gate.js +829 -0
- package/dist/src/backend/kernel.js +91 -0
- package/dist/src/backend/modules/booking-copilot.js +92 -0
- package/dist/src/backend/modules/booking-executor.js +124 -0
- package/dist/src/backend/modules/session-search.js +551 -0
- package/dist/src/benchmark-agent-conformance.js +578 -0
- package/dist/src/benchmark-environment-bridge.js +515 -0
- package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
- package/dist/src/benchmark-tool-isolation.js +151 -0
- package/dist/src/bookable-facts.js +533 -0
- package/dist/src/booking-saga.js +97 -0
- package/dist/src/booking-surface/availability-policy.js +697 -0
- package/dist/src/booking-surface/booking-intent.js +43 -0
- package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
- package/dist/src/booking-surface/canonical-schema.js +116 -0
- package/dist/src/booking-surface/contracts.js +75 -0
- package/dist/src/booking-surface/dsh-planner.js +1854 -0
- package/dist/src/booking-surface/dsh-plugin.js +378 -0
- package/dist/src/booking-surface/dsh-worker.js +98 -0
- package/dist/src/booking-surface/error-codes.js +231 -0
- package/dist/src/booking-surface/index.js +9 -0
- package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
- package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
- package/dist/src/booking-surface/profile.js +24 -0
- package/dist/src/booking-surface/recovery-chain.js +367 -0
- package/dist/src/booking-surface/runtime.js +1968 -0
- package/dist/src/booking-surface/server.js +674 -0
- package/dist/src/booking-surface/startup.js +168 -0
- package/dist/src/booking-surface/validation.js +261 -0
- package/dist/src/bridge.js +20 -13
- package/dist/src/city-scenario-tier.js +378 -0
- package/dist/src/companions.js +48 -74
- package/dist/src/contracts.js +21 -43
- package/dist/src/dsh-llm.js +171 -115
- package/dist/src/engine.js +276 -193
- package/dist/src/evaluation-cadence.js +97 -0
- package/dist/src/evaluation-contracts.js +283 -0
- package/dist/src/flight-pack-adapter.js +54 -0
- package/dist/src/flight-pack-contract.js +2 -0
- package/dist/src/flyai-setup-tool.js +70 -0
- package/dist/src/gotry-backend.js +125 -0
- package/dist/src/hotel-date-gate.js +118 -0
- package/dist/src/i18n.js +88 -0
- package/dist/src/index.js +2385 -881
- package/dist/src/itinerary-deck.js +139 -0
- package/dist/src/itinerary-doc-shared.js +661 -0
- package/dist/src/itinerary-html.js +131 -0
- package/dist/src/journey.js +155 -108
- package/dist/src/lavish-tools.js +400 -0
- package/dist/src/ledger-repair-apply.js +538 -0
- package/dist/src/ledger-repair-plan.js +463 -0
- package/dist/src/loop.js +331 -161
- package/dist/src/m3-cohort.js +1577 -0
- 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/outcome-projection.js +746 -0
- package/dist/src/realtime-pricing.js +103 -0
- package/dist/src/recall/card.js +74 -0
- package/dist/src/recall/evaluator.js +140 -0
- package/dist/src/recall/integration.js +17 -0
- package/dist/src/recall/tick.js +166 -0
- package/dist/src/session-link/plan-it-action.js +48 -0
- package/dist/src/session-link/session-link.js +248 -0
- package/dist/src/session-zone-ledger.js +312 -0
- package/dist/src/session-zone-observation.js +354 -0
- package/dist/src/session-zone-wiring.js +658 -0
- package/dist/src/session-zones.js +510 -0
- package/dist/src/share/adapters.js +51 -0
- package/dist/src/share/share-consent.js +76 -0
- package/dist/src/share/share-deck.js +58 -0
- package/dist/src/share/share-token.js +146 -0
- package/dist/src/slot-spec.js +84 -106
- package/dist/src/state-ledger.js +696 -524
- package/dist/src/state-repair.js +299 -0
- 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 +287 -0
- package/dist/src/turn-policy.js +118 -0
- package/dist/src/tz-resolver.js +143 -0
- package/dist/src/unified.js +600 -360
- package/dist/src/wish-pool.js +42 -12
- package/dist/src/write-gate.js +495 -0
- package/dist/src/z3-shared.js +284 -0
- package/extension/README.md +21 -0
- package/extension/README.zh-CN.md +21 -0
- package/extension/background.js +463 -0
- package/extension/content-bridge.js +270 -0
- package/extension/content-main.js +111 -0
- package/extension/manifest.json +60 -0
- package/package.json +407 -14
- package/schemas/booking.intent.schema.json +193 -0
- package/schemas/booking.surface.schema.json +2622 -0
- package/ts/capabilities/agent-reach-deep.ts +114 -0
- package/ts/capabilities/agent-reach.ts +198 -0
- package/ts/capabilities/anything.ts +282 -0
- package/ts/capabilities/artifacts.ts +428 -0
- package/ts/capabilities/fact-log.ts +54 -0
- package/ts/capabilities/flyai-config.ts +388 -0
- package/ts/capabilities/flyai.ts +1274 -0
- package/ts/capabilities/hbcli.ts +253 -71
- package/ts/capabilities/incident-log.ts +88 -59
- package/ts/capabilities/itinerary-artifact.ts +214 -0
- package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
- package/ts/capabilities/itinerary-deck-export.ts +378 -0
- package/ts/capabilities/opensky.ts +121 -0
- package/ts/capabilities/session/action-cache.ts +148 -0
- package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
- package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
- package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
- package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
- package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
- package/ts/capabilities/session/benchmark.ts +276 -0
- package/ts/capabilities/session/bridge-ledger.ts +333 -0
- package/ts/capabilities/session/extension-bridge.ts +794 -0
- package/ts/capabilities/session/extension-channel.ts +144 -0
- package/ts/capabilities/session/extension-distribution.ts +266 -0
- package/ts/capabilities/session/extract.ts +54 -0
- package/ts/capabilities/session/golden-score.ts +139 -0
- package/ts/capabilities/session/health-watch.ts +264 -0
- package/ts/capabilities/session/read-guard.ts +141 -0
- package/ts/capabilities/session/static-flight-golden.ts +209 -0
- package/ts/capabilities/session/transport.ts +146 -0
- package/ts/capabilities/session/wizard.ts +140 -0
- package/ts/capabilities/session-consent.ts +211 -0
- package/ts/capabilities/session-login.ts +208 -0
- package/ts/capabilities/session-search.ts +893 -0
- package/ts/capabilities/weather.ts +330 -0
- package/ts/dsh-runtime/vendor/README.md +68 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
- package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
- package/ts/package.json +293 -3
- package/ts/scripts/async-collect.ts +91 -0
- package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
- package/ts/scripts/skeleton-check.ts +1 -1
- package/ts/scripts/skeleton-integration-test.ts +23 -1
- package/ts/scripts/state-cli.ts +586 -0
- package/ts/scripts/turn-handoff-collect.ts +178 -0
- package/ts/src/artifact-gate.ts +991 -0
- package/ts/src/benchmark-agent-conformance.ts +619 -0
- package/ts/src/benchmark-environment-bridge.ts +538 -0
- package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
- package/ts/src/benchmark-tool-isolation.ts +166 -0
- package/ts/src/bookable-facts.ts +837 -0
- package/ts/src/booking-saga.ts +133 -0
- package/ts/src/booking-surface/availability-policy.ts +522 -0
- package/ts/src/booking-surface/booking-intent.ts +86 -0
- package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
- package/ts/src/booking-surface/canonical-schema.js +116 -0
- package/ts/src/booking-surface/contracts.ts +475 -0
- package/ts/src/booking-surface/dsh-planner.ts +1949 -0
- package/ts/src/booking-surface/dsh-plugin.js +378 -0
- package/ts/src/booking-surface/dsh-worker.ts +110 -0
- package/ts/src/booking-surface/error-codes.ts +241 -0
- package/ts/src/booking-surface/index.ts +9 -0
- package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
- package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
- package/ts/src/booking-surface/profile.ts +42 -0
- package/ts/src/booking-surface/recovery-chain.ts +409 -0
- package/ts/src/booking-surface/runtime.ts +1793 -0
- package/ts/src/booking-surface/server.ts +733 -0
- package/ts/src/booking-surface/startup.ts +201 -0
- package/ts/src/booking-surface/validation.ts +217 -0
- package/ts/src/companions.ts +113 -0
- package/ts/src/contracts.ts +17 -3
- package/ts/src/dsh-llm.ts +152 -17
- package/ts/src/flyai-setup-tool.ts +77 -0
- package/ts/src/index.ts +2123 -200
- package/ts/src/itinerary-deck.ts +189 -0
- package/ts/src/itinerary-doc-shared.ts +741 -0
- package/ts/src/itinerary-html.ts +171 -0
- package/ts/src/loop.ts +234 -26
- package/ts/src/memory-capture.ts +283 -0
- package/ts/src/memory-decay.ts +55 -0
- package/ts/src/memory-utility.ts +70 -0
- package/ts/src/mock-llm.ts +4 -8
- package/ts/src/model.ts +88 -2
- package/ts/src/recall/card.ts +106 -0
- package/ts/src/recall/evaluator.ts +170 -0
- package/ts/src/recall/integration.ts +35 -0
- package/ts/src/recall/tick.ts +213 -0
- package/ts/src/session-link/plan-it-action.ts +78 -0
- package/ts/src/session-link/session-link.ts +275 -0
- package/ts/src/share/adapters.ts +93 -0
- package/ts/src/share/share-consent.ts +105 -0
- package/ts/src/share/share-deck.ts +85 -0
- package/ts/src/share/share-token.ts +166 -0
- package/ts/src/slot-spec.ts +172 -0
- package/ts/src/state-ledger.ts +1166 -0
- package/ts/src/subagent-job-id-guard.ts +72 -0
- package/ts/src/time-anchor.ts +338 -0
- package/ts/src/tool-packet.ts +32 -0
- package/ts/src/travel-slots.ts +219 -0
- package/ts/src/travel-timeline.ts +83 -0
- package/ts/src/turn-deadline.ts +366 -0
- package/ts/src/turn-policy.ts +154 -0
- package/ts/src/unified.ts +444 -105
- package/ts/src/wish-pool.ts +79 -0
- package/dist/scripts/session-attach-wait.js +0 -41
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D-39 live-route provider CONFORMANCE contract v1 (issue #429 contract slice,
|
|
3
|
+
* SIMULATED-TRIGGER DRILL — default OFF, zero callers, trigger flag frozen false,
|
|
4
|
+
* provider registry frozen EMPTY).
|
|
5
|
+
*
|
|
6
|
+
* ⚠ Evidence boundary: this is the conformance GATE any future live-route adapter
|
|
7
|
+
* must pass, exercised here against a MOCK adapter only. #429's trigger is, per
|
|
8
|
+
* path, "a named product use case + the actual data provider and access boundary +
|
|
9
|
+
* reviewable authority/freshness/coverage evidence"; it has NOT fired for any path.
|
|
10
|
+
* No real routing provider is contacted (`consultRouteProvider` refuses before
|
|
11
|
+
* touching an adapter while the trigger is false), no dependency is added, and the
|
|
12
|
+
* accepted narrow path of #341 (explicit-coordinate destination driving estimate
|
|
13
|
+
* with static price evidence) is untouched. Nothing here claims provider
|
|
14
|
+
* availability or an M4/M5/M6 Exit.
|
|
15
|
+
*
|
|
16
|
+
* What it owns: the single admission gate `admitRouteFact` — a provider outcome
|
|
17
|
+
* becomes a route fact only if the provider's OWN claims (mode, evidence class,
|
|
18
|
+
* echoed origin/destination, freshness, fare authority) match the declared use
|
|
19
|
+
* case. Every mismatch is a typed refusal whose detail is sanitized, and a refusal
|
|
20
|
+
* always leaves the static fallback and its original price label intact.
|
|
21
|
+
*
|
|
22
|
+
* Frozen upstream constraints (READ-ONLY reuse):
|
|
23
|
+
* - docs/architecture.md D-39 + §10: each wider path needs its own named use case,
|
|
24
|
+
* source, freshness contract, access boundary and real-data proof; read-only
|
|
25
|
+
* routing authorizes no write path;
|
|
26
|
+
* - ts/capabilities/ground-transfer.ts (#341/#364/#382): the accepted narrow shape
|
|
27
|
+
* — per-direction isolation, host observation time (never a provider publication
|
|
28
|
+
* timestamp), `trafficStatus: 'not-live-route-estimate'`, and the static
|
|
29
|
+
* `priceCny` + `[静态包:估算]` label that a route fact never replaces;
|
|
30
|
+
* - ts/capabilities/fx-contract.ts (#344): the trigger-gated, frozen-empty
|
|
31
|
+
* registry seam and the "stale/miss/error never masquerades as current" rule.
|
|
32
|
+
*
|
|
33
|
+
* Layering: this module performs zero network, cache, timer, clock or filesystem
|
|
34
|
+
* work, and its ONLY import is the pure sibling sanitizer
|
|
35
|
+
* `provider-detail-sanitize.ts` (shared with the live ground-transfer path so one
|
|
36
|
+
* implementation serves both). It imports nothing from the kernel evaluate/solve
|
|
37
|
+
* layer (`src/model.ts`, `src/unified.ts`), and no product file imports it. Any
|
|
38
|
+
* future adapter's network/cache work stays on the capability side of that line;
|
|
39
|
+
* the focused suite asserts the import surface mechanically.
|
|
40
|
+
*
|
|
41
|
+
* Only the real trigger can supply: the provider identity and licence, actual
|
|
42
|
+
* coverage/freshness measurements, a separately authoritative fare source, and an
|
|
43
|
+
* authorized minimal real path recorded at an exact source SHA.
|
|
44
|
+
*
|
|
45
|
+
* @module capabilities/route-provider-conformance
|
|
46
|
+
*/
|
|
47
|
+
import { FAULT_DETAIL_MAX_CHARS, faultDetailLeak, sanitizeFaultDetail } from './provider-detail-sanitize.js';
|
|
48
|
+
/** Re-exported so the conformance gate stays the single API surface for callers. */
|
|
49
|
+
export { FAULT_DETAIL_MAX_CHARS, faultDetailLeak, sanitizeFaultDetail };
|
|
50
|
+
export const ROUTE_PROVIDER_CONFORMANCE_SCHEMA = 'gotry_route_provider_conformance.v1';
|
|
51
|
+
/**
|
|
52
|
+
* D-39 wider-path trigger gate, frozen false. Each path (live traffic, transit,
|
|
53
|
+
* rail, fare, address resolution) is admitted independently; flipping this is a
|
|
54
|
+
* per-path founder decision with a named use case and a real provider.
|
|
55
|
+
*/
|
|
56
|
+
export const D39_LIVE_ROUTE_TRIGGER_FIRED = false;
|
|
57
|
+
/** Transport modes. A provider may never relabel one as another, in either direction. */
|
|
58
|
+
export const ROUTE_MODES = ['driving', 'transit', 'rail', 'walking', 'cycling'];
|
|
59
|
+
/** Evidence classes, weakest first. A declared class must match EXACTLY. */
|
|
60
|
+
export const ROUTE_EVIDENCE_CLASSES = ['static_estimate', 'route_estimate', 'live_traffic'];
|
|
61
|
+
/** Access boundaries. A read-only routing admission never implies a write path. */
|
|
62
|
+
export const ROUTE_ACCESS_BOUNDARIES = ['read_only_public', 'licensed_read_only', 'supplier_transaction'];
|
|
63
|
+
/** Fault modes every candidate provider must be probed against before admission. */
|
|
64
|
+
export const ROUTE_PROVIDER_FAULT_MODES = [
|
|
65
|
+
'unavailable',
|
|
66
|
+
'stale',
|
|
67
|
+
'mismatched_direction',
|
|
68
|
+
'mode_relabel',
|
|
69
|
+
'estimate_as_live_traffic',
|
|
70
|
+
'challenge',
|
|
71
|
+
'rate_limited',
|
|
72
|
+
'partial_result',
|
|
73
|
+
];
|
|
74
|
+
/** Conformance clauses. A future adapter is admissible only if ALL of them pass. */
|
|
75
|
+
export const ROUTE_CONFORMANCE_CLAUSES = [
|
|
76
|
+
/** the response must echo the requested origin/destination; the swapped pair is a different fact */
|
|
77
|
+
'direction_binding',
|
|
78
|
+
/** the provider's own mode claim must equal the use case's mode */
|
|
79
|
+
'mode_isolation',
|
|
80
|
+
/** the provider's own evidence class must equal the use case's (no escalation, no shortfall) */
|
|
81
|
+
'evidence_class_isolation',
|
|
82
|
+
/** a provider outside the freshness contract is stale, never current */
|
|
83
|
+
'freshness_contract',
|
|
84
|
+
/** every admitted fact names its source identity and access boundary */
|
|
85
|
+
'source_identity',
|
|
86
|
+
/** every fault mode fails closed with a typed code — never a silent degrade */
|
|
87
|
+
'fault_fail_closed',
|
|
88
|
+
/** a refusal leaves the static fallback minutes, price and original label untouched */
|
|
89
|
+
'static_fallback_preserved',
|
|
90
|
+
/** a route provider is never a fare authority unless the use case declares a separate one */
|
|
91
|
+
'fare_authority_separate',
|
|
92
|
+
/** fault details are sanitized: no provider response body, markup, cookie or token */
|
|
93
|
+
'fault_detail_sanitized',
|
|
94
|
+
];
|
|
95
|
+
function fail(code, detail) {
|
|
96
|
+
return { ok: false, code, detail };
|
|
97
|
+
}
|
|
98
|
+
function pass(value) {
|
|
99
|
+
return { ok: true, value };
|
|
100
|
+
}
|
|
101
|
+
/** Runtime provider registry, frozen EMPTY. A non-empty value is a founder decision. */
|
|
102
|
+
export const ADMITTED_LIVE_ROUTE_PROVIDERS = [];
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Detail sanitization: see ./provider-detail-sanitize.ts (shared with the live
|
|
105
|
+
// ground-transfer path; re-exported above so this gate stays the single API).
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// The admission gate
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
function parseInstant(value, label) {
|
|
111
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
112
|
+
return fail('bad_ts', `${label} must be a non-empty ISO-8601 instant, got ${JSON.stringify(value)}`);
|
|
113
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value.trim()))
|
|
114
|
+
return fail('bad_ts', `${label} must carry a full time-of-day (date-only '${value}' cannot be aged)`);
|
|
115
|
+
const ms = Date.parse(value);
|
|
116
|
+
if (!Number.isFinite(ms))
|
|
117
|
+
return fail('bad_ts', `${label} is not a parseable ISO-8601 instant: ${JSON.stringify(value)}`);
|
|
118
|
+
return pass(new Date(ms).toISOString());
|
|
119
|
+
}
|
|
120
|
+
/** Map a provider fault to its typed refusal code (closed, total mapping). */
|
|
121
|
+
const FAULT_CODE = {
|
|
122
|
+
unavailable: 'unavailable',
|
|
123
|
+
stale: 'stale',
|
|
124
|
+
mismatched_direction: 'direction_mismatch',
|
|
125
|
+
mode_relabel: 'mode_mismatch',
|
|
126
|
+
estimate_as_live_traffic: 'evidence_class_escalation',
|
|
127
|
+
challenge: 'challenge',
|
|
128
|
+
rate_limited: 'rate_limited',
|
|
129
|
+
partial_result: 'partial_result',
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* The single admission gate: a provider outcome becomes a route fact only if every
|
|
133
|
+
* declared claim matches the named use case. Each refusal is typed and sanitized;
|
|
134
|
+
* no refusal ever degrades into a weaker-but-accepted fact.
|
|
135
|
+
*/
|
|
136
|
+
export function admitRouteFact(useCase, descriptor, request, outcome, now) {
|
|
137
|
+
if (typeof useCase?.id !== 'string' || useCase.id.trim() === '')
|
|
138
|
+
return fail('binding_incomplete', 'use case id is mandatory: a path is admitted per NAMED product use case, never globally');
|
|
139
|
+
if (!ROUTE_MODES.includes(useCase.mode))
|
|
140
|
+
return fail('closed_set', `use case mode must be one of [${ROUTE_MODES.join('/')}], got ${JSON.stringify(useCase.mode)}`);
|
|
141
|
+
if (!ROUTE_EVIDENCE_CLASSES.includes(useCase.evidence_class))
|
|
142
|
+
return fail('closed_set', `use case evidence_class must be one of [${ROUTE_EVIDENCE_CLASSES.join('/')}], got ${JSON.stringify(useCase.evidence_class)}`);
|
|
143
|
+
if (!ROUTE_ACCESS_BOUNDARIES.includes(useCase.access_boundary))
|
|
144
|
+
return fail('closed_set', `use case access_boundary must be one of [${ROUTE_ACCESS_BOUNDARIES.join('/')}]`);
|
|
145
|
+
if (!Number.isFinite(useCase.freshness_max_age_s) || useCase.freshness_max_age_s <= 0)
|
|
146
|
+
return fail('binding_incomplete', 'use case freshness_max_age_s must be a positive number of seconds (a path without a freshness contract is not admitted)');
|
|
147
|
+
if (typeof descriptor?.id !== 'string' || descriptor.id.trim() === '')
|
|
148
|
+
return fail('binding_incomplete', 'provider descriptor id is mandatory (source identity)');
|
|
149
|
+
if (typeof descriptor.legal_basis !== 'string' || descriptor.legal_basis.trim() === '')
|
|
150
|
+
return fail('binding_incomplete', `provider ${descriptor.id} carries no legal_basis — admission requires a stated licence / access boundary`);
|
|
151
|
+
if (typeof descriptor.source_sha !== 'string' || descriptor.source_sha.trim() === '')
|
|
152
|
+
return fail('binding_incomplete', `provider ${descriptor.id} carries no source_sha — D-39 requires the exact reviewed source revision`);
|
|
153
|
+
if (descriptor.access_boundary !== useCase.access_boundary) {
|
|
154
|
+
return fail('closed_set', `provider ${descriptor.id} access boundary '${descriptor.access_boundary}' does not match use case '${useCase.id}' boundary '${useCase.access_boundary}' — a read-only routing admission never widens into a transaction boundary`);
|
|
155
|
+
}
|
|
156
|
+
if (typeof request?.origin !== 'string' || request.origin.trim() === '' || typeof request?.destination !== 'string' || request.destination.trim() === '') {
|
|
157
|
+
return fail('binding_incomplete', 'request origin and destination are mandatory (direction binding has nothing to bind otherwise)');
|
|
158
|
+
}
|
|
159
|
+
if (request.mode !== useCase.mode) {
|
|
160
|
+
return fail('mode_mismatch', `request mode '${request.mode}' contradicts use case '${useCase.id}' mode '${useCase.mode}'`);
|
|
161
|
+
}
|
|
162
|
+
if (!outcome?.ok) {
|
|
163
|
+
if (!ROUTE_PROVIDER_FAULT_MODES.includes(outcome?.fault)) {
|
|
164
|
+
return fail('closed_set', `provider fault must be one of [${ROUTE_PROVIDER_FAULT_MODES.join('/')}], got ${JSON.stringify(outcome?.fault)} — an unclassified failure is not a degrade licence`);
|
|
165
|
+
}
|
|
166
|
+
return fail(FAULT_CODE[outcome.fault], `provider ${descriptor.id} fault '${outcome.fault}': ${sanitizeFaultDetail(outcome.detail)}`);
|
|
167
|
+
}
|
|
168
|
+
const response = outcome.response;
|
|
169
|
+
if (typeof response?.provider_id !== 'string' || response.provider_id.trim() === '')
|
|
170
|
+
return fail('binding_incomplete', 'response provider_id is mandatory (source identity per fact)');
|
|
171
|
+
if (response.provider_id !== descriptor.id) {
|
|
172
|
+
return fail('binding_incomplete', `response provider_id '${response.provider_id}' does not match the admitted descriptor '${descriptor.id}' — a fact may not be attributed to a provider that did not produce it`);
|
|
173
|
+
}
|
|
174
|
+
if (!ROUTE_MODES.includes(response.mode)) {
|
|
175
|
+
return fail('closed_set', `response mode must be one of [${ROUTE_MODES.join('/')}], got ${JSON.stringify(response.mode)} — a response without an explicit mode claim may not be labelled by the request`);
|
|
176
|
+
}
|
|
177
|
+
if (response.mode !== useCase.mode) {
|
|
178
|
+
return fail('mode_mismatch', `provider ${descriptor.id} returned mode '${response.mode}' for a '${useCase.mode}' use case — ${response.mode} must never be relabelled as ${useCase.mode} (nor the reverse)`);
|
|
179
|
+
}
|
|
180
|
+
if (!ROUTE_EVIDENCE_CLASSES.includes(response.evidence_class)) {
|
|
181
|
+
return fail('closed_set', `response evidence_class must be one of [${ROUTE_EVIDENCE_CLASSES.join('/')}], got ${JSON.stringify(response.evidence_class)}`);
|
|
182
|
+
}
|
|
183
|
+
if (response.evidence_class !== useCase.evidence_class) {
|
|
184
|
+
const providerRank = ROUTE_EVIDENCE_CLASSES.indexOf(response.evidence_class);
|
|
185
|
+
const useCaseRank = ROUTE_EVIDENCE_CLASSES.indexOf(useCase.evidence_class);
|
|
186
|
+
return providerRank > useCaseRank
|
|
187
|
+
? fail('evidence_class_escalation', `provider ${descriptor.id} claims '${response.evidence_class}' for a '${useCase.evidence_class}' use case — an estimate must never be presented as ${response.evidence_class}`)
|
|
188
|
+
: fail('evidence_class_shortfall', `provider ${descriptor.id} delivered '${response.evidence_class}' for a '${useCase.evidence_class}' use case — a weaker class may not fill a stronger promise`);
|
|
189
|
+
}
|
|
190
|
+
if (response.echoed_origin !== request.origin || response.echoed_destination !== request.destination) {
|
|
191
|
+
return fail('direction_mismatch', `provider ${descriptor.id} routed ${response.echoed_origin}→${response.echoed_destination} but the ${request.direction} request was ${request.origin}→${request.destination} — direction binding is verified against the RESPONSE, not assumed from the request`);
|
|
192
|
+
}
|
|
193
|
+
const distance = response.distance_m;
|
|
194
|
+
const duration = response.duration_s;
|
|
195
|
+
if (typeof distance !== 'number' || !Number.isFinite(distance) || distance < 0
|
|
196
|
+
|| typeof duration !== 'number' || !Number.isFinite(duration) || duration < 0
|
|
197
|
+
|| (distance > 0 && duration === 0)) {
|
|
198
|
+
return fail('partial_result', `provider ${descriptor.id} returned an incomplete or self-contradictory route (distance_m=${String(distance)}, duration_s=${String(duration)}); a positive distance cannot be covered in zero time`);
|
|
199
|
+
}
|
|
200
|
+
const nowParsed = parseInstant(now, 'gate clock now');
|
|
201
|
+
if (!nowParsed.ok)
|
|
202
|
+
return nowParsed;
|
|
203
|
+
const observedAt = parseInstant(response.observed_at, 'response observed_at (host observation instant)');
|
|
204
|
+
if (!observedAt.ok)
|
|
205
|
+
return observedAt;
|
|
206
|
+
if (observedAt.value > nowParsed.value) {
|
|
207
|
+
return fail('bad_ts', `observed_at ${observedAt.value} postdates the gate clock ${nowParsed.value} — a provider publication timestamp is not a host observation instant`);
|
|
208
|
+
}
|
|
209
|
+
const ageS = (Date.parse(nowParsed.value) - Date.parse(observedAt.value)) / 1000;
|
|
210
|
+
if (ageS > useCase.freshness_max_age_s) {
|
|
211
|
+
return fail('stale', `observation is ${ageS}s old, beyond the '${useCase.id}' freshness contract of ${useCase.freshness_max_age_s}s — stale never masquerades as current`);
|
|
212
|
+
}
|
|
213
|
+
let fare = null;
|
|
214
|
+
if (response.fare !== undefined) {
|
|
215
|
+
if (useCase.fare_authority === 'none') {
|
|
216
|
+
return fail('fare_not_authoritative', `provider ${descriptor.id} offered a fare for use case '${useCase.id}' which declares no fare authority — the static price and its original label stand until a separately authoritative fare exists`);
|
|
217
|
+
}
|
|
218
|
+
const f = response.fare;
|
|
219
|
+
if (typeof f.amount !== 'string' || f.amount.trim() === '' || typeof f.currency !== 'string' || f.currency.trim() === '' || typeof f.authority !== 'string' || f.authority.trim() === '') {
|
|
220
|
+
return fail('binding_incomplete', 'an admitted fare needs amount, currency and a named authority');
|
|
221
|
+
}
|
|
222
|
+
if (f.authority === descriptor.id || f.authority === response.provider_id) {
|
|
223
|
+
return fail('fare_not_authoritative', `a route provider ('${descriptor.id}') is never its own fare authority — '${useCase.id}' requires a separately authoritative fare source`);
|
|
224
|
+
}
|
|
225
|
+
fare = { amount: f.amount, currency: f.currency, authority: f.authority };
|
|
226
|
+
}
|
|
227
|
+
return pass(Object.freeze({
|
|
228
|
+
schema: ROUTE_PROVIDER_CONFORMANCE_SCHEMA,
|
|
229
|
+
use_case_id: useCase.id,
|
|
230
|
+
direction: request.direction,
|
|
231
|
+
origin: request.origin,
|
|
232
|
+
destination: request.destination,
|
|
233
|
+
mode: useCase.mode,
|
|
234
|
+
evidence_class: useCase.evidence_class,
|
|
235
|
+
provider_id: descriptor.id,
|
|
236
|
+
access_boundary: descriptor.access_boundary,
|
|
237
|
+
source_sha: descriptor.source_sha,
|
|
238
|
+
distance_m: distance,
|
|
239
|
+
duration_s: duration,
|
|
240
|
+
duration_min: Math.round(duration / 60),
|
|
241
|
+
observed_at: observedAt.value,
|
|
242
|
+
age_s: ageS,
|
|
243
|
+
fare,
|
|
244
|
+
}));
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* The only entry point to a live route adapter. While `D39_LIVE_ROUTE_TRIGGER_FIRED`
|
|
248
|
+
* is false this refuses BEFORE touching the adapter, so zero routing providers are
|
|
249
|
+
* contacted (the fetch-spy zero-call proof in run-all §87).
|
|
250
|
+
*/
|
|
251
|
+
export async function consultRouteProvider(adapter, useCase, request,
|
|
252
|
+
/** `now` is MANDATORY: this module reads no clock, so the caller injects one. */
|
|
253
|
+
options) {
|
|
254
|
+
const triggerFired = options?.triggerFired ?? D39_LIVE_ROUTE_TRIGGER_FIRED;
|
|
255
|
+
if (!triggerFired) {
|
|
256
|
+
return fail('trigger_deferred', `D-39 path trigger has not fired for use case '${String(useCase?.id)}' (#429: a named product use case + the actual provider and access boundary + reviewable authority/freshness/coverage evidence); zero routing providers contacted, static fallback stands`);
|
|
257
|
+
}
|
|
258
|
+
const registry = options?.registry ?? ADMITTED_LIVE_ROUTE_PROVIDERS;
|
|
259
|
+
if (!registry.some(d => d.id === adapter?.descriptor?.id)) {
|
|
260
|
+
return fail('provider_not_admitted', `provider '${String(adapter?.descriptor?.id)}' is not in the admitted registry (admitted: [${registry.map(d => d.id).join('/') || 'none'}]); admitting one is a per-path founder decision with a legal_basis and source_sha`);
|
|
261
|
+
}
|
|
262
|
+
const outcome = await adapter.fetchRoute(request, { signal: options?.signal ?? new AbortController().signal });
|
|
263
|
+
return admitRouteFact(useCase, adapter.descriptor, request, outcome, options.now);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Mechanical check: after a refusal, the static fallback must be unchanged —
|
|
267
|
+
* same mode, same minutes, same price and the SAME original price label. Returns
|
|
268
|
+
* a violation string, or null.
|
|
269
|
+
*/
|
|
270
|
+
export function staticFallbackViolation(before, after) {
|
|
271
|
+
if (before.mode !== after.mode)
|
|
272
|
+
return `static fallback mode changed '${before.mode}' → '${after.mode}'`;
|
|
273
|
+
if (before.minutes !== after.minutes)
|
|
274
|
+
return `static fallback minutes changed ${before.minutes} → ${after.minutes}: a refused route fact must not touch the static estimate`;
|
|
275
|
+
if (before.priceCny !== after.priceCny)
|
|
276
|
+
return `static fallback priceCny changed ${before.priceCny} → ${after.priceCny}: a route fact never supplies a price`;
|
|
277
|
+
if (before.priceEvidence !== after.priceEvidence)
|
|
278
|
+
return `static price label changed '${before.priceEvidence}' → '${after.priceEvidence}': the original label stands until a separately authoritative fare exists`;
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Run the conformance probes and report per clause.
|
|
283
|
+
*
|
|
284
|
+
* `admissible` is true only when every clause in `ROUTE_CONFORMANCE_CLAUSES` was
|
|
285
|
+
* probed AND passed: an unprobed clause is reported as unprobed and blocks
|
|
286
|
+
* admission, because "we never tested that" is not evidence of conformance.
|
|
287
|
+
*/
|
|
288
|
+
export function runRouteProviderConformance(useCase, descriptor, probes, now) {
|
|
289
|
+
const byClause = new Map();
|
|
290
|
+
for (const probe of probes) {
|
|
291
|
+
const slot = byClause.get(probe.clause) ?? { pass: true, count: 0, evidence: [] };
|
|
292
|
+
slot.count++;
|
|
293
|
+
const result = admitRouteFact(useCase, descriptor, probe.request, probe.outcome, now);
|
|
294
|
+
if (probe.expect === null) {
|
|
295
|
+
if (result.ok)
|
|
296
|
+
slot.evidence.push(`${probe.label}: admitted as expected`);
|
|
297
|
+
else {
|
|
298
|
+
slot.pass = false;
|
|
299
|
+
slot.evidence.push(`${probe.label}: expected admission, got refusal ${result.code} — ${result.detail}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else if (result.ok) {
|
|
303
|
+
slot.pass = false;
|
|
304
|
+
slot.evidence.push(`${probe.label}: expected refusal ${probe.expect}, got ADMISSION (a fault was silently accepted)`);
|
|
305
|
+
}
|
|
306
|
+
else if (result.code !== probe.expect) {
|
|
307
|
+
slot.pass = false;
|
|
308
|
+
slot.evidence.push(`${probe.label}: expected refusal ${probe.expect}, got ${result.code} — ${result.detail}`);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
const leak = faultDetailLeak(result.detail);
|
|
312
|
+
if (leak !== null) {
|
|
313
|
+
slot.pass = false;
|
|
314
|
+
slot.evidence.push(`${probe.label}: refused ${result.code} but the detail leaks — ${leak}`);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
slot.evidence.push(`${probe.label}: refused ${result.code} with a sanitized detail`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
byClause.set(probe.clause, slot);
|
|
321
|
+
}
|
|
322
|
+
const clauses = [];
|
|
323
|
+
const unprobed = [];
|
|
324
|
+
for (const clause of ROUTE_CONFORMANCE_CLAUSES) {
|
|
325
|
+
const slot = byClause.get(clause);
|
|
326
|
+
if (slot === undefined) {
|
|
327
|
+
unprobed.push(clause);
|
|
328
|
+
clauses.push({ clause, verdict: 'fail', probes: 0, evidence: ['clause was never probed — "untested" is not conformance'] });
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
clauses.push({ clause, verdict: slot.pass ? 'pass' : 'fail', probes: slot.count, evidence: Object.freeze([...slot.evidence]) });
|
|
332
|
+
}
|
|
333
|
+
return Object.freeze({
|
|
334
|
+
schema: ROUTE_PROVIDER_CONFORMANCE_SCHEMA,
|
|
335
|
+
use_case_id: useCase.id,
|
|
336
|
+
provider_id: descriptor.id,
|
|
337
|
+
admissible: unprobed.length === 0 && clauses.every(c => c.verdict === 'pass'),
|
|
338
|
+
clauses: Object.freeze([...clauses]),
|
|
339
|
+
unprobed: Object.freeze([...unprobed]),
|
|
340
|
+
});
|
|
341
|
+
}
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* action-cache 本地自愈层(RFC docs/rfc/user-session-data-rfc.md §3.2 / §2.3;Stagehand 云端缓存的本地化):
|
|
3
|
+
*
|
|
4
|
+
* 目的:会话检索的查询模式高度重复(同站点同类型搜索),首跑用 LLM/规则定位,后续走
|
|
5
|
+
* 缓存的确定性载荷零成本重放;站点改版 → DOM 指纹失配 → miss → 重新定位并回写。
|
|
6
|
+
*
|
|
7
|
+
* 设计原则(Stagehand「错误的缓存点击比慢更糟」的被动失效):
|
|
8
|
+
* - key = site + action + 参数模板(%from%/%to%/%date% 变量化,同型查询共享条目);
|
|
9
|
+
* - 每条目绑 domFingerprint(快照/接口形状的 sha256 指纹);lookup 时现场指纹与条目不符 = miss(即使 key 命中);
|
|
10
|
+
* - miss 即回写(记录新定位),过期(默认 48h)与容量(每 site 默认 50 条,LRU)被动淘汰;
|
|
11
|
+
* - 纯函数 + JSON 文件持久化(隔离 stateRoot;损坏文件按空缓存处理,永不抛错)。
|
|
12
|
+
*
|
|
13
|
+
* P2 切片:模块+确定性测试先行;消费方(P2 美团适配器/a11y 兜底)下一切片接线。
|
|
14
|
+
*/
|
|
1
15
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { mkdirSync, readFileSync, writeFileSync, existsSync
|
|
16
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
3
17
|
import { dirname, join } from 'node:path';
|
|
18
|
+
/** 把具体查询参数变量化为模板 key:日期→%date%,from/to 语义序在前,其余参数按字典序尾随 */
|
|
4
19
|
export function templateKey(site, action, params) {
|
|
5
|
-
const val = (k)=>k === 'date' ? '%date%' : (params[k] ?? '').trim();
|
|
6
|
-
const head = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
'date'
|
|
10
|
-
].filter((k)=>k in params).map(val);
|
|
11
|
-
const tail = Object.keys(params).filter((k)=>![
|
|
12
|
-
'from',
|
|
13
|
-
'to',
|
|
14
|
-
'date'
|
|
15
|
-
].includes(k)).sort().map(val);
|
|
16
|
-
return `${site}:${action}:${[
|
|
17
|
-
...head,
|
|
18
|
-
...tail
|
|
19
|
-
].join('|')}`;
|
|
20
|
+
const val = (k) => (k === 'date' ? '%date%' : (params[k] ?? '').trim());
|
|
21
|
+
const head = ['from', 'to', 'date'].filter((k) => k in params).map(val);
|
|
22
|
+
const tail = Object.keys(params).filter((k) => !['from', 'to', 'date'].includes(k)).sort().map(val);
|
|
23
|
+
return `${site}:${action}:${[...head, ...tail].join('|')}`;
|
|
20
24
|
}
|
|
25
|
+
/** 指纹:快照/接口形状文本 → sha256 前 16 位(微改版即失配——宁可 miss 不可错点) */
|
|
21
26
|
export function fingerprint(shapeText) {
|
|
22
27
|
return createHash('sha256').update(shapeText).digest('hex').slice(0, 16);
|
|
23
28
|
}
|
|
@@ -28,76 +33,79 @@ export class ActionCache {
|
|
|
28
33
|
ttlMs;
|
|
29
34
|
maxPerSite;
|
|
30
35
|
now;
|
|
31
|
-
constructor(filePath, opts = {}){
|
|
36
|
+
constructor(filePath, opts = {}) {
|
|
32
37
|
this.filePath = filePath;
|
|
33
38
|
this.ttlMs = opts.ttlMs ?? 48 * 3600_000;
|
|
34
39
|
this.maxPerSite = opts.maxEntriesPerSite ?? 50;
|
|
35
|
-
this.now = opts.now ?? (()=>new Date());
|
|
40
|
+
this.now = opts.now ?? (() => new Date());
|
|
36
41
|
}
|
|
37
42
|
load() {
|
|
38
|
-
if (this.loaded)
|
|
43
|
+
if (this.loaded)
|
|
44
|
+
return;
|
|
39
45
|
this.loaded = true;
|
|
40
46
|
try {
|
|
41
47
|
if (existsSync(this.filePath)) {
|
|
42
48
|
const raw = JSON.parse(readFileSync(this.filePath, 'utf8'));
|
|
43
|
-
for (const e of raw){
|
|
44
|
-
if (e?.key && e.domFingerprint && e.locator)
|
|
49
|
+
for (const e of raw) {
|
|
50
|
+
if (e?.key && e.domFingerprint && e.locator)
|
|
51
|
+
this.entries.set(e.key, e);
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
|
-
}
|
|
54
|
+
}
|
|
55
|
+
catch { /* 损坏文件按空缓存处理 */ }
|
|
48
56
|
}
|
|
49
57
|
persist() {
|
|
50
58
|
try {
|
|
51
|
-
mkdirSync(dirname(this.filePath), {
|
|
52
|
-
recursive: true
|
|
53
|
-
});
|
|
59
|
+
mkdirSync(dirname(this.filePath), { recursive: true });
|
|
54
60
|
const tmp = this.filePath + '.tmp';
|
|
55
|
-
writeFileSync(tmp, JSON.stringify([
|
|
56
|
-
...this.entries.values()
|
|
57
|
-
], null, 0), 'utf8');
|
|
61
|
+
writeFileSync(tmp, JSON.stringify([...this.entries.values()], null, 0), 'utf8');
|
|
58
62
|
writeFileSync(this.filePath, readFileSync(tmp, 'utf8'), 'utf8');
|
|
59
63
|
try {
|
|
60
64
|
require('node:fs').rmSync(tmp);
|
|
61
|
-
}
|
|
62
|
-
|
|
65
|
+
}
|
|
66
|
+
catch { /* best effort */ }
|
|
67
|
+
}
|
|
68
|
+
catch { /* 持久化失败不阻塞内存路径 */ }
|
|
63
69
|
}
|
|
70
|
+
/** 站点前缀条目数(LRU 淘汰用) */
|
|
64
71
|
siteEntries(site) {
|
|
65
|
-
return [
|
|
66
|
-
...this.entries.values()
|
|
67
|
-
].filter((e)=>e.key.startsWith(site + ':'));
|
|
72
|
+
return [...this.entries.values()].filter((e) => e.key.startsWith(site + ':'));
|
|
68
73
|
}
|
|
74
|
+
/** 命中三条件:key 存在 + 未过期 + 指纹一致;命中计 hits 并惰性落盘 */
|
|
69
75
|
lookup(key, domFingerprint, site) {
|
|
70
76
|
this.load();
|
|
71
77
|
const e = this.entries.get(key);
|
|
72
|
-
if (!e)
|
|
78
|
+
if (!e)
|
|
79
|
+
return null;
|
|
73
80
|
if (this.now().getTime() - Date.parse(e.lastHitAt || e.createdAt) > this.ttlMs) {
|
|
74
81
|
this.entries.delete(key);
|
|
75
82
|
this.persist();
|
|
76
83
|
return null;
|
|
77
84
|
}
|
|
78
|
-
if (e.domFingerprint !== domFingerprint)
|
|
85
|
+
if (e.domFingerprint !== domFingerprint)
|
|
86
|
+
return null; // 改版:被动失效,等 record 回写
|
|
79
87
|
e.hits += 1;
|
|
80
88
|
e.lastHitAt = this.now().toISOString();
|
|
81
89
|
this.persist();
|
|
82
90
|
void site;
|
|
83
91
|
return e;
|
|
84
92
|
}
|
|
93
|
+
/** miss 后回写(重新定位的产物);同 key 覆盖;超容 LRU 淘汰最旧 */
|
|
85
94
|
record(key, domFingerprint, locator, site) {
|
|
86
95
|
this.load();
|
|
87
96
|
const ts = this.now().toISOString();
|
|
88
97
|
const prev = this.entries.get(key);
|
|
89
98
|
this.entries.set(key, {
|
|
90
|
-
key,
|
|
91
|
-
domFingerprint,
|
|
92
|
-
locator,
|
|
99
|
+
key, domFingerprint, locator,
|
|
93
100
|
createdAt: prev?.createdAt ?? ts,
|
|
94
101
|
lastHitAt: ts,
|
|
95
|
-
hits: prev?.hits ?? 0
|
|
102
|
+
hits: prev?.hits ?? 0,
|
|
96
103
|
});
|
|
97
104
|
const siteList = this.siteEntries(site);
|
|
98
105
|
if (siteList.length > this.maxPerSite) {
|
|
99
|
-
const victim = siteList.sort((a, b)=>Date.parse(a.lastHitAt) - Date.parse(b.lastHitAt))[0];
|
|
100
|
-
if (victim)
|
|
106
|
+
const victim = siteList.sort((a, b) => Date.parse(a.lastHitAt) - Date.parse(b.lastHitAt))[0];
|
|
107
|
+
if (victim)
|
|
108
|
+
this.entries.delete(victim.key);
|
|
101
109
|
}
|
|
102
110
|
this.persist();
|
|
103
111
|
return this.entries.get(key);
|
|
@@ -112,9 +120,7 @@ export class ActionCache {
|
|
|
112
120
|
return site ? this.siteEntries(site).length : this.entries.size;
|
|
113
121
|
}
|
|
114
122
|
}
|
|
123
|
+
/** 便捷入口:隔离 stateRoot 下的缓存文件路径 */
|
|
115
124
|
export function actionCachePath(stateRoot) {
|
|
116
125
|
return join(stateRoot, 'session-action-cache.json');
|
|
117
126
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//# sourceURL=/Users/bytedance/work/gotry/ts/capabilities/session/action-cache.ts
|