@effect-agent/testing 0.1.0-beta.38 → 0.1.0-beta.40

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 (44) hide show
  1. package/dist/certification.d.mts +102 -0
  2. package/dist/certification.mjs +561 -0
  3. package/dist/certification.mjs.map +1 -0
  4. package/dist/chaos.d.mts +124 -0
  5. package/dist/chaos.mjs +739 -0
  6. package/dist/chaos.mjs.map +1 -0
  7. package/dist/code-executor.d.mts +48 -0
  8. package/dist/code-executor.mjs +565 -0
  9. package/dist/code-executor.mjs.map +1 -0
  10. package/dist/deterministic-layers-CKyYxBhN.mjs +354 -0
  11. package/dist/deterministic-layers-CKyYxBhN.mjs.map +1 -0
  12. package/dist/docs-researcher.d.mts +254 -0
  13. package/dist/docs-researcher.mjs +479 -0
  14. package/dist/docs-researcher.mjs.map +1 -0
  15. package/dist/index.d.mts +2 -2947
  16. package/dist/index.mjs +2 -4913
  17. package/dist/scripted-model-C2y0ztuj.mjs +167 -0
  18. package/dist/scripted-model-C2y0ztuj.mjs.map +1 -0
  19. package/dist/scripted-model-dOa_e0-n.d.mts +677 -0
  20. package/dist/travel-planner.d.mts +1767 -0
  21. package/dist/travel-planner.mjs +2103 -0
  22. package/dist/travel-planner.mjs.map +1 -0
  23. package/package.json +34 -11
  24. package/src/certification.ts +71 -61
  25. package/src/chaos.ts +58 -71
  26. package/src/code-executor.ts +3 -0
  27. package/src/docs-researcher.ts +2 -0
  28. package/src/fixtures/docs-researcher/definition.ts +7 -7
  29. package/src/fixtures/docs-researcher/harness.ts +12 -14
  30. package/src/fixtures/docs-researcher/index.ts +1 -1
  31. package/src/fixtures/travel-planner/definition.ts +1 -1
  32. package/src/fixtures/travel-planner/deterministic-layers.ts +7 -4
  33. package/src/fixtures/travel-planner/phase2.ts +1 -1
  34. package/src/fixtures/travel-planner/phase3.ts +14 -18
  35. package/src/fixtures/travel-planner/phase4.ts +7 -7
  36. package/src/fixtures/travel-planner/phase5.ts +5 -5
  37. package/src/fixtures/travel-planner/phase6.ts +30 -29
  38. package/src/fixtures/travel-planner/subagents-durable.ts +6 -6
  39. package/src/fixtures/travel-planner/subagents.ts +4 -4
  40. package/src/index.ts +1 -10
  41. package/src/travel-planner.ts +2 -0
  42. package/dist/index.mjs.map +0 -1
  43. package/src/code-executor-conformance.d.ts +0 -30
  44. package/src/fixtures/warehouse/index.ts +0 -412
@@ -0,0 +1,2103 @@
1
+ import { r as ScriptedModel } from "./scripted-model-C2y0ztuj.mjs";
2
+ import { A as LodgingQuery, B as TravelPlannerToolkitLayer, C as FlightOption, D as Itinerary, E as GuidanceFailure, F as SearchLodging, I as TravelGuidance, L as TravelPlan, M as QuoteId, N as SearchActivities, O as LodgingCatalog, P as SearchFlights, R as TravelPlanner, S as FlightCatalog, T as FlightUnavailable, V as TripRequest, _ as ActivityCatalog, a as DeterministicIdGeneratorLayer, b as ActivityUnavailable, c as ReverseCompletionToolkitLayer, d as SupplierOperation, f as SupplierUnavailable, g as supplierBookingRefFor, h as cancelBookingIdempotencyKey, i as CatalogLifecycleCounts, j as LodgingUnavailable, k as LodgingOption, l as SupplierBookingDesk, m as TravelPlannerRuntimeLayer, n as BookingRef, o as FlightCatalogLayer, p as TravelGuidanceLayer, r as CatalogLifecycle, s as LodgingCatalogLayer, t as ActivityCatalogLayer, u as SupplierBookingRecord, v as ActivityQuery, w as FlightQuery, x as AirportCode, y as ActivitySearchResult, z as TravelPlannerToolkit } from "./deterministic-layers-CKyYxBhN.mjs";
3
+ import { Context, Deferred, Duration, Effect, Layer, Option, Ref, Schema, Stream } from "effect";
4
+ import { LanguageModel, Model, Tool, Toolkit } from "effect/unstable/ai";
5
+ import { Subagent, SubagentPolicy, SubagentReservationsMemoryLive, SubagentRuntime, delegationAllocationFromPolicy } from "@effect-agent/capabilities";
6
+ import { Agent, AgentId, AgentPolicy, RunId, SubmissionId, ThreadId } from "@effect-agent/core";
7
+ import { DurableStep, DurableStepError, ToolExecutionClass } from "@effect-agent/engine";
8
+ import { BatchId, CanonicalBatch, CanonicalRecordEnvelope, DefinitionDigests, DeploymentId, Digest, DurableWorkerBinding, PersistedJson, Principal, ProducerId, ReconciliationCompleted, ReconciliationSafeToRetry, ReconciliationUncertain, RecordEnvelope, RecordId, ThreadCheckpoint, ThreadProjection, ToolReconciler, ToolReconcilerError } from "@effect-agent/thread";
9
+ //#region src/fixtures/travel-planner/phase2.ts
10
+ var ItineraryHoldRequest = class extends Schema.Class("@effect-agent/testing/travel-planner/ItineraryHoldRequest")({
11
+ quoteId: QuoteId,
12
+ expiresInMinutes: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(60))
13
+ }) {};
14
+ var ItineraryHold = class extends Schema.Class("@effect-agent/testing/travel-planner/ItineraryHold")({
15
+ holdId: Schema.NonEmptyString,
16
+ quoteId: QuoteId,
17
+ status: Schema.Literal("held")
18
+ }) {};
19
+ var ItineraryHoldUnavailable = class extends Schema.TaggedError()("ItineraryHoldUnavailable", {
20
+ quoteId: QuoteId,
21
+ message: Schema.String
22
+ }) {};
23
+ var ItineraryHoldGateway = class extends Context.Service()("@effect-agent/testing/travel-planner/ItineraryHoldGateway") {};
24
+ /**
25
+ * The first mutating Travel Planner Tool. Effect AI marks it as approval-gated
26
+ * so the engine must settle approval before acquiring a handler permit.
27
+ */
28
+ const HoldItinerary = Tool.make("hold_itinerary", {
29
+ parameters: ItineraryHoldRequest,
30
+ success: ItineraryHold,
31
+ failure: ItineraryHoldUnavailable,
32
+ failureMode: "error",
33
+ dependencies: [ItineraryHoldGateway],
34
+ needsApproval: true
35
+ });
36
+ const TravelPlannerPhase2Toolkit = Toolkit.make(SearchFlights, SearchLodging, SearchActivities, HoldItinerary);
37
+ const TravelPlannerPhase2ToolkitLayer = TravelPlannerPhase2Toolkit.toLayer({
38
+ search_flights: (query) => Effect.flatMap(FlightCatalog, (catalog) => catalog.search(query)),
39
+ search_lodging: (query) => Effect.flatMap(LodgingCatalog, (catalog) => catalog.search(query)),
40
+ search_activities: (query) => Effect.flatMap(ActivityCatalog, (catalog) => catalog.search(query)),
41
+ hold_itinerary: (request) => Effect.flatMap(ItineraryHoldGateway, (gateway) => gateway.hold(request))
42
+ });
43
+ const TravelPlannerPhase2 = Agent.make("travel-planner-phase-2", {
44
+ input: TripRequest,
45
+ output: TravelPlan,
46
+ instructions: (input) => Effect.flatMap(TravelGuidance, (guidance) => guidance.instructions(input)),
47
+ toolkit: TravelPlannerPhase2Toolkit,
48
+ policy: AgentPolicy.make({
49
+ maxTurns: 3,
50
+ maxToolCalls: 4,
51
+ maxDuration: "30 seconds",
52
+ toolConcurrency: 3,
53
+ tokenBudget: 4096
54
+ }),
55
+ description: "Build a review-only itinerary and require approval before creating a temporary hold.",
56
+ metadata: {
57
+ deploymentClass: "E",
58
+ phase: "P2"
59
+ }
60
+ });
61
+ //#endregion
62
+ //#region src/fixtures/travel-planner/scenarios.ts
63
+ const usage = {
64
+ inputTokens: { total: 128 },
65
+ outputTokens: { total: 96 }
66
+ };
67
+ const phase1Trip = Schema.decodeSync(TripRequest)({
68
+ request: "Plan a review-only London trip using the deterministic flight, lodging, and activity searches.",
69
+ origin: "SFO",
70
+ destination: "LHR",
71
+ departOn: "2026-09-14",
72
+ nights: 4,
73
+ travelers: 2,
74
+ budgetCents: 35e4,
75
+ currency: "USD"
76
+ });
77
+ const expectedTravelPlan = Schema.decodeSync(TravelPlan)({ itineraries: [{
78
+ title: "Westward light, eastbound overnight",
79
+ route: "San Francisco → London",
80
+ dates: "14–19 September 2026",
81
+ flight: "EA 218 · nonstop · SFO 18:40 → LHR 13:05+1",
82
+ lodging: "Bloomsbury House · refundable studio · 4 nights",
83
+ activities: ["British Museum timed entry", "Thames evening walk"],
84
+ estimatedTotalCents: 284e3,
85
+ currency: "USD",
86
+ quoteId: "quote-sfo-lhr-001",
87
+ assumptions: ["Two travelers sharing one studio", "Quote is read-only availability, not a reservation"],
88
+ unresolvedConstraints: ["Traveler names and accessibility requests are intentionally omitted"],
89
+ nextAction: "review"
90
+ }] });
91
+ const phase1HappyPathTurns = [{
92
+ _tag: "Stream",
93
+ parts: [
94
+ {
95
+ type: "tool-call",
96
+ id: "flight-call-1",
97
+ name: "search_flights",
98
+ params: {
99
+ origin: "SFO",
100
+ destination: "LHR",
101
+ departOn: "2026-09-14",
102
+ travelers: 2
103
+ }
104
+ },
105
+ {
106
+ type: "tool-call",
107
+ id: "lodging-call-1",
108
+ name: "search_lodging",
109
+ params: {
110
+ destination: "LHR",
111
+ departOn: "2026-09-14",
112
+ nights: 4,
113
+ travelers: 2
114
+ }
115
+ },
116
+ {
117
+ type: "tool-call",
118
+ id: "activity-call-1",
119
+ name: "search_activities",
120
+ params: {
121
+ destination: "LHR",
122
+ departOn: "2026-09-14",
123
+ nights: 4,
124
+ travelers: 2
125
+ }
126
+ },
127
+ {
128
+ type: "finish",
129
+ reason: "tool-calls",
130
+ usage
131
+ }
132
+ ],
133
+ termination: { _tag: "Complete" }
134
+ }, {
135
+ _tag: "Stream",
136
+ parts: [
137
+ {
138
+ type: "text-start",
139
+ id: "itinerary-json"
140
+ },
141
+ {
142
+ type: "text-delta",
143
+ id: "itinerary-json",
144
+ delta: JSON.stringify(Schema.encodeSync(TravelPlan)(expectedTravelPlan))
145
+ },
146
+ {
147
+ type: "text-end",
148
+ id: "itinerary-json"
149
+ },
150
+ {
151
+ type: "finish",
152
+ reason: "stop",
153
+ usage
154
+ }
155
+ ],
156
+ termination: { _tag: "Complete" }
157
+ }];
158
+ //#endregion
159
+ //#region src/fixtures/travel-planner/phase3.ts
160
+ /**
161
+ * The Phase 3 profile persists Thread history but deliberately does not
162
+ * claim durable admission or recovery of accepted work.
163
+ */
164
+ var TravelPlannerPersistenceProfile = class extends Schema.Class("@effect-agent/testing/travel-planner/TravelPlannerPersistenceProfile")({
165
+ deploymentClass: Schema.Literal("P"),
166
+ durableAcceptedWork: Schema.Literal(false),
167
+ canonicalSchemaVersion: Schema.Literal(1)
168
+ }) {};
169
+ const phase3TravelPlannerProfile = TravelPlannerPersistenceProfile.make({
170
+ deploymentClass: "P",
171
+ durableAcceptedWork: false,
172
+ canonicalSchemaVersion: 1
173
+ });
174
+ const phase3TravelPlannerThreadId = Schema.decodeSync(ThreadId)("travel-planner-p3-thread");
175
+ const phase3TravelPlannerProducerId = Schema.decodeSync(ProducerId)("travel-planner-p3-producer");
176
+ const phase3TravelPlannerRunId = Schema.decodeSync(RunId)("travel-planner-p3-run");
177
+ const deploymentId = Schema.decodeSync(DeploymentId)("travel-planner-p3-scripted");
178
+ const agentId = Schema.decodeSync(AgentId)("travel-planner");
179
+ const submissionId = Schema.decodeSync(SubmissionId)("travel-planner-p3-submission");
180
+ const digest$2 = (character) => Schema.decodeSync(Digest)(character.repeat(64));
181
+ /** Redacted, deterministic definition identities for the current fixture version. */
182
+ const phase3TravelPlannerDefinitionDigests = DefinitionDigests.make({
183
+ agent: digest$2("a"),
184
+ model: digest$2("b"),
185
+ tools: digest$2("c")
186
+ });
187
+ const tripInput = Schema.encodeSync(TripRequest)(phase1Trip);
188
+ const travelPlanOutput = Schema.encodeSync(TravelPlan)(expectedTravelPlan);
189
+ const record = (recordId, createdAt, payload) => Schema.decodeUnknownSync(RecordEnvelope)({
190
+ recordId: Schema.decodeSync(RecordId)(recordId),
191
+ family: "thread",
192
+ schemaVersion: 1,
193
+ createdAt,
194
+ deploymentId,
195
+ payload
196
+ });
197
+ /**
198
+ * The first atomic append establishes the Thread and records its input.
199
+ * Its encoded value is the redacted current-version persistence fixture.
200
+ */
201
+ const phase3TravelPlannerInitialBatch = CanonicalBatch.make({
202
+ batchId: Schema.decodeSync(BatchId)("travel-planner-p3-initial"),
203
+ producerId: phase3TravelPlannerProducerId,
204
+ records: [record("travel-planner-p3-created", "2026-09-01T00:00:00.000Z", {
205
+ _tag: "ThreadCreated",
206
+ agentId,
207
+ definitions: phase3TravelPlannerDefinitionDigests
208
+ }), record("travel-planner-p3-input", "2026-09-01T00:00:01.000Z", {
209
+ _tag: "UserInputRecorded",
210
+ submissionId,
211
+ kind: "user",
212
+ runId: phase3TravelPlannerRunId,
213
+ input: tripInput
214
+ })]
215
+ });
216
+ /** The second append records the Schema-decoded itinerary and terminal Run result. */
217
+ const phase3TravelPlannerCompletionBatch = CanonicalBatch.make({
218
+ batchId: Schema.decodeSync(BatchId)("travel-planner-p3-completion"),
219
+ producerId: phase3TravelPlannerProducerId,
220
+ records: [record("travel-planner-p3-model", "2026-09-01T00:00:02.000Z", {
221
+ _tag: "ModelCompleted",
222
+ runId: phase3TravelPlannerRunId,
223
+ output: travelPlanOutput
224
+ }), record("travel-planner-p3-completed", "2026-09-01T00:00:03.000Z", {
225
+ _tag: "RunCompleted",
226
+ runId: phase3TravelPlannerRunId,
227
+ output: travelPlanOutput
228
+ })]
229
+ });
230
+ const phase3TravelPlannerBatches = [phase3TravelPlannerInitialBatch, phase3TravelPlannerCompletionBatch];
231
+ /** Portable current-version fixture; it contains no passenger identity or credentials. */
232
+ const phase3TravelPlannerEncodedFixture = Schema.encodeSync(Schema.Array(CanonicalBatch))(phase3TravelPlannerBatches);
233
+ var TravelPlannerProjectionError = class extends Schema.TaggedError()("TravelPlannerProjectionError", { message: Schema.String }) {};
234
+ /** Decode the itinerary projection rebuilt from canonical model-completion records. */
235
+ const travelPlanFromProjection = (projection) => {
236
+ const output = projection.modelOutputs.at(-1);
237
+ if (output === void 0) return Effect.fail(TravelPlannerProjectionError.make({ message: "The canonical projection has no completed Travel Planner model output." }));
238
+ return Schema.decodeUnknownEffect(TravelPlan)(output).pipe(Effect.mapError((error) => TravelPlannerProjectionError.make({ message: error.message })));
239
+ };
240
+ /** Build a disposable checkpoint bound to a validated canonical prefix. */
241
+ const makePhase3TravelPlannerCheckpoint = (projection) => Schema.decodeSync(ThreadCheckpoint)({
242
+ schemaVersion: 1,
243
+ threadId: projection.threadId,
244
+ throughSequence: projection.throughSequence,
245
+ tailDigest: projection.tailDigest,
246
+ engineVersion: "phase-3-test-runtime",
247
+ agentDefinitionDigest: phase3TravelPlannerDefinitionDigests.agent,
248
+ modelDigest: phase3TravelPlannerDefinitionDigests.model,
249
+ toolDigest: phase3TravelPlannerDefinitionDigests.tools,
250
+ state: Schema.encodeSync(ThreadProjection)(projection),
251
+ createdAt: "2026-09-01T00:00:04.000Z"
252
+ });
253
+ //#endregion
254
+ //#region src/fixtures/travel-planner/phase4.ts
255
+ /**
256
+ * The Phase 4 profile claims durable accepted work on the Node/SQLite runtime (deployment class
257
+ * DN): once `submit` returns a Receipt, the Submission settles exactly once even across process
258
+ * loss. The claim is limited to safe-to-repeat toolkits (D6): supplier booking is explicitly NOT
259
+ * claimed safely replayable — replay-safe external mutation is P5 (Durable Tools) scope.
260
+ */
261
+ var TravelPlannerDurabilityProfile = class extends Schema.Class("@effect-agent/testing/travel-planner/TravelPlannerDurabilityProfile")({
262
+ deploymentClass: Schema.Literal("DN"),
263
+ durableAcceptedWork: Schema.Literal(true),
264
+ canonicalSchemaVersion: Schema.Literal(1),
265
+ /** Supplier booking replay safety is P5 (Durable Tools) scope; DN does not claim it. */
266
+ supplierBookingReplaySafe: Schema.Literal(false)
267
+ }) {};
268
+ const phase4TravelPlannerProfile = TravelPlannerDurabilityProfile.make({
269
+ deploymentClass: "DN",
270
+ durableAcceptedWork: true,
271
+ canonicalSchemaVersion: 1,
272
+ supplierBookingReplaySafe: false
273
+ });
274
+ const phase4TravelPlannerDeploymentId = Schema.decodeSync(DeploymentId)("travel-planner-p4-deployment");
275
+ const phase4TravelPlannerProducerId = Schema.decodeSync(ProducerId)("travel-planner-p4-producer");
276
+ const phase4TravelPlannerPrincipal = Schema.decodeSync(Principal)("travel-planner-p4-principal");
277
+ const digest$1 = (character) => Schema.decodeSync(Digest)(character.repeat(64));
278
+ /** Redacted, deterministic definition identities for the current fixture version. */
279
+ const phase4TravelPlannerDefinitionDigests = DefinitionDigests.make({
280
+ agent: digest$1("d"),
281
+ model: digest$1("e"),
282
+ tools: digest$1("f")
283
+ });
284
+ /** Durable admission options for one Travel Planner Submission on one trip lane. */
285
+ const phase4TravelPlannerSubmitOptions = (threadId, idempotencyKey) => ({
286
+ threadId,
287
+ principal: phase4TravelPlannerPrincipal,
288
+ idempotencyKey,
289
+ definitions: phase4TravelPlannerDefinitionDigests
290
+ });
291
+ /**
292
+ * The P4 read-only search Tools, calling the same deterministic catalogs as the P1 toolkit.
293
+ *
294
+ * The plain-Struct parameter shape is a historical remnant of the P4 carry-in workaround: since
295
+ * the P5 engine fix, official history carries Schema-ENCODED Tool-call parameters, so class-typed
296
+ * parameter codecs persist canonically too — the Structs simply need no change here. The
297
+ * `ToolExecutionClass` `readonly` annotation is the deliberate P5 migration (plan §4.3): these
298
+ * Tools perform no external mutation, so a crash between start and settlement is a free re-run
299
+ * and they never enter the prepared/settled uncertainty protocol — keeping the P4 canonical
300
+ * history byte-stable (an unannotated Tool fails closed to `uncertain`).
301
+ */
302
+ const DurableSearchFlights = Tool.make("search_flights", {
303
+ parameters: Schema.Struct(FlightQuery.fields),
304
+ success: FlightOption,
305
+ failure: FlightUnavailable,
306
+ failureMode: "error",
307
+ dependencies: [FlightCatalog]
308
+ }).annotate(ToolExecutionClass, "readonly");
309
+ const DurableSearchLodging = Tool.make("search_lodging", {
310
+ parameters: Schema.Struct(LodgingQuery.fields),
311
+ success: LodgingOption,
312
+ failure: LodgingUnavailable,
313
+ failureMode: "error",
314
+ dependencies: [LodgingCatalog]
315
+ }).annotate(ToolExecutionClass, "readonly");
316
+ const DurableSearchActivities = Tool.make("search_activities", {
317
+ parameters: Schema.Struct(ActivityQuery.fields),
318
+ success: ActivitySearchResult,
319
+ failure: ActivityUnavailable,
320
+ failureMode: "error",
321
+ dependencies: [ActivityCatalog]
322
+ }).annotate(ToolExecutionClass, "readonly");
323
+ const TravelPlannerPhase4Toolkit = Toolkit.make(DurableSearchFlights, DurableSearchLodging, DurableSearchActivities);
324
+ const TravelPlannerPhase4ToolkitLayer = TravelPlannerPhase4Toolkit.toLayer({
325
+ search_flights: (query) => Effect.flatMap(FlightCatalog, (catalog) => catalog.search(FlightQuery.make(query))),
326
+ search_lodging: (query) => Effect.flatMap(LodgingCatalog, (catalog) => catalog.search(LodgingQuery.make(query))),
327
+ search_activities: (query) => Effect.flatMap(ActivityCatalog, (catalog) => catalog.search(ActivityQuery.make(query)))
328
+ });
329
+ /**
330
+ * The cumulative Travel Planner, Phase 4: the P1 planning behavior on the durable Node/SQLite
331
+ * runtime. The searches are read-only and safe to repeat across Attempts (D6); supplier booking
332
+ * is deliberately absent because DN does NOT claim replay-safe external mutation (P5 scope).
333
+ */
334
+ const TravelPlannerPhase4 = Agent.make("travel-planner-phase-4", {
335
+ input: TripRequest,
336
+ output: TravelPlan,
337
+ instructions: (input) => Effect.flatMap(TravelGuidance, (guidance) => guidance.instructions(input)),
338
+ toolkit: TravelPlannerPhase4Toolkit,
339
+ policy: AgentPolicy.make({
340
+ maxTurns: 2,
341
+ maxToolCalls: 3,
342
+ maxDuration: "30 seconds",
343
+ toolConcurrency: 3
344
+ }),
345
+ description: "Durably plan one review-only itinerary from safe-to-repeat deterministic searches; supplier booking is not claimed safely replayable.",
346
+ metadata: {
347
+ deploymentClass: "DN",
348
+ phase: "P4"
349
+ }
350
+ });
351
+ /**
352
+ * The P4 Agent Binding: the durable Travel Planner definition bound to a finite scripted model.
353
+ * The scripted Layer is rebuilt per Run, so every Run of one Binding replays the same
354
+ * deterministic script.
355
+ */
356
+ const makePhase4TravelPlannerAgent = (turns = phase1HappyPathTurns) => Agent.withModel(TravelPlannerPhase4, Model.make("scripted", "travel-planner-phase-4", ScriptedModel.layer(turns)));
357
+ /**
358
+ * Everything a durable worker needs beyond the runtime stack, reusing the deterministic P1
359
+ * travel-service Layers. The durable coordinator supplies its own deterministic `IdGenerator`,
360
+ * so this Layer deliberately provides none.
361
+ */
362
+ const phase4TravelPlannerWorkerLayer = Layer.mergeAll(TravelPlannerPhase4ToolkitLayer, FlightCatalogLayer, LodgingCatalogLayer, ActivityCatalogLayer, TravelGuidanceLayer).pipe(Layer.provide(CatalogLifecycle.layerNoDeps));
363
+ var TravelPlannerDurableEvidenceError = class extends Schema.TaggedError()("TravelPlannerDurableEvidenceError", { message: Schema.String }) {};
364
+ /**
365
+ * Decode the completed itinerary from the canonical `SubmissionSettled` record. Canonical history
366
+ * is the outcome authority (DUR-015): the settled result — not any ledger cache — must decode
367
+ * through the trip output schema.
368
+ */
369
+ const travelPlanFromDurableSettlement = Effect.fn("TravelPlannerPhase4.travelPlanFromDurableSettlement")(function* (records) {
370
+ const settled = records.flatMap((envelope) => envelope.record.payload._tag === "SubmissionSettled" ? [envelope.record.payload] : []).at(0);
371
+ if (settled === void 0) return yield* TravelPlannerDurableEvidenceError.make({ message: "The canonical Thread Log has no SubmissionSettled record." });
372
+ if (settled.outcome !== "completed" || settled.result === void 0) return yield* TravelPlannerDurableEvidenceError.make({ message: `The Submission settled ${settled.outcome} without a completed itinerary result.` });
373
+ return yield* Schema.decodeUnknownEffect(TravelPlan)(settled.result).pipe(Effect.mapError((error) => TravelPlannerDurableEvidenceError.make({ message: `The settled result does not decode through the TravelPlan schema: ${error.message}` })));
374
+ });
375
+ const encodeEvidence = Schema.encodeEffect(Schema.Array(CanonicalRecordEnvelope));
376
+ const decodeComparableJson$1 = Schema.decodeUnknownEffect(Schema.Json);
377
+ /**
378
+ * Project canonical evidence into a Submission-identity-independent comparable form: batch
379
+ * identity, canonical sequence, and the full encoded record, with the ledger-minted
380
+ * `submissionId`/`receiptId` (and every identity derived from them: run, turn, batch, record,
381
+ * and settlement ids) replaced by stable placeholders. Two Threads whose normalized
382
+ * evidence is equal took byte-equivalent canonical histories, so restart-equivalence can compare
383
+ * a recovered run against an uninterrupted control run on a separate database.
384
+ */
385
+ const normalizeDurableTravelPlannerEvidence = Effect.fn("TravelPlannerPhase4.normalizeDurableTravelPlannerEvidence")(function* (records, receipt) {
386
+ const comparable = (yield* encodeEvidence(records).pipe(Effect.mapError((error) => TravelPlannerDurableEvidenceError.make({ message: `Canonical evidence failed to encode: ${error.message}` })))).map((envelope) => ({
387
+ batchId: envelope.batchId,
388
+ sequence: envelope.sequence,
389
+ record: envelope.record
390
+ }));
391
+ const substituted = JSON.parse(JSON.stringify(comparable).replaceAll(receipt.submissionId, "{submissionId}").replaceAll(receipt.receiptId, "{receiptId}"));
392
+ return yield* decodeComparableJson$1(substituted).pipe(Effect.mapError((error) => TravelPlannerDurableEvidenceError.make({ message: `Normalized evidence is not comparable JSON: ${error.message}` })));
393
+ });
394
+ //#endregion
395
+ //#region src/fixtures/travel-planner/phase5.ts
396
+ /**
397
+ * The Phase 5 profile extends the P4 `DN` claim to consequential supplier mutation: booking
398
+ * Tools enter the prepared/settled uncertainty protocol, unresolved external effects stop at
399
+ * Unknown Outcomes instead of replaying, Durable Steps replay recorded results, and queued
400
+ * traveler input joins the active Run. Exactly-once EXTERNAL execution is still — deliberately —
401
+ * not claimed (DUR-003): the supplier's own idempotency keys are what dedupe repeats.
402
+ */
403
+ var TravelPlannerBookingProfile = class extends Schema.Class("@effect-agent/testing/travel-planner/TravelPlannerBookingProfile")({
404
+ deploymentClass: Schema.Literal("DN"),
405
+ durableAcceptedWork: Schema.Literal(true),
406
+ canonicalSchemaVersion: Schema.Literal(1),
407
+ /** P5: supplier mutations get prepared/settled records, Unknown Outcomes, and reconciliation. */
408
+ supplierBookingUncertaintyProtocol: Schema.Literal(true),
409
+ /** P5: Durable Steps are exactly-once-RECORDED; their side effects stay at-least-once. */
410
+ durableStepsRecorded: Schema.Literal(true),
411
+ /** Never claimed at any phase (DUR-003). */
412
+ exactlyOnceExternalEffects: Schema.Literal(false)
413
+ }) {};
414
+ const phase5TravelPlannerProfile = TravelPlannerBookingProfile.make({
415
+ deploymentClass: "DN",
416
+ durableAcceptedWork: true,
417
+ canonicalSchemaVersion: 1,
418
+ supplierBookingUncertaintyProtocol: true,
419
+ durableStepsRecorded: true,
420
+ exactlyOnceExternalEffects: false
421
+ });
422
+ const phase5TravelPlannerDeploymentId = Schema.decodeSync(DeploymentId)("travel-planner-p5-deployment");
423
+ const phase5TravelPlannerProducerId = Schema.decodeSync(ProducerId)("travel-planner-p5-producer");
424
+ const phase5TravelPlannerPrincipal = Schema.decodeSync(Principal)("travel-planner-p5-principal");
425
+ const digest = (character) => Schema.decodeSync(Digest)(character.repeat(64));
426
+ /** Redacted, deterministic definition identities for the current fixture version. */
427
+ const phase5TravelPlannerDefinitionDigests = DefinitionDigests.make({
428
+ agent: digest("1"),
429
+ model: digest("2"),
430
+ tools: digest("3")
431
+ });
432
+ /** Durable admission options for one Travel Planner Submission on one trip lane. */
433
+ const phase5TravelPlannerSubmitOptions = (threadId, idempotencyKey) => ({
434
+ threadId,
435
+ principal: phase5TravelPlannerPrincipal,
436
+ idempotencyKey,
437
+ definitions: phase5TravelPlannerDefinitionDigests
438
+ });
439
+ const TravelerRef = Schema.NonEmptyString.pipe(Schema.brand("@effect-agent/testing/travel-planner/TravelerRef"));
440
+ /**
441
+ * Class-shaped booking parameters with branded fields: since the P5 engine fix, official history
442
+ * carries Schema-ENCODED Tool-call parameters, so class-typed parameter codecs persist
443
+ * canonically end-to-end (the P4 Struct workaround is gone for new Tools).
444
+ */
445
+ var FlightBookingRequest = class extends Schema.Class("FlightBookingRequest")({
446
+ quoteId: QuoteId,
447
+ travelerRef: TravelerRef,
448
+ departOn: Schema.String
449
+ }) {};
450
+ var SupplierBookingConfirmation = class extends Schema.Class("SupplierBookingConfirmation")({
451
+ bookingRef: BookingRef,
452
+ status: Schema.Literal("confirmed"),
453
+ detail: Schema.String
454
+ }) {};
455
+ var CancelBookingRequest = class extends Schema.Class("CancelBookingRequest")({
456
+ bookingRef: BookingRef,
457
+ travelerRef: TravelerRef
458
+ }) {};
459
+ var CancellationConfirmation = class extends Schema.Class("CancellationConfirmation")({
460
+ bookingRef: BookingRef,
461
+ status: Schema.Literal("cancelled")
462
+ }) {};
463
+ var ItineraryBookingRequest = class extends Schema.Class("ItineraryBookingRequest")({
464
+ quoteId: QuoteId,
465
+ destination: AirportCode,
466
+ nights: Schema.Int.check(Schema.isGreaterThan(0)),
467
+ travelerRef: TravelerRef
468
+ }) {};
469
+ var ItineraryConfirmation = class extends Schema.Class("ItineraryConfirmation")({
470
+ flightBookingRef: BookingRef,
471
+ lodgingBookingRef: BookingRef,
472
+ confirmationCode: Schema.String
473
+ }) {};
474
+ /** The P5 Run output: a booked (or explicitly not-booked) trip report. */
475
+ var TravelBookingReport = class extends Schema.Class("TravelBookingReport")({
476
+ summary: Schema.String,
477
+ bookingRefs: Schema.Array(BookingRef)
478
+ }) {};
479
+ /**
480
+ * Supplier idempotency-key derivations. The handler owns key derivation (the `idempotent` and
481
+ * `uncertain` execution classes carry no key), and the reconciler MUST use the same derivations
482
+ * to query external truth — both sides are exported so they cannot drift.
483
+ */
484
+ const bookFlightIdempotencyKey = (toolCallId) => `book-flight:${toolCallId}`;
485
+ const itineraryStepIdempotencyKey = (toolCallId, stepName) => `${toolCallId}:${stepName}`;
486
+ /**
487
+ * Approval-gated supplier booking, explicitly `uncertain`: a crash after the call may have
488
+ * mutated supplier state without a recorded outcome, so recovery must reconcile or stop at an
489
+ * Unknown Outcome — never replay automatically (DUR-009, ADR-0004).
490
+ */
491
+ const BookFlight = Tool.make("book_flight", {
492
+ parameters: FlightBookingRequest,
493
+ success: SupplierBookingConfirmation,
494
+ failure: SupplierUnavailable,
495
+ failureMode: "error",
496
+ needsApproval: true,
497
+ dependencies: [SupplierBookingDesk]
498
+ }).annotate(ToolExecutionClass, "uncertain");
499
+ /**
500
+ * Approval-gated cancellation, annotated `idempotent`: the DECLARED external contract is that
501
+ * cancellation is idempotent by `bookingRef` (the supplier desk enforces it), so recovery may
502
+ * re-execute a prepared-but-unsettled cancel without reconciliation proof. Repeats stay
503
+ * observable in the supplier call counters — the annotation never claims exactly-once execution.
504
+ */
505
+ const CancelBooking = Tool.make("cancel_booking", {
506
+ parameters: CancelBookingRequest,
507
+ success: CancellationConfirmation,
508
+ failure: SupplierUnavailable,
509
+ failureMode: "error",
510
+ needsApproval: true,
511
+ dependencies: [SupplierBookingDesk]
512
+ }).annotate(ToolExecutionClass, "idempotent");
513
+ /**
514
+ * The Durable Tool: declaring `DurableStep` in `dependencies` is what makes it durable
515
+ * (GLOSSARY.md). Its handler divides supplier mutation into three named Steps — `reserve-flight`,
516
+ * `reserve-lodging`, `issue-confirmation` — each deriving its supplier idempotency key from
517
+ * `(toolCallId, stepName)`, so re-entry after interruption replays recorded Step results and the
518
+ * supplier dedupes any honestly-repeated call. The Tool itself carries no execution-class
519
+ * annotation: it stays fail-closed `uncertain`, and `TravelSupplierReconcilerLayer` proves
520
+ * re-entry safe from the keyed-Step construction instead.
521
+ */
522
+ const BookItinerary = Tool.make("book_itinerary", {
523
+ parameters: ItineraryBookingRequest,
524
+ success: ItineraryConfirmation,
525
+ failure: Schema.Union([SupplierUnavailable, DurableStepError]),
526
+ failureMode: "error",
527
+ dependencies: [DurableStep, SupplierBookingDesk]
528
+ });
529
+ const TravelPlannerPhase5Toolkit = Toolkit.make(DurableSearchFlights, DurableSearchLodging, DurableSearchActivities, BookFlight, CancelBooking, BookItinerary);
530
+ const requireToolCallId = (toolName, toolCallId) => toolCallId === void 0 ? Effect.fail(SupplierUnavailable.make({ message: `${toolName} needs its stable Tool Call ID to derive the supplier idempotency key.` })) : Effect.succeed(toolCallId);
531
+ const TravelPlannerPhase5ToolkitLayer = TravelPlannerPhase5Toolkit.toLayer({
532
+ search_flights: (query) => Effect.flatMap(FlightCatalog, (catalog) => catalog.search(FlightQuery.make(query))),
533
+ search_lodging: (query) => Effect.flatMap(LodgingCatalog, (catalog) => catalog.search(LodgingQuery.make(query))),
534
+ search_activities: (query) => Effect.flatMap(ActivityCatalog, (catalog) => catalog.search(ActivityQuery.make(query))),
535
+ book_flight: (request, context) => Effect.gen(function* () {
536
+ const desk = yield* SupplierBookingDesk;
537
+ const toolCallId = yield* requireToolCallId("book_flight", context.toolCallId);
538
+ const record = yield* desk.book({
539
+ operation: "book-flight",
540
+ idempotencyKey: bookFlightIdempotencyKey(toolCallId),
541
+ detail: `flight ${request.quoteId} for ${request.travelerRef} on ${request.departOn}`
542
+ });
543
+ return SupplierBookingConfirmation.make({
544
+ bookingRef: record.bookingRef,
545
+ status: "confirmed",
546
+ detail: record.detail
547
+ });
548
+ }),
549
+ cancel_booking: (request) => Effect.gen(function* () {
550
+ const record = yield* (yield* SupplierBookingDesk).cancel(request.bookingRef);
551
+ return CancellationConfirmation.make({
552
+ bookingRef: record.bookingRef,
553
+ status: "cancelled"
554
+ });
555
+ }),
556
+ book_itinerary: (request, context) => Effect.gen(function* () {
557
+ const desk = yield* SupplierBookingDesk;
558
+ const step = yield* DurableStep;
559
+ const toolCallId = yield* requireToolCallId("book_itinerary", context.toolCallId);
560
+ const bookStep = (stepName, detail) => step.do(stepName, SupplierBookingRecord, desk.book({
561
+ operation: stepName,
562
+ idempotencyKey: itineraryStepIdempotencyKey(toolCallId, stepName),
563
+ detail
564
+ }));
565
+ const flight = yield* bookStep("reserve-flight", `flight ${request.quoteId} for ${request.travelerRef}`);
566
+ const lodging = yield* bookStep("reserve-lodging", `lodging ${request.destination} for ${request.nights} nights (${request.travelerRef})`);
567
+ const confirmation = yield* bookStep("issue-confirmation", `itinerary confirmation for ${request.travelerRef}`);
568
+ return ItineraryConfirmation.make({
569
+ flightBookingRef: flight.bookingRef,
570
+ lodgingBookingRef: lodging.bookingRef,
571
+ confirmationCode: confirmation.bookingRef
572
+ });
573
+ })
574
+ });
575
+ const decodePersistedJson = Schema.decodeUnknownEffect(PersistedJson);
576
+ const encodeConfirmation = Schema.encodeEffect(SupplierBookingConfirmation);
577
+ /**
578
+ * The application reconciliation policy (durability §10): a claim about EXTERNAL truth, queried
579
+ * from the supplier desk by the same idempotency-key derivations the handlers use.
580
+ *
581
+ * - `book_flight`: a confirmed booking under `book-flight:{toolCallId}` is recovered supplier
582
+ * truth — `CompletedWithResult` settles it canonically without executing anything. Absence is
583
+ * NOT proof the call never started (a real supplier write could be in flight), so the desk
584
+ * answer stays fail-closed `Uncertain`.
585
+ * - `book_itinerary`: every external mutation inside is a named Step whose supplier idempotency
586
+ * key derives from `(toolCallId, stepName)`, so re-entry is provably safe by construction —
587
+ * `SafeToRetry`. Committed Steps replay from their records; repeated calls dedupe at the desk.
588
+ * - `cancel_booking`: declared `idempotent`, so the coordinator re-executes without consulting
589
+ * this policy; if ever asked, the bookingRef contract makes `SafeToRetry` honest.
590
+ * - anything else: fail-closed `Uncertain` (AGENTS rule 11).
591
+ */
592
+ const TravelSupplierReconcilerLayer = Layer.effect(ToolReconciler, Effect.gen(function* () {
593
+ const desk = yield* SupplierBookingDesk;
594
+ return ToolReconciler.of({ reconcile: (evidence) => Effect.gen(function* () {
595
+ switch (evidence.toolName) {
596
+ case "book_flight": {
597
+ const key = bookFlightIdempotencyKey(evidence.toolCallId);
598
+ const booking = yield* desk.lookup(key);
599
+ if (Option.isSome(booking) && booking.value.status === "confirmed") {
600
+ const confirmation = yield* encodeConfirmation(SupplierBookingConfirmation.make({
601
+ bookingRef: booking.value.bookingRef,
602
+ status: "confirmed",
603
+ detail: booking.value.detail
604
+ })).pipe(Effect.flatMap(decodePersistedJson));
605
+ return ReconciliationCompleted.make({
606
+ result: confirmation,
607
+ isFailure: false
608
+ });
609
+ }
610
+ return ReconciliationUncertain.make({ reason: `The supplier desk shows no confirmed booking under ${key}; a write may still be in flight.` });
611
+ }
612
+ case "book_itinerary": return ReconciliationSafeToRetry.make();
613
+ case "cancel_booking": return ReconciliationSafeToRetry.make();
614
+ default: return ReconciliationUncertain.make({ reason: `No supplier reconciliation exists for ${evidence.toolName}.` });
615
+ }
616
+ }).pipe(Effect.mapError((error) => ToolReconcilerError.make({
617
+ toolCallId: evidence.toolCallId,
618
+ message: `Supplier reconciliation failed: ${error.message}`
619
+ }))) });
620
+ }));
621
+ /**
622
+ * The cumulative Travel Planner, Phase 5: the durable planner now performs consequential
623
+ * supplier mutation under the full uncertainty protocol — approval-gated uncertain booking,
624
+ * idempotent-by-contract cancellation, and one Durable Tool whose Steps carry supplier
625
+ * idempotency keys.
626
+ */
627
+ const TravelPlannerPhase5 = Agent.make("travel-planner-phase-5", {
628
+ input: TripRequest,
629
+ output: TravelBookingReport,
630
+ instructions: [
631
+ "You are the Effect Agent Travel Planner P5 booking fixture.",
632
+ "Search with the read-only tools, then book with book_flight, book_itinerary, or",
633
+ "cancel_booking exactly as scripted. Every consequential mutation is approval-gated",
634
+ "or Step-structured. Return only a JSON object with summary and bookingRefs."
635
+ ].join(" "),
636
+ toolkit: TravelPlannerPhase5Toolkit,
637
+ policy: AgentPolicy.make({
638
+ maxTurns: 4,
639
+ maxToolCalls: 6,
640
+ maxDuration: "30 seconds",
641
+ toolConcurrency: 2
642
+ }),
643
+ description: "Durably book one itinerary with prepared/settled supplier records, Unknown Outcomes, named Steps, and joined traveler input.",
644
+ metadata: {
645
+ deploymentClass: "DN",
646
+ phase: "P5"
647
+ }
648
+ });
649
+ var TravelPlannerBookingEvidenceError = class extends Schema.TaggedError()("TravelPlannerBookingEvidenceError", { message: Schema.String }) {};
650
+ const bookingResultRefs = (result) => {
651
+ if (typeof result !== "object" || result === null) return [];
652
+ const refs = [];
653
+ for (const [field, value] of Object.entries(result)) if (typeof value === "string" && (field === "bookingRef" || field === "flightBookingRef" || field === "lodgingBookingRef" || field === "confirmationCode")) refs.push(value);
654
+ return refs;
655
+ };
656
+ const bookingToolNames = /* @__PURE__ */ new Set([
657
+ "book_flight",
658
+ "cancel_booking",
659
+ "book_itinerary"
660
+ ]);
661
+ /**
662
+ * Never-fabricate assertion (ROADMAP P5 exit gate): every successfully settled booking result in
663
+ * canonical history must reference a booking that actually exists in the supplier store. A
664
+ * `ToolCallSettled` whose bookingRef the supplier cannot produce would be a fabricated result —
665
+ * the exact lie the uncertainty protocol exists to prevent.
666
+ */
667
+ const assertSettledBookingsExistAtSupplier = Effect.fn("TravelPlannerPhase5.assertSettledBookingsExistAtSupplier")(function* (records) {
668
+ const bookings = yield* (yield* SupplierBookingDesk).bookings;
669
+ const knownRefs = new Set(bookings.map((booking) => booking.bookingRef));
670
+ for (const envelope of records) {
671
+ const payload = envelope.record.payload;
672
+ if (payload._tag !== "ToolCallSettled" || payload.isFailure || !bookingToolNames.has(payload.toolName)) continue;
673
+ for (const ref of bookingResultRefs(payload.result)) if (!knownRefs.has(ref)) return yield* TravelPlannerBookingEvidenceError.make({ message: `Canonical record ${envelope.record.recordId} settled bookingRef ${ref}, which the supplier store cannot produce — a fabricated result.` });
674
+ }
675
+ });
676
+ /**
677
+ * Everything a durable P5 worker needs beyond the runtime stack and the supplier desk: the
678
+ * booking toolkit plus the deterministic P1 travel-service Layers. `SupplierBookingDesk` is
679
+ * deliberately NOT provided here — tests own the desk's lifetime so its counters, bookings, and
680
+ * crash windows survive Tool-Layer rebuilds across Attempts.
681
+ */
682
+ const phase5TravelPlannerWorkerLayer = Layer.mergeAll(TravelPlannerPhase5ToolkitLayer, FlightCatalogLayer, LodgingCatalogLayer, ActivityCatalogLayer).pipe(Layer.provide(CatalogLifecycle.layerNoDeps));
683
+ //#endregion
684
+ //#region src/fixtures/travel-planner/subagents.ts
685
+ var DestinationQuery = class extends Schema.Class("DestinationQuery")({ destination: AirportCode }) {};
686
+ var DestinationFacts = class extends Schema.Class("DestinationFacts")({
687
+ destination: AirportCode,
688
+ highlights: Schema.Array(Schema.String),
689
+ advisory: Schema.NonEmptyString
690
+ }) {};
691
+ var DestinationGuideUnavailable = class extends Schema.TaggedError()("DestinationGuideUnavailable", {
692
+ destination: AirportCode,
693
+ message: Schema.String
694
+ }) {};
695
+ var DestinationGuide = class extends Context.Service()("@effect-agent/testing/travel-planner/DestinationGuide") {};
696
+ const LookupDestination = Tool.make("lookup_destination", {
697
+ parameters: DestinationQuery,
698
+ success: DestinationFacts,
699
+ failure: DestinationGuideUnavailable,
700
+ failureMode: "error",
701
+ dependencies: [DestinationGuide]
702
+ });
703
+ const DestinationResearcherToolkit = Toolkit.make(LookupDestination);
704
+ const DestinationResearcherToolkitLayer = DestinationResearcherToolkit.toLayer({ lookup_destination: (query) => Effect.flatMap(DestinationGuide, (guide) => guide.lookup(query)) });
705
+ var DestinationBrief = class extends Schema.Class("DestinationBrief")({
706
+ destination: AirportCode,
707
+ focus: Schema.NonEmptyString
708
+ }) {};
709
+ var DestinationReport = class extends Schema.Class("DestinationReport")({
710
+ destination: AirportCode,
711
+ highlights: Schema.Array(Schema.String),
712
+ advisory: Schema.NonEmptyString
713
+ }) {};
714
+ const DestinationResearcher = Agent.make("destination-researcher", {
715
+ input: DestinationBrief,
716
+ output: DestinationReport,
717
+ instructions: "Consult lookup_destination exactly once for the briefed airport, then return only a JSON destination report.",
718
+ toolkit: DestinationResearcherToolkit,
719
+ policy: AgentPolicy.make({
720
+ maxTurns: 2,
721
+ maxToolCalls: 1,
722
+ maxDuration: "30 seconds",
723
+ toolConcurrency: 1
724
+ }),
725
+ description: "Research one candidate destination with the deterministic travel guide.",
726
+ metadata: {
727
+ deploymentClass: "E",
728
+ phase: "S1"
729
+ }
730
+ });
731
+ const decodeAirportCode = Schema.decodeSync(AirportCode);
732
+ const guideFacts = /* @__PURE__ */ new Map([["LHR", DestinationFacts.make({
733
+ destination: decodeAirportCode("LHR"),
734
+ highlights: ["Barbican brutalism walk", "Kew glasshouse survey"],
735
+ advisory: "London favors museum mornings and riverside evenings."
736
+ })], ["CDG", DestinationFacts.make({
737
+ destination: decodeAirportCode("CDG"),
738
+ highlights: ["Marais passage crawl", "Seine bookstall loop"],
739
+ advisory: "Paris rewards early galleries and late cafes."
740
+ })]]);
741
+ /** Deterministic guide lookup shared by the default and test-local guide Layers. */
742
+ const destinationLookup = (query) => {
743
+ const facts = guideFacts.get(query.destination);
744
+ return facts === void 0 ? Effect.fail(DestinationGuideUnavailable.make({
745
+ destination: query.destination,
746
+ message: "No deterministic guide entry exists for this destination."
747
+ })) : Effect.succeed(facts);
748
+ };
749
+ const requireDestinationFacts = (destination) => {
750
+ const facts = guideFacts.get(destination);
751
+ if (facts === void 0) throw new Error(`No deterministic guide entry exists for destination ${destination}`);
752
+ return facts;
753
+ };
754
+ /** The report the scripted researcher writes after consulting the guide. */
755
+ const destinationReportFor = (destination) => {
756
+ const facts = requireDestinationFacts(destination);
757
+ return DestinationReport.make({
758
+ destination: facts.destination,
759
+ highlights: facts.highlights,
760
+ advisory: facts.advisory
761
+ });
762
+ };
763
+ const encodedDestinationReport = (destination) => JSON.stringify(Schema.encodeSync(DestinationReport)(destinationReportFor(destination)));
764
+ const DestinationGuideLayer = Layer.effect(DestinationGuide, Effect.gen(function* () {
765
+ const lifecycle = yield* CatalogLifecycle;
766
+ yield* Effect.acquireRelease(lifecycle.markAcquired, () => lifecycle.markFinalized);
767
+ return DestinationGuide.of({ lookup: destinationLookup });
768
+ }));
769
+ /** Child-side construction requirements of the delegation handler Layer. */
770
+ const DestinationResearchSupportLayer = Layer.mergeAll(DestinationResearcherToolkitLayer, DestinationGuideLayer);
771
+ var DestinationResearchRequest = class extends Schema.Class("DestinationResearchRequest")({
772
+ destination: AirportCode,
773
+ focus: Schema.NonEmptyString
774
+ }) {};
775
+ var DestinationResearchFindings = class extends Schema.Class("DestinationResearchFindings")({
776
+ destination: AirportCode,
777
+ summary: Schema.NonEmptyString
778
+ }) {};
779
+ var DestinationResearchFailed = class extends Schema.TaggedError()("DestinationResearchFailed", { childErrorTag: Schema.NonEmptyString }) {};
780
+ /**
781
+ * Deterministic delegation-admission choreography seam. `prepareInput` awaits
782
+ * this gate before the handler reserves budget or spawns, so tests can order
783
+ * concurrent delegation preflights without sleeps. It also keeps the
784
+ * projection's construction requirements honestly visible in the handler
785
+ * Layer's `R`. The open Layer never waits.
786
+ */
787
+ var ResearchDispatchGate = class ResearchDispatchGate extends Context.Service()("@effect-agent/testing/travel-planner/ResearchDispatchGate") {
788
+ static layerOpen = Layer.succeed(this, ResearchDispatchGate.of({ awaitDispatch: () => Effect.void }));
789
+ };
790
+ /**
791
+ * Finite per-invocation bounds (SUB-009): each child may use two Turns and
792
+ * one Tool Call; the parent Run may establish at most two children with at
793
+ * most two running concurrently.
794
+ */
795
+ const destinationResearchPolicy = SubagentPolicy.make({
796
+ maxChildren: 2,
797
+ maxConcurrency: 2,
798
+ maxTurns: 2,
799
+ maxToolCalls: 1,
800
+ maxDuration: "10 seconds"
801
+ });
802
+ const destinationResearchDelegation = Subagent.define("delegate_destination_research", {
803
+ description: "Research one candidate destination with the deterministic travel guide and return a bounded finding.",
804
+ target: DestinationResearcher,
805
+ parameters: DestinationResearchRequest,
806
+ success: DestinationResearchFindings,
807
+ failure: DestinationResearchFailed,
808
+ prepareInput: (request) => Effect.gen(function* () {
809
+ yield* (yield* ResearchDispatchGate).awaitDispatch(request.destination);
810
+ return DestinationBrief.make({
811
+ destination: request.destination,
812
+ focus: `research:${request.focus}`
813
+ });
814
+ }),
815
+ projectResult: (report) => Effect.succeed(DestinationResearchFindings.make({
816
+ destination: report.destination,
817
+ summary: report.advisory
818
+ })),
819
+ policy: destinationResearchPolicy
820
+ });
821
+ /** Total mapping from every expected child Run failure to the declared Tool failure (SUB-028). */
822
+ const mapResearchChildFailure = (failure) => DestinationResearchFailed.make({ childErrorTag: failure._tag });
823
+ /** Runtime wiring: pair the immutable delegation with one explicit child Binding. */
824
+ const destinationResearchHandlersLayer = (childBinding) => SubagentRuntime.layer(destinationResearchDelegation, childBinding, { mapChildFailure: mapResearchChildFailure });
825
+ var ResearchMission = class extends Schema.Class("ResearchMission")({
826
+ request: Schema.NonEmptyString,
827
+ candidates: Schema.Array(AirportCode).check(Schema.isMinLength(1))
828
+ }) {};
829
+ var DestinationRecommendation = class extends Schema.Class("DestinationRecommendation")({
830
+ destination: AirportCode,
831
+ summary: Schema.NonEmptyString
832
+ }) {};
833
+ var DestinationShortlist = class extends Schema.Class("DestinationShortlist")({
834
+ recommendations: Schema.Array(DestinationRecommendation),
835
+ nextAction: Schema.Literal("review")
836
+ }) {};
837
+ /** Parent-only transcript markers used to prove child context isolation (SUB-006/015). */
838
+ const coordinatorConfidentialMarker = "coordinator-vault-7q42";
839
+ const missionConfidentialMarker = "traveler-dossier-19f";
840
+ const TravelCoordinatorToolkit = Toolkit.make(destinationResearchDelegation.tool);
841
+ const TravelCoordinator = Agent.make("travel-coordinator", {
842
+ input: ResearchMission,
843
+ output: DestinationShortlist,
844
+ instructions: [
845
+ "You are the Effect Agent Travel Planner S1 delegation coordinator.",
846
+ `Coordinator-only context: ${coordinatorConfidentialMarker}.`,
847
+ "Call delegate_destination_research once per candidate in one Tool batch.",
848
+ "Return only a JSON shortlist built from the delegated findings. This is read-only planning."
849
+ ].join("\n"),
850
+ toolkit: TravelCoordinatorToolkit,
851
+ policy: AgentPolicy.make({
852
+ maxTurns: 2,
853
+ maxToolCalls: 3,
854
+ maxDuration: "30 seconds",
855
+ toolConcurrency: 3
856
+ }),
857
+ description: "Coordinate bounded destination research through one declared attached delegation Tool.",
858
+ metadata: {
859
+ deploymentClass: "E",
860
+ phase: "S1"
861
+ }
862
+ });
863
+ const researchMission = Schema.decodeSync(ResearchMission)({
864
+ request: `Shortlist one September culture city; keep ${missionConfidentialMarker} inside the coordinator thread.`,
865
+ candidates: ["LHR", "CDG"]
866
+ });
867
+ const expectedDestinationShortlist = DestinationShortlist.make({
868
+ recommendations: researchMission.candidates.map((destination) => DestinationRecommendation.make({
869
+ destination,
870
+ summary: requireDestinationFacts(destination).advisory
871
+ })),
872
+ nextAction: "review"
873
+ });
874
+ const scriptedUsage$2 = {
875
+ inputTokens: { total: 96 },
876
+ outputTokens: { total: 64 }
877
+ };
878
+ /** One coordinator Turn that declares the given delegation Tool Calls in order. */
879
+ const coordinatorResearchTurn = (calls) => ({
880
+ _tag: "Stream",
881
+ parts: [...calls.map((call) => ({
882
+ type: "tool-call",
883
+ id: call.id,
884
+ name: "delegate_destination_research",
885
+ params: {
886
+ destination: call.destination,
887
+ focus: call.focus
888
+ }
889
+ })), {
890
+ type: "finish",
891
+ reason: "tool-calls",
892
+ usage: scriptedUsage$2
893
+ }],
894
+ termination: { _tag: "Complete" }
895
+ });
896
+ /** The coordinator's final structured-output Turn. */
897
+ const coordinatorShortlistTurn = (shortlist) => ({
898
+ _tag: "Stream",
899
+ parts: [
900
+ {
901
+ type: "text-start",
902
+ id: "shortlist"
903
+ },
904
+ {
905
+ type: "text-delta",
906
+ id: "shortlist",
907
+ delta: JSON.stringify(Schema.encodeSync(DestinationShortlist)(shortlist))
908
+ },
909
+ {
910
+ type: "text-end",
911
+ id: "shortlist"
912
+ },
913
+ {
914
+ type: "finish",
915
+ reason: "stop",
916
+ usage: scriptedUsage$2
917
+ }
918
+ ],
919
+ termination: { _tag: "Complete" }
920
+ });
921
+ /** Static researcher script for single-child tests: one guide lookup, then the report. */
922
+ const researcherHappyPathTurns = (destination) => [{
923
+ _tag: "Stream",
924
+ parts: [{
925
+ type: "tool-call",
926
+ id: `lookup-${destination}`,
927
+ name: "lookup_destination",
928
+ params: { destination }
929
+ }, {
930
+ type: "finish",
931
+ reason: "tool-calls",
932
+ usage: scriptedUsage$2
933
+ }],
934
+ termination: { _tag: "Complete" }
935
+ }, {
936
+ _tag: "Stream",
937
+ parts: [
938
+ {
939
+ type: "text-start",
940
+ id: "destination-report"
941
+ },
942
+ {
943
+ type: "text-delta",
944
+ id: "destination-report",
945
+ delta: encodedDestinationReport(destination)
946
+ },
947
+ {
948
+ type: "text-end",
949
+ id: "destination-report"
950
+ },
951
+ {
952
+ type: "finish",
953
+ reason: "stop",
954
+ usage: scriptedUsage$2
955
+ }
956
+ ],
957
+ termination: { _tag: "Complete" }
958
+ }];
959
+ const researcherLookupParts$2 = (destination) => [{
960
+ type: "tool-call",
961
+ id: `lookup-${destination}`,
962
+ name: "lookup_destination",
963
+ params: { destination },
964
+ providerExecuted: false
965
+ }, {
966
+ type: "finish",
967
+ reason: "tool-calls",
968
+ usage: scriptedUsage$2
969
+ }];
970
+ const researcherReportParts$2 = (destination) => [
971
+ {
972
+ type: "text-start",
973
+ id: "destination-report"
974
+ },
975
+ {
976
+ type: "text-delta",
977
+ id: "destination-report",
978
+ delta: encodedDestinationReport(destination)
979
+ },
980
+ {
981
+ type: "text-end",
982
+ id: "destination-report"
983
+ },
984
+ {
985
+ type: "finish",
986
+ reason: "stop",
987
+ usage: scriptedUsage$2
988
+ }
989
+ ];
990
+ /**
991
+ * Build a deterministic researcher Model whose per-child behavior is keyed by
992
+ * the destination named in the child's own prompt: Turn one records the
993
+ * prompt, signals `started`, and calls the guide Tool; Turn two waits for the
994
+ * caller's `release` before writing the report. Each child Run builds the
995
+ * Model Layer inside its own scope, so one `CatalogLifecycle` acquisition and
996
+ * finalization is observed per child — the same acquire/release counting the
997
+ * catalog Layers use to prove interruption reaches every finalizer.
998
+ */
999
+ const makeDestinationResearcherModel = (destinations) => Effect.gen(function* () {
1000
+ const lifecycle = yield* CatalogLifecycle;
1001
+ const prompts = yield* Ref.make([]);
1002
+ const gates = /* @__PURE__ */ new Map();
1003
+ for (const destination of destinations) gates.set(destination, {
1004
+ started: yield* Deferred.make(),
1005
+ release: yield* Deferred.make()
1006
+ });
1007
+ const gatesFor = (destination) => Effect.suspend(() => {
1008
+ const entry = gates.get(destination);
1009
+ return entry === void 0 ? Effect.die(/* @__PURE__ */ new Error(`No researcher gates exist for destination ${destination}`)) : Effect.succeed(entry);
1010
+ });
1011
+ return {
1012
+ controls: {
1013
+ awaitStarted: (destination) => gatesFor(destination).pipe(Effect.flatMap((entry) => Deferred.await(entry.started))),
1014
+ release: (destination) => gatesFor(destination).pipe(Effect.flatMap((entry) => Deferred.succeed(entry.release, void 0)), Effect.asVoid),
1015
+ prompts: Ref.get(prompts)
1016
+ },
1017
+ model: Model.make("scripted", "destination-researcher-scripted", Layer.effect(LanguageModel.LanguageModel, Effect.gen(function* () {
1018
+ yield* Effect.acquireRelease(lifecycle.markAcquired, () => lifecycle.markFinalized);
1019
+ const turn = yield* Ref.make(0);
1020
+ return yield* LanguageModel.make({
1021
+ generateText: () => Effect.succeed([]),
1022
+ streamText: (options) => Stream.unwrap(Effect.gen(function* () {
1023
+ const promptJson = JSON.stringify(options.prompt.content);
1024
+ const destination = destinations.find((candidate) => promptJson.includes(candidate));
1025
+ if (destination === void 0) return yield* Effect.die(/* @__PURE__ */ new Error("The researcher prompt names no scripted destination"));
1026
+ const entry = yield* gatesFor(destination);
1027
+ if ((yield* Ref.getAndUpdate(turn, (value) => value + 1)) === 0) {
1028
+ yield* Ref.update(prompts, (previous) => [...previous, promptJson]);
1029
+ yield* Deferred.succeed(entry.started, void 0);
1030
+ return Stream.fromIterable(researcherLookupParts$2(destination));
1031
+ }
1032
+ yield* Deferred.await(entry.release);
1033
+ return Stream.fromIterable(researcherReportParts$2(destination));
1034
+ }))
1035
+ });
1036
+ })))
1037
+ };
1038
+ });
1039
+ //#endregion
1040
+ //#region src/fixtures/travel-planner/subagents-durable.ts
1041
+ var TravelPlannerSubagentDurabilityProfile = class extends Schema.Class("@effect-agent/testing/travel-planner/TravelPlannerSubagentDurabilityProfile")({
1042
+ deploymentClass: Schema.Literal("DN"),
1043
+ durableAttachedSubagents: Schema.Literal(true),
1044
+ canonicalSchemaVersion: Schema.Literal(1),
1045
+ /** Establishment/join replay converges on one child Receipt, Thread, and join batch. */
1046
+ subagentReplaySafe: Schema.Literal(true),
1047
+ /** Never claimed (rule 8): child ordinary Tools stop at Unknown Outcomes, they do not replay. */
1048
+ childExternalEffectsExactlyOnce: Schema.Literal(false),
1049
+ /** The same conformance suite under DO eviction/alarms is P6 scope (spec §17 `DC`). */
1050
+ cloudflareEquivalence: Schema.Literal(false)
1051
+ }) {};
1052
+ const s2TravelPlannerProfile = TravelPlannerSubagentDurabilityProfile.make({
1053
+ deploymentClass: "DN",
1054
+ durableAttachedSubagents: true,
1055
+ canonicalSchemaVersion: 1,
1056
+ subagentReplaySafe: true,
1057
+ childExternalEffectsExactlyOnce: false,
1058
+ cloudflareEquivalence: false
1059
+ });
1060
+ const s2TravelPlannerDeploymentId = Schema.decodeSync(DeploymentId)("travel-planner-s2-deployment");
1061
+ const s2TravelPlannerProducerId = Schema.decodeSync(ProducerId)("travel-planner-s2-producer");
1062
+ const s2TravelPlannerPrincipal = Schema.decodeSync(Principal)("travel-planner-s2-principal");
1063
+ const digestOf$1 = (character) => Schema.decodeSync(Digest)(character.repeat(64));
1064
+ /** Redacted, deterministic parent (coordinator) definition digests for this fixture version. */
1065
+ const s2CoordinatorDigests = DefinitionDigests.make({
1066
+ agent: digestOf$1("a"),
1067
+ model: digestOf$1("b"),
1068
+ tools: digestOf$1("c")
1069
+ });
1070
+ /**
1071
+ * The exact child Binding digest strings the application declares on
1072
+ * `SubagentRuntimeOptions.durable.targetDigests` AND the host registers with
1073
+ * the host's binding array for the researcher Binding. The coordinator
1074
+ * stores and verifies them byte-for-byte (SUB-023); a host registration under
1075
+ * different strings is a `ChildCompatibilityFailure`, never a substitution.
1076
+ */
1077
+ const s2ResearcherDigestStrings = {
1078
+ agent: "d".repeat(64),
1079
+ model: "e".repeat(64),
1080
+ tools: "f".repeat(64)
1081
+ };
1082
+ const s2ResearcherDigests = DefinitionDigests.make({
1083
+ agent: Schema.decodeSync(Digest)(s2ResearcherDigestStrings.agent),
1084
+ model: Schema.decodeSync(Digest)(s2ResearcherDigestStrings.model),
1085
+ tools: Schema.decodeSync(Digest)(s2ResearcherDigestStrings.tools)
1086
+ });
1087
+ /** Durable admission options for one coordinator Submission on one mission lane. */
1088
+ const s2TravelPlannerSubmitOptions = (threadId, idempotencyKey) => ({
1089
+ threadId,
1090
+ principal: s2TravelPlannerPrincipal,
1091
+ idempotencyKey,
1092
+ definitions: s2CoordinatorDigests
1093
+ });
1094
+ /** The structural submit slice of the coordinator Binding (`DurableAgentRuntime.submit`). */
1095
+ const s2CoordinatorSubmitAgent = { definition: {
1096
+ id: TravelCoordinator.id,
1097
+ input: TravelCoordinator.input
1098
+ } };
1099
+ /**
1100
+ * The per-invocation reservation the durable handler computes from the S1
1101
+ * delegation policy (`delegationAllocationFromPolicy`): the conservation
1102
+ * evidence in the S2 tests checks the ledger reservation rows and the
1103
+ * canonical `SubagentJoined.finalAccounting` against exactly this value.
1104
+ */
1105
+ const durableResearchAllocation = delegationAllocationFromPolicy(destinationResearchPolicy);
1106
+ /** The one scripted delegation Tool Call id of the durable coordinator Run. */
1107
+ const durableResearchCallId = "research-lhr-1";
1108
+ /** The child's own scripted guide-lookup Tool Call id. */
1109
+ const durableChildLookupCallId = (destination) => `lookup-${destination}`;
1110
+ /** The projected finding the parent joins (only the advisory crosses, SUB-015). */
1111
+ const durableResearchFinding = (destination) => ({
1112
+ destination: destinationReportFor(destination).destination,
1113
+ summary: destinationReportFor(destination).advisory
1114
+ });
1115
+ /** The coordinator's expected final shortlist for one researched destination. */
1116
+ const durableResearchShortlist = (destination) => DestinationShortlist.make({
1117
+ recommendations: [DestinationRecommendation.make({
1118
+ destination: destinationReportFor(destination).destination,
1119
+ summary: destinationReportFor(destination).advisory
1120
+ })],
1121
+ nextAction: "review"
1122
+ });
1123
+ /**
1124
+ * The deterministic guide facts in encoded (wire) form: the "supplier truth"
1125
+ * an authorized operator records through `resolveUnknown` when a child guide
1126
+ * lookup stopped at an Unknown Outcome (DUR-017 — the framework never guesses
1127
+ * or replays it).
1128
+ */
1129
+ const encodedDestinationFacts = (destination) => {
1130
+ const report = destinationReportFor(destination);
1131
+ return Schema.encodeSync(DestinationFacts)(DestinationFacts.make({
1132
+ destination: report.destination,
1133
+ highlights: report.highlights,
1134
+ advisory: report.advisory
1135
+ }));
1136
+ };
1137
+ const scriptedUsage$1 = {
1138
+ inputTokens: { total: 96 },
1139
+ outputTokens: { total: 64 }
1140
+ };
1141
+ /** One scripted model whose behavior is keyed by the global invocation index. */
1142
+ const makeInvocationCountingModel = (name, script) => Effect.gen(function* () {
1143
+ const calls = yield* Ref.make(0);
1144
+ const prompts = yield* Ref.make([]);
1145
+ return {
1146
+ model: Model.make("scripted", name, Layer.effect(LanguageModel.LanguageModel, LanguageModel.make({
1147
+ generateText: () => Effect.succeed([]),
1148
+ streamText: (request) => Stream.unwrap(Effect.gen(function* () {
1149
+ const call = yield* Ref.getAndUpdate(calls, (value) => value + 1);
1150
+ yield* Ref.update(prompts, (previous) => [...previous, JSON.stringify(request.prompt.content)]);
1151
+ return Stream.fromIterable(script(call));
1152
+ }))
1153
+ }))),
1154
+ calls: Ref.get(calls),
1155
+ prompts: Ref.get(prompts)
1156
+ };
1157
+ });
1158
+ const delegationTurnParts = (toolCallId, destination, focus) => [{
1159
+ type: "tool-call",
1160
+ id: toolCallId,
1161
+ name: "delegate_destination_research",
1162
+ params: {
1163
+ destination,
1164
+ focus
1165
+ },
1166
+ providerExecuted: false
1167
+ }, {
1168
+ type: "finish",
1169
+ reason: "tool-calls",
1170
+ usage: scriptedUsage$1
1171
+ }];
1172
+ const shortlistParts = (shortlist) => [
1173
+ {
1174
+ type: "text-start",
1175
+ id: "shortlist"
1176
+ },
1177
+ {
1178
+ type: "text-delta",
1179
+ id: "shortlist",
1180
+ delta: JSON.stringify(Schema.encodeSync(DestinationShortlist)(shortlist))
1181
+ },
1182
+ {
1183
+ type: "text-end",
1184
+ id: "shortlist"
1185
+ },
1186
+ {
1187
+ type: "finish",
1188
+ reason: "stop",
1189
+ usage: scriptedUsage$1
1190
+ }
1191
+ ];
1192
+ const researcherLookupParts$1 = (destination) => [{
1193
+ type: "tool-call",
1194
+ id: durableChildLookupCallId(destination),
1195
+ name: "lookup_destination",
1196
+ params: { destination },
1197
+ providerExecuted: false
1198
+ }, {
1199
+ type: "finish",
1200
+ reason: "tool-calls",
1201
+ usage: scriptedUsage$1
1202
+ }];
1203
+ const researcherReportParts$1 = (destination) => [
1204
+ {
1205
+ type: "text-start",
1206
+ id: "destination-report"
1207
+ },
1208
+ {
1209
+ type: "text-delta",
1210
+ id: "destination-report",
1211
+ delta: encodedDestinationReport(destination)
1212
+ },
1213
+ {
1214
+ type: "text-end",
1215
+ id: "destination-report"
1216
+ },
1217
+ {
1218
+ type: "finish",
1219
+ reason: "stop",
1220
+ usage: scriptedUsage$1
1221
+ }
1222
+ ];
1223
+ /** Runtime wiring for the durable slice: the S1 delegation plus the S2 digest declaration. */
1224
+ const durableDestinationResearchHandlersLayer = (childBinding) => SubagentRuntime.layer(destinationResearchDelegation, childBinding, {
1225
+ mapChildFailure: mapResearchChildFailure,
1226
+ durable: { targetDigests: s2ResearcherDigestStrings }
1227
+ });
1228
+ /**
1229
+ * Build the S2 Travel Planner harness: an invocation-counting scripted
1230
+ * coordinator (Turn 1 declares the one delegation call, Turn 2 writes the
1231
+ * shortlist), an invocation-counting scripted researcher (Turn 1 consults the
1232
+ * guide, Turn 2 writes the report), and both worker Bindings captured with
1233
+ * their requirement Contexts via `DurableWorkerBinding.make` under the exact
1234
+ * fixture digests. The returned `bindings` are plain values: they can be
1235
+ * registered with several `NodeDurableRuntime` stacks over the same SQLite
1236
+ * file while the counters keep counting across all of them.
1237
+ */
1238
+ const makeDurableResearchHarness = (options) => Effect.gen(function* () {
1239
+ const destination = options?.destination ?? "LHR";
1240
+ const focus = options?.focus ?? "museums";
1241
+ const guideInvocations = yield* Ref.make(0);
1242
+ const guideLayer = Layer.succeed(DestinationGuide, DestinationGuide.of({ lookup: (query) => Ref.update(guideInvocations, (count) => count + 1).pipe(Effect.andThen(destinationLookup(query))) }));
1243
+ const childToolkitLayer = DestinationResearcherToolkitLayer.pipe(Layer.provideMerge(guideLayer));
1244
+ const childModel = yield* makeInvocationCountingModel("destination-researcher-s2", (call) => call === 0 ? researcherLookupParts$1(destination) : researcherReportParts$1(destination));
1245
+ const childBinding = Agent.withModel(DestinationResearcher, childModel.model);
1246
+ const parentModel = yield* makeInvocationCountingModel("travel-coordinator-s2", (call) => call === 0 ? delegationTurnParts(durableResearchCallId, destination, focus) : shortlistParts(durableResearchShortlist(destination)));
1247
+ const parentBinding = Agent.withModel(TravelCoordinator, parentModel.model);
1248
+ const delegationLayer = durableDestinationResearchHandlersLayer(childBinding).pipe(Layer.provide(Layer.mergeAll(childToolkitLayer, SubagentReservationsMemoryLive, DeterministicIdGeneratorLayer, ResearchDispatchGate.layerOpen)));
1249
+ return {
1250
+ bindings: [yield* DurableWorkerBinding.make(parentBinding, s2CoordinatorDigests).pipe(Effect.provide(delegationLayer)), yield* DurableWorkerBinding.make(childBinding, options?.childRegistrationDigests ?? s2ResearcherDigests).pipe(Effect.provide(childToolkitLayer))],
1251
+ parentModelCalls: parentModel.calls,
1252
+ parentPrompts: parentModel.prompts,
1253
+ childModelCalls: childModel.calls,
1254
+ childPrompts: childModel.prompts,
1255
+ guideInvocations: Ref.get(guideInvocations)
1256
+ };
1257
+ });
1258
+ //#endregion
1259
+ //#region src/fixtures/travel-planner/phase6.ts
1260
+ /**
1261
+ * The Phase 6 profile: the P4/P5/S2 Travel Planner claims re-earned on the Cloudflare Durable
1262
+ * Object runtime (deployment class `DC`), where eviction and alarm redelivery replace process
1263
+ * kill and restart as the exercised recovery path. `cloudflareEquivalence` is the claim the S2
1264
+ * fixture explicitly deferred to P6 (`TravelPlannerSubagentDurabilityProfile` pins it `false`
1265
+ * for `DN`): it flips to `true` here ONLY because the phase-6 suites assert byte-equal
1266
+ * cross-platform normalized canonical evidence against one committed golden. Exactly-once
1267
+ * EXTERNAL effects remain — deliberately — unclaimed on every platform (DUR-003).
1268
+ */
1269
+ var TravelPlannerCloudflareProfile = class extends Schema.Class("@effect-agent/testing/travel-planner/TravelPlannerCloudflareProfile")({
1270
+ deploymentClass: Schema.Literal("DC"),
1271
+ durableAcceptedWork: Schema.Literal(true),
1272
+ canonicalSchemaVersion: Schema.Literal(1),
1273
+ /** P5 semantics under DC recovery: prepared/settled records, Unknown Outcomes, approvals. */
1274
+ supplierBookingUncertaintyProtocol: Schema.Literal(true),
1275
+ /** S2 semantics under DC recovery: cross-Object establishment/join, completed child never re-runs. */
1276
+ durableAttachedSubagents: Schema.Literal(true),
1277
+ /** DN and DC produce byte-equal cross-platform normalized canonical evidence (one golden). */
1278
+ cloudflareEquivalence: Schema.Literal(true),
1279
+ /** Never claimed at any phase on any platform (DUR-003). */
1280
+ exactlyOnceExternalEffects: Schema.Literal(false)
1281
+ }) {};
1282
+ const phase6TravelPlannerProfile = TravelPlannerCloudflareProfile.make({
1283
+ deploymentClass: "DC",
1284
+ durableAcceptedWork: true,
1285
+ canonicalSchemaVersion: 1,
1286
+ supplierBookingUncertaintyProtocol: true,
1287
+ durableAttachedSubagents: true,
1288
+ cloudflareEquivalence: true,
1289
+ exactlyOnceExternalEffects: false
1290
+ });
1291
+ const phase6TravelPlannerDeploymentId = Schema.decodeSync(DeploymentId)("travel-planner-p6-deployment");
1292
+ /** Producer prefix of the DC host; each Object mints `{prefix}:{threadId}`. */
1293
+ const phase6TravelPlannerProducerPrefix = "travel-planner-p6-producer";
1294
+ /** The full producer identity one DC Thread Object mints for itself. */
1295
+ const phase6TravelPlannerProducerId = (threadId) => Schema.decodeSync(ProducerId)(`${phase6TravelPlannerProducerPrefix}:${threadId}`);
1296
+ const digestOf = (character) => Schema.decodeSync(Digest)(character.repeat(64));
1297
+ /**
1298
+ * Registration digests of the GATED planner Binding: the same `TravelPlannerPhase4` definition
1299
+ * bound to a model whose first response waits on a test gate, addressable separately so the
1300
+ * admission-limits rows can hold a lane busy deterministically without touching the ordinary
1301
+ * planner registration.
1302
+ */
1303
+ const phase6GatedPlannerDefinitionDigests = DefinitionDigests.make({
1304
+ agent: digestOf("9"),
1305
+ model: digestOf("8"),
1306
+ tools: digestOf("7")
1307
+ });
1308
+ const decodeComparableJson = Schema.decodeUnknownEffect(Schema.Json);
1309
+ /** The base normal form's element shape, re-decoded so sequences can be renumbered. */
1310
+ const ComparableEnvelope = Schema.Struct({
1311
+ batchId: Schema.String,
1312
+ sequence: Schema.Number,
1313
+ record: Schema.Json
1314
+ });
1315
+ const decodeComparableEnvelopes = Schema.decodeUnknownEffect(Schema.Array(ComparableEnvelope));
1316
+ /**
1317
+ * The CROSS-PLATFORM extension of `normalizeDurableTravelPlannerEvidence` (D-P6-6): after the
1318
+ * base normalization replaces the two ledger-minted identities (which also normalizes the
1319
+ * DC-format routable `{uuidv7}:{threadId}` Submission identities and everything derived
1320
+ * from them), this form additionally scrubs everything that legitimately differs between a DN
1321
+ * process and a DC Durable Object over the same scenario:
1322
+ *
1323
+ * - `RepairAnnotated` audit records are dropped BEFORE normalization and the canonical
1324
+ * sequence is renumbered to the surviving order: repairs are DUR-013 evidence of recovery
1325
+ * itself, legally present in a recovered run and legally absent from an uninterrupted
1326
+ * control (on DC even a CLEAN run carries one, because every pass reconciles before it
1327
+ * claims, so the ready lane's input is applied through the recovery path). Canonical ORDER
1328
+ * is the durability §5 claim; sequence contiguity is a platform artifact of who appended;
1329
+ * - the Thread identity (DC lanes mint unique names per test run);
1330
+ * - the deployment and producer identities (host configuration, not canonical semantics);
1331
+ * - `createdAt` commit timestamps (wall clock);
1332
+ * - 64-hex digests (they hash RAW content that legally embeds run-specific identity, so they
1333
+ * can never be byte-equal across runs; chain integrity is asserted separately by the
1334
+ * adapters and the convergence helpers).
1335
+ *
1336
+ * Two runs whose cross-platform normalized evidence is byte-equal took canonically equivalent
1337
+ * histories — the exact sense in which durability §5 permits storage differences while
1338
+ * requiring the same observable ordering. Both the DN and DC suites assert equality against
1339
+ * the one committed `phase6TravelPlannerGoldenEvidence`, so DN ≡ DC transitively.
1340
+ */
1341
+ const normalizeCrossPlatformTravelPlannerEvidence = Effect.fn("TravelPlannerPhase6.normalizeCrossPlatformTravelPlannerEvidence")(function* (records, receipt, identity) {
1342
+ const canonical = records.filter((envelope) => envelope.record.payload._tag !== "RepairAnnotated");
1343
+ const base = yield* normalizeDurableTravelPlannerEvidence(canonical, receipt);
1344
+ const scrubbed = JSON.parse(JSON.stringify(base).replaceAll(identity.producerId, "{producerId}").replaceAll(identity.deploymentId, "{deploymentId}").replaceAll(identity.threadId, "{threadId}").replaceAll(/\d{4}-\d{2}-\d{2}T[0-9:.]+Z/g, "{timestamp}").replaceAll(/"[0-9a-f]{64}"/g, "\"{digest}\""));
1345
+ const renumbered = (yield* decodeComparableEnvelopes(scrubbed).pipe(Effect.mapError((error) => TravelPlannerDurableEvidenceError.make({ message: `Cross-platform normalized evidence lost the comparable shape: ${error.message}` })))).map((entry, index) => ({
1346
+ batchId: entry.batchId,
1347
+ sequence: index + 1,
1348
+ record: entry.record
1349
+ }));
1350
+ return yield* decodeComparableJson(renumbered).pipe(Effect.mapError((error) => TravelPlannerDurableEvidenceError.make({ message: `Cross-platform normalized evidence is not comparable JSON: ${error.message}` })));
1351
+ });
1352
+ const scriptedUsage = {
1353
+ inputTokens: { total: 128 },
1354
+ outputTokens: { total: 96 }
1355
+ };
1356
+ const promptAwareModel = (name, decide) => Model.make("scripted", name, Layer.effect(LanguageModel.LanguageModel, LanguageModel.make({
1357
+ generateText: () => Effect.succeed([]),
1358
+ streamText: (options) => Stream.unwrap(Effect.sync(() => decide(JSON.stringify(options.prompt))))
1359
+ })));
1360
+ /** The P1/P4 happy-path Tool Call identities (scenarios.ts, byte-stable since P1). */
1361
+ const phase6FlightCallId = "flight-call-1";
1362
+ const phase6LodgingCallId = "lodging-call-1";
1363
+ const phase6ActivityCallId = "activity-call-1";
1364
+ /** Turn 1 of the planner: the SAME three search declarations as `phase1HappyPathTurns`. */
1365
+ const plannerSearchTurnParts = [
1366
+ {
1367
+ type: "tool-call",
1368
+ id: phase6FlightCallId,
1369
+ name: "search_flights",
1370
+ params: {
1371
+ origin: "SFO",
1372
+ destination: "LHR",
1373
+ departOn: "2026-09-14",
1374
+ travelers: 2
1375
+ }
1376
+ },
1377
+ {
1378
+ type: "tool-call",
1379
+ id: phase6LodgingCallId,
1380
+ name: "search_lodging",
1381
+ params: {
1382
+ destination: "LHR",
1383
+ departOn: "2026-09-14",
1384
+ nights: 4,
1385
+ travelers: 2
1386
+ }
1387
+ },
1388
+ {
1389
+ type: "tool-call",
1390
+ id: phase6ActivityCallId,
1391
+ name: "search_activities",
1392
+ params: {
1393
+ destination: "LHR",
1394
+ departOn: "2026-09-14",
1395
+ nights: 4,
1396
+ travelers: 2
1397
+ }
1398
+ },
1399
+ {
1400
+ type: "finish",
1401
+ reason: "tool-calls",
1402
+ usage: scriptedUsage
1403
+ }
1404
+ ];
1405
+ /** Turn 2 of the planner: the SAME itinerary text as `phase1HappyPathTurns`. */
1406
+ const plannerPlanTurnParts = [
1407
+ {
1408
+ type: "text-start",
1409
+ id: "itinerary-json"
1410
+ },
1411
+ {
1412
+ type: "text-delta",
1413
+ id: "itinerary-json",
1414
+ delta: JSON.stringify(Schema.encodeSync(TravelPlan)(expectedTravelPlan))
1415
+ },
1416
+ {
1417
+ type: "text-end",
1418
+ id: "itinerary-json"
1419
+ },
1420
+ {
1421
+ type: "finish",
1422
+ reason: "stop",
1423
+ usage: scriptedUsage
1424
+ }
1425
+ ];
1426
+ const plannerDecide = (promptJson) => promptJson.includes("flight-call-1") ? Stream.fromIterable(plannerPlanTurnParts) : Stream.fromIterable(plannerSearchTurnParts);
1427
+ /**
1428
+ * The P4 planner script (`phase1HappyPathTurns`) as a prompt-aware model: once the search
1429
+ * batch is committed history, every later request gets the plan — identical parts, so the DC
1430
+ * canonical evidence is byte-equivalent to the DN ScriptedModel run after normalization.
1431
+ */
1432
+ const phase6PlannerModel = promptAwareModel("travel-planner-phase-4", plannerDecide);
1433
+ const releasedPlannerGates = /* @__PURE__ */ new Set();
1434
+ /** Release the gated planner model for one `[gate:...]` marker. */
1435
+ const releasePhase6PlannerGate = (marker) => {
1436
+ releasedPlannerGates.add(marker);
1437
+ };
1438
+ /** Re-close one gate marker (fresh suites reuse markers safely). */
1439
+ const resetPhase6PlannerGate = (marker) => {
1440
+ releasedPlannerGates.delete(marker);
1441
+ };
1442
+ const awaitPlannerGate = (marker) => Effect.gen(function* () {
1443
+ while (!releasedPlannerGates.has(marker)) yield* Effect.sleep(Duration.millis(10));
1444
+ });
1445
+ const gateMarkerFromPrompt = (promptJson) => /\[gate:([^\]]+)\]/.exec(promptJson)?.[1] ?? "unknown-gate";
1446
+ /** A trip whose request text carries the gate marker the gated model waits on. */
1447
+ const phase6GatedTrip = (marker) => Schema.decodeUnknownSync(TripRequest)({
1448
+ request: `Plan a review-only London trip, but wait for the concierge. [gate:${marker}]`,
1449
+ origin: "SFO",
1450
+ destination: "LHR",
1451
+ departOn: "2026-09-14",
1452
+ nights: 4,
1453
+ travelers: 2,
1454
+ budgetCents: 35e4,
1455
+ currency: "USD"
1456
+ });
1457
+ /**
1458
+ * The SAME planner behavior with a hanging first response: the model waits on the released
1459
+ * gate before answering, keeping its lane durably busy so queue-depth admission limits can be
1460
+ * exercised deterministically.
1461
+ */
1462
+ const phase6GatedPlannerModel = Model.make("scripted", "travel-planner-phase-4-gated", Layer.effect(LanguageModel.LanguageModel, LanguageModel.make({
1463
+ generateText: () => Effect.succeed([]),
1464
+ streamText: (options) => Stream.unwrap(Effect.sync(() => {
1465
+ const promptJson = JSON.stringify(options.prompt);
1466
+ return promptJson.includes("flight-call-1") ? plannerDecide(promptJson) : Stream.fromEffectDrain(awaitPlannerGate(gateMarkerFromPrompt(promptJson))).pipe(Stream.concat(plannerDecide(promptJson)));
1467
+ }))
1468
+ })));
1469
+ const sharedSupplierDesk = Effect.runSync(Effect.flatMap(SupplierBookingDesk, Effect.succeed).pipe(Effect.provide(SupplierBookingDesk.layer)));
1470
+ /** The shared external supplier desk instance (module-level external truth). */
1471
+ const phase6SupplierDesk = sharedSupplierDesk;
1472
+ /** Layer handing the shared desk to Bindings, reconcilers, and assertions. */
1473
+ const phase6SupplierDeskLayer = Layer.succeed(SupplierBookingDesk, sharedSupplierDesk);
1474
+ /**
1475
+ * The REAL P5 supplier reconciliation policy over the shared desk, closed to no requirements
1476
+ * so a Thread Object can install it directly: `book_flight` recovers only from supplier
1477
+ * truth (absence stays fail-closed `Uncertain` → durable Unknown Outcome), keyed Steps are
1478
+ * provably re-enterable.
1479
+ */
1480
+ const phase6SupplierReconcilerLayer = TravelSupplierReconcilerLayer.pipe(Layer.provide(phase6SupplierDeskLayer));
1481
+ const bookingMarkerFromPrompt = (promptJson) => /\[case:([^\]]+)\]/.exec(promptJson)?.[1] ?? "unknown-case";
1482
+ /** The deterministic booking Tool Call identity for one `[case:...]` marker. */
1483
+ const phase6BookingToolCallId = (marker) => `book-${marker}`;
1484
+ /** The bookingRef the supplier desk mints for one marker's approved booking. */
1485
+ const phase6BookingRef = (marker) => supplierBookingRefFor(bookFlightIdempotencyKey(phase6BookingToolCallId(marker)));
1486
+ /** A trip whose request text carries the per-lane booking case marker. */
1487
+ const phase6BookingTrip = (marker) => Schema.decodeUnknownSync(TripRequest)({
1488
+ request: `Book the approved London flight for the traveler. [case:${marker}]`,
1489
+ origin: "SFO",
1490
+ destination: "LHR",
1491
+ departOn: "2026-09-14",
1492
+ nights: 4,
1493
+ travelers: 2,
1494
+ budgetCents: 35e4,
1495
+ currency: "USD"
1496
+ });
1497
+ const bookingCallParts = (marker) => [{
1498
+ type: "tool-call",
1499
+ id: phase6BookingToolCallId(marker),
1500
+ name: "book_flight",
1501
+ params: {
1502
+ quoteId: "quote-sfo-lhr-001",
1503
+ travelerRef: `traveler-${marker}`,
1504
+ departOn: "2026-09-14"
1505
+ },
1506
+ providerExecuted: false
1507
+ }, {
1508
+ type: "finish",
1509
+ reason: "tool-calls",
1510
+ usage: scriptedUsage
1511
+ }];
1512
+ const bookingReportParts = (marker) => [
1513
+ {
1514
+ type: "text-start",
1515
+ id: "booking-report"
1516
+ },
1517
+ {
1518
+ type: "text-delta",
1519
+ id: "booking-report",
1520
+ delta: JSON.stringify({
1521
+ summary: "trip booked",
1522
+ bookingRefs: [phase6BookingRef(marker)]
1523
+ })
1524
+ },
1525
+ {
1526
+ type: "text-end",
1527
+ id: "booking-report"
1528
+ },
1529
+ {
1530
+ type: "finish",
1531
+ reason: "stop",
1532
+ usage: scriptedUsage
1533
+ }
1534
+ ];
1535
+ /**
1536
+ * The P5 booking script as a prompt-aware model: request 1 declares the approval-gated
1537
+ * `book_flight` call (identity derived from the lane's `[case:...]` marker so supplier
1538
+ * idempotency keys never collide across lanes); once that call is committed history, the model
1539
+ * writes the booking report.
1540
+ */
1541
+ const phase6BookingModel = promptAwareModel("travel-planner-phase-5", (promptJson) => {
1542
+ const marker = bookingMarkerFromPrompt(promptJson);
1543
+ return promptJson.includes(phase6BookingToolCallId(marker)) ? Stream.fromIterable(bookingReportParts(marker)) : Stream.fromIterable(bookingCallParts(marker));
1544
+ });
1545
+ let guideInvocations = 0;
1546
+ /** Deterministic guide-lookup handler executions across every incarnation. */
1547
+ const phase6GuideInvocationCount = () => guideInvocations;
1548
+ const countingGuideLayer = Layer.succeed(DestinationGuide, DestinationGuide.of({ lookup: (query) => Effect.suspend(() => {
1549
+ guideInvocations += 1;
1550
+ return destinationLookup(query);
1551
+ }) }));
1552
+ /** The one-candidate research mission of the DC delegation slice. */
1553
+ const phase6ResearchMission = Schema.decodeUnknownSync(ResearchMission)({
1554
+ request: "Shortlist one September culture city for the DC delegation slice.",
1555
+ candidates: ["LHR"]
1556
+ });
1557
+ const phase6ResearchDestination = "LHR";
1558
+ /** The child's scripted guide-lookup Tool Call identity. */
1559
+ const phase6ChildLookupCallId = `lookup-LHR`;
1560
+ const coordinatorDelegationParts = [{
1561
+ type: "tool-call",
1562
+ id: durableResearchCallId,
1563
+ name: "delegate_destination_research",
1564
+ params: {
1565
+ destination: "LHR",
1566
+ focus: "museums"
1567
+ },
1568
+ providerExecuted: false
1569
+ }, {
1570
+ type: "finish",
1571
+ reason: "tool-calls",
1572
+ usage: scriptedUsage
1573
+ }];
1574
+ const coordinatorShortlistParts = [
1575
+ {
1576
+ type: "text-start",
1577
+ id: "shortlist"
1578
+ },
1579
+ {
1580
+ type: "text-delta",
1581
+ id: "shortlist",
1582
+ delta: JSON.stringify(Schema.encodeSync(DestinationShortlist)(durableResearchShortlist("LHR")))
1583
+ },
1584
+ {
1585
+ type: "text-end",
1586
+ id: "shortlist"
1587
+ },
1588
+ {
1589
+ type: "finish",
1590
+ reason: "stop",
1591
+ usage: scriptedUsage
1592
+ }
1593
+ ];
1594
+ const researcherLookupParts = [{
1595
+ type: "tool-call",
1596
+ id: phase6ChildLookupCallId,
1597
+ name: "lookup_destination",
1598
+ params: { destination: "LHR" },
1599
+ providerExecuted: false
1600
+ }, {
1601
+ type: "finish",
1602
+ reason: "tool-calls",
1603
+ usage: scriptedUsage
1604
+ }];
1605
+ const researcherReportParts = [
1606
+ {
1607
+ type: "text-start",
1608
+ id: "destination-report"
1609
+ },
1610
+ {
1611
+ type: "text-delta",
1612
+ id: "destination-report",
1613
+ delta: encodedDestinationReport("LHR")
1614
+ },
1615
+ {
1616
+ type: "text-end",
1617
+ id: "destination-report"
1618
+ },
1619
+ {
1620
+ type: "finish",
1621
+ reason: "stop",
1622
+ usage: scriptedUsage
1623
+ }
1624
+ ];
1625
+ /** Prompt-aware S2 coordinator: delegation call first, shortlist once it is history. */
1626
+ const phase6CoordinatorModel = promptAwareModel("travel-coordinator-p6", (promptJson) => promptJson.includes("research-lhr-1") ? Stream.fromIterable(coordinatorShortlistParts) : Stream.fromIterable(coordinatorDelegationParts));
1627
+ let researcherGateReleased = false;
1628
+ /** Allow the researcher's FIRST model response to proceed (sticky across incarnations). */
1629
+ const releasePhase6ResearcherGate = () => {
1630
+ researcherGateReleased = true;
1631
+ };
1632
+ /** Re-close the researcher gate (each delegation scenario starts gated). */
1633
+ const resetPhase6ResearcherGate = () => {
1634
+ researcherGateReleased = false;
1635
+ };
1636
+ const awaitResearcherGate = Effect.gen(function* () {
1637
+ while (!researcherGateReleased) yield* Effect.sleep(Duration.millis(10));
1638
+ });
1639
+ /**
1640
+ * Prompt-aware S2 researcher: guide lookup first, report once it is history. The FIRST
1641
+ * response waits on the researcher gate — a stand-in for real model latency. The child's own
1642
+ * Object may legally start its Attempt the moment its routed admission commits, while the
1643
+ * parent is still appending the lineage record into the child's log; a child whose first
1644
+ * batch commits during that window races the parent's append on one tail. Real models answer
1645
+ * in seconds, so establishment always wins that race in production; the gate reproduces that
1646
+ * timing deterministically instead of relying on scheduler luck.
1647
+ */
1648
+ const phase6ResearcherModel = promptAwareModel("destination-researcher-p6", (promptJson) => promptJson.includes(phase6ChildLookupCallId) ? Stream.fromIterable(researcherReportParts) : Stream.fromEffectDrain(awaitResearcherGate).pipe(Stream.concat(Stream.fromIterable(researcherLookupParts))));
1649
+ /**
1650
+ * Every phase-6 Travel Planner worker Binding, captured with its requirement Contexts:
1651
+ * the P4 planner and its gated twin, the P5 booking agent over the
1652
+ * shared supplier desk, and the S2 coordinator/researcher pair wired through the durable
1653
+ * delegation Layer. A Thread Object registers these via its `bindings` option; the
1654
+ * capture runs once per incarnation, and everything stateful the assertions rely on (desk,
1655
+ * guide counter, gates) lives at module level so it survives incarnation loss.
1656
+ */
1657
+ const makePhase6TravelPlannerBindings = Effect.gen(function* () {
1658
+ const planner = yield* DurableWorkerBinding.make(Agent.withModel(TravelPlannerPhase4, phase6PlannerModel), phase4TravelPlannerDefinitionDigests).pipe(Effect.provide(phase4TravelPlannerWorkerLayer));
1659
+ const gatedPlanner = yield* DurableWorkerBinding.make(Agent.withModel(TravelPlannerPhase4, phase6GatedPlannerModel), phase6GatedPlannerDefinitionDigests).pipe(Effect.provide(phase4TravelPlannerWorkerLayer));
1660
+ const booking = yield* DurableWorkerBinding.make(Agent.withModel(TravelPlannerPhase5, phase6BookingModel), phase5TravelPlannerDefinitionDigests).pipe(Effect.provide(phase5TravelPlannerWorkerLayer.pipe(Layer.provideMerge(phase6SupplierDeskLayer))));
1661
+ const researcherBinding = Agent.withModel(DestinationResearcher, phase6ResearcherModel);
1662
+ const childToolkitLayer = DestinationResearcherToolkitLayer.pipe(Layer.provideMerge(countingGuideLayer));
1663
+ return [
1664
+ planner,
1665
+ gatedPlanner,
1666
+ booking,
1667
+ yield* DurableWorkerBinding.make(Agent.withModel(TravelCoordinator, phase6CoordinatorModel), s2CoordinatorDigests).pipe(Effect.provide(durableDestinationResearchHandlersLayer(researcherBinding).pipe(Layer.provide(Layer.mergeAll(childToolkitLayer, SubagentReservationsMemoryLive, DeterministicIdGeneratorLayer, ResearchDispatchGate.layerOpen))))),
1668
+ yield* DurableWorkerBinding.make(researcherBinding, s2ResearcherDigests).pipe(Effect.provide(childToolkitLayer))
1669
+ ];
1670
+ });
1671
+ /**
1672
+ * The committed cross-platform normalized canonical evidence of ONE uninterrupted Travel
1673
+ * Planner planning Submission (the P1/P4 happy path: canonical input, the search Turn, three
1674
+ * Tool settlements, the plan Turn, one Settlement). `travel-planner-phase6.test.ts` asserts
1675
+ * the DN run equals this value and `travel-planner-dc.test.ts` asserts the DC run equals this
1676
+ * value, so the two platforms' canonical outcomes are byte-equivalent transitively — the P6
1677
+ * exit gate "Travel Planner produces equivalent canonical outcomes under DN and DC".
1678
+ *
1679
+ * Regenerate ONLY when the Travel Planner scenario itself changes, by printing either suite's
1680
+ * normalized value; both suites must then agree on the new golden.
1681
+ */
1682
+ const phase6TravelPlannerGoldenEvidence = [
1683
+ {
1684
+ batchId: "thread-created:{threadId}",
1685
+ sequence: 1,
1686
+ record: {
1687
+ recordId: "thread-created:{threadId}",
1688
+ family: "thread",
1689
+ schemaVersion: 1,
1690
+ createdAt: "{timestamp}",
1691
+ deploymentId: "{deploymentId}",
1692
+ payload: {
1693
+ _tag: "ThreadCreated",
1694
+ agentId: "travel-planner-phase-4",
1695
+ definitions: {
1696
+ agent: "{digest}",
1697
+ model: "{digest}",
1698
+ tools: "{digest}"
1699
+ }
1700
+ }
1701
+ }
1702
+ },
1703
+ {
1704
+ batchId: "submission-input:{submissionId}",
1705
+ sequence: 2,
1706
+ record: {
1707
+ recordId: "input:{submissionId}",
1708
+ family: "thread",
1709
+ schemaVersion: 1,
1710
+ createdAt: "{timestamp}",
1711
+ deploymentId: "{deploymentId}",
1712
+ payload: {
1713
+ _tag: "UserInputRecorded",
1714
+ submissionId: "{submissionId}",
1715
+ kind: "user",
1716
+ runId: "run:{submissionId}",
1717
+ input: {
1718
+ request: "Plan a review-only London trip using the deterministic flight, lodging, and activity searches.",
1719
+ origin: "SFO",
1720
+ destination: "LHR",
1721
+ departOn: "2026-09-14",
1722
+ nights: 4,
1723
+ travelers: 2,
1724
+ budgetCents: 35e4,
1725
+ currency: "USD"
1726
+ }
1727
+ }
1728
+ }
1729
+ },
1730
+ {
1731
+ batchId: "run-start:run:{submissionId}",
1732
+ sequence: 3,
1733
+ record: {
1734
+ recordId: "run-start:run:{submissionId}",
1735
+ family: "thread",
1736
+ schemaVersion: 1,
1737
+ createdAt: "{timestamp}",
1738
+ deploymentId: "{deploymentId}",
1739
+ payload: {
1740
+ _tag: "RunStarted",
1741
+ runId: "run:{submissionId}",
1742
+ policyAccountingVersion: 1,
1743
+ maxDurationMillis: 3e4
1744
+ }
1745
+ }
1746
+ },
1747
+ {
1748
+ batchId: "turn-response:run:{submissionId}:1",
1749
+ sequence: 4,
1750
+ record: {
1751
+ recordId: "model-response:run:{submissionId}:1",
1752
+ family: "thread",
1753
+ schemaVersion: 1,
1754
+ createdAt: "{timestamp}",
1755
+ deploymentId: "{deploymentId}",
1756
+ payload: {
1757
+ _tag: "ModelResponseRecorded",
1758
+ runId: "run:{submissionId}",
1759
+ turnId: "turn:run:{submissionId}:1",
1760
+ turn: 1,
1761
+ inputTokens: 128,
1762
+ outputTokens: 96,
1763
+ runScopedPrefixLength: 2,
1764
+ modelUsage: [{
1765
+ provider: "scripted",
1766
+ model: "travel-planner-phase-4",
1767
+ inputTokens: {
1768
+ total: 128,
1769
+ uncached: 128,
1770
+ cacheRead: 0,
1771
+ cacheWrite: 0
1772
+ },
1773
+ outputTokens: {
1774
+ total: 96,
1775
+ text: 96,
1776
+ reasoning: 0
1777
+ },
1778
+ costMicrousd: 0
1779
+ }],
1780
+ messages: { content: [
1781
+ {
1782
+ options: {},
1783
+ role: "system",
1784
+ content: "You are the Effect Agent Travel Planner P1 interpreter fixture.\nThe user asked: Plan a review-only London trip using the deterministic flight, lodging, and activity searches.\nCall search_flights, search_lodging, and search_activities exactly once in one Tool batch.\nThen return only a JSON object of exactly this shape, no prose:\n{\"itineraries\": [{\"title\": \"<short itinerary name>\", \"route\": \"<origin-destination>\", \"dates\": \"<date range>\", \"flight\": \"<flight description from the Tool result>\", \"lodging\": \"<lodging description from the Tool result>\", \"activities\": [\"<activity>\", \"...\"], \"estimatedTotalCents\": <positive integer total in cents>, \"currency\": \"USD\", \"quoteId\": \"<quoteId from the flight Tool result>\", \"assumptions\": [\"<assumption>\", \"...\"], \"unresolvedConstraints\": [], \"nextAction\": \"review\"}]}\nUse the Tool results verbatim; activity results may legitimately be an empty array.\nThis is read-only planning. Require review before any mutation."
1785
+ },
1786
+ {
1787
+ options: {},
1788
+ role: "user",
1789
+ content: "{\"request\":\"Plan a review-only London trip using the deterministic flight, lodging, and activity searches.\",\"origin\":\"SFO\",\"destination\":\"LHR\",\"departOn\":\"2026-09-14\",\"nights\":4,\"travelers\":2,\"budgetCents\":350000,\"currency\":\"USD\"}"
1790
+ },
1791
+ {
1792
+ options: {},
1793
+ role: "assistant",
1794
+ content: [
1795
+ {
1796
+ options: {},
1797
+ type: "tool-call",
1798
+ id: "flight-call-1",
1799
+ name: "search_flights",
1800
+ params: {
1801
+ origin: "SFO",
1802
+ destination: "LHR",
1803
+ departOn: "2026-09-14",
1804
+ travelers: 2
1805
+ },
1806
+ providerExecuted: false
1807
+ },
1808
+ {
1809
+ options: {},
1810
+ type: "tool-call",
1811
+ id: "lodging-call-1",
1812
+ name: "search_lodging",
1813
+ params: {
1814
+ destination: "LHR",
1815
+ departOn: "2026-09-14",
1816
+ nights: 4,
1817
+ travelers: 2
1818
+ },
1819
+ providerExecuted: false
1820
+ },
1821
+ {
1822
+ options: {},
1823
+ type: "tool-call",
1824
+ id: "activity-call-1",
1825
+ name: "search_activities",
1826
+ params: {
1827
+ destination: "LHR",
1828
+ departOn: "2026-09-14",
1829
+ nights: 4,
1830
+ travelers: 2
1831
+ },
1832
+ providerExecuted: false
1833
+ }
1834
+ ]
1835
+ }
1836
+ ] },
1837
+ messagesDigest: "{digest}"
1838
+ }
1839
+ }
1840
+ },
1841
+ {
1842
+ batchId: "turn-results:run:{submissionId}:1",
1843
+ sequence: 5,
1844
+ record: {
1845
+ recordId: "tool-settled:run:{submissionId}:1:flight-call-1",
1846
+ family: "thread",
1847
+ schemaVersion: 1,
1848
+ createdAt: "{timestamp}",
1849
+ deploymentId: "{deploymentId}",
1850
+ payload: {
1851
+ _tag: "ToolCallSettled",
1852
+ runId: "run:{submissionId}",
1853
+ toolCallId: "flight-call-1",
1854
+ toolName: "search_flights",
1855
+ result: {
1856
+ quoteId: "quote-sfo-lhr-001",
1857
+ flight: "EA 218 · nonstop · SFO 18:40 → LHR 13:05+1",
1858
+ estimatedCents: 18e4,
1859
+ currency: "USD"
1860
+ },
1861
+ isFailure: false
1862
+ }
1863
+ }
1864
+ },
1865
+ {
1866
+ batchId: "turn-results:run:{submissionId}:1",
1867
+ sequence: 6,
1868
+ record: {
1869
+ recordId: "tool-settled:run:{submissionId}:1:lodging-call-1",
1870
+ family: "thread",
1871
+ schemaVersion: 1,
1872
+ createdAt: "{timestamp}",
1873
+ deploymentId: "{deploymentId}",
1874
+ payload: {
1875
+ _tag: "ToolCallSettled",
1876
+ runId: "run:{submissionId}",
1877
+ toolCallId: "lodging-call-1",
1878
+ toolName: "search_lodging",
1879
+ result: {
1880
+ lodging: "Bloomsbury House · refundable studio · 4 nights",
1881
+ estimatedCents: 104e3,
1882
+ currency: "USD"
1883
+ },
1884
+ isFailure: false
1885
+ }
1886
+ }
1887
+ },
1888
+ {
1889
+ batchId: "turn-results:run:{submissionId}:1",
1890
+ sequence: 7,
1891
+ record: {
1892
+ recordId: "tool-settled:run:{submissionId}:1:activity-call-1",
1893
+ family: "thread",
1894
+ schemaVersion: 1,
1895
+ createdAt: "{timestamp}",
1896
+ deploymentId: "{deploymentId}",
1897
+ payload: {
1898
+ _tag: "ToolCallSettled",
1899
+ runId: "run:{submissionId}",
1900
+ toolCallId: "activity-call-1",
1901
+ toolName: "search_activities",
1902
+ result: { activities: ["British Museum timed entry", "Thames evening walk"] },
1903
+ isFailure: false
1904
+ }
1905
+ }
1906
+ },
1907
+ {
1908
+ batchId: "turn:run:{submissionId}:2",
1909
+ sequence: 8,
1910
+ record: {
1911
+ recordId: "model-response:run:{submissionId}:2",
1912
+ family: "thread",
1913
+ schemaVersion: 1,
1914
+ createdAt: "{timestamp}",
1915
+ deploymentId: "{deploymentId}",
1916
+ payload: {
1917
+ _tag: "ModelResponseRecorded",
1918
+ runId: "run:{submissionId}",
1919
+ turnId: "turn:run:{submissionId}:2",
1920
+ turn: 2,
1921
+ inputTokens: 128,
1922
+ outputTokens: 96,
1923
+ modelUsage: [{
1924
+ provider: "scripted",
1925
+ model: "travel-planner-phase-4",
1926
+ inputTokens: {
1927
+ total: 128,
1928
+ uncached: 128,
1929
+ cacheRead: 0,
1930
+ cacheWrite: 0
1931
+ },
1932
+ outputTokens: {
1933
+ total: 96,
1934
+ text: 96,
1935
+ reasoning: 0
1936
+ },
1937
+ costMicrousd: 0
1938
+ }],
1939
+ messages: { content: [{
1940
+ options: {},
1941
+ role: "assistant",
1942
+ content: "{\"itineraries\":[{\"title\":\"Westward light, eastbound overnight\",\"route\":\"San Francisco → London\",\"dates\":\"14–19 September 2026\",\"flight\":\"EA 218 · nonstop · SFO 18:40 → LHR 13:05+1\",\"lodging\":\"Bloomsbury House · refundable studio · 4 nights\",\"activities\":[\"British Museum timed entry\",\"Thames evening walk\"],\"estimatedTotalCents\":284000,\"currency\":\"USD\",\"quoteId\":\"quote-sfo-lhr-001\",\"assumptions\":[\"Two travelers sharing one studio\",\"Quote is read-only availability, not a reservation\"],\"unresolvedConstraints\":[\"Traveler names and accessibility requests are intentionally omitted\"],\"nextAction\":\"review\"}]}"
1943
+ }] },
1944
+ messagesDigest: "{digest}"
1945
+ }
1946
+ }
1947
+ },
1948
+ {
1949
+ batchId: "turn:run:{submissionId}:2",
1950
+ sequence: 9,
1951
+ record: {
1952
+ recordId: "run-completed:run:{submissionId}",
1953
+ family: "thread",
1954
+ schemaVersion: 1,
1955
+ createdAt: "{timestamp}",
1956
+ deploymentId: "{deploymentId}",
1957
+ payload: {
1958
+ _tag: "RunCompleted",
1959
+ runId: "run:{submissionId}",
1960
+ output: { itineraries: [{
1961
+ title: "Westward light, eastbound overnight",
1962
+ route: "San Francisco → London",
1963
+ dates: "14–19 September 2026",
1964
+ flight: "EA 218 · nonstop · SFO 18:40 → LHR 13:05+1",
1965
+ lodging: "Bloomsbury House · refundable studio · 4 nights",
1966
+ activities: ["British Museum timed entry", "Thames evening walk"],
1967
+ estimatedTotalCents: 284e3,
1968
+ currency: "USD",
1969
+ quoteId: "quote-sfo-lhr-001",
1970
+ assumptions: ["Two travelers sharing one studio", "Quote is read-only availability, not a reservation"],
1971
+ unresolvedConstraints: ["Traveler names and accessibility requests are intentionally omitted"],
1972
+ nextAction: "review"
1973
+ }] }
1974
+ }
1975
+ }
1976
+ },
1977
+ {
1978
+ batchId: "submission-settlement:{submissionId}",
1979
+ sequence: 10,
1980
+ record: {
1981
+ recordId: "settlement:{submissionId}",
1982
+ family: "thread",
1983
+ schemaVersion: 1,
1984
+ createdAt: "{timestamp}",
1985
+ deploymentId: "{deploymentId}",
1986
+ payload: {
1987
+ _tag: "SubmissionSettled",
1988
+ submissionId: "{submissionId}",
1989
+ settlementId: "settlement:{submissionId}",
1990
+ receiptId: "{receiptId}",
1991
+ outcome: "completed",
1992
+ runId: "run:{submissionId}",
1993
+ result: { itineraries: [{
1994
+ title: "Westward light, eastbound overnight",
1995
+ route: "San Francisco → London",
1996
+ dates: "14–19 September 2026",
1997
+ flight: "EA 218 · nonstop · SFO 18:40 → LHR 13:05+1",
1998
+ lodging: "Bloomsbury House · refundable studio · 4 nights",
1999
+ activities: ["British Museum timed entry", "Thames evening walk"],
2000
+ estimatedTotalCents: 284e3,
2001
+ currency: "USD",
2002
+ quoteId: "quote-sfo-lhr-001",
2003
+ assumptions: ["Two travelers sharing one studio", "Quote is read-only availability, not a reservation"],
2004
+ unresolvedConstraints: ["Traveler names and accessibility requests are intentionally omitted"],
2005
+ nextAction: "review"
2006
+ }] },
2007
+ usageSummary: {
2008
+ modelCalls: 2,
2009
+ inputTokens: {
2010
+ total: 256,
2011
+ uncached: 256,
2012
+ cacheRead: 0,
2013
+ cacheWrite: 0
2014
+ },
2015
+ outputTokens: {
2016
+ total: 192,
2017
+ text: 192,
2018
+ reasoning: 0
2019
+ },
2020
+ costMicrousd: 0,
2021
+ byModel: [{
2022
+ provider: "scripted",
2023
+ model: "travel-planner-phase-4",
2024
+ modelCalls: 2,
2025
+ inputTokens: {
2026
+ total: 256,
2027
+ uncached: 256,
2028
+ cacheRead: 0,
2029
+ cacheWrite: 0
2030
+ },
2031
+ outputTokens: {
2032
+ total: 192,
2033
+ text: 192,
2034
+ reasoning: 0
2035
+ },
2036
+ costMicrousd: 0
2037
+ }]
2038
+ }
2039
+ }
2040
+ }
2041
+ }
2042
+ ];
2043
+ //#endregion
2044
+ //#region src/fixtures/travel-planner/phase7.ts
2045
+ /**
2046
+ * The P7 dual-profile claim, schema-first so the exact scope of "live
2047
+ * integration profiles" is a committed, decodable value:
2048
+ *
2049
+ * - `offlineConformanceDeterministic` / `offlineRequiresCredentials`: the
2050
+ * cumulative conformance suites stay deterministic and credential-free.
2051
+ * - `liveProfileOptIn`: live suites are excluded from ordinary gates by the
2052
+ * environment predicate (`phase7LiveProfileEnabled`), never by test-runner
2053
+ * configuration that could silently drift.
2054
+ * - `liveModelLayers` / `liveSupplierLayers`: live profiles exercise real
2055
+ * model Layers over the SAME deterministic supplier desk — no claim of a
2056
+ * live supplier integration is made anywhere (decision 9).
2057
+ * - `structurallyRedactedTranscripts`: transcript evidence a live profile
2058
+ * emits passes through the structural `Redactor` first (SEC-008,
2059
+ * testing.md §12: "live model and supplier profiles are opt-in smoke or
2060
+ * release tests, rate-limited and structurally redacted").
2061
+ * - `exactlyOnceExternalEffects`: never claimed at any phase (DUR-003).
2062
+ */
2063
+ var TravelPlannerPhase7Profile = class extends Schema.Class("@effect-agent/testing/travel-planner/TravelPlannerPhase7Profile")({
2064
+ phase: Schema.Literal("P7"),
2065
+ offlineConformanceDeterministic: Schema.Literal(true),
2066
+ offlineRequiresCredentials: Schema.Literal(false),
2067
+ liveProfileOptIn: Schema.Literal(true),
2068
+ liveModelLayers: Schema.Literal(true),
2069
+ liveSupplierLayers: Schema.Literal(false),
2070
+ structurallyRedactedTranscripts: Schema.Literal(true),
2071
+ exactlyOnceExternalEffects: Schema.Literal(false)
2072
+ }) {};
2073
+ const phase7TravelPlannerProfile = TravelPlannerPhase7Profile.make({
2074
+ phase: "P7",
2075
+ offlineConformanceDeterministic: true,
2076
+ offlineRequiresCredentials: false,
2077
+ liveProfileOptIn: true,
2078
+ liveModelLayers: true,
2079
+ liveSupplierLayers: false,
2080
+ structurallyRedactedTranscripts: true,
2081
+ exactlyOnceExternalEffects: false
2082
+ });
2083
+ /**
2084
+ * The one opt-in switch for EVERY live profile in this repository. `"1"` is
2085
+ * the only enabling value: an unset, empty, or differently-truthy value keeps
2086
+ * the suite skipped, so CI and ordinary developer runs stay offline.
2087
+ */
2088
+ const PHASE7_LIVE_GATE_ENV = "EFFECT_AGENT_LIVE";
2089
+ /** The credential a Travel Planner live-model profile additionally requires. */
2090
+ const PHASE7_LIVE_CREDENTIAL_ENV = "OPENAI_API_KEY";
2091
+ /**
2092
+ * The test-side live gate (P7 plan §6: no test-side live-gating pattern
2093
+ * existed before this — the demo gates at serve time via
2094
+ * `Config.redacted("OPENAI_API_KEY")`). Suites use it as
2095
+ * `describe.skipIf(!phase7LiveProfileEnabled(process.env))`, which keeps the
2096
+ * live block out of ordinary gates while the SAME file's ungated tests keep
2097
+ * pinning the profile schema on every run.
2098
+ */
2099
+ const phase7LiveProfileEnabled = (env) => env["EFFECT_AGENT_LIVE"] === "1" && (env["OPENAI_API_KEY"] ?? "") !== "";
2100
+ //#endregion
2101
+ export { ActivityCatalog, ActivityCatalogLayer, ActivityQuery, ActivitySearchResult, ActivityUnavailable, AirportCode, BookFlight, BookItinerary, BookingRef, CancelBooking, CancelBookingRequest, CancellationConfirmation, CatalogLifecycle, CatalogLifecycleCounts, DestinationBrief, DestinationFacts, DestinationGuide, DestinationGuideLayer, DestinationGuideUnavailable, DestinationQuery, DestinationRecommendation, DestinationReport, DestinationResearchFailed, DestinationResearchFindings, DestinationResearchRequest, DestinationResearchSupportLayer, DestinationResearcher, DestinationResearcherToolkit, DestinationResearcherToolkitLayer, DestinationShortlist, DeterministicIdGeneratorLayer, DurableSearchActivities, DurableSearchFlights, DurableSearchLodging, FlightBookingRequest, FlightCatalog, FlightCatalogLayer, FlightOption, FlightQuery, FlightUnavailable, GuidanceFailure, HoldItinerary, Itinerary, ItineraryBookingRequest, ItineraryConfirmation, ItineraryHold, ItineraryHoldGateway, ItineraryHoldRequest, ItineraryHoldUnavailable, LodgingCatalog, LodgingCatalogLayer, LodgingOption, LodgingQuery, LodgingUnavailable, LookupDestination, PHASE7_LIVE_CREDENTIAL_ENV, PHASE7_LIVE_GATE_ENV, QuoteId, ResearchDispatchGate, ResearchMission, ReverseCompletionToolkitLayer, SearchActivities, SearchFlights, SearchLodging, SupplierBookingConfirmation, SupplierBookingDesk, SupplierBookingRecord, SupplierOperation, SupplierUnavailable, TravelBookingReport, TravelCoordinator, TravelCoordinatorToolkit, TravelGuidance, TravelGuidanceLayer, TravelPlan, TravelPlanner, TravelPlannerBookingEvidenceError, TravelPlannerBookingProfile, TravelPlannerCloudflareProfile, TravelPlannerDurabilityProfile, TravelPlannerDurableEvidenceError, TravelPlannerPersistenceProfile, TravelPlannerPhase2, TravelPlannerPhase2Toolkit, TravelPlannerPhase2ToolkitLayer, TravelPlannerPhase4, TravelPlannerPhase4Toolkit, TravelPlannerPhase4ToolkitLayer, TravelPlannerPhase5, TravelPlannerPhase5Toolkit, TravelPlannerPhase5ToolkitLayer, TravelPlannerPhase7Profile, TravelPlannerProjectionError, TravelPlannerRuntimeLayer, TravelPlannerSubagentDurabilityProfile, TravelPlannerToolkit, TravelPlannerToolkitLayer, TravelSupplierReconcilerLayer, TravelerRef, TripRequest, assertSettledBookingsExistAtSupplier, bookFlightIdempotencyKey, cancelBookingIdempotencyKey, coordinatorConfidentialMarker, coordinatorResearchTurn, coordinatorShortlistTurn, destinationLookup, destinationReportFor, destinationResearchDelegation, destinationResearchHandlersLayer, destinationResearchPolicy, durableChildLookupCallId, durableDestinationResearchHandlersLayer, durableResearchAllocation, durableResearchCallId, durableResearchFinding, durableResearchShortlist, encodedDestinationFacts, encodedDestinationReport, expectedDestinationShortlist, expectedTravelPlan, itineraryStepIdempotencyKey, makeDestinationResearcherModel, makeDurableResearchHarness, makeInvocationCountingModel, makePhase3TravelPlannerCheckpoint, makePhase4TravelPlannerAgent, makePhase6TravelPlannerBindings, mapResearchChildFailure, missionConfidentialMarker, normalizeCrossPlatformTravelPlannerEvidence, normalizeDurableTravelPlannerEvidence, phase1HappyPathTurns, phase1Trip, phase3TravelPlannerBatches, phase3TravelPlannerCompletionBatch, phase3TravelPlannerDefinitionDigests, phase3TravelPlannerEncodedFixture, phase3TravelPlannerInitialBatch, phase3TravelPlannerProducerId, phase3TravelPlannerProfile, phase3TravelPlannerRunId, phase3TravelPlannerThreadId, phase4TravelPlannerDefinitionDigests, phase4TravelPlannerDeploymentId, phase4TravelPlannerPrincipal, phase4TravelPlannerProducerId, phase4TravelPlannerProfile, phase4TravelPlannerSubmitOptions, phase4TravelPlannerWorkerLayer, phase5TravelPlannerDefinitionDigests, phase5TravelPlannerDeploymentId, phase5TravelPlannerPrincipal, phase5TravelPlannerProducerId, phase5TravelPlannerProfile, phase5TravelPlannerSubmitOptions, phase5TravelPlannerWorkerLayer, phase6ActivityCallId, phase6BookingModel, phase6BookingRef, phase6BookingToolCallId, phase6BookingTrip, phase6ChildLookupCallId, phase6CoordinatorModel, phase6FlightCallId, phase6GatedPlannerDefinitionDigests, phase6GatedPlannerModel, phase6GatedTrip, phase6GuideInvocationCount, phase6LodgingCallId, phase6PlannerModel, phase6ResearchDestination, phase6ResearchMission, phase6ResearcherModel, phase6SupplierDesk, phase6SupplierDeskLayer, phase6SupplierReconcilerLayer, phase6TravelPlannerDeploymentId, phase6TravelPlannerGoldenEvidence, phase6TravelPlannerProducerId, phase6TravelPlannerProducerPrefix, phase6TravelPlannerProfile, phase7LiveProfileEnabled, phase7TravelPlannerProfile, releasePhase6PlannerGate, releasePhase6ResearcherGate, researchMission, researcherHappyPathTurns, resetPhase6PlannerGate, resetPhase6ResearcherGate, s2CoordinatorDigests, s2CoordinatorSubmitAgent, s2ResearcherDigestStrings, s2ResearcherDigests, s2TravelPlannerDeploymentId, s2TravelPlannerPrincipal, s2TravelPlannerProducerId, s2TravelPlannerProfile, s2TravelPlannerSubmitOptions, supplierBookingRefFor, travelPlanFromDurableSettlement, travelPlanFromProjection };
2102
+
2103
+ //# sourceMappingURL=travel-planner.mjs.map