@danceiny/gotry 0.0.1-rc.21 → 0.0.1-rc.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/README.md +102 -194
  2. package/README.zh-CN.md +115 -210
  3. package/bin/gotry-backend.js +53 -0
  4. package/bin/gotry-bootstrap.js +466 -35
  5. package/bin/gotry-inner.js +255 -36
  6. package/bin/gotry-process-liveness.d.ts +27 -0
  7. package/bin/gotry-process-liveness.js +97 -0
  8. package/bin/gotry-runtime-resolution.d.ts +1 -1
  9. package/bin/gotry-runtime-resolution.js +2 -2
  10. package/client/client.js +174 -0
  11. package/cordis.gotry-patch.yml +70 -93
  12. package/dist/capabilities/agent-reach-deep.js +45 -122
  13. package/dist/capabilities/agent-reach.js +63 -148
  14. package/dist/capabilities/anything.js +89 -75
  15. package/dist/capabilities/artifacts.js +123 -104
  16. package/dist/capabilities/channel-health.js +65 -45
  17. package/dist/capabilities/channel-registry.js +108 -87
  18. package/dist/capabilities/doctor.js +357 -235
  19. package/dist/capabilities/effect.js +223 -309
  20. package/dist/capabilities/fact-log.js +28 -14
  21. package/dist/capabilities/flyai.js +245 -156
  22. package/dist/capabilities/ground-transfer.js +509 -0
  23. package/dist/capabilities/hbcli.js +144 -148
  24. package/dist/capabilities/hotelbyte-transaction.js +194 -0
  25. package/dist/capabilities/incident-log.js +131 -61
  26. package/dist/capabilities/model-override.js +30 -10
  27. package/dist/capabilities/opensky.js +54 -43
  28. package/dist/capabilities/resilience.js +50 -32
  29. package/dist/capabilities/session/action-cache.js +50 -44
  30. package/dist/capabilities/session/adapters/ctrip-flight.js +119 -62
  31. package/dist/capabilities/session/adapters/ctrip-hotel.js +125 -110
  32. package/dist/capabilities/session/adapters/dida-portal.js +206 -0
  33. package/dist/capabilities/session/adapters/meituan-local.js +35 -54
  34. package/dist/capabilities/session/adapters/rail-12306.js +169 -112
  35. package/dist/capabilities/session/benchmark.js +85 -149
  36. package/dist/capabilities/session/extension-bridge.js +320 -259
  37. package/dist/capabilities/session/extension-channel.js +57 -76
  38. package/dist/capabilities/session/extension-distribution.js +115 -119
  39. package/dist/capabilities/session/extract.js +31 -21
  40. package/dist/capabilities/session/golden-score.js +55 -33
  41. package/dist/capabilities/session/health-watch.js +146 -154
  42. package/dist/capabilities/session/read-guard.js +55 -47
  43. package/dist/capabilities/session/static-flight-golden.js +49 -36
  44. package/dist/capabilities/session/transport.js +54 -61
  45. package/dist/capabilities/session/wizard.js +63 -93
  46. package/dist/capabilities/session-consent.js +143 -47
  47. package/dist/capabilities/session-login.js +95 -126
  48. package/dist/capabilities/session-search.js +391 -253
  49. package/dist/capabilities/sponsor-plugin.js +341 -0
  50. package/dist/capabilities/visa-policy.js +87 -73
  51. package/dist/capabilities/weather.js +163 -235
  52. package/dist/scripts/action-cache-tests.js +24 -59
  53. package/dist/scripts/agent-planning-turn-deadline-e2e.js +91 -142
  54. package/dist/scripts/agent-planning-turn-deadline-tests.js +80 -176
  55. package/dist/scripts/agent-reach-deep-tests.js +30 -40
  56. package/dist/scripts/agent-reach-tests.js +26 -18
  57. package/dist/scripts/agent-reach-wrapper-tests.js +46 -50
  58. package/dist/scripts/anything-tests.js +58 -62
  59. package/dist/scripts/artifact-client-contract-tests.js +69 -0
  60. package/dist/scripts/artifacts-capability-tests.js +235 -0
  61. package/dist/scripts/async-collect.js +26 -15
  62. package/dist/scripts/benchmark-environment-bridge-e2e.js +287 -684
  63. package/dist/scripts/benchmark-environment-bridge-tests.js +818 -3123
  64. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +66 -279
  65. package/dist/scripts/booking-copilot-availability-policy-tests.js +153 -1257
  66. package/dist/scripts/booking-copilot-bin-proof-tests.js +22 -45
  67. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +64 -76
  68. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +69 -199
  69. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +393 -759
  70. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +33 -75
  71. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +60 -110
  72. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +28 -66
  73. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +72 -271
  74. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +73 -275
  75. package/dist/scripts/booking-copilot-runtime-proof-tests.js +784 -3398
  76. package/dist/scripts/booking-copilot-server-proof-tests.js +63 -168
  77. package/dist/scripts/booking-copilot-startup-proof-tests.js +38 -124
  78. package/dist/scripts/booking-executor-tests.js +80 -0
  79. package/dist/scripts/booking-recovery-chain-tests.js +182 -0
  80. package/dist/scripts/booking-saga-tests.js +61 -123
  81. package/dist/scripts/booking-surface-contract-proof-tests.js +152 -1167
  82. package/dist/scripts/bootstrap-tests.js +1383 -128
  83. package/dist/scripts/build-changelog.js +89 -130
  84. package/dist/scripts/build-metrics-report.js +135 -143
  85. package/dist/scripts/changelog-tests.js +35 -82
  86. package/dist/scripts/channel-probe-tests.js +44 -116
  87. package/dist/scripts/channel-probe.js +84 -167
  88. package/dist/scripts/channel-registry-tests.js +97 -185
  89. package/dist/scripts/companion-tests.js +25 -70
  90. package/dist/scripts/dida-cookie-probe.js +87 -0
  91. package/dist/scripts/dida-sw-probe.js +114 -0
  92. package/dist/scripts/diff-test.js +17 -12
  93. package/dist/scripts/doctor-tests.js +428 -120
  94. package/dist/scripts/dsh-artifact-e2e.js +150 -0
  95. package/dist/scripts/dsh-artifact-web-e2e.js +443 -0
  96. package/dist/scripts/dsh-http-proxy-sse-proof.js +90 -0
  97. package/dist/scripts/dsh-runtime-closure-tests.js +110 -153
  98. package/dist/scripts/dsh-runtime-closure.js +75 -63
  99. package/dist/scripts/dsh-session-v3-migration-proof.js +106 -0
  100. package/dist/scripts/dsh-subprocess-local-proof.js +149 -0
  101. package/dist/scripts/dsh-target-closure-proof.js +178 -0
  102. package/dist/scripts/effect-tests.js +165 -552
  103. package/dist/scripts/engine-run.js +1 -3
  104. package/dist/scripts/engine-tests.js +16 -10
  105. package/dist/scripts/evaluation-cadence-tests.js +69 -242
  106. package/dist/scripts/evaluation-contract-tests.js +193 -499
  107. package/dist/scripts/extension-distribution-cli.js +19 -15
  108. package/dist/scripts/extension-distribution-tests.js +98 -211
  109. package/dist/scripts/extension-tests.js +366 -389
  110. package/dist/scripts/fact-gate-tests.js +725 -263
  111. package/dist/scripts/fixtures/extension-bridge-unref-child.mjs +21 -0
  112. package/dist/scripts/flight-hotel-anchor-363-registered-e2e.js +169 -0
  113. package/dist/scripts/flight-malformed-tests.js +159 -0
  114. package/dist/scripts/flyai-tests.js +325 -68
  115. package/dist/scripts/g5-guard-tests.js +131 -0
  116. package/dist/scripts/g5-guard.js +189 -0
  117. package/dist/scripts/gen-lunar-anchors.js +106 -0
  118. package/dist/scripts/gotry-backend-kernel-tests.js +79 -0
  119. package/dist/scripts/ground-transfer-tests.js +956 -0
  120. package/dist/scripts/hbcli-e2e-tests.js +71 -90
  121. package/dist/scripts/hbcli-live-optin-tests.js +96 -0
  122. package/dist/scripts/hbcli-release-contract-tests.js +122 -0
  123. package/dist/scripts/hbcli-tests.js +41 -115
  124. package/dist/scripts/health-watch-cli.js +42 -28
  125. package/dist/scripts/hotel-date-gate-tests.js +496 -0
  126. package/dist/scripts/hotelbyte-reconcile-tests.js +141 -0
  127. package/dist/scripts/hotelbyte-spawn-e2e-tests.js +373 -0
  128. package/dist/scripts/i18n-tests.js +16 -9
  129. package/dist/scripts/incident-tests.js +281 -87
  130. package/dist/scripts/issue-194-job-id-guard-tests.js +106 -0
  131. package/dist/scripts/issue-233-cancel-refund-commission-tests.js +392 -0
  132. package/dist/scripts/issue-271-liveness-tests.js +547 -0
  133. package/dist/scripts/issue-289-model-retry-real-tests.js +296 -0
  134. package/dist/scripts/issue-289-model-retry-tests.js +441 -0
  135. package/dist/scripts/issue-289-web-retry-e2e.js +630 -0
  136. package/dist/scripts/issue-338-home-city-e2e.js +577 -0
  137. package/dist/scripts/issue343-real-entry-e2e.js +160 -0
  138. package/dist/scripts/journey-tests.js +22 -27
  139. package/dist/scripts/kernel-manifest-evidence.js +109 -0
  140. package/dist/scripts/kernel-manifest-gate.js +126 -0
  141. package/dist/scripts/kernel-manifest-tests.js +212 -0
  142. package/dist/scripts/kernel-manifest-trace-entry.js +7 -0
  143. package/dist/scripts/kernel-manifest-trace-hook.mjs +28 -0
  144. package/dist/scripts/kernel-manifest.js +369 -0
  145. package/dist/scripts/ledger-repair-apply-tests.js +316 -0
  146. package/dist/scripts/ledger-repair-plan-tests.js +375 -0
  147. package/dist/scripts/ledger-tests.js +325 -340
  148. package/dist/scripts/ledger-workflow-crash.js +10 -20
  149. package/dist/scripts/map-tools-vendor-package-proof.js +206 -134
  150. package/dist/scripts/memory-capture-tests.js +242 -61
  151. package/dist/scripts/memory-decay-tests.js +18 -52
  152. package/dist/scripts/memory-lifecycle-tests.js +657 -0
  153. package/dist/scripts/memory-lifecycle.js +196 -0
  154. package/dist/scripts/memory-metrics.js +24 -12
  155. package/dist/scripts/memory-value-report.js +474 -222
  156. package/dist/scripts/memory-value-tests.js +328 -0
  157. package/dist/scripts/metrics-report-tests.js +62 -199
  158. package/dist/scripts/model-override-e2e.js +66 -105
  159. package/dist/scripts/nightly-evidence-tests.js +64 -89
  160. package/dist/scripts/nightly-evidence.js +108 -111
  161. package/dist/scripts/nudge-digest.js +39 -28
  162. package/dist/scripts/onboarding-tests.js +63 -88
  163. package/dist/scripts/opensky-check.js +18 -13
  164. package/dist/scripts/opensky-tests.js +28 -28
  165. package/dist/scripts/persona-surface-guard-tests.js +37 -12
  166. package/dist/scripts/pnpm-dsh-closure-proof.js +2 -5
  167. package/dist/scripts/policy-anchor-359-registered-e2e.js +214 -0
  168. package/dist/scripts/price-drift-tests.js +126 -227
  169. package/dist/scripts/price-drift-watch.js +209 -253
  170. package/dist/scripts/probe-poi-tests.js +52 -45
  171. package/dist/scripts/product-metrics.js +187 -273
  172. package/dist/scripts/publish-preverify.js +47 -41
  173. package/dist/scripts/realtime-pricing-tests.js +37 -76
  174. package/dist/scripts/replay-async.js +20 -18
  175. package/dist/scripts/replay-real.js +16 -18
  176. package/dist/scripts/replay.js +52 -82
  177. package/dist/scripts/session-attach-diagnose.js +16 -12
  178. package/dist/scripts/session-attach-poc.js +34 -37
  179. package/dist/scripts/session-benchmark.js +66 -147
  180. package/dist/scripts/session-dida-live-e2e.js +151 -0
  181. package/dist/scripts/session-extract-tests.js +14 -35
  182. package/dist/scripts/session-login.js +14 -13
  183. package/dist/scripts/session-tests.js +545 -583
  184. package/dist/scripts/sf-live-benchmark.js +92 -110
  185. package/dist/scripts/sf-live-cli-tests.js +2 -9
  186. package/dist/scripts/sf-soft-score-tests.js +19 -60
  187. package/dist/scripts/sf-summary-tests.js +149 -0
  188. package/dist/scripts/sf-summary.js +466 -84
  189. package/dist/scripts/skeleton-check.js +16 -14
  190. package/dist/scripts/skeleton-integration-test.js +11 -10
  191. package/dist/scripts/skills-contract-tests.js +51 -46
  192. package/dist/scripts/smoke-session-gate-tests.js +12 -20
  193. package/dist/scripts/smoke.js +541 -422
  194. package/dist/scripts/sponsor-reuse-tests.js +262 -0
  195. package/dist/scripts/state-cli-tests.js +226 -101
  196. package/dist/scripts/state-cli.js +549 -212
  197. package/dist/scripts/static-golden-tests.js +46 -180
  198. package/dist/scripts/time-eval-tests.js +210 -192
  199. package/dist/scripts/travel-timeline-tests.js +29 -93
  200. package/dist/scripts/turn-handoff-collect-tests.js +46 -93
  201. package/dist/scripts/turn-handoff-collect.js +71 -99
  202. package/dist/scripts/turn-policy-tests.js +28 -29
  203. package/dist/scripts/typed-contract-canary.js +77 -162
  204. package/dist/scripts/tz-resolver-sanity.js +50 -0
  205. package/dist/scripts/tz-resolver-tests.js +584 -0
  206. package/dist/scripts/unified-tests.js +23 -19
  207. package/dist/scripts/visa-policy-tests.js +31 -44
  208. package/dist/scripts/weather-tests.js +121 -543
  209. package/dist/scripts/wish-channel-gate-tests.js +29 -86
  210. package/dist/scripts/write-gate-tests.js +522 -0
  211. package/dist/scripts/z3-lifecycle-fault-tests.js +188 -0
  212. package/dist/scripts/z3-lifecycle-tests.js +170 -0
  213. package/dist/scripts/z3-race-repeat-tests.js +39 -0
  214. package/dist/scripts/z3-race-tests.js +18 -12
  215. package/dist/src/artifact-gate.js +652 -221
  216. package/dist/src/backend/kernel.js +91 -0
  217. package/dist/src/backend/modules/booking-copilot.js +55 -0
  218. package/dist/src/backend/modules/booking-executor.js +124 -0
  219. package/dist/src/backend/modules/session-search.js +194 -0
  220. package/dist/src/benchmark-agent-conformance.js +296 -262
  221. package/dist/src/benchmark-environment-bridge.js +298 -413
  222. package/dist/src/benchmark-headless-child-diagnostics.js +93 -100
  223. package/dist/src/benchmark-tool-isolation.js +94 -67
  224. package/dist/src/bookable-facts.js +299 -174
  225. package/dist/src/booking-saga.js +64 -120
  226. package/dist/src/booking-surface/availability-policy.js +443 -576
  227. package/dist/src/booking-surface/cancel-refund-commission.js +379 -0
  228. package/dist/src/booking-surface/contracts.js +24 -80
  229. package/dist/src/booking-surface/dsh-planner.js +510 -281
  230. package/dist/src/booking-surface/dsh-plugin.js +17 -1
  231. package/dist/src/booking-surface/error-codes.js +82 -10
  232. package/dist/src/booking-surface/index.js +0 -3
  233. package/dist/src/booking-surface/profile.js +10 -54
  234. package/dist/src/booking-surface/recovery-chain.js +367 -0
  235. package/dist/src/booking-surface/runtime.js +765 -891
  236. package/dist/src/booking-surface/server.js +200 -251
  237. package/dist/src/booking-surface/startup.js +58 -54
  238. package/dist/src/booking-surface/validation.js +150 -218
  239. package/dist/src/bridge.js +20 -13
  240. package/dist/src/companions.js +48 -74
  241. package/dist/src/contracts.js +21 -43
  242. package/dist/src/dsh-llm.js +82 -120
  243. package/dist/src/engine.js +253 -239
  244. package/dist/src/evaluation-cadence.js +72 -209
  245. package/dist/src/evaluation-contracts.js +220 -843
  246. package/dist/src/flight-pack-adapter.js +54 -0
  247. package/dist/src/flight-pack-contract.js +2 -0
  248. package/dist/src/gotry-backend.js +70 -0
  249. package/dist/src/hotel-date-gate.js +118 -0
  250. package/dist/src/i18n.js +18 -7
  251. package/dist/src/index.js +1425 -1629
  252. package/dist/src/journey.js +132 -81
  253. package/dist/src/ledger-repair-apply.js +538 -0
  254. package/dist/src/ledger-repair-plan.js +463 -0
  255. package/dist/src/loop.js +257 -166
  256. package/dist/src/memory-capture.js +180 -32
  257. package/dist/src/memory-decay.js +30 -14
  258. package/dist/src/memory-lifecycle.js +1310 -0
  259. package/dist/src/memory-utility.js +27 -40
  260. package/dist/src/mock-llm.js +36 -61
  261. package/dist/src/model.js +81 -36
  262. package/dist/src/realtime-pricing.js +63 -72
  263. package/dist/src/slot-spec.js +84 -106
  264. package/dist/src/state-ledger.js +310 -471
  265. package/dist/src/subagent-job-id-guard.js +58 -0
  266. package/dist/src/time-anchor.js +231 -33
  267. package/dist/src/tool-packet.js +20 -8
  268. package/dist/src/travel-slots.js +58 -35
  269. package/dist/src/travel-timeline.js +44 -63
  270. package/dist/src/turn-deadline.js +121 -127
  271. package/dist/src/turn-policy.js +61 -89
  272. package/dist/src/tz-resolver.js +143 -0
  273. package/dist/src/unified.js +504 -381
  274. package/dist/src/wish-pool.js +39 -14
  275. package/dist/src/write-gate.js +495 -0
  276. package/dist/src/z3-shared.js +273 -7
  277. package/extension/README.md +4 -3
  278. package/extension/background.js +125 -14
  279. package/extension/content-bridge.js +23 -1
  280. package/extension/content-main.js +15 -4
  281. package/extension/manifest.json +16 -8
  282. package/package.json +251 -220
  283. package/ts/capabilities/agent-reach.ts +4 -4
  284. package/ts/capabilities/anything.ts +1 -1
  285. package/ts/capabilities/artifacts.ts +46 -9
  286. package/ts/capabilities/flyai.ts +156 -37
  287. package/ts/capabilities/hbcli.ts +1 -1
  288. package/ts/capabilities/incident-log.ts +88 -59
  289. package/ts/capabilities/session/adapters/ctrip-flight.ts +99 -36
  290. package/ts/capabilities/session/adapters/dida-portal.ts +250 -0
  291. package/ts/capabilities/session/adapters/rail-12306.ts +123 -24
  292. package/ts/capabilities/session/extension-bridge.ts +226 -101
  293. package/ts/capabilities/session/extension-channel.ts +22 -9
  294. package/ts/capabilities/session/wizard.ts +2 -2
  295. package/ts/capabilities/session-consent.ts +98 -14
  296. package/ts/capabilities/session-login.ts +1 -0
  297. package/ts/capabilities/session-search.ts +315 -31
  298. package/ts/dsh-runtime/vendor/README.md +8 -4
  299. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +7 -1
  300. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +5 -3
  301. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +1 -1
  302. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +1 -1
  303. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +6 -6
  304. package/ts/package.json +236 -16
  305. package/ts/scripts/map-tools-vendor-package-proof.ts +152 -31
  306. package/ts/scripts/state-cli.ts +418 -51
  307. package/ts/src/artifact-gate.ts +561 -15
  308. package/ts/src/benchmark-environment-bridge.ts +37 -20
  309. package/ts/src/bookable-facts.ts +183 -7
  310. package/ts/src/booking-surface/cancel-refund-commission.ts +488 -0
  311. package/ts/src/booking-surface/dsh-planner.ts +240 -32
  312. package/ts/src/booking-surface/dsh-plugin.js +17 -1
  313. package/ts/src/booking-surface/error-codes.ts +75 -0
  314. package/ts/src/booking-surface/recovery-chain.ts +409 -0
  315. package/ts/src/booking-surface/server.ts +84 -51
  316. package/ts/src/booking-surface/validation.ts +2 -0
  317. package/ts/src/contracts.ts +12 -2
  318. package/ts/src/dsh-llm.ts +4 -8
  319. package/ts/src/index.ts +609 -90
  320. package/ts/src/loop.ts +116 -7
  321. package/ts/src/memory-capture.ts +227 -3
  322. package/ts/src/mock-llm.ts +4 -8
  323. package/ts/src/model.ts +88 -2
  324. package/ts/src/state-ledger.ts +47 -29
  325. package/ts/src/subagent-job-id-guard.ts +72 -0
  326. package/ts/src/time-anchor.ts +217 -13
  327. package/ts/src/unified.ts +316 -54
@@ -8,45 +8,11 @@ import { ensureLedger } from '../src/state-ledger.js';
8
8
  import { BookingCopilotTaskRuntime } from '../src/booking-surface/runtime.js';
9
9
  const taskId = 'task-operation-atomicity';
10
10
  const workspace = {
11
- schemaVersion: 'booking.surface',
12
- contextRef: 'ctx-operation-atomicity',
13
- surface: 'tenant',
14
- revision: 0,
15
- locale: 'en-US',
16
- currency: 'AED',
17
- searchDraft: {},
18
- results: {
19
- status: 'idle'
20
- },
21
- visibleHotels: [],
22
- loadedOffers: [],
23
- shortlistedOfferRefs: [],
24
- capabilities: {
25
- surface: 'tenant',
26
- allowedActions: [
27
- 'search.patch',
28
- 'search.run'
29
- ]
30
- }
31
- };
32
- const base = {
33
- schemaVersion: 'booking.surface',
34
- kind: 'search.patch',
35
- actionId: 'action-operation-atomicity',
36
- contextRef: workspace.contextRef,
37
- expectedRevision: 0,
38
- reason: 'raw-reason-marker',
39
- factRefs: [
40
- 'fact:opaque'
41
- ],
42
- input: {
43
- patch: {
44
- destination: {
45
- query: 'typed-input-marker'
46
- }
47
- }
48
- }
11
+ schemaVersion: 'booking.surface', contextRef: 'ctx-operation-atomicity', surface: 'tenant', revision: 0,
12
+ locale: 'en-US', currency: 'AED', searchDraft: {}, results: { status: 'idle' }, visibleHotels: [], loadedOffers: [], shortlistedOfferRefs: [],
13
+ capabilities: { surface: 'tenant', allowedActions: ['search.patch', 'search.run'] },
49
14
  };
15
+ const base = { schemaVersion: 'booking.surface', kind: 'search.patch', actionId: 'action-operation-atomicity', contextRef: workspace.contextRef, expectedRevision: 0, reason: 'raw-reason-marker', factRefs: ['fact:opaque'], input: { patch: { destination: { query: 'typed-input-marker' } } } };
50
16
  const child = process.argv.indexOf('--child') >= 0;
51
17
  const replayMode = process.argv.indexOf('--replay') >= 0;
52
18
  const root = child ? process.argv[process.argv.indexOf('--child') + 1] : '';
@@ -57,26 +23,15 @@ if (replayMode) {
57
23
  const replayLedger = ensureLedger(replayRoot);
58
24
  const replayAction = replayVariant === 'conflict' ? action('conflict') : replayVariant === 'different' ? action('different') : base;
59
25
  try {
60
- console.log(JSON.stringify({
61
- result: 'success',
62
- event: new BookingCopilotTaskRuntime(replayLedger).issueOperation(taskId, replayAction)
63
- }));
64
- } catch (error) {
65
- console.log(JSON.stringify({
66
- result: 'error',
67
- error: error instanceof Error ? error.message : String(error)
68
- }));
26
+ console.log(JSON.stringify({ result: 'success', event: new BookingCopilotTaskRuntime(replayLedger).issueOperation(taskId, replayAction) }));
27
+ }
28
+ catch (error) {
29
+ console.log(JSON.stringify({ result: 'error', error: error instanceof Error ? error.message : String(error) }));
69
30
  }
70
31
  replayLedger.close();
71
32
  process.exit(0);
72
33
  }
73
- function waitFile(path, timeout = 30_000) {
74
- return new Promise((resolve, reject)=>{
75
- const end = Date.now() + timeout;
76
- const tick = ()=>existsSync(path) ? resolve() : Date.now() > end ? reject(new Error(`timeout:${path}`)) : setTimeout(tick, 5);
77
- tick();
78
- });
79
- }
34
+ function waitFile(path, timeout = 30_000) { return new Promise((resolve, reject) => { const end = Date.now() + timeout; const tick = () => existsSync(path) ? resolve() : Date.now() > end ? reject(new Error(`timeout:${path}`)) : setTimeout(tick, 5); tick(); }); }
80
35
  function action(which) {
81
36
  return {
82
37
  ...base,
@@ -84,18 +39,9 @@ function action(which) {
84
39
  reason: which === 'conflict' ? 'different reason' : base.reason,
85
40
  contextRef: which === 'context' ? 'ctx-other' : base.contextRef,
86
41
  expectedRevision: which === 'revision' ? 1 : base.expectedRevision,
87
- factRefs: which === 'fact-order' ? [
88
- 'fact:other',
89
- 'fact:opaque'
90
- ] : base.factRefs,
91
- input: which === 'kind' ? {} : which === 'input' ? {
92
- patch: {
93
- destination: {
94
- query: 'other'
95
- }
96
- }
97
- } : base.input,
98
- actionId: which === 'different' ? 'action-different' : base.actionId
42
+ factRefs: which === 'fact-order' ? ['fact:other', 'fact:opaque'] : base.factRefs,
43
+ input: which === 'kind' ? {} : which === 'input' ? { patch: { destination: { query: 'other' } } } : base.input,
44
+ actionId: which === 'different' ? 'action-different' : base.actionId,
99
45
  };
100
46
  }
101
47
  if (child) {
@@ -105,35 +51,29 @@ if (child) {
105
51
  let first = true;
106
52
  writeFileSync(join(root, `started-${variant}`), 'started');
107
53
  const gateEnd = Date.now() + 10_000;
108
- while(!existsSync(join(root, 'start'))){
109
- if (Date.now() > gateEnd) throw new Error('start_gate_timeout');
54
+ while (!existsSync(join(root, 'start'))) {
55
+ if (Date.now() > gateEnd)
56
+ throw new Error('start_gate_timeout');
110
57
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5);
111
58
  }
112
- if (variant !== 'left') Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100);
113
- runtime.resumeTask = (id)=>{
114
- const state = original(id);
115
- if (first && !state?.pendingAction) {
116
- first = false;
117
- writeFileSync(join(root, `ready-${variant}`), 'ready');
118
- const end = Date.now() + 10_000;
119
- while(!existsSync(join(root, 'release'))){
120
- if (Date.now() > end) throw new Error('barrier_timeout');
121
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5);
122
- }
59
+ if (variant !== 'left')
60
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 100);
61
+ runtime.resumeTask = (id) => { const state = original(id); if (first && !state?.pendingAction) {
62
+ first = false;
63
+ writeFileSync(join(root, `ready-${variant}`), 'ready');
64
+ const end = Date.now() + 10_000;
65
+ while (!existsSync(join(root, 'release'))) {
66
+ if (Date.now() > end)
67
+ throw new Error('barrier_timeout');
68
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5);
123
69
  }
124
- return state;
125
- };
70
+ } return state; };
126
71
  try {
127
72
  const event = runtime.issueOperation(taskId, action(variant));
128
- console.log(JSON.stringify({
129
- result: 'success',
130
- event
131
- }));
132
- } catch (error) {
133
- console.log(JSON.stringify({
134
- result: 'error',
135
- error: error instanceof Error ? error.message : String(error)
136
- }));
73
+ console.log(JSON.stringify({ result: 'success', event }));
74
+ }
75
+ catch (error) {
76
+ console.log(JSON.stringify({ result: 'error', error: error instanceof Error ? error.message : String(error) }));
137
77
  }
138
78
  ledger.close();
139
79
  process.exit(0);
@@ -141,88 +81,46 @@ if (child) {
141
81
  async function pair(root, left, right) {
142
82
  const tsx = fileURLToPath(new URL('../node_modules/tsx/dist/cli.mjs', import.meta.url));
143
83
  const script = fileURLToPath(import.meta.url);
144
- const ps = [
145
- left,
146
- right
147
- ].map((v)=>spawn(process.execPath, [
148
- tsx,
149
- script,
150
- '--child',
151
- root,
152
- v
153
- ], {
154
- cwd: process.cwd(),
155
- stdio: [
156
- 'ignore',
157
- 'pipe',
158
- 'pipe'
159
- ]
160
- }));
161
- const out = ps.map(()=>'');
162
- ps.forEach((p, i)=>{
163
- p.stdout.on('data', (b)=>{
164
- out[i] += b;
165
- });
166
- p.stderr.on('data', (b)=>{
167
- out[i] += b;
168
- });
169
- });
170
- await Promise.all([
171
- waitFile(join(root, `started-${left}`)),
172
- waitFile(join(root, `started-${right}`))
173
- ]);
84
+ const ps = [left, right].map((v) => spawn(process.execPath, [tsx, script, '--child', root, v], { cwd: process.cwd(), stdio: ['ignore', 'pipe', 'pipe'] }));
85
+ const out = ps.map(() => '');
86
+ ps.forEach((p, i) => { p.stdout.on('data', (b) => { out[i] += b; }); p.stderr.on('data', (b) => { out[i] += b; }); });
87
+ await Promise.all([waitFile(join(root, `started-${left}`)), waitFile(join(root, `started-${right}`))]);
174
88
  writeFileSync(join(root, 'start'), 'start');
175
89
  try {
176
- await Promise.race([
177
- waitFile(join(root, `ready-${left}`)),
178
- waitFile(join(root, `ready-${right}`))
179
- ]);
180
- } catch (error) {
181
- ps.forEach((p)=>p.kill('SIGKILL'));
90
+ await Promise.race([waitFile(join(root, `ready-${left}`)), waitFile(join(root, `ready-${right}`))]);
91
+ }
92
+ catch (error) {
93
+ ps.forEach((p) => p.kill('SIGKILL'));
182
94
  throw new Error(`workers_did_not_reach_callsite:${out.join('|')}:${error}`);
183
95
  }
184
- await new Promise((resolve)=>setTimeout(resolve, 250));
96
+ await new Promise((resolve) => setTimeout(resolve, 250));
185
97
  assert.equal(existsSync(join(root, `ready-${left}`)) && existsSync(join(root, `ready-${right}`)), false, 'both workers entered transaction before release');
186
98
  writeFileSync(join(root, 'release'), 'release');
187
99
  try {
188
- await Promise.all(ps.map((p)=>new Promise((resolve, reject)=>{
189
- const timer = setTimeout(()=>reject(new Error('worker_timeout')), 10_000);
190
- p.on('exit', (code)=>{
191
- clearTimeout(timer);
192
- code === 0 ? resolve() : reject(new Error(`worker_exit:${code}:${out.join('|')}`));
193
- });
194
- })));
195
- } finally{
196
- ps.forEach((p)=>{
197
- if (p.exitCode === null) p.kill('SIGKILL');
198
- });
100
+ await Promise.all(ps.map((p) => new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error('worker_timeout')), 10_000); p.on('exit', (code) => { clearTimeout(timer); code === 0 ? resolve() : reject(new Error(`worker_exit:${code}:${out.join('|')}`)); }); })));
101
+ }
102
+ finally {
103
+ ps.forEach((p) => { if (p.exitCode === null)
104
+ p.kill('SIGKILL'); });
199
105
  }
200
- return out.map((s)=>JSON.parse(s.trim().split('\n').at(-1)));
106
+ return out.map((s) => JSON.parse(s.trim().split('\n').at(-1)));
201
107
  }
202
108
  async function run(kind, conflictVariant = 'conflict') {
203
109
  const root = mkdtempSync(join(tmpdir(), `gotry-operation-${kind}-`));
204
- mkdirSync(root, {
205
- recursive: true
206
- });
110
+ mkdirSync(root, { recursive: true });
207
111
  const ledger = ensureLedger(root);
208
112
  const runtime = new BookingCopilotTaskRuntime(ledger);
209
- const turn = {
210
- schemaVersion: 'booking.surface',
211
- kind: 'user.turn',
212
- taskId,
213
- turnId: 'operation-anchor-turn',
214
- workspace,
215
- request: {
216
- text: 'opaque'
217
- }
218
- };
113
+ const turn = { schemaVersion: 'booking.surface', kind: 'user.turn', taskId, turnId: 'operation-anchor-turn', workspace, request: { text: 'opaque' } };
219
114
  runtime.startTask(turn);
220
115
  const result = await pair(root, kind === 'different' ? 'different' : 'left', kind === 'conflict' ? conflictVariant : 'right');
221
- const success = result.filter((r)=>r.result === 'success');
116
+ const success = result.filter((r) => r.result === 'success');
222
117
  assert.equal(success.length, kind === 'same' ? 2 : 1);
223
- if (kind === 'conflict') assert.equal(result.filter((r)=>r.error === 'action_conflict').length, 1, JSON.stringify(result));
224
- if (kind === 'different') assert.equal(result.filter((r)=>r.error === 'receipt_required').length, 1);
225
- if (kind === 'same') assert.deepEqual(success[0].event, success[1].event);
118
+ if (kind === 'conflict')
119
+ assert.equal(result.filter((r) => r.error === 'action_conflict').length, 1, JSON.stringify(result));
120
+ if (kind === 'different')
121
+ assert.equal(result.filter((r) => r.error === 'receipt_required').length, 1);
122
+ if (kind === 'same')
123
+ assert.deepEqual(success[0].event, success[1].event);
226
124
  assert.equal(ledger.db.prepare("SELECT COUNT(*) AS n FROM events WHERE kind = 'booking.copilot.action.issued'").get().n, 1);
227
125
  const durable = ledger.db.prepare("SELECT payload FROM events WHERE kind = 'booking.copilot.action.issued'").get();
228
126
  assert.ok(!/raw-reason-marker|@example|secret/i.test(durable.payload), 'action reason prose is never durable');
@@ -231,40 +129,7 @@ async function run(kind, conflictVariant = 'conflict') {
231
129
  const event = success[0].event;
232
130
  ledger.close();
233
131
  const tsx = fileURLToPath(new URL('../node_modules/tsx/dist/cli.mjs', import.meta.url));
234
- async function replayVariant(v) {
235
- const replayChild = spawn(process.execPath, [
236
- tsx,
237
- fileURLToPath(import.meta.url),
238
- '--replay',
239
- root,
240
- v
241
- ], {
242
- cwd: process.cwd(),
243
- stdio: [
244
- 'ignore',
245
- 'pipe',
246
- 'pipe'
247
- ]
248
- });
249
- let replayOutput = '';
250
- replayChild.stdout.on('data', (b)=>{
251
- replayOutput += b;
252
- });
253
- replayChild.stderr.on('data', (b)=>{
254
- replayOutput += b;
255
- });
256
- await new Promise((resolve, reject)=>{
257
- const timer = setTimeout(()=>{
258
- replayChild.kill('SIGKILL');
259
- reject(new Error('replay_timeout'));
260
- }, 10_000);
261
- replayChild.on('exit', (code)=>{
262
- clearTimeout(timer);
263
- code === 0 ? resolve() : reject(new Error(`replay_exit:${code}:${replayOutput}`));
264
- });
265
- });
266
- return JSON.parse(replayOutput.trim().split('\n').at(-1));
267
- }
132
+ async function replayVariant(v) { const replayChild = spawn(process.execPath, [tsx, fileURLToPath(import.meta.url), '--replay', root, v], { cwd: process.cwd(), stdio: ['ignore', 'pipe', 'pipe'] }); let replayOutput = ''; replayChild.stdout.on('data', (b) => { replayOutput += b; }); replayChild.stderr.on('data', (b) => { replayOutput += b; }); await new Promise((resolve, reject) => { const timer = setTimeout(() => { replayChild.kill('SIGKILL'); reject(new Error('replay_timeout')); }, 10_000); replayChild.on('exit', (code) => { clearTimeout(timer); code === 0 ? resolve() : reject(new Error(`replay_exit:${code}:${replayOutput}`)); }); }); return JSON.parse(replayOutput.trim().split('\n').at(-1)); }
268
133
  const replayResult = await replayVariant('base');
269
134
  assert.deepEqual(replayResult.event, event);
270
135
  const conflictResult = await replayVariant('conflict');
@@ -275,108 +140,44 @@ async function run(kind, conflictVariant = 'conflict') {
275
140
  assert.equal(restarted.db.prepare("SELECT COUNT(*) AS n FROM events WHERE kind = 'booking.copilot.action.issued'").get().n, 1);
276
141
  const replay = replayResult.event;
277
142
  const pending = new BookingCopilotTaskRuntime(restarted).resumeTask(taskId)?.pendingAction;
278
- assert.deepEqual(pending && {
279
- eventId: pending.eventId,
280
- sequence: pending.sequence,
281
- emittedAt: pending.emittedAt
282
- }, {
283
- eventId: replay.eventId,
284
- sequence: replay.sequence,
285
- emittedAt: replay.emittedAt
286
- });
143
+ assert.deepEqual(pending && { eventId: pending.eventId, sequence: pending.sequence, emittedAt: pending.emittedAt }, { eventId: replay.eventId, sequence: replay.sequence, emittedAt: replay.emittedAt });
287
144
  restarted.close();
288
- } else {
145
+ }
146
+ else {
289
147
  ledger.close();
290
148
  }
291
- rmSync(root, {
292
- recursive: true,
293
- force: true
294
- });
149
+ rmSync(root, { recursive: true, force: true });
295
150
  }
296
151
  if (!child) {
297
- for(let round = 0; round < 20; round++){
152
+ for (let round = 0; round < 20; round++) {
298
153
  await run('same');
299
- await run('conflict', [
300
- 'conflict',
301
- 'kind',
302
- 'context',
303
- 'revision',
304
- 'fact-order',
305
- 'input'
306
- ][round % 6]);
154
+ await run('conflict', ['conflict', 'kind', 'context', 'revision', 'fact-order', 'input'][round % 6]);
307
155
  await run('different');
308
156
  }
309
157
  const unsafeRoot = mkdtempSync(join(tmpdir(), 'gotry-operation-unsafe-'));
310
158
  const unsafeLedger = ensureLedger(unsafeRoot);
311
159
  const unsafeRuntime = new BookingCopilotTaskRuntime(unsafeLedger);
312
- unsafeRuntime.startTask({
313
- schemaVersion: 'booking.surface',
314
- kind: 'user.turn',
315
- taskId,
316
- turnId: 'unsafe-anchor-turn',
317
- workspace,
318
- request: {
319
- text: 'opaque'
320
- }
321
- });
322
- assert.throws(()=>unsafeRuntime.issueOperation(taskId, {
323
- ...base,
324
- reason: 'raw prose marker@example.invalid'
325
- }), /invalid_action|unsafe/, 'email prose is rejected before an operation is issued');
326
- assert.throws(()=>unsafeRuntime.issueOperation(taskId, {
327
- ...base,
328
- factRefs: [
329
- 'attacker@example.invalid'
330
- ]
331
- }), /invalid_action|unsafe_fact_ref/);
332
- assert.throws(()=>unsafeRuntime.issueOperation(taskId, {
333
- ...base,
334
- actionId: 'attacker@example.invalid'
335
- }), /invalid_action|unsafe_action_id/);
336
- assert.throws(()=>unsafeRuntime.issueOperation(taskId, {
337
- ...base,
338
- actionId: 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.signature'
339
- }), /invalid_action|unsafe_action_id/);
160
+ unsafeRuntime.startTask({ schemaVersion: 'booking.surface', kind: 'user.turn', taskId, turnId: 'unsafe-anchor-turn', workspace, request: { text: 'opaque' } });
161
+ assert.throws(() => unsafeRuntime.issueOperation(taskId, { ...base, reason: 'raw prose marker@example.invalid' }), /invalid_action|unsafe/, 'email prose is rejected before an operation is issued');
162
+ assert.throws(() => unsafeRuntime.issueOperation(taskId, { ...base, factRefs: ['attacker@example.invalid'] }), /invalid_action|unsafe_fact_ref/);
163
+ assert.throws(() => unsafeRuntime.issueOperation(taskId, { ...base, actionId: 'attacker@example.invalid' }), /invalid_action|unsafe_action_id/);
164
+ assert.throws(() => unsafeRuntime.issueOperation(taskId, { ...base, actionId: 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.signature' }), /invalid_action|unsafe_action_id/);
340
165
  assert.equal(unsafeLedger.countEvents(), 2);
341
166
  unsafeLedger.close();
342
- rmSync(unsafeRoot, {
343
- recursive: true,
344
- force: true
345
- });
346
- for (const field of [
347
- 'actionId',
348
- 'factRefs',
349
- 'expectedRevision'
350
- ]){
167
+ rmSync(unsafeRoot, { recursive: true, force: true });
168
+ for (const field of ['actionId', 'factRefs', 'expectedRevision']) {
351
169
  const tamperRoot = mkdtempSync(join(tmpdir(), `gotry-operation-tamper-${field}-`));
352
170
  const tamperLedger = ensureLedger(tamperRoot);
353
171
  const tamperRuntime = new BookingCopilotTaskRuntime(tamperLedger);
354
- tamperRuntime.startTask({
355
- schemaVersion: 'booking.surface',
356
- kind: 'user.turn',
357
- taskId,
358
- turnId: 'tamper-anchor-turn',
359
- workspace,
360
- request: {
361
- text: 'opaque'
362
- }
363
- });
172
+ tamperRuntime.startTask({ schemaVersion: 'booking.surface', kind: 'user.turn', taskId, turnId: 'tamper-anchor-turn', workspace, request: { text: 'opaque' } });
364
173
  tamperRuntime.issueOperation(taskId, base);
365
174
  const row = tamperLedger.db.prepare("SELECT seq, payload FROM events WHERE kind = 'booking.copilot.action.issued'").get();
366
175
  const payload = JSON.parse(row.payload);
367
- payload.action[field] = field === 'factRefs' ? [
368
- 'tampered'
369
- ] : field === 'expectedRevision' ? 99 : 'tampered-action';
176
+ payload.action[field] = field === 'factRefs' ? ['tampered'] : field === 'expectedRevision' ? 99 : 'tampered-action';
370
177
  tamperLedger.db.prepare('UPDATE events SET payload = ? WHERE seq = ?').run(JSON.stringify(payload), row.seq);
371
- assert.throws(()=>new BookingCopilotTaskRuntime(tamperLedger).resumeTask(taskId), /ledger_corrupt/);
178
+ assert.throws(() => new BookingCopilotTaskRuntime(tamperLedger).resumeTask(taskId), /ledger_corrupt/);
372
179
  tamperLedger.close();
373
- rmSync(tamperRoot, {
374
- recursive: true,
375
- force: true
376
- });
180
+ rmSync(tamperRoot, { recursive: true, force: true });
377
181
  }
378
182
  console.log('BOOKING COPILOT OPERATION LEDGER CONCURRENCY PROOF: 20 rounds atomic');
379
183
  }
380
-
381
-
382
- //# sourceURL=ts/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.ts