@danceiny/gotry 0.0.1-rc.8 → 0.2.0-rc.27

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 (506) hide show
  1. package/README.md +172 -217
  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 +1744 -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 -49
  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 +135 -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 +546 -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 +968 -0
  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 +509 -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/resilience.js +191 -0
  41. package/dist/capabilities/session/action-cache.js +126 -0
  42. package/dist/capabilities/session/adapters/ctrip-flight.js +141 -0
  43. package/dist/capabilities/session/adapters/ctrip-hotel.js +222 -0
  44. package/dist/capabilities/session/adapters/dida-portal.js +274 -0
  45. package/dist/capabilities/session/adapters/meituan-local.js +54 -0
  46. package/dist/capabilities/session/adapters/rail-12306.js +342 -0
  47. package/dist/capabilities/session/benchmark.js +189 -0
  48. package/dist/capabilities/session/bridge-ledger.js +224 -0
  49. package/dist/capabilities/session/extension-bridge.js +636 -0
  50. package/dist/capabilities/session/extension-channel.js +109 -0
  51. package/dist/capabilities/session/extension-distribution.js +230 -0
  52. package/dist/capabilities/session/extract.js +50 -0
  53. package/dist/capabilities/session/golden-score.js +114 -0
  54. package/dist/capabilities/session/health-watch.js +215 -0
  55. package/dist/capabilities/session/read-guard.js +107 -0
  56. package/dist/capabilities/session/static-flight-golden.js +150 -0
  57. package/dist/capabilities/session/transport.js +109 -0
  58. package/dist/capabilities/session/wizard.js +117 -0
  59. package/dist/capabilities/session-consent.js +178 -0
  60. package/dist/capabilities/session-login.js +170 -0
  61. package/dist/capabilities/session-search.js +686 -0
  62. package/dist/capabilities/spawn-bounded.js +203 -0
  63. package/dist/capabilities/sponsor-plugin.js +341 -0
  64. package/dist/capabilities/visa-policy.js +140 -0
  65. package/dist/capabilities/weather.js +243 -138
  66. package/dist/data/session-golden-20.json +25 -0
  67. package/dist/data/sf-golden-manifest.json +103 -0
  68. package/dist/data/sf-static-routes.json +91 -0
  69. package/dist/scripts/action-cache-tests.js +72 -0
  70. package/dist/scripts/agent-planning-turn-deadline-e2e.js +242 -0
  71. package/dist/scripts/agent-planning-turn-deadline-tests.js +185 -0
  72. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  73. package/dist/scripts/agent-reach-error-tests.js +354 -0
  74. package/dist/scripts/agent-reach-tests.js +26 -18
  75. package/dist/scripts/agent-reach-wrapper-tests.js +50 -50
  76. package/dist/scripts/anything-tests.js +116 -60
  77. package/dist/scripts/artifact-client-contract-tests.js +220 -0
  78. package/dist/scripts/artifacts-capability-tests.js +727 -0
  79. package/dist/scripts/async-collect.js +68 -10
  80. package/dist/scripts/benchmark-environment-bridge-e2e.js +741 -0
  81. package/dist/scripts/benchmark-environment-bridge-tests.js +1452 -0
  82. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +126 -0
  83. package/dist/scripts/booking-copilot-availability-policy-tests.js +265 -0
  84. package/dist/scripts/booking-copilot-bin-proof-tests.js +66 -0
  85. package/dist/scripts/booking-copilot-cleanup-proof-helper.js +76 -0
  86. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +144 -0
  87. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +424 -0
  88. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +2839 -0
  89. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +309 -0
  90. package/dist/scripts/booking-copilot-dsh-readiness-proof.js +238 -0
  91. package/dist/scripts/booking-copilot-dsh-warmer-proof.js +123 -0
  92. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +156 -0
  93. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +70 -0
  94. package/dist/scripts/booking-copilot-intent-proof-tests.js +422 -0
  95. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +184 -0
  96. package/dist/scripts/booking-copilot-planner-live-probe.js +95 -0
  97. package/dist/scripts/booking-copilot-proof-runtime.js +42 -0
  98. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +210 -0
  99. package/dist/scripts/booking-copilot-runtime-proof-tests.js +2349 -0
  100. package/dist/scripts/booking-copilot-server-proof-tests.js +784 -0
  101. package/dist/scripts/booking-copilot-startup-proof-tests.js +94 -0
  102. package/dist/scripts/booking-executor-tests.js +80 -0
  103. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  104. package/dist/scripts/booking-saga-tests.js +125 -0
  105. package/dist/scripts/booking-surface-contract-proof-tests.js +212 -0
  106. package/dist/scripts/bootstrap-tests.js +1479 -0
  107. package/dist/scripts/bridge-events-tests.js +239 -0
  108. package/dist/scripts/bridge-ledger-tests.js +428 -0
  109. package/dist/scripts/build-changelog.js +238 -0
  110. package/dist/scripts/build-metrics-report.js +331 -0
  111. package/dist/scripts/changelog-tests.js +118 -0
  112. package/dist/scripts/channel-probe-tests.js +103 -0
  113. package/dist/scripts/channel-probe.js +169 -0
  114. package/dist/scripts/channel-registry-tests.js +208 -0
  115. package/dist/scripts/companion-tests.js +67 -0
  116. package/dist/scripts/dida-cookie-probe.js +87 -0
  117. package/dist/scripts/dida-runner-stop-tests.js +311 -0
  118. package/dist/scripts/dida-sw-probe.js +114 -0
  119. package/dist/scripts/diff-test.js +17 -12
  120. package/dist/scripts/doctor-tests.js +564 -0
  121. package/dist/scripts/dsh-artifact-e2e.js +279 -0
  122. package/dist/scripts/dsh-artifact-web-e2e.js +675 -0
  123. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  124. package/dist/scripts/dsh-runtime-closure-tests.js +182 -0
  125. package/dist/scripts/dsh-runtime-closure.js +162 -0
  126. package/dist/scripts/dsh-session-v3-migration-proof.js +109 -0
  127. package/dist/scripts/dsh-subprocess-local-proof.js +150 -0
  128. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  129. package/dist/scripts/effect-tests.js +539 -0
  130. package/dist/scripts/engine-run.js +1 -3
  131. package/dist/scripts/engine-tests.js +16 -10
  132. package/dist/scripts/evaluation-cadence-tests.js +174 -0
  133. package/dist/scripts/evaluation-contract-tests.js +268 -0
  134. package/dist/scripts/extension-distribution-cli.js +39 -0
  135. package/dist/scripts/extension-distribution-tests.js +443 -0
  136. package/dist/scripts/extension-tests.js +988 -0
  137. package/dist/scripts/external-event-tests.js +350 -0
  138. package/dist/scripts/fact-gate-tests.js +869 -0
  139. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  140. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  141. package/dist/scripts/flight-malformed-tests.js +159 -0
  142. package/dist/scripts/flyai-setup-tests.js +228 -0
  143. package/dist/scripts/flyai-setup-tool-tests.js +54 -0
  144. package/dist/scripts/flyai-tests.js +692 -0
  145. package/dist/scripts/flyai-tool-registration-contract-tests.js +91 -0
  146. package/dist/scripts/fx-contract-tests.js +201 -0
  147. package/dist/scripts/g5-guard-tests.js +131 -0
  148. package/dist/scripts/g5-guard.js +189 -0
  149. package/dist/scripts/gen-lunar-anchors.js +106 -0
  150. package/dist/scripts/geo-atlas-tests.js +283 -0
  151. package/dist/scripts/gotry-backend-kernel-tests.js +206 -0
  152. package/dist/scripts/gotry-try-demo-tests.js +79 -0
  153. package/dist/scripts/gotry-try-demo.js +49 -0
  154. package/dist/scripts/ground-transfer-tests.js +956 -0
  155. package/dist/scripts/hbcli-e2e-tests.js +159 -0
  156. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  157. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  158. package/dist/scripts/hbcli-tests.js +121 -69
  159. package/dist/scripts/health-watch-cli.js +73 -0
  160. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  161. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  162. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  163. package/dist/scripts/i18n-tests.js +41 -0
  164. package/dist/scripts/incident-tests.js +281 -87
  165. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  166. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  167. package/dist/scripts/issue-271-liveness-tests.js +569 -0
  168. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  169. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  170. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  171. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  172. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  173. package/dist/scripts/issue436-persisted-routing-e2e.js +247 -0
  174. package/dist/scripts/itinerary-artifact-tests.js +368 -0
  175. package/dist/scripts/itinerary-deck-artifact-tests.js +416 -0
  176. package/dist/scripts/itinerary-deck-export-tests.js +552 -0
  177. package/dist/scripts/itinerary-deck-tests.js +435 -0
  178. package/dist/scripts/itinerary-html-tests.js +426 -0
  179. package/dist/scripts/journey-tests.js +22 -27
  180. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  181. package/dist/scripts/kernel-manifest-gate.js +126 -0
  182. package/dist/scripts/kernel-manifest-tests.js +212 -0
  183. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  184. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  185. package/dist/scripts/kernel-manifest.js +369 -0
  186. package/dist/scripts/lavish-local-tests.js +1226 -0
  187. package/dist/scripts/lavish-product-tools-tests.js +537 -0
  188. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  189. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  190. package/dist/scripts/ledger-tests.js +480 -0
  191. package/dist/scripts/ledger-workflow-crash.js +32 -0
  192. package/dist/scripts/managed-dsh-cleanup-diagnostic-proof.js +184 -0
  193. package/dist/scripts/managed-dsh-close-failure-proof.js +172 -0
  194. package/dist/scripts/managed-dsh-run-port-proof.js +153 -0
  195. package/dist/scripts/managed-dsh-terminal-proof.js +252 -0
  196. package/dist/scripts/map-tools-vendor-package-proof.js +365 -0
  197. package/dist/scripts/memory-capture-tests.js +242 -61
  198. package/dist/scripts/memory-decay-tests.js +49 -0
  199. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  200. package/dist/scripts/memory-lifecycle.js +196 -0
  201. package/dist/scripts/memory-metrics.js +29 -31
  202. package/dist/scripts/memory-value-report.js +631 -0
  203. package/dist/scripts/memory-value-tests.js +328 -0
  204. package/dist/scripts/metrics-report-tests.js +151 -0
  205. package/dist/scripts/model-override-e2e.js +137 -0
  206. package/dist/scripts/nightly-evidence-tests.js +161 -0
  207. package/dist/scripts/nightly-evidence.js +286 -0
  208. package/dist/scripts/nudge-digest.js +43 -42
  209. package/dist/scripts/observability-tests.js +381 -0
  210. package/dist/scripts/onboarding-tests.js +161 -0
  211. package/dist/scripts/opensky-check.js +18 -13
  212. package/dist/scripts/opensky-tests.js +28 -28
  213. package/dist/scripts/persona-surface-guard-tests.js +49 -0
  214. package/dist/scripts/pnpm-dsh-closure-proof.js +17 -0
  215. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  216. package/dist/scripts/price-drift-tests.js +340 -0
  217. package/dist/scripts/price-drift-watch.js +447 -0
  218. package/dist/scripts/probe-poi-tests.js +53 -45
  219. package/dist/scripts/product-metrics.js +483 -0
  220. package/dist/scripts/publish-preverify.js +110 -0
  221. package/dist/scripts/realtime-pricing-tests.js +76 -0
  222. package/dist/scripts/recall-tests.js +513 -0
  223. package/dist/scripts/replay-async.js +20 -18
  224. package/dist/scripts/replay-real.js +18 -18
  225. package/dist/scripts/replay.js +52 -82
  226. package/dist/scripts/session-attach-diagnose.js +31 -0
  227. package/dist/scripts/session-attach-poc.js +62 -0
  228. package/dist/scripts/session-benchmark.js +180 -0
  229. package/dist/scripts/session-dida-live-e2e.js +199 -0
  230. package/dist/scripts/session-extract-tests.js +60 -0
  231. package/dist/scripts/session-link-tests.js +478 -0
  232. package/dist/scripts/session-login.js +29 -0
  233. package/dist/scripts/session-tests.js +862 -0
  234. package/dist/scripts/session-zones-tests.js +358 -0
  235. package/dist/scripts/sf-live-benchmark.js +367 -0
  236. package/dist/scripts/sf-live-challenge-stop-tests.js +453 -0
  237. package/dist/scripts/sf-live-cli-tests.js +92 -0
  238. package/dist/scripts/sf-live-options.js +46 -0
  239. package/dist/scripts/sf-manifest-tests.js +30 -0
  240. package/dist/scripts/sf-manifest.js +33 -0
  241. package/dist/scripts/sf-soft-score-tests.js +67 -0
  242. package/dist/scripts/sf-summary-tests.js +324 -0
  243. package/dist/scripts/sf-summary.js +525 -0
  244. package/dist/scripts/share-tests.js +432 -0
  245. package/dist/scripts/skeleton-check.js +16 -14
  246. package/dist/scripts/skeleton-integration-test.js +28 -11
  247. package/dist/scripts/skills-contract-tests.js +51 -46
  248. package/dist/scripts/smoke-session-gate-tests.js +21 -0
  249. package/dist/scripts/smoke.js +703 -219
  250. package/dist/scripts/spawn-bounded-abort-tests.js +241 -0
  251. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  252. package/dist/scripts/state-cli-tests.js +261 -0
  253. package/dist/scripts/state-cli.js +585 -0
  254. package/dist/scripts/state-repair-cli.js +66 -0
  255. package/dist/scripts/state-repair-tests.js +140 -0
  256. package/dist/scripts/static-golden-tests.js +165 -0
  257. package/dist/scripts/time-eval-tests.js +210 -192
  258. package/dist/scripts/travel-timeline-tests.js +59 -0
  259. package/dist/scripts/turn-handoff-collect-tests.js +169 -0
  260. package/dist/scripts/turn-handoff-collect.js +161 -0
  261. package/dist/scripts/turn-policy-tests.js +55 -0
  262. package/dist/scripts/typed-contract-canary.js +176 -0
  263. package/dist/scripts/tz-resolver-sanity.js +50 -0
  264. package/dist/scripts/tz-resolver-tests.js +584 -0
  265. package/dist/scripts/unified-tests.js +23 -19
  266. package/dist/scripts/visa-policy-tests.js +62 -0
  267. package/dist/scripts/weather-tests.js +276 -41
  268. package/dist/scripts/wish-channel-gate-tests.js +54 -0
  269. package/dist/scripts/write-gate-tests.js +522 -0
  270. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  271. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  272. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  273. package/dist/scripts/z3-race-tests.js +41 -0
  274. package/dist/src/artifact-gate.js +829 -0
  275. package/dist/src/backend/kernel.js +91 -0
  276. package/dist/src/backend/modules/booking-copilot.js +92 -0
  277. package/dist/src/backend/modules/booking-executor.js +124 -0
  278. package/dist/src/backend/modules/session-search.js +551 -0
  279. package/dist/src/benchmark-agent-conformance.js +578 -0
  280. package/dist/src/benchmark-environment-bridge.js +515 -0
  281. package/dist/src/benchmark-headless-child-diagnostics.js +166 -0
  282. package/dist/src/benchmark-tool-isolation.js +151 -0
  283. package/dist/src/bookable-facts.js +533 -0
  284. package/dist/src/booking-saga.js +97 -0
  285. package/dist/src/booking-surface/availability-policy.js +697 -0
  286. package/dist/src/booking-surface/booking-intent.js +43 -0
  287. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  288. package/dist/src/booking-surface/canonical-schema.js +116 -0
  289. package/dist/src/booking-surface/contracts.js +75 -0
  290. package/dist/src/booking-surface/dsh-planner.js +1854 -0
  291. package/dist/src/booking-surface/dsh-plugin.js +378 -0
  292. package/dist/src/booking-surface/dsh-worker.js +98 -0
  293. package/dist/src/booking-surface/error-codes.js +231 -0
  294. package/dist/src/booking-surface/index.js +9 -0
  295. package/dist/src/booking-surface/managed-dsh-cleanup-diagnostic.js +97 -0
  296. package/dist/src/booking-surface/managed-dsh-run-port.js +244 -0
  297. package/dist/src/booking-surface/profile.js +24 -0
  298. package/dist/src/booking-surface/recovery-chain.js +367 -0
  299. package/dist/src/booking-surface/runtime.js +1968 -0
  300. package/dist/src/booking-surface/server.js +674 -0
  301. package/dist/src/booking-surface/startup.js +168 -0
  302. package/dist/src/booking-surface/validation.js +261 -0
  303. package/dist/src/bridge.js +20 -13
  304. package/dist/src/companions.js +86 -0
  305. package/dist/src/contracts.js +21 -43
  306. package/dist/src/dsh-llm.js +97 -111
  307. package/dist/src/engine.js +276 -193
  308. package/dist/src/evaluation-cadence.js +97 -0
  309. package/dist/src/evaluation-contracts.js +283 -0
  310. package/dist/src/flight-pack-adapter.js +54 -0
  311. package/dist/src/flight-pack-contract.js +2 -0
  312. package/dist/src/flyai-setup-tool.js +70 -0
  313. package/dist/src/gotry-backend.js +125 -0
  314. package/dist/src/hotel-date-gate.js +118 -0
  315. package/dist/src/i18n.js +88 -0
  316. package/dist/src/index.js +2305 -731
  317. package/dist/src/itinerary-deck.js +139 -0
  318. package/dist/src/itinerary-doc-shared.js +661 -0
  319. package/dist/src/itinerary-html.js +131 -0
  320. package/dist/src/journey.js +155 -108
  321. package/dist/src/lavish-tools.js +400 -0
  322. package/dist/src/ledger-repair-apply.js +538 -0
  323. package/dist/src/ledger-repair-plan.js +463 -0
  324. package/dist/src/loop.js +358 -162
  325. package/dist/src/memory-capture.js +180 -32
  326. package/dist/src/memory-decay.js +47 -0
  327. package/dist/src/memory-lifecycle.js +1310 -0
  328. package/dist/src/memory-utility.js +27 -40
  329. package/dist/src/mock-llm.js +36 -61
  330. package/dist/src/model.js +81 -36
  331. package/dist/src/realtime-pricing.js +103 -0
  332. package/dist/src/recall/card.js +74 -0
  333. package/dist/src/recall/evaluator.js +140 -0
  334. package/dist/src/recall/integration.js +17 -0
  335. package/dist/src/recall/tick.js +166 -0
  336. package/dist/src/session-link/plan-it-action.js +48 -0
  337. package/dist/src/session-link/session-link.js +248 -0
  338. package/dist/src/session-zones.js +507 -0
  339. package/dist/src/share/adapters.js +51 -0
  340. package/dist/src/share/share-consent.js +76 -0
  341. package/dist/src/share/share-deck.js +58 -0
  342. package/dist/src/share/share-token.js +146 -0
  343. package/dist/src/slot-spec.js +84 -106
  344. package/dist/src/state-ledger.js +767 -0
  345. package/dist/src/state-repair.js +299 -0
  346. package/dist/src/subagent-job-id-guard.js +58 -0
  347. package/dist/src/time-anchor.js +231 -33
  348. package/dist/src/tool-packet.js +20 -8
  349. package/dist/src/travel-slots.js +58 -35
  350. package/dist/src/travel-timeline.js +59 -0
  351. package/dist/src/turn-deadline.js +287 -0
  352. package/dist/src/turn-policy.js +118 -0
  353. package/dist/src/tz-resolver.js +143 -0
  354. package/dist/src/unified.js +538 -360
  355. package/dist/src/wish-pool.js +42 -12
  356. package/dist/src/write-gate.js +495 -0
  357. package/dist/src/z3-shared.js +284 -0
  358. package/extension/README.md +21 -0
  359. package/extension/README.zh-CN.md +21 -0
  360. package/extension/background.js +463 -0
  361. package/extension/content-bridge.js +270 -0
  362. package/extension/content-main.js +111 -0
  363. package/extension/manifest.json +60 -0
  364. package/package.json +407 -14
  365. package/schemas/booking.intent.schema.json +193 -0
  366. package/schemas/booking.surface.schema.json +2622 -0
  367. package/ts/capabilities/agent-reach-deep.ts +114 -0
  368. package/ts/capabilities/agent-reach.ts +198 -0
  369. package/ts/capabilities/anything.ts +255 -0
  370. package/ts/capabilities/artifacts.ts +428 -0
  371. package/ts/capabilities/fact-log.ts +54 -0
  372. package/ts/capabilities/flyai-config.ts +388 -0
  373. package/ts/capabilities/flyai.ts +1274 -0
  374. package/ts/capabilities/hbcli.ts +253 -71
  375. package/ts/capabilities/incident-log.ts +88 -59
  376. package/ts/capabilities/itinerary-artifact.ts +214 -0
  377. package/ts/capabilities/itinerary-deck-artifact.ts +218 -0
  378. package/ts/capabilities/itinerary-deck-export.ts +378 -0
  379. package/ts/capabilities/opensky.ts +121 -0
  380. package/ts/capabilities/session/action-cache.ts +148 -0
  381. package/ts/capabilities/session/adapters/ctrip-flight.ts +181 -0
  382. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  383. package/ts/capabilities/session/adapters/dida-portal.ts +338 -0
  384. package/ts/capabilities/session/adapters/meituan-local.ts +70 -0
  385. package/ts/capabilities/session/adapters/rail-12306.ts +392 -0
  386. package/ts/capabilities/session/benchmark.ts +276 -0
  387. package/ts/capabilities/session/bridge-ledger.ts +333 -0
  388. package/ts/capabilities/session/extension-bridge.ts +794 -0
  389. package/ts/capabilities/session/extension-channel.ts +144 -0
  390. package/ts/capabilities/session/extension-distribution.ts +266 -0
  391. package/ts/capabilities/session/extract.ts +54 -0
  392. package/ts/capabilities/session/golden-score.ts +139 -0
  393. package/ts/capabilities/session/health-watch.ts +264 -0
  394. package/ts/capabilities/session/read-guard.ts +141 -0
  395. package/ts/capabilities/session/static-flight-golden.ts +209 -0
  396. package/ts/capabilities/session/transport.ts +146 -0
  397. package/ts/capabilities/session/wizard.ts +140 -0
  398. package/ts/capabilities/session-consent.ts +211 -0
  399. package/ts/capabilities/session-login.ts +208 -0
  400. package/ts/capabilities/session-search.ts +893 -0
  401. package/ts/capabilities/weather.ts +330 -0
  402. package/ts/dsh-runtime/vendor/README.md +68 -0
  403. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  404. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +405 -0
  405. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +404 -0
  406. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +1584 -0
  407. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  408. package/ts/dsh-runtime/vendor/dsh-map-tools/icon.svg +5 -0
  409. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +595 -0
  410. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  411. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +58 -0
  412. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  413. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  414. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +131 -0
  415. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  416. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/geo.js +232 -0
  417. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +120 -0
  418. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +40 -0
  419. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/staticmap-route.js +115 -0
  420. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  421. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  422. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +267 -0
  423. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +90 -0
  424. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  425. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  426. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  427. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  428. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +23 -0
  429. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  430. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/geo.d.ts +61 -0
  431. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  432. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  433. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/staticmap-route.d.ts +31 -0
  434. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  435. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  436. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +75 -0
  437. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +68 -0
  438. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  439. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +97 -0
  440. package/ts/package.json +296 -3
  441. package/ts/scripts/async-collect.ts +91 -0
  442. package/ts/scripts/map-tools-vendor-package-proof.ts +404 -0
  443. package/ts/scripts/skeleton-check.ts +1 -1
  444. package/ts/scripts/skeleton-integration-test.ts +23 -1
  445. package/ts/scripts/state-cli.ts +568 -0
  446. package/ts/scripts/turn-handoff-collect.ts +178 -0
  447. package/ts/src/artifact-gate.ts +991 -0
  448. package/ts/src/benchmark-agent-conformance.ts +619 -0
  449. package/ts/src/benchmark-environment-bridge.ts +538 -0
  450. package/ts/src/benchmark-headless-child-diagnostics.ts +184 -0
  451. package/ts/src/benchmark-tool-isolation.ts +166 -0
  452. package/ts/src/bookable-facts.ts +837 -0
  453. package/ts/src/booking-saga.ts +133 -0
  454. package/ts/src/booking-surface/availability-policy.ts +522 -0
  455. package/ts/src/booking-surface/booking-intent.ts +86 -0
  456. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  457. package/ts/src/booking-surface/canonical-schema.js +116 -0
  458. package/ts/src/booking-surface/contracts.ts +475 -0
  459. package/ts/src/booking-surface/dsh-planner.ts +1949 -0
  460. package/ts/src/booking-surface/dsh-plugin.js +378 -0
  461. package/ts/src/booking-surface/dsh-worker.ts +110 -0
  462. package/ts/src/booking-surface/error-codes.ts +241 -0
  463. package/ts/src/booking-surface/index.ts +9 -0
  464. package/ts/src/booking-surface/managed-dsh-cleanup-diagnostic.ts +151 -0
  465. package/ts/src/booking-surface/managed-dsh-run-port.ts +273 -0
  466. package/ts/src/booking-surface/profile.ts +42 -0
  467. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  468. package/ts/src/booking-surface/runtime.ts +1793 -0
  469. package/ts/src/booking-surface/server.ts +733 -0
  470. package/ts/src/booking-surface/startup.ts +201 -0
  471. package/ts/src/booking-surface/validation.ts +217 -0
  472. package/ts/src/companions.ts +113 -0
  473. package/ts/src/contracts.ts +13 -3
  474. package/ts/src/dsh-llm.ts +44 -11
  475. package/ts/src/flyai-setup-tool.ts +77 -0
  476. package/ts/src/index.ts +2107 -224
  477. package/ts/src/itinerary-deck.ts +189 -0
  478. package/ts/src/itinerary-doc-shared.ts +741 -0
  479. package/ts/src/itinerary-html.ts +171 -0
  480. package/ts/src/loop.ts +278 -40
  481. package/ts/src/memory-capture.ts +283 -0
  482. package/ts/src/memory-decay.ts +55 -0
  483. package/ts/src/memory-utility.ts +70 -0
  484. package/ts/src/mock-llm.ts +4 -8
  485. package/ts/src/model.ts +88 -2
  486. package/ts/src/recall/card.ts +106 -0
  487. package/ts/src/recall/evaluator.ts +170 -0
  488. package/ts/src/recall/integration.ts +35 -0
  489. package/ts/src/recall/tick.ts +213 -0
  490. package/ts/src/session-link/plan-it-action.ts +78 -0
  491. package/ts/src/session-link/session-link.ts +275 -0
  492. package/ts/src/share/adapters.ts +93 -0
  493. package/ts/src/share/share-consent.ts +105 -0
  494. package/ts/src/share/share-deck.ts +85 -0
  495. package/ts/src/share/share-token.ts +166 -0
  496. package/ts/src/slot-spec.ts +172 -0
  497. package/ts/src/state-ledger.ts +912 -0
  498. package/ts/src/subagent-job-id-guard.ts +72 -0
  499. package/ts/src/time-anchor.ts +338 -0
  500. package/ts/src/tool-packet.ts +32 -0
  501. package/ts/src/travel-slots.ts +219 -0
  502. package/ts/src/travel-timeline.ts +83 -0
  503. package/ts/src/turn-deadline.ts +366 -0
  504. package/ts/src/turn-policy.ts +154 -0
  505. package/ts/src/unified.ts +360 -89
  506. package/ts/src/wish-pool.ts +79 -0
@@ -0,0 +1,483 @@
1
+ /**
2
+ * M3 真实种子 cohort 指标评分器(issue #22)。
3
+ *
4
+ * 私有证据默认位于 gotry-state/evidence/m3/:
5
+ * manifest.json 冻结样本窗口、纳排、分母、归因与阈值
6
+ * cohort.jsonl 脱敏 plan 记录与 nightly real-LLM 运行记录
7
+ * summary.json 可复跑的聚合结果(仅显式 --write-summary 时写入)
8
+ *
9
+ * 运行:
10
+ * npx tsx scripts/product-metrics.ts --evidence-root gotry-state/evidence/m3 --format json
11
+ * npx tsx scripts/product-metrics.ts --evidence-root gotry-state/evidence/m3 --write-summary
12
+ * npx tsx scripts/product-metrics.ts --fixture data/product-metrics-fixture.json --format json
13
+ *
14
+ * 纪律:
15
+ * - fixture 只验证 schema 与公式,永远不能得到 business_pass=true。
16
+ * - participant/plan/run 只接受 HMAC-SHA256 假名键;未知字段 fail-closed,
17
+ * 防止姓名、邮箱、电话、原始会话等进入证据面。
18
+ * - 分母为 0 时指标 unavailable(pass=false),不得把空样本算作 0% 幻觉。
19
+ */
20
+ import { createHash } from 'node:crypto';
21
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ const FORMULAS = {
24
+ finalization: 'finalized_eligible_delivered_plans / eligible_delivered_plans',
25
+ nps: '100 * (promoters_9_10 - detractors_0_6) / valid_responses',
26
+ poi: 'audited_invalid_poi_claims / locked_audited_poi_claims',
27
+ };
28
+ const EXCLUSION_CODES = [
29
+ 'outside_locked_window',
30
+ 'not_invited',
31
+ 'consent_missing_or_withdrawn',
32
+ 'test_or_staff',
33
+ 'attribution_not_allowed',
34
+ ];
35
+ const M3_ACCEPTANCE = {
36
+ sampleMinimum: 50,
37
+ sampleMaximum: 200,
38
+ finalizationMinimum: 0.4,
39
+ npsMinimum: 40,
40
+ poiExclusiveMaximum: 0.01,
41
+ };
42
+ const HMAC_KEY = /^hmac-sha256:[0-9a-f]{64}$/;
43
+ const SHA256 = /^[0-9a-f]{64}$/;
44
+ function object(value, label) {
45
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
46
+ throw new Error(`${label} must be an object`);
47
+ }
48
+ return value;
49
+ }
50
+ function exactKeys(value, label, keys) {
51
+ const expected = new Set(keys);
52
+ const unknown = Object.keys(value).filter(key => !expected.has(key));
53
+ const missing = keys.filter(key => !(key in value));
54
+ if (unknown.length > 0)
55
+ throw new Error(`${label} contains undeclared fields: ${unknown.join(', ')}`);
56
+ if (missing.length > 0)
57
+ throw new Error(`${label} missing fields: ${missing.join(', ')}`);
58
+ }
59
+ function string(value, label) {
60
+ if (typeof value !== 'string' || value.length === 0)
61
+ throw new Error(`${label} must be a non-empty string`);
62
+ return value;
63
+ }
64
+ function boolean(value, label) {
65
+ if (typeof value !== 'boolean')
66
+ throw new Error(`${label} must be boolean`);
67
+ return value;
68
+ }
69
+ function finiteNumber(value, label) {
70
+ if (typeof value !== 'number' || !Number.isFinite(value))
71
+ throw new Error(`${label} must be a finite number`);
72
+ return value;
73
+ }
74
+ function integer(value, label) {
75
+ const result = finiteNumber(value, label);
76
+ if (!Number.isInteger(result))
77
+ throw new Error(`${label} must be an integer`);
78
+ return result;
79
+ }
80
+ function timestamp(value, label) {
81
+ const result = string(value, label);
82
+ if (!Number.isFinite(Date.parse(result)))
83
+ throw new Error(`${label} must be an ISO timestamp`);
84
+ return result;
85
+ }
86
+ function nullableTimestamp(value, label) {
87
+ if (value === null)
88
+ return null;
89
+ return timestamp(value, label);
90
+ }
91
+ function nullableNps(value, label) {
92
+ if (value === null)
93
+ return null;
94
+ const result = integer(value, label);
95
+ if (result < 0 || result > 10)
96
+ throw new Error(`${label} must be an integer from 0 to 10`);
97
+ return result;
98
+ }
99
+ function hmacKey(value, label) {
100
+ const result = string(value, label);
101
+ if (!HMAC_KEY.test(result))
102
+ throw new Error(`${label} must be an hmac-sha256 pseudonymous key`);
103
+ return result;
104
+ }
105
+ function sha256(value, label) {
106
+ const result = string(value, label);
107
+ if (!SHA256.test(result))
108
+ throw new Error(`${label} must be a lowercase SHA-256 digest`);
109
+ return result;
110
+ }
111
+ function literal(value, label, allowed) {
112
+ const result = string(value, label);
113
+ if (!allowed.includes(result))
114
+ throw new Error(`${label} must be one of ${allowed.join(', ')}`);
115
+ return result;
116
+ }
117
+ function literalArray(value, label, allowed) {
118
+ if (!Array.isArray(value) || value.length === 0)
119
+ throw new Error(`${label} must be a non-empty array`);
120
+ const result = value.map((item, index) => literal(item, `${label}[${index}]`, allowed));
121
+ if (new Set(result).size !== result.length)
122
+ throw new Error(`${label} must not contain duplicates`);
123
+ return result;
124
+ }
125
+ function exactStringArray(value, label, expected) {
126
+ if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
127
+ throw new Error(`${label} must be a string array`);
128
+ }
129
+ const actual = [...value].sort();
130
+ const wanted = [...expected].sort();
131
+ if (JSON.stringify(actual) !== JSON.stringify(wanted)) {
132
+ throw new Error(`${label} must freeze exactly: ${wanted.join(', ')}`);
133
+ }
134
+ return value;
135
+ }
136
+ function requiredTrue(value, label) {
137
+ if (value !== true)
138
+ throw new Error(`${label} must be true in schema v1`);
139
+ return true;
140
+ }
141
+ export function parseManifest(raw) {
142
+ const root = object(raw, 'manifest');
143
+ exactKeys(root, 'manifest', ['schema_version', 'evidence_kind', 'cohort_id', 'locked_at', 'window', 'eligibility', 'metrics', 'nightly']);
144
+ const window = object(root.window, 'manifest.window');
145
+ exactKeys(window, 'manifest.window', ['start_at', 'end_at', 'timezone']);
146
+ const startAt = timestamp(window.start_at, 'manifest.window.start_at');
147
+ const endAt = timestamp(window.end_at, 'manifest.window.end_at');
148
+ if (Date.parse(startAt) > Date.parse(endAt))
149
+ throw new Error('manifest.window start_at must not be after end_at');
150
+ const eligibility = object(root.eligibility, 'manifest.eligibility');
151
+ exactKeys(eligibility, 'manifest.eligibility', ['sample_unit', 'requires_invitation', 'requires_consent', 'allowed_attribution', 'exclusion_codes']);
152
+ const metrics = object(root.metrics, 'manifest.metrics');
153
+ exactKeys(metrics, 'manifest.metrics', ['sample_size', 'finalization_rate', 'nps', 'poi_hallucination_rate']);
154
+ const sampleSize = object(metrics.sample_size, 'manifest.metrics.sample_size');
155
+ exactKeys(sampleSize, 'manifest.metrics.sample_size', ['minimum', 'maximum']);
156
+ const finalization = object(metrics.finalization_rate, 'manifest.metrics.finalization_rate');
157
+ exactKeys(finalization, 'manifest.metrics.finalization_rate', ['formula', 'minimum']);
158
+ const nps = object(metrics.nps, 'manifest.metrics.nps');
159
+ exactKeys(nps, 'manifest.metrics.nps', ['formula', 'minimum']);
160
+ const poi = object(metrics.poi_hallucination_rate, 'manifest.metrics.poi_hallucination_rate');
161
+ exactKeys(poi, 'manifest.metrics.poi_hallucination_rate', ['formula', 'exclusive_maximum']);
162
+ const nightly = object(root.nightly, 'manifest.nightly');
163
+ exactKeys(nightly, 'manifest.nightly', ['requires_real_llm', 'requires_prompt_set_sha256', 'requires_output_sha256', 'requires_cost_usd']);
164
+ const minimum = integer(sampleSize.minimum, 'manifest.metrics.sample_size.minimum');
165
+ const maximum = integer(sampleSize.maximum, 'manifest.metrics.sample_size.maximum');
166
+ if (minimum < 1 || maximum < minimum)
167
+ throw new Error('manifest sample size bounds are invalid');
168
+ const finalizationMinimum = finiteNumber(finalization.minimum, 'manifest.metrics.finalization_rate.minimum');
169
+ const npsMinimum = finiteNumber(nps.minimum, 'manifest.metrics.nps.minimum');
170
+ const poiMaximum = finiteNumber(poi.exclusive_maximum, 'manifest.metrics.poi_hallucination_rate.exclusive_maximum');
171
+ if (finalizationMinimum < 0 || finalizationMinimum > 1)
172
+ throw new Error('finalization minimum must be within 0..1');
173
+ if (npsMinimum < -100 || npsMinimum > 100)
174
+ throw new Error('NPS minimum must be within -100..100');
175
+ if (poiMaximum <= 0 || poiMaximum > 1)
176
+ throw new Error('POI exclusive maximum must be within 0..1');
177
+ if (minimum !== M3_ACCEPTANCE.sampleMinimum || maximum !== M3_ACCEPTANCE.sampleMaximum) {
178
+ throw new Error(`M3 sample size thresholds are frozen at ${M3_ACCEPTANCE.sampleMinimum}..${M3_ACCEPTANCE.sampleMaximum}`);
179
+ }
180
+ if (finalizationMinimum !== M3_ACCEPTANCE.finalizationMinimum) {
181
+ throw new Error(`M3 finalization threshold is frozen at ${M3_ACCEPTANCE.finalizationMinimum}`);
182
+ }
183
+ if (npsMinimum !== M3_ACCEPTANCE.npsMinimum) {
184
+ throw new Error(`M3 NPS threshold is frozen at ${M3_ACCEPTANCE.npsMinimum}`);
185
+ }
186
+ if (poiMaximum !== M3_ACCEPTANCE.poiExclusiveMaximum) {
187
+ throw new Error(`M3 POI hallucination threshold is frozen at ${M3_ACCEPTANCE.poiExclusiveMaximum}`);
188
+ }
189
+ return {
190
+ schema_version: literal(root.schema_version, 'manifest.schema_version', ['gotry_m3_evidence_manifest_v1']),
191
+ evidence_kind: literal(root.evidence_kind, 'manifest.evidence_kind', ['real_seed_cohort', 'synthetic_fixture']),
192
+ cohort_id: string(root.cohort_id, 'manifest.cohort_id'),
193
+ locked_at: timestamp(root.locked_at, 'manifest.locked_at'),
194
+ window: { start_at: startAt, end_at: endAt, timezone: string(window.timezone, 'manifest.window.timezone') },
195
+ eligibility: {
196
+ sample_unit: literal(eligibility.sample_unit, 'manifest.eligibility.sample_unit', ['unique_participant_with_eligible_delivered_plan']),
197
+ requires_invitation: requiredTrue(eligibility.requires_invitation, 'manifest.eligibility.requires_invitation'),
198
+ requires_consent: requiredTrue(eligibility.requires_consent, 'manifest.eligibility.requires_consent'),
199
+ allowed_attribution: literalArray(eligibility.allowed_attribution, 'manifest.eligibility.allowed_attribution', ['gotry_primary', 'gotry_assisted']),
200
+ exclusion_codes: exactStringArray(eligibility.exclusion_codes, 'manifest.eligibility.exclusion_codes', EXCLUSION_CODES),
201
+ },
202
+ metrics: {
203
+ sample_size: { minimum, maximum },
204
+ finalization_rate: {
205
+ formula: literal(finalization.formula, 'manifest.metrics.finalization_rate.formula', [FORMULAS.finalization]),
206
+ minimum: finalizationMinimum,
207
+ },
208
+ nps: {
209
+ formula: literal(nps.formula, 'manifest.metrics.nps.formula', [FORMULAS.nps]),
210
+ minimum: npsMinimum,
211
+ },
212
+ poi_hallucination_rate: {
213
+ formula: literal(poi.formula, 'manifest.metrics.poi_hallucination_rate.formula', [FORMULAS.poi]),
214
+ exclusive_maximum: poiMaximum,
215
+ },
216
+ },
217
+ nightly: {
218
+ requires_real_llm: requiredTrue(nightly.requires_real_llm, 'manifest.nightly.requires_real_llm'),
219
+ requires_prompt_set_sha256: requiredTrue(nightly.requires_prompt_set_sha256, 'manifest.nightly.requires_prompt_set_sha256'),
220
+ requires_output_sha256: requiredTrue(nightly.requires_output_sha256, 'manifest.nightly.requires_output_sha256'),
221
+ requires_cost_usd: requiredTrue(nightly.requires_cost_usd, 'manifest.nightly.requires_cost_usd'),
222
+ },
223
+ };
224
+ }
225
+ export function parseCohortRecord(raw, index) {
226
+ const label = `cohort[${index}]`;
227
+ const root = object(raw, label);
228
+ exactKeys(root, label, ['schema_version', 'participant_key', 'plan_key', 'invited', 'consent', 'test_or_staff', 'attribution', 'delivered_at', 'finalized_at', 'nps_score', 'nps_recorded_at', 'poi_audit']);
229
+ const poi = object(root.poi_audit, `${label}.poi_audit`);
230
+ exactKeys(poi, `${label}.poi_audit`, ['locked_at', 'locked_claims', 'invalid_claims']);
231
+ const lockedClaims = integer(poi.locked_claims, `${label}.poi_audit.locked_claims`);
232
+ const invalidClaims = integer(poi.invalid_claims, `${label}.poi_audit.invalid_claims`);
233
+ if (lockedClaims < 0 || invalidClaims < 0 || invalidClaims > lockedClaims) {
234
+ throw new Error(`${label}.poi_audit requires 0 <= invalid_claims <= locked_claims`);
235
+ }
236
+ const deliveredAt = timestamp(root.delivered_at, `${label}.delivered_at`);
237
+ const finalizedAt = nullableTimestamp(root.finalized_at, `${label}.finalized_at`);
238
+ const npsScore = nullableNps(root.nps_score, `${label}.nps_score`);
239
+ const npsRecordedAt = nullableTimestamp(root.nps_recorded_at, `${label}.nps_recorded_at`);
240
+ const poiLockedAt = timestamp(poi.locked_at, `${label}.poi_audit.locked_at`);
241
+ if (finalizedAt !== null && Date.parse(finalizedAt) < Date.parse(deliveredAt)) {
242
+ throw new Error(`${label}.finalized_at must not be before delivered_at`);
243
+ }
244
+ if ((npsScore === null) !== (npsRecordedAt === null)) {
245
+ throw new Error(`${label}.nps_score and nps_recorded_at must both be null or both be set`);
246
+ }
247
+ if (npsRecordedAt !== null && Date.parse(npsRecordedAt) < Date.parse(deliveredAt)) {
248
+ throw new Error(`${label}.nps_recorded_at must not be before delivered_at`);
249
+ }
250
+ if (Date.parse(poiLockedAt) < Date.parse(deliveredAt)) {
251
+ throw new Error(`${label}.poi_audit.locked_at must not be before delivered_at`);
252
+ }
253
+ return {
254
+ schema_version: literal(root.schema_version, `${label}.schema_version`, ['gotry_m3_cohort_record_v1']),
255
+ participant_key: hmacKey(root.participant_key, `${label}.participant_key`),
256
+ plan_key: hmacKey(root.plan_key, `${label}.plan_key`),
257
+ invited: boolean(root.invited, `${label}.invited`),
258
+ consent: boolean(root.consent, `${label}.consent`),
259
+ test_or_staff: boolean(root.test_or_staff, `${label}.test_or_staff`),
260
+ attribution: literal(root.attribution, `${label}.attribution`, ['gotry_primary', 'gotry_assisted']),
261
+ delivered_at: deliveredAt,
262
+ finalized_at: finalizedAt,
263
+ nps_score: npsScore,
264
+ nps_recorded_at: npsRecordedAt,
265
+ poi_audit: { locked_at: poiLockedAt, locked_claims: lockedClaims, invalid_claims: invalidClaims },
266
+ };
267
+ }
268
+ export function parseNightlyRun(raw, index) {
269
+ const label = `nightly_runs[${index}]`;
270
+ const root = object(raw, label);
271
+ exactKeys(root, label, ['schema_version', 'run_key', 'executed_at', 'real_llm', 'prompt_set_sha256', 'output_sha256', 'cost_usd']);
272
+ const costUsd = finiteNumber(root.cost_usd, `${label}.cost_usd`);
273
+ if (costUsd < 0)
274
+ throw new Error(`${label}.cost_usd must be non-negative`);
275
+ return {
276
+ schema_version: literal(root.schema_version, `${label}.schema_version`, ['gotry_m3_nightly_run_v1']),
277
+ run_key: hmacKey(root.run_key, `${label}.run_key`),
278
+ executed_at: timestamp(root.executed_at, `${label}.executed_at`),
279
+ real_llm: boolean(root.real_llm, `${label}.real_llm`),
280
+ prompt_set_sha256: sha256(root.prompt_set_sha256, `${label}.prompt_set_sha256`),
281
+ output_sha256: sha256(root.output_sha256, `${label}.output_sha256`),
282
+ cost_usd: costUsd,
283
+ };
284
+ }
285
+ function round(value) {
286
+ return Number(value.toFixed(6));
287
+ }
288
+ function canonical(value) {
289
+ if (Array.isArray(value))
290
+ return `[${value.map(canonical).join(',')}]`;
291
+ if (typeof value === 'object' && value !== null) {
292
+ const record = value;
293
+ return `{${Object.keys(record).sort().map(key => `${JSON.stringify(key)}:${canonical(record[key])}`).join(',')}}`;
294
+ }
295
+ return JSON.stringify(value);
296
+ }
297
+ function exclusionsFor(manifest, record) {
298
+ const result = [];
299
+ const delivered = Date.parse(record.delivered_at);
300
+ if (delivered < Date.parse(manifest.window.start_at) || delivered > Date.parse(manifest.window.end_at))
301
+ result.push('outside_locked_window');
302
+ if (!record.invited)
303
+ result.push('not_invited');
304
+ if (!record.consent)
305
+ result.push('consent_missing_or_withdrawn');
306
+ if (record.test_or_staff)
307
+ result.push('test_or_staff');
308
+ if (!manifest.eligibility.allowed_attribution.includes(record.attribution))
309
+ result.push('attribution_not_allowed');
310
+ return result;
311
+ }
312
+ export function scoreProductMetrics(manifest, cohort, nightlyRuns) {
313
+ const planKeys = new Set();
314
+ const runKeys = new Set();
315
+ for (const record of cohort) {
316
+ if (planKeys.has(record.plan_key))
317
+ throw new Error(`duplicate plan_key: ${record.plan_key}`);
318
+ planKeys.add(record.plan_key);
319
+ }
320
+ for (const run of nightlyRuns) {
321
+ if (runKeys.has(run.run_key))
322
+ throw new Error(`duplicate run_key: ${run.run_key}`);
323
+ runKeys.add(run.run_key);
324
+ }
325
+ const exclusionCounts = Object.fromEntries(EXCLUSION_CODES.map(code => [code, 0]));
326
+ const eligible = cohort.filter(record => {
327
+ const exclusions = exclusionsFor(manifest, record);
328
+ for (const code of exclusions)
329
+ exclusionCounts[code] += 1;
330
+ return exclusions.length === 0;
331
+ });
332
+ const participants = new Set(eligible.map(record => record.participant_key));
333
+ const windowEnd = Date.parse(manifest.window.end_at);
334
+ const finalized = eligible.filter(record => record.finalized_at !== null && Date.parse(record.finalized_at) <= windowEnd).length;
335
+ const finalizationRate = eligible.length === 0 ? null : round(finalized / eligible.length);
336
+ const npsByParticipant = new Map();
337
+ for (const record of eligible) {
338
+ if (record.nps_score === null || record.nps_recorded_at === null || Date.parse(record.nps_recorded_at) > windowEnd)
339
+ continue;
340
+ if (npsByParticipant.has(record.participant_key)) {
341
+ throw new Error(`participant has more than one NPS response in the locked window: ${record.participant_key}`);
342
+ }
343
+ npsByParticipant.set(record.participant_key, record.nps_score);
344
+ }
345
+ const scores = [...npsByParticipant.values()];
346
+ const promoters = scores.filter(score => score >= 9).length;
347
+ const detractors = scores.filter(score => score <= 6).length;
348
+ const passives = scores.length - promoters - detractors;
349
+ const npsScore = scores.length === 0 ? null : round(100 * (promoters - detractors) / scores.length);
350
+ const lockedAudits = eligible.filter(record => Date.parse(record.poi_audit.locked_at) <= windowEnd);
351
+ const lockedClaims = lockedAudits.reduce((sum, record) => sum + record.poi_audit.locked_claims, 0);
352
+ const invalidClaims = lockedAudits.reduce((sum, record) => sum + record.poi_audit.invalid_claims, 0);
353
+ const poiRate = lockedClaims === 0 ? null : round(invalidClaims / lockedClaims);
354
+ const windowStart = Date.parse(manifest.window.start_at);
355
+ const replayableRuns = nightlyRuns.filter(run => {
356
+ const executedAt = Date.parse(run.executed_at);
357
+ return run.real_llm && executedAt >= windowStart && executedAt <= windowEnd;
358
+ });
359
+ const nightlyCost = round(replayableRuns.reduce((sum, run) => sum + run.cost_usd, 0));
360
+ const samplePass = participants.size >= manifest.metrics.sample_size.minimum && participants.size <= manifest.metrics.sample_size.maximum;
361
+ const finalizationPass = finalizationRate !== null && finalizationRate >= manifest.metrics.finalization_rate.minimum;
362
+ const npsPass = npsScore !== null && npsScore >= manifest.metrics.nps.minimum;
363
+ const poiPass = poiRate !== null && poiRate < manifest.metrics.poi_hallucination_rate.exclusive_maximum;
364
+ const nightlyPass = replayableRuns.length > 0;
365
+ const metricPass = samplePass && finalizationPass && npsPass && poiPass && nightlyPass;
366
+ const businessPass = manifest.evidence_kind === 'real_seed_cohort' && metricPass;
367
+ const failedChecks = [
368
+ !samplePass && 'sample_size',
369
+ !finalizationPass && 'finalization_rate',
370
+ !npsPass && 'nps',
371
+ !poiPass && 'poi_hallucination_rate',
372
+ !nightlyPass && 'nightly_real_llm',
373
+ ].filter(Boolean);
374
+ const businessPassReason = manifest.evidence_kind === 'synthetic_fixture'
375
+ ? 'evidence_kind=synthetic_fixture cannot prove business pass'
376
+ : businessPass
377
+ ? 'all locked M3 acceptance thresholds passed on real_seed_cohort evidence'
378
+ : `real_seed_cohort acceptance gaps: ${failedChecks.join(', ')}`;
379
+ return {
380
+ schema_version: 'gotry_m3_product_metrics_summary_v1',
381
+ evidence_kind: manifest.evidence_kind,
382
+ cohort_id: manifest.cohort_id,
383
+ evidence_digest_sha256: createHash('sha256').update(canonical({ manifest, cohort, nightlyRuns })).digest('hex'),
384
+ sample: {
385
+ participants: participants.size,
386
+ minimum: manifest.metrics.sample_size.minimum,
387
+ maximum: manifest.metrics.sample_size.maximum,
388
+ pass: samplePass,
389
+ },
390
+ finalization: { numerator: finalized, denominator: eligible.length, rate: finalizationRate, pass: finalizationPass },
391
+ nps: { promoters, passives, detractors, denominator: scores.length, score: npsScore, pass: npsPass },
392
+ poi_hallucination: { invalid_claims: invalidClaims, locked_claims: lockedClaims, rate: poiRate, pass: poiPass },
393
+ nightly: { replayable_real_llm_runs: replayableRuns.length, cost_usd: nightlyCost, pass: nightlyPass },
394
+ exclusions: exclusionCounts,
395
+ business_pass: businessPass,
396
+ business_pass_reason: businessPassReason,
397
+ };
398
+ }
399
+ function parseJsonLines(contents) {
400
+ return contents.split(/\r?\n/).flatMap((line, index) => {
401
+ if (line.trim() === '')
402
+ return [];
403
+ try {
404
+ return [JSON.parse(line)];
405
+ }
406
+ catch (error) {
407
+ throw new Error(`cohort.jsonl line ${index + 1} is invalid JSON: ${error.message}`);
408
+ }
409
+ });
410
+ }
411
+ function loadFixture(path) {
412
+ const raw = object(JSON.parse(readFileSync(path, 'utf8')), 'fixture');
413
+ exactKeys(raw, 'fixture', ['schema_version', 'manifest', 'cohort', 'nightly_runs']);
414
+ literal(raw.schema_version, 'fixture.schema_version', ['gotry_m3_product_metrics_fixture_v1']);
415
+ if (!Array.isArray(raw.cohort))
416
+ throw new Error('fixture.cohort must be an array');
417
+ if (!Array.isArray(raw.nightly_runs))
418
+ throw new Error('fixture.nightly_runs must be an array');
419
+ return {
420
+ manifest: parseManifest(raw.manifest),
421
+ cohort: raw.cohort.map(parseCohortRecord),
422
+ nightlyRuns: raw.nightly_runs.map(parseNightlyRun),
423
+ };
424
+ }
425
+ function loadEvidenceRoot(root) {
426
+ const manifest = parseManifest(JSON.parse(readFileSync(join(root, 'manifest.json'), 'utf8')));
427
+ const records = parseJsonLines(readFileSync(join(root, 'cohort.jsonl'), 'utf8'));
428
+ const cohort = [];
429
+ const nightlyRuns = [];
430
+ for (const record of records) {
431
+ const schema = object(record, 'cohort.jsonl record').schema_version;
432
+ if (schema === 'gotry_m3_cohort_record_v1')
433
+ cohort.push(parseCohortRecord(record, cohort.length));
434
+ else if (schema === 'gotry_m3_nightly_run_v1')
435
+ nightlyRuns.push(parseNightlyRun(record, nightlyRuns.length));
436
+ else
437
+ throw new Error(`cohort.jsonl contains unknown schema_version: ${String(schema)}`);
438
+ }
439
+ return { manifest, cohort, nightlyRuns };
440
+ }
441
+ function arg(name) {
442
+ const index = process.argv.indexOf(name);
443
+ return index >= 0 ? process.argv[index + 1] : undefined;
444
+ }
445
+ function renderMarkdown(summary) {
446
+ const percent = (value) => value === null ? 'unavailable' : `${round(value * 100)}%`;
447
+ return [
448
+ `# M3 cohort 指标摘要(${summary.evidence_kind})`,
449
+ '',
450
+ `- 样本: ${summary.sample.participants} 人(pass=${summary.sample.pass};要求 ${summary.sample.minimum}..${summary.sample.maximum})`,
451
+ `- 定稿率: ${summary.finalization.numerator}/${summary.finalization.denominator} = ${percent(summary.finalization.rate)}(pass=${summary.finalization.pass})`,
452
+ `- NPS: ${summary.nps.score ?? 'unavailable'}(responses=${summary.nps.denominator};pass=${summary.nps.pass})`,
453
+ `- POI 幻觉率: ${summary.poi_hallucination.invalid_claims}/${summary.poi_hallucination.locked_claims} = ${percent(summary.poi_hallucination.rate)}(pass=${summary.poi_hallucination.pass})`,
454
+ `- Nightly real-LLM: ${summary.nightly.replayable_real_llm_runs} runs, $${summary.nightly.cost_usd}(pass=${summary.nightly.pass})`,
455
+ `- Business pass: ${summary.business_pass} — ${summary.business_pass_reason}`,
456
+ `- Evidence digest: ${summary.evidence_digest_sha256}`,
457
+ ].join('\n');
458
+ }
459
+ function main() {
460
+ const fixturePath = arg('--fixture');
461
+ const evidenceRoot = arg('--evidence-root') ?? 'gotry-state/evidence/m3';
462
+ const loaded = fixturePath ? loadFixture(fixturePath) : loadEvidenceRoot(evidenceRoot);
463
+ const summary = scoreProductMetrics(loaded.manifest, loaded.cohort, loaded.nightlyRuns);
464
+ if (process.argv.includes('--write-summary')) {
465
+ if (fixturePath)
466
+ throw new Error('--write-summary is forbidden for synthetic fixtures');
467
+ mkdirSync(evidenceRoot, { recursive: true });
468
+ writeFileSync(join(evidenceRoot, 'summary.json'), `${JSON.stringify(summary, null, 2)}\n`, 'utf8');
469
+ }
470
+ if ((arg('--format') ?? 'markdown') === 'json')
471
+ console.log(JSON.stringify(summary));
472
+ else
473
+ console.log(renderMarkdown(summary));
474
+ }
475
+ if (process.argv[1]?.endsWith('product-metrics.ts')) {
476
+ try {
477
+ main();
478
+ }
479
+ catch (error) {
480
+ console.error(`M3 product metrics error: ${error.message}`);
481
+ process.exitCode = 1;
482
+ }
483
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * 发布前离线预验证(发布闸,rc.9 教训固化):
3
+ * 1. npm pack 产 tarball;
4
+ * 2. 装进 mktemp 干净目录(--ignore-scripts 快速);
5
+ * 3. 核验:版本号一致 + dependencies 闭包可达 + 关键入口文件在 + 账本模块可 import。
6
+ * 任何一步失败即 FAIL——rc.9「装得上跑不起」教训的永久闸。
7
+ * 运行:cd ts && npx tsx scripts/publish-preverify.ts
8
+ */
9
+ import { execSync } from 'node:child_process';
10
+ import { mkdtempSync, rmSync, existsSync, readFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join } from 'node:path';
13
+ import { pathToFileURL } from 'node:url';
14
+ import { REQUIRED_BENCHMARK_DSH_VERSION } from '../../bin/gotry-runtime-resolution.js';
15
+ import { parsePnpmDshLock, parsePnpmRootDshImporter, REQUIRED_DSH_RUNTIME_PACKAGE_COUNT, validateDshRuntimeClosure, validatePnpmRootDshImporter, } from './dsh-runtime-closure.js';
16
+ const repoRoot = join(import.meta.dirname, '..', '..');
17
+ process.chdir(repoRoot);
18
+ const pkg = JSON.parse(execSync('cat package.json', { encoding: 'utf-8' }));
19
+ const version = pkg.version;
20
+ console.log(`pre-verify: @danceiny/gotry@${version}`);
21
+ let tgz = '';
22
+ let dest = '';
23
+ try {
24
+ // 1) pack(产物落临时目录,不污染仓根;输出走文件防 ENOBUFS)
25
+ const outDir = mkdtempSync(join(tmpdir(), 'gotry-preverify-out-'));
26
+ execSync(`npm pack --pack-destination ${outDir}`, { stdio: 'ignore' });
27
+ const tgzPath = `danceiny-gotry-${version}.tgz`;
28
+ if (!existsSync(join(outDir, tgzPath)))
29
+ throw new Error('npm pack 未产出 tarball');
30
+ tgz = join(outDir, tgzPath);
31
+ console.log(`tarball: ${tgzPath}`);
32
+ // 2) 直接解 tarball(免网络:验证的是 tarball 自身内容,声明依赖可达性交由 npm registry 安装时保证)
33
+ dest = mkdtempSync(join(tmpdir(), 'gotry-preverify-'));
34
+ execSync(`tar -xzf "${tgz}" -C "${dest}"`, { stdio: 'pipe' });
35
+ const pkgDir = join(dest, 'package');
36
+ const installedPkg = JSON.parse(execSync(`cat ${join(pkgDir, 'package.json')}`, { encoding: 'utf-8' }));
37
+ if (installedPkg.version !== version)
38
+ throw new Error(`版本不符:${installedPkg.version}`);
39
+ // DSH prerelease packages publish their internal edges as caret ranges. A
40
+ // clean consumer must therefore receive the whole tested family as exact
41
+ // top-level dependencies; otherwise a newly published alpha can be mixed
42
+ // into the older runtime even though the source lockfile is coherent.
43
+ const rootLock = JSON.parse(readFileSync(join(repoRoot, 'package-lock.json'), 'utf-8'));
44
+ const dshClosure = validateDshRuntimeClosure({
45
+ dependencies: installedPkg.dependencies ?? {},
46
+ lockPackages: rootLock.packages ?? {},
47
+ runtimeVersion: REQUIRED_BENCHMARK_DSH_VERSION,
48
+ expectedPackageCount: REQUIRED_DSH_RUNTIME_PACKAGE_COUNT,
49
+ });
50
+ console.log(`dsh closure: ${dshClosure.names.length} packages pinned at ${dshClosure.version}`);
51
+ const pnpmLock = readFileSync(join(repoRoot, 'pnpm-lock.yaml'), 'utf-8');
52
+ const pnpmClosure = validateDshRuntimeClosure({
53
+ dependencies: installedPkg.dependencies ?? {},
54
+ lockPackages: parsePnpmDshLock(pnpmLock),
55
+ runtimeVersion: REQUIRED_BENCHMARK_DSH_VERSION,
56
+ expectedPackageCount: REQUIRED_DSH_RUNTIME_PACKAGE_COUNT,
57
+ });
58
+ const pnpmImporter = validatePnpmRootDshImporter({
59
+ dependencies: installedPkg.dependencies ?? {},
60
+ importerEntries: parsePnpmRootDshImporter(pnpmLock),
61
+ runtimeVersion: REQUIRED_BENCHMARK_DSH_VERSION,
62
+ expectedPackageCount: REQUIRED_DSH_RUNTIME_PACKAGE_COUNT,
63
+ });
64
+ console.log(`pnpm closure: ${pnpmClosure.names.length} packages, root importer ${pnpmImporter.names.length}`);
65
+ // 3) dependencies 声明完整性:每个依赖必须存在于安装树(rc.9 缺陷=声明了运行时使用但根本没声明依赖)
66
+ const deps = Object.keys(installedPkg.dependencies ?? {});
67
+ console.log(`dependencies: ${deps.length} declared`);
68
+ // 3b) 运行时 import 的重依赖必须在 dependencies 里声明(可用性由 npm 安装时保证;rc.9 缺陷=用了但没声明)
69
+ const runtimeImports = ['better-sqlite3'];
70
+ for (const dep of runtimeImports) {
71
+ if (!deps.includes(dep))
72
+ throw new Error(`运行时依赖 ${dep} 未声明进 dependencies(rc.9 缺陷形态)`);
73
+ }
74
+ console.log('deps resolvable: OK');
75
+ // 4) 关键入口文件在包内 + 账本模块真实 import
76
+ for (const e of [
77
+ 'dist/src/state-ledger.js',
78
+ 'dist/src/index.js',
79
+ 'bin/gotry-inner.js',
80
+ 'dist/capabilities/session/static-flight-golden.js',
81
+ 'dist/capabilities/session/golden-score.js',
82
+ 'dist/scripts/sf-live-benchmark.js',
83
+ 'dist/data/session-golden-20.json',
84
+ 'dist/data/sf-golden-manifest.json',
85
+ 'dist/data/sf-static-routes.json',
86
+ ]) {
87
+ if (!existsSync(join(pkgDir, e)))
88
+ throw new Error(`发布缺文件: ${e}`);
89
+ }
90
+ // import 冒烟改静态:state-ledger 的 better-sqlite3 引用已被 §3b 声明检查覆盖(无安装树时无法真 import)
91
+ if (!execSync(`grep -c "better-sqlite3" ${join(pkgDir, 'dist/src/state-ledger.js')}`, { encoding: 'utf-8' }).trim().match(/^[1-9]/)) {
92
+ throw new Error('dist/src/state-ledger.js 未引用 better-sqlite3(声明与实现不符)');
93
+ }
94
+ const staticProvider = await import(pathToFileURL(join(pkgDir, 'dist/capabilities/session/static-flight-golden.js')).href);
95
+ const staticSnapshot = staticProvider.loadStaticFlightSnapshot();
96
+ if (staticSnapshot.schema_version !== 'sf-static-routes.v1' || staticSnapshot.routes.length !== 8) {
97
+ throw new Error('发布 static golden 快照不可加载或覆盖不足 8 条');
98
+ }
99
+ console.log('PUBLISH PREVERIFY: OK');
100
+ }
101
+ catch (e) {
102
+ console.error(`PREVERIFY FAILED: ${e.message}`);
103
+ process.exit(1);
104
+ }
105
+ finally {
106
+ if (tgz)
107
+ rmSync(tgz, { force: true });
108
+ if (dest)
109
+ rmSync(dest, { recursive: true, force: true });
110
+ }