js-bao-wss-client 2.2.0-alpha.10 → 2.2.0-alpha.11

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.
package/README.md CHANGED
@@ -3052,7 +3052,7 @@ await client.me.update({
3052
3052
  avatarUrl: null,
3053
3053
  });
3054
3054
 
3055
- // Upload avatar image (stored in R2, proxied through the API)
3055
+ // Upload avatar image (stored by the platform, proxied through the API)
3056
3056
  const imageBlob = await fetch("/path/to/image.png").then((r) => r.blob());
3057
3057
  const { avatarUrl } = await client.me.uploadAvatar(imageBlob, "image/png");
3058
3058
  console.log("New avatar URL:", avatarUrl);
@@ -7,6 +7,7 @@ import { LogLevel } from "./internal/logger";
7
7
  import { type SubscribeOptions } from "./internal/databaseSubscriptions";
8
8
  import { type StorageConfig, type YjsPersistenceFactory } from "./internal/storage/index.js";
9
9
  import { type WorkflowStatusSlice } from "./internal/workflowSlice";
10
+ import { type WorkflowRunError, type WorkflowRunErrorWire } from "./internal/workflowRunError";
10
11
  import { BlobManager } from "./internal/blobManager";
11
12
  import { type AnalyticsEventInput } from "./internal/analyticsQueue";
12
13
  import { type GoogleClientsConfig } from "./internal/authController";
@@ -57,7 +58,7 @@ export type { ReasoningOptions, LlmChatOptions } from "./api/llmApi";
57
58
  export type { AnalyticsEventInput } from "./internal/analyticsQueue";
58
59
  export { ANALYTICS_UNAUTHENTICATED_USER } from "./internal/analyticsQueue";
59
60
  export type { DocumentBlobContext, BlobUploadSourceOptions, BlobUploadResult, BlobListResult, BlobUploadStatus, BlobReadOptions, BlobPrefetchOptions, BlobProxyUrlOptions, BlobDisposition, } from "./internal/blobManager";
60
- export type { DocumentsAPI, DocumentContext, DocumentAliasesAPI } from "./api/documentsApi";
61
+ export type { DocumentsAPI, DocumentContext, DocumentAliasesAPI, DocumentIngestsAPI, DocumentSnapshotsAPI, } from "./api/documentsApi";
61
62
  export type { DatabasesAPI } from "./api/databasesApi";
62
63
  export type { CollectionsAPI } from "./api/collectionsApi";
63
64
  export type { GeminiAPI } from "./api/geminiApi";
@@ -74,7 +75,7 @@ export type { CollectionTypeConfigsAPI } from "./api/collectionTypeConfigsApi";
74
75
  export type { DatabaseTypeConfigsAPI } from "./api/databaseTypeConfigsApi";
75
76
  export type { CronTriggersAPI } from "./api/cronTriggersApi";
76
77
  export type { CronTriggerInfo, CreateCronTriggerParams, UpdateCronTriggerParams, CronTriggerListResult, ObjectStatus, } from "./api/cronTriggersApi";
77
- export type { CreateDocumentOptions, CreateOfflineOptions, CreateWithAliasOptions, GetOrCreateWithAliasOptions, DeleteDocumentOptions, DocumentAccessRequest, DocumentAccessRequestResponse, DocumentListOptions, DocumentListPage, EvictAllDocumentsOptions, EvictDocumentOptions, GrantGroupPermissionParams, ResolveAliasParams, SetAliasParams, UpdateDocumentData, } from "./api/documentsApi";
78
+ export type { CreateDocumentOptions, CreateOfflineOptions, CreateWithAliasOptions, GetOrCreateWithAliasOptions, DeleteDocumentOptions, DocumentAccessRequest, DocumentAccessRequestResponse, DocumentListOptions, DocumentListPage, EvictAllDocumentsOptions, EvictDocumentOptions, GrantGroupPermissionParams, ResolveAliasParams, SetAliasParams, UpdateDocumentData, DocumentIngestSession, DocumentIngestChunkUpload, DocumentIngestChunkUploadResult, DocumentIngestPage, DocumentSnapshotBuild, DocumentSnapshotPage, } from "./api/documentsApi";
78
79
  export type { CreateDatabaseParams, UpdateDatabaseParams } from "./api/databasesApi";
79
80
  export type { CreateCollectionParams, UpdateCollectionParams, GrantCollectionGroupPermissionParams, ListCollectionsOptions, } from "./api/collectionsApi";
80
81
  export type { ListResult } from "./api/listResult";
@@ -94,7 +95,7 @@ export type { DocumentDebugSnapshot, DocumentPermission, LocalDocumentEntry, Loc
94
95
  export type { LogLevel } from "./internal/logger";
95
96
  export type { RequestOptions } from "./internal/httpClient";
96
97
  export type { LocksAPI } from "./api/locksApi";
97
- export type { FunctionsAPI, FunctionInvokeOptions, FunctionInvokeResult, FunctionInvokeStatus, FunctionInvokeLimits, FunctionStartOptions, FunctionStartResult, FunctionRunRef, FunctionWaitForResult, } from "./api/functionsApi";
98
+ export type { FunctionsAPI, FunctionInvokeOptions, FunctionInvokeResult, FunctionInvokeStatus, FunctionInvokeLimits, FunctionStartOptions, FunctionStartResult, FunctionRunRef, FunctionWaitForResult, FunctionRun, FunctionRunError, FunctionRunErrorCode, FunctionRunSettled, FunctionRunSlice, FunctionRunStatus, FunctionRunStatusValue, FunctionRunTerminalStatus, FunctionWaitOptions, } from "./api/functionsApi";
98
99
  export type { LockHandle, LockContention, AcquireResponse, AcquireOptions, BlockingAcquireOptions, ReleaseResult, RenewResult, LockStatus, LockListEntry, LockListResult, } from "./api/locksApi";
99
100
  export type { ResourceMetadataAPI } from "./api/resourceMetadataApi";
100
101
  export type { ResourceMetadataReadResult, ResourceMetadataWriteResult, ResourceMetadataBatchRequestItem, ResourceMetadataBatchParams, ResourceMetadataBatchCategoryResult, ResourceMetadataBatchResourceResult, ResourceMetadataBatchResult, ResourceMetadataListEntry, ResourceMetadataListResult, ResourceMetadataDeleteResult, ResourceMetadataResolveParams, ResourceMetadataResolveResult, } from "./api/resourceMetadataApi";
@@ -425,10 +426,14 @@ export interface JsBaoClientOptions {
425
426
  /**
426
427
  * The local query engine. Default `{ type: "sqljs" }`, in memory. A web app
427
428
  * that opens large documents passes `{ type: "opfs", options: { workerURL?,
428
- * locateFile? } }`: format-1 documents keep the SQL.js mirror and each large
429
- * document gets a worker-hosted store that survives a reload. Needs js-bao
430
- * 0.7.0 or newer; with an older js-bao the client throws
431
- * `OPFS_ENGINE_UNAVAILABLE`.
429
+ * brokerURL?, locateFile? } }`: format-1 documents keep the SQL.js mirror
430
+ * and each large document gets a worker-hosted store that survives a
431
+ * reload. `brokerURL` points at a small SharedWorker (`js-bao/format2-broker`)
432
+ * that lets several tabs of the same app share one document's store — one
433
+ * tab hosts the engine, the others reach it through a port the broker hands
434
+ * over; without it, a second tab opening the same large document is
435
+ * refused. Needs js-bao 0.7.0 or newer (0.8.0 for `brokerURL`); with an
436
+ * older js-bao the client throws `OPFS_ENGINE_UNAVAILABLE`.
432
437
  */
433
438
  databaseConfig?: DatabaseConfig;
434
439
  /**
@@ -518,9 +523,8 @@ export interface SyncEvent {
518
523
  * It also fires with `state: "error"` when an open document cannot be kept
519
524
  * in sync:
520
525
  *
521
- * - a remote update for it arrives but cannot be applied — when downloading
522
- * a large update from R2 is rejected (401/403), which leaves the document
523
- * behind the server;
526
+ * - a remote update for it arrives but cannot be fetched or applied, which
527
+ * leaves the document behind the server;
524
528
  * - its sync handshake goes unanswered for the whole handshake budget
525
529
  * (`sync.handshakeTimeoutMs`, default 10s), so what the app is rendering
526
530
  * has stopped converging. The client keeps retrying underneath, at a
@@ -1370,7 +1374,20 @@ export type WorkflowStatusValue = "queued" | "running" | "apply_pending" | "appl
1370
1374
  export interface WorkflowStatusResult<O = any> {
1371
1375
  status: WorkflowStatusValue;
1372
1376
  output?: O;
1373
- error?: string;
1377
+ /**
1378
+ * Why the run failed, exactly as the server sent it.
1379
+ *
1380
+ * An OBJECT for every failed durable run, `null` on a read that has not
1381
+ * failed, and a string on the older form. Branch on {@link failure}
1382
+ * instead — it says the same thing whichever form arrived.
1383
+ */
1384
+ error?: WorkflowRunErrorWire | null;
1385
+ /**
1386
+ * The same error, normalized: `message` always, `name` when the wire carried
1387
+ * one, and any remaining keys under `details`. Additive, and `undefined`
1388
+ * when the run did not fail or the field was not one the client could read.
1389
+ */
1390
+ failure?: WorkflowRunError;
1374
1391
  /** Why the run did not run, when `status === "skipped"`. */
1375
1392
  skipReason?: WorkflowRunSkipReason;
1376
1393
  run?: WorkflowRun;
@@ -1384,6 +1401,7 @@ export interface WorkflowStatusResult<O = any> {
1384
1401
  slice?: WorkflowStatusSlice;
1385
1402
  }
1386
1403
  export type { WorkflowStatusSlice };
1404
+ export type { WorkflowRunError, WorkflowRunErrorWire };
1387
1405
  /** Options for claiming a workflow apply */
1388
1406
  export interface ClaimApplyOptions {
1389
1407
  workflowKey: string;
@@ -1513,8 +1531,17 @@ export interface WaitForWorkflowResult {
1513
1531
  status: WaitForWorkflowStatus;
1514
1532
  /** Final output of the run, when available. */
1515
1533
  output?: any;
1516
- /** Error message when `status === "failed"`. */
1517
- error?: string;
1534
+ /**
1535
+ * Why the run failed, exactly as it arrived — an object from a status read,
1536
+ * a string from the terminal `workflowStatus` frame.
1537
+ */
1538
+ error?: WorkflowRunErrorWire | null;
1539
+ /**
1540
+ * The same error, normalized. Present on a `failed` result whichever path
1541
+ * settled the wait, so a caller reporting a failure does not have to know
1542
+ * which one did.
1543
+ */
1544
+ failure?: WorkflowRunError;
1518
1545
  /** Why the run did not run, when `status === "skipped"`. */
1519
1546
  skipReason?: WorkflowRunSkipReason;
1520
1547
  }
@@ -1588,6 +1615,19 @@ export interface EvictAllLocalOptions {
1588
1615
  export interface DocumentSnapshotLoadEvent {
1589
1616
  documentId: string;
1590
1617
  phase: "started" | "progress" | "model" | "loaded";
1618
+ /**
1619
+ * What this load IS.
1620
+ *
1621
+ * `"load"` installs a base whole — a cold start, or a rebuild. `"converge"`
1622
+ * replaces only the ranges a bulk load touched and keeps the rest, which is
1623
+ * why it also reports {@link chunksReused}.
1624
+ */
1625
+ mode?: "load" | "converge";
1626
+ /**
1627
+ * Chunks a convergence kept rather than fetched, on the `loaded` phase of a
1628
+ * `"converge"` load. The saving the whole design exists for.
1629
+ */
1630
+ chunksReused?: number;
1591
1631
  /** The epoch the snapshot is a base for. */
1592
1632
  epoch: number;
1593
1633
  rows: number;
@@ -1892,6 +1932,25 @@ export declare class JsBaoClient extends Observable<any> {
1892
1932
  private jsBaoWhenFormat2ProjectionSettled;
1893
1933
  private jsBaoFormat2NoteClockOffset;
1894
1934
  private jsBaoFormat2ForgetPendingOps;
1935
+ /**
1936
+ * #3435, behavior 18 — record durably that this document crossed a bulk
1937
+ * load's discontinuity. A client that followed the flagged seal and then
1938
+ * restarted reads its epoch mark as current, so the convergence it owes has
1939
+ * to be written somewhere that outlives the process.
1940
+ */
1941
+ private jsBaoFormat2NoteDiscontinuity;
1942
+ /** #3435 — the convergence landed: forget what it reconciled. */
1943
+ private jsBaoFormat2ClearDiscontinuities;
1944
+ /**
1945
+ * #3435 — the models this client holds rows of, which is the inventory a
1946
+ * convergence plan decides its whole-model prunes against.
1947
+ */
1948
+ private jsBaoFormat2LocalModels;
1949
+ /**
1950
+ * #3435, behavior 21 — whether each of these records is in the merged view
1951
+ * once a convergence has landed. The fact an owed write is judged against.
1952
+ */
1953
+ private jsBaoFormat2RecordPresence;
1895
1954
  /**
1896
1955
  * #2816, behavior 17 — rewrite the pending ops a replay resolution narrowed.
1897
1956
  * A write that survived only in part must be recorded as the surviving part,
@@ -1971,8 +2030,71 @@ export declare class JsBaoClient extends Observable<any> {
1971
2030
  * goes down with that document (#2816, behavior 10).
1972
2031
  */
1973
2032
  private jsBaoFormat2HoldWrites;
2033
+ /**
2034
+ * Documents whose writes this client is already holding.
2035
+ *
2036
+ * The ORM's hold is a barrier, not a lock a holder may take twice: it waits
2037
+ * for the transition in flight before raising its own, so a hold taken
2038
+ * INSIDE one waits for itself. That is reachable since #3435 — a convergence
2039
+ * holds writes for its whole run and completes the deferred replay within
2040
+ * it, and that replay's own move takes the hold again — so the client tracks
2041
+ * what it is holding and re-enters rather than deadlocking. Re-entering is
2042
+ * the correct answer as well as the safe one: writes are already held.
2043
+ */
2044
+ private readonly format2HeldWrites;
1974
2045
  /** Documents currently moving to a new epoch, so a repeat notice waits. */
1975
2046
  private readonly format2Rotations;
2047
+ /**
2048
+ * Bulk-load epochs each document crossed and has not converged past (#3435),
2049
+ * ascending — the in-memory face of the store's `_discontinuities` table.
2050
+ *
2051
+ * Kept here as well as durably because the decisions that read it run on
2052
+ * frames: a seal, a `snapshot.ready` and a handshake all ask "does this
2053
+ * document owe a convergence?" and none of them may wait on a store that may
2054
+ * not be bound yet.
2055
+ */
2056
+ private readonly format2Discontinuities;
2057
+ /**
2058
+ * The replay a flagged seal deferred, per document (#3435, behavior 18).
2059
+ *
2060
+ * Unlike #2816's held replay this carries NO timer. The ordinary hold
2061
+ * replays what it owes when the sync it waits for never lands, which is the
2062
+ * right fallback for a rotation; here it would publish exactly the writes
2063
+ * the classification exists to drop. It waits for the convergence, however
2064
+ * long that takes, and the writes stay durable in `_pending_ops` meanwhile.
2065
+ */
2066
+ private readonly format2ConvergenceReplays;
2067
+ /**
2068
+ * What a landed convergence found for the owed records (#3435,
2069
+ * behavior 21), set only while the deferred replay is running.
2070
+ *
2071
+ * The replay resolves through `resolveReplay`, which `followEpoch` calls at
2072
+ * completion time rather than at the seal — so this is where the answer the
2073
+ * classification needs, which did not exist when the move was made, is put
2074
+ * within its reach.
2075
+ */
2076
+ private readonly format2IngestReplays;
2077
+ /**
2078
+ * The sequences one convergence's replay has already judged (#3435,
2079
+ * finding 3435-SO-05), held only while it runs.
2080
+ *
2081
+ * Every rotation crossed before the convergence deferred its own copy of
2082
+ * what was owed at the time, and they are replayed in order. The same write
2083
+ * therefore arrives more than once, already settled: it must not be carried
2084
+ * twice, and the application must not hear about it twice.
2085
+ */
2086
+ private readonly format2JudgedReplays;
2087
+ /**
2088
+ * The bulk-load boundary a landed convergence reconciled, and the ranges it
2089
+ * knows the artifact touched (#3435, finding FROZEN-02).
2090
+ *
2091
+ * Kept so the presence question can be asked AGAIN, as late as possible. A
2092
+ * returning client converges on the base, then folds the chain above it,
2093
+ * then moves — and a record the artifact deleted may have been re-created in
2094
+ * one of those archives. An answer taken off the base alone would call it
2095
+ * absent and drop a write that still stands.
2096
+ */
2097
+ private readonly format2ConvergedBoundaries;
1976
2098
  /**
1977
2099
  * The freshest artifact grants each large document has been given (#2816).
1978
2100
  *
@@ -2001,6 +2123,23 @@ export declare class JsBaoClient extends Observable<any> {
2001
2123
  * sent. See `format2RequireReload`.
2002
2124
  */
2003
2125
  private readonly format2StaleEpochs;
2126
+ /**
2127
+ * Large documents whose handshake on THIS connection has not been answered.
2128
+ *
2129
+ * #3435, finding 3435-R05's third door. `sendSyncStep1` flushes a
2130
+ * document's queued local updates before it sends the handshake frame, and
2131
+ * `epoch.info` is where a returning client finds out that a bulk load stands
2132
+ * between what it holds and the room. So a large document that has just sent
2133
+ * its handshake holds those writes: publishing them first would put an owed
2134
+ * write onto the post-ingest epoch before anything could classify it, and
2135
+ * the presence read that classifies it would then be reading this client's
2136
+ * own replay instead of the bulk load's result.
2137
+ *
2138
+ * They are HELD, not dropped — queued in memory and durable in
2139
+ * `_pending_ops`, exactly as the stale-epoch hold beside it leaves them —
2140
+ * and released once the handshake has been answered.
2141
+ */
2142
+ private readonly format2AwaitingHandshake;
2004
2143
  /** Outbound sequences per large document: queued, sent, acknowledged. */
2005
2144
  private readonly format2Ack;
2006
2145
  private jsBaoAddDocumentModelMapping;
@@ -2895,6 +3034,18 @@ export declare class JsBaoClient extends Observable<any> {
2895
3034
  * resynced: see `format2RequireReload`.
2896
3035
  */
2897
3036
  private followEpochSeal;
3037
+ /**
3038
+ * Run `work` in this document's one queue of epoch moves, catch-ups and
3039
+ * convergences (#3435, finding FROZEN-04).
3040
+ *
3041
+ * The queue is what keeps a convergence from replacing rows while a move
3042
+ * rebinds the overlay under it. Reading the promise in flight and only THEN
3043
+ * installing one's own is not a queue: two callers waiting on the same
3044
+ * predecessor both see it settle and both go, and the second overwrites the
3045
+ * first's entry so nothing after them waits for it either. The link is made
3046
+ * here, synchronously, before anything is awaited.
3047
+ */
3048
+ private format2Serialize;
2898
3049
  /**
2899
3050
  * The epoch a large document is on (#2816, behavior 10).
2900
3051
  *
@@ -2967,6 +3118,39 @@ export declare class JsBaoClient extends Observable<any> {
2967
3118
  * has been rebuilt — so the jump is no longer a jump over anything unknown.
2968
3119
  */
2969
3120
  private format2MoveOnto;
3121
+ /**
3122
+ * Record a bulk load's discontinuity, in memory and durably (#3435,
3123
+ * behavior 18).
3124
+ *
3125
+ * Both, because the two answer different questions. The durable row is what
3126
+ * a restarted client reads at its bind; the in-memory list is what the very
3127
+ * next frame on THIS connection reads, before any store has been bound.
3128
+ */
3129
+ private format2NoteDiscontinuity;
3130
+ /**
3131
+ * Run `run` with this document's local writes held back, once.
3132
+ *
3133
+ * The ORM's hold drains what is in flight and then raises a barrier the next
3134
+ * hold waits on, so taking it from inside itself waits forever. Every hold
3135
+ * this client takes goes through here, and one taken while this client is
3136
+ * already holding the same document simply runs: the writes it exists to
3137
+ * exclude are excluded already, by the hold above it.
3138
+ */
3139
+ private format2WithWriteHold;
3140
+ /**
3141
+ * Keep the sequences a deferred carry withheld off every claim (#3435,
3142
+ * finding 3435-SO-06).
3143
+ *
3144
+ * The lowest of them is the floor: the server's acknowledgement mark is
3145
+ * contiguous, so nothing above a withheld sequence can be acknowledged
3146
+ * anyway, and a frame claiming it would only invite the prune this exists to
3147
+ * prevent.
3148
+ */
3149
+ private format2WithholdSequences;
3150
+ /** The withheld writes have been replayed: their sequences may travel. */
3151
+ private format2ReleaseWithheldSequences;
3152
+ /** The highest bulk-load epoch this document has not converged past (#3435). */
3153
+ private format2HighestDiscontinuity;
2970
3154
  /**
2971
3155
  * Hold a returning client's replay until the epoch it joined has synced
2972
3156
  * (#2816, behavior 17).
@@ -3058,6 +3242,114 @@ export declare class JsBaoClient extends Observable<any> {
3058
3242
  * merged view (#2816, behavior 15).
3059
3243
  */
3060
3244
  private format2LoadSnapshot;
3245
+ /**
3246
+ * Run a convergence in the same queue as this document's epoch moves and
3247
+ * catch-ups (#3435, behavior 20).
3248
+ *
3249
+ * A convergence swaps whole ranges of the merged view; a seal arriving
3250
+ * halfway through would rebind the overlay underneath it, and a catch-up
3251
+ * would fold archives into rows that are being replaced. One at a time,
3252
+ * exactly as #2816 serializes the rest.
3253
+ */
3254
+ private format2ScheduleConvergence;
3255
+ /**
3256
+ * Make this document's merged view the ingested table plus every write since
3257
+ * (#3435, behavior 19).
3258
+ *
3259
+ * The order is the behavior:
3260
+ *
3261
+ * 1. the manifest, validated before a chunk moves — a malformed `ingest`
3262
+ * block leaves the document held rather than half-replaced (edge E5);
3263
+ * 2. the plan, partial only where keeping rows is provably sound;
3264
+ * 3. the load, replacing each fetched chunk's coverage;
3265
+ * 4. the overlays SEALED between the base's epoch and this client's, which
3266
+ * the replacement just wrote over (finding 3435-R03);
3267
+ * 5. the open epoch's overlay, refolded over the rows that moved;
3268
+ * 6. the pending writes, classified against what is now present, and only
3269
+ * then published (finding 3435-R05);
3270
+ * 7. the discontinuities, forgotten — this view has converged past them.
3271
+ */
3272
+ private format2Converge;
3273
+ /**
3274
+ * The artifact ranges a PARTIAL convergence may plan against, or `null` for
3275
+ * the full plan (#3435, behavior 19, findings 3435-R04 and R07).
3276
+ *
3277
+ * Four conditions, and the reason any of them failed is logged rather than
3278
+ * left to be inferred from a chunk count:
3279
+ *
3280
+ * - the local base FINISHED loading, so the rows a kept chunk vouches for
3281
+ * are a complete baseline rather than however far a load got;
3282
+ * - exactly one bulk load was crossed, since only the latest one's ranges
3283
+ * are in this manifest and nothing names what an earlier one touched;
3284
+ * - the base is that bulk load's OWN build, which its `ingest.epoch` says;
3285
+ * - the chain is applied through E — this client followed the flagged seal,
3286
+ * so its rows are the pre-ingest table plus every overlay up to the swap.
3287
+ */
3288
+ private format2ConvergencePlanInput;
3289
+ /**
3290
+ * Fold the overlays sealed from `from` through `to` back over the ranges a
3291
+ * convergence replaced (#3435, finding 3435-R03).
3292
+ *
3293
+ * A connected client already holds these writes — it was there when they
3294
+ * were made — but the base it just installed is a torn read cut before some
3295
+ * of them, so the replaced ranges lost them. The archives are the only copy,
3296
+ * and the grants for them are asked for exactly as a returning client's are.
3297
+ */
3298
+ private format2RefoldSealedSince;
3299
+ /** Forget the discontinuities a landed convergence reconciled (#3435). */
3300
+ private format2ClearDiscontinuities;
3301
+ /**
3302
+ * Judge the writes a flagged seal held, now that the ingested ranges are in
3303
+ * (#3435, behavior 21, finding 3435-R05).
3304
+ *
3305
+ * Presence is read HERE, between the refolds and the replay: before the
3306
+ * refolds it would be a statement about a half-replaced view, and after the
3307
+ * replay it would be the client reading back its own writes.
3308
+ *
3309
+ * `touched` decides how far the question reaches. With the artifact's own
3310
+ * ranges in hand only the owed records inside one can have raced the bulk
3311
+ * load, so only those are asked about and everything else follows the
3312
+ * ordinary recency rules. Without them — the full plan, or more than one
3313
+ * boundary crossed — nothing names what moved, so every owed write is asked
3314
+ * about and classified by presence alone (finding 3435-R07).
3315
+ */
3316
+ private format2SettleConvergenceReplay;
3317
+ /**
3318
+ * The owed writes a RESTART left for the convergence to judge (#3435,
3319
+ * finding FROZEN-01).
3320
+ *
3321
+ * The same test the bind made when it kept them off the overlay: this
3322
+ * document's own epoch is already above the bulk load's discontinuity, so
3323
+ * this client followed the flagged seal itself and its unacknowledged
3324
+ * writes were made against the table the load replaced. A client still on a
3325
+ * pre-load epoch is not in this case — its writes are on the overlay it is
3326
+ * bound to and are carried, and judged, by the move it makes next.
3327
+ */
3328
+ private format2RestoredOwed;
3329
+ /**
3330
+ * What a landed convergence found for the records this document still owes
3331
+ * writes on (#3435, behavior 21).
3332
+ *
3333
+ * `touched` decides how far the question reaches. With the artifact's own
3334
+ * ranges in hand only the owed records inside one can have raced the bulk
3335
+ * load, so only those are asked about and everything else follows the
3336
+ * ordinary recency rules. Without them — the full plan, or more than one
3337
+ * boundary crossed — nothing names what moved, so every owed write is asked
3338
+ * about and classified by presence alone (finding 3435-R07).
3339
+ */
3340
+ private format2IngestReplayInput;
3341
+ /**
3342
+ * Ask the presence question again, of the document as it stands now (#3435,
3343
+ * finding FROZEN-02).
3344
+ *
3345
+ * A convergence answers it off the base it has just installed, which is the
3346
+ * earliest moment it can be answered and not the truest one: the chain above
3347
+ * that base is applied afterwards, and a record the artifact deleted can have
3348
+ * been re-created in one of those archives. Re-read immediately before the
3349
+ * replay that uses it, the answer is about the document this client is
3350
+ * actually joining. A no-op where no convergence has landed.
3351
+ */
3352
+ private format2RefreshIngestReplayInput;
3061
3353
  /**
3062
3354
  * Read a snapshot build through the ONE grant the handshake minted for it.
3063
3355
  *
@@ -3185,6 +3477,24 @@ export declare class JsBaoClient extends Observable<any> {
3185
3477
  * nothing of its local state may go out (see `format2RequireReload`).
3186
3478
  */
3187
3479
  private format2NeedsReload;
3480
+ /**
3481
+ * Hold every open large document's queued writes until its own handshake on
3482
+ * this connection has been answered (#3435).
3483
+ *
3484
+ * Every document that could have a queue is covered, not only the ones that
3485
+ * have one now: a write made between the socket opening and the handshake
3486
+ * being answered would otherwise go out on the debounce timer.
3487
+ */
3488
+ private format2HoldWritesUntilHandshake;
3489
+ /**
3490
+ * Let a large document's queued writes go, now that its handshake has been
3491
+ * answered (#3435).
3492
+ *
3493
+ * A document that still owes a catch-up or a convergence is held again the
3494
+ * moment the flush looks, by `format2NeedsReload` — this only lifts the
3495
+ * hold that was about not knowing what the room had to say.
3496
+ */
3497
+ private format2ReleaseHandshakeHold;
3188
3498
  /**
3189
3499
  * Run the catch-up a document owes, now that its merged view exists
3190
3500
  * (#2816, behavior 12).
@@ -3196,6 +3506,62 @@ export declare class JsBaoClient extends Observable<any> {
3196
3506
  * told to reload.
3197
3507
  */
3198
3508
  private format2SettleOwedCatchUp;
3509
+ /**
3510
+ * Take the bulk loads the STORE remembers, at the bind (#3435, behavior 24,
3511
+ * finding 3435-SO-04).
3512
+ *
3513
+ * `_discontinuities` outlives the process; the in-memory list does not, and
3514
+ * the handshake cannot fill it in for a client that followed the flagged
3515
+ * seal itself — that client's epoch mark is the room's own, so the chain's
3516
+ * flagged entry is one it reads as already behind it. Without this, a
3517
+ * restart between the seal and the announcement leaves a document serving
3518
+ * pre-bulk-load rows under a mark that says it is current, for good.
3519
+ *
3520
+ * Raising the debt is what keeps the document silent until it converges; the
3521
+ * entry is the last handshake's, so the chain and the base it names are the
3522
+ * ones the convergence needs.
3523
+ */
3524
+ private format2AdoptDurableDiscontinuities;
3525
+ /**
3526
+ * Record every bulk load that stands between what this client holds and the
3527
+ * room (#3435, behaviors 22 and 23).
3528
+ *
3529
+ * Two sources, neither of which covers the other:
3530
+ *
3531
+ * - the store's own `_discontinuities`, which is all a client that followed
3532
+ * a flagged seal and then restarted has left — its epoch mark reads as the
3533
+ * room's current one, so nothing about the handshake says it is behind;
3534
+ * - the handshake's chain, which is how a client that was AWAY when the swap
3535
+ * happened finds out about it at all.
3536
+ *
3537
+ * A flagged epoch this client is already PAST is not recorded: it converged
3538
+ * on that bulk load's base and cleared its own record of it, and the chain
3539
+ * goes on reporting the epoch as flagged for ever.
3540
+ */
3541
+ private format2NoteHandshakeDiscontinuities;
3542
+ /**
3543
+ * Adopt the epoch of the base a convergence just installed (#3435,
3544
+ * finding 3435-SO-03).
3545
+ *
3546
+ * The same statement a cold start's `join` makes, at the one other place a
3547
+ * document's rows become a whole base it never held: durably, because a mark
3548
+ * written only in memory leaves a client that has just streamed a base
3549
+ * presenting as fresh again on its next handshake, and in the transport's
3550
+ * ledger, because the chain and the move that follow read the epoch from
3551
+ * there.
3552
+ */
3553
+ private format2AdoptConvergedEpoch;
3554
+ /**
3555
+ * Bring a document that owes a convergence up to date, or hold it (#3435,
3556
+ * behaviors 22 and 23).
3557
+ *
3558
+ * Returns `true` when the merged view has converged and the caller may go on
3559
+ * to the ordinary chain and move; `false` when the document is HELD — the
3560
+ * base it needs does not exist yet, so it keeps serving reads and waits for
3561
+ * the announcement, which is the intent's rule and the opposite of what
3562
+ * #2816 did here.
3563
+ */
3564
+ private format2ConvergeOwed;
3199
3565
  /**
3200
3566
  * Claim sequences that appeared AFTER the handshake had already run (#3431).
3201
3567
  *