@earendil-works/pi-durable 0.87.1 → 0.99.0

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 (168) hide show
  1. package/README.md +46 -4
  2. package/dist/documents.d.ts +66 -0
  3. package/dist/documents.d.ts.map +1 -0
  4. package/dist/documents.js +98 -0
  5. package/dist/documents.js.map +1 -0
  6. package/dist/entries.d.ts +13 -0
  7. package/dist/entries.d.ts.map +1 -0
  8. package/dist/entries.js +18 -0
  9. package/dist/entries.js.map +1 -0
  10. package/dist/env/index.d.ts +131 -0
  11. package/dist/env/index.d.ts.map +1 -0
  12. package/dist/env/index.js +45 -0
  13. package/dist/env/index.js.map +1 -0
  14. package/dist/env/node.d.ts +45 -0
  15. package/dist/env/node.d.ts.map +1 -0
  16. package/dist/env/node.js +908 -0
  17. package/dist/env/node.js.map +1 -0
  18. package/dist/env/utils/adaptive-publisher.d.ts +24 -0
  19. package/dist/env/utils/adaptive-publisher.d.ts.map +1 -0
  20. package/dist/env/utils/adaptive-publisher.js +79 -0
  21. package/dist/env/utils/adaptive-publisher.js.map +1 -0
  22. package/dist/env/utils/output-capture.d.ts +31 -0
  23. package/dist/env/utils/output-capture.d.ts.map +1 -0
  24. package/dist/env/utils/output-capture.js +238 -0
  25. package/dist/env/utils/output-capture.js.map +1 -0
  26. package/dist/env/utils/truncate.d.ts +71 -0
  27. package/dist/env/utils/truncate.d.ts.map +1 -0
  28. package/dist/env/utils/truncate.js +294 -0
  29. package/dist/env/utils/truncate.js.map +1 -0
  30. package/dist/errors.d.ts +15 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +24 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/harness/config.d.ts +20 -0
  35. package/dist/harness/config.d.ts.map +1 -0
  36. package/dist/harness/config.js +18 -0
  37. package/dist/harness/config.js.map +1 -0
  38. package/dist/harness/context.d.ts +27 -0
  39. package/dist/harness/context.d.ts.map +1 -0
  40. package/dist/harness/context.js +109 -0
  41. package/dist/harness/context.js.map +1 -0
  42. package/dist/harness/generation.d.ts +36 -0
  43. package/dist/harness/generation.d.ts.map +1 -0
  44. package/dist/harness/generation.js +266 -0
  45. package/dist/harness/generation.js.map +1 -0
  46. package/dist/harness/harness.d.ts +10 -0
  47. package/dist/harness/harness.d.ts.map +1 -0
  48. package/dist/harness/harness.js +266 -0
  49. package/dist/harness/harness.js.map +1 -0
  50. package/dist/harness/live.d.ts +40 -0
  51. package/dist/harness/live.d.ts.map +1 -0
  52. package/dist/harness/live.js +41 -0
  53. package/dist/harness/live.js.map +1 -0
  54. package/dist/harness/prompt.d.ts +24 -0
  55. package/dist/harness/prompt.d.ts.map +1 -0
  56. package/dist/harness/prompt.js +88 -0
  57. package/dist/harness/prompt.js.map +1 -0
  58. package/dist/harness/registry.d.ts +7 -0
  59. package/dist/harness/registry.d.ts.map +1 -0
  60. package/dist/harness/registry.js +309 -0
  61. package/dist/harness/registry.js.map +1 -0
  62. package/dist/harness/scheduler.d.ts +63 -0
  63. package/dist/harness/scheduler.d.ts.map +1 -0
  64. package/dist/harness/scheduler.js +605 -0
  65. package/dist/harness/scheduler.js.map +1 -0
  66. package/dist/harness/submissions.d.ts +24 -0
  67. package/dist/harness/submissions.d.ts.map +1 -0
  68. package/dist/harness/submissions.js +133 -0
  69. package/dist/harness/submissions.js.map +1 -0
  70. package/dist/harness/types.d.ts +358 -0
  71. package/dist/harness/types.d.ts.map +1 -0
  72. package/dist/harness/types.js +2 -0
  73. package/dist/harness/types.js.map +1 -0
  74. package/dist/harness/util.d.ts +14 -0
  75. package/dist/harness/util.d.ts.map +1 -0
  76. package/dist/harness/util.js +55 -0
  77. package/dist/harness/util.js.map +1 -0
  78. package/dist/ids.d.ts +6 -0
  79. package/dist/ids.d.ts.map +1 -0
  80. package/dist/ids.js +9 -0
  81. package/dist/ids.js.map +1 -0
  82. package/dist/index.d.ts +12 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +10 -0
  85. package/dist/index.js.map +1 -1
  86. package/dist/session/forks.d.ts +10 -0
  87. package/dist/session/forks.d.ts.map +1 -0
  88. package/dist/session/forks.js +42 -0
  89. package/dist/session/forks.js.map +1 -0
  90. package/dist/session/observation.d.ts +28 -0
  91. package/dist/session/observation.d.ts.map +1 -0
  92. package/dist/session/observation.js +280 -0
  93. package/dist/session/observation.js.map +1 -0
  94. package/dist/session/session.d.ts +59 -0
  95. package/dist/session/session.d.ts.map +1 -0
  96. package/dist/session/session.js +380 -0
  97. package/dist/session/session.js.map +1 -0
  98. package/dist/session/transaction.d.ts +105 -0
  99. package/dist/session/transaction.d.ts.map +1 -0
  100. package/dist/session/transaction.js +718 -0
  101. package/dist/session/transaction.js.map +1 -0
  102. package/dist/storage/jsonl/index.d.ts +2 -0
  103. package/dist/storage/jsonl/index.d.ts.map +1 -0
  104. package/dist/storage/jsonl/index.js +2 -0
  105. package/dist/storage/jsonl/index.js.map +1 -0
  106. package/dist/storage/jsonl/node.d.ts +6 -0
  107. package/dist/storage/jsonl/node.d.ts.map +1 -0
  108. package/dist/storage/jsonl/node.js +8 -0
  109. package/dist/storage/jsonl/node.js.map +1 -0
  110. package/dist/storage/jsonl/storage.d.ts +115 -0
  111. package/dist/storage/jsonl/storage.d.ts.map +1 -0
  112. package/dist/storage/jsonl/storage.js +681 -0
  113. package/dist/storage/jsonl/storage.js.map +1 -0
  114. package/dist/storage/memory.d.ts +31 -14
  115. package/dist/storage/memory.d.ts.map +1 -1
  116. package/dist/storage/memory.js +208 -61
  117. package/dist/storage/memory.js.map +1 -1
  118. package/dist/storage/sqlite/database.d.ts +5 -1
  119. package/dist/storage/sqlite/database.d.ts.map +1 -1
  120. package/dist/storage/sqlite/database.js.map +1 -1
  121. package/dist/storage/sqlite/index.d.ts.map +1 -1
  122. package/dist/storage/sqlite/migrations.d.ts +1 -1
  123. package/dist/storage/sqlite/migrations.d.ts.map +1 -1
  124. package/dist/storage/sqlite/migrations.js +8 -1
  125. package/dist/storage/sqlite/migrations.js.map +1 -1
  126. package/dist/storage/sqlite/node.d.ts.map +1 -1
  127. package/dist/storage/sqlite/node.js +2 -2
  128. package/dist/storage/sqlite/node.js.map +1 -1
  129. package/dist/storage/sqlite/storage.d.ts +20 -14
  130. package/dist/storage/sqlite/storage.d.ts.map +1 -1
  131. package/dist/storage/sqlite/storage.js +159 -55
  132. package/dist/storage/sqlite/storage.js.map +1 -1
  133. package/dist/tasks.d.ts +6 -0
  134. package/dist/tasks.d.ts.map +1 -0
  135. package/dist/tasks.js +5 -0
  136. package/dist/tasks.js.map +1 -0
  137. package/dist/testing/assertions.d.ts +5 -0
  138. package/dist/testing/assertions.d.ts.map +1 -0
  139. package/dist/testing/assertions.js +25 -0
  140. package/dist/testing/assertions.js.map +1 -0
  141. package/dist/testing/index.d.ts +6 -0
  142. package/dist/testing/index.d.ts.map +1 -0
  143. package/dist/testing/index.js +5 -0
  144. package/dist/testing/index.js.map +1 -0
  145. package/dist/testing/runner.d.ts +10 -0
  146. package/dist/testing/runner.d.ts.map +1 -0
  147. package/dist/testing/runner.js +14 -0
  148. package/dist/testing/runner.js.map +1 -0
  149. package/dist/testing/storage-benchmark.d.ts +41 -0
  150. package/dist/testing/storage-benchmark.d.ts.map +1 -0
  151. package/dist/testing/storage-benchmark.js +351 -0
  152. package/dist/testing/storage-benchmark.js.map +1 -0
  153. package/dist/testing/storage-conformance.d.ts +4 -0
  154. package/dist/testing/storage-conformance.d.ts.map +1 -0
  155. package/dist/testing/storage-conformance.js +1122 -0
  156. package/dist/testing/storage-conformance.js.map +1 -0
  157. package/dist/testing/types.d.ts +19 -0
  158. package/dist/testing/types.d.ts.map +1 -0
  159. package/dist/testing/types.js +2 -0
  160. package/dist/testing/types.js.map +1 -0
  161. package/dist/types.d.ts +422 -54
  162. package/dist/types.d.ts.map +1 -1
  163. package/dist/types.js.map +1 -1
  164. package/docs/chord-delta-findings.md +1 -1
  165. package/docs/pico-v5-chord-usage.md +47 -60
  166. package/docs/pico-v5-handoff.md +469 -264
  167. package/docs/pico-v5.md +1523 -639
  168. package/package.json +30 -5
package/dist/types.d.ts CHANGED
@@ -1,34 +1,215 @@
1
- import type { Context, JsonValue } from "@earendil-works/chord";
1
+ import type { AttachedReplicatedState, Context, Draft, JsonValue } from "@earendil-works/chord";
2
2
  import type { Op } from "@earendil-works/chord/delta";
3
- import type { Message } from "@earendil-works/pi-ai";
3
+ import type { Message, Models } from "@earendil-works/pi-ai";
4
+ import type { ContextView, RegistrySnapshot } from "./harness/types.ts";
4
5
  /** JSON object used as the root of every durable document. */
5
6
  export type JsonObject = {
6
7
  [key: string]: JsonValue;
7
8
  };
8
- /** Session-global identifier shared by every durable record table. */
9
- export type Id = number;
9
+ declare const idBrand: unique symbol;
10
+ /** Erased nominal number identifying one durable record kind. */
11
+ export type Id<Kind extends string, Type = unknown> = number & {
12
+ readonly [idBrand]: {
13
+ readonly kind: Kind;
14
+ readonly type: Type;
15
+ };
16
+ };
17
+ export type ConversationId = Id<"conversation">;
18
+ export type EntryId = Id<"entry">;
19
+ export type TaskId<Result = unknown> = Id<"task", Result>;
20
+ export type SubmissionId = Id<"submission">;
21
+ export type DocumentId = Id<"document">;
22
+ declare const seqBrand: unique symbol;
10
23
  /** Strictly increasing sequence assigned to one atomic storage commit; gaps are permitted. */
11
- export type Seq = number;
24
+ export type Seq = number & {
25
+ readonly [seqBrand]: "sequence";
26
+ };
12
27
  /** The root conversation always uses this reserved ID. */
13
- export declare const ROOT_CONVERSATION_ID: Id;
28
+ export declare const ROOT_CONVERSATION_ID: ConversationId;
29
+ /** Conversation document that retains only its current state. */
30
+ export type LatestConversationSemantics = {
31
+ readonly scope: "conversation";
32
+ readonly history: "latest";
33
+ readonly fork: "current" | "initial";
34
+ };
35
+ /** Conversation document whose history remains addressable for as-of reads. */
36
+ export type RewindableConversationSemantics = {
37
+ readonly scope: "conversation";
38
+ readonly history: "rewindable";
39
+ readonly fork: "asOf" | "current" | "initial";
40
+ };
41
+ /** Ownership and lifetime of a document; only conversation documents declare history and fork behavior. */
42
+ export type DocumentSemantics = {
43
+ readonly scope: "session";
44
+ readonly history?: never;
45
+ readonly fork?: never;
46
+ } | LatestConversationSemantics | RewindableConversationSemantics | {
47
+ readonly scope: "task";
48
+ readonly history?: never;
49
+ readonly fork?: never;
50
+ };
51
+ /** Stored replay state supplied to a document's checkpoint predicate. */
52
+ export type CheckpointInfo = {
53
+ /** Deltas already stored after the newest base, excluding the change being evaluated. */
54
+ readonly deltasSinceBase: number;
55
+ };
56
+ /** Definition fields shared by singleton documents and document families. */
57
+ export type CommonDocDefinition<T extends JsonObject> = {
58
+ /** Stable persisted kind; part of the public protocol. */
59
+ readonly kind: string;
60
+ /** Positive integer version of the stored value shape. */
61
+ readonly version: number;
62
+ initial(): T;
63
+ migrate?(value: JsonObject, fromVersion: number): T;
64
+ /** Return true to store this ordinary change as a complete base instead of a delta. */
65
+ checkpointWhen?(value: Readonly<T>, ops: readonly Op[], info: CheckpointInfo): boolean;
66
+ };
67
+ /** Singleton document definition. */
68
+ export type DocDefinition<T extends JsonObject> = CommonDocDefinition<T> & DocumentSemantics;
69
+ /** Keyed document family definition; `initial(seed)` runs only when a member is absent. */
70
+ export type DocFamilyDefinition<T extends JsonObject, I extends JsonValue> = Omit<CommonDocDefinition<T>, "initial"> & DocumentSemantics & {
71
+ readonly family: true;
72
+ initial(seed: I): T;
73
+ };
74
+ declare const docType: unique symbol;
75
+ /** Typed singleton document token passed explicitly to typed access. */
76
+ export interface DocToken<T extends JsonObject, D extends DocDefinition<T>> {
77
+ readonly definition: D;
78
+ readonly [docType]?: T;
79
+ }
80
+ /** Typed document family token passed explicitly to typed access. */
81
+ export interface DocFamilyToken<T extends JsonObject, I extends JsonValue, D extends DocFamilyDefinition<T, I>> {
82
+ readonly definition: D;
83
+ readonly [docType]?: T;
84
+ }
85
+ export type SessionDocToken<T extends JsonObject> = DocToken<T, CommonDocDefinition<T> & {
86
+ readonly scope: "session";
87
+ }>;
88
+ export type ConversationDocToken<T extends JsonObject> = DocToken<T, CommonDocDefinition<T> & (LatestConversationSemantics | RewindableConversationSemantics)>;
89
+ export type RewindableConversationDocToken<T extends JsonObject> = DocToken<T, CommonDocDefinition<T> & RewindableConversationSemantics>;
90
+ export type TaskDocToken<T extends JsonObject> = DocToken<T, CommonDocDefinition<T> & {
91
+ readonly scope: "task";
92
+ }>;
93
+ export type SessionDocFamilyToken<T extends JsonObject, I extends JsonValue> = DocFamilyToken<T, I, DocFamilyDefinition<T, I> & {
94
+ readonly scope: "session";
95
+ }>;
96
+ export type ConversationDocFamilyToken<T extends JsonObject, I extends JsonValue> = DocFamilyToken<T, I, DocFamilyDefinition<T, I> & (LatestConversationSemantics | RewindableConversationSemantics)>;
97
+ export type RewindableConversationDocFamilyToken<T extends JsonObject, I extends JsonValue> = DocFamilyToken<T, I, DocFamilyDefinition<T, I> & RewindableConversationSemantics>;
98
+ export type TaskDocFamilyToken<T extends JsonObject, I extends JsonValue> = DocFamilyToken<T, I, DocFamilyDefinition<T, I> & {
99
+ readonly scope: "task";
100
+ }>;
101
+ /** Live task record reserved by one invocation. */
102
+ export type RunningTask<I, S, R> = TaskRecord<I, S, R> & {
103
+ readonly state: Extract<TaskState<S, R>, {
104
+ readonly status: "running";
105
+ }>;
106
+ };
107
+ /** Next state a task commits for itself: a replacement checkpoint or its terminal outcome. */
108
+ export type NextTaskState<S, R> = Extract<TaskState<S, R>, {
109
+ readonly status: "running" | "terminal";
110
+ }>;
111
+ /**
112
+ * Runs one checkpoint phase. It must commit a changed checkpoint or a terminal outcome through `runtime.commit()`;
113
+ * returning without durable progress faults the task.
114
+ */
115
+ export type PhaseHandler<I, P, S, R, H extends object> = (task: RunningTask<I, P, R>, runtime: TaskRuntime<I, S, R, H>, context: Context) => Promise<void>;
116
+ /**
117
+ * Operations of one task invocation. Every operation rejects after the invocation ends; watches acquired through it
118
+ * stop at invocation end. `_H` is the task's hook map, consumed once the runtime gains its hook runner.
119
+ */
120
+ export interface TaskRuntime<I, S, R, _H extends object> extends DocumentObserver, DocumentReader {
121
+ readonly taskId: TaskId<R>;
122
+ readonly conversationId: ConversationId;
123
+ /** Aborted when the run is signalled by `abortTask()` or the Harness closes. */
124
+ readonly signal: AbortSignal;
125
+ /** Registry snapshot of the current phase; refreshed at every phase boundary. */
126
+ readonly registry: RegistrySnapshot;
127
+ readonly models: Models;
128
+ /**
129
+ * Commit on the Session line after rereading the task. Rejects when the task is terminal, the invocation ended, the
130
+ * Harness is closing, or, in a run invocation, the task carries an abort mark. A returned state replaces the task's
131
+ * state in the same commit; returning nothing leaves it unchanged. `tx.createTask()` defaults to the task's
132
+ * conversation.
133
+ */
134
+ commit(change: (tx: Tx, current: RunningTask<I, S, R>) => NextTaskState<S, R> | undefined | Promise<NextTaskState<S, R> | undefined>, context: Context): Promise<void>;
135
+ /** Read a durable memo of this task. */
136
+ memo<T extends JsonValue>(name: string, context: Context): Promise<T | undefined>;
137
+ /** Store `candidate` unless a memo already exists; return the durable winner. */
138
+ memo<T extends JsonValue>(name: string, candidate: T, context: Context): Promise<T>;
139
+ /** Committed raw active transcript and model context, optionally cut off at the visible entry `at`. */
140
+ context(conversationId: ConversationId, context: Context, at?: EntryId): Promise<ContextView>;
141
+ /** The Harness clock. */
142
+ now(): number;
143
+ /** Forward a non-fatal failure to `HarnessOptions.onReport`. */
144
+ report(error: unknown): void;
145
+ /** Resolve once the Harness clock reaches `until`; rejects when the invocation or `context` is cancelled. */
146
+ sleep(until: number, context: Context): Promise<void>;
147
+ }
148
+ /** Executable durable state machine definition, registered in the registry by `name`. */
149
+ export type TaskDefinition<I, S extends {
150
+ phase: string;
151
+ }, R, H extends object> = {
152
+ /** Registered task kind persisted in `TaskRecord.kind`. */
153
+ readonly name: string;
154
+ /** Definition version persisted with live input and checkpoints. */
155
+ readonly version: number;
156
+ /** First durable checkpoint for a newly created task. */
157
+ initial(input: I): S;
158
+ /** Exhaustive phase map; each handler receives the task narrowed to its phase. */
159
+ readonly phases: {
160
+ readonly [P in S["phase"]]: PhaseHandler<I, Extract<S, {
161
+ phase: P;
162
+ }>, S, R, H>;
163
+ };
164
+ /** Runs in a fresh invocation after an abort mark and must commit a terminal outcome. */
165
+ abort(task: RunningTask<I, S, R>, runtime: TaskRuntime<I, S, R, H>, context: Context): Promise<void>;
166
+ /** Convert a record stored by any older supported version; runs at reservation. */
167
+ migrate?(input: JsonValue, checkpoint: JsonValue, fromVersion: number): {
168
+ input: I;
169
+ checkpoint: S;
170
+ };
171
+ readonly hooks?: H;
172
+ };
173
+ /** Typed executable task definition. */
174
+ export interface Task<I, S extends {
175
+ phase: string;
176
+ }, R, H extends object> {
177
+ readonly definition: TaskDefinition<I, S, R, H>;
178
+ }
179
+ /** Creation options for a durable task. */
180
+ export type TaskOptions = {
181
+ /** Owning conversation; required for Session commits that are not bound to a conversation. */
182
+ readonly conversationId?: ConversationId;
183
+ /** Tasks that must be terminal before ordinary execution may begin. */
184
+ readonly after?: readonly TaskId[];
185
+ /** Excluded from ordinary idle waits and conversation aborts. */
186
+ readonly background?: boolean;
187
+ };
188
+ /** Ownership selected explicitly whenever a conversation is created. */
189
+ export type ConversationOwnership = {
190
+ readonly kind: "ownerless";
191
+ } | {
192
+ readonly kind: "task";
193
+ readonly taskId: TaskId;
194
+ };
14
195
  /** Immutable identity, history ancestry, and task ownership of a transcript scope. */
15
196
  export type ConversationRecord = {
16
- readonly id: Id;
197
+ readonly id: ConversationId;
17
198
  /** Fork source and inclusive parent entry through which history is inherited. */
18
199
  readonly parent?: {
19
- readonly conversationId: Id;
20
- readonly at: Id;
200
+ readonly conversationId: ConversationId;
201
+ readonly at: EntryId;
21
202
  };
22
- /** Creator edge used for authorization, subtree abort, and subtree idle waits. */
203
+ /** Creator edge used for attribution, subtree abort, and subtree idle waits. */
23
204
  readonly owner?: {
24
- readonly conversationId: Id;
25
- readonly taskId: Id;
205
+ readonly conversationId: ConversationId;
206
+ readonly taskId: TaskId;
26
207
  };
27
208
  };
28
209
  /** An immutable override of one visible entry's contribution to model context. */
29
210
  export type ContextEdit = {
30
211
  /** Entry whose model messages are omitted or replaced. */
31
- readonly target: Id;
212
+ readonly target: EntryId;
32
213
  } & ({
33
214
  readonly action: "omit";
34
215
  readonly messages?: never;
@@ -39,8 +220,8 @@ export type ContextEdit = {
39
220
  });
40
221
  /** Immutable transcript event with separate model-facing and application-facing payloads. */
41
222
  export type EntryRecord = {
42
- readonly id: Id;
43
- readonly conversationId: Id;
223
+ readonly id: EntryId;
224
+ readonly conversationId: ConversationId;
44
225
  /** Application-defined entry discriminator. */
45
226
  readonly kind: string;
46
227
  /** Messages contributed to model context; absent for display or bookkeeping entries. */
@@ -48,21 +229,38 @@ export type EntryRecord = {
48
229
  /** JSON payload consumed by views, extensions, or bookkeeping logic. */
49
230
  readonly data?: JsonValue;
50
231
  /** First entry in the active context selected by this entry. */
51
- readonly head?: Id;
232
+ readonly head?: EntryId;
52
233
  /** Context-only overrides of earlier visible entries. */
53
234
  readonly edits?: readonly ContextEdit[];
54
235
  /** Task that appended this entry, when it was produced by durable work. */
55
- readonly byTaskId?: Id;
236
+ readonly byTaskId?: TaskId;
56
237
  };
57
238
  /** Entry content supplied before the Session assigns identity and task attribution. */
58
239
  export type EntryDraft = Omit<EntryRecord, "id" | "conversationId" | "byTaskId" | "head"> & {
59
240
  /** `"self"` starts active context at the newly assigned entry ID. */
60
- readonly head?: Id | "self";
241
+ readonly head?: EntryId | "self";
61
242
  };
243
+ /** Entry whose `data` has type `D`; `never` means the kind carries no data. */
244
+ export type TypedEntry<D extends JsonValue> = Omit<EntryRecord, "data"> & ([D] extends [never] ? {
245
+ readonly data?: never;
246
+ } : {
247
+ readonly data: D;
248
+ });
249
+ /** Entry content of a typed kind; the token supplies `kind`. */
250
+ export type TypedEntryDraft<D extends JsonValue> = Omit<EntryDraft, "kind" | "data"> & ([D] extends [never] ? {
251
+ readonly data?: never;
252
+ } : {
253
+ readonly data: D;
254
+ });
255
+ /** Typed entry kind with a narrowing guard. */
256
+ export interface Entry<D extends JsonValue = never> {
257
+ readonly kind: string;
258
+ is(entry: EntryRecord | undefined): entry is TypedEntry<D>;
259
+ }
62
260
  /** Identity fields shared by every durable submission state. */
63
261
  type SubmissionRecordBase = {
64
- readonly id: Id;
65
- readonly conversationId: Id;
262
+ readonly id: SubmissionId;
263
+ readonly conversationId: ConversationId;
66
264
  /** Host-provided deduplication key, scoped to the conversation. */
67
265
  readonly requestId?: string;
68
266
  };
@@ -77,23 +275,23 @@ export type SubmissionRecord = (SubmissionRecordBase & {
77
275
  readonly reason?: never;
78
276
  readonly detail?: never;
79
277
  } | {
80
- /** Added to the transcript and owned by an active turn. */
278
+ /** Added to the transcript and owned by an active run. */
81
279
  readonly status: "placed";
82
- readonly entry: Id;
280
+ readonly entry: EntryId;
83
281
  readonly answer?: never;
84
282
  readonly reason?: never;
85
283
  readonly detail?: never;
86
284
  } | {
87
285
  /** Successfully answered user input. */
88
286
  readonly status: "done";
89
- readonly entry: Id;
90
- readonly answer: Id;
287
+ readonly entry: EntryId;
288
+ readonly answer: EntryId;
91
289
  readonly reason?: never;
92
290
  readonly detail?: never;
93
291
  } | {
94
292
  /** Terminal input that can no longer receive an answer. */
95
293
  readonly status: "unanswered";
96
- readonly entry?: Id;
294
+ readonly entry?: EntryId;
97
295
  readonly answer?: never;
98
296
  readonly reason: string;
99
297
  readonly detail?: JsonValue;
@@ -109,7 +307,7 @@ export type SubmissionRecord = (SubmissionRecordBase & {
109
307
  } | {
110
308
  /** Successfully appended passive entry. */
111
309
  readonly status: "done";
112
- readonly entry: Id;
310
+ readonly entry: EntryId;
113
311
  readonly answer?: never;
114
312
  readonly reason?: never;
115
313
  readonly detail?: never;
@@ -121,6 +319,15 @@ export type SubmissionRecord = (SubmissionRecordBase & {
121
319
  readonly reason: string;
122
320
  readonly detail?: JsonValue;
123
321
  }));
322
+ /** Terminal status staged for a submission; identity, type, and entry come from its current record. */
323
+ export type SubmissionSettlement = {
324
+ readonly status: "done";
325
+ readonly answer: EntryId;
326
+ } | {
327
+ readonly status: "unanswered";
328
+ readonly reason: string;
329
+ readonly detail?: JsonValue;
330
+ };
124
331
  /** Submission fields supplied before the Session assigns an ID. */
125
332
  export type SubmissionCreate = SubmissionRecord extends infer Record ? Record extends SubmissionRecord ? Omit<Record, "id"> : never : never;
126
333
  /** JSON-safe error snapshot persisted instead of a runtime `Error` object. */
@@ -184,9 +391,9 @@ export type TaskState<S, R> = {
184
391
  readonly outcome: TaskOutcome<R>;
185
392
  };
186
393
  /** Identity, definition, and scheduling fields shared by every task state. */
187
- type TaskRecordBase<I> = {
188
- readonly id: Id;
189
- readonly conversationId: Id;
394
+ type TaskRecordBase<I, R> = {
395
+ readonly id: TaskId<R>;
396
+ readonly conversationId: ConversationId;
190
397
  /** Registered task definition name. */
191
398
  readonly kind: string;
192
399
  /** Definition version used to migrate live input and checkpoints. */
@@ -194,14 +401,14 @@ type TaskRecordBase<I> = {
194
401
  /** Original task input retained while the task is live or terminal. */
195
402
  readonly input: I;
196
403
  /** Tasks that must be terminal before ordinary execution may begin. */
197
- readonly after: readonly Id[];
404
+ readonly after: readonly TaskId[];
198
405
  /** Whether this task is excluded from ordinary idle waits and conversation aborts. */
199
406
  readonly background: boolean;
200
407
  /** Durable abort mark checked before run-mode progress is committed. */
201
408
  readonly abortRequested: boolean;
202
409
  };
203
410
  /** Complete replacement record for one durable task state machine. */
204
- export type TaskRecord<I, S, R> = TaskRecordBase<I> & ({
411
+ export type TaskRecord<I, S, R> = TaskRecordBase<I, R> & ({
205
412
  readonly state: Extract<TaskState<S, R>, {
206
413
  readonly status: "pending" | "running";
207
414
  }>;
@@ -216,7 +423,7 @@ export type TaskRecord<I, S, R> = TaskRecordBase<I> & ({
216
423
  /** Persisted lifecycle record for one create-to-retire document incarnation. */
217
424
  export type DocumentRecord = {
218
425
  /** Unique incarnation ID; never reused when the same logical document is recreated. */
219
- readonly id: Id;
426
+ readonly id: DocumentId;
220
427
  /** Stable document definition kind. */
221
428
  readonly kind: string;
222
429
  /** Family member key; absent for singleton documents. */
@@ -234,7 +441,7 @@ export type DocumentRecord = {
234
441
  } | ({
235
442
  readonly scope: {
236
443
  readonly kind: "conversation";
237
- readonly conversationId: Id;
444
+ readonly conversationId: ConversationId;
238
445
  };
239
446
  } & ({
240
447
  /** Retain only current state. */
@@ -249,7 +456,7 @@ export type DocumentRecord = {
249
456
  })) | {
250
457
  readonly scope: {
251
458
  readonly kind: "task";
252
- readonly taskId: Id;
459
+ readonly taskId: TaskId;
253
460
  };
254
461
  readonly history?: never;
255
462
  readonly fork?: never;
@@ -263,22 +470,32 @@ export type Page<T, C> = {
263
470
  };
264
471
  /** Backend-owned JSON continuation state that callers only round-trip to the same scan. */
265
472
  export type Cursor = Readonly<Record<string, JsonValue>>;
473
+ /** Optional filters for an ordered conversation scan. */
474
+ export type ConversationQuery = {
475
+ readonly ownerConversationId?: ConversationId;
476
+ readonly ownerTaskId?: TaskId;
477
+ };
266
478
  /** Inclusive ID bounds for a newest-first scan of one conversation's fork-aware history. */
267
479
  export type EntryQuery = {
268
- readonly conversationId: Id;
480
+ readonly conversationId: ConversationId;
269
481
  /** Oldest entry ID that may be returned. */
270
- readonly minEntryId?: Id;
482
+ readonly minEntryId?: EntryId;
271
483
  /** Newest entry ID that may be returned. */
272
- readonly maxEntryId?: Id;
484
+ readonly maxEntryId?: EntryId;
273
485
  };
274
486
  /** Optional filters for an ordered scan of durable task records. */
275
487
  export type TaskQuery = {
276
- readonly conversationId?: Id;
488
+ readonly conversationId?: ConversationId;
277
489
  readonly kind?: string;
278
490
  readonly status?: "pending" | "running" | "terminal";
279
491
  readonly abortRequested?: boolean;
280
492
  readonly background?: boolean;
281
493
  };
494
+ /** Optional filters for an ordered scan of submission records. */
495
+ export type SubmissionQuery = {
496
+ readonly conversationId?: ConversationId;
497
+ readonly status?: SubmissionRecord["status"];
498
+ };
282
499
  /** Current state or one historical commit sequence used for document membership and content reads. */
283
500
  export type DocumentPoint = Seq | "current";
284
501
  /** Exact logical identity of a singleton or one keyed family member. */
@@ -304,11 +521,18 @@ export type DocumentContent = {
304
521
  readonly kind: "delta";
305
522
  readonly ops: readonly Op[];
306
523
  };
524
+ /** Exact persisted source selected for a definition-free document copy. */
525
+ export type DocumentCopySource = {
526
+ readonly id: DocumentId;
527
+ readonly at: DocumentPoint;
528
+ };
307
529
  /** Detached materialized value and stored definition version at a selected point. */
308
530
  export type StoredDocument = {
309
531
  readonly record: DocumentRecord;
310
532
  readonly version: number;
311
533
  readonly value: JsonObject;
534
+ /** Deltas replayed after the selected base to materialize `value`. */
535
+ readonly deltasSinceBase: number;
312
536
  };
313
537
  /** One record or document mutation in an atomic storage commit. */
314
538
  export type StorageWrite = {
@@ -329,14 +553,151 @@ export type StorageWrite = {
329
553
  readonly content: Extract<DocumentContent, {
330
554
  readonly kind: "base";
331
555
  }>;
556
+ } | {
557
+ readonly type: "document.copy";
558
+ readonly record: DocumentCreate;
559
+ readonly source: DocumentCopySource;
332
560
  } | {
333
561
  readonly type: "document.change";
334
- readonly id: Id;
562
+ readonly id: DocumentId;
335
563
  readonly content: DocumentContent;
336
564
  } | {
337
565
  readonly type: "document.retire";
338
- readonly id: Id;
566
+ readonly id: DocumentId;
567
+ };
568
+ /** Committed change of one document incarnation. */
569
+ export type DocumentCommitChange = {
570
+ readonly type: "document";
571
+ readonly record: DocumentRecord;
572
+ /** Conversation owning the document; task documents derive it from their task record. Undefined only for Session documents. */
573
+ readonly conversationId: ConversationId | undefined;
574
+ /** Definition version of `value`; absent when this commit retired the incarnation. */
575
+ readonly version: number | undefined;
576
+ /** Exact adopted immutable revision, or `null` when this commit retired the incarnation. */
577
+ readonly value: JsonObject | null;
578
+ /** Exact adopted operations for an ordinary update; empty for creation and retirement. */
579
+ readonly ops: readonly Op[];
580
+ } | {
581
+ /** Definition-free child initialization; consumers hydrate through state or watch acquisition. */
582
+ readonly type: "document.copy";
583
+ readonly record: DocumentRecord;
584
+ readonly conversationId: ConversationId;
585
+ readonly source: DocumentCopySource;
586
+ };
587
+ /** Complete table record committed without another publication copy. */
588
+ export type TableCommitChange = Extract<StorageWrite, {
589
+ readonly type: "conversation" | "entry" | "task" | "submission";
590
+ }>;
591
+ export type CommitChange = TableCommitChange | DocumentCommitChange;
592
+ /** Every immutable change from one successful Session commit. Change order is unspecified. */
593
+ export type CommitPublication = {
594
+ readonly seq: Seq;
595
+ readonly changes: readonly CommitChange[];
339
596
  };
597
+ /**
598
+ * Transaction surface of one Session commit callback.
599
+ * Table reads and creation results are trusted immutable values and may be shared with internal commit state.
600
+ */
601
+ export interface Tx {
602
+ conversation(id: ConversationId): Promise<ConversationRecord | undefined>;
603
+ entry(id: EntryId): Promise<EntryRecord | undefined>;
604
+ /** Undefined when the entry is absent or has another kind. */
605
+ entry<D extends JsonValue>(token: Entry<D>, id: EntryId): Promise<TypedEntry<D> | undefined>;
606
+ task(id: TaskId): Promise<TaskRecord<JsonValue, JsonValue, JsonValue> | undefined>;
607
+ scanConversations(query: ConversationQuery, limit: number, cursor?: Cursor): Promise<Page<ConversationRecord, Cursor>>;
608
+ scanEntries(query: EntryQuery, limit: number, cursor?: Cursor): Promise<Page<EntryRecord, Cursor>>;
609
+ scanTasks(query: TaskQuery, limit: number, cursor?: Cursor): Promise<Page<TaskRecord<JsonValue, JsonValue, JsonValue>, Cursor>>;
610
+ /** Create a conversation with explicitly selected ownership. */
611
+ createConversation(options: {
612
+ readonly ownership: ConversationOwnership;
613
+ }): Promise<ConversationRecord>;
614
+ /** Create a history fork at one concrete visible entry with explicitly selected ownership. */
615
+ forkConversation(parentConversationId: ConversationId, at: EntryId, options: {
616
+ readonly ownership: ConversationOwnership;
617
+ }): Promise<ConversationRecord>;
618
+ /** Returned records are Session-owned immutable values and may be shared with commit listeners. */
619
+ appendEntry(conversationId: ConversationId, value: EntryDraft): Promise<EntryRecord>;
620
+ /** The token supplies `kind` and types `data`. */
621
+ appendEntry<D extends JsonValue>(token: Entry<D>, conversationId: ConversationId, value: TypedEntryDraft<NoInfer<D>>): Promise<TypedEntry<D>>;
622
+ createTask<I, S extends {
623
+ phase: string;
624
+ }, R, H extends object>(task: Task<I, S, R, H>, input: I, options?: TaskOptions): Promise<TaskId<R>>;
625
+ /**
626
+ * Settle a queued or placed submission; only a placed input can be answered, and a settled submission stays
627
+ * unchanged. Resolved against this transaction's latest record of the submission, so it works after table writes.
628
+ * Run tasks settle the inputs they answer.
629
+ */
630
+ settleSubmission(id: SubmissionId, settlement: SubmissionSettlement): void;
631
+ doc<T extends JsonObject>(token: SessionDocToken<T>): Promise<Draft<T>>;
632
+ doc<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId): Promise<Draft<T>>;
633
+ doc<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId): Promise<Draft<T>>;
634
+ doc<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, seed: I): Promise<Draft<T>>;
635
+ doc<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, seed: I): Promise<Draft<T>>;
636
+ doc<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, seed: I): Promise<Draft<T>>;
637
+ retireDoc<T extends JsonObject>(token: SessionDocToken<T>): Promise<void>;
638
+ retireDoc<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId): Promise<void>;
639
+ retireDoc<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId): Promise<void>;
640
+ retireDoc<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string): Promise<void>;
641
+ retireDoc<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string): Promise<void>;
642
+ retireDoc<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string): Promise<void>;
643
+ }
644
+ /** Disposable, read-only Chord state bound to one committed document incarnation. */
645
+ export type DocumentState<T extends JsonObject> = AttachedReplicatedState<Readonly<T> | null>;
646
+ /** Terminal result of one document watch. */
647
+ export type WatchEnd = {
648
+ readonly reason: "stopped" | "cancelled" | "session_closed" | "retired";
649
+ } | {
650
+ readonly reason: "listener_error";
651
+ readonly error: Error;
652
+ };
653
+ /** Serialized exact-frame observation of an immutable value with bounded pending delivery. */
654
+ export interface WatchHandle<T> {
655
+ /** Acquisition revision before start; latest delivered immutable revision afterward. */
656
+ readonly value: T;
657
+ /** Install the sole asynchronous listener. Never invokes it inline. */
658
+ start(listener: (value: T, ops: readonly Op[], context: Context) => Promise<void>): void;
659
+ /** Idempotently stop future callbacks and return this watch's terminal result. */
660
+ stop(): Promise<WatchEnd>;
661
+ /** Settle when the watch terminates; an already-running callback remains caller-owned. */
662
+ readonly closed: Promise<WatchEnd>;
663
+ }
664
+ export type DocumentWatch<T extends JsonObject> = WatchHandle<Readonly<T> | null>;
665
+ /** Committed document reads. */
666
+ export type DocumentReader = Pick<Session, "snapshot" | "snapshotAsOf">;
667
+ /** Non-creating document watch acquisition shared by Session and later invocation APIs. */
668
+ export interface DocumentObserver {
669
+ watchDoc<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<DocumentWatch<T> | undefined>;
670
+ watchDoc<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId, context: Context): Promise<DocumentWatch<T> | undefined>;
671
+ watchDoc<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId, context: Context): Promise<DocumentWatch<T> | undefined>;
672
+ watchDoc<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, context: Context): Promise<DocumentWatch<T> | undefined>;
673
+ watchDoc<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, context: Context): Promise<DocumentWatch<T> | undefined>;
674
+ watchDoc<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, context: Context): Promise<DocumentWatch<T> | undefined>;
675
+ }
676
+ /** Owner of one mutation line, its records, and its tracked documents. */
677
+ export interface Session extends DocumentObserver {
678
+ /** Run one atomic transaction on the Session mutation line. */
679
+ commit<T>(change: (tx: Tx) => T | Promise<T>, context: Context): Promise<T>;
680
+ /** Seal admission, settle admitted commits, then close storage. */
681
+ close(context: Context): Promise<void>;
682
+ /** Observe complete commits synchronously after adoption. The listener must not throw, block, or call Session APIs. */
683
+ subscribeCommits(listener: (publication: CommitPublication, context: Context) => void): () => void;
684
+ /** Observe close synchronously when it begins. The listener must not throw, block, or call Session APIs. */
685
+ subscribeClose(listener: () => void): () => void;
686
+ snapshot<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<Readonly<T> | undefined>;
687
+ snapshot<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId, context: Context): Promise<Readonly<T> | undefined>;
688
+ snapshot<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId, context: Context): Promise<Readonly<T> | undefined>;
689
+ snapshot<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, context: Context): Promise<Readonly<T> | undefined>;
690
+ snapshot<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, context: Context): Promise<Readonly<T> | undefined>;
691
+ snapshot<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, context: Context): Promise<Readonly<T> | undefined>;
692
+ documentState<T extends JsonObject>(token: SessionDocToken<T>, context: Context): Promise<DocumentState<T> | undefined>;
693
+ documentState<T extends JsonObject>(token: ConversationDocToken<T>, conversationId: ConversationId, context: Context): Promise<DocumentState<T> | undefined>;
694
+ documentState<T extends JsonObject>(token: TaskDocToken<T>, taskId: TaskId, context: Context): Promise<DocumentState<T> | undefined>;
695
+ documentState<T extends JsonObject, I extends JsonValue>(token: SessionDocFamilyToken<T, I>, key: string, context: Context): Promise<DocumentState<T> | undefined>;
696
+ documentState<T extends JsonObject, I extends JsonValue>(token: ConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, context: Context): Promise<DocumentState<T> | undefined>;
697
+ documentState<T extends JsonObject, I extends JsonValue>(token: TaskDocFamilyToken<T, I>, taskId: TaskId, key: string, context: Context): Promise<DocumentState<T> | undefined>;
698
+ snapshotAsOf<T extends JsonObject>(token: RewindableConversationDocToken<T>, conversationId: ConversationId, at: EntryId, context: Context): Promise<Readonly<T> | undefined>;
699
+ snapshotAsOf<T extends JsonObject, I extends JsonValue>(token: RewindableConversationDocFamilyToken<T, I>, conversationId: ConversationId, key: string, at: EntryId, context: Context): Promise<Readonly<T> | undefined>;
700
+ }
340
701
  /**
341
702
  * Atomic persistence boundary for Session records.
342
703
  *
@@ -350,14 +711,19 @@ export interface Storage {
350
711
  * Atomically persist one batch and return its sequence. Once resolved, later reads through this storage observe it.
351
712
  */
352
713
  commit(writes: readonly StorageWrite[], context: Context): Promise<Seq>;
353
- /** Return a fresh candidate from the Session-global record ID namespace. */
354
- mintId(): Promise<Id>;
714
+ /** Return a fresh branded candidate from the Session-global numeric ID namespace. */
715
+ mintId<I extends Id<string>>(): Promise<I>;
355
716
  /** Look up one conversation by exact ID. */
356
- conversation(id: Id, context: Context): Promise<ConversationRecord | undefined>;
717
+ conversation(id: ConversationId, context: Context): Promise<ConversationRecord | undefined>;
357
718
  /** Scan conversations in ascending ID order. */
358
- scanConversations(cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<ConversationRecord, Cursor>>;
719
+ scanConversations(query: ConversationQuery, limit: number, cursor: Cursor | undefined, context: Context): Promise<Page<ConversationRecord, Cursor>>;
359
720
  /** Look up one global entry and the sequence of the commit that persisted it. */
360
- entry(id: Id, context: Context): Promise<{
721
+ entry(id: EntryId, context: Context): Promise<{
722
+ readonly entry: EntryRecord;
723
+ readonly commitSeq: Seq;
724
+ } | undefined>;
725
+ /** Look up one entry only when it is visible through the requested conversation's ancestry. */
726
+ entry(conversationId: ConversationId, id: EntryId, context: Context): Promise<{
361
727
  readonly entry: EntryRecord;
362
728
  readonly commitSeq: Seq;
363
729
  } | undefined>;
@@ -365,25 +731,27 @@ export interface Storage {
365
731
  * Return the newest visible entry with a `head` at or below the optional inclusive cutoff.
366
732
  * The returned entry is the marker; its `head` value is the range's actual lower bound.
367
733
  */
368
- findLatestHeadMarker(conversationId: Id, atOrBeforeEntryId: Id | undefined, context: Context): Promise<(EntryRecord & {
369
- readonly head: Id;
734
+ findLatestHeadMarker(conversationId: ConversationId, atOrBeforeEntryId: EntryId | undefined, context: Context): Promise<(EntryRecord & {
735
+ readonly head: EntryId;
370
736
  }) | undefined>;
371
737
  /** Scan the inclusive visible range newest-first, returning at most `limit` entries. */
372
- scanEntries(query: EntryQuery, cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<EntryRecord, Cursor>>;
738
+ scanEntries(query: EntryQuery, limit: number, cursor: Cursor | undefined, context: Context): Promise<Page<EntryRecord, Cursor>>;
373
739
  /** Look up the latest complete record for one task. */
374
- task(id: Id, context: Context): Promise<TaskRecord<JsonValue, JsonValue, JsonValue> | undefined>;
740
+ task(id: TaskId, context: Context): Promise<TaskRecord<JsonValue, JsonValue, JsonValue> | undefined>;
375
741
  /** Scan task records matching every supplied filter. */
376
- scanTasks(query: TaskQuery, cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<TaskRecord<JsonValue, JsonValue, JsonValue>, Cursor>>;
742
+ scanTasks(query: TaskQuery, limit: number, cursor: Cursor | undefined, context: Context): Promise<Page<TaskRecord<JsonValue, JsonValue, JsonValue>, Cursor>>;
377
743
  /** Look up the latest complete record for one admitted submission. */
378
- submission(id: Id, context: Context): Promise<SubmissionRecord | undefined>;
744
+ submission(id: SubmissionId, context: Context): Promise<SubmissionRecord | undefined>;
745
+ /** Scan submissions matching every supplied filter in ascending ID order. */
746
+ scanSubmissions(query: SubmissionQuery, limit: number, cursor: Cursor | undefined, context: Context): Promise<Page<SubmissionRecord, Cursor>>;
379
747
  /** Find a submission by its conversation-scoped host deduplication key. */
380
- submissionByRequest(conversationId: Id, requestId: string, context: Context): Promise<SubmissionRecord | undefined>;
748
+ submissionByRequest(conversationId: ConversationId, requestId: string, context: Context): Promise<SubmissionRecord | undefined>;
381
749
  /** Resolve the incarnation occupying one exact logical address at the selected point. */
382
750
  findDocument(address: DocumentAddress, at: DocumentPoint, context: Context): Promise<DocumentRecord | undefined>;
383
751
  /** Materialize one specific incarnation by ID at the selected point without following a replacement at its address. */
384
- document(id: Id, at: DocumentPoint, context: Context): Promise<StoredDocument | undefined>;
752
+ document(id: DocumentId, at: DocumentPoint, context: Context): Promise<StoredDocument | undefined>;
385
753
  /** Scan incarnations alive in one exact scope at the selected point. */
386
- scanDocuments(query: DocumentQuery, cursor: Cursor | undefined, limit: number, context: Context): Promise<Page<DocumentRecord, Cursor>>;
754
+ scanDocuments(query: DocumentQuery, limit: number, cursor: Cursor | undefined, context: Context): Promise<Page<DocumentRecord, Cursor>>;
387
755
  /** Release backend resources; all later operations must reject. */
388
756
  close(context: Context): Promise<void>;
389
757
  }