@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.
Files changed (533) hide show
  1. package/README.md +172 -219
  2. package/README.zh-CN.md +222 -0
  3. package/bin/gotry-backend.js +53 -0
  4. package/bin/gotry-booking-copilot.js +53 -0
  5. package/bin/gotry-bootstrap.js +1788 -0
  6. package/bin/gotry-inner.js +733 -83
  7. package/bin/gotry-process-liveness.d.ts +27 -0
  8. package/bin/gotry-process-liveness.js +97 -0
  9. package/bin/gotry-runtime-resolution.d.ts +27 -0
  10. package/bin/gotry-runtime-resolution.js +49 -0
  11. package/bin/gotry.js +1 -1
  12. package/client/client.js +203 -0
  13. package/cordis.gotry-patch.yml +80 -56
  14. package/data/airline-airports.json +39 -0
  15. package/data/stations-12306-verify.json +524 -0
  16. package/dist/capabilities/agent-reach-deep.js +45 -122
  17. package/dist/capabilities/agent-reach.js +101 -146
  18. package/dist/capabilities/anything.js +161 -94
  19. package/dist/capabilities/artifacts.js +370 -0
  20. package/dist/capabilities/channel-health.js +131 -0
  21. package/dist/capabilities/channel-registry.js +256 -0
  22. package/dist/capabilities/doctor.js +553 -0
  23. package/dist/capabilities/effect.js +394 -0
  24. package/dist/capabilities/external-event.js +149 -0
  25. package/dist/capabilities/fact-log.js +55 -0
  26. package/dist/capabilities/flyai-config.js +337 -0
  27. package/dist/capabilities/flyai.js +947 -110
  28. package/dist/capabilities/fx-contract.js +293 -0
  29. package/dist/capabilities/geo-atlas.js +246 -0
  30. package/dist/capabilities/ground-transfer.js +676 -0
  31. package/dist/capabilities/hbcli.js +260 -123
  32. package/dist/capabilities/hotelbyte-transaction.js +194 -0
  33. package/dist/capabilities/incident-log.js +131 -61
  34. package/dist/capabilities/itinerary-artifact.js +190 -0
  35. package/dist/capabilities/itinerary-deck-artifact.js +194 -0
  36. package/dist/capabilities/itinerary-deck-export.js +339 -0
  37. package/dist/capabilities/lavish-local.js +924 -0
  38. package/dist/capabilities/model-override.js +38 -0
  39. package/dist/capabilities/opensky.js +54 -43
  40. package/dist/capabilities/provider-detail-sanitize.js +64 -0
  41. package/dist/capabilities/resilience.js +191 -0
  42. package/dist/capabilities/route-provider-conformance.js +341 -0
  43. package/dist/capabilities/session/action-cache.js +50 -44
  44. package/dist/capabilities/session/adapters/ctrip-flight.js +120 -62
  45. package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
  46. package/dist/capabilities/session/adapters/dida-portal.js +274 -0
  47. package/dist/capabilities/session/adapters/meituan-local.js +35 -54
  48. package/dist/capabilities/session/adapters/rail-12306.js +342 -0
  49. package/dist/capabilities/session/benchmark.js +189 -0
  50. package/dist/capabilities/session/bridge-ledger.js +224 -0
  51. package/dist/capabilities/session/extension-bridge.js +636 -0
  52. package/dist/capabilities/session/extension-channel.js +109 -0
  53. package/dist/capabilities/session/extension-distribution.js +230 -0
  54. package/dist/capabilities/session/extract.js +31 -21
  55. package/dist/capabilities/session/golden-score.js +114 -0
  56. package/dist/capabilities/session/health-watch.js +215 -0
  57. package/dist/capabilities/session/read-guard.js +75 -24
  58. package/dist/capabilities/session/static-flight-golden.js +150 -0
  59. package/dist/capabilities/session/transport.js +97 -83
  60. package/dist/capabilities/session/wizard.js +117 -0
  61. package/dist/capabilities/session-consent.js +178 -0
  62. package/dist/capabilities/session-login.js +170 -0
  63. package/dist/capabilities/session-search.js +635 -44
  64. package/dist/capabilities/spawn-bounded.js +203 -0
  65. package/dist/capabilities/sponsor-plugin.js +341 -0
  66. package/dist/capabilities/visa-policy.js +140 -0
  67. package/dist/capabilities/weather.js +243 -138
  68. package/dist/data/session-golden-20.json +25 -0
  69. package/dist/data/sf-golden-manifest.json +103 -0
  70. package/dist/data/sf-static-routes.json +91 -0
  71. package/dist/scripts/action-cache-tests.js +24 -59
  72. package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
  73. package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
  74. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  75. package/dist/scripts/agent-reach-error-tests.js +354 -0
  76. package/dist/scripts/agent-reach-tests.js +26 -18
  77. package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
  78. package/dist/scripts/anything-path-measure-tests.js +133 -0
  79. package/dist/scripts/anything-path-measure.js +150 -0
  80. package/dist/scripts/anything-tests.js +250 -60
  81. package/dist/scripts/artifact-client-contract-tests.js +220 -0
  82. package/dist/scripts/artifacts-capability-tests.js +727 -0
  83. package/dist/scripts/async-collect.js +50 -11
  84. package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
  85. package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
  86. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
  87. package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
  88. package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
  89. package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
  90. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
  91. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
  92. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
  93. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
  94. package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
  95. package/dist/scripts/booking-copilot-dsh-warmer-proof.js +126 -0
  96. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
  97. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
  98. package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
  99. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
  100. package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
  101. package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
  102. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
  103. package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
  104. package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
  105. package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
  106. package/dist/scripts/booking-executor-tests.js +80 -0
  107. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  108. package/dist/scripts/booking-saga-tests.js +125 -0
  109. package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
  110. package/dist/scripts/bootstrap-tests.js +1549 -0
  111. package/dist/scripts/bridge-events-tests.js +239 -0
  112. package/dist/scripts/bridge-ledger-tests.js +428 -0
  113. package/dist/scripts/build-changelog.js +238 -0
  114. package/dist/scripts/build-metrics-report.js +331 -0
  115. package/dist/scripts/changelog-tests.js +118 -0
  116. package/dist/scripts/channel-probe-tests.js +103 -0
  117. package/dist/scripts/channel-probe.js +169 -0
  118. package/dist/scripts/channel-registry-tests.js +208 -0
  119. package/dist/scripts/city-scenario-tier-tests.js +234 -0
  120. package/dist/scripts/companion-tests.js +25 -70
  121. package/dist/scripts/dida-cookie-probe.js +87 -0
  122. package/dist/scripts/dida-runner-stop-tests.js +311 -0
  123. package/dist/scripts/dida-sw-probe.js +114 -0
  124. package/dist/scripts/diff-test.js +17 -12
  125. package/dist/scripts/doctor-tests.js +600 -0
  126. package/dist/scripts/drill-multiuser-ledger-tests.js +1076 -0
  127. package/dist/scripts/drill-sdk-descendant-cleanup-tests.js +606 -0
  128. package/dist/scripts/drill-w2a-sensor-tests.js +788 -0
  129. package/dist/scripts/dsh-artifact-e2e.js +279 -0
  130. package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
  131. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  132. package/dist/scripts/dsh-llm-tests.js +437 -0
  133. package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
  134. package/dist/scripts/dsh-runtime-closure.js +162 -0
  135. package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
  136. package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
  137. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  138. package/dist/scripts/effect-tests.js +539 -0
  139. package/dist/scripts/engine-run.js +1 -3
  140. package/dist/scripts/engine-tests.js +16 -10
  141. package/dist/scripts/evaluation-cadence-tests.js +174 -0
  142. package/dist/scripts/evaluation-contract-tests.js +268 -0
  143. package/dist/scripts/extension-distribution-cli.js +39 -0
  144. package/dist/scripts/extension-distribution-tests.js +443 -0
  145. package/dist/scripts/extension-tests.js +988 -0
  146. package/dist/scripts/external-event-tests.js +350 -0
  147. package/dist/scripts/fact-gate-tests.js +869 -0
  148. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  149. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  150. package/dist/scripts/flight-malformed-tests.js +159 -0
  151. package/dist/scripts/flyai-setup-tests.js +228 -0
  152. package/dist/scripts/flyai-setup-tool-tests.js +54 -0
  153. package/dist/scripts/flyai-tests.js +692 -0
  154. package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
  155. package/dist/scripts/fx-contract-tests.js +201 -0
  156. package/dist/scripts/g5-guard-tests.js +150 -0
  157. package/dist/scripts/g5-guard.js +193 -0
  158. package/dist/scripts/gen-lunar-anchors.js +106 -0
  159. package/dist/scripts/geo-atlas-tests.js +283 -0
  160. package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
  161. package/dist/scripts/gotry-try-demo-tests.js +79 -0
  162. package/dist/scripts/gotry-try-demo.js +49 -0
  163. package/dist/scripts/ground-transfer-tests.js +956 -0
  164. package/dist/scripts/hbcli-e2e-tests.js +159 -0
  165. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  166. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  167. package/dist/scripts/hbcli-tests.js +121 -69
  168. package/dist/scripts/health-watch-cli.js +73 -0
  169. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  170. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  171. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  172. package/dist/scripts/i18n-tests.js +41 -0
  173. package/dist/scripts/incident-tests.js +281 -87
  174. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  175. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  176. package/dist/scripts/issue-271-liveness-tests.js +569 -0
  177. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  178. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  179. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  180. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  181. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  182. package/dist/scripts/issue436-persisted-routing-e2e.js +247 -0
  183. package/dist/scripts/itinerary-artifact-tests.js +368 -0
  184. package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
  185. package/dist/scripts/itinerary-deck-export-tests.js +552 -0
  186. package/dist/scripts/itinerary-deck-tests.js +435 -0
  187. package/dist/scripts/itinerary-html-tests.js +426 -0
  188. package/dist/scripts/journey-tests.js +22 -27
  189. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  190. package/dist/scripts/kernel-manifest-gate.js +126 -0
  191. package/dist/scripts/kernel-manifest-tests.js +212 -0
  192. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  193. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  194. package/dist/scripts/kernel-manifest.js +369 -0
  195. package/dist/scripts/lavish-local-tests.js +1226 -0
  196. package/dist/scripts/lavish-product-tools-tests.js +537 -0
  197. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  198. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  199. package/dist/scripts/ledger-tests.js +382 -246
  200. package/dist/scripts/ledger-workflow-crash.js +10 -20
  201. package/dist/scripts/m3-cohort-tests.js +714 -0
  202. package/dist/scripts/m3-cohort.js +310 -0
  203. package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
  204. package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
  205. package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
  206. package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
  207. package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
  208. package/dist/scripts/memory-capture-tests.js +242 -61
  209. package/dist/scripts/memory-decay-tests.js +18 -52
  210. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  211. package/dist/scripts/memory-lifecycle.js +196 -0
  212. package/dist/scripts/memory-metrics.js +24 -12
  213. package/dist/scripts/memory-value-report.js +631 -0
  214. package/dist/scripts/memory-value-tests.js +328 -0
  215. package/dist/scripts/metrics-report-tests.js +151 -0
  216. package/dist/scripts/model-override-e2e.js +137 -0
  217. package/dist/scripts/nightly-evidence-tests.js +203 -0
  218. package/dist/scripts/nightly-evidence.js +303 -0
  219. package/dist/scripts/nudge-digest.js +39 -28
  220. package/dist/scripts/observability-tests.js +381 -0
  221. package/dist/scripts/onboarding-tests.js +161 -0
  222. package/dist/scripts/opensky-check.js +18 -13
  223. package/dist/scripts/opensky-tests.js +28 -28
  224. package/dist/scripts/outcome-projection-tests.js +427 -0
  225. package/dist/scripts/persona-sim-tests.js +603 -0
  226. package/dist/scripts/persona-sim.js +1081 -0
  227. package/dist/scripts/persona-surface-guard-tests.js +49 -0
  228. package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
  229. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  230. package/dist/scripts/price-drift-tests.js +340 -0
  231. package/dist/scripts/price-drift-watch.js +447 -0
  232. package/dist/scripts/probe-poi-tests.js +53 -45
  233. package/dist/scripts/product-metrics.js +483 -0
  234. package/dist/scripts/publish-preverify.js +110 -0
  235. package/dist/scripts/realtime-pricing-tests.js +76 -0
  236. package/dist/scripts/recall-tests.js +513 -0
  237. package/dist/scripts/replay-async.js +22 -18
  238. package/dist/scripts/replay-real.js +18 -18
  239. package/dist/scripts/replay.js +54 -82
  240. package/dist/scripts/route-provider-conformance-tests.js +391 -0
  241. package/dist/scripts/session-attach-diagnose.js +20 -20
  242. package/dist/scripts/session-attach-poc.js +34 -37
  243. package/dist/scripts/session-benchmark.js +180 -0
  244. package/dist/scripts/session-dida-live-e2e.js +199 -0
  245. package/dist/scripts/session-extract-tests.js +14 -35
  246. package/dist/scripts/session-link-tests.js +478 -0
  247. package/dist/scripts/session-login.js +27 -46
  248. package/dist/scripts/session-tests.js +796 -96
  249. package/dist/scripts/session-zone-crash.js +49 -0
  250. package/dist/scripts/session-zone-ledger-tests.js +432 -0
  251. package/dist/scripts/session-zone-observation-tests.js +492 -0
  252. package/dist/scripts/session-zone-observe.js +135 -0
  253. package/dist/scripts/session-zone-wiring-tests.js +566 -0
  254. package/dist/scripts/session-zones-tests.js +374 -0
  255. package/dist/scripts/sf-live-benchmark.js +367 -0
  256. package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
  257. package/dist/scripts/sf-live-cli-tests.js +92 -0
  258. package/dist/scripts/sf-live-options.js +46 -0
  259. package/dist/scripts/sf-manifest-tests.js +30 -0
  260. package/dist/scripts/sf-manifest.js +33 -0
  261. package/dist/scripts/sf-soft-score-tests.js +67 -0
  262. package/dist/scripts/sf-summary-tests.js +324 -0
  263. package/dist/scripts/sf-summary.js +525 -0
  264. package/dist/scripts/share-tests.js +432 -0
  265. package/dist/scripts/skeleton-check.js +16 -14
  266. package/dist/scripts/skeleton-integration-test.js +28 -11
  267. package/dist/scripts/skills-contract-tests.js +51 -46
  268. package/dist/scripts/smoke-session-gate-tests.js +21 -0
  269. package/dist/scripts/smoke.js +690 -246
  270. package/dist/scripts/spawn-bounded-abort-tests.js +244 -0
  271. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  272. package/dist/scripts/state-cli-tests.js +226 -101
  273. package/dist/scripts/state-cli.js +565 -198
  274. package/dist/scripts/state-repair-cli.js +66 -0
  275. package/dist/scripts/state-repair-tests.js +140 -0
  276. package/dist/scripts/static-golden-tests.js +165 -0
  277. package/dist/scripts/time-eval-tests.js +212 -192
  278. package/dist/scripts/travel-timeline-tests.js +29 -93
  279. package/dist/scripts/turn-handoff-collect-tests.js +169 -0
  280. package/dist/scripts/turn-handoff-collect.js +161 -0
  281. package/dist/scripts/turn-policy-tests.js +55 -0
  282. package/dist/scripts/typed-contract-canary.js +176 -0
  283. package/dist/scripts/tz-resolver-sanity.js +50 -0
  284. package/dist/scripts/tz-resolver-tests.js +584 -0
  285. package/dist/scripts/unified-tests.js +60 -20
  286. package/dist/scripts/visa-policy-tests.js +62 -0
  287. package/dist/scripts/weather-tests.js +276 -41
  288. package/dist/scripts/wish-channel-gate-tests.js +54 -0
  289. package/dist/scripts/write-gate-tests.js +522 -0
  290. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  291. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  292. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  293. package/dist/scripts/z3-race-tests.js +46 -0
  294. package/dist/src/artifact-gate.js +829 -0
  295. package/dist/src/backend/kernel.js +91 -0
  296. package/dist/src/backend/modules/booking-copilot.js +92 -0
  297. package/dist/src/backend/modules/booking-executor.js +124 -0
  298. package/dist/src/backend/modules/session-search.js +551 -0
  299. package/dist/src/benchmark-agent-conformance.js +578 -0
  300. package/dist/src/benchmark-environment-bridge.js +515 -0
  301. package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
  302. package/dist/src/benchmark-tool-isolation.js +151 -0
  303. package/dist/src/bookable-facts.js +533 -0
  304. package/dist/src/booking-saga.js +97 -0
  305. package/dist/src/booking-surface/availability-policy.js +697 -0
  306. package/dist/src/booking-surface/booking-intent.js +43 -0
  307. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  308. package/dist/src/booking-surface/canonical-schema.js +116 -0
  309. package/dist/src/booking-surface/contracts.js +75 -0
  310. package/dist/src/booking-surface/dsh-planner.js +1854 -0
  311. package/dist/src/booking-surface/dsh-plugin.js +378 -0
  312. package/dist/src/booking-surface/dsh-worker.js +98 -0
  313. package/dist/src/booking-surface/error-codes.js +231 -0
  314. package/dist/src/booking-surface/index.js +9 -0
  315. package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
  316. package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
  317. package/dist/src/booking-surface/profile.js +24 -0
  318. package/dist/src/booking-surface/recovery-chain.js +367 -0
  319. package/dist/src/booking-surface/runtime.js +1968 -0
  320. package/dist/src/booking-surface/server.js +674 -0
  321. package/dist/src/booking-surface/startup.js +168 -0
  322. package/dist/src/booking-surface/validation.js +261 -0
  323. package/dist/src/bridge.js +20 -13
  324. package/dist/src/city-scenario-tier.js +378 -0
  325. package/dist/src/companions.js +48 -74
  326. package/dist/src/contracts.js +21 -43
  327. package/dist/src/dsh-llm.js +171 -115
  328. package/dist/src/engine.js +276 -193
  329. package/dist/src/evaluation-cadence.js +97 -0
  330. package/dist/src/evaluation-contracts.js +283 -0
  331. package/dist/src/flight-pack-adapter.js +54 -0
  332. package/dist/src/flight-pack-contract.js +2 -0
  333. package/dist/src/flyai-setup-tool.js +70 -0
  334. package/dist/src/gotry-backend.js +125 -0
  335. package/dist/src/hotel-date-gate.js +118 -0
  336. package/dist/src/i18n.js +88 -0
  337. package/dist/src/index.js +2385 -881
  338. package/dist/src/itinerary-deck.js +139 -0
  339. package/dist/src/itinerary-doc-shared.js +661 -0
  340. package/dist/src/itinerary-html.js +131 -0
  341. package/dist/src/journey.js +155 -108
  342. package/dist/src/lavish-tools.js +400 -0
  343. package/dist/src/ledger-repair-apply.js +538 -0
  344. package/dist/src/ledger-repair-plan.js +463 -0
  345. package/dist/src/loop.js +331 -161
  346. package/dist/src/m3-cohort.js +1577 -0
  347. package/dist/src/memory-capture.js +180 -32
  348. package/dist/src/memory-decay.js +30 -14
  349. package/dist/src/memory-lifecycle.js +1310 -0
  350. package/dist/src/memory-utility.js +27 -40
  351. package/dist/src/mock-llm.js +36 -61
  352. package/dist/src/model.js +81 -36
  353. package/dist/src/outcome-projection.js +746 -0
  354. package/dist/src/realtime-pricing.js +103 -0
  355. package/dist/src/recall/card.js +74 -0
  356. package/dist/src/recall/evaluator.js +140 -0
  357. package/dist/src/recall/integration.js +17 -0
  358. package/dist/src/recall/tick.js +166 -0
  359. package/dist/src/session-link/plan-it-action.js +48 -0
  360. package/dist/src/session-link/session-link.js +248 -0
  361. package/dist/src/session-zone-ledger.js +312 -0
  362. package/dist/src/session-zone-observation.js +354 -0
  363. package/dist/src/session-zone-wiring.js +658 -0
  364. package/dist/src/session-zones.js +510 -0
  365. package/dist/src/share/adapters.js +51 -0
  366. package/dist/src/share/share-consent.js +76 -0
  367. package/dist/src/share/share-deck.js +58 -0
  368. package/dist/src/share/share-token.js +146 -0
  369. package/dist/src/slot-spec.js +84 -106
  370. package/dist/src/state-ledger.js +696 -524
  371. package/dist/src/state-repair.js +299 -0
  372. package/dist/src/subagent-job-id-guard.js +58 -0
  373. package/dist/src/time-anchor.js +231 -33
  374. package/dist/src/tool-packet.js +20 -8
  375. package/dist/src/travel-slots.js +58 -35
  376. package/dist/src/travel-timeline.js +44 -63
  377. package/dist/src/turn-deadline.js +287 -0
  378. package/dist/src/turn-policy.js +118 -0
  379. package/dist/src/tz-resolver.js +143 -0
  380. package/dist/src/unified.js +600 -360
  381. package/dist/src/wish-pool.js +42 -12
  382. package/dist/src/write-gate.js +495 -0
  383. package/dist/src/z3-shared.js +284 -0
  384. package/extension/README.md +21 -0
  385. package/extension/README.zh-CN.md +21 -0
  386. package/extension/background.js +463 -0
  387. package/extension/content-bridge.js +270 -0
  388. package/extension/content-main.js +111 -0
  389. package/extension/manifest.json +60 -0
  390. package/package.json +407 -14
  391. package/schemas/booking.intent.schema.json +193 -0
  392. package/schemas/booking.surface.schema.json +2622 -0
  393. package/ts/capabilities/agent-reach-deep.ts +114 -0
  394. package/ts/capabilities/agent-reach.ts +198 -0
  395. package/ts/capabilities/anything.ts +282 -0
  396. package/ts/capabilities/artifacts.ts +428 -0
  397. package/ts/capabilities/fact-log.ts +54 -0
  398. package/ts/capabilities/flyai-config.ts +388 -0
  399. package/ts/capabilities/flyai.ts +1274 -0
  400. package/ts/capabilities/hbcli.ts +253 -71
  401. package/ts/capabilities/incident-log.ts +88 -59
  402. package/ts/capabilities/itinerary-artifact.ts +214 -0
  403. package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
  404. package/ts/capabilities/itinerary-deck-export.ts +378 -0
  405. package/ts/capabilities/opensky.ts +121 -0
  406. package/ts/capabilities/session/action-cache.ts +148 -0
  407. package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
  408. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  409. package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
  410. package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
  411. package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
  412. package/ts/capabilities/session/benchmark.ts +276 -0
  413. package/ts/capabilities/session/bridge-ledger.ts +333 -0
  414. package/ts/capabilities/session/extension-bridge.ts +794 -0
  415. package/ts/capabilities/session/extension-channel.ts +144 -0
  416. package/ts/capabilities/session/extension-distribution.ts +266 -0
  417. package/ts/capabilities/session/extract.ts +54 -0
  418. package/ts/capabilities/session/golden-score.ts +139 -0
  419. package/ts/capabilities/session/health-watch.ts +264 -0
  420. package/ts/capabilities/session/read-guard.ts +141 -0
  421. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  422. package/ts/capabilities/session/transport.ts +146 -0
  423. package/ts/capabilities/session/wizard.ts +140 -0
  424. package/ts/capabilities/session-consent.ts +211 -0
  425. package/ts/capabilities/session-login.ts +208 -0
  426. package/ts/capabilities/session-search.ts +893 -0
  427. package/ts/capabilities/weather.ts +330 -0
  428. package/ts/dsh-runtime/vendor/README.md +68 -0
  429. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  430. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
  431. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
  432. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
  433. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  434. package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
  435. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
  436. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  437. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
  438. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  439. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  440. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
  441. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  442. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
  443. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
  444. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
  445. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
  446. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  447. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  448. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
  449. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
  450. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  451. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  452. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  453. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  454. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
  455. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  456. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
  457. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  458. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  459. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
  460. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  461. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  462. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
  463. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
  464. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  465. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
  466. package/ts/package.json +293 -3
  467. package/ts/scripts/async-collect.ts +91 -0
  468. package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
  469. package/ts/scripts/skeleton-check.ts +1 -1
  470. package/ts/scripts/skeleton-integration-test.ts +23 -1
  471. package/ts/scripts/state-cli.ts +586 -0
  472. package/ts/scripts/turn-handoff-collect.ts +178 -0
  473. package/ts/src/artifact-gate.ts +991 -0
  474. package/ts/src/benchmark-agent-conformance.ts +619 -0
  475. package/ts/src/benchmark-environment-bridge.ts +538 -0
  476. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  477. package/ts/src/benchmark-tool-isolation.ts +166 -0
  478. package/ts/src/bookable-facts.ts +837 -0
  479. package/ts/src/booking-saga.ts +133 -0
  480. package/ts/src/booking-surface/availability-policy.ts +522 -0
  481. package/ts/src/booking-surface/booking-intent.ts +86 -0
  482. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  483. package/ts/src/booking-surface/canonical-schema.js +116 -0
  484. package/ts/src/booking-surface/contracts.ts +475 -0
  485. package/ts/src/booking-surface/dsh-planner.ts +1949 -0
  486. package/ts/src/booking-surface/dsh-plugin.js +378 -0
  487. package/ts/src/booking-surface/dsh-worker.ts +110 -0
  488. package/ts/src/booking-surface/error-codes.ts +241 -0
  489. package/ts/src/booking-surface/index.ts +9 -0
  490. package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
  491. package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
  492. package/ts/src/booking-surface/profile.ts +42 -0
  493. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  494. package/ts/src/booking-surface/runtime.ts +1793 -0
  495. package/ts/src/booking-surface/server.ts +733 -0
  496. package/ts/src/booking-surface/startup.ts +201 -0
  497. package/ts/src/booking-surface/validation.ts +217 -0
  498. package/ts/src/companions.ts +113 -0
  499. package/ts/src/contracts.ts +17 -3
  500. package/ts/src/dsh-llm.ts +152 -17
  501. package/ts/src/flyai-setup-tool.ts +77 -0
  502. package/ts/src/index.ts +2123 -200
  503. package/ts/src/itinerary-deck.ts +189 -0
  504. package/ts/src/itinerary-doc-shared.ts +741 -0
  505. package/ts/src/itinerary-html.ts +171 -0
  506. package/ts/src/loop.ts +234 -26
  507. package/ts/src/memory-capture.ts +283 -0
  508. package/ts/src/memory-decay.ts +55 -0
  509. package/ts/src/memory-utility.ts +70 -0
  510. package/ts/src/mock-llm.ts +4 -8
  511. package/ts/src/model.ts +88 -2
  512. package/ts/src/recall/card.ts +106 -0
  513. package/ts/src/recall/evaluator.ts +170 -0
  514. package/ts/src/recall/integration.ts +35 -0
  515. package/ts/src/recall/tick.ts +213 -0
  516. package/ts/src/session-link/plan-it-action.ts +78 -0
  517. package/ts/src/session-link/session-link.ts +275 -0
  518. package/ts/src/share/adapters.ts +93 -0
  519. package/ts/src/share/share-consent.ts +105 -0
  520. package/ts/src/share/share-deck.ts +85 -0
  521. package/ts/src/share/share-token.ts +166 -0
  522. package/ts/src/slot-spec.ts +172 -0
  523. package/ts/src/state-ledger.ts +1166 -0
  524. package/ts/src/subagent-job-id-guard.ts +72 -0
  525. package/ts/src/time-anchor.ts +338 -0
  526. package/ts/src/tool-packet.ts +32 -0
  527. package/ts/src/travel-slots.ts +219 -0
  528. package/ts/src/travel-timeline.ts +83 -0
  529. package/ts/src/turn-deadline.ts +366 -0
  530. package/ts/src/turn-policy.ts +154 -0
  531. package/ts/src/unified.ts +444 -105
  532. package/ts/src/wish-pool.ts +79 -0
  533. package/dist/scripts/session-attach-wait.js +0 -41
@@ -0,0 +1,97 @@
1
+ import { assertPublicArtifactSafe } from './evaluation-contracts.js';
2
+ export const CADENCES = ['pr', 'nightly', 'weekly', 'milestone'];
3
+ export const STOP_SIGNALS = ['source_revision_drift', 'license_unresolved', 'scorer_ceiling_invalid', 'known_bad_no_longer_fails', 'hard_violation', 'matched_regression', 'variance_breach', 'budget_breach'];
4
+ function object(value, label) { if (!value || typeof value !== 'object' || Array.isArray(value))
5
+ throw new Error(`${label} must be an object`); return value; }
6
+ function exact(value, label, keys) { const actual = Object.keys(value).sort(); const expected = [...keys].sort(); if (JSON.stringify(actual) !== JSON.stringify(expected))
7
+ throw new Error(`${label} keys must be exact`); }
8
+ function number(value, label, min = 0) { if (typeof value !== 'number' || !Number.isFinite(value) || value < min)
9
+ throw new Error(`${label} must be finite and non-negative`); return value; }
10
+ function integer(value, label, min = 0) { const n = number(value, label, min); if (!Number.isInteger(n))
11
+ throw new Error(`${label} must be an integer`); return n; }
12
+ function literal(value, label, allowed) { if (typeof value !== 'string' || !allowed.includes(value))
13
+ throw new Error(`${label} is invalid`); return value; }
14
+ function bool(value, label, expected) { if (value !== expected)
15
+ throw new Error(`${label} must be ${expected}`); return expected; }
16
+ export function parseEvaluationCadencePolicy(value) {
17
+ const root = object(value, 'policy');
18
+ exact(root, 'policy', ['schema', 'levels', 'cross_benchmark_window', 'performance_tradeoff_disclosure_threshold', 'round_delivery', 'stop_signals', 'failure_registry_signals', 'public_safety']);
19
+ if (root.schema !== 'gotry_evaluation_cadence_policy_v1')
20
+ throw new Error('policy schema is invalid');
21
+ if (!Array.isArray(root.levels) || root.levels.length !== 4)
22
+ throw new Error('policy levels must be complete');
23
+ for (let index = 0; index < root.levels.length; index += 1)
24
+ if (!Object.hasOwn(root.levels, index))
25
+ throw new Error('policy levels must be dense');
26
+ const levels = root.levels.map((raw, i) => {
27
+ const item = object(raw, `policy.levels[${i}]`);
28
+ exact(item, `policy.levels[${i}]`, ['cadence', 'pass_k', 'max_cost_usd', 'max_wall_minutes', 'max_tool_calls_per_case', 'human_calibration']);
29
+ const cadence = literal(item.cadence, 'cadence', CADENCES);
30
+ if (cadence !== CADENCES[i])
31
+ throw new Error('policy levels must use canonical order');
32
+ const calibration = object(item.human_calibration, 'human_calibration');
33
+ exact(calibration, 'human_calibration', ['required', 'min_samples']);
34
+ const pass_k = integer(item.pass_k, 'pass_k', 1);
35
+ const max_cost_usd = number(item.max_cost_usd, 'max_cost_usd');
36
+ const max_wall_minutes = number(item.max_wall_minutes, 'max_wall_minutes');
37
+ if (item.max_tool_calls_per_case !== 18)
38
+ throw new Error('max_tool_calls_per_case must be 18');
39
+ const required = Boolean(calibration.required);
40
+ if (calibration.required !== required)
41
+ throw new Error('human calibration required must be boolean');
42
+ const min_samples = integer(calibration.min_samples, 'min_samples');
43
+ const expected = [[1, 0, 20, false, 0], [2, 2, 90, false, 0], [3, 10, 360, true, 10], [5, 50, 1440, true, 30]][i];
44
+ if (pass_k !== expected[0] || max_cost_usd !== expected[1] || max_wall_minutes !== expected[2] || required !== expected[3] || min_samples !== expected[4])
45
+ throw new Error('policy level literals are invalid');
46
+ return { cadence, pass_k, max_cost_usd, max_wall_minutes, max_tool_calls_per_case: 18, human_calibration: { required, min_samples } };
47
+ });
48
+ const window = object(root.cross_benchmark_window, 'cross_benchmark_window');
49
+ exact(window, 'cross_benchmark_window', ['min_prs', 'max_prs']);
50
+ if (window.min_prs !== 3 || window.max_prs !== 5)
51
+ throw new Error('cross benchmark window must be 3..5');
52
+ if (root.performance_tradeoff_disclosure_threshold !== 0.2)
53
+ throw new Error('tradeoff threshold must be 0.2');
54
+ const delivery = object(root.round_delivery, 'round_delivery');
55
+ exact(delivery, 'round_delivery', ['exactly_one_gotry_pr', 'exactly_one_discussion_78_comment', 'update_existing_comment']);
56
+ for (const key of Object.keys(delivery))
57
+ bool(delivery[key], `round_delivery.${key}`, true);
58
+ if (!Array.isArray(root.stop_signals) || JSON.stringify(root.stop_signals) !== JSON.stringify(STOP_SIGNALS))
59
+ throw new Error('stop signals must be the complete canonical set');
60
+ if (!Array.isArray(root.failure_registry_signals) || JSON.stringify(root.failure_registry_signals) !== JSON.stringify(STOP_SIGNALS.slice(4)))
61
+ throw new Error('failure registry signals are invalid');
62
+ const publicSafety = object(root.public_safety, 'public_safety');
63
+ exact(publicSafety, 'public_safety', ['artifact_classification', 'contains_third_party_prompt', 'contains_gold', 'contains_oracle', 'contains_private_data']);
64
+ if (publicSafety.artifact_classification !== 'public_safe')
65
+ throw new Error('policy must be public safe');
66
+ for (const key of ['contains_third_party_prompt', 'contains_gold', 'contains_oracle', 'contains_private_data'])
67
+ bool(publicSafety[key], `public_safety.${key}`, false);
68
+ const policy = { schema: root.schema, levels, cross_benchmark_window: { min_prs: 3, max_prs: 5 }, performance_tradeoff_disclosure_threshold: 0.2, round_delivery: { exactly_one_gotry_pr: true, exactly_one_discussion_78_comment: true, update_existing_comment: true }, stop_signals: [...STOP_SIGNALS], failure_registry_signals: [...STOP_SIGNALS.slice(4)], public_safety: { artifact_classification: 'public_safe', contains_third_party_prompt: false, contains_gold: false, contains_oracle: false, contains_private_data: false } };
69
+ assertPublicArtifactSafe(policy, 'evaluation cadence policy');
70
+ return policy;
71
+ }
72
+ export function planEvaluationCadence(policy, input) {
73
+ const inputObject = object(input, 'planner input');
74
+ exact(inputObject, 'planner input', ['cadence', 'signals', 'recent_optimization_prs']);
75
+ if (!CADENCES.includes(input.cadence) || !Array.isArray(input.signals) || !Array.isArray(input.recent_optimization_prs))
76
+ throw new Error('planner input is invalid');
77
+ for (let index = 0; index < input.signals.length; index += 1)
78
+ if (!Object.hasOwn(input.signals, index))
79
+ throw new Error('stop signals must be dense');
80
+ for (let index = 0; index < input.recent_optimization_prs.length; index += 1)
81
+ if (!Object.hasOwn(input.recent_optimization_prs, index))
82
+ throw new Error('recent optimization PR IDs must be dense');
83
+ if (input.recent_optimization_prs.some((id) => !Number.isInteger(id) || id < 1) || new Set(input.recent_optimization_prs).size !== input.recent_optimization_prs.length)
84
+ throw new Error('recent optimization PR IDs must be positive and unique');
85
+ const normalizedPolicy = parseEvaluationCadencePolicy(policy);
86
+ const cadence = input.cadence;
87
+ const signals = input.signals.map((signal) => literal(signal, 'stop signal', STOP_SIGNALS));
88
+ if (new Set(signals).size !== signals.length)
89
+ throw new Error('stop signals must be unique');
90
+ const level = normalizedPolicy.levels.find((item) => item.cadence === cadence);
91
+ if (!level)
92
+ throw new Error('cadence is not configured');
93
+ const failure_registry = signals.some((signal) => normalizedPolicy.failure_registry_signals.includes(signal));
94
+ const decision = { cadence, admission: signals.length === 0, failure_registry, stop_signals: signals, launches_external_runs: false, pass_k: level.pass_k, max_cost_usd: level.max_cost_usd, max_wall_minutes: level.max_wall_minutes, max_tool_calls_per_case: 18, human_calibration: level.human_calibration, cross_benchmark_window: { min_prs: 3, max_prs: 5 }, performance_tradeoff_disclosure_threshold: 0.2, delivery: normalizedPolicy.round_delivery, cross_benchmark_synthesis: { required: input.recent_optimization_prs.length >= 3, overdue: input.recent_optimization_prs.length > 5 } };
95
+ assertPublicArtifactSafe(decision, 'evaluation cadence decision');
96
+ return decision;
97
+ }
@@ -0,0 +1,283 @@
1
+ import { createHash } from 'node:crypto';
2
+ export const BENCHMARK_IDS = ['trek', 'travelplanner', 'chinatravel', 'travelbench', 'tau2', 'locomo', 'bfcl'];
3
+ export const FAILURE_CATEGORIES = ['schema_or_format', 'grounding_or_provenance', 'constraint_or_feasibility', 'time_or_location_continuity', 'cost_or_cardinality', 'tool_selection_or_arguments', 'policy_or_write_safety', 'preference_elicitation', 'memory_retrieval_or_temporal_reasoning', 'reliability_cost_or_latency'];
4
+ function obj(value, label) { if (!value || typeof value !== 'object' || Array.isArray(value))
5
+ throw new Error(`${label} must be an object`); return value; }
6
+ function exact(value, label, keys) { const unknown = Object.keys(value).filter(key => !keys.includes(key)); const missing = keys.filter(key => !(key in value)); if (unknown.length)
7
+ throw new Error(`${label} contains undeclared fields: ${unknown.join(',')}`); if (missing.length)
8
+ throw new Error(`${label} missing fields: ${missing.join(',')}`); }
9
+ function text(value, label) { if (typeof value !== 'string' || value.length === 0)
10
+ throw new Error(`${label} must be non-empty text`); return value; }
11
+ function id(value, label) { const out = text(value, label); if (!/^[a-z0-9][a-z0-9:._-]+$/.test(out))
12
+ throw new Error(`${label} must be a stable identifier`); return out; }
13
+ function lit(value, label, values) { const out = text(value, label); if (!values.includes(out))
14
+ throw new Error(`${label} invalid literal`); return out; }
15
+ function boolean(value, label) { if (typeof value !== 'boolean')
16
+ throw new Error(`${label} must be boolean`); return value; }
17
+ function finite(value, label, min = 0) { if (typeof value !== 'number' || !Number.isFinite(value) || value < min)
18
+ throw new Error(`${label} must be a finite number >= ${min}`); return value; }
19
+ function integer(value, label, min = 0) { const out = finite(value, label, min); if (!Number.isInteger(out))
20
+ throw new Error(`${label} must be an integer`); return out; }
21
+ function strings(value, label, empty = false) { if (!Array.isArray(value) || (!empty && value.length === 0))
22
+ throw new Error(`${label} must be an array`); const out = value.map((item, index) => text(item, `${label}[${index}]`)); if (new Set(out).size !== out.length)
23
+ throw new Error(`${label} must be unique`); return out; }
24
+ function digest(value, label) { const out = text(value, label); if (!/^[0-9a-f]{64}$/.test(out))
25
+ throw new Error(`${label} must be lowercase SHA-256`); return out; }
26
+ function commit(value, label) { const out = text(value, label); if (!/^[0-9a-f]{40}$/.test(out))
27
+ throw new Error(`${label} must be a lowercase 40-character Git commit`); return out; }
28
+ function url(value, label) { const out = text(value, label); let parsed; try {
29
+ parsed = new URL(out);
30
+ }
31
+ catch {
32
+ throw new Error(`${label} must be a valid URL`);
33
+ } ; if (parsed.protocol !== 'https:')
34
+ throw new Error(`${label} must use https`); if (parsed.username || parsed.password)
35
+ throw new Error(`${label} must not contain credentials`); return out; }
36
+ function instant(value, label) { const out = text(value, label); const date = new Date(out); if (!Number.isFinite(date.valueOf()) || date.toISOString() !== out)
37
+ throw new Error(`${label} must be canonical ISO UTC with milliseconds`); return out; }
38
+ function zone(value, label) { const out = text(value, label); if (out === 'UTC')
39
+ return out; try {
40
+ new Intl.DateTimeFormat('en', { timeZone: out }).format(new Date(0));
41
+ }
42
+ catch {
43
+ throw new Error(`${label} must be UTC or an IANA timezone`);
44
+ } ; if (!out.includes('/'))
45
+ throw new Error(`${label} must be UTC or an IANA timezone`); return out; }
46
+ function revision(value, label) { const root = obj(value, label); exact(root, label, ['kind', 'value']); const kind = lit(root.kind, `${label}.kind`, ['git_commit', 'content_sha256', 'not_separately_declared']); if (kind === 'not_separately_declared') {
47
+ if (root.value !== null)
48
+ throw new Error(`${label}.value must be null`);
49
+ return { kind, value: null };
50
+ } ; return { kind, value: kind === 'git_commit' ? commit(root.value, `${label}.value`) : digest(root.value, `${label}.value`) }; }
51
+ function pin(value, label) { const root = obj(value, label); exact(root, label, ['url', 'revision', 'source_scope']); return { url: url(root.url, `${label}.url`), revision: revision(root.revision, `${label}.revision`), source_scope: text(root.source_scope, `${label}.source_scope`) }; }
52
+ function licenseDetermination(value, label) { const root = obj(value, label); exact(root, label, ['value', 'determination', 'source_url']); const determination = lit(root.determination, `${label}.determination`, ['declared', 'not_separately_declared']); const resolved = text(root.value, `${label}.value`); if (determination === 'not_separately_declared' && resolved !== 'not_separately_declared')
53
+ throw new Error(`${label}.value must be not_separately_declared`); return { value: resolved, determination, source_url: url(root.source_url, `${label}.source_url`) }; }
54
+ export function stableEvaluationJson(value) { const sort = (item) => Array.isArray(item) ? item.map(sort) : item && typeof item === 'object' ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b)).map(([key, child]) => [key, sort(child)])) : item; return `${JSON.stringify(sort(value), null, 2)}\n`; }
55
+ export function evaluationFingerprint(value) { return createHash('sha256').update(stableEvaluationJson(value)).digest('hex'); }
56
+ const sensitiveKeys = new Set(['apikey', 'accesstoken', 'refreshtoken', 'authorization', 'password', 'clientsecret', 'credentials', 'cookie', 'rawprompt', 'goldanswer', 'oraclepayload', 'credential', 'rawanswer', 'privatepayload', 'secretpayload', 'trajectorypayload']);
57
+ export function assertPublicArtifactSafe(value, label = 'artifact') {
58
+ const walk = (item, path) => {
59
+ if (Array.isArray(item))
60
+ return item.forEach((child, index) => walk(child, `${path}[${index}]`));
61
+ if (typeof item === 'string') {
62
+ const withoutHttpsUrls = item.replace(/https:\/\/[^\s]+/g, '');
63
+ const highConfidenceSecret = /Bearer\s+[A-Za-z0-9._~-]{24,}|\bsk-[A-Za-z0-9_-]{20,}|\bgh[pousr]_[A-Za-z0-9_]{20,}|\bAKIA[0-9A-Z]{16}\b/;
64
+ if (/(?:^|[^A-Za-z0-9])(?:\/|~\/)|[A-Za-z]:[\\/]|file:\/\//.test(withoutHttpsUrls) || highConfidenceSecret.test(item))
65
+ throw new Error(`${path} contains an absolute path or secret`);
66
+ return;
67
+ }
68
+ if (!item || typeof item !== 'object')
69
+ return;
70
+ for (const [key, child] of Object.entries(item)) {
71
+ if (sensitiveKeys.has(key.replace(/[^a-z0-9]/gi, '').toLowerCase()) && child !== '' && child !== null)
72
+ throw new Error(`${path}.${key} contains credentials or raw sensitive payload`);
73
+ walk(child, `${path}.${key}`);
74
+ }
75
+ };
76
+ walk(value, label);
77
+ }
78
+ function registryEntry(value, label) {
79
+ const root = obj(value, label);
80
+ exact(root, label, ['schema_version', 'benchmark_id', 'provenance', 'license', 'task_scopes', 'native_metrics', 'source_fence', 'countability_default']);
81
+ const provenance = obj(root.provenance, `${label}.provenance`);
82
+ exact(provenance, `${label}.provenance`, ['official_entry', 'data', 'evaluator']);
83
+ const license = obj(root.license, `${label}.license`);
84
+ exact(license, `${label}.license`, ['upstream_rights', 'repo_storage_policy']);
85
+ const rights = obj(license.upstream_rights, `${label}.license.upstream_rights`);
86
+ exact(rights, `${label}.license.upstream_rights`, ['code', 'data', 'evaluator']);
87
+ const metrics = obj(root.native_metrics, `${label}.native_metrics`);
88
+ exact(metrics, `${label}.native_metrics`, ['status', 'values']);
89
+ if (!Array.isArray(metrics.values))
90
+ throw new Error(`${label}.native_metrics.values must be an array`);
91
+ const status = lit(metrics.status, `${label}.native_metrics.status`, ['declared', 'not_separately_declared']);
92
+ const values = metrics.values.map((raw, index) => { const metric = obj(raw, `${label}.metric[${index}]`); exact(metric, `${label}.metric[${index}]`, ['receipt_key', 'upstream_label', 'scope', 'source_url']); return { receipt_key: id(metric.receipt_key, `${label}.metric.receipt_key`), upstream_label: text(metric.upstream_label, `${label}.metric.upstream_label`), scope: text(metric.scope, `${label}.metric.scope`), source_url: url(metric.source_url, `${label}.metric.source_url`) }; });
93
+ if (status === 'declared' && values.length === 0)
94
+ throw new Error(`${label} declared metrics must be non-empty`);
95
+ if (status === 'not_separately_declared' && values.length !== 0)
96
+ throw new Error(`${label} undeclared metrics must be empty`);
97
+ const fence = obj(root.source_fence, `${label}.source_fence`);
98
+ exact(fence, `${label}.source_fence`, ['solver_allowed_field_classes', 'solver_forbidden_field_classes']);
99
+ return { schema_version: lit(root.schema_version, `${label}.schema_version`, ['gotry_benchmark_registry_entry_v0']), benchmark_id: lit(root.benchmark_id, `${label}.benchmark_id`, BENCHMARK_IDS), provenance: { official_entry: pin(provenance.official_entry, `${label}.official_entry`), data: pin(provenance.data, `${label}.data`), evaluator: pin(provenance.evaluator, `${label}.evaluator`) }, license: { upstream_rights: { code: licenseDetermination(rights.code, `${label}.rights.code`), data: licenseDetermination(rights.data, `${label}.rights.data`), evaluator: licenseDetermination(rights.evaluator, `${label}.rights.evaluator`) }, repo_storage_policy: lit(license.repo_storage_policy, `${label}.storage`, ['metadata_only_no_upstream_payload']) }, task_scopes: strings(root.task_scopes, `${label}.task_scopes`), native_metrics: status === 'declared' ? { status, values } : { status, values: [] }, source_fence: { solver_allowed_field_classes: strings(fence.solver_allowed_field_classes, `${label}.allowed`), solver_forbidden_field_classes: strings(fence.solver_forbidden_field_classes, `${label}.forbidden`) }, countability_default: lit(root.countability_default, `${label}.countability_default`, ['countable_if_qualified', 'diagnostic_only']) };
100
+ }
101
+ export function parseBenchmarkRegistry(value) { if (!Array.isArray(value) || value.length !== 7)
102
+ throw new Error('registry must contain exactly seven entries'); const out = value.map((item, index) => registryEntry(item, `registry[${index}]`)); if (out.some((item, index) => item.benchmark_id !== BENCHMARK_IDS[index]))
103
+ throw new Error('registry must use canonical unique order'); return out; }
104
+ export function parseEvalCase(value) {
105
+ const root = obj(value, 'case');
106
+ exact(root, 'case', ['schema_version', 'case_id', 'benchmark_id', 'input_ref', 'isolation', 'clock', 'allowed_effects', 'forbidden_effects', 'budget', 'scorer_revision', 'public_safety']);
107
+ const input = obj(root.input_ref, 'case.input_ref');
108
+ exact(input, 'case.input_ref', ['kind', 'revision', 'digest_sha256']);
109
+ const isolation = obj(root.isolation, 'case.isolation');
110
+ exact(isolation, 'case.isolation', ['state_root', 'network', 'writes']);
111
+ const clock = obj(root.clock, 'case.clock');
112
+ exact(clock, 'case.clock', ['now', 'timezone']);
113
+ const budget = obj(root.budget, 'case.budget');
114
+ exact(budget, 'case.budget', ['max_seconds', 'max_cost_usd', 'max_tool_calls', 'max_turns']);
115
+ const safety = obj(root.public_safety, 'case.public_safety');
116
+ exact(safety, 'case.public_safety', ['contains_third_party_prompt', 'contains_gold', 'contains_oracle', 'contains_private_data']);
117
+ for (const [key, flag] of Object.entries(safety))
118
+ if (boolean(flag, `case.public_safety.${key}`) !== false)
119
+ throw new Error(`case.public_safety.${key} must be false`);
120
+ const out = { schema_version: lit(root.schema_version, 'case.schema_version', ['gotry_eval_case_v0']), case_id: id(root.case_id, 'case.case_id'), benchmark_id: lit(root.benchmark_id, 'case.benchmark_id', BENCHMARK_IDS), input_ref: { kind: lit(input.kind, 'case.input_ref.kind', ['gotry_owned_synthetic', 'external_opaque_reference']), revision: revision(input.revision, 'case.input_ref.revision'), digest_sha256: digest(input.digest_sha256, 'case.input_ref.digest_sha256') }, isolation: { state_root: lit(isolation.state_root, 'case.state_root', ['ephemeral']), network: lit(isolation.network, 'case.network', ['denied', 'benchmark_declared']), writes: lit(isolation.writes, 'case.writes', ['forbidden']) }, clock: { now: instant(clock.now, 'case.clock.now'), timezone: zone(clock.timezone, 'case.clock.timezone') }, allowed_effects: strings(root.allowed_effects, 'case.allowed_effects', true), forbidden_effects: strings(root.forbidden_effects, 'case.forbidden_effects'), budget: { max_seconds: finite(budget.max_seconds, 'case.max_seconds'), max_cost_usd: finite(budget.max_cost_usd, 'case.max_cost_usd'), max_tool_calls: integer(budget.max_tool_calls, 'case.max_tool_calls'), max_turns: integer(budget.max_turns, 'case.max_turns') }, scorer_revision: revision(root.scorer_revision, 'case.scorer_revision'), public_safety: { contains_third_party_prompt: false, contains_gold: false, contains_oracle: false, contains_private_data: false } };
121
+ assertPublicArtifactSafe(out, 'case');
122
+ return out;
123
+ }
124
+ function optionalDigest(value, label) { return value === null ? null : digest(value, label); }
125
+ // The only schema-free object maps are native_metrics and evidence counts. Their leaves are numeric;
126
+ // native_metrics keys close exactly to registry receipt_key values in parseEvaluationFoundation.
127
+ function numberMap(value, label, integers = false) { const root = obj(value, label); return Object.fromEntries(Object.entries(root).map(([key, item]) => [id(key, `${label}.key`), integers ? integer(item, `${label}.${key}`) : finite(item, `${label}.${key}`, Number.NEGATIVE_INFINITY)])); }
128
+ export function parseEvalRunReceipt(value) {
129
+ const root = obj(value, 'run');
130
+ exact(root, 'run', ['schema_version', 'run_id', 'benchmark_id', 'case_id', 'evidence_kind', 'pairing', 'status', 'started_at', 'finished_at', 'gotry_sha', 'model', 'controls', 'qualification', 'experiment', 'native_metrics', 'guardrails', 'evidence_summary']);
131
+ const model = obj(root.model, 'run.model');
132
+ exact(model, 'run.model', ['provider', 'model']);
133
+ const controls = obj(root.controls, 'run.controls');
134
+ const controlKeys = ['case_set_sha256', 'protocol_control_sha256', 'model_parameters_sha256', 'scorer_sha256', 'tool_snapshot_sha256', 'source_fence_sha256', 'integrity_sha256', 'official_evaluator_sha256'];
135
+ exact(controls, 'run.controls', controlKeys);
136
+ const qualification = obj(root.qualification, 'run.qualification');
137
+ exact(qualification, 'run.qualification', ['official_result', 'source_fence_passed', 'integrity_passed', 'evidence_receipts']);
138
+ const receipts = obj(qualification.evidence_receipts, 'run.qualification.evidence_receipts');
139
+ exact(receipts, 'run.qualification.evidence_receipts', ['official_evaluator_output_sha256', 'source_fence_audit_sha256', 'integrity_audit_sha256']);
140
+ const experiment = obj(root.experiment, 'run.experiment');
141
+ exact(experiment, 'run.experiment', ['changed_variables', 'candidate_sha256']);
142
+ const guard = obj(root.guardrails, 'run.guardrails');
143
+ exact(guard, 'run.guardrails', ['hard_violation_count', 'forbidden_leakage_hits', 'latency_ms', 'cost_usd', 'tool_calls', 'turns']);
144
+ const summary = obj(root.evidence_summary, 'run.evidence_summary');
145
+ exact(summary, 'run.evidence_summary', ['artifact_classification', 'sha256', 'counts', 'reason_codes', 'fixture_only', 'statement']);
146
+ let pairing = null;
147
+ if (root.pairing !== null) {
148
+ const item = obj(root.pairing, 'run.pairing');
149
+ exact(item, 'run.pairing', ['pair_id', 'role', 'counterpart_run_id']);
150
+ pairing = { pair_id: id(item.pair_id, 'run.pair_id'), role: lit(item.role, 'run.role', ['baseline', 'treatment']), counterpart_run_id: id(item.counterpart_run_id, 'run.counterpart') };
151
+ }
152
+ const evidence_kind = lit(root.evidence_kind, 'run.evidence_kind', ['synthetic_fixture', 'observed_external']);
153
+ const status = lit(root.status, 'run.status', ['running', 'succeeded', 'failed', 'blocked']);
154
+ const finished_at = root.finished_at === null ? null : instant(root.finished_at, 'run.finished_at');
155
+ if ((status === 'running') !== (finished_at === null))
156
+ throw new Error('run.finished_at must be null only while running');
157
+ const out = { schema_version: lit(root.schema_version, 'run.schema_version', ['gotry_eval_run_receipt_v0']), run_id: id(root.run_id, 'run.run_id'), benchmark_id: lit(root.benchmark_id, 'run.benchmark_id', BENCHMARK_IDS), case_id: id(root.case_id, 'run.case_id'), evidence_kind, pairing, status, started_at: instant(root.started_at, 'run.started_at'), finished_at, gotry_sha: commit(root.gotry_sha, 'run.gotry_sha'), model: { provider: text(model.provider, 'run.provider'), model: text(model.model, 'run.model') }, controls: Object.fromEntries(controlKeys.map(key => [key, digest(controls[key], `run.controls.${key}`)])), qualification: { official_result: boolean(qualification.official_result, 'run.official_result'), source_fence_passed: boolean(qualification.source_fence_passed, 'run.source_fence_passed'), integrity_passed: boolean(qualification.integrity_passed, 'run.integrity_passed'), evidence_receipts: { official_evaluator_output_sha256: optionalDigest(receipts.official_evaluator_output_sha256, 'run.evaluator_receipt'), source_fence_audit_sha256: optionalDigest(receipts.source_fence_audit_sha256, 'run.fence_receipt'), integrity_audit_sha256: optionalDigest(receipts.integrity_audit_sha256, 'run.integrity_receipt') } }, experiment: { changed_variables: strings(experiment.changed_variables, 'run.changed_variables', true), candidate_sha256: digest(experiment.candidate_sha256, 'run.candidate') }, native_metrics: numberMap(root.native_metrics, 'run.native_metrics'), guardrails: { hard_violation_count: integer(guard.hard_violation_count, 'run.hard'), forbidden_leakage_hits: integer(guard.forbidden_leakage_hits, 'run.leakage'), latency_ms: finite(guard.latency_ms, 'run.latency'), cost_usd: finite(guard.cost_usd, 'run.cost'), tool_calls: integer(guard.tool_calls, 'run.tools'), turns: integer(guard.turns, 'run.turns') }, evidence_summary: { artifact_classification: lit(summary.artifact_classification, 'run.classification', ['public_safe']), sha256: strings(summary.sha256, 'run.sha256', true).map((item, index) => digest(item, `run.sha256[${index}]`)), counts: numberMap(summary.counts, 'run.counts', true), reason_codes: strings(summary.reason_codes, 'run.reason_codes', true), fixture_only: boolean(summary.fixture_only, 'run.fixture_only'), statement: text(summary.statement, 'run.statement') } };
158
+ if (out.finished_at !== null && new Date(out.finished_at).valueOf() < new Date(out.started_at).valueOf())
159
+ throw new Error('run.finished_at must not precede started_at');
160
+ if (evidence_kind === 'synthetic_fixture' && (pairing !== null || out.qualification.official_result || out.qualification.source_fence_passed || out.qualification.integrity_passed || Object.values(out.qualification.evidence_receipts).some(Boolean) || !out.evidence_summary.fixture_only))
161
+ throw new Error('synthetic fixture must be unmatched, unqualified, receipt-free, and fixture-only');
162
+ if (evidence_kind === 'observed_external' && out.evidence_summary.fixture_only)
163
+ throw new Error('observed_external receipt must set fixture_only=false');
164
+ assertPublicArtifactSafe(out, 'run');
165
+ return out;
166
+ }
167
+ export function parseEvalFailureCluster(value) { const root = obj(value, 'failure'); exact(root, 'failure', ['schema_version', 'cluster_id', 'category', 'severity', 'benchmark_ids', 'case_ids', 'run_ids', 'reproduction', 'falsifiable_hypothesis', 'gotry_regression_id', 'suggested_surface', 'state']); const reproduction = obj(root.reproduction, 'failure.reproduction'); exact(reproduction, 'failure.reproduction', ['condition', 'minimum_repetitions', 'observed_repetitions']); const out = { schema_version: lit(root.schema_version, 'failure.schema_version', ['gotry_eval_failure_cluster_v0']), cluster_id: id(root.cluster_id, 'failure.cluster_id'), category: lit(root.category, 'failure.category', FAILURE_CATEGORIES), severity: lit(root.severity, 'failure.severity', ['P0', 'P1', 'P2', 'P3']), benchmark_ids: strings(root.benchmark_ids, 'failure.benchmark_ids').map(item => lit(item, 'failure.benchmark', BENCHMARK_IDS)), case_ids: strings(root.case_ids, 'failure.case_ids'), run_ids: strings(root.run_ids, 'failure.run_ids'), reproduction: { condition: text(reproduction.condition, 'failure.condition'), minimum_repetitions: integer(reproduction.minimum_repetitions, 'failure.minimum', 1), observed_repetitions: integer(reproduction.observed_repetitions, 'failure.observed') }, falsifiable_hypothesis: text(root.falsifiable_hypothesis, 'failure.hypothesis'), gotry_regression_id: id(root.gotry_regression_id, 'failure.regression'), suggested_surface: lit(root.suggested_surface, 'failure.surface', ['agent', 'tool_policy', 'deterministic', 'evaluation']), state: lit(root.state, 'failure.state', ['observed', 'confirmed', 'resolved', 'rejected']) }; if (out.state === 'confirmed' && out.reproduction.observed_repetitions < out.reproduction.minimum_repetitions)
168
+ throw new Error('confirmed failure lacks repetitions'); assertPublicArtifactSafe(out, 'failure'); return out; }
169
+ export function parseEvaluationFoundation(value) {
170
+ const root = obj(value, 'foundation');
171
+ exact(root, 'foundation', ['registry', 'cases', 'run_receipts', 'failure_clusters']);
172
+ const registry = parseBenchmarkRegistry(root.registry);
173
+ if (!Array.isArray(root.cases) || !Array.isArray(root.run_receipts) || !Array.isArray(root.failure_clusters))
174
+ throw new Error('foundation collections must be arrays');
175
+ const cases = root.cases.map(parseEvalCase), runs = root.run_receipts.map(parseEvalRunReceipt), failures = root.failure_clusters.map(parseEvalFailureCluster);
176
+ const unique = (values, label) => { if (new Set(values).size !== values.length)
177
+ throw new Error(`${label} ids must be unique`); };
178
+ unique(cases.map(item => item.case_id), 'case');
179
+ unique(runs.map(item => item.run_id), 'run');
180
+ unique(failures.map(item => item.cluster_id), 'failure');
181
+ const caseById = new Map(cases.map(item => [item.case_id, item])), runById = new Map(runs.map(item => [item.run_id, item])), registryById = new Map(registry.map(item => [item.benchmark_id, item]));
182
+ for (const run of runs) {
183
+ const linked = caseById.get(run.case_id), entry = registryById.get(run.benchmark_id);
184
+ if (!linked || linked.benchmark_id !== run.benchmark_id || !entry)
185
+ throw new Error(`run ${run.run_id} must close to case and registry`);
186
+ const metricKeys = Object.keys(run.native_metrics).sort(), declared = entry.native_metrics.values.map(metric => metric.receipt_key).sort();
187
+ if (JSON.stringify(metricKeys) !== JSON.stringify(declared))
188
+ throw new Error(`run ${run.run_id} metric keys must equal registry receipt keys`);
189
+ }
190
+ for (const failure of failures) {
191
+ const linkedCases = failure.case_ids.map(key => caseById.get(key)), linkedRuns = failure.run_ids.map(key => runById.get(key));
192
+ if (linkedCases.some(item => !item) || linkedRuns.some(item => !item))
193
+ throw new Error(`failure ${failure.cluster_id} has unclosed links`);
194
+ const actual = new Set([...linkedCases, ...linkedRuns].map(item => item.benchmark_id));
195
+ if (actual.size !== failure.benchmark_ids.length || failure.benchmark_ids.some(key => !actual.has(key)))
196
+ throw new Error(`failure ${failure.cluster_id} benchmark closure must equal linked case and run benchmarks`);
197
+ }
198
+ return { registry, cases, run_receipts: runs, failure_clusters: failures };
199
+ }
200
+ function runBinding(run) { const { evidence_receipts: _receipts, ...qualification } = run.qualification; return evaluationFingerprint({ ...run, qualification }); }
201
+ function resolveArtifact(resolver, run, kind, evalCase) { const expected = kind === 'official_evaluator' ? run.qualification.evidence_receipts.official_evaluator_output_sha256 : kind === 'source_fence_audit' ? run.qualification.evidence_receipts.source_fence_audit_sha256 : run.qualification.evidence_receipts.integrity_audit_sha256; if (!expected)
202
+ throw new Error(`pair ${run.run_id} lacks qualification evidence receipts`); const value = obj(resolver.resolve(expected), `${kind} artifact`); const common = ['schema_version', 'artifact_kind', 'run_id', 'benchmark_id', 'case_id', 'run_binding_sha256']; const specific = kind === 'official_evaluator' ? ['evaluator_sha256', 'native_metrics_sha256', 'native_metrics', 'official_result'] : kind === 'source_fence_audit' ? ['source_fence_sha256', 'input_digest_sha256', 'source_fence_passed', 'forbidden_field_hits'] : ['integrity_sha256', 'candidate_sha256', 'integrity_passed']; exact(value, `${kind} artifact`, [...common, ...specific]); lit(value.schema_version, `${kind}.schema_version`, ['gotry_eval_evidence_artifact_v0']); if (value.artifact_kind !== kind)
203
+ throw new Error(`${kind} artifact kind mismatch`); if (typeof value.run_id !== 'string' || typeof value.benchmark_id !== 'string' || typeof value.case_id !== 'string' || typeof value.run_binding_sha256 !== 'string')
204
+ throw new Error(`${kind} artifact schema types mismatch`); assertPublicArtifactSafe(value, ` artifact`); if (kind === 'official_evaluator' && (typeof value.official_result !== 'boolean' || typeof value.native_metrics_sha256 !== 'string'))
205
+ throw new Error(`${kind} artifact schema types mismatch`); if (kind === 'source_fence_audit' && (typeof value.source_fence_passed !== 'boolean' || typeof value.forbidden_field_hits !== 'number' || !Number.isInteger(value.forbidden_field_hits)))
206
+ throw new Error(`${kind} artifact schema types mismatch`); if (kind === 'integrity_audit' && typeof value.integrity_passed !== 'boolean')
207
+ throw new Error(`${kind} artifact schema types mismatch`); if (evaluationFingerprint(value) !== expected)
208
+ throw new Error(`pair ${run.run_id} ${kind} artifact fingerprint mismatch`); if (value.run_id !== run.run_id || value.benchmark_id !== run.benchmark_id || value.case_id !== run.case_id || value.run_binding_sha256 !== runBinding(run))
209
+ throw new Error(`pair ${run.run_id} ${kind} artifact binding mismatch`); if (kind === 'official_evaluator' && (value.evaluator_sha256 !== run.controls.official_evaluator_sha256 || value.native_metrics_sha256 !== evaluationFingerprint(run.native_metrics) || value.official_result !== true || JSON.stringify(value.native_metrics) !== JSON.stringify(run.native_metrics)))
210
+ throw new Error(`pair ${run.run_id} evaluator artifact mismatch`); if (kind === 'source_fence_audit' && (value.source_fence_sha256 !== run.controls.source_fence_sha256 || value.source_fence_passed !== true || value.forbidden_field_hits !== 0 || (evalCase !== undefined && value.input_digest_sha256 !== evalCase.input_ref.digest_sha256)))
211
+ throw new Error(`pair ${run.run_id} source-fence artifact mismatch`); if (kind === 'integrity_audit' && (value.integrity_sha256 !== run.controls.integrity_sha256 || value.candidate_sha256 !== run.experiment.candidate_sha256 || value.integrity_passed !== true))
212
+ throw new Error(`pair ${run.run_id} integrity artifact mismatch`); return value; }
213
+ export function deriveMatchedPairs(foundation, resolver) {
214
+ const groups = new Map();
215
+ for (const run of foundation.run_receipts)
216
+ if (run.pairing)
217
+ groups.set(run.pairing.pair_id, [...(groups.get(run.pairing.pair_id) ?? []), run]);
218
+ const registry = new Map(foundation.registry.map(item => [item.benchmark_id, item])), cases = new Map(foundation.cases.map(item => [item.case_id, item]));
219
+ return [...groups.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([pairId, members]) => {
220
+ if (members.length !== 2)
221
+ throw new Error(`pair ${pairId} must contain exactly two receipts`);
222
+ const baseline = members.find(item => item.pairing?.role === 'baseline'), treatment = members.find(item => item.pairing?.role === 'treatment');
223
+ if (!baseline || !treatment)
224
+ throw new Error(`pair ${pairId} must contain opposite baseline and treatment roles`);
225
+ if (baseline.pairing.counterpart_run_id !== treatment.run_id || treatment.pairing.counterpart_run_id !== baseline.run_id)
226
+ throw new Error(`pair ${pairId} counterpart references must be reciprocal`);
227
+ if (baseline.benchmark_id !== treatment.benchmark_id || baseline.case_id !== treatment.case_id)
228
+ throw new Error(`pair ${pairId} must share benchmark and case`);
229
+ const entry = registry.get(baseline.benchmark_id), evalCase = cases.get(baseline.case_id);
230
+ if (entry.countability_default !== 'countable_if_qualified')
231
+ throw new Error(`pair ${pairId} benchmark is diagnostic only`);
232
+ if (evalCase.input_ref.kind !== 'external_opaque_reference')
233
+ throw new Error(`pair ${pairId} requires an external opaque case reference`);
234
+ if ([baseline, treatment].some(run => run.evidence_kind !== 'observed_external'))
235
+ throw new Error(`pair ${pairId} requires observed_external evidence`);
236
+ if (baseline.status !== 'succeeded' || treatment.status !== 'succeeded')
237
+ throw new Error(`pair ${pairId} requires succeeded terminal receipts`);
238
+ if (baseline.model.provider !== treatment.model.provider || baseline.model.model !== treatment.model.model)
239
+ throw new Error(`pair ${pairId} model identity must match`);
240
+ for (const key of ['case_set_sha256', 'protocol_control_sha256', 'model_parameters_sha256', 'scorer_sha256', 'tool_snapshot_sha256', 'source_fence_sha256', 'integrity_sha256', 'official_evaluator_sha256'])
241
+ if (baseline.controls[key] !== treatment.controls[key])
242
+ throw new Error(`pair ${pairId} control mismatch: ${key}`);
243
+ if (baseline.controls.scorer_sha256 !== evaluationFingerprint(evalCase.scorer_revision))
244
+ throw new Error(`pair ${pairId} scorer fingerprint does not close`);
245
+ if (baseline.controls.case_set_sha256 !== evaluationFingerprint(foundation.cases.filter(item => item.benchmark_id === baseline.benchmark_id)))
246
+ throw new Error(`pair ${pairId} case-set fingerprint does not close`);
247
+ if (baseline.controls.source_fence_sha256 !== evaluationFingerprint(entry.source_fence))
248
+ throw new Error(`pair ${pairId} source-fence fingerprint does not close`);
249
+ if (baseline.controls.official_evaluator_sha256 !== evaluationFingerprint(entry.provenance.evaluator))
250
+ throw new Error(`pair ${pairId} evaluator fingerprint does not close`);
251
+ if (baseline.experiment.changed_variables.length !== 0 || JSON.stringify(treatment.experiment.changed_variables) !== JSON.stringify(['gotry_sha']))
252
+ throw new Error(`pair ${pairId} treatment variable must be exactly gotry_sha`);
253
+ if (baseline.gotry_sha === treatment.gotry_sha)
254
+ throw new Error(`pair ${pairId} baseline and treatment gotry_sha must differ`);
255
+ if (baseline.guardrails.hard_violation_count !== 0 || treatment.guardrails.hard_violation_count !== 0 || baseline.guardrails.forbidden_leakage_hits !== 0 || treatment.guardrails.forbidden_leakage_hits !== 0)
256
+ throw new Error(`pair ${pairId} hard violation or leakage`);
257
+ for (const run of [baseline, treatment])
258
+ if (run.experiment.candidate_sha256 !== evaluationFingerprint({ treatment_variable: 'gotry_sha', gotry_sha: run.gotry_sha }))
259
+ throw new Error(`pair ${pairId} candidate fingerprint does not close to gotry_sha`);
260
+ for (const run of [baseline, treatment]) {
261
+ const receipts = Object.values(run.qualification.evidence_receipts);
262
+ if (!run.qualification.official_result || !run.qualification.source_fence_passed || !run.qualification.integrity_passed || receipts.some(item => item === null))
263
+ throw new Error(`pair ${pairId} lacks qualification evidence receipts`);
264
+ const evaluator = resolveArtifact(resolver, run, 'official_evaluator'), fence = resolveArtifact(resolver, run, 'source_fence_audit', evalCase), integrity = resolveArtifact(resolver, run, 'integrity_audit');
265
+ }
266
+ return { schema_version: 'gotry_eval_matched_pair_derived_v0', pair_id: pairId, benchmark_id: baseline.benchmark_id, case_id: baseline.case_id, baseline_run_id: baseline.run_id, treatment_run_id: treatment.run_id, treatment_variable: 'gotry_sha', matched_pair_countable: true };
267
+ });
268
+ }
269
+ export function parseMutationVectors(value) { if (!Array.isArray(value))
270
+ throw new Error('mutation vectors must be an array'); return value.map((raw, index) => { const root = obj(raw, `mutation[${index}]`), kind = lit(root.value_kind, 'mutation.value_kind', ['literal', 'synthetic_absolute_path', 'nan', 'duplicate_treatment_receipt']), keys = kind === 'literal' ? ['id', 'foundation_kind', 'target', 'operation', 'path', 'value_kind', 'value', 'expected_error'] : ['id', 'foundation_kind', 'target', 'operation', 'path', 'value_kind', 'expected_error']; exact(root, `mutation[${index}]`, keys); return { id: id(root.id, 'mutation.id'), foundation_kind: lit(root.foundation_kind, 'mutation.foundation_kind', ['diagnostic_repository', 'countable_test_only']), target: lit(root.target, 'mutation.target', ['registry', 'case', 'run', 'failure', 'foundation']), operation: lit(root.operation, 'mutation.operation', ['replace', 'remove', 'append']), path: text(root.path, 'mutation.path'), value_kind: kind, ...(kind === 'literal' ? { value: root.value } : {}), expected_error: text(root.expected_error, 'mutation.expected_error') }; }); }
271
+ export function applyMutationVector(foundation, vector) { const cloned = JSON.parse(JSON.stringify(foundation)); const selected = vector.target === 'foundation' ? cloned : vector.target === 'registry' ? cloned.registry : vector.target === 'case' ? cloned.cases[0] : vector.target === 'run' ? cloned.run_receipts[0] : cloned.failure_clusters[0]; let value = vector.value; if (vector.value_kind === 'synthetic_absolute_path')
272
+ value = ['', 'Users', 'fixture', 'private.json'].join('/'); if (vector.value_kind === 'nan')
273
+ value = Number.NaN; if (vector.value_kind === 'duplicate_treatment_receipt') {
274
+ const run = structuredClone(cloned.run_receipts[1]);
275
+ run.run_id = 'run:trek:treatment-duplicate';
276
+ value = run;
277
+ } const parts = vector.path.split('.').filter(Boolean); let parent = selected; for (const part of parts.slice(0, -1))
278
+ parent = parent[part]; const leaf = parts.at(-1); if (vector.operation === 'remove')
279
+ Array.isArray(parent) ? parent.splice(Number(leaf), 1) : delete parent[leaf];
280
+ else if (vector.operation === 'append')
281
+ parent[leaf].push(value);
282
+ else
283
+ parent[leaf] = value; return selected; }
@@ -0,0 +1,54 @@
1
+ import { FLIGHT_PACK_VERSION } from './flight-pack-contract.js';
2
+ import { isKnownZoneLoose } from './tz-resolver.js';
3
+ export class WorkWindowPrecedenceError extends Error {
4
+ code;
5
+ constructor(code, message) {
6
+ super(message);
7
+ this.name = 'WorkWindowPrecedenceError';
8
+ this.code = code;
9
+ }
10
+ }
11
+ /**
12
+ * Merge the user's schedule onto a parsed flight-pack window.
13
+ *
14
+ * v2 pack metadata owns the home zone. The profile contributes only schedule
15
+ * fields; its legacy numeric offset is intentionally ignored on that path.
16
+ * Legacy v1 keeps the adapter's historical numeric replacement behavior.
17
+ */
18
+ export function mergeProfileWorkWindow(spec, profileWindow) {
19
+ // Vacation is an explicit profile fact, not an omitted schedule. It clears
20
+ // any pack window for both versions before the version-specific merge.
21
+ if (profileWindow?.vacation === true)
22
+ return { ...spec, workWindow: undefined };
23
+ if (spec[FLIGHT_PACK_VERSION] === 2) {
24
+ if (!profileWindow)
25
+ return spec;
26
+ const packWindow = spec.workWindow;
27
+ if (!packWindow?.homeZone || !isKnownZoneLoose(packWindow.homeZone)) {
28
+ throw new WorkWindowPrecedenceError('v2_profile_requires_pack_home_zone', 'v2 profile schedule requires a valid explicit pack work_window.home_zone');
29
+ }
30
+ const workWindow = {
31
+ ...packWindow,
32
+ startMin: profileWindow.startMin,
33
+ endMin: profileWindow.endMin,
34
+ workdays: profileWindow.workdays,
35
+ };
36
+ return { ...spec, workWindow };
37
+ }
38
+ // v1 adapter behavior: profile replaces the legacy pack window; no profile
39
+ // clears it as the existing adapters historically did.
40
+ if (!profileWindow)
41
+ return { ...spec, workWindow: undefined };
42
+ if (typeof profileWindow.homeTzOffsetMin !== 'number') {
43
+ throw new WorkWindowPrecedenceError('v1_profile_requires_numeric_home_offset', 'v1 profile work window requires homeTzOffsetMin');
44
+ }
45
+ return {
46
+ ...spec,
47
+ workWindow: {
48
+ homeTzOffsetMin: profileWindow.homeTzOffsetMin,
49
+ startMin: profileWindow.startMin,
50
+ endMin: profileWindow.endMin,
51
+ workdays: profileWindow.workdays,
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,2 @@
1
+ /** Internal flight-pack provenance; symbol properties stay out of JSON/public tool schemas. */
2
+ export const FLIGHT_PACK_VERSION = Symbol('gotry.flightPackVersion');
@@ -0,0 +1,70 @@
1
+ /** Read-only model surface. Credentials are entered only through the local CLI. */
2
+ import { homedir } from 'node:os';
3
+ import { defineTool } from '@deepseek-ai/dsh-tools';
4
+ import { displayEndpoint, endpointFingerprint, readFlyaiVerification, resolveFlyaiEndpoint, resolveFlyaiKey, sha256Hex, writeFlyaiVerification, } from '../capabilities/flyai-config.js';
5
+ import { readLatestChannelEvents } from '../capabilities/channel-health.js';
6
+ const guidance = '在本机运行 gotry setup flyai(隐藏输入),或 gotry setup flyai --stdin;清除文件配置用 --clear。不要在聊天中发送 API key。打开 https://flyai.open.fliggy.com/console,登录后复制 API Key。';
7
+ const guidanceImpact = '影响面:未配置 key 时 gotry_flyai_search 走匿名共享额度池(易达 Trial limit reached,达限本会话该工具不可用);配置后额度走本机 key,失败时按 verdict 改道 gotry_session_search 账号会话通道。';
8
+ export function createFlyaiSetupTool(runEffect, stateRoot) {
9
+ return defineTool({
10
+ name: 'gotry_flyai_setup',
11
+ description: 'Inspect FlyAI credential source and verification status, or check the current configuration with a read-only search. Never accepts, changes or returns credentials. Check updates only a verification receipt; setting or clearing credentials requires the local gotry setup flyai command.',
12
+ parameters: { action: { type: 'string', enum: ['status', 'check'], description: 'status (default): local status; check: read-only provider verification' } },
13
+ output: { schema: { type: 'json' }, render: (_a, value) => [{ type: 'text', text: JSON.stringify(value) }] },
14
+ async execute(args, exec) {
15
+ // Reject unknown arguments before any provider invocation or metadata write.
16
+ if (Object.keys(args).some(key => key !== 'action') || (args.action !== undefined && args.action !== 'status' && args.action !== 'check')) {
17
+ return { ok: false, summary: `仅支持 status/check;不接收凭据。${guidance} ${guidanceImpact}` };
18
+ }
19
+ const home = homedir();
20
+ const current = resolveFlyaiKey();
21
+ const endpoint = resolveFlyaiEndpoint();
22
+ const fingerprint = endpointFingerprint(endpoint.url);
23
+ let receipt = readFlyaiVerification(home);
24
+ let checkVerdict;
25
+ let receiptSaved;
26
+ if (args.action === 'check') {
27
+ const date = new Date(Date.now() + 7 * 86_400_000).toISOString().slice(0, 10);
28
+ const outcome = await runEffect({ effect: 'FLYAI_SEARCH', params: {
29
+ kind: 'flight', origin: '上海', destination: '北京', depDate: date,
30
+ timeoutMs: 20_000, signal: exec?.signal,
31
+ } });
32
+ const result = outcome.result;
33
+ checkVerdict = outcome.trace.declined === 'aborted' ? 'cancelled' : result?.verdict ?? 'error';
34
+ // A concurrent local credential change invalidates this check's receipt.
35
+ const after = resolveFlyaiKey();
36
+ const unchanged = current.key === after.key && current.source === after.source
37
+ && fingerprint === endpointFingerprint(resolveFlyaiEndpoint().url);
38
+ if (current.key && fingerprint && unchanged && checkVerdict !== 'cancelled') {
39
+ const allowed = ['auth-error', 'forbidden', 'rate-limited', 'timeout', 'needs-setup', 'error'];
40
+ const verdict = checkVerdict === 'hit' || checkVerdict === 'miss' ? 'verified'
41
+ : allowed.find(value => value === checkVerdict) ?? 'error';
42
+ receipt = { schema: 'gotry.flyai-verification.v1', source: current.source,
43
+ keySha256: sha256Hex(current.key), maskedKey: current.maskedKey ?? '****',
44
+ endpointFingerprint: fingerprint, endpointDebug: endpoint.debug,
45
+ verdict, at: new Date().toISOString() };
46
+ receiptSaved = writeFlyaiVerification(receipt, home);
47
+ }
48
+ }
49
+ const matches = Boolean(current.key && receipt && receipt.keySha256 === sha256Hex(current.key)
50
+ && receipt.source === current.source && receipt.endpointFingerprint === fingerprint
51
+ && receipt.endpointDebug === endpoint.debug);
52
+ const verified = matches && receipt?.verdict === 'verified';
53
+ const event = stateRoot ? (await readLatestChannelEvents(stateRoot, { requireValidTimestamp: true })).get('flyai') : undefined;
54
+ const lastTrialLimit = event?.state === 'down' && event.reason === 'needs-setup' ? event.at : undefined;
55
+ const status = !current.key ? '匿名试用(共享额度)' : verified ? '已验证当前配置' : '已配置,未验证通过';
56
+ const summary = `${status};来源 ${current.source};endpoint ${displayEndpoint(endpoint.url)}${endpoint.debug ? '(DEBUG)' : ''}。`
57
+ + (checkVerdict ? `本次只读检查:${checkVerdict}。` : '')
58
+ + (lastTrialLimit ? `最近试用额度受限:${lastTrialLimit}。` : '')
59
+ + (receiptSaved === false ? '验证回执保存失败,doctor 状态尚未更新。' : '') + guidance
60
+ + ' ' + guidanceImpact;
61
+ return JSON.parse(JSON.stringify({ ok: receiptSaved !== false && (!checkVerdict || checkVerdict === 'hit' || checkVerdict === 'miss'), action: args.action ?? 'status',
62
+ source: current.source, configured: Boolean(current.key), verified,
63
+ maskedKey: current.maskedKey, configPath: current.configPath,
64
+ endpoint: displayEndpoint(endpoint.url), endpointDebug: endpoint.debug,
65
+ checkVerdict, receiptSaved, lastTrialLimit, summary }));
66
+ },
67
+ // Do not retain unexpected arguments even when a host bypasses schema validation.
68
+ presentCall: args => ({ card: 'generic', title: 'FlyAI 配置检查', kind: 'fetch', rawInput: { action: args.action === 'check' ? 'check' : 'status' } }),
69
+ });
70
+ }