@effect-agent/testing 0.1.0-beta.11 → 0.1.0-beta.110

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 (54) hide show
  1. package/dist/Certification.d.mts +105 -0
  2. package/dist/Certification.mjs +637 -0
  3. package/dist/Certification.mjs.map +1 -0
  4. package/dist/Chaos.d.mts +127 -0
  5. package/dist/Chaos.mjs +756 -0
  6. package/dist/Chaos.mjs.map +1 -0
  7. package/{src/code-executor-conformance.d.ts → dist/CodeExecutorConformance.d.mts} +12 -10
  8. package/dist/CodeExecutorConformance.mjs +231 -0
  9. package/dist/CodeExecutorConformance.mjs.map +1 -0
  10. package/dist/CodeExecutorSubstitute.d.mts +20 -0
  11. package/dist/CodeExecutorSubstitute.mjs +368 -0
  12. package/dist/CodeExecutorSubstitute.mjs.map +1 -0
  13. package/dist/DocsResearcher.d.mts +276 -0
  14. package/dist/DocsResearcher.mjs +490 -0
  15. package/dist/DocsResearcher.mjs.map +1 -0
  16. package/dist/ScriptedModel-HIvFn-5K.d.mts +220 -0
  17. package/dist/ScriptedModel.d.mts +2 -0
  18. package/dist/ScriptedModel.mjs +155 -0
  19. package/dist/ScriptedModel.mjs.map +1 -0
  20. package/dist/TravelPlanner.d.mts +1680 -0
  21. package/dist/TravelPlanner.mjs +1985 -0
  22. package/dist/TravelPlanner.mjs.map +1 -0
  23. package/dist/deterministic-layers-D5owIoke.mjs +358 -0
  24. package/dist/deterministic-layers-D5owIoke.mjs.map +1 -0
  25. package/dist/index.d.mts +2 -3408
  26. package/dist/index.mjs +2 -4771
  27. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  28. package/package.json +1 -48
  29. package/src/{certification.ts → Certification.ts} +375 -171
  30. package/src/{chaos.ts → Chaos.ts} +290 -191
  31. package/src/{code-executor-conformance.ts → CodeExecutorConformance.ts} +30 -7
  32. package/src/{code-executor-substitute.ts → CodeExecutorSubstitute.ts} +113 -46
  33. package/src/{fixtures/docs-researcher/index.ts → DocsResearcher.ts} +68 -5
  34. package/src/{scripted-model.ts → ScriptedModel.ts} +25 -29
  35. package/src/TravelPlanner.ts +232 -0
  36. package/src/fixtures/docs-researcher/definition.ts +20 -11
  37. package/src/fixtures/docs-researcher/harness.ts +41 -34
  38. package/src/fixtures/docs-researcher/mcp.ts +49 -3
  39. package/src/fixtures/travel-planner/definition.ts +15 -2
  40. package/src/fixtures/travel-planner/deterministic-layers.ts +47 -4
  41. package/src/fixtures/travel-planner/phase2.ts +4 -3
  42. package/src/fixtures/travel-planner/phase3.ts +19 -42
  43. package/src/fixtures/travel-planner/phase4.ts +24 -37
  44. package/src/fixtures/travel-planner/phase5.ts +35 -42
  45. package/src/fixtures/travel-planner/phase6.ts +224 -96
  46. package/src/fixtures/travel-planner/phase7.ts +4 -102
  47. package/src/fixtures/travel-planner/scenarios.ts +3 -4
  48. package/src/fixtures/travel-planner/subagents-durable.ts +35 -61
  49. package/src/fixtures/travel-planner/subagents.ts +36 -14
  50. package/src/index.ts +1 -11
  51. package/src/internal/certification-report.ts +25 -0
  52. package/dist/index.mjs.map +0 -1
  53. package/src/fixtures/travel-planner/index.ts +0 -11
  54. package/src/fixtures/warehouse/index.ts +0 -412
@@ -1,17 +1,16 @@
1
- import { SubagentReservationsMemoryLive } from "@effect-agent/capabilities";
2
- import { Agent } from "@effect-agent/core";
1
+ import { Duration, Effect, Layer, Schema, Stream } from "effect";
2
+ import * as Agent from "effect-agent/agent";
3
+ import { DurableWorkerBinding, type ResolvedBinding } from "effect-agent/agent-registration";
4
+ import { type Receipt } from "effect-agent/durable-agent-runtime";
3
5
  import {
4
6
  DefinitionDigests,
5
7
  DeploymentId,
6
8
  Digest,
7
- DurableWorkerBinding,
8
9
  ProducerId,
9
10
  type CanonicalRecordEnvelope,
10
- type Receipt,
11
- type ResolvedBinding,
12
- type ToolReconciler,
13
- } from "@effect-agent/session";
14
- import { Duration, Effect, Layer, Schema, Stream } from "effect";
11
+ } from "effect-agent/records";
12
+ import { SubagentReservationsMemoryLive } from "effect-agent/subagent-reservations";
13
+ import { type ToolReconciler } from "effect-agent/tool-reconciler";
15
14
  import { LanguageModel, Model, type Response } from "effect/unstable/ai";
16
15
 
17
16
  import { TravelPlan, TripRequest } from "./definition.ts";
@@ -54,58 +53,17 @@ import {
54
53
  encodedDestinationReport,
55
54
  } from "./subagents.ts";
56
55
 
57
- // ---------------------------------------------------------------------------
58
- // Phase 6 (P6): the SAME cumulative Travel Planner on the Cloudflare Durable
59
- // Object runtime, deployment class DC. This module is deliberately
60
- // platform-neutral (it imports no Cloudflare types): the worker Bindings it
61
- // builds are plain `ResolvedBinding` values a Conversation Object registers,
62
- // and the cross-platform evidence normal form is shared by the DN and DC
63
- // halves of the equivalence suite (plan §1.8, D-P6-6).
64
- // ---------------------------------------------------------------------------
65
-
66
- /**
67
- * The Phase 6 profile: the P4/P5/S2 Travel Planner claims re-earned on the Cloudflare Durable
68
- * Object runtime (deployment class `DC`), where eviction and alarm redelivery replace process
69
- * kill and restart as the exercised recovery path. `cloudflareEquivalence` is the claim the S2
70
- * fixture explicitly deferred to P6 (`TravelPlannerSubagentDurabilityProfile` pins it `false`
71
- * for `DN`): it flips to `true` here ONLY because the phase-6 suites assert byte-equal
72
- * cross-platform normalized canonical evidence against one committed golden. Exactly-once
73
- * EXTERNAL effects remain — deliberately — unclaimed on every platform (DUR-003).
74
- */
75
- export class TravelPlannerCloudflareProfile extends Schema.Class<TravelPlannerCloudflareProfile>(
76
- "@effect-agent/testing/travel-planner/TravelPlannerCloudflareProfile",
77
- )({
78
- deploymentClass: Schema.Literal("DC"),
79
- durableAcceptedWork: Schema.Literal(true),
80
- canonicalSchemaVersion: Schema.Literal(1),
81
- /** P5 semantics under DC recovery: prepared/settled records, Unknown Outcomes, approvals. */
82
- supplierBookingUncertaintyProtocol: Schema.Literal(true),
83
- /** S2 semantics under DC recovery: cross-Object establishment/join, completed child never re-runs. */
84
- durableAttachedSubagents: Schema.Literal(true),
85
- /** DN and DC produce byte-equal cross-platform normalized canonical evidence (one golden). */
86
- cloudflareEquivalence: Schema.Literal(true),
87
- /** Never claimed at any phase on any platform (DUR-003). */
88
- exactlyOnceExternalEffects: Schema.Literal(false),
89
- }) {}
90
-
91
- export const phase6TravelPlannerProfile = TravelPlannerCloudflareProfile.make({
92
- deploymentClass: "DC",
93
- durableAcceptedWork: true,
94
- canonicalSchemaVersion: 1,
95
- supplierBookingUncertaintyProtocol: true,
96
- durableAttachedSubagents: true,
97
- cloudflareEquivalence: true,
98
- exactlyOnceExternalEffects: false,
99
- });
100
-
56
+ /** Platform-neutral bindings and canonical evidence shared by Node and Cloudflare tests. */
101
57
  export const phase6TravelPlannerDeploymentId = Schema.decodeSync(DeploymentId)(
102
58
  "travel-planner-p6-deployment",
103
59
  );
104
- /** Producer prefix of the DC host; each Object mints `{prefix}:{conversationId}`. */
60
+
61
+ /** Producer prefix of the DC host; each Object mints `{prefix}:{threadId}`. */
105
62
  export const phase6TravelPlannerProducerPrefix = "travel-planner-p6-producer";
106
- /** The full producer identity one DC Conversation Object mints for itself. */
107
- export const phase6TravelPlannerProducerId = (conversationId: string): ProducerId =>
108
- Schema.decodeSync(ProducerId)(`${phase6TravelPlannerProducerPrefix}:${conversationId}`);
63
+
64
+ /** The full producer identity one DC Thread Object mints for itself. */
65
+ export const phase6TravelPlannerProducerId = (threadId: string): ProducerId =>
66
+ Schema.decodeSync(ProducerId)(`${phase6TravelPlannerProducerPrefix}:${threadId}`);
109
67
 
110
68
  const digestOf = (character: string) => Schema.decodeSync(Digest)(character.repeat(64));
111
69
 
@@ -127,11 +85,11 @@ export const phase6GatedPlannerDefinitionDigests = DefinitionDigests.make({
127
85
 
128
86
  /** The run-specific identities the cross-platform normal form scrubs. */
129
87
  export interface CrossPlatformEvidenceIdentity {
130
- /** The Conversation lane the evidence came from. */
131
- readonly conversationId: string;
88
+ /** The Thread lane the evidence came from. */
89
+ readonly threadId: string;
132
90
  /** The host's deployment identity (`DeploymentId` on every record envelope). */
133
91
  readonly deploymentId: string;
134
- /** The full producer identity of the run (DN: configured; DC: `{prefix}:{conversationId}`). */
92
+ /** The full producer identity of the run (DN: configured; DC: `{prefix}:{threadId}`). */
135
93
  readonly producerId: string;
136
94
  }
137
95
 
@@ -143,12 +101,13 @@ const ComparableEnvelope = Schema.Struct({
143
101
  sequence: Schema.Number,
144
102
  record: Schema.Json,
145
103
  });
104
+
146
105
  const decodeComparableEnvelopes = Schema.decodeUnknownEffect(Schema.Array(ComparableEnvelope));
147
106
 
148
107
  /**
149
108
  * The CROSS-PLATFORM extension of `normalizeDurableTravelPlannerEvidence` (D-P6-6): after the
150
109
  * base normalization replaces the two ledger-minted identities (which also normalizes the
151
- * DC-format routable `{uuidv7}:{conversationId}` Submission identities and everything derived
110
+ * DC-format routable `{uuidv7}:{threadId}` Submission identities and everything derived
152
111
  * from them), this form additionally scrubs everything that legitimately differs between a DN
153
112
  * process and a DC Durable Object over the same scenario:
154
113
  *
@@ -158,7 +117,7 @@ const decodeComparableEnvelopes = Schema.decodeUnknownEffect(Schema.Array(Compar
158
117
  * control (on DC even a CLEAN run carries one, because every pass reconciles before it
159
118
  * claims, so the ready lane's input is applied through the recovery path). Canonical ORDER
160
119
  * is the durability §5 claim; sequence contiguity is a platform artifact of who appended;
161
- * - the Conversation identity (DC lanes mint unique names per test run);
120
+ * - the Thread identity (DC lanes mint unique names per test run);
162
121
  * - the deployment and producer identities (host configuration, not canonical semantics);
163
122
  * - `createdAt` commit timestamps (wall clock);
164
123
  * - 64-hex digests (they hash RAW content that legally embeds run-specific identity, so they
@@ -180,15 +139,18 @@ export const normalizeCrossPlatformTravelPlannerEvidence = Effect.fn(
180
139
  const canonical = records.filter(
181
140
  (envelope) => envelope.record.payload._tag !== "RepairAnnotated",
182
141
  );
142
+
183
143
  const base = yield* normalizeDurableTravelPlannerEvidence(canonical, receipt);
144
+
184
145
  const scrubbed: unknown = JSON.parse(
185
146
  JSON.stringify(base)
186
147
  .replaceAll(identity.producerId, "{producerId}")
187
148
  .replaceAll(identity.deploymentId, "{deploymentId}")
188
- .replaceAll(identity.conversationId, "{conversationId}")
149
+ .replaceAll(identity.threadId, "{threadId}")
189
150
  .replaceAll(/\d{4}-\d{2}-\d{2}T[0-9:.]+Z/g, "{timestamp}")
190
151
  .replaceAll(/"[0-9a-f]{64}"/g, '"{digest}"'),
191
152
  );
153
+
192
154
  const comparable = yield* decodeComparableEnvelopes(scrubbed).pipe(
193
155
  Effect.mapError((error) =>
194
156
  TravelPlannerDurableEvidenceError.make({
@@ -196,11 +158,13 @@ export const normalizeCrossPlatformTravelPlannerEvidence = Effect.fn(
196
158
  }),
197
159
  ),
198
160
  );
161
+
199
162
  const renumbered = comparable.map((entry, index) => ({
200
163
  batchId: entry.batchId,
201
164
  sequence: index + 1,
202
165
  record: entry.record,
203
166
  }));
167
+
204
168
  return yield* decodeComparableJson(renumbered).pipe(
205
169
  Effect.mapError((error) =>
206
170
  TravelPlannerDurableEvidenceError.make({
@@ -286,12 +250,18 @@ const plannerDecide = (promptJson: string): Stream.Stream<Response.StreamPartEnc
286
250
  * batch is committed history, every later request gets the plan — identical parts, so the DC
287
251
  * canonical evidence is byte-equivalent to the DN ScriptedModel run after normalization.
288
252
  */
289
- export const phase6PlannerModel = promptAwareModel("travel-planner-phase-4", plannerDecide);
253
+ export const phase6PlannerModel = promptAwareModel("travel-planner-phase-4", (promptJson) =>
254
+ promptJson.includes("[gate:") && !promptJson.includes(phase6FlightCallId)
255
+ ? Stream.fromEffectDrain(awaitPlannerGate(gateMarkerFromPrompt(promptJson))).pipe(
256
+ Stream.concat(plannerDecide(promptJson)),
257
+ )
258
+ : plannerDecide(promptJson),
259
+ );
290
260
 
291
261
  // ---------------------------------------------------------------------------
292
262
  // Deterministic test gate for the admission-limits rows. Module state is
293
263
  // intentionally NOT durable: it plays the external world's role (a slow
294
- // upstream model), never Conversation state.
264
+ // upstream model), never Thread state.
295
265
  // ---------------------------------------------------------------------------
296
266
 
297
267
  const releasedPlannerGates = new Set<string>();
@@ -318,7 +288,7 @@ const gateMarkerFromPrompt = (promptJson: string): string =>
318
288
 
319
289
  /** A trip whose request text carries the gate marker the gated model waits on. */
320
290
  export const phase6GatedTrip = (marker: string): TripRequest =>
321
- Schema.decodeUnknownSync(TripRequest)({
291
+ Schema.decodeSync(TripRequest)({
322
292
  request: `Plan a review-only London trip, but wait for the concierge. [gate:${marker}]`,
323
293
  origin: "SFO",
324
294
  destination: "LHR",
@@ -345,6 +315,7 @@ export const phase6GatedPlannerModel = Model.make(
345
315
  Stream.unwrap(
346
316
  Effect.sync(() => {
347
317
  const promptJson = JSON.stringify(options.prompt);
318
+
348
319
  return promptJson.includes(phase6FlightCallId)
349
320
  ? plannerDecide(promptJson)
350
321
  : Stream.fromEffectDrain(awaitPlannerGate(gateMarkerFromPrompt(promptJson))).pipe(
@@ -381,7 +352,7 @@ export const phase6SupplierDeskLayer: Layer.Layer<SupplierBookingDesk> = Layer.s
381
352
 
382
353
  /**
383
354
  * The REAL P5 supplier reconciliation policy over the shared desk, closed to no requirements
384
- * so a Conversation Object can install it directly: `book_flight` recovers only from supplier
355
+ * so a Thread Object can install it directly: `book_flight` recovers only from supplier
385
356
  * truth (absence stays fail-closed `Uncertain` → durable Unknown Outcome), keyed Steps are
386
357
  * provably re-enterable.
387
358
  */
@@ -400,7 +371,7 @@ export const phase6BookingRef = (marker: string): string =>
400
371
 
401
372
  /** A trip whose request text carries the per-lane booking case marker. */
402
373
  export const phase6BookingTrip = (marker: string): TripRequest =>
403
- Schema.decodeUnknownSync(TripRequest)({
374
+ Schema.decodeSync(TripRequest)({
404
375
  request: `Book the approved London flight for the traveler. [case:${marker}]`,
405
376
  origin: "SFO",
406
377
  destination: "LHR",
@@ -448,6 +419,7 @@ const bookingReportParts = (marker: string): ReadonlyArray<Response.StreamPartEn
448
419
  */
449
420
  export const phase6BookingModel = promptAwareModel("travel-planner-phase-5", (promptJson) => {
450
421
  const marker = bookingMarkerFromPrompt(promptJson);
422
+
451
423
  return promptJson.includes(phase6BookingToolCallId(marker))
452
424
  ? Stream.fromIterable(bookingReportParts(marker))
453
425
  : Stream.fromIterable(bookingCallParts(marker));
@@ -471,13 +443,14 @@ const countingGuideLayer = Layer.succeed(
471
443
  lookup: (query) =>
472
444
  Effect.suspend(() => {
473
445
  guideInvocations += 1;
446
+
474
447
  return destinationLookup(query);
475
448
  }),
476
449
  }),
477
450
  );
478
451
 
479
452
  /** The one-candidate research mission of the DC delegation slice. */
480
- export const phase6ResearchMission = Schema.decodeUnknownSync(ResearchMission)({
453
+ export const phase6ResearchMission = Schema.decodeSync(ResearchMission)({
481
454
  request: "Shortlist one September culture city for the DC delegation slice.",
482
455
  candidates: ["LHR"],
483
456
  });
@@ -576,14 +549,14 @@ export const phase6ResearcherModel = promptAwareModel("destination-researcher-p6
576
549
  );
577
550
 
578
551
  // ---------------------------------------------------------------------------
579
- // Worker Binding registrations for the DC Conversation Object
552
+ // Worker Binding registrations for the DC Thread Object
580
553
  // ---------------------------------------------------------------------------
581
554
 
582
555
  /**
583
- * Every phase-6 Travel Planner worker Binding, captured with its requirement Contexts
584
- * (spec/subagents.md §11): the P4 planner and its gated twin, the P5 booking agent over the
556
+ * Every phase-6 Travel Planner worker Binding, captured with its requirement Contexts:
557
+ * one P4 planner whose prompt selects the optional test gate, the P5 booking agent over the
585
558
  * shared supplier desk, and the S2 coordinator/researcher pair wired through the durable
586
- * delegation Layer. A Conversation Object registers these via its `bindings` option; the
559
+ * delegation Layer. A Thread Object registers these via its `bindings` option; the
587
560
  * capture runs once per incarnation, and everything stateful the assertions rely on (desk,
588
561
  * guide counter, gates) lives at module level so it survives incarnation loss.
589
562
  */
@@ -594,11 +567,6 @@ export const makePhase6TravelPlannerBindings: Effect.Effect<ReadonlyArray<Resolv
594
567
  phase4TravelPlannerDefinitionDigests,
595
568
  ).pipe(Effect.provide(phase4TravelPlannerWorkerLayer));
596
569
 
597
- const gatedPlanner: ResolvedBinding = yield* DurableWorkerBinding.make(
598
- Agent.withModel(TravelPlannerPhase4, phase6GatedPlannerModel),
599
- phase6GatedPlannerDefinitionDigests,
600
- ).pipe(Effect.provide(phase4TravelPlannerWorkerLayer));
601
-
602
570
  const booking: ResolvedBinding = yield* DurableWorkerBinding.make(
603
571
  Agent.withModel(TravelPlannerPhase5, phase6BookingModel),
604
572
  phase5TravelPlannerDefinitionDigests,
@@ -609,6 +577,7 @@ export const makePhase6TravelPlannerBindings: Effect.Effect<ReadonlyArray<Resolv
609
577
  );
610
578
 
611
579
  const researcherBinding = Agent.withModel(DestinationResearcher, phase6ResearcherModel);
580
+
612
581
  const childToolkitLayer = DestinationResearcherToolkitLayer.pipe(
613
582
  Layer.provideMerge(countingGuideLayer),
614
583
  );
@@ -636,7 +605,7 @@ export const makePhase6TravelPlannerBindings: Effect.Effect<ReadonlyArray<Resolv
636
605
  s2ResearcherDigests,
637
606
  ).pipe(Effect.provide(childToolkitLayer));
638
607
 
639
- return [planner, gatedPlanner, booking, coordinator, researcher];
608
+ return [planner, booking, coordinator, researcher];
640
609
  });
641
610
 
642
611
  // ---------------------------------------------------------------------------
@@ -651,21 +620,21 @@ export const makePhase6TravelPlannerBindings: Effect.Effect<ReadonlyArray<Resolv
651
620
  * value, so the two platforms' canonical outcomes are byte-equivalent transitively — the P6
652
621
  * exit gate "Travel Planner produces equivalent canonical outcomes under DN and DC".
653
622
  *
654
- * Regenerate ONLY when the Travel Planner scenario itself changes, by printing either suite's
623
+ * Regenerate ONLY when the Travel Planner scenario or canonical protocol changes, by printing either suite's
655
624
  * normalized value; both suites must then agree on the new golden.
656
625
  */
657
626
  export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
658
627
  {
659
- batchId: "conversation-created:{conversationId}",
628
+ batchId: "thread-created:{threadId}",
660
629
  sequence: 1,
661
630
  record: {
662
- recordId: "conversation-created:{conversationId}",
663
- family: "conversation",
631
+ recordId: "thread-created:{threadId}",
632
+ family: "thread",
664
633
  schemaVersion: 1,
665
634
  createdAt: "{timestamp}",
666
635
  deploymentId: "{deploymentId}",
667
636
  payload: {
668
- _tag: "ConversationCreated",
637
+ _tag: "ThreadCreated",
669
638
  agentId: "travel-planner-phase-4",
670
639
  definitions: {
671
640
  agent: "{digest}",
@@ -680,7 +649,7 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
680
649
  sequence: 2,
681
650
  record: {
682
651
  recordId: "input:{submissionId}",
683
- family: "conversation",
652
+ family: "thread",
684
653
  schemaVersion: 1,
685
654
  createdAt: "{timestamp}",
686
655
  deploymentId: "{deploymentId}",
@@ -704,21 +673,83 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
704
673
  },
705
674
  },
706
675
  {
707
- batchId: "turn-response:run:{submissionId}:1",
676
+ batchId: "run-start:run:{submissionId}",
708
677
  sequence: 3,
678
+ record: {
679
+ recordId: "run-start:run:{submissionId}",
680
+ family: "thread",
681
+ schemaVersion: 1,
682
+ createdAt: "{timestamp}",
683
+ deploymentId: "{deploymentId}",
684
+ payload: {
685
+ _tag: "RunStarted",
686
+ runId: "run:{submissionId}",
687
+ policyAccountingVersion: 1,
688
+ maxDurationMillis: 30_000,
689
+ },
690
+ },
691
+ },
692
+ {
693
+ batchId: "turn-response:run:{submissionId}:1",
694
+ sequence: 4,
709
695
  record: {
710
696
  recordId: "model-response:run:{submissionId}:1",
711
- family: "conversation",
697
+ family: "thread",
712
698
  schemaVersion: 1,
713
699
  createdAt: "{timestamp}",
714
700
  deploymentId: "{deploymentId}",
715
701
  payload: {
716
702
  _tag: "ModelResponseRecorded",
703
+ toolOperations: [
704
+ {
705
+ toolCallId: "flight-call-1",
706
+ toolName: "search_flights",
707
+ executionClass: "readonly",
708
+ executionKind: "ordinary",
709
+ replay: "{digest}",
710
+ },
711
+ {
712
+ toolCallId: "lodging-call-1",
713
+ toolName: "search_lodging",
714
+ executionClass: "readonly",
715
+ executionKind: "ordinary",
716
+ replay: "{digest}",
717
+ },
718
+ {
719
+ toolCallId: "activity-call-1",
720
+ toolName: "search_activities",
721
+ executionClass: "readonly",
722
+ executionKind: "ordinary",
723
+ replay: "{digest}",
724
+ },
725
+ ],
717
726
  runId: "run:{submissionId}",
718
727
  turnId: "turn:run:{submissionId}:1",
719
728
  turn: 1,
720
729
  inputTokens: 128,
721
730
  outputTokens: 96,
731
+ runScopedPrefixLength: 2,
732
+ modelUsage: [
733
+ {
734
+ provider: "scripted",
735
+ model: "travel-planner-phase-4",
736
+ purpose: "turn",
737
+ usageStatus: "partial",
738
+ pricingStatus: "unknown",
739
+ inputTokens: {
740
+ total: 128,
741
+ uncached: 128,
742
+ cacheRead: 0,
743
+ cacheWrite: 0,
744
+ },
745
+ outputTokens: {
746
+ total: 96,
747
+ text: 96,
748
+ reasoning: 0,
749
+ },
750
+ costMicrousd: 0,
751
+ },
752
+ ],
722
753
  messages: {
723
754
  content: [
724
755
  {
@@ -786,10 +817,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
786
817
  },
787
818
  {
788
819
  batchId: "turn-results:run:{submissionId}:1",
789
- sequence: 4,
820
+ sequence: 5,
790
821
  record: {
791
822
  recordId: "tool-settled:run:{submissionId}:1:flight-call-1",
792
- family: "conversation",
823
+ family: "thread",
793
824
  schemaVersion: 1,
794
825
  createdAt: "{timestamp}",
795
826
  deploymentId: "{deploymentId}",
@@ -810,10 +841,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
810
841
  },
811
842
  {
812
843
  batchId: "turn-results:run:{submissionId}:1",
813
- sequence: 5,
844
+ sequence: 6,
814
845
  record: {
815
846
  recordId: "tool-settled:run:{submissionId}:1:lodging-call-1",
816
- family: "conversation",
847
+ family: "thread",
817
848
  schemaVersion: 1,
818
849
  createdAt: "{timestamp}",
819
850
  deploymentId: "{deploymentId}",
@@ -833,10 +864,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
833
864
  },
834
865
  {
835
866
  batchId: "turn-results:run:{submissionId}:1",
836
- sequence: 6,
867
+ sequence: 7,
837
868
  record: {
838
869
  recordId: "tool-settled:run:{submissionId}:1:activity-call-1",
839
- family: "conversation",
870
+ family: "thread",
840
871
  schemaVersion: 1,
841
872
  createdAt: "{timestamp}",
842
873
  deploymentId: "{deploymentId}",
@@ -854,10 +885,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
854
885
  },
855
886
  {
856
887
  batchId: "turn:run:{submissionId}:2",
857
- sequence: 7,
888
+ sequence: 8,
858
889
  record: {
859
890
  recordId: "model-response:run:{submissionId}:2",
860
- family: "conversation",
891
+ family: "thread",
861
892
  schemaVersion: 1,
862
893
  createdAt: "{timestamp}",
863
894
  deploymentId: "{deploymentId}",
@@ -868,6 +899,27 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
868
899
  turn: 2,
869
900
  inputTokens: 128,
870
901
  outputTokens: 96,
902
+ modelUsage: [
903
+ {
904
+ provider: "scripted",
905
+ model: "travel-planner-phase-4",
906
+ purpose: "turn",
907
+ usageStatus: "partial",
908
+ pricingStatus: "unknown",
909
+ inputTokens: {
910
+ total: 128,
911
+ uncached: 128,
912
+ cacheRead: 0,
913
+ cacheWrite: 0,
914
+ },
915
+ outputTokens: {
916
+ total: 96,
917
+ text: 96,
918
+ reasoning: 0,
919
+ },
920
+ costMicrousd: 0,
921
+ },
922
+ ],
871
923
  messages: {
872
924
  content: [
873
925
  {
@@ -882,12 +934,51 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
882
934
  },
883
935
  },
884
936
  },
937
+ {
938
+ batchId: "turn:run:{submissionId}:2",
939
+ sequence: 9,
940
+ record: {
941
+ recordId: "run-completed:run:{submissionId}",
942
+ family: "thread",
943
+ schemaVersion: 1,
944
+ createdAt: "{timestamp}",
945
+ deploymentId: "{deploymentId}",
946
+ payload: {
947
+ _tag: "RunCompleted",
948
+ resultDigest: "{digest}",
949
+ runId: "run:{submissionId}",
950
+ output: {
951
+ itineraries: [
952
+ {
953
+ title: "Westward light, eastbound overnight",
954
+ route: "San Francisco → London",
955
+ dates: "14–19 September 2026",
956
+ flight: "EA 218 · nonstop · SFO 18:40 → LHR 13:05+1",
957
+ lodging: "Bloomsbury House · refundable studio · 4 nights",
958
+ activities: ["British Museum timed entry", "Thames evening walk"],
959
+ estimatedTotalCents: 284000,
960
+ currency: "USD",
961
+ quoteId: "quote-sfo-lhr-001",
962
+ assumptions: [
963
+ "Two travelers sharing one studio",
964
+ "Quote is read-only availability, not a reservation",
965
+ ],
966
+ unresolvedConstraints: [
967
+ "Traveler names and accessibility requests are intentionally omitted",
968
+ ],
969
+ nextAction: "review",
970
+ },
971
+ ],
972
+ },
973
+ },
974
+ },
975
+ },
885
976
  {
886
977
  batchId: "submission-settlement:{submissionId}",
887
- sequence: 8,
978
+ sequence: 10,
888
979
  record: {
889
980
  recordId: "settlement:{submissionId}",
890
- family: "conversation",
981
+ family: "thread",
891
982
  schemaVersion: 1,
892
983
  createdAt: "{timestamp}",
893
984
  deploymentId: "{deploymentId}",
@@ -921,6 +1012,43 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
921
1012
  },
922
1013
  ],
923
1014
  },
1015
+ usageSummary: {
1016
+ usageStatus: "partial",
1017
+ pricingStatus: "unknown",
1018
+ unobservedModelCalls: 0,
1019
+ modelCalls: 2,
1020
+ inputTokens: {
1021
+ total: 256,
1022
+ uncached: 256,
1023
+ cacheRead: 0,
1024
+ cacheWrite: 0,
1025
+ },
1026
+ outputTokens: {
1027
+ total: 192,
1028
+ text: 192,
1029
+ reasoning: 0,
1030
+ },
1031
+ costMicrousd: 0,
1032
+ byModel: [
1033
+ {
1034
+ provider: "scripted",
1035
+ model: "travel-planner-phase-4",
1036
+ modelCalls: 2,
1037
+ inputTokens: {
1038
+ total: 256,
1039
+ uncached: 256,
1040
+ cacheRead: 0,
1041
+ cacheWrite: 0,
1042
+ },
1043
+ outputTokens: {
1044
+ total: 192,
1045
+ text: 192,
1046
+ reasoning: 0,
1047
+ },
1048
+ costMicrousd: 0,
1049
+ },
1050
+ ],
1051
+ },
924
1052
  },
925
1053
  },
926
1054
  },