@danceiny/gotry 0.0.1-rc.18 → 0.0.1-rc.20

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 (176) hide show
  1. package/README.md +42 -16
  2. package/README.zh-CN.md +37 -15
  3. package/bin/gotry-bootstrap.js +309 -30
  4. package/bin/gotry-inner.js +74 -23
  5. package/bin/gotry-runtime-resolution.d.ts +1 -1
  6. package/bin/gotry-runtime-resolution.js +7 -8
  7. package/cordis.gotry-patch.yml +22 -8
  8. package/data/stations-12306-verify.json +524 -0
  9. package/dist/capabilities/agent-reach.js +4 -4
  10. package/dist/capabilities/anything.js +62 -29
  11. package/dist/capabilities/channel-health.js +103 -0
  12. package/dist/capabilities/channel-registry.js +213 -0
  13. package/dist/capabilities/doctor.js +307 -0
  14. package/dist/capabilities/effect.js +178 -5
  15. package/dist/capabilities/flyai.js +13 -0
  16. package/dist/capabilities/hbcli.js +28 -2
  17. package/dist/capabilities/session/adapters/ctrip-hotel.js +207 -0
  18. package/dist/capabilities/session/adapters/rail-12306.js +285 -0
  19. package/dist/capabilities/session/extension-bridge.js +14 -1
  20. package/dist/capabilities/session/extension-channel.js +4 -2
  21. package/dist/capabilities/session/extension-distribution.js +1 -1
  22. package/dist/capabilities/session-search.js +311 -0
  23. package/dist/capabilities/visa-policy.js +126 -0
  24. package/dist/scripts/agent-planning-turn-deadline-e2e.js +305 -0
  25. package/dist/scripts/agent-planning-turn-deadline-tests.js +281 -0
  26. package/dist/scripts/anything-tests.js +70 -21
  27. package/dist/scripts/benchmark-environment-bridge-e2e.js +139 -37
  28. package/dist/scripts/benchmark-environment-bridge-tests.js +1099 -306
  29. package/dist/scripts/booking-copilot-availability-ledger-binding-tests.js +26 -26
  30. package/dist/scripts/{booking-copilot-availability-policy-v2-tests.js → booking-copilot-availability-policy-tests.js} +115 -115
  31. package/dist/scripts/booking-copilot-crossrepo-fixture-server.js +41 -1
  32. package/dist/scripts/booking-copilot-dsh-core-proof-tests.js +75 -120
  33. package/dist/scripts/booking-copilot-dsh-planner-proof-tests.js +370 -61
  34. package/dist/scripts/booking-copilot-dsh-plugin-proof-tests.js +2 -2
  35. package/dist/scripts/booking-copilot-event-sequence-concurrency-proof-tests.js +7 -3
  36. package/dist/scripts/booking-copilot-gap-code-contract-proof-tests.js +15 -9
  37. package/dist/scripts/booking-copilot-operation-ledger-concurrency-proof-tests.js +19 -11
  38. package/dist/scripts/booking-copilot-receipt-ledger-concurrency-proof-tests.js +16 -52
  39. package/dist/scripts/booking-copilot-runtime-proof-tests.js +3953 -155
  40. package/dist/scripts/booking-copilot-server-proof-tests.js +58 -23
  41. package/dist/scripts/booking-copilot-startup-proof-tests.js +10 -119
  42. package/dist/scripts/booking-surface-contract-proof-tests.js +1154 -326
  43. package/dist/scripts/bootstrap-tests.js +113 -2
  44. package/dist/scripts/build-metrics-report.js +339 -0
  45. package/dist/scripts/channel-probe-tests.js +148 -0
  46. package/dist/scripts/channel-probe.js +252 -0
  47. package/dist/scripts/channel-registry-tests.js +262 -0
  48. package/dist/scripts/doctor-tests.js +175 -0
  49. package/dist/scripts/effect-tests.js +274 -1
  50. package/dist/scripts/extension-tests.js +129 -11
  51. package/dist/scripts/fact-gate-tests.js +91 -2
  52. package/dist/scripts/flyai-tests.js +17 -1
  53. package/dist/scripts/hbcli-e2e-tests.js +1 -3
  54. package/dist/scripts/hbcli-tests.js +38 -1
  55. package/dist/scripts/metrics-report-tests.js +288 -0
  56. package/dist/scripts/persona-surface-guard-tests.js +19 -0
  57. package/dist/scripts/session-tests.js +401 -1
  58. package/dist/scripts/smoke.js +100 -83
  59. package/dist/scripts/turn-handoff-collect-tests.js +216 -0
  60. package/dist/scripts/turn-handoff-collect.js +189 -0
  61. package/dist/scripts/turn-policy-tests.js +56 -0
  62. package/dist/scripts/typed-contract-canary.js +261 -0
  63. package/dist/scripts/visa-policy-tests.js +75 -0
  64. package/dist/scripts/wish-channel-gate-tests.js +111 -0
  65. package/dist/src/artifact-gate.js +91 -3
  66. package/dist/src/benchmark-agent-conformance.js +39 -16
  67. package/dist/src/benchmark-environment-bridge.js +316 -52
  68. package/dist/src/bookable-facts.js +62 -3
  69. package/dist/src/booking-surface/{availability-policy-v2.js → availability-policy.js} +89 -89
  70. package/dist/src/booking-surface/canonical-schema.js +8 -22
  71. package/dist/src/booking-surface/contracts.js +70 -19
  72. package/dist/src/booking-surface/dsh-planner.js +310 -177
  73. package/dist/src/booking-surface/dsh-plugin.js +3 -3
  74. package/dist/src/booking-surface/index.js +1 -5
  75. package/dist/src/booking-surface/profile.js +1 -1
  76. package/dist/src/booking-surface/runtime.js +1682 -247
  77. package/dist/src/booking-surface/server.js +371 -185
  78. package/dist/src/booking-surface/startup.js +17 -27
  79. package/dist/src/booking-surface/validation.js +270 -760
  80. package/dist/src/index.js +739 -150
  81. package/dist/src/turn-deadline.js +292 -0
  82. package/dist/src/turn-policy.js +146 -0
  83. package/dist/src/wish-pool.js +5 -0
  84. package/extension/background.js +23 -4
  85. package/extension/content-main.js +47 -9
  86. package/extension/manifest.json +27 -9
  87. package/package.json +7 -26
  88. package/schemas/booking.surface.schema.json +2593 -0
  89. package/ts/capabilities/agent-reach.ts +4 -4
  90. package/ts/capabilities/anything.ts +89 -38
  91. package/ts/capabilities/flyai.ts +21 -3
  92. package/ts/capabilities/hbcli.ts +53 -4
  93. package/ts/capabilities/session/action-cache.ts +1 -1
  94. package/ts/capabilities/session/adapters/ctrip-hotel.ts +238 -0
  95. package/ts/capabilities/session/adapters/rail-12306.ts +293 -0
  96. package/ts/capabilities/session/extension-bridge.ts +32 -2
  97. package/ts/capabilities/session/extension-channel.ts +9 -8
  98. package/ts/capabilities/session/extension-distribution.ts +3 -1
  99. package/ts/capabilities/session/health-watch.ts +1 -1
  100. package/ts/capabilities/session/read-guard.ts +1 -1
  101. package/ts/capabilities/session/wizard.ts +1 -1
  102. package/ts/capabilities/session-search.ts +323 -1
  103. package/ts/dsh-runtime/vendor/README.md +60 -0
  104. package/ts/dsh-runtime/vendor/dsh-map-tools/LICENSE +21 -0
  105. package/ts/dsh-runtime/vendor/dsh-map-tools/README.en.md +200 -0
  106. package/ts/dsh-runtime/vendor/dsh-map-tools/README.md +202 -0
  107. package/ts/dsh-runtime/vendor/dsh-map-tools/client/client.js +216 -0
  108. package/ts/dsh-runtime/vendor/dsh-map-tools/cordis.patch.yml +5 -0
  109. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/amap.js +371 -0
  110. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/nominatim.js +63 -0
  111. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/osrm.js +56 -0
  112. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/clients/photon.js +55 -0
  113. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-file.js +87 -0
  114. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config-route.js +126 -0
  115. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/config.js +16 -0
  116. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/index.js +109 -0
  117. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/settings-ns.js +27 -0
  118. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/geocode.js +127 -0
  119. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/poi.js +84 -0
  120. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/tools/routes.js +170 -0
  121. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/amap.d.ts +53 -0
  122. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/nominatim.d.ts +17 -0
  123. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/osrm.d.ts +15 -0
  124. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/clients/photon.d.ts +22 -0
  125. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-file.d.ts +33 -0
  126. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config-route.d.ts +20 -0
  127. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/config.d.ts +23 -0
  128. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/index.d.ts +18 -0
  129. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/settings-ns.d.ts +14 -0
  130. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/geocode.d.ts +11 -0
  131. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/poi.d.ts +9 -0
  132. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/tools/routes.d.ts +16 -0
  133. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types/types.d.ts +55 -0
  134. package/ts/dsh-runtime/vendor/dsh-map-tools/lib/types.js +16 -0
  135. package/ts/dsh-runtime/vendor/dsh-map-tools/package.json +91 -0
  136. package/ts/package.json +9 -0
  137. package/ts/scripts/turn-handoff-collect.ts +178 -0
  138. package/ts/src/artifact-gate.ts +82 -2
  139. package/ts/src/benchmark-agent-conformance.ts +54 -15
  140. package/ts/src/benchmark-environment-bridge.ts +234 -46
  141. package/ts/src/bookable-facts.ts +109 -5
  142. package/ts/src/booking-saga.ts +1 -1
  143. package/ts/src/booking-surface/{availability-policy-v2.ts → availability-policy.ts} +124 -125
  144. package/ts/src/booking-surface/canonical-schema.js +8 -22
  145. package/ts/src/booking-surface/contracts.ts +278 -239
  146. package/ts/src/booking-surface/dsh-planner.ts +333 -194
  147. package/ts/src/booking-surface/dsh-plugin.js +3 -3
  148. package/ts/src/booking-surface/index.ts +1 -5
  149. package/ts/src/booking-surface/profile.ts +11 -11
  150. package/ts/src/booking-surface/runtime.ts +1351 -351
  151. package/ts/src/booking-surface/server.ts +282 -175
  152. package/ts/src/booking-surface/startup.ts +36 -48
  153. package/ts/src/booking-surface/validation.ts +194 -442
  154. package/ts/src/contracts.ts +1 -1
  155. package/ts/src/index.ts +492 -172
  156. package/ts/src/loop.ts +1 -1
  157. package/ts/src/state-ledger.ts +1 -1
  158. package/ts/src/turn-deadline.ts +365 -0
  159. package/ts/src/turn-policy.ts +154 -0
  160. package/ts/src/wish-pool.ts +17 -4
  161. package/dist/scripts/agent-planning-budget-e2e.js +0 -227
  162. package/dist/scripts/agent-planning-budget-tests.js +0 -173
  163. package/dist/scripts/booking-copilot-v2-runtime-proof-tests.js +0 -3935
  164. package/dist/scripts/booking-surface-v2-contract-proof-tests.js +0 -1174
  165. package/dist/src/booking-surface/contracts-v2.js +0 -89
  166. package/dist/src/booking-surface/runtime-v2.js +0 -1771
  167. package/dist/src/booking-surface/server-v2.js +0 -334
  168. package/dist/src/booking-surface/validation-v2.js +0 -319
  169. package/dist/src/tool-budget.js +0 -136
  170. package/schemas/booking.surface.v1.schema.json +0 -927
  171. package/schemas/booking.surface.v2.schema.json +0 -61
  172. package/ts/src/booking-surface/contracts-v2.ts +0 -118
  173. package/ts/src/booking-surface/runtime-v2.ts +0 -1466
  174. package/ts/src/booking-surface/server-v2.ts +0 -247
  175. package/ts/src/booking-surface/validation-v2.ts +0 -205
  176. package/ts/src/tool-budget.ts +0 -165
@@ -1,14 +1,14 @@
1
1
  import { createHash } from 'node:crypto';
2
- export const MAX_HOTELS_PER_TASK_V2 = 5;
3
- export const MAX_OFFERS_PER_HOTEL_GENERATION_V2 = 3;
4
- export const MAX_OFFER_CHECKS_PER_HOTEL_V2 = 2;
5
- export const MAX_OFFER_QUERIES_PER_HOTEL_V2 = 2;
2
+ export const MAX_HOTELS_PER_TASK = 5;
3
+ export const MAX_OFFERS_PER_HOTEL_GENERATION = 3;
4
+ export const MAX_OFFER_CHECKS_PER_HOTEL = 2;
5
+ export const MAX_OFFER_QUERIES_PER_HOTEL = 2;
6
6
  function unique(values) {
7
7
  return [
8
8
  ...new Set(values)
9
9
  ];
10
10
  }
11
- export function assertWorkspaceLoadedOfferRefsUniqueV2(workspace) {
11
+ export function assertWorkspaceLoadedOfferRefsUnique(workspace) {
12
12
  if (workspace.loadedOffers.length !== new Set(workspace.loadedOffers.map((offer)=>offer.offerRef)).size) throw new Error('availability_duplicate_offer_ref');
13
13
  if (workspace.loadedOffers.length !== new Set(workspace.loadedOffers.map((offer)=>offer.offerVersionRef)).size) throw new Error('availability_duplicate_offer_version_ref');
14
14
  }
@@ -20,20 +20,20 @@ function stable(value) {
20
20
  stable(value[key])
21
21
  ]));
22
22
  }
23
- export function digestV2(value) {
23
+ export function digest(value) {
24
24
  return createHash('sha256').update(JSON.stringify(stable(value))).digest('hex');
25
25
  }
26
- function workspaceDigestV2(workspace) {
26
+ function workspaceDigest(workspace) {
27
27
  const { contextRef: _context, ...bound } = workspace;
28
- return digestV2(bound);
28
+ return digest(bound);
29
29
  }
30
30
  function offerRefsForHotel(workspace, hotelRef, selectedOfferRef) {
31
31
  const refs = unique(workspace.loadedOffers.filter((offer)=>offer.hotelRef === hotelRef).map((offer)=>offer.offerRef));
32
32
  if (selectedOfferRef) return unique([
33
33
  selectedOfferRef,
34
34
  ...refs
35
- ]).slice(0, MAX_OFFERS_PER_HOTEL_GENERATION_V2);
36
- if (refs.length > MAX_OFFERS_PER_HOTEL_GENERATION_V2) throw new Error('availability_offer_limit_exceeded');
35
+ ]).slice(0, MAX_OFFERS_PER_HOTEL_GENERATION);
36
+ if (refs.length > MAX_OFFERS_PER_HOTEL_GENERATION) throw new Error('availability_offer_limit_exceeded');
37
37
  return refs;
38
38
  }
39
39
  function loadedOfferVersion(workspace, offerRef, offerVersionRef) {
@@ -45,7 +45,7 @@ function legalOfferRefsForHotel(workspace, hotel, refs) {
45
45
  const loaded = workspace.loadedOffers.find((offer)=>offer.offerRef === ref && offer.hotelRef === hotel.hotelRef);
46
46
  return Boolean(loaded && !hotel.tombstonedOfferVersionRefs.includes(loaded.offerVersionRef));
47
47
  });
48
- if (legal.length > MAX_OFFERS_PER_HOTEL_GENERATION_V2) throw new Error('availability_offer_limit_exceeded');
48
+ if (legal.length > MAX_OFFERS_PER_HOTEL_GENERATION) throw new Error('availability_offer_limit_exceeded');
49
49
  return unique(legal);
50
50
  }
51
51
  function copyHotel(hotel) {
@@ -124,7 +124,7 @@ function isCriterion(value, valueCheck) {
124
124
  function isMoney(value) {
125
125
  return isPlainRecord(value) && Object.keys(value).length === 3 && typeof value.amount === 'string' && Boolean(value.amount) && typeof value.currency === 'string' && Boolean(value.currency) && typeof value.sourceFactRef === 'string' && Boolean(value.sourceFactRef);
126
126
  }
127
- function isOfferCriteriaV2(value) {
127
+ function isOfferCriteria(value) {
128
128
  if (!isPlainRecord(value)) return false;
129
129
  const allowed = [
130
130
  'roomType',
@@ -160,13 +160,13 @@ function isOfferCriteriaV2(value) {
160
160
  }
161
161
  function bindCriteria(next, criteriaDigest, criteria, required = false) {
162
162
  if (criteria !== undefined) {
163
- if (!isOfferCriteriaV2(criteria) || digestV2(criteria) !== criteriaDigest) throw new Error('availability_criteria_invalid');
163
+ if (!isOfferCriteria(criteria) || digest(criteria) !== criteriaDigest) throw new Error('availability_criteria_invalid');
164
164
  if (next.criteriaDigest !== undefined && next.criteriaDigest !== criteriaDigest) throw new Error('availability_criteria_changed');
165
- if (next.criteria && digestV2(next.criteria) !== criteriaDigest) throw new Error('availability_criteria_changed');
165
+ if (next.criteria && digest(next.criteria) !== criteriaDigest) throw new Error('availability_criteria_changed');
166
166
  next.criteria = structuredClone(criteria);
167
167
  next.criteriaDigest = criteriaDigest;
168
168
  } else if (required && !next.criteria) throw new Error('availability_criteria_required');
169
- else if (next.criteria && next.criteriaDigest !== digestV2(next.criteria)) throw new Error('availability_criteria_mismatch');
169
+ else if (next.criteria && next.criteriaDigest !== digest(next.criteria)) throw new Error('availability_criteria_mismatch');
170
170
  else if (!next.criteria && criteriaDigest) {
171
171
  if (next.criteriaDigest !== undefined && next.criteriaDigest !== criteriaDigest) throw new Error('availability_criteria_changed');
172
172
  next.criteriaDigest = criteriaDigest;
@@ -184,7 +184,7 @@ function terminalFor(state) {
184
184
  reason: 'confirmed',
185
185
  evidence: 'conclusive'
186
186
  };
187
- if (hotels.some((hotel)=>hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL_V2 && (hotel.status === 'active' || hotel.status === 'unvisited' || hotel.freshOffersRequired && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL_V2))) return undefined;
187
+ if (hotels.some((hotel)=>hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL && (hotel.status === 'active' || hotel.status === 'unvisited' || hotel.freshOffersRequired && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL))) return undefined;
188
188
  const conclusive = hotels.every((hotel)=>hotel.status === 'negative');
189
189
  return {
190
190
  code: conclusive ? 'availability_exhausted_complete' : 'availability_exhausted_inconclusive',
@@ -224,8 +224,8 @@ function phaseForActiveHotel(state) {
224
224
  const active = state.hotels[state.hotelRefs[state.activeHotelOrdinal] ?? ''];
225
225
  return active?.status === 'active' && active.currentGeneration?.valid && active.currentOfferRefs.length > 0 && !active.freshOffersRequired ? 'need_check' : 'need_offers';
226
226
  }
227
- export function createAvailabilityPolicyV2(workspace) {
228
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
227
+ export function createAvailabilityPolicy(workspace) {
228
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
229
229
  return {
230
230
  initialized: false,
231
231
  recoveryStarted: false,
@@ -237,11 +237,11 @@ export function createAvailabilityPolicyV2(workspace) {
237
237
  queryReservations: []
238
238
  };
239
239
  }
240
- export function recordVisibleHotelsV2(state, _workspace) {
240
+ export function recordVisibleHotels(state, _workspace) {
241
241
  return copyState(state);
242
242
  }
243
- export function recordObservedOffersQueryV2(state, hotelRefs, criteriaDigest, workspace, receipt, sourceActionId, receiptDigest, criteria) {
244
- if (workspace) assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
243
+ export function recordObservedOffersQuery(state, hotelRefs, criteriaDigest, workspace, receipt, sourceActionId, receiptDigest, criteria) {
244
+ if (workspace) assertWorkspaceLoadedOfferRefsUnique(workspace);
245
245
  if (state.recoveryStarted) return copyState(state);
246
246
  const next = copyState(state);
247
247
  if (!workspace || !receipt) return next;
@@ -257,12 +257,12 @@ export function recordObservedOffersQueryV2(state, hotelRefs, criteriaDigest, wo
257
257
  delete next.criteria;
258
258
  delete next.criteriaDigest;
259
259
  bindCriteria(next, criteriaDigest, criteria);
260
- if (!sourceActionId || sourceActionId !== receipt.actionId || !receiptDigest || receiptDigest !== digestV2(receipt)) throw new Error('availability_query_provenance_mismatch');
260
+ if (!sourceActionId || sourceActionId !== receipt.actionId || !receiptDigest || receiptDigest !== digest(receipt)) throw new Error('availability_query_provenance_mismatch');
261
261
  next.lastQueryHotelRefs = [
262
262
  ...new Set(hotelRefs)
263
263
  ];
264
264
  next.lastQueryCriteriaDigest = criteriaDigest || undefined;
265
- next.lastQueryOfferHotels = validateOffersReceiptWorkspaceV2(receipt, workspace, hotelRefs);
265
+ next.lastQueryOfferHotels = validateOffersReceiptWorkspace(receipt, workspace, hotelRefs);
266
266
  next.lastQuerySourceActionId = sourceActionId;
267
267
  next.lastQuerySourceReceiptDigest = receiptDigest;
268
268
  next.lastQueryWorkspaceRevision = workspace.revision;
@@ -272,8 +272,8 @@ export function recordObservedOffersQueryV2(state, hotelRefs, criteriaDigest, wo
272
272
  }
273
273
  return next;
274
274
  }
275
- export function validateOffersReceiptWorkspaceV2(receipt, workspace, hotelRefs) {
276
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
275
+ export function validateOffersReceiptWorkspace(receipt, workspace, hotelRefs) {
276
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
277
277
  if (receipt.observation.kind !== 'offers.state') throw new Error('availability_offers_observation_required');
278
278
  const requested = unique(hotelRefs);
279
279
  if (!sameSet(receipt.observation.hotelRefs, requested)) throw new Error('availability_offers_hotel_mismatch');
@@ -304,14 +304,14 @@ export function validateOffersReceiptWorkspaceV2(receipt, workspace, hotelRefs)
304
304
  function sameSet(a, b) {
305
305
  return a.length === b.length && unique(a).sort().every((value, index)=>value === unique(b).sort()[index]);
306
306
  }
307
- export function recordOffersQueryIssuedV2(state, hotelRefs, workspace, actionId, criteriaDigest = '', criteria) {
308
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
307
+ export function recordOffersQueryIssued(state, hotelRefs, workspace, actionId, criteriaDigest = '', criteria) {
308
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
309
309
  const next = copyState(state);
310
310
  const requested = unique(hotelRefs);
311
- if (!requested.length || requested.length > MAX_HOTELS_PER_TASK_V2) throw new Error('availability_hotel_limit_exceeded');
311
+ if (!requested.length || requested.length > MAX_HOTELS_PER_TASK) throw new Error('availability_hotel_limit_exceeded');
312
312
  if (!state.recoveryStarted) throw new Error('availability_recovery_not_started');
313
313
  if (state.terminal) {
314
- if (requested.some((ref)=>state.hotels[ref]?.offerQueriesIssued >= MAX_OFFER_QUERIES_PER_HOTEL_V2)) throw new Error('availability_offer_query_limit_reached');
314
+ if (requested.some((ref)=>state.hotels[ref]?.offerQueriesIssued >= MAX_OFFER_QUERIES_PER_HOTEL)) throw new Error('availability_offer_query_limit_reached');
315
315
  throw new Error('availability_terminal');
316
316
  }
317
317
  if (requested.some((ref)=>!next.hotels[ref])) throw new Error('availability_hotel_unknown');
@@ -324,7 +324,7 @@ export function recordOffersQueryIssuedV2(state, hotelRefs, workspace, actionId,
324
324
  }
325
325
  for (const hotelRef of requested){
326
326
  const hotel = next.hotels[hotelRef];
327
- if (hotel.offerQueriesIssued >= MAX_OFFER_QUERIES_PER_HOTEL_V2) throw new Error('availability_offer_query_limit_reached');
327
+ if (hotel.offerQueriesIssued >= MAX_OFFER_QUERIES_PER_HOTEL) throw new Error('availability_offer_query_limit_reached');
328
328
  hotel.offerQueriesIssued += 1;
329
329
  }
330
330
  next.queryReservations.push({
@@ -338,21 +338,21 @@ export function recordOffersQueryIssuedV2(state, hotelRefs, workspace, actionId,
338
338
  next.initialized = true;
339
339
  return next;
340
340
  }
341
- export function recordOffersGenerationV2(state, hotelRefs, workspace, actionId, receiptDigest, receipt, criteriaDigest = '', criteria) {
342
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
341
+ export function recordOffersGeneration(state, hotelRefs, workspace, actionId, receiptDigest, receipt, criteriaDigest = '', criteria) {
342
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
343
343
  if (!state.recoveryStarted) return copyState(state);
344
344
  if (state.terminal) throw new Error('availability_terminal');
345
345
  const next = copyState(state);
346
346
  const requested = unique(hotelRefs);
347
- if (!requested.length || requested.length > MAX_HOTELS_PER_TASK_V2) throw new Error('availability_hotel_limit_exceeded');
347
+ if (!requested.length || requested.length > MAX_HOTELS_PER_TASK) throw new Error('availability_hotel_limit_exceeded');
348
348
  const reservation = next.queryReservations.find((query)=>query.actionId === actionId);
349
349
  if (!reservation || !sameSet(reservation.hotelRefs, requested)) throw new Error('availability_query_not_reserved');
350
350
  if (receipt.actionId !== actionId) throw new Error('availability_query_receipt_mismatch');
351
- if (receiptDigest !== digestV2(receipt)) throw new Error('availability_receipt_digest_mismatch');
351
+ if (receiptDigest !== digest(receipt)) throw new Error('availability_receipt_digest_mismatch');
352
352
  if (requested.some((ref)=>!next.hotels[ref])) throw new Error('availability_hotel_unknown');
353
353
  else if ((requested.length !== 1 || next.hotelRefs[next.activeHotelOrdinal] !== requested[0]) && (next.attempts.length > 0 || Object.values(next.hotels).some((hotel)=>hotel.generationNo > 0))) throw new Error('availability_hotel_not_active');
354
354
  bindCriteria(next, criteriaDigest, criteria);
355
- if (receipt.observation.kind === 'offers.state') validateOffersReceiptWorkspaceV2(receipt, workspace, requested);
355
+ if (receipt.observation.kind === 'offers.state') validateOffersReceiptWorkspace(receipt, workspace, requested);
356
356
  for (const hotelRef of requested){
357
357
  const hotel = next.hotels[hotelRef];
358
358
  const partial = receipt.status === 'changed' || receipt.status === 'partial' || receipt.status === 'failed' || receipt.status === 'stale' || receipt.resultContract.outcome === 'partial' || receipt.resultContract.outcome === 'complete' && !receipt.resultContract.hardCriteriaMet || Boolean(receipt.resultContract.blockers.length) || Boolean(receipt.resultContract.gapCodes.length) || Boolean(receipt.observation.kind === 'gap' || receipt.observation.kind === 'offers.state' && receipt.observation.gapCodes?.length);
@@ -368,18 +368,18 @@ export function recordOffersGenerationV2(state, hotelRefs, workspace, actionId,
368
368
  hotel.invalidatedOfferRefs = [
369
369
  ...hotel.currentGeneration?.orderedOfferRefs ?? []
370
370
  ];
371
- hotel.freshOffersRequired = hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL_V2 && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL_V2;
371
+ hotel.freshOffersRequired = hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL;
372
372
  hotel.status = 'inconclusive';
373
373
  hotel.lastEvidence = 'inconclusive';
374
374
  continue;
375
375
  }
376
376
  const filteredAllCandidates = candidateRefs.length > 0 && refs.length === 0;
377
- const noLegalRefsNeedsRefresh = filteredAllCandidates && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL_V2;
377
+ const noLegalRefsNeedsRefresh = filteredAllCandidates && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL;
378
378
  hotel.generationNo += 1;
379
379
  hotel.generation = hotel.generationNo;
380
380
  hotel.currentOfferRefs = partial || noLegalRefsNeedsRefresh ? [] : refs;
381
381
  hotel.invalidatedOfferRefs = partial || noLegalRefsNeedsRefresh ? candidateRefs : [];
382
- hotel.freshOffersRequired = (partial || noLegalRefsNeedsRefresh) && hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL_V2 && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL_V2;
382
+ hotel.freshOffersRequired = (partial || noLegalRefsNeedsRefresh) && hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL;
383
383
  hotel.status = partial || noLegalRefsNeedsRefresh ? 'inconclusive' : refs.length ? 'active' : 'negative';
384
384
  hotel.lastEvidence = partial || noLegalRefsNeedsRefresh ? 'inconclusive' : refs.length ? 'none' : 'unavailable';
385
385
  hotel.currentGeneration = {
@@ -390,7 +390,7 @@ export function recordOffersGenerationV2(state, hotelRefs, workspace, actionId,
390
390
  receiptDigest,
391
391
  workspaceRevision: workspace.revision
392
392
  },
393
- offerSetDigest: digestV2(refs),
393
+ offerSetDigest: digest(refs),
394
394
  orderedOfferRefs: refs,
395
395
  evidence: partial ? 'partial' : 'complete',
396
396
  valid: refs.length > 0 && !partial
@@ -412,8 +412,8 @@ export function recordOffersGenerationV2(state, hotelRefs, workspace, actionId,
412
412
  delete next.terminal;
413
413
  return withTerminal(next);
414
414
  }
415
- export function canIssueOfferCheckV2(state, workspace, offerRef, offerVersionRef) {
416
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
415
+ export function canIssueOfferCheck(state, workspace, offerRef, offerVersionRef) {
416
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
417
417
  if (!state.recoveryStarted) {
418
418
  const loaded = loadedOfferVersion(workspace, offerRef, offerVersionRef);
419
419
  return loaded ? {
@@ -458,7 +458,7 @@ export function canIssueOfferCheckV2(state, workspace, offerRef, offerVersionRef
458
458
  ok: false,
459
459
  code: 'generation_invalid'
460
460
  };
461
- if (hotel.checksIssued >= MAX_OFFER_CHECKS_PER_HOTEL_V2) return {
461
+ if (hotel.checksIssued >= MAX_OFFER_CHECKS_PER_HOTEL) return {
462
462
  ok: false,
463
463
  code: 'hotel_check_limit_reached'
464
464
  };
@@ -471,8 +471,8 @@ export function canIssueOfferCheckV2(state, workspace, offerRef, offerVersionRef
471
471
  generation: hotel.generationNo
472
472
  };
473
473
  }
474
- function startRecoveryAtOfferV2(state, workspace, offerRef, actionId) {
475
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
474
+ function startRecoveryAtOffer(state, workspace, offerRef, actionId) {
475
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
476
476
  const loaded = workspace.loadedOffers.find((offer)=>offer.offerRef === offerRef);
477
477
  if (!loaded) return copyState(state);
478
478
  const shortlistHotels = workspace.shortlistedOfferRefs.map((ref)=>workspace.loadedOffers.find((offer)=>offer.offerRef === ref)?.hotelRef ?? state.lastQueryOfferHotels?.[ref]).map((ref, index)=>{
@@ -483,12 +483,12 @@ function startRecoveryAtOfferV2(state, workspace, offerRef, actionId) {
483
483
  const candidates = unique([
484
484
  loaded.hotelRef,
485
485
  ...fallbackHotels
486
- ]).slice(0, MAX_HOTELS_PER_TASK_V2);
486
+ ]).slice(0, MAX_HOTELS_PER_TASK);
487
487
  const next = copyState(state);
488
488
  next.recoveryStarted = true;
489
489
  next.recoveryId = `recovery:${actionId}`;
490
490
  next.hotelRefs = candidates;
491
- next.candidateSetDigest = digestV2(candidates);
491
+ next.candidateSetDigest = digest(candidates);
492
492
  next.hotels = Object.fromEntries(candidates.map((ref)=>[
493
493
  ref,
494
494
  newHotel(ref)
@@ -499,12 +499,12 @@ function startRecoveryAtOfferV2(state, workspace, offerRef, actionId) {
499
499
  const mapped = state.lastQueryOfferHotels?.[offerRef] === loaded.hotelRef && state.lastQueryWorkspaceRevision === workspace.revision && Boolean(state.lastQuerySourceActionId && state.lastQuerySourceReceiptDigest) && sameSet(mappedRefs, currentRefs);
500
500
  if (mapped && state.criteria) {
501
501
  next.criteria = structuredClone(state.criteria);
502
- next.criteriaDigest = digestV2(next.criteria);
502
+ next.criteriaDigest = digest(next.criteria);
503
503
  }
504
504
  const refs = mapped && state.lastQueryOfferHotels ? unique([
505
505
  offerRef,
506
506
  ...mappedRefs
507
- ]).slice(0, MAX_OFFERS_PER_HOTEL_GENERATION_V2) : offerRefsForHotel(workspace, loaded.hotelRef, offerRef);
507
+ ]).slice(0, MAX_OFFERS_PER_HOTEL_GENERATION) : offerRefsForHotel(workspace, loaded.hotelRef, offerRef);
508
508
  const source = mapped ? {
509
509
  kind: 'query_receipt',
510
510
  actionId: state.lastQuerySourceActionId,
@@ -512,7 +512,7 @@ function startRecoveryAtOfferV2(state, workspace, offerRef, actionId) {
512
512
  workspaceRevision: state.lastQueryWorkspaceRevision
513
513
  } : {
514
514
  kind: 'workspace_snapshot',
515
- workspaceDigest: workspaceDigestV2(workspace),
515
+ workspaceDigest: workspaceDigest(workspace),
516
516
  workspaceRevision: workspace.revision
517
517
  };
518
518
  nextHotel.generationNo = 1;
@@ -522,7 +522,7 @@ function startRecoveryAtOfferV2(state, workspace, offerRef, actionId) {
522
522
  nextHotel.currentGeneration = {
523
523
  generationId: `${loaded.hotelRef}:generation:1`,
524
524
  source,
525
- offerSetDigest: digestV2(refs),
525
+ offerSetDigest: digest(refs),
526
526
  orderedOfferRefs: refs,
527
527
  evidence: 'complete',
528
528
  valid: refs.length > 0
@@ -531,15 +531,15 @@ function startRecoveryAtOfferV2(state, workspace, offerRef, actionId) {
531
531
  next.availabilityPhase = 'need_check';
532
532
  return next;
533
533
  }
534
- export function recordOfferCheckIssuedV2(state, workspace, offerRef, offerVersionRef, actionId = `offer-check-${offerRef}-${state.attempts.length + 1}`) {
535
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
534
+ export function recordOfferCheckIssued(state, workspace, offerRef, offerVersionRef, actionId = `offer-check-${offerRef}-${state.attempts.length + 1}`) {
535
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
536
536
  if (state.terminal) throw new Error('availability_terminal');
537
537
  if (!state.recoveryStarted) {
538
538
  if (!loadedOfferVersion(workspace, offerRef, offerVersionRef)) throw new Error('availability_offer_not_loaded');
539
- const started = startRecoveryAtOfferV2(state, workspace, offerRef, actionId);
540
- return recordOfferCheckIssuedV2(started, workspace, offerRef, offerVersionRef, actionId);
539
+ const started = startRecoveryAtOffer(state, workspace, offerRef, actionId);
540
+ return recordOfferCheckIssued(started, workspace, offerRef, offerVersionRef, actionId);
541
541
  }
542
- const decision = canIssueOfferCheckV2(state, workspace, offerRef, offerVersionRef);
542
+ const decision = canIssueOfferCheck(state, workspace, offerRef, offerVersionRef);
543
543
  if (!decision.ok) throw new Error(`availability_${decision.code}`);
544
544
  const next = copyState(state);
545
545
  const hotel = next.hotels[decision.hotelRef];
@@ -558,21 +558,21 @@ export function recordOfferCheckIssuedV2(state, workspace, offerRef, offerVersio
558
558
  next.availabilityPhase = 'waiting_check';
559
559
  return next;
560
560
  }
561
- export function reduceAvailabilityActionV2(state, workspace, action) {
561
+ export function reduceAvailabilityAction(state, workspace, action) {
562
562
  if (action.kind === 'offers.query') {
563
- if (!isOfferCriteriaV2(action.input.criteria) && (!state.criteria || !isOfferCriteriaV2(state.criteria))) throw new Error('availability_criteria_required');
564
- if (!isOfferCriteriaV2(action.input.criteria) && state.recoveryStarted) throw new Error('availability_criteria_required');
565
- if (!isOfferCriteriaV2(action.input.criteria)) throw new Error('availability_criteria_required');
566
- const criteriaDigest = digestV2(action.input.criteria);
567
- let next = recordObservedOffersQueryV2(state, action.input.hotelRefs, criteriaDigest);
568
- if (state.recoveryStarted) next = recordOffersQueryIssuedV2(next, action.input.hotelRefs, workspace, action.actionId, criteriaDigest, action.input.criteria);
563
+ if (!isOfferCriteria(action.input.criteria) && (!state.criteria || !isOfferCriteria(state.criteria))) throw new Error('availability_criteria_required');
564
+ if (!isOfferCriteria(action.input.criteria) && state.recoveryStarted) throw new Error('availability_criteria_required');
565
+ if (!isOfferCriteria(action.input.criteria)) throw new Error('availability_criteria_required');
566
+ const criteriaDigest = digest(action.input.criteria);
567
+ let next = recordObservedOffersQuery(state, action.input.hotelRefs, criteriaDigest);
568
+ if (state.recoveryStarted) next = recordOffersQueryIssued(next, action.input.hotelRefs, workspace, action.actionId, criteriaDigest, action.input.criteria);
569
569
  return next;
570
570
  }
571
- if (action.kind === 'offer.check') return recordOfferCheckIssuedV2(state, workspace, action.input.offerRef, action.input.offerVersionRef, action.actionId);
571
+ if (action.kind === 'offer.check') return recordOfferCheckIssued(state, workspace, action.input.offerRef, action.input.offerVersionRef, action.actionId);
572
572
  return copyState(state);
573
573
  }
574
- export function recordOfferCheckReceiptV2(state, workspace, receipt, actionId, offerRef, offerVersionRef, expectedRevision) {
575
- assertWorkspaceLoadedOfferRefsUniqueV2(workspace);
574
+ export function recordOfferCheckReceipt(state, workspace, receipt, actionId, offerRef, offerVersionRef, expectedRevision) {
575
+ assertWorkspaceLoadedOfferRefsUnique(workspace);
576
576
  if (!state.recoveryStarted) return copyState(state);
577
577
  const attempt = state.attempts.find((candidate)=>candidate.actionId === actionId);
578
578
  if (!attempt) throw new Error('availability_attempt_unknown');
@@ -642,7 +642,7 @@ export function recordOfferCheckReceiptV2(state, workspace, receipt, actionId, o
642
642
  ...hotel.currentGeneration.orderedOfferRefs
643
643
  ];
644
644
  hotel.currentOfferRefs = [];
645
- hotel.freshOffersRequired = hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL_V2 && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL_V2;
645
+ hotel.freshOffersRequired = hotel.checksIssued < MAX_OFFER_CHECKS_PER_HOTEL && hotel.offerQueriesIssued < MAX_OFFER_QUERIES_PER_HOTEL;
646
646
  hotel.status = completeNegative ? 'negative' : 'inconclusive';
647
647
  hotel.lastEvidence = completeNegative ? 'unavailable' : 'inconclusive';
648
648
  const currentOrdinal = next.hotelRefs.indexOf(attempt.hotelRef);
@@ -654,24 +654,24 @@ export function recordOfferCheckReceiptV2(state, workspace, receipt, actionId, o
654
654
  next.availabilityPhase = phaseForActiveHotel(next);
655
655
  return withTerminal(next);
656
656
  }
657
- export function reduceAvailabilityReceiptV2(state, workspace, receipt, action) {
658
- let next = recordVisibleHotelsV2(state, workspace);
657
+ export function reduceAvailabilityReceipt(state, workspace, receipt, action) {
658
+ let next = recordVisibleHotels(state, workspace);
659
659
  if (action.kind === 'offers.query' && !state.recoveryStarted) {
660
- if (!isOfferCriteriaV2(action.input.criteria)) throw new Error('availability_criteria_required');
661
- next = recordObservedOffersQueryV2(next, action.input.hotelRefs, digestV2(action.input.criteria), workspace, receipt, action.actionId, digestV2(receipt), action.input.criteria);
660
+ if (!isOfferCriteria(action.input.criteria)) throw new Error('availability_criteria_required');
661
+ next = recordObservedOffersQuery(next, action.input.hotelRefs, digest(action.input.criteria), workspace, receipt, action.actionId, digest(receipt), action.input.criteria);
662
662
  } else if (action.kind === 'offers.query' && state.recoveryStarted) {
663
- if (!isOfferCriteriaV2(action.input.criteria)) throw new Error('availability_criteria_required');
664
- next = recordOffersGenerationV2(next, action.input.hotelRefs, workspace, action.actionId, digestV2(receipt), receipt, state.criteriaDigest ?? '', action.input.criteria);
663
+ if (!isOfferCriteria(action.input.criteria)) throw new Error('availability_criteria_required');
664
+ next = recordOffersGeneration(next, action.input.hotelRefs, workspace, action.actionId, digest(receipt), receipt, state.criteriaDigest ?? '', action.input.criteria);
665
665
  } else if (action.kind === 'offer.check') {
666
666
  if (action.expectedRevision === undefined) throw new Error('availability_expected_revision_missing');
667
- next = recordOfferCheckReceiptV2(next, workspace, receipt, action.actionId, action.input.offerRef, action.input.offerVersionRef, action.expectedRevision);
667
+ next = recordOfferCheckReceipt(next, workspace, receipt, action.actionId, action.input.offerRef, action.input.offerVersionRef, action.expectedRevision);
668
668
  }
669
669
  return next;
670
670
  }
671
- export function availabilityPolicyIsTerminalV2(state) {
671
+ export function availabilityPolicyIsTerminal(state) {
672
672
  return Boolean(state.terminal);
673
673
  }
674
- export function availabilityPolicyResultV2(state) {
674
+ export function availabilityPolicyResult(state) {
675
675
  return state.terminal ? {
676
676
  ...state.terminal,
677
677
  hotelRefs: [
@@ -679,7 +679,7 @@ export function availabilityPolicyResultV2(state) {
679
679
  ]
680
680
  } : undefined;
681
681
  }
682
- export function validateAvailabilityPolicyV2(state) {
682
+ export function validateAvailabilityPolicy(state) {
683
683
  try {
684
684
  if (!state || typeof state.initialized !== 'boolean' || typeof state.recoveryStarted !== 'boolean') return false;
685
685
  if (state.recoveryId !== undefined && (typeof state.recoveryId !== 'string' || !state.recoveryId)) return false;
@@ -692,7 +692,7 @@ export function validateAvailabilityPolicyV2(state) {
692
692
  'waiting_check',
693
693
  'terminal'
694
694
  ].includes(state.availabilityPhase)) return false;
695
- if (!Number.isSafeInteger(state.activeHotelOrdinal) || !Array.isArray(state.hotelRefs) || state.hotelRefs.length > MAX_HOTELS_PER_TASK_V2) return false;
695
+ if (!Number.isSafeInteger(state.activeHotelOrdinal) || !Array.isArray(state.hotelRefs) || state.hotelRefs.length > MAX_HOTELS_PER_TASK) return false;
696
696
  if (state.hotelRefs.some((ref)=>typeof ref !== 'string' || !ref) || new Set(state.hotelRefs).size !== state.hotelRefs.length) return false;
697
697
  if (state.hotelRefs.length && (state.activeHotelOrdinal < 0 || state.activeHotelOrdinal >= state.hotelRefs.length) || !state.hotelRefs.length && state.activeHotelOrdinal !== 0) return false;
698
698
  if (!state.hotels || typeof state.hotels !== 'object' || Object.keys(state.hotels).sort().join('\0') !== [
@@ -702,7 +702,7 @@ export function validateAvailabilityPolicyV2(state) {
702
702
  if (!state.recoveryStarted) {
703
703
  if (state.recoveryId !== undefined || state.candidateSetDigest !== undefined || state.hotelRefs.length || Object.keys(state.hotels).length || state.attempts.length || state.queryReservations.length || state.terminal !== undefined) return false;
704
704
  if (state.criteria !== undefined || state.criteriaDigest !== undefined) {
705
- if (!isOfferCriteriaV2(state.criteria) || !state.criteriaDigest || state.criteriaDigest !== digestV2(state.criteria)) return false;
705
+ if (!isOfferCriteria(state.criteria) || !state.criteriaDigest || state.criteriaDigest !== digest(state.criteria)) return false;
706
706
  }
707
707
  if (state.lastQueryCriteriaDigest !== undefined && state.lastQueryCriteriaDigest !== state.criteriaDigest) return false;
708
708
  if (state.lastQueryHotelRefs !== undefined && (!Array.isArray(state.lastQueryHotelRefs) || new Set(state.lastQueryHotelRefs).size !== state.lastQueryHotelRefs.length || state.lastQueryHotelRefs.some((ref)=>typeof ref !== 'string' || !ref))) return false;
@@ -711,8 +711,8 @@ export function validateAvailabilityPolicyV2(state) {
711
711
  if (state.lastQuerySourceReceiptDigest !== undefined && state.lastQuerySourceActionId === undefined) return false;
712
712
  return state.initialized === false && state.availabilityPhase === 'need_offers';
713
713
  }
714
- if (!state.initialized || !state.recoveryId || !state.candidateSetDigest || state.candidateSetDigest !== digestV2(state.hotelRefs)) return false;
715
- const criteriaBound = isOfferCriteriaV2(state.criteria) && Boolean(state.criteriaDigest) && state.criteriaDigest === digestV2(state.criteria);
714
+ if (!state.initialized || !state.recoveryId || !state.candidateSetDigest || state.candidateSetDigest !== digest(state.hotelRefs)) return false;
715
+ const criteriaBound = isOfferCriteria(state.criteria) && Boolean(state.criteriaDigest) && state.criteriaDigest === digest(state.criteria);
716
716
  const manualCheckWorkspaceSnapshot = state.attempts.length > 0 && state.attempts.every((attempt)=>state.hotels[attempt.hotelRef]?.currentGeneration?.source.kind === 'workspace_snapshot');
717
717
  const manualCheckMayBindCriteria = !state.criteria && !state.criteriaDigest && state.queryReservations.length === 0 && manualCheckWorkspaceSnapshot && ([
718
718
  'waiting_check',
@@ -748,20 +748,20 @@ export function validateAvailabilityPolicyV2(state) {
748
748
  hotel.generation,
749
749
  hotel.checkCount
750
750
  ].every(Number.isSafeInteger)) return false;
751
- if (hotel.checksIssued < 0 || hotel.checksIssued > MAX_OFFER_CHECKS_PER_HOTEL_V2 || hotel.offerQueriesIssued < 0 || hotel.offerQueriesIssued > MAX_OFFER_QUERIES_PER_HOTEL_V2 || hotel.generationNo < 0 || hotel.generation !== hotel.generationNo || hotel.checkCount !== hotel.checksIssued) return false;
751
+ if (hotel.checksIssued < 0 || hotel.checksIssued > MAX_OFFER_CHECKS_PER_HOTEL || hotel.offerQueriesIssued < 0 || hotel.offerQueriesIssued > MAX_OFFER_QUERIES_PER_HOTEL || hotel.generationNo < 0 || hotel.generation !== hotel.generationNo || hotel.checkCount !== hotel.checksIssued) return false;
752
752
  if (typeof hotel.freshOffersRequired !== 'boolean' || !Array.isArray(hotel.currentOfferRefs) || !Array.isArray(hotel.invalidatedOfferRefs) || !Array.isArray(hotel.tombstonedOfferRefs) || !Array.isArray(hotel.tombstonedOfferVersionRefs)) return false;
753
753
  if (hotel.currentOfferRefs.some((offer)=>typeof offer !== 'string' || !offer) || hotel.invalidatedOfferRefs.some((offer)=>typeof offer !== 'string' || !offer) || hotel.tombstonedOfferRefs.some((offer)=>typeof offer !== 'string' || !offer) || hotel.tombstonedOfferVersionRefs.some((offer)=>typeof offer !== 'string' || !offer)) return false;
754
- if (new Set(hotel.currentOfferRefs).size !== hotel.currentOfferRefs.length || new Set(hotel.invalidatedOfferRefs).size !== hotel.invalidatedOfferRefs.length || new Set(hotel.tombstonedOfferRefs).size !== hotel.tombstonedOfferRefs.length || new Set(hotel.tombstonedOfferVersionRefs).size !== hotel.tombstonedOfferVersionRefs.length || hotel.currentOfferRefs.length > MAX_OFFERS_PER_HOTEL_GENERATION_V2 || hotel.invalidatedOfferRefs.length > MAX_OFFERS_PER_HOTEL_GENERATION_V2 || hotel.currentOfferRefs.some((offer)=>hotel.invalidatedOfferRefs.includes(offer) || hotel.tombstonedOfferRefs.includes(offer))) return false;
754
+ if (new Set(hotel.currentOfferRefs).size !== hotel.currentOfferRefs.length || new Set(hotel.invalidatedOfferRefs).size !== hotel.invalidatedOfferRefs.length || new Set(hotel.tombstonedOfferRefs).size !== hotel.tombstonedOfferRefs.length || new Set(hotel.tombstonedOfferVersionRefs).size !== hotel.tombstonedOfferVersionRefs.length || hotel.currentOfferRefs.length > MAX_OFFERS_PER_HOTEL_GENERATION || hotel.invalidatedOfferRefs.length > MAX_OFFERS_PER_HOTEL_GENERATION || hotel.currentOfferRefs.some((offer)=>hotel.invalidatedOfferRefs.includes(offer) || hotel.tombstonedOfferRefs.includes(offer))) return false;
755
755
  const generation = hotel.currentGeneration;
756
756
  if (hotel.generationNo === 0) {
757
757
  if (generation !== undefined || hotel.currentOfferRefs.length || hotel.invalidatedOfferRefs.length || hotel.tombstonedOfferRefs.length || hotel.tombstonedOfferVersionRefs.length || hotel.status !== 'unvisited' || hotel.lastEvidence !== 'none' || hotel.checksIssued !== 0 || hotel.offerQueriesIssued !== 0 || hotel.freshOffersRequired) return false;
758
758
  continue;
759
759
  }
760
- if (!generation || generation.generationId !== `${ref}:generation:${hotel.generationNo}` || !/^[0-9a-f]{64}$/.test(generation.offerSetDigest) || generation.offerSetDigest !== digestV2(generation.orderedOfferRefs) || !Array.isArray(generation.orderedOfferRefs) || generation.orderedOfferRefs.length > MAX_OFFERS_PER_HOTEL_GENERATION_V2 || generation.orderedOfferRefs.some((offer)=>typeof offer !== 'string' || !offer) || new Set(generation.orderedOfferRefs).size !== generation.orderedOfferRefs.length || ![
760
+ if (!generation || generation.generationId !== `${ref}:generation:${hotel.generationNo}` || !/^[0-9a-f]{64}$/.test(generation.offerSetDigest) || generation.offerSetDigest !== digest(generation.orderedOfferRefs) || !Array.isArray(generation.orderedOfferRefs) || generation.orderedOfferRefs.length > MAX_OFFERS_PER_HOTEL_GENERATION || generation.orderedOfferRefs.some((offer)=>typeof offer !== 'string' || !offer) || new Set(generation.orderedOfferRefs).size !== generation.orderedOfferRefs.length || ![
761
761
  'complete',
762
762
  'partial'
763
763
  ].includes(generation.evidence) || typeof generation.valid !== 'boolean') return false;
764
- if (generation.offerSetDigest !== digestV2(generation.orderedOfferRefs) || hotel.currentOfferRefs.some((offer)=>!generation.orderedOfferRefs.includes(offer)) || hotel.invalidatedOfferRefs.some((offer)=>!generation.orderedOfferRefs.includes(offer))) return false;
764
+ if (generation.offerSetDigest !== digest(generation.orderedOfferRefs) || hotel.currentOfferRefs.some((offer)=>!generation.orderedOfferRefs.includes(offer)) || hotel.invalidatedOfferRefs.some((offer)=>!generation.orderedOfferRefs.includes(offer))) return false;
765
765
  const source = generation.source;
766
766
  if (!source || ![
767
767
  'query_receipt',
@@ -770,7 +770,7 @@ export function validateAvailabilityPolicyV2(state) {
770
770
  if (source.kind === 'query_receipt' && (typeof source.actionId !== 'string' || !source.actionId || !/^[0-9a-f]{64}$/.test(source.receiptDigest))) return false;
771
771
  if (source.kind === 'workspace_snapshot' && (typeof source.workspaceDigest !== 'string' || !/^[0-9a-f]{64}$/.test(source.workspaceDigest))) return false;
772
772
  if (source.kind === 'query_receipt' && state.lastQuerySourceActionId === source.actionId && (state.lastQuerySourceReceiptDigest !== source.receiptDigest || state.lastQueryWorkspaceRevision !== source.workspaceRevision)) return false;
773
- if (hotel.freshOffersRequired && (hotel.currentOfferRefs.length !== 0 || hotel.checksIssued >= MAX_OFFER_CHECKS_PER_HOTEL_V2 || hotel.offerQueriesIssued >= MAX_OFFER_QUERIES_PER_HOTEL_V2)) return false;
773
+ if (hotel.freshOffersRequired && (hotel.currentOfferRefs.length !== 0 || hotel.checksIssued >= MAX_OFFER_CHECKS_PER_HOTEL || hotel.offerQueriesIssued >= MAX_OFFER_QUERIES_PER_HOTEL)) return false;
774
774
  if (hotel.status === 'unvisited' || hotel.status === 'negative') {
775
775
  if (hotel.status === 'unvisited' || hotel.lastEvidence !== 'unavailable' || hotel.currentOfferRefs.length || generation.valid) return false;
776
776
  }
@@ -798,7 +798,7 @@ export function validateAvailabilityPolicyV2(state) {
798
798
  if (new Set(state.queryReservations.map((reservation)=>reservation.actionId)).size !== state.queryReservations.length) return false;
799
799
  const reservedHotels = new Set();
800
800
  for (const reservation of state.queryReservations){
801
- if (typeof reservation.actionId !== 'string' || !reservation.actionId || !Array.isArray(reservation.hotelRefs) || !reservation.hotelRefs.length || reservation.hotelRefs.length > MAX_HOTELS_PER_TASK_V2 || new Set(reservation.hotelRefs).size !== reservation.hotelRefs.length || reservation.hotelRefs.some((ref)=>!state.hotels[ref]) || !Number.isSafeInteger(reservation.workspaceRevision) || reservation.workspaceRevision < 0 || reservation.hotelRefs.some((ref)=>reservedHotels.has(ref))) return false;
801
+ if (typeof reservation.actionId !== 'string' || !reservation.actionId || !Array.isArray(reservation.hotelRefs) || !reservation.hotelRefs.length || reservation.hotelRefs.length > MAX_HOTELS_PER_TASK || new Set(reservation.hotelRefs).size !== reservation.hotelRefs.length || reservation.hotelRefs.some((ref)=>!state.hotels[ref]) || !Number.isSafeInteger(reservation.workspaceRevision) || reservation.workspaceRevision < 0 || reservation.hotelRefs.some((ref)=>reservedHotels.has(ref))) return false;
802
802
  reservation.hotelRefs.forEach((ref)=>reservedHotels.add(ref));
803
803
  }
804
804
  if (state.availabilityPhase === 'waiting_offers' && state.queryReservations.length === 0) return false;
@@ -812,7 +812,7 @@ export function validateAvailabilityPolicyV2(state) {
812
812
  if (state.availabilityPhase !== 'terminal' && state.terminal) return false;
813
813
  const recomputedTerminal = terminalFor(state);
814
814
  if (state.terminal) {
815
- if (!recomputedTerminal || digestV2(state.terminal) !== digestV2(recomputedTerminal)) return false;
815
+ if (!recomputedTerminal || digest(state.terminal) !== digest(recomputedTerminal)) return false;
816
816
  } else if (recomputedTerminal && ![
817
817
  'waiting_offers',
818
818
  'waiting_check'
@@ -822,9 +822,9 @@ export function validateAvailabilityPolicyV2(state) {
822
822
  return false;
823
823
  }
824
824
  }
825
- export function availabilityPolicyActionIsRelevantV2(action) {
825
+ export function availabilityPolicyActionIsRelevant(action) {
826
826
  return action.kind === 'offers.query' || action.kind === 'offer.check';
827
827
  }
828
828
 
829
829
 
830
- //# sourceURL=ts/src/booking-surface/availability-policy-v2.ts
830
+ //# sourceURL=ts/src/booking-surface/availability-policy.ts
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Runtime projection of the canonical booking.surface.v1 JSON Schema.
2
+ * Runtime projection of the canonical booking.surface JSON Schema.
3
3
  *
4
4
  * dsh tools need self-contained JSON Schemas, while the canonical document is
5
5
  * organized with local $refs. This helper derives each action branch directly
@@ -9,10 +9,8 @@
9
9
 
10
10
  import { readFileSync } from 'node:fs'
11
11
 
12
- const schemaUrl = new URL('../../../schemas/booking.surface.v1.schema.json', import.meta.url)
13
- export const canonicalBookingSurfaceSchemaV1 = JSON.parse(readFileSync(schemaUrl, 'utf8'))
14
- const schemaV2Url = new URL('../../../schemas/booking.surface.v2.schema.json', import.meta.url)
15
- export const canonicalBookingSurfaceSchemaV2 = JSON.parse(readFileSync(schemaV2Url, 'utf8'))
12
+ const schemaUrl = new URL('../../../schemas/booking.surface.schema.json', import.meta.url)
13
+ export const canonicalBookingSurfaceSchema = JSON.parse(readFileSync(schemaUrl, 'utf8'))
16
14
 
17
15
  function clone(value) {
18
16
  return JSON.parse(JSON.stringify(value))
@@ -20,14 +18,11 @@ function clone(value) {
20
18
 
21
19
  function definitionFromRef(ref, schema) {
22
20
  const prefix = '#/$defs/'
23
- if (typeof ref !== 'string') {
21
+ if (typeof ref !== 'string' || !ref.startsWith(prefix)) {
24
22
  throw new Error(`booking_schema_external_ref_forbidden:${String(ref)}`)
25
23
  }
26
- const externalV1 = 'https://gotry.dev/schemas/booking.surface.v1.schema.json#/$defs/'
27
- const definitionSchema = ref.startsWith(prefix) ? schema : ref.startsWith(externalV1) ? canonicalBookingSurfaceSchemaV1 : undefined
28
- if (!definitionSchema) throw new Error(`booking_schema_external_ref_forbidden:${String(ref)}`)
29
- const name = ref.startsWith(prefix) ? ref.slice(prefix.length) : ref.slice(externalV1.length)
30
- const definition = definitionSchema.$defs?.[name]
24
+ const name = ref.slice(prefix.length)
25
+ const definition = schema.$defs?.[name]
31
26
  if (!definition) throw new Error(`booking_schema_missing_definition:${name}`)
32
27
  return definition
33
28
  }
@@ -38,9 +33,8 @@ function inlineLocalRefs(value, schema, stack = []) {
38
33
  if (typeof value.$ref === 'string') {
39
34
  if (stack.includes(value.$ref)) throw new Error(`booking_schema_recursive_ref:${value.$ref}`)
40
35
  const { $ref, ...siblings } = value
41
- const definitionSchema = typeof $ref === 'string' && $ref.startsWith('https://gotry.dev/schemas/booking.surface.v1.schema.json#/$defs/') ? canonicalBookingSurfaceSchemaV1 : schema
42
36
  return {
43
- ...inlineLocalRefs(definitionFromRef($ref, schema), definitionSchema, [...stack, $ref]),
37
+ ...inlineLocalRefs(definitionFromRef($ref, schema), schema, [...stack, $ref]),
44
38
  ...inlineLocalRefs(siblings, schema, stack),
45
39
  }
46
40
  }
@@ -73,11 +67,7 @@ function canonicalActionSchemaForKind(kind, schema, definitionName) {
73
67
  }
74
68
 
75
69
  export function canonicalBookingActionSchemaForKind(kind) {
76
- return canonicalActionSchemaForKind(kind, canonicalBookingSurfaceSchemaV1, 'BookingReadActionV1')
77
- }
78
-
79
- export function canonicalBookingActionSchemaForKindV2(kind) {
80
- return canonicalActionSchemaForKind(kind, canonicalBookingSurfaceSchemaV2, 'Action')
70
+ return canonicalActionSchemaForKind(kind, canonicalBookingSurfaceSchema, 'Action')
81
71
  }
82
72
 
83
73
  const DSH_JSON_SCHEMA_KEYS = new Set([
@@ -107,7 +97,3 @@ function projectDshSchema(value) {
107
97
  export function dshBookingActionSchemaForKind(kind) {
108
98
  return projectDshSchema(canonicalBookingActionSchemaForKind(kind))
109
99
  }
110
-
111
- export function dshBookingActionSchemaForKindV2(kind) {
112
- return projectDshSchema(canonicalBookingActionSchemaForKindV2(kind))
113
- }