@effect-agent/testing 0.0.1-beta.6 → 0.1.0-beta.100

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 -3376
  26. package/dist/index.mjs +2 -4766
  27. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  28. package/package.json +1 -48
  29. package/src/{certification.ts → Certification.ts} +380 -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 +228 -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,19 +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,
729
+ inputTokens: 128,
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
+ ],
720
753
  messages: {
721
754
  content: [
722
755
  {
@@ -784,10 +817,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
784
817
  },
785
818
  {
786
819
  batchId: "turn-results:run:{submissionId}:1",
787
- sequence: 4,
820
+ sequence: 5,
788
821
  record: {
789
822
  recordId: "tool-settled:run:{submissionId}:1:flight-call-1",
790
- family: "conversation",
823
+ family: "thread",
791
824
  schemaVersion: 1,
792
825
  createdAt: "{timestamp}",
793
826
  deploymentId: "{deploymentId}",
@@ -808,10 +841,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
808
841
  },
809
842
  {
810
843
  batchId: "turn-results:run:{submissionId}:1",
811
- sequence: 5,
844
+ sequence: 6,
812
845
  record: {
813
846
  recordId: "tool-settled:run:{submissionId}:1:lodging-call-1",
814
- family: "conversation",
847
+ family: "thread",
815
848
  schemaVersion: 1,
816
849
  createdAt: "{timestamp}",
817
850
  deploymentId: "{deploymentId}",
@@ -831,10 +864,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
831
864
  },
832
865
  {
833
866
  batchId: "turn-results:run:{submissionId}:1",
834
- sequence: 6,
867
+ sequence: 7,
835
868
  record: {
836
869
  recordId: "tool-settled:run:{submissionId}:1:activity-call-1",
837
- family: "conversation",
870
+ family: "thread",
838
871
  schemaVersion: 1,
839
872
  createdAt: "{timestamp}",
840
873
  deploymentId: "{deploymentId}",
@@ -852,10 +885,10 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
852
885
  },
853
886
  {
854
887
  batchId: "turn:run:{submissionId}:2",
855
- sequence: 7,
888
+ sequence: 8,
856
889
  record: {
857
890
  recordId: "model-response:run:{submissionId}:2",
858
- family: "conversation",
891
+ family: "thread",
859
892
  schemaVersion: 1,
860
893
  createdAt: "{timestamp}",
861
894
  deploymentId: "{deploymentId}",
@@ -864,6 +897,29 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
864
897
  runId: "run:{submissionId}",
865
898
  turnId: "turn:run:{submissionId}:2",
866
899
  turn: 2,
900
+ inputTokens: 128,
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
+ ],
867
923
  messages: {
868
924
  content: [
869
925
  {
@@ -878,12 +934,51 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
878
934
  },
879
935
  },
880
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
+ },
881
976
  {
882
977
  batchId: "submission-settlement:{submissionId}",
883
- sequence: 8,
978
+ sequence: 10,
884
979
  record: {
885
980
  recordId: "settlement:{submissionId}",
886
- family: "conversation",
981
+ family: "thread",
887
982
  schemaVersion: 1,
888
983
  createdAt: "{timestamp}",
889
984
  deploymentId: "{deploymentId}",
@@ -917,6 +1012,43 @@ export const phase6TravelPlannerGoldenEvidence: Schema.Json = [
917
1012
  },
918
1013
  ],
919
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
+ },
920
1052
  },
921
1053
  },
922
1054
  },