stitchkit 0.65.1 → 0.66.1

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 (35) hide show
  1. package/dist/agent-runtime/coordinator.d.ts +8 -5
  2. package/dist/agent-runtime/coordinator.d.ts.map +1 -1
  3. package/dist/agent-runtime/events.d.ts +36 -30
  4. package/dist/agent-runtime/events.d.ts.map +1 -1
  5. package/dist/agent-runtime/injection.d.ts +28 -0
  6. package/dist/agent-runtime/injection.d.ts.map +1 -0
  7. package/dist/agent-runtime/observability.d.ts +22 -20
  8. package/dist/agent-runtime/observability.d.ts.map +1 -1
  9. package/dist/agent-runtime/prompt.d.ts +11 -1
  10. package/dist/agent-runtime/prompt.d.ts.map +1 -1
  11. package/dist/agent-runtime/run-execution.d.ts +11 -0
  12. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  13. package/dist/agent-runtime/runtime-internals.d.ts.map +1 -1
  14. package/dist/agent-runtime/runtime.d.ts.map +1 -1
  15. package/dist/agent-runtime/schemas.d.ts +75 -21
  16. package/dist/agent-runtime/schemas.d.ts.map +1 -1
  17. package/dist/agent-runtime/store-driver.d.ts +21 -15
  18. package/dist/agent-runtime/store-driver.d.ts.map +1 -1
  19. package/dist/agent-runtime/store.d.ts +280 -46
  20. package/dist/agent-runtime/store.d.ts.map +1 -1
  21. package/dist/agent-runtime/terminal-commit.d.ts +33 -3
  22. package/dist/agent-runtime/terminal-commit.d.ts.map +1 -1
  23. package/dist/agent-runtime/terminal-status.d.ts.map +1 -1
  24. package/dist/agent-runtime-openrouter.js +1 -1
  25. package/dist/agent-runtime.d.ts +1 -1
  26. package/dist/agent-runtime.d.ts.map +1 -1
  27. package/dist/agent-runtime.js +384 -97
  28. package/dist/{index-sbkyvacf.js → index-fhsmrzj7.js} +45 -5
  29. package/dist/testing/agent-store-conformance.d.ts +34 -1
  30. package/dist/testing/agent-store-conformance.d.ts.map +1 -1
  31. package/dist/testing.d.ts +1 -1
  32. package/dist/testing.d.ts.map +1 -1
  33. package/dist/testing.js +175 -4
  34. package/llms-full.txt +281 -22
  35. package/package.json +1 -1
@@ -114,6 +114,7 @@ var AgentTerminalReasonSchema = z.enum([
114
114
  "shutdown",
115
115
  "provider_failure",
116
116
  "context_overflow",
117
+ "absorbed",
117
118
  "abandoned"
118
119
  ]);
119
120
  function runStateForTerminalReason(reason) {
@@ -122,7 +123,7 @@ function runStateForTerminalReason(reason) {
122
123
  }
123
124
  if (reason === "interrupted")
124
125
  return "interrupted";
125
- if (reason === "superseded")
126
+ if (reason === "superseded" || reason === "absorbed")
126
127
  return "superseded";
127
128
  if (reason === "cancelled" || reason === "shutdown" || reason === "timeout") {
128
129
  return "cancelled";
@@ -131,14 +132,31 @@ function runStateForTerminalReason(reason) {
131
132
  return "abandoned";
132
133
  return "failed";
133
134
  }
135
+ var AgentProvenanceSchema = z.enum([
136
+ "provider-reported",
137
+ "measured",
138
+ "computed",
139
+ "estimated",
140
+ "unavailable"
141
+ ]);
134
142
  var AgentUsageValueSchema = z.object({
135
- value: z.number().nonnegative().optional(),
136
- provenance: z.enum(["provider-reported", "computed", "estimated", "unavailable"])
143
+ value: z.int().nonnegative().optional(),
144
+ provenance: AgentProvenanceSchema.extract([
145
+ "provider-reported",
146
+ "computed",
147
+ "estimated",
148
+ "unavailable"
149
+ ])
137
150
  });
138
151
  var AgentCostValueSchema = z.object({
139
152
  value: z.number().nonnegative().optional(),
140
153
  currency: z.string().length(3).optional(),
141
- provenance: z.enum(["provider-reported", "computed", "estimated", "unavailable"])
154
+ provenance: AgentProvenanceSchema.extract([
155
+ "provider-reported",
156
+ "computed",
157
+ "estimated",
158
+ "unavailable"
159
+ ])
142
160
  });
143
161
  var AgentUsageSchema = z.object({
144
162
  inputTokens: AgentUsageValueSchema,
@@ -160,11 +178,19 @@ var AgentRunFieldsSchema = z.object({
160
178
  fencingToken: AgentRecordVersionSchema.optional(),
161
179
  terminalReason: AgentTerminalReasonSchema.optional(),
162
180
  terminalPolicyName: z.string().min(1).optional(),
181
+ absorbedIntoRunId: AgentRecordIdSchema.optional(),
163
182
  usage: AgentUsageSchema.optional(),
164
183
  createdAt: AgentTimestampSchema,
165
184
  updatedAt: AgentTimestampSchema
166
185
  });
167
186
  var AgentRunSchema = AgentRunFieldsSchema.superRefine((run, ctx) => {
187
+ if (run.terminalReason !== "absorbed" && run.absorbedIntoRunId !== undefined) {
188
+ ctx.addIssue({
189
+ code: "custom",
190
+ path: ["absorbedIntoRunId"],
191
+ message: "Only an absorbed run names the run that answered it"
192
+ });
193
+ }
168
194
  if (run.terminalReason === undefined) {
169
195
  if (TERMINAL_RUN_STATES.has(run.state)) {
170
196
  ctx.addIssue({
@@ -190,6 +216,20 @@ var AgentRunSchema = AgentRunFieldsSchema.superRefine((run, ctx) => {
190
216
  message: "A policy stop names the policy that stopped the run"
191
217
  });
192
218
  }
219
+ if (run.terminalReason === "absorbed" && run.absorbedIntoRunId === undefined) {
220
+ ctx.addIssue({
221
+ code: "custom",
222
+ path: ["absorbedIntoRunId"],
223
+ message: "An absorbed run names the run that answered its input"
224
+ });
225
+ }
226
+ if (run.absorbedIntoRunId === run.id) {
227
+ ctx.addIssue({
228
+ code: "custom",
229
+ path: ["absorbedIntoRunId"],
230
+ message: "A run cannot absorb itself"
231
+ });
232
+ }
193
233
  });
194
234
  var TERMINAL_RUN_STATES = new Set([
195
235
  "completed",
@@ -213,4 +253,4 @@ var AgentRunMetricsSchema = z.object({
213
253
  ttftMs: z.number().nonnegative().optional()
214
254
  });
215
255
 
216
- export { AgentRecordIdSchema, AgentRecordVersionSchema, AgentTimestampSchema, AgentJsonObjectSchema, AgentProviderEnvelopeSchema, AgentTextPartSchema, AgentReasoningPartSchema, AgentFilePartSchema, AgentSourcePartSchema, AgentToolCallPartSchema, AgentToolResultPartSchema, AgentOpaquePartSchema, AgentControlPartSchema, AgentMessagePartSchema, AgentMessageRoleSchema, AgentMessageStatusSchema, AgentMessageSchema, AgentAssistantPlaceholderSchema, AgentRunStateSchema, AgentTerminalReasonSchema, runStateForTerminalReason, AgentUsageValueSchema, AgentCostValueSchema, AgentUsageSchema, AgentRunSchema, AgentSnapshotSchema, AgentRunMetricsSchema };
256
+ export { AgentRecordIdSchema, AgentRecordVersionSchema, AgentTimestampSchema, AgentJsonObjectSchema, AgentProviderEnvelopeSchema, AgentTextPartSchema, AgentReasoningPartSchema, AgentFilePartSchema, AgentSourcePartSchema, AgentToolCallPartSchema, AgentToolResultPartSchema, AgentOpaquePartSchema, AgentControlPartSchema, AgentMessagePartSchema, AgentMessageRoleSchema, AgentMessageStatusSchema, AgentMessageSchema, AgentAssistantPlaceholderSchema, AgentRunStateSchema, AgentTerminalReasonSchema, runStateForTerminalReason, AgentProvenanceSchema, AgentUsageValueSchema, AgentCostValueSchema, AgentUsageSchema, AgentRunSchema, AgentSnapshotSchema, AgentRunMetricsSchema };
@@ -1,6 +1,39 @@
1
1
  import type { AgentRuntimeStore } from '../agent-runtime/store';
2
+ /**
3
+ * What the scenario is about to touch, handed over before the first mutation.
4
+ *
5
+ * The kit used to pick its conversation identities *after* `createStore()`
6
+ * returned, which locked out exactly the adapters it exists to certify: a
7
+ * durable store whose runtime rows hang off an application-owned conversation
8
+ * row cannot serve the first admission, because nobody ever told it which
9
+ * parent to provision. Running the kit against the memory reference store
10
+ * instead proves the reducer — which is not the thing under test.
11
+ */
12
+ export interface AgentStoreConformanceContext {
13
+ /**
14
+ * Every conversation the scenario mutates, in the order it first touches
15
+ * them. Provision one parent per id before returning the store, and remove
16
+ * them again in `cleanup`.
17
+ */
18
+ readonly conversationIds: readonly string[];
19
+ }
2
20
  export interface AgentStoreConformanceConfig {
3
- createStore(): AgentRuntimeStore | Promise<AgentRuntimeStore>;
21
+ /**
22
+ * Build the store under test. The context arrives first so an adapter can
23
+ * provision fixture state; a factory that needs none may ignore it, and an
24
+ * existing zero-argument factory stays valid unchanged.
25
+ */
26
+ createStore(context: AgentStoreConformanceContext): AgentRuntimeStore | Promise<AgentRuntimeStore>;
27
+ /**
28
+ * Remove whatever `createStore` provisioned.
29
+ *
30
+ * Runs exactly once, after the scenario, whether it passed or failed — a kit
31
+ * that only cleans up on success leaks a row for every red run, which is the
32
+ * shape that makes a failing suite un-rerunnable. A failure here never
33
+ * replaces the scenario's own: the answer to "does this adapter conform" is
34
+ * not overwritten by the answer to "did the teardown work".
35
+ */
36
+ cleanup?(context: AgentStoreConformanceContext): void | Promise<void>;
4
37
  }
5
38
  /** Black-box contract shared by memory and third-party durable agent stores. */
6
39
  export declare function runAgentStoreConformance(config: AgentStoreConformanceConfig): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/agent-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,WAAW,2BAA2B;IAC1C,WAAW,IAAI,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC/D;AAwCD,gFAAgF;AAChF,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,IAAI,CAAC,CAiXf"}
1
+ {"version":3,"file":"agent-store-conformance.d.ts","sourceRoot":"","sources":["../../src/testing/agent-store-conformance.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE;;;;;;;;;GASG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,WAAW,CACT,OAAO,EAAE,4BAA4B,GACpC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClD;;;;;;;;OAQG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE,4BAA4B,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAwCD,gFAAgF;AAChF,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
package/dist/testing.d.ts CHANGED
@@ -32,7 +32,7 @@ export declare function createHandlerTestClients<T extends Record<string, Contra
32
32
  [P in keyof T]: ScopedHttpClient<T[P]['endpoints'], ScopedKeys<K>>;
33
33
  };
34
34
  export { type AgentRaceBarrier, type AgentRaceDriver, type AgentRaceTrace, type AgentRaceTraceEntry, createAgentRaceBarrier, createAgentRaceDriver, createAgentRaceTrace, } from './agent-runtime/testing';
35
- export { type AgentStoreConformanceConfig, runAgentStoreConformance, } from './testing/agent-store-conformance';
35
+ export { type AgentStoreConformanceConfig, type AgentStoreConformanceContext, runAgentStoreConformance, } from './testing/agent-store-conformance';
36
36
  export { type ManagedResourceConformanceConfig, type ManagedResourceConformanceControls, ManagedResourceConformanceError, type ManagedResourceConformanceFactoryInput, type ManagedResourceConformanceFixture, type ManagedResourceConformancePhase, ManagedResourceConformancePhaseSchema, type ManagedResourceConformanceScenario, type ManagedResourceConformanceScenarioId, ManagedResourceConformanceScenarioIdSchema, ManagedResourceConformanceScenarioSchema, type ManagedResourceConformanceTraceEntry, ManagedResourceConformanceTraceEntrySchema, type ManagedResourceConformanceTraceOutcome, ManagedResourceConformanceTraceOutcomeSchema, runManagedResourceConformance, } from './testing/managed-resource-conformance';
37
37
  export { assertSurfaceDiscovery, type ConformanceTransport, type CreateRealtimeProbeDriverConfig, createRealtimeProbeDriver, type DefineRealtimeProbeConfig, defineRealtimeProbe, type RealtimeDisconnectObservation, RealtimeDisconnectObservationSchema, type RealtimeProbeAdapter, type RealtimeProbeFixture, type RealtimeProbeScenario, type RealtimeRejectionObservation, RealtimeRejectionObservationSchema, type RunSurfaceProbesConfig, runSurfaceProbes, type SurfaceDiscoveryObservation, type SurfaceProbe, type SurfaceProbeDriver, type SurfaceRealtimeDiscoveryObservation, type SurfaceToolDiscoveryObservation, type TransportObservation, TransportObservationSchema, } from './testing/surface-conformance';
38
38
  export { assertSurfaceManifestSnapshot, buildSurfaceManifest, type IncompatibleSchemaPolicy, type McpSchemaValidationConfig, type SurfaceAgentProjection, type SurfaceManifest, type SurfaceManifestConfig, type SurfaceManifestExtension, SurfaceManifestExtensionSchema, type SurfaceManifestOperation, SurfaceManifestOperationSchema, type SurfaceManifestRealtimeEvent, SurfaceManifestRealtimeEventSchema, SurfaceManifestSchema, type SurfaceManifestTool, SurfaceManifestToolSchema, type SurfaceManifestToolSurface, SurfaceManifestToolSurfaceSchema, type SurfaceMcpPreparation, SurfaceRealtimeSchemaPairSchema, type SurfaceRuntimeToolDefinition, SurfaceSchemaDigestsSchema, type SurfaceToolDefinition, type SurfaceToolExtension, serializeSurfaceValue, } from './testing/surface-manifest';
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,oBAAoB,EAGzB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;AAEhF,MAAM,WAAW,0BAA0B,CAAC,OAAO;IACjD,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC/B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qFAAqF;IACrF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB,CACtC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,OAAO,GAAG,OAAO,EACjB,CAAC,SAAS,MAAM,GAAG,KAAK,CACxB,SAAQ,0BAA0B,CAAC,OAAO,CAAC;IAC3C,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACjC,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,wBAAwB,CACvC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,EAC1E,OAAO,GAAG,OAAO,EACjB,CAAC,SAAS,MAAM,GAAG,KAAK,CACxB,SAAQ,0BAA0B,CAAC,OAAO,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC;IACb,cAAc,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;CAC1C;AA+BD,gGAAgG;AAChG,wBAAgB,uBAAuB,CACrC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,OAAO,GAAG,OAAO,EACjB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,EAC9B,MAAM,EAAE,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAEpF;AAED,2FAA2F;AAC3F,wBAAgB,wBAAwB,CACtC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,EAC1E,OAAO,GAAG,OAAO,EACjB,KAAK,CAAC,CAAC,SAAS,MAAM,GAAG,KAAK,EAE9B,MAAM,EAAE,wBAAwB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,GAC9C;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CAAE,CAMxE;AAED,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,2BAA2B,EAChC,wBAAwB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,KAAK,gCAAgC,EACrC,KAAK,kCAAkC,EACvC,+BAA+B,EAC/B,KAAK,sCAAsC,EAC3C,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EACpC,qCAAqC,EACrC,KAAK,kCAAkC,EACvC,KAAK,oCAAoC,EACzC,0CAA0C,EAC1C,wCAAwC,EACxC,KAAK,oCAAoC,EACzC,0CAA0C,EAC1C,KAAK,sCAAsC,EAC3C,4CAA4C,EAC5C,6BAA6B,GAC9B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,+BAA+B,EACpC,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,mBAAmB,EACnB,KAAK,6BAA6B,EAClC,mCAAmC,EACnC,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,4BAA4B,EACjC,kCAAkC,EAClC,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,KAAK,2BAA2B,EAChC,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,mCAAmC,EACxC,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,EACzB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,6BAA6B,EAC7B,oBAAoB,EACpB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,8BAA8B,EAC9B,KAAK,wBAAwB,EAC7B,8BAA8B,EAC9B,KAAK,4BAA4B,EACjC,kCAAkC,EAClC,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,gCAAgC,EAChC,KAAK,qBAAqB,EAC1B,+BAA+B,EAC/B,KAAK,4BAA4B,EACjC,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
package/dist/testing.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AgentMessageSchema,
3
3
  AgentRunSchema
4
- } from "./index-sbkyvacf.js";
4
+ } from "./index-fhsmrzj7.js";
5
5
  import {
6
6
  createApplication
7
7
  } from "./index-eabpd4tb.js";
@@ -141,8 +141,33 @@ function requireOutcome(actual, expected) {
141
141
  }
142
142
  }
143
143
  async function runAgentStoreConformance(config) {
144
- const store = await config.createStore();
145
- const conversationId = `conformance-${crypto.randomUUID()}`;
144
+ const run = `conformance-${crypto.randomUUID()}`;
145
+ const context = {
146
+ conversationIds: [run, `${run}-recovery`, `${run}-absorb`]
147
+ };
148
+ const store = await config.createStore(context);
149
+ let failure;
150
+ try {
151
+ await conformanceScenario(store, context.conversationIds);
152
+ } catch (error) {
153
+ failure = error;
154
+ }
155
+ try {
156
+ await config.cleanup?.(context);
157
+ } catch (cleanupError) {
158
+ if (failure === undefined)
159
+ throw cleanupError;
160
+ throw new AggregateError([failure, cleanupError], `${failure instanceof Error ? failure.message : String(failure)} (cleanup also failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)})`);
161
+ }
162
+ if (failure !== undefined)
163
+ throw failure;
164
+ }
165
+ async function conformanceScenario(store, conversationIds) {
166
+ const [conversationId, recoveryConversationId, absorbConversationId] = conversationIds;
167
+ if (!conversationId || !recoveryConversationId || !absorbConversationId) {
168
+ throw new Error("Agent store conformance requires three conversation identities");
169
+ }
170
+ const absentConversationId = `${conversationId}-absent`;
146
171
  const firstInput = userMessage(conversationId, "input-1");
147
172
  const firstRun = queuedRun(conversationId, firstInput.id, "run-1");
148
173
  const accepted = await store.acceptInputAndAssignRun({
@@ -352,6 +377,50 @@ async function runAgentStoreConformance(config) {
352
377
  if (foreignOwner.outcome !== "conflict") {
353
378
  throw new Error("A checkpoint from another owner must conflict");
354
379
  }
380
+ const liveView = await store.loadRun({ conversationId, runId: running.id });
381
+ if (!liveView)
382
+ throw new Error("loadRun must find a run of this conversation");
383
+ if (liveView.run.id !== running.id || liveView.run.conversationId !== conversationId) {
384
+ throw new Error("loadRun returned a run it was not asked for");
385
+ }
386
+ if (liveView.run.revision !== checkpointedRun.revision) {
387
+ throw new Error("loadRun must return the run as the last mutation left it");
388
+ }
389
+ if (liveView.run.usage?.cost?.value !== 0.25) {
390
+ throw new Error("loadRun must carry the figure the run has spent so far");
391
+ }
392
+ if (liveView.snapshotVersion !== checkpoint.snapshot.version) {
393
+ throw new Error("loadRun must report the conversation version it read at");
394
+ }
395
+ if (liveView.assistant !== undefined) {
396
+ throw new Error("loadRun must not report a terminal answer for a live run");
397
+ }
398
+ if (await store.loadRun({ conversationId, runId: "no-such-run" })) {
399
+ throw new Error("loadRun must return undefined for an unknown run");
400
+ }
401
+ if (await store.loadRun({ conversationId: absentConversationId, runId: running.id })) {
402
+ throw new Error("loadRun must not cross conversation boundaries");
403
+ }
404
+ const activeRuns = await store.listActiveRuns(conversationId);
405
+ if (!activeRuns.some((run) => run.id === running.id)) {
406
+ throw new Error("listActiveRuns must report a run that is in flight");
407
+ }
408
+ if (activeRuns.some((run) => run.terminalReason !== undefined)) {
409
+ throw new Error("listActiveRuns must not report a run that has ended");
410
+ }
411
+ for (let index = 1;index < activeRuns.length; index += 1) {
412
+ const previous = activeRuns[index - 1];
413
+ const current = activeRuns[index];
414
+ if (!previous || !current)
415
+ continue;
416
+ const ordered = previous.createdAt === current.createdAt ? previous.id.localeCompare(current.id) < 0 : previous.createdAt < current.createdAt;
417
+ if (!ordered) {
418
+ throw new Error("listActiveRuns must order by createdAt and then by id");
419
+ }
420
+ }
421
+ if ((await store.listActiveRuns(absentConversationId)).length !== 0) {
422
+ throw new Error("listActiveRuns must be empty for an unknown conversation");
423
+ }
355
424
  const recoverable = await store.scanRecoverable({ limit: 10 });
356
425
  if (!recoverable.items.some((item) => item.run.id === running.id)) {
357
426
  throw new Error("A running run must appear in a recoverable scan");
@@ -409,6 +478,16 @@ async function runAgentStoreConformance(config) {
409
478
  if (settledRun?.usage?.cost?.value !== 1.5) {
410
479
  throw new Error("Terminal commit did not persist the run usage it was given");
411
480
  }
481
+ const terminalView = await store.loadRun({ conversationId, runId: running.id });
482
+ if (terminalView?.run.terminalReason !== "success") {
483
+ throw new Error("loadRun must report the terminal reason a settled run ended with");
484
+ }
485
+ if (JSON.stringify(terminalView.assistant) !== JSON.stringify(terminalAssistant)) {
486
+ throw new Error("loadRun must retain the answer a settled run produced");
487
+ }
488
+ if ((await store.listActiveRuns(conversationId)).some((run) => run.id === running.id)) {
489
+ throw new Error("listActiveRuns must drop a run once it has ended");
490
+ }
412
491
  const compactedTerminal = await store.replaceCompactedRange({
413
492
  conversationId,
414
493
  expectedVersion: terminalApplied.snapshot.version,
@@ -434,7 +513,6 @@ async function runAgentStoreConformance(config) {
434
513
  if (duplicateTerminal.run.terminalReason !== "success" || JSON.stringify(duplicateTerminal.assistant) !== JSON.stringify(terminalAssistant)) {
435
514
  throw new Error("Compaction discarded the canonical duplicate terminal result");
436
515
  }
437
- const recoveryConversationId = `${conversationId}-recovery`;
438
516
  const recoveryInput = userMessage(recoveryConversationId, "recovery-input");
439
517
  const recoveryRun = queuedRun(recoveryConversationId, recoveryInput.id, "recovery-run");
440
518
  const recoveryAccepted = await store.acceptInputAndAssignRun({
@@ -468,6 +546,99 @@ async function runAgentStoreConformance(config) {
468
546
  if (terminalRun?.state !== "abandoned" || terminalMessage?.status !== "failed") {
469
547
  throw new Error("Abandon recovery did not atomically terminalize its assistant record");
470
548
  }
549
+ await assertAbsorptionIsAtomic(store, absorbConversationId);
550
+ }
551
+ async function assertAbsorptionIsAtomic(store, conversationId) {
552
+ const leadInput = userMessage(conversationId, "absorb-input-1");
553
+ const leadRun = queuedRun(conversationId, leadInput.id, "absorb-run-1");
554
+ const lead = await store.acceptInputAndAssignRun({
555
+ idempotencyKey: "absorb-request-1",
556
+ input: leadInput,
557
+ run: leadRun
558
+ });
559
+ requireOutcome(lead, "applied");
560
+ const successorInput = userMessage(conversationId, "absorb-input-2");
561
+ const successorRun = queuedRun(conversationId, successorInput.id, "absorb-run-2");
562
+ const successor = await store.acceptInputAndAssignRun({
563
+ idempotencyKey: "absorb-request-2",
564
+ input: successorInput,
565
+ run: successorRun
566
+ });
567
+ requireOutcome(successor, "applied");
568
+ const acquired = await store.acquireRun({
569
+ conversationId,
570
+ runId: leadRun.id,
571
+ expectedRevision: 0,
572
+ ownerId: "absorb-owner"
573
+ });
574
+ requireOutcome(acquired, "applied");
575
+ const running = acquired.snapshot.runs.find((run) => run.id === leadRun.id);
576
+ if (!running)
577
+ throw new Error("Absorbing run disappeared after acquisition");
578
+ const answer = AgentMessageSchema.parse({
579
+ schemaVersion: 1,
580
+ id: running.assistantMessageId,
581
+ conversationId,
582
+ runId: running.id,
583
+ role: "assistant",
584
+ status: "completed",
585
+ parts: [{ type: "text", text: "answered both" }],
586
+ createdAt: "2026-08-26T00:00:00.000Z",
587
+ updatedAt: "2026-08-26T00:00:02.000Z"
588
+ });
589
+ await store.commitRunTerminal({
590
+ conversationId,
591
+ runId: running.id,
592
+ expectedRevision: running.revision,
593
+ ownerId: "absorb-owner",
594
+ assistant: AgentMessageSchema.parse({ ...answer, status: "interrupted" }),
595
+ reason: "interrupted",
596
+ absorb: [{ runId: successorRun.id, inputMessageIds: [successorInput.id] }]
597
+ }).then(() => {
598
+ throw new Error("A non-completing run absorbed a queued successor");
599
+ }, (error) => {
600
+ if (!(error instanceof TypeError))
601
+ throw error;
602
+ });
603
+ const committed = await store.commitRunTerminal({
604
+ conversationId,
605
+ runId: running.id,
606
+ expectedRevision: running.revision,
607
+ ownerId: "absorb-owner",
608
+ assistant: answer,
609
+ reason: "success",
610
+ absorb: [{ runId: successorRun.id, inputMessageIds: [successorInput.id] }]
611
+ });
612
+ requireOutcome(committed, "applied");
613
+ const absorbingView = await store.loadRun({ conversationId, runId: leadRun.id });
614
+ if (absorbingView?.run.inputMessageIds.join(",") !== "absorb-input-1,absorb-input-2") {
615
+ throw new Error("An absorbing run must record the inputs it answered");
616
+ }
617
+ const absorbedView = await store.loadRun({ conversationId, runId: successorRun.id });
618
+ if (absorbedView?.run.terminalReason !== "absorbed") {
619
+ throw new Error("An absorbed successor must be terminal in the same transaction");
620
+ }
621
+ if (absorbedView.run.absorbedIntoRunId !== leadRun.id) {
622
+ throw new Error("An absorbed run must name the run that answered its input");
623
+ }
624
+ if (absorbedView.assistant !== undefined) {
625
+ throw new Error("An absorbed run produced no answer and must retain none");
626
+ }
627
+ if ((await store.listActiveRuns(conversationId)).length !== 0) {
628
+ throw new Error("An absorbed successor must leave the active listing");
629
+ }
630
+ const retried = await store.acceptInputAndAssignRun({
631
+ idempotencyKey: "absorb-request-2",
632
+ input: userMessage(conversationId, "absorb-discarded"),
633
+ run: queuedRun(conversationId, "absorb-discarded", "absorb-discarded-run")
634
+ });
635
+ requireOutcome(retried, "duplicate");
636
+ if (retried.runId !== leadRun.id || retried.assistant?.id !== answer.id) {
637
+ throw new Error("A retried absorbed key must resolve to the run that answered it");
638
+ }
639
+ if (retried.inputMessageId !== successorInput.id) {
640
+ throw new Error("A retried absorbed key must still name its own input");
641
+ }
471
642
  }
472
643
  // src/testing/managed-resource-conformance-contract.ts
473
644
  import { z } from "zod";