@thomasfosterau/legation 0.0.0 → 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MemoryBackend-DxP8t4ge.js","names":["make","FilterPolicy.withKeyDefaults","registry","compare","evaluate","empty","Predicate.compareLiterals","Predicate.compareText","Predicate.isNullish","Predicate.fieldValue","Predicate.holds","plan","Predicate.always","Predicate.and","Predicate.test","Predicate.PredicateSchema","make","Predicate.always","Predicate.eq","Predicate.ne","Predicate.gt","Predicate.gte","Predicate.lt","Predicate.lte","Predicate.isIn","Predicate.notIn","Predicate.isNull","Predicate.isNotNull","Predicate.and","Predicate.or","Predicate.not","fieldOf","Predicate.fieldValue","Predicate.isNullish","Predicate.compareLiterals","Predicate.compareText","Predicate.test","Index.evaluate","Predicate.fieldValue","Collection.relationshipsOf","Subset.make","Predicate.isIn","Predicate.eq","Subset.hash","observe","Predicate.resolveExists","Predicate.existsValues","make","Subset.parseOrder","Predicate.always","Predicate.eq","Predicate.and","Subset.make","Related.query","Related.queryRows","Related.queryVia","observe","Related.observe","registry","count","Predicate.fieldValue","Predicate.test","make","rowKey","Identity.keySegment","Identity.transitionOf","canonical","Predicate.compareText","OrderedTree.findBy","Subset.comparator","OrderedTree.rankOf","OrderedTree.size","OrderedTree.slice","FractionalIndex.compare","FractionalIndex.generateNBetween","make","Subset.sortFiltered","OrderedTree.fromSorted","Subset.sortFilteredIndexed","Predicate.test","OrderedTree.remove","OrderedTree.insert","diff","isWindowed","DEFAULT_CHANGE_HUB_CAPACITY","make","MutationState.seed","MutationState.hasUntracked","MutationState.adopt","Identity.keySegment","Telemetry.syncFailuresTotal","Telemetry.journalDepth","Telemetry.rebaseDurationMs","Index.empty","Subset.applyIndexed","MutationState.acknowledgedMany","MutationState.phaseOf","MutationState.rejected","MutationState.compacted","reset","Identity.transitionOf","Telemetry.mutationsPushedTotal","Telemetry.pushesTotal","Telemetry.pushMutations","Telemetry.pullsTotal","Telemetry.pullPatchOps","Subset.hash","seed","hash","Hash.canonicalJson","LiveView.put","LiveView.del","LiveView.result","LiveView.makeIndexed","Telemetry.changeCollapsesTotal","RowChange.reset","RowChange.diff","RowChange.enters","retarget","LiveView.retarget","Aggregate.compute","Aggregate.computeGrouped","Aggregate.applyPut","Aggregate.applyDel","Aggregate.applyGroupedPut","Aggregate.applyGroupedDel","Aggregate.observe","Aggregate.initState","Subset.apply","Aggregate.stateValue","Aggregate.sameValue","Aggregate.observeGrouped","Aggregate.initGroupedState","Aggregate.groupedStateValue","Aggregate.sameGroupedValue","MutationState.journaled","layer","asTransportError","make","layer","Transport.withFallback","Hash.contentHash","Subset.hash","Subset.Subset","Query.edgeSelects","Subset.hash","Related.windowsFor","Query.plan","Coverage.NOT_PULLED","Coverage.covers","make","hash","Subset.hash","Subset.hash","make","Subscriptions.counted","PullMarks.make","Subset.hash","Related.related","MirrorProtocol.relatedKey","Related.trackEdges","layer","MirrorProtocol.FORM_MUTATION_MUTATOR","make","MirrorProtocol.decodeHostMessage","MirrorProtocol.MUTATION_STATES_KEY","Subset.hash","Telemetry.mirrorRefreshesTotal","RowChange.enters","RowChange.reset","RowChange.diff","Related.edgeSelect","MirrorProtocol.relatedKey","MirrorProtocol.namedKey","Coverage.NOT_PULLED","Collection.filterDeclarationOf","FilterPolicy.bare","FilterPolicy.check","Predicates.isIn","Predicates.and","Predicates.setNames","Predicates.bindSets","make","UnknownMutator.make","RejectionMemory.floorsOf","Telemetry.hintsDroppedTotal","Hash.canonicalJson","Hash.contentHash","Predicate.test","Predicate.hasExists","Cvr.CvrStore","Query.QueryResolver","Telemetry.pokesTotal","Telemetry.pokesSuppressedTotal","Telemetry.fanoutLatencyMs","Cvr.diff","Cvr.empty","Subsets.make","Telemetry.patchOps","Telemetry.serverPullsTotal","make","layer","RejectionMemory.forgetBelow","Predicate.resolveExists","Predicate.existsValues","Subset.apply"],"sources":["../src/Errors.ts","../src/FilterPolicy.ts","../src/Collection.ts","../src/Predicate.ts","../src/CollectionIndex.ts","../src/Subset.ts","../src/Related.ts","../src/Query.ts","../src/Aggregate.ts","../src/Mutator.ts","../src/AtomicKeyValue.ts","../src/Identity.ts","../src/Protocol.ts","../src/ClientStore.ts","../src/Hash.ts","../src/FractionalIndex.ts","../src/OrderedTree.ts","../src/LiveView.ts","../src/MutationState.ts","../src/RowChange.ts","../src/Telemetry.ts","../src/Transport.ts","../src/ClientEngine.ts","../src/RpcTransport.ts","../src/MirrorProtocol.ts","../src/Coverage.ts","../src/PullMarks.ts","../src/Subscriptions.ts","../src/ClientView.ts","../src/Mirror.ts","../src/Authorization.ts","../src/RejectionMemory.ts","../src/UnknownMutator.ts","../src/Backend.ts","../src/Cvr.ts","../src/InvalidationBus.ts","../src/SyncServer.ts","../src/MemoryBackend.ts"],"sourcesContent":["/**\n * Errors\n *\n * Tagged errors shared across the sync engine. All errors extend\n * `Schema.TaggedError`, so they are yieldable in `Effect.gen`, catchable\n * with `Effect.catchTag` / `Effect.catchTags`, and carry a schema.\n */\n\nimport * as Schema from \"effect/Schema\";\n\n/** A client or server storage operation failed. */\nexport class StoreError extends Schema.TaggedError<StoreError, { readonly brand: unique symbol }>()(\n \"StoreError\",\n {\n message: Schema.String,\n cause: Schema.optional(Schema.Defect()),\n }\n) {}\n\n/** A protocol message could not be carried (connection lost, send failed). */\nexport class TransportError extends Schema.TaggedError<\n TransportError,\n { readonly brand: unique symbol }\n>()(\"TransportError\", {\n message: Schema.String,\n cause: Schema.optional(Schema.Defect()),\n}) {}\n\n/** A received frame was not a valid protocol message. */\nexport class ProtocolError extends Schema.TaggedError<\n ProtocolError,\n { readonly brand: unique symbol }\n>()(\"ProtocolError\", {\n message: Schema.String,\n cause: Schema.optional(Schema.Defect()),\n}) {}\n\n/**\n * The backend failed to apply mutations or evaluate a subscription. A\n * `BackendError` from a mutator handler is a *transient* failure: the push\n * batch is aborted and the client retries (correct for deadlocks, timeouts,\n * lost connections).\n */\nexport class BackendError extends Schema.TaggedError<\n BackendError,\n { readonly brand: unique symbol }\n>()(\"BackendError\", {\n message: Schema.String,\n cause: Schema.optional(Schema.Defect()),\n}) {}\n\n/**\n * A mutator was *permanently* rejected by the backend — failed server-side\n * validation, a revoked permission, a violated business rule. Unlike a\n * transient `BackendError`, the backend records the mutation as processed\n * (bumps `lastMutationId` without applying effects, atomically) so it never\n * poisons the queue: mutations behind it still apply, and the client drops the\n * optimistic effect on the next rebase. A mutator handler raises this to opt a\n * failure into the permanent class (Replicache's lastMutationID rule).\n */\nexport class MutationRejected extends Schema.TaggedError<\n MutationRejected,\n { readonly brand: unique symbol }\n>()(\"MutationRejected\", {\n reason: Schema.String,\n cause: Schema.optional(Schema.Defect()),\n}) {}\n\n/**\n * The server rejected a request because the client's declared `schemaVersion`\n * is not one this build accepts (#48). Unlike a {@link MutationRejected} (a\n * per-mutation, permanent business verdict) this is a *transport-level* \"your\n * build is obsolete\" condition: it is raised up front, before any mutation is\n * applied or any patch computed, so the journal is never poisoned — the client\n * retains its pending intents and is told to update. Distinct from a\n * {@link TransportError} so a carrier that can carry the tag lets the client\n * react precisely (the in-memory seam does; the RPC carrier degrades it to a\n * `TransportError`, see RpcTransport.ts).\n */\nexport class VersionNotSupportedError extends Schema.TaggedError<\n VersionNotSupportedError,\n { readonly brand: unique symbol }\n>()(\"VersionNotSupportedError\", {\n schemaVersion: Schema.optional(Schema.String),\n message: Schema.String,\n}) {}\n\n/** A subscription or push was refused by auth filters or middleware. */\nexport class AuthorizationError extends Schema.TaggedError<\n AuthorizationError,\n { readonly brand: unique symbol }\n>()(\"AuthorizationError\", {\n message: Schema.String,\n collection: Schema.optional(Schema.String),\n}) {}\n\n/** The journal could not append, read, or acknowledge pending mutations. */\nexport class JournalError extends Schema.TaggedError<\n JournalError,\n { readonly brand: unique symbol }\n>()(\"JournalError\", {\n message: Schema.String,\n cause: Schema.optional(Schema.Defect()),\n}) {}\n\n/** A mutator was missing, its args failed validation, or it failed locally. */\nexport class MutatorError extends Schema.TaggedError<\n MutatorError,\n { readonly brand: unique symbol }\n>()(\"MutatorError\", {\n message: Schema.String,\n mutator: Schema.optional(Schema.String),\n cause: Schema.optional(Schema.Defect()),\n}) {}\n\n/**\n * A named query was missing or its args failed validation; or a declarative\n * read could not be compiled (an unknown collection or edge) or parsed from\n * a URL. `parameter` names the offending query-string parameter\n * (`filter[age][gt]`, `include`, `page[limit]`) when the error comes from\n * URL parsing (`@thomasfosterau/legation-jsonapi`'s `JsonApiQuery.parseRead`) — the value a\n * JSON:API 400 document carries as `source.parameter`.\n */\nexport class QueryError extends Schema.TaggedError<QueryError, { readonly brand: unique symbol }>()(\n \"QueryError\",\n {\n message: Schema.String,\n query: Schema.optional(Schema.String),\n parameter: Schema.optional(Schema.String),\n cause: Schema.optional(Schema.Defect()),\n }\n) {}\n\n/**\n * A Node (or Collection) declared a filterable or sortable field its row does\n * not carry, or a filterable attribute whose literal kind can neither be\n * derived from its schema nor was given explicitly (#154, ADR-0028). A static\n * definition bug surfaced at setup time, like {@link DuplicateNameError};\n * thrown by the synchronous `Node.make`.\n */\nexport class FilterDeclarationError extends Schema.TaggedError<\n FilterDeclarationError,\n { readonly brand: unique symbol }\n>()(\"FilterDeclarationError\", {\n collection: Schema.String,\n field: Schema.String,\n message: Schema.String,\n}) {}\n\n/**\n * A registry (collections, mutators, queries) was built with a duplicate\n * name — a static configuration bug surfaced at setup time. Thrown by the\n * synchronous `registry` builders; tagged so it is still identifiable.\n */\nexport class DuplicateNameError extends Schema.TaggedError<\n DuplicateNameError,\n { readonly brand: unique symbol }\n>()(\"DuplicateNameError\", {\n kind: Schema.Literals([\"collection\", \"mutator\", \"query\", \"relationship\"]),\n name: Schema.String,\n}) {\n override get message(): string {\n return `Duplicate ${this.kind} name: ${this.name}`;\n }\n}\n\n/**\n * A collection declared a relationship pointing at a foreign collection that is\n * not present in the registry — a static configuration bug surfaced at setup\n * time (like {@link DuplicateNameError}). Thrown by the synchronous\n * `Collection.registry` builder.\n */\nexport class UnknownCollectionError extends Schema.TaggedError<\n UnknownCollectionError,\n { readonly brand: unique symbol }\n>()(\"UnknownCollectionError\", {\n /** The collection declaring the relationship. */\n from: Schema.String,\n /** The relationship name whose `collection` is unknown. */\n relationship: Schema.String,\n /** The missing foreign collection the relationship points at. */\n collection: Schema.String,\n}) {\n override get message(): string {\n return `Relationship \"${this.relationship}\" on collection \"${this.from}\" points at unknown collection: ${this.collection}`;\n }\n}\n","/**\n * FilterPolicy\n *\n * The **filterable set** (ADR-0028 rule d, issue #154): the attributes of a\n * node a client may filter or sort by, each with the operators it accepts\n * and the literal kind its values must carry. Declared on the Node\n * (`Node.make`'s `filterable` / `sortable` options), carried onto the\n * derived Collection exactly as `indexes` is, and enforced by\n * `Authorization.authorize` before an auth filter is AND-ed in and before\n * `Backend.evaluate` runs — so an undeclared column is unreachable by\n * construction, not by the good behaviour of every evaluator.\n *\n * Two things are server-authored and therefore exempt from the check: the\n * auth filter's own predicate, and the subsets a named-query resolver\n * produces (`SyncServer` authorises those with `origin: \"server\"`).\n *\n * The operator vocabulary is the grammar's full core (ADR-0028 §3):\n * `eq ne lt lte gt gte in nin isnull`. `NotIn` is checked as `nin` and\n * `IsNull` (negated or not) as `isnull`; so are their older wire forms,\n * `Not(In)` and a `Compare` against a `null` literal (ADR-0028 §5), which\n * a client built before #155 may still send.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Option from \"effect/Option\";\nimport * as P from \"effect/Predicate\";\nimport * as SchemaAST from \"effect/SchemaAST\";\nimport { AuthorizationError, FilterDeclarationError } from \"./Errors.js\";\nimport type { Literal, Predicate } from \"./Predicate.js\";\nimport type { OrderBy } from \"./Subset.js\";\n\n// ─── Vocabulary ──────────────────────────────────────────────────────────────\n\n/** A comparison operator of the filter grammar (ADR-0028 §3). */\nexport type FilterOperator = \"eq\" | \"ne\" | \"lt\" | \"lte\" | \"gt\" | \"gte\" | \"in\" | \"nin\" | \"isnull\";\n\n/** Every {@link FilterOperator}, in grammar order. */\nexport const operators: ReadonlyArray<FilterOperator> = [\n \"eq\",\n \"ne\",\n \"lt\",\n \"lte\",\n \"gt\",\n \"gte\",\n \"in\",\n \"nin\",\n \"isnull\",\n];\n\n/**\n * The literal kind of a filterable attribute (ADR-0028 §2(e), §4). The kind\n * cannot always be read off a JS literal — `text` and `instant` are both\n * strings, `integer` and `double` both numbers — so the declaration carries\n * it: the SQL compilers bind and collate by it (#156), and `authorize`\n * checks every client literal against it.\n */\nexport type LiteralKind = \"text\" | \"integer\" | \"double\" | \"boolean\" | \"instant\";\n\n/** One filterable attribute: its literal kind and the operators it accepts. */\nexport interface FilterableField {\n readonly kind: LiteralKind;\n readonly operators: ReadonlyArray<FilterOperator>;\n}\n\n/** A collection's filterable set: filterable attributes plus sortable ones. */\nexport interface FilterDeclaration {\n readonly filterable: Readonly<Record<string, FilterableField>>;\n readonly sortable: ReadonlyArray<string>;\n}\n\n/**\n * The per-field form `Node.make` accepts: the operators alone (the kind is\n * derived from the attribute schema), or operators with an explicit kind\n * (required where derivation cannot tell, e.g. an `instant` stored as text).\n */\nexport type FilterableInput =\n | ReadonlyArray<FilterOperator>\n | { readonly operators: ReadonlyArray<FilterOperator>; readonly kind?: LiteralKind };\n\n/**\n * What a key field (the identity attribute, or a `one`-edge's `via` field) is\n * filterable by when nothing else is declared: `eq` / `in` over text — the\n * shape edge windows (`fk = parent`, `identity IN (…)`) and allow-set auth\n * filters already depend on.\n */\nexport const keyDefaults: FilterableField = { kind: \"text\", operators: [\"eq\", \"in\"] };\n\n/**\n * The declaration a collection with nothing declared but its identity\n * attribute is checked against: that attribute by `eq` / `in`, sortable by\n * it (ADR-0026's tie-break).\n */\nexport const bareFor = (identity: string): FilterDeclaration => ({\n filterable: { [identity]: keyDefaults },\n sortable: [identity],\n});\n\n/**\n * The declaration a collection with no declaration at all is checked\n * against: `id` by `eq` / `in`, sortable by `id`. The floor for a collection\n * the registry does not know — there is no node to read an identity\n * attribute off, so the default name is all that can be assumed.\n */\nexport const bare: FilterDeclaration = bareFor(\"id\");\n\n// ─── Kind derivation ─────────────────────────────────────────────────────────\n\nconst INT_CHECK_ID = \"effect/schema/isInt\";\n\n/** Whether any check on the node (recursing into groups) is `Schema.isInt`. */\nconst hasIntCheck = (checks: SchemaAST.Checks | undefined): boolean =>\n checks !== undefined &&\n checks.some((check) =>\n check._tag === \"FilterGroup\"\n ? hasIntCheck(check.checks)\n : check.annotations?.representation?.id === INT_CHECK_ID\n );\n\n/** The kind of a literal schema, by the JS type of its literal. */\nconst kindOfLiteral = (literal: SchemaAST.LiteralValue): LiteralKind | undefined => {\n switch (typeof literal) {\n case \"string\":\n return \"text\";\n case \"number\":\n return \"double\";\n case \"boolean\":\n return \"boolean\";\n default:\n return undefined;\n }\n};\n\n/** The one kind shared by a union's non-null members (`NullOr`, `optional`, `Literals`). */\nconst kindOfUnion = (members: ReadonlyArray<SchemaAST.AST>): LiteralKind | undefined => {\n const kinds = members\n .filter((member) => member._tag !== \"Null\" && member._tag !== \"Undefined\")\n .map(kindOfAst);\n if (kinds.includes(undefined)) return undefined;\n const distinct = new Set(kinds);\n return distinct.size === 1 ? [...distinct][0] : undefined;\n};\n\nconst kindOfAst = (ast: SchemaAST.AST): LiteralKind | undefined => {\n switch (ast._tag) {\n case \"String\":\n return \"text\";\n case \"Number\":\n return hasIntCheck(ast.checks) ? \"integer\" : \"double\";\n case \"Boolean\":\n return \"boolean\";\n case \"Literal\":\n return kindOfLiteral(ast.literal);\n case \"Union\":\n return kindOfUnion(ast.types);\n default:\n return undefined;\n }\n};\n\n/**\n * The default literal kind of an attribute, read off its schema's **encoded**\n * form (the wire type a client literal is compared with): a `String` is\n * `text`, a `Number` is `double` unless it carries `Schema.isInt` (then\n * `integer`), a `Boolean` is `boolean`; literals and nullable / optional\n * unions resolve to their members' one kind. `instant` is never derived — a\n * string is a string on the wire — so an instant attribute declares its kind\n * explicitly. `undefined` where nothing can be said (a declaration such as\n * `Schema.Date`, an object, an array).\n */\nexport const kindOf = (schema: { readonly ast: SchemaAST.AST }): LiteralKind | undefined =>\n kindOfAst(SchemaAST.toEncoded(schema.ast));\n\n// ─── Resolution (definition time) ────────────────────────────────────────────\n\n/** What {@link resolve} needs from a node definition. */\nexport interface ResolveOptions {\n readonly collection: string;\n /** The scalar attributes, by field name — the kind derivation source. */\n readonly attributes: Readonly<Record<string, { readonly ast: SchemaAST.AST }>>;\n /**\n * The attribute supplying the row id — a node's declared identity, or\n * `\"id\"` when it declares none. Always sortable (ADR-0026's tie-break).\n */\n readonly identity?: string | undefined;\n /**\n * The key fields defaulting to {@link keyDefaults}: the identity attribute\n * plus every `one`-edge `via`.\n */\n readonly keyFields: ReadonlyArray<string>;\n readonly filterable?: Readonly<Record<string, FilterableInput>> | undefined;\n readonly sortable?: ReadonlyArray<string> | undefined;\n}\n\n/**\n * Resolve a node's declaration: the key defaults first, then each declared\n * field with its operators and its explicit or derived kind; `sortable`\n * always includes the identity attribute. A field the row does not carry, or\n * an attribute whose kind cannot be derived and is not given, is a\n * definition-time defect (a thrown {@link FilterDeclarationError}), never a\n * runtime failure.\n */\nexport const resolve = (options: ResolveOptions): FilterDeclaration => {\n const known = new Set<string>([...options.keyFields, ...Object.keys(options.attributes)]);\n const filterable: Record<string, FilterableField> = {};\n Arr.forEach(Object.entries(options.filterable ?? {}), ([field, input]) => {\n assertRowField(options, known, field, \"filterable\");\n filterable[field] = resolveField(options, field, normaliseInput(input));\n });\n Arr.forEach(options.sortable ?? [], (field) => {\n assertRowField(options, known, field, \"sortable\");\n });\n return withKeyDefaults(\n options.keyFields,\n filterable,\n options.sortable ?? [],\n options.identity ?? \"id\"\n );\n};\n\n/** One field's declaration with the operators-only shorthand expanded. */\ntype DeclaredField = {\n readonly operators: ReadonlyArray<FilterOperator>;\n readonly kind?: LiteralKind;\n};\n\n/** The declared form of one field, with the operators-only shorthand expanded. */\nconst normaliseInput = (input: FilterableInput): DeclaredField =>\n Array.isArray(input)\n ? { operators: input as ReadonlyArray<FilterOperator> }\n : (input as DeclaredField);\n\n/** A declared field must be a field of the row. */\nconst assertRowField = (\n options: ResolveOptions,\n known: ReadonlySet<string>,\n field: string,\n role: \"filterable\" | \"sortable\"\n): void => {\n if (known.has(field)) return;\n throw new FilterDeclarationError({\n collection: options.collection,\n field,\n message: `Collection \"${options.collection}\" declares ${role} field \"${field}\", which is not a field of its row`,\n });\n};\n\n/** One field's resolved entry: its explicit or derived kind plus its operators. */\nconst resolveField = (\n options: ResolveOptions,\n field: string,\n declared: DeclaredField\n): FilterableField => {\n const attribute = options.attributes[field];\n const kind = declared.kind ?? (attribute === undefined ? keyDefaults.kind : kindOf(attribute));\n if (kind === undefined) {\n throw new FilterDeclarationError({\n collection: options.collection,\n field,\n message: `Collection \"${options.collection}\" cannot derive a literal kind for filterable field \"${field}\"; declare its kind explicitly (text, integer, double, boolean or instant)`,\n });\n }\n return { kind, operators: [...new Set(declared.operators)] };\n};\n\n/**\n * Overlay a declaration on the key defaults: every key field (the identity\n * attribute, a `one`-edge / relationship key) is filterable by at least `eq`\n * / `in` — a declaration naming one **widens** it, never replaces it,\n * because the engine's own edge windows (`fk = parent`, `identity IN (…)`)\n * depend on those operators — and the identity attribute is always sortable\n * (ADR-0026's tie-break). Shared by the Node resolution above and\n * `Collection.filterDeclarationOf`.\n *\n * `identity` is the attribute supplying the row id, `\"id\"` when the\n * definition names none — so a node identified by `username` gets `username`\n * sortable and no phantom `id`.\n */\nexport const withKeyDefaults = (\n keyFields: ReadonlyArray<string>,\n filterable: Readonly<Record<string, FilterableField>>,\n sortable: ReadonlyArray<string>,\n identity: string = \"id\"\n): FilterDeclaration => {\n const merged: Record<string, FilterableField> = {};\n Arr.forEach(keyFields, (field) => {\n merged[field] = keyDefaults;\n });\n Arr.forEach(Object.entries(filterable), ([field, declared]) => {\n const base = merged[field];\n merged[field] =\n base === undefined\n ? declared\n : {\n kind: declared.kind,\n operators: [...new Set([...base.operators, ...declared.operators])],\n };\n });\n return { filterable: merged, sortable: [...new Set([identity, ...sortable])] };\n};\n\n// ─── Enforcement (request time) ──────────────────────────────────────────────\n\nconst INT4_MIN = -2147483648;\nconst INT4_MAX = 2147483647;\n/** `Date#toISOString`'s fixed-width UTC form (ADR-0028 §2(e)). */\nconst INSTANT = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/;\n\n/** Whether a (non-null) literal is a value of the kind. */\nexport const matchesKind = (kind: LiteralKind, value: Literal): boolean => {\n switch (kind) {\n case \"text\":\n return P.isString(value);\n case \"instant\":\n return P.isString(value) && INSTANT.test(value);\n case \"double\":\n return P.isNumber(value) && Number.isFinite(value);\n case \"integer\":\n return (\n P.isNumber(value) && Number.isSafeInteger(value) && value >= INT4_MIN && value <= INT4_MAX\n );\n case \"boolean\":\n return P.isBoolean(value);\n }\n};\n\nconst deny = (collection: string, message: string): AuthorizationError =>\n new AuthorizationError({ message: `Collection \"${collection}\": ${message}`, collection });\n\nconst fieldCheck = (\n collection: string,\n declaration: FilterDeclaration,\n field: string,\n operator: FilterOperator\n): AuthorizationError | undefined => {\n const declared = declaration.filterable[field];\n if (declared === undefined) {\n return deny(\n collection,\n `field \"${field}\" is not filterable (filterable: ${Object.keys(declaration.filterable).join(\", \")})`\n );\n }\n if (!declared.operators.includes(operator)) {\n return deny(\n collection,\n `field \"${field}\" is not filterable with \"${operator}\" (declared: ${declared.operators.join(\", \")})`\n );\n }\n return undefined;\n};\n\nconst literalCheck = (\n collection: string,\n declaration: FilterDeclaration,\n field: string,\n operator: FilterOperator,\n value: Literal\n): AuthorizationError | undefined => {\n const kind = declaration.filterable[field]?.kind;\n return value !== null && kind !== undefined && matchesKind(kind, value)\n ? undefined\n : deny(\n collection,\n `literal ${JSON.stringify(value)} for field \"${field}\" (\"${operator}\") does not match its kind \"${kind}\"`\n );\n};\n\n/** An `In` node checked as `in`, or as `nin` when it sits under `Not`. */\nconst inCheck = (\n collection: string,\n declaration: FilterDeclaration,\n node: { readonly field: string; readonly values: ReadonlyArray<Literal> },\n operator: \"in\" | \"nin\"\n): AuthorizationError | undefined => {\n const failed = fieldCheck(collection, declaration, node.field, operator);\n if (failed !== undefined) return failed;\n return Option.getOrUndefined(\n Arr.findFirst(node.values, (value) =>\n Option.fromUndefinedOr(literalCheck(collection, declaration, node.field, operator, value))\n )\n );\n};\n\n/** Whether a `Compare` is the wire form of `isnull` (a null literal on `eq` / `ne`; ADR-0028 §5). */\nconst isNullTest = (node: { readonly op: string; readonly value: Literal }): boolean =>\n node.value === null && (node.op === \"eq\" || node.op === \"ne\");\n\n/**\n * Check a client-authored predicate against a collection's declaration:\n * every `Compare` / `In` names a declared field with that operator and a\n * literal of the field's kind; `Exists` is refused anywhere (only an auth\n * filter may introduce it); the connectives recurse. `undefined` means the\n * predicate is admissible.\n *\n * `NotIn` is `nin` and `IsNull` is `isnull` whether or not it is negated.\n * The older wire forms, `Not(In)` and a `Compare` against a null literal\n * (negated under `Not`), are checked against the same operators, so a\n * `nin`-only declaration admits both `NotIn` and `Not(In)` and an\n * `in`-only one admits neither.\n */\nexport const checkWhere = (\n collection: string,\n declaration: FilterDeclaration,\n where: Predicate\n): AuthorizationError | undefined => {\n switch (where._tag) {\n case \"True\":\n return undefined;\n case \"Compare\":\n return compareCheck(collection, declaration, where);\n case \"In\":\n return inCheck(collection, declaration, where, \"in\");\n case \"NotIn\":\n return inCheck(collection, declaration, where, \"nin\");\n case \"IsNull\":\n return fieldCheck(collection, declaration, where.field, \"isnull\");\n case \"And\":\n case \"Or\":\n return connectiveCheck(collection, declaration, where.predicates);\n case \"Not\":\n return notCheck(collection, declaration, where.predicate);\n case \"Exists\":\n return deny(collection, `\"Exists\" is not allowed in a client predicate`);\n default:\n return deny(\n collection,\n `predicate node \"${(where as { readonly _tag: string })._tag}\" is not allowed in a client predicate`\n );\n }\n};\n\ntype CompareNode = Extract<Predicate, { readonly _tag: \"Compare\" }>;\n\n/** A `Compare`: its operator on its field, or `isnull` for the null-literal wire form. */\nconst compareCheck = (\n collection: string,\n declaration: FilterDeclaration,\n node: CompareNode\n): AuthorizationError | undefined => {\n if (node.value === null) {\n return isNullTest(node)\n ? fieldCheck(collection, declaration, node.field, \"isnull\")\n : deny(\n collection,\n `literal null for field \"${node.field}\" (\"${node.op}\") is not a comparable value`\n );\n }\n return (\n fieldCheck(collection, declaration, node.field, node.op) ??\n literalCheck(collection, declaration, node.field, node.op, node.value)\n );\n};\n\n/** `And` / `Or`: the first inadmissible operand decides. */\nconst connectiveCheck = (\n collection: string,\n declaration: FilterDeclaration,\n predicates: ReadonlyArray<Predicate>\n): AuthorizationError | undefined => {\n return Option.getOrUndefined(\n Arr.findFirst(predicates, (predicate) =>\n Option.fromUndefinedOr(checkWhere(collection, declaration, predicate))\n )\n );\n};\n\n/** `Not`: `Not(In)` is `nin`, a negated null test is `isnull`, anything else recurses. */\nconst notCheck = (\n collection: string,\n declaration: FilterDeclaration,\n inner: Predicate\n): AuthorizationError | undefined => {\n if (inner._tag === \"In\") return inCheck(collection, declaration, inner, \"nin\");\n if (inner._tag === \"Compare\" && isNullTest(inner)) {\n return fieldCheck(collection, declaration, inner.field, \"isnull\");\n }\n return checkWhere(collection, declaration, inner);\n};\n\n/** Check a client-authored `orderBy`: every field must be sortable. */\nexport const checkOrderBy = (\n collection: string,\n declaration: FilterDeclaration,\n orderBy: ReadonlyArray<OrderBy>\n): AuthorizationError | undefined => {\n const unsortable = orderBy.find((term) => !declaration.sortable.includes(term.field));\n return unsortable === undefined\n ? undefined\n : deny(\n collection,\n `field \"${unsortable.field}\" is not sortable (sortable: ${declaration.sortable.join(\", \")})`\n );\n};\n\n/** {@link checkWhere} then {@link checkOrderBy} over one subset's client-authored parts. */\nexport const check = (\n collection: string,\n declaration: FilterDeclaration,\n subset: { readonly where: Predicate; readonly orderBy: ReadonlyArray<OrderBy> }\n): AuthorizationError | undefined =>\n checkWhere(collection, declaration, subset.where) ??\n checkOrderBy(collection, declaration, subset.orderBy);\n","/**\n * Collection\n *\n * A collection is a named, schema-typed set of rows keyed by row id — the\n * unit the client materializes locally and queries (CONTEXT.md). The\n * collection definition is shared by client and server: the row `Schema` is\n * the single source of truth for validation, wire serialization, and\n * persistence encoding.\n *\n * The resource graph ({@link Node}) is the recommended front door: its\n * `Node.registry` derives collections through this module's constructor. For\n * domains the graph cannot express, hand-authoring a collection with\n * {@link make} is a supported lower-level surface. Neither surface is\n * deprecated; the graph is preferred when it applies.\n */\n\nimport * as Arr from \"effect/Array\";\nimport type * as Schema from \"effect/Schema\";\nimport { DuplicateNameError, UnknownCollectionError } from \"./Errors.js\";\nimport * as FilterPolicy from \"./FilterPolicy.js\";\n\n/** The identifier of one row within a collection. */\nexport type RowId = string;\n\n/**\n * A declared relationship from one collection to a foreign collection, by\n * field mapping (ADR-0006, issue #38). The read-side join a `Related` query\n * resolves and an auto-subscription narrows:\n *\n * - `\"one\"`: the single foreign row whose `foreignField` equals this row's\n * `localField` value (e.g. `comment.issueId → issues.id`).\n * - `\"many\"`: the foreign rows whose `foreignField` equals this row's\n * `localField` value (e.g. `issue.id → comments.issueId`).\n * - `\"paginated\"`: `\"many\"` with a declared stable `order` — the shape a\n * per-parent sync window needs (ADR-0024): windowed reads register one\n * `(foreignField = parent, order, limit)` subset per parent row.\n *\n * The mapping is deliberately symmetric so both directions declare the same\n * shape; only `kind` and which side holds the key differ.\n */\nexport interface Relationship {\n readonly name: string;\n readonly kind: \"one\" | \"many\" | \"paginated\";\n /** The foreign collection this relationship resolves against. */\n readonly collection: string;\n /**\n * The local row field holding the join value (`\"issueId\"`, or this\n * collection's identity attribute for `\"many\"`).\n */\n readonly localField: string;\n /**\n * The foreign row field the join matches (the target's identity attribute\n * for `\"one\"`, the FK for `\"many\"`).\n */\n readonly foreignField: string;\n /** The declared sort for `\"paginated\"` — part of the edge's identity (ADR-0022). */\n readonly order?: ReadonlyArray<{ readonly field: string; readonly direction: \"asc\" | \"desc\" }>;\n}\n\n/**\n * An opaque per-row token the backend changes on every authoritative write.\n * The basis for CVR diffing (ADR-0008).\n */\nexport type RowVersion = string | number;\n\n/** A row as held by the engine: value plus authoritative version. */\nexport interface Row<A> {\n readonly id: RowId;\n readonly version: RowVersion;\n readonly value: A;\n}\n\n/**\n * A collection definition.\n *\n * `Type` is the decoded row type; `Encoded` is its wire/persistence form.\n */\nexport interface Collection<A, I = unknown> {\n readonly name: string;\n /** Row codec: decoded type `A`, encoded (JSON-compatible) form `I`. */\n readonly schema: Schema.Codec<A, I>;\n /** Derive the row id from a row value. */\n readonly id: (value: A) => RowId;\n /**\n * The row field the id is derived from — the Node's declared identity\n * attribute (`Node.make`'s `id` option), or `\"id\"` when it declares none.\n * Unlike {@link Collection.id} it is introspectable, so the engine's joins\n * and the filterable set can name the field the way a query must\n * (`filterDeclarationOf`, `Node.registry`'s edge compilation). Absent on a\n * hand-built collection: `\"id\"` is assumed, exactly as before this field\n * existed.\n */\n readonly identity?: string;\n /** Declared relationships to other collections (issue #38). */\n readonly relationships?: ReadonlyArray<Relationship>;\n /**\n * Fields eligible for secondary indexing (issue #113): `eq`/`In` predicates\n * on a declared field resolve via an in-memory hash index, range\n * `Compare`s via an ordered one, instead of a full collection scan. Purely\n * an engine-level acceleration hint — maintained from row deltas, rebuilt\n * on demand; absent (or an engine with `autoIndex` off) means every\n * predicate scans, exactly like before this field existed.\n */\n readonly indexes?: ReadonlyArray<string>;\n /**\n * The **filterable set** (ADR-0028 rule d, #154): the fields a client may\n * filter by, each with its operators and literal kind. Resolved on the\n * Node (`Node.make`'s `filterable` option plus the identity / `one`-edge\n * key defaults) and carried here so the server enforces it in `authorize`\n * without Node definitions — exactly how `indexes` travels. Absent on a\n * hand-built collection: see {@link filterDeclarationOf} for what is\n * enforced then.\n */\n readonly filterable?: Readonly<Record<string, FilterPolicy.FilterableField>>;\n /** The fields a client may order by (#154); always includes the identity. */\n readonly sortable?: ReadonlyArray<string>;\n}\n\n/** A collection definition with the row type erased. */\nexport type AnyCollection = Collection<any, any>;\n\n/** Extract the row type of a collection. */\nexport type RowOf<C> = C extends Collection<infer A, any> ? A : never;\n\n/** Define a collection. */\nexport const make = <A, I>(options: {\n readonly name: string;\n readonly schema: Schema.Codec<A, I>;\n readonly id: (value: A) => RowId;\n readonly identity?: string;\n readonly relationships?: ReadonlyArray<Relationship>;\n readonly indexes?: ReadonlyArray<string>;\n readonly filterable?: Readonly<Record<string, FilterPolicy.FilterableField>>;\n readonly sortable?: ReadonlyArray<string>;\n}): Collection<A, I> => options;\n\n/**\n * The filter declaration `authorize` enforces for a collection (#154): the\n * carried `filterable` / `sortable` (every Node-derived collection has\n * them) overlaid on the key defaults — the {@link Collection.identity}\n * attribute plus every `\"one\"` relationship's local key field by at least\n * `eq` / `in`, the identity always sortable — so a hand-built collection\n * keeps the same invariants a node does, and one declaring nothing is closed\n * exactly as an undeclared node would be. A collection carrying no\n * `identity` is keyed on `\"id\"`, as every collection was before a node could\n * name its identity attribute.\n */\nexport const filterDeclarationOf = (collection: AnyCollection): FilterPolicy.FilterDeclaration => {\n const identity = collection.identity ?? \"id\";\n const keyFields = [identity];\n Arr.forEach(collection.relationships ?? [], (relationship) => {\n if (relationship.kind === \"one\") keyFields.push(relationship.localField);\n });\n return FilterPolicy.withKeyDefaults(\n keyFields,\n collection.filterable ?? {},\n collection.sortable ?? [],\n identity\n );\n};\n\n/**\n * A set of collections, by name — what an engine or backend is configured\n * with. Lookups at the protocol boundary are by name, so registries are\n * intentionally string-keyed.\n */\nexport type CollectionRegistry = ReadonlyMap<string, AnyCollection>;\n\n/**\n * Validate one collection's relationships against the built registry: a\n * duplicate relationship name within the collection, or a relationship pointing\n * at a collection not in the registry, throws.\n */\nconst validateRelationships = (\n collection: AnyCollection,\n map: ReadonlyMap<string, AnyCollection>\n): void => {\n const seen = new Set<string>();\n Arr.forEach(collection.relationships ?? [], (relationship) => {\n if (seen.has(relationship.name)) {\n throw new DuplicateNameError({ kind: \"relationship\", name: relationship.name });\n }\n seen.add(relationship.name);\n if (!map.has(relationship.collection)) {\n throw new UnknownCollectionError({\n from: collection.name,\n relationship: relationship.name,\n collection: relationship.collection,\n });\n }\n });\n};\n\n/**\n * Build a registry from collection definitions. Duplicate collection names,\n * duplicate relationship names within a collection, and relationships pointing\n * at an unknown collection all throw at build time.\n */\nexport const registry = (collections: ReadonlyArray<AnyCollection>): CollectionRegistry => {\n const map = new Map<string, AnyCollection>();\n Arr.forEach(collections, (collection) => {\n if (map.has(collection.name)) {\n throw new DuplicateNameError({ kind: \"collection\", name: collection.name });\n }\n map.set(collection.name, collection);\n });\n Arr.forEach(collections, (collection) => {\n validateRelationships(collection, map);\n });\n return map;\n};\n\n/**\n * The declared relationships of a collection, by name — `undefined` collection\n * or none declared yields an empty map. A convenience for `Related` resolvers\n * that select relationships by name.\n */\nexport const relationshipsOf = (\n registry: CollectionRegistry,\n collectionName: string\n): ReadonlyMap<string, Relationship> => {\n const map = new Map<string, Relationship>();\n Arr.forEach(registry.get(collectionName)?.relationships ?? [], (relationship) => {\n map.set(relationship.name, relationship);\n });\n return map;\n};\n","/**\n * Predicate\n *\n * The serializable expression language over row fields used by\n * subscriptions and live queries. Predicates are data (an expression tree),\n * not opaque functions, so they can travel over the wire, be narrowed by\n * server-side auth filters (AND-ed, never widened), be evaluated against\n * any storage, and later feed incremental view maintenance.\n *\n * Semantics are Postgres's, per ADR-0028 (`docs/adr/0028-filter-grammar-\n * and-normative-semantics.md`): `evaluate` is three-valued (`Option<boolean>`\n * with Kleene connectives), an absent attribute is NULL, text orders by code\n * point, and a `Compare`/`In` against a `null` literal is unknown. `test` is\n * the `WHERE` collapse of `evaluate`: a row matches iff the result is\n * `Some(true)`. The differential harness in `@thomasfosterau/legation/sql` proves every\n * evaluator agrees with a real Postgres.\n *\n * Core ships this in-memory evaluator; storage-specific translators (e.g.\n * predicate → SQL WHERE clause) live with the backends that need them.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as P from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\n\n/**\n * A literal comparable value. `null` stays in the wire union for\n * compatibility; under ADR-0028 NULL is not a literal (use `IsNull`), and a\n * `Compare`/`In` carrying `null` evaluates to unknown, as in Postgres.\n */\nexport type Literal = string | number | boolean | null;\n\n/** Comparison operators over a row field. */\nexport type Comparison = \"eq\" | \"ne\" | \"gt\" | \"gte\" | \"lt\" | \"lte\";\n\n/**\n * The literal kinds of ADR-0028 rule (e): `text` (code-point ordered),\n * `integer` (int4), `double` (double precision), `boolean`, and `instant`\n * (an ISO-8601 UTC string in the fixed `Date#toISOString` format, so text\n * order is chronological order). A declared attribute carries one of these;\n * the SQL compilers bind and collate by it (`@thomasfosterau/legation/sql`), and the\n * differential corpus (`FilterCorpus`) generates literals of it.\n */\nexport type LiteralKind = \"text\" | \"integer\" | \"double\" | \"boolean\" | \"instant\";\n\n/**\n * A predicate expression tree.\n *\n * - `True` matches every row (the empty predicate).\n * - `Compare` compares a top-level row field against a literal.\n * - `In` tests field membership in a literal set; `NotIn` is its SQL\n * `NOT IN` (`x <> a AND x <> b`), not the Kleene negation of `In`.\n * - `IsNull` is the only way to test for NULL (an absent field is NULL too);\n * `negated` makes it `IS NOT NULL`.\n * - `And` / `Or` / `Not` compose (Kleene connectives).\n * - `Exists` is a correlated relationship test: this row matches if a row\n * exists in `collection` whose `where` holds and whose `foreignField` equals\n * this row's `localField`. It is a relational node — a single-row evaluator\n * can't decide it; a backend resolves it to an `In` over `localField` against\n * the matching `foreignField` set (`resolveExists`).\n * - `InSet` tests field membership in a **named set** (ADR-0015 amendment,\n * #205): the node carries the set's name, never its members, so an auth\n * filter's authored form is stable while the set moves. It is server-authored\n * only — the wire codec has no case for it — and the sync server binds it to\n * the resolved values (`bindSets`) before a subset reaches a backend. An\n * unbound `InSet` matches nothing.\n */\nexport type Predicate =\n | { readonly _tag: \"True\" }\n | {\n readonly _tag: \"Compare\";\n readonly op: Comparison;\n readonly field: string;\n readonly value: Literal;\n }\n | { readonly _tag: \"In\"; readonly field: string; readonly values: ReadonlyArray<Literal> }\n | { readonly _tag: \"NotIn\"; readonly field: string; readonly values: ReadonlyArray<Literal> }\n | { readonly _tag: \"IsNull\"; readonly field: string; readonly negated?: boolean }\n | { readonly _tag: \"And\"; readonly predicates: ReadonlyArray<Predicate> }\n | { readonly _tag: \"Or\"; readonly predicates: ReadonlyArray<Predicate> }\n | { readonly _tag: \"Not\"; readonly predicate: Predicate }\n | {\n readonly _tag: \"Exists\";\n readonly collection: string;\n readonly localField: string;\n readonly foreignField: string;\n readonly where: Predicate;\n }\n | { readonly _tag: \"InSet\"; readonly field: string; readonly set: string };\n\n/** The fields of an {@link Predicate} `Exists` node. */\nexport interface ExistsNode {\n readonly collection: string;\n readonly localField: string;\n readonly foreignField: string;\n readonly where: Predicate;\n}\n\nconst Literal = Schema.Union([Schema.String, Schema.Number, Schema.Boolean, Schema.Null]);\n\n/**\n * Wire codec for {@link Predicate}. `NotIn` and `IsNull` were added by\n * ADR-0028 (wire-additive: every older encoding still decodes). `InSet` has\n * no case: a named-set reference is server-authored only (#205), so a client\n * can never send one, and the server binds every one before a subset is\n * stored or sent.\n */\nexport const PredicateSchema: Schema.Codec<Predicate> = Schema.Union([\n Schema.Struct({ _tag: Schema.tag(\"True\") }),\n Schema.Struct({\n _tag: Schema.tag(\"Compare\"),\n op: Schema.Literals([\"eq\", \"ne\", \"gt\", \"gte\", \"lt\", \"lte\"]),\n field: Schema.String,\n value: Literal,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"In\"),\n field: Schema.String,\n values: Schema.Array(Literal),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"NotIn\"),\n field: Schema.String,\n values: Schema.Array(Literal),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"IsNull\"),\n field: Schema.String,\n negated: Schema.optional(Schema.Boolean),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"And\"),\n predicates: Schema.Array(Schema.suspend((): Schema.Codec<Predicate> => PredicateSchema)),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"Or\"),\n predicates: Schema.Array(Schema.suspend((): Schema.Codec<Predicate> => PredicateSchema)),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"Not\"),\n predicate: Schema.suspend((): Schema.Codec<Predicate> => PredicateSchema),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"Exists\"),\n collection: Schema.String,\n localField: Schema.String,\n foreignField: Schema.String,\n where: Schema.suspend((): Schema.Codec<Predicate> => PredicateSchema),\n }),\n]) as Schema.Codec<Predicate>;\n\n// ─── Constructors ────────────────────────────────────────────────────────────\n\n/** The predicate every row matches. */\nexport const always: Predicate = { _tag: \"True\" };\n\n/**\n * The raw `Compare` node. Prefer the named constructors: `eq`/`ne` desugar\n * a `null` literal to `IsNull`, whereas a `Compare` built here with `null`\n * evaluates to unknown for every row (ADR-0028 section 5).\n */\nexport const compare = (op: Comparison, field: string, value: Literal): Predicate => ({\n _tag: \"Compare\",\n op,\n field,\n value,\n});\n\n/** `field IS NULL` — true for an explicit `null` and for an absent field alike. */\nexport const isNull = (field: string): Predicate => ({ _tag: \"IsNull\", field });\n\n/** `field IS NOT NULL`. */\nexport const isNotNull = (field: string): Predicate => ({ _tag: \"IsNull\", field, negated: true });\n\n/** `field = value`; `eq(field, null)` desugars to {@link isNull} (ADR-0028). */\nexport const eq = (field: string, value: Literal): Predicate =>\n value === null ? isNull(field) : compare(\"eq\", field, value);\n/** `field <> value`; `ne(field, null)` desugars to {@link isNotNull} (ADR-0028). */\nexport const ne = (field: string, value: Literal): Predicate =>\n value === null ? isNotNull(field) : compare(\"ne\", field, value);\n/** `field > value`; unknown when the field is null or absent (three-valued, ADR-0028). */\nexport const gt = (field: string, value: Literal): Predicate => compare(\"gt\", field, value);\n/** `field >= value`; unknown when the field is null or absent (three-valued, ADR-0028). */\nexport const gte = (field: string, value: Literal): Predicate => compare(\"gte\", field, value);\n/** `field < value`; unknown when the field is null or absent (three-valued, ADR-0028). */\nexport const lt = (field: string, value: Literal): Predicate => compare(\"lt\", field, value);\n/** `field <= value`; unknown when the field is null or absent (three-valued, ADR-0028). */\nexport const lte = (field: string, value: Literal): Predicate => compare(\"lte\", field, value);\n\n/** `field IN (values)`: unknown on a NULL or absent field; an empty list matches no row. */\nexport const isIn = (field: string, values: ReadonlyArray<Literal>): Predicate => ({\n _tag: \"In\",\n field,\n values,\n});\n\n/** `field NOT IN (values)`: SQL's `x <> a AND x <> b`, unknown on a NULL field. */\nexport const notIn = (field: string, values: ReadonlyArray<Literal>): Predicate => ({\n _tag: \"NotIn\",\n field,\n values,\n});\n\n/** Conjunction (three-valued); a single predicate is returned unchanged. */\nexport const and = (...predicates: ReadonlyArray<Predicate>): Predicate => {\n const only = predicates[0];\n return predicates.length === 1 && only !== undefined ? only : { _tag: \"And\", predicates };\n};\n\n/** Disjunction (three-valued); a single predicate is returned unchanged. */\nexport const or = (...predicates: ReadonlyArray<Predicate>): Predicate => {\n const only = predicates[0];\n return predicates.length === 1 && only !== undefined ? only : { _tag: \"Or\", predicates };\n};\n\n/** Negation (three-valued: `not` of unknown stays unknown). */\nexport const not = (predicate: Predicate): Predicate => ({ _tag: \"Not\", predicate });\n\n/**\n * A correlated relationship test: this row matches if a row exists in\n * `collection` where `where` holds and `foreignField` equals this row's\n * `localField`. Resolved server-side by a backend (`resolveExists`).\n */\nexport const exists = (options: {\n readonly collection: string;\n readonly localField: string;\n readonly foreignField: string;\n readonly where?: Predicate;\n}): Predicate => ({\n _tag: \"Exists\",\n collection: options.collection,\n localField: options.localField,\n foreignField: options.foreignField,\n where: options.where ?? always,\n});\n\n/**\n * `field IN set(name)`: membership in a named, session-resolved set (#205).\n * The predicate refers to the set by name; the sync server binds it to the\n * values the set's resolver produced ({@link bindSets}). Server-authored only.\n */\nexport const inSet = (field: string, set: string): Predicate => ({ _tag: \"InSet\", field, set });\n\n// ─── Ordering ────────────────────────────────────────────────────────────────\n\n/**\n * Compare two strings by Unicode code point (ADR-0028 rule (c)): the order\n * of Postgres `COLLATE \"C\"` (UTF-8 bytes) and SQLite `BINARY`. JS `<`\n * compares UTF-16 code units, which diverges only where an astral character\n * (a surrogate pair, U+10000 and above) meets U+E000–U+FFFF. Walks the two\n * strings code point by code point without allocating; a lone surrogate\n * compares as its own code unit, exactly like iterating `Array.from(s)`.\n */\nexport const compareText = (a: string, b: string): number => {\n let i = 0;\n while (i < a.length && i < b.length) {\n const x = a.codePointAt(i) ?? 0;\n const y = b.codePointAt(i) ?? 0;\n if (x !== y) return x < y ? -1 : 1;\n i += x > 0xffff ? 2 : 1;\n }\n return i < a.length ? 1 : i < b.length ? -1 : 0;\n};\n\n/**\n * Order two same-typed literals: numbers numerically, text by code point,\n * booleans `false < true` (ADR-0028 section 3). `undefined` when the operands\n * are not of one comparable type — the \"type mismatch\" of rule (d).\n */\nexport const compareLiterals = (left: unknown, right: unknown): number | undefined => {\n if (typeof left !== typeof right) return undefined;\n switch (typeof left) {\n case \"number\":\n return numericOrder(left, right as number);\n case \"string\":\n return compareText(left, right as string);\n case \"boolean\":\n return numericOrder(Number(left), Number(right));\n default:\n return undefined;\n }\n};\n\nconst numericOrder = (left: number, right: number): number =>\n left < right ? -1 : left > right ? 1 : 0;\n\n/**\n * Whether a comparison operator holds for an ordering result (`-1`, `0`,\n * `1`) from {@link compareLiterals}: the per-operator table of ADR-0028\n * section 3 in one place, shared by `evaluate` and `CollectionIndex`.\n */\nexport const holds = (op: Comparison, ordered: number): boolean => {\n switch (op) {\n case \"eq\":\n return ordered === 0;\n case \"ne\":\n return ordered !== 0;\n case \"gt\":\n return ordered > 0;\n case \"gte\":\n return ordered >= 0;\n case \"lt\":\n return ordered < 0;\n case \"lte\":\n return ordered <= 0;\n }\n};\n\n// ─── Evaluation ──────────────────────────────────────────────────────────────\n\n/**\n * Top-level field access on a row value: `undefined` for a non-object row or\n * an absent field, `null` for an explicit null. Evaluation treats the two\n * alike (ADR-0028 rule (b): absent ≡ NULL); accelerated evaluators\n * (`CollectionIndex.ts`) read fields with exactly this function so they bucket\n * the same way `evaluate` does.\n */\nexport const fieldValue = (row: unknown, field: string): unknown =>\n P.isObjectOrArray(row) ? (row as Record<string, unknown>)[field] : undefined;\n\n/** Whether a field value is NULL for evaluation: an explicit `null` or absent. */\nexport const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined;\n\nconst TRUE: Option.Option<boolean> = Option.some(true);\nconst FALSE: Option.Option<boolean> = Option.some(false);\nconst UNKNOWN: Option.Option<boolean> = Option.none();\n\nconst definite = (value: boolean): Option.Option<boolean> => (value ? TRUE : FALSE);\n\ntype CompareNode = Extract<Predicate, { readonly _tag: \"Compare\" }>;\n\n/** `Compare`: unknown on a NULL field, a `null` literal or a type mismatch; else the operator. */\nconst evaluateCompare = (predicate: CompareNode, row: unknown): Option.Option<boolean> => {\n const left = fieldValue(row, predicate.field);\n if (isNullish(left) || predicate.value === null) return UNKNOWN;\n const ordered = compareLiterals(left, predicate.value);\n return ordered === undefined ? UNKNOWN : definite(holds(predicate.op, ordered));\n};\n\n/**\n * `In` / `NotIn` over a present field and a non-empty list: `Some(onMatch)`\n * on a match; unknown when no listed literal matches and one of them is\n * `null`, or when no listed literal has the field's type (rule (d), so\n * `Not(In)` and `Not(eq)` agree on a mismatch); else `Some(!onMatch)`.\n */\nconst membership = (\n left: unknown,\n values: ReadonlyArray<Literal>,\n onMatch: boolean\n): Option.Option<boolean> => {\n if (values.includes(left as Literal)) return definite(onMatch);\n if (values.includes(null)) return UNKNOWN;\n if (!values.some((value) => compareLiterals(left, value) !== undefined)) return UNKNOWN;\n return definite(!onMatch);\n};\n\n/**\n * `In` (`onMatch` true) / `NotIn` (`onMatch` false). An empty list is\n * definite before the field is even read: SQL has no `x IN ()`, and the\n * compilers render it as `1 = 0` / `1 = 1`, which is false / true for a NULL\n * row too. The harness pins this.\n */\nconst evaluateMembership = (\n field: string,\n values: ReadonlyArray<Literal>,\n onMatch: boolean,\n row: unknown\n): Option.Option<boolean> => {\n if (Arr.isReadonlyArrayEmpty(values)) return definite(!onMatch);\n const left = fieldValue(row, field);\n return isNullish(left) ? UNKNOWN : membership(left, values, onMatch);\n};\n\n/** Kleene `And`: `Some(false)` if any operand is, else unknown if any is, else `Some(true)`. */\nconst evaluateAnd = (\n predicates: ReadonlyArray<Predicate>,\n row: unknown\n): Option.Option<boolean> => {\n let unknown = false;\n for (const inner of predicates) {\n const result = evaluate(inner, row);\n if (Option.isNone(result)) unknown = true;\n else if (!result.value) return FALSE;\n }\n return unknown ? UNKNOWN : TRUE;\n};\n\n/** Kleene `Or`: `Some(true)` if any operand is, else unknown if any is, else `Some(false)`. */\nconst evaluateOr = (predicates: ReadonlyArray<Predicate>, row: unknown): Option.Option<boolean> => {\n let unknown = false;\n for (const inner of predicates) {\n const result = evaluate(inner, row);\n if (Option.isNone(result)) unknown = true;\n else if (result.value) return TRUE;\n }\n return unknown ? UNKNOWN : FALSE;\n};\n\n/** Kleene `Not`, over the shared constants rather than `Option.map`: no allocation per row. */\nconst negate = (inner: Option.Option<boolean>): Option.Option<boolean> =>\n Option.isNone(inner) ? UNKNOWN : inner.value ? FALSE : TRUE;\n\n/**\n * Evaluate a predicate against a row value under Postgres's three-valued\n * semantics (ADR-0028 section 3). `Some(true)` / `Some(false)` are definite;\n * `None` is unknown (a NULL got involved). Per node:\n *\n * - `True` → `Some(true)`.\n * - `Compare` → unknown if the field is NULL/absent or the literal is `null`;\n * else the comparison over same-typed operands (numbers numerically, text\n * by code point, booleans `false < true`); a type mismatch is unknown.\n * - `In` → `Some(false)` on an empty list (definite even for a NULL field:\n * the compilers render it `1 = 0`); else unknown if the field is NULL;\n * `Some(true)` on a match; unknown if no match and a listed literal is\n * `null` or none has the field's type; else `Some(false)`.\n * - `NotIn` → the same with `true`/`false` swapped (`x <> a AND x <> b`;\n * empty list `Some(true)`, `1 = 1`).\n * - `IsNull` → always definite: `Some(field is NULL)`, flipped by `negated`.\n * - `And` / `Or` / `Not` → Kleene's tables, written by hand: `And` is\n * `Some(false)` if any operand is, else unknown if any operand is, else\n * `Some(true)`; `Or` is the dual; `Not` maps over the option. Deliberately\n * not `Option.all`/`zipWith`, which would make unknown absorbing.\n * - `Exists` → `Some(true)`. It is relational and can't be decided from one\n * row: a backend resolves it to an `In` before evaluation (`resolveExists`),\n * and on the client the rows were already narrowed by the server.\n * - `InSet` → `Some(false)`: an unbound named set is the empty set (#205).\n * The sync server binds every one before evaluation ({@link bindSets}).\n */\nexport const evaluate = (predicate: Predicate, row: unknown): Option.Option<boolean> => {\n switch (predicate._tag) {\n case \"True\":\n case \"Exists\":\n return TRUE;\n case \"Compare\":\n return evaluateCompare(predicate, row);\n case \"InSet\":\n return FALSE;\n case \"In\":\n return evaluateMembership(predicate.field, predicate.values, true, row);\n case \"NotIn\":\n return evaluateMembership(predicate.field, predicate.values, false, row);\n case \"IsNull\":\n return definite(isNullish(fieldValue(row, predicate.field)) !== (predicate.negated === true));\n case \"And\":\n return evaluateAnd(predicate.predicates, row);\n case \"Or\":\n return evaluateOr(predicate.predicates, row);\n case \"Not\":\n return negate(evaluate(predicate.predicate, row));\n }\n};\n\n/**\n * Whether a row satisfies a predicate: the SQL `WHERE` collapse of\n * {@link evaluate} — `true` iff the result is `Some(true)`, so an unknown\n * (a NULL or absent field under `ne`, `NotIn`, `Not(eq)`, …) never matches.\n */\nexport const test = (predicate: Predicate, row: unknown): boolean =>\n Option.getOrElse(evaluate(predicate, row), () => false);\n\n/**\n * Rewrite every `Exists` node to an `In` over its `localField`, using `resolve`\n * to materialize the matching `foreignField` values from the related\n * collection. Backends call this before evaluation, turning a correlated join\n * into a flat, locally-evaluable predicate (an allow-set).\n */\nexport const resolveExists = <E, R>(\n predicate: Predicate,\n resolve: (node: ExistsNode) => Effect.Effect<ReadonlyArray<Literal>, E, R>\n): Effect.Effect<Predicate, E, R> => {\n switch (predicate._tag) {\n case \"Exists\":\n return resolve(predicate).pipe(Effect.map((values) => isIn(predicate.localField, values)));\n case \"And\":\n return Effect.forEach(predicate.predicates, (p) => resolveExists(p, resolve)).pipe(\n Effect.map((predicates) => and(...predicates))\n );\n case \"Or\":\n return Effect.forEach(predicate.predicates, (p) => resolveExists(p, resolve)).pipe(\n Effect.map((predicates) => or(...predicates))\n );\n case \"Not\":\n return resolveExists(predicate.predicate, resolve).pipe(Effect.map(not));\n case \"True\":\n case \"Compare\":\n case \"In\":\n case \"NotIn\":\n case \"IsNull\":\n case \"InSet\":\n return Effect.succeed(predicate);\n }\n};\n\n/**\n * The distinct `foreignField` values among rows matching an Exists `where`.\n * NULL and absent values are left out: NULL equals nothing, so a related row\n * without the field can never satisfy the correlation (ADR-0028 rule (b)).\n */\nexport const existsValues = (node: ExistsNode, rows: Iterable<unknown>): ReadonlyArray<Literal> => {\n const values = new Set<Literal>();\n for (const row of rows) {\n if (!test(node.where, row)) continue;\n const value = fieldValue(row, node.foreignField);\n if (!isNullish(value)) values.add(value as Literal);\n }\n return [...values];\n};\n\n/** Whether a predicate contains any (unresolved) `Exists` node. */\nexport const hasExists = (predicate: Predicate): boolean => {\n switch (predicate._tag) {\n case \"Exists\":\n return true;\n case \"And\":\n case \"Or\":\n return predicate.predicates.some(hasExists);\n case \"Not\":\n return hasExists(predicate.predicate);\n case \"True\":\n case \"Compare\":\n case \"In\":\n case \"NotIn\":\n case \"IsNull\":\n case \"InSet\":\n return false;\n }\n};\n\n// ─── Named sets (#205) ───────────────────────────────────────────────────────\n\n/** The sets a predicate's `InSet` nodes refer to, by name, with repeats. */\nconst setsIn = (node: Predicate): ReadonlyArray<string> =>\n Match.valueTags(node, {\n InSet: (branch): ReadonlyArray<string> => [branch.set],\n And: (branch) => branch.predicates.flatMap(setsIn),\n Or: (branch) => branch.predicates.flatMap(setsIn),\n Not: (branch) => setsIn(branch.predicate),\n Exists: (branch) => setsIn(branch.where),\n True: () => [],\n Compare: () => [],\n In: () => [],\n NotIn: () => [],\n IsNull: () => [],\n });\n\n/** The names of the sets a predicate's `InSet` nodes refer to, each once. */\nexport const setNames = (predicate: Predicate): ReadonlyArray<string> =>\n Arr.dedupe(setsIn(predicate));\n\n/**\n * Bind every `InSet` node to its resolved values: `InSet(field, name)`\n * becomes `In(field, values)`. A name with no binding — its resolver failed,\n * or it was never declared — **narrows, never widens** (ADR-0015 amendment,\n * rule 5): it becomes the empty `In` (false) where it occurs positively, and\n * `True` under an odd number of `Not`s, so the negation around it is false.\n * Either way that branch admits no row, and the predicate's other branches\n * still apply.\n */\nexport const bindSets = (\n predicate: Predicate,\n bindings: HashMap.HashMap<string, ReadonlyArray<Literal>>\n): Predicate => {\n const bind = (node: Predicate, negated: boolean): Predicate =>\n Match.valueTags(node, {\n InSet: (branch): Predicate =>\n Option.match(HashMap.get(bindings, branch.set), {\n onSome: (values) => isIn(branch.field, values),\n onNone: () => (negated ? always : isIn(branch.field, [])),\n }),\n And: (branch): Predicate => ({\n _tag: \"And\",\n predicates: branch.predicates.map((inner) => bind(inner, negated)),\n }),\n Or: (branch): Predicate => ({\n _tag: \"Or\",\n predicates: branch.predicates.map((inner) => bind(inner, negated)),\n }),\n Not: (branch): Predicate => not(bind(branch.predicate, !negated)),\n Exists: (branch): Predicate => ({ ...branch, where: bind(branch.where, negated) }),\n True: (leaf): Predicate => leaf,\n Compare: (leaf): Predicate => leaf,\n In: (leaf): Predicate => leaf,\n NotIn: (leaf): Predicate => leaf,\n IsNull: (leaf): Predicate => leaf,\n });\n return Arr.isReadonlyArrayEmpty(setNames(predicate)) ? predicate : bind(predicate, false);\n};\n","/**\n * CollectionIndex\n *\n * Secondary field-value indexes over a collection's confirmed rows (issue\n * #113): a hash index answers `eq`/`In`/`IsNull` and an ordered index answers\n * range `Compare`s, so a subset's `where` resolves against `O(hits)`\n * candidates instead of a full collection scan. Purely in-memory\n * acceleration — never the source of truth (the confirmed rows in\n * `ClientStore` are) — rebuilt from a full snapshot (`rebuild`) or maintained\n * incrementally from the same row deltas the engine's change hub already\n * carries (`upsertRow`/`deleteRow`/`clear`).\n *\n * `evaluate` is the planner in front of `Subset.apply`'s full-scan filter: it\n * decomposes a predicate's top-level `And` conjuncts, narrows via the index\n * for every indexable one (`eq`/`In` on a hash-indexed field, `IsNull`, range\n * `Compare`s on an ordered one), intersects the hits, and runs the residual\n * (non-indexable) conjuncts through `Predicate.test` over just those\n * candidates. A predicate with no indexable conjunct returns `undefined` —\n * the caller's cue to fall back to the full scan.\n *\n * Semantics match `Predicate.evaluate` exactly (ADR-0028), which is what the\n * property test proves over the differential corpus: NULL and absent rows\n * share one bucket (rule (b)) that no `eq`/`In`/range lookup ever returns —\n * every such comparison is unknown on a NULL field, and unknown never\n * matches — and that `IsNull` reads directly; a `Compare` with a `null`\n * literal narrows to the empty set (unknown for every row); range lookups\n * consult only same-typed rows (a number index for a number literal, a string\n * index for a string literal, the two boolean buckets for a boolean literal),\n * mirroring rule (d)'s unknown on a type mismatch; sorted runs order text by\n * code point (rule (c)). `ne`, `NotIn` and `IS NOT NULL` do not narrow — each\n * is the complement of a bucket plus three-valued handling — so they stay\n * residual conjuncts, evaluated by `Predicate.test` over the candidates.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as P from \"effect/Predicate\";\nimport type { RowId } from \"./Collection.js\";\nimport * as Predicate from \"./Predicate.js\";\n\n/** One sorted entry in a range index: value plus the row id it belongs to. */\ninterface SortedEntry {\n readonly value: number | string;\n readonly id: RowId;\n}\n\n/** A single indexed field: hash buckets plus type-partitioned sorted runs for range queries. */\ninterface FieldIndex {\n readonly field: string;\n /** Exact non-null value → row ids. */\n readonly byValue: Map<unknown, Set<RowId>>;\n /** Rows whose field is NULL or absent — one bucket, per ADR-0028 rule (b). */\n readonly nulls: Set<RowId>;\n /** Rows whose value is a `number`, sorted ascending (value, then id). */\n readonly numbers: Array<SortedEntry>;\n /** Rows whose value is a `string`, sorted ascending by code point (value, then id). */\n readonly strings: Array<SortedEntry>;\n /** Each indexed row's last-seen raw field value, so an update/delete finds its old bucket. */\n readonly current: Map<RowId, unknown>;\n}\n\n/** A collection's secondary index: one {@link FieldIndex} per declared/auto-discovered field. */\nexport interface CollectionIndex {\n readonly fields: ReadonlyMap<string, FieldIndex>;\n}\n\nconst EMPTY_IDS: ReadonlySet<RowId> = new Set();\n\nconst emptyField = (field: string): FieldIndex => ({\n field,\n byValue: new Map(),\n nulls: new Set(),\n numbers: [],\n strings: [],\n current: new Map(),\n});\n\n/** Build an empty index over the given field names. */\nexport const empty = (fields: Iterable<string>): CollectionIndex => ({\n fields: new Map([...fields].map((field) => [field, emptyField(field)])),\n});\n\n/** The field names this index covers. */\nexport const fieldNames = (index: CollectionIndex): ReadonlySet<string> =>\n new Set(index.fields.keys());\n\n// ─── Ordered maintenance (binary search insert/remove/range) ────────────────\n\n/** Order two sorted-run values; each run holds one type, so `compareLiterals` always answers. */\nconst valueOrder = (a: number | string, b: number | string): number =>\n Predicate.compareLiterals(a, b) ?? 0;\n\nconst entryOrder = (a: SortedEntry, b: SortedEntry): number => {\n const byValue = valueOrder(a.value, b.value);\n return byValue !== 0 ? byValue : Predicate.compareText(a.id, b.id);\n};\n\nconst lowerBoundOf = (arr: ReadonlyArray<SortedEntry>, probe: SortedEntry): number => {\n let lo = 0;\n let hi = arr.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = arr[mid];\n if (entry !== undefined && entryOrder(entry, probe) < 0) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst insertSorted = (arr: Array<SortedEntry>, entry: SortedEntry): void => {\n arr.splice(lowerBoundOf(arr, entry), 0, entry);\n};\n\nconst removeSorted = (arr: Array<SortedEntry>, entry: SortedEntry): void => {\n const at = lowerBoundOf(arr, entry);\n const found = arr[at];\n if (found !== undefined && found.value === entry.value && found.id === entry.id) {\n arr.splice(at, 1);\n }\n};\n\n/** First index whose value is `>= value` (or `> value` when `strict`). */\nconst lowerBoundValue = (\n arr: ReadonlyArray<SortedEntry>,\n value: number | string,\n strict: boolean\n): number => {\n let lo = 0;\n let hi = arr.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n const entry = arr[mid];\n const ordered = entry === undefined ? 1 : valueOrder(entry.value, value);\n if (strict ? ordered <= 0 : ordered < 0) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n};\n\nconst rangeIds = (\n arr: ReadonlyArray<SortedEntry>,\n op: Predicate.Comparison,\n value: number | string\n): ReadonlySet<RowId> => {\n let start = 0;\n let end = arr.length;\n switch (op) {\n case \"gt\":\n start = lowerBoundValue(arr, value, true);\n break;\n case \"gte\":\n start = lowerBoundValue(arr, value, false);\n break;\n case \"lt\":\n end = lowerBoundValue(arr, value, false);\n break;\n case \"lte\":\n end = lowerBoundValue(arr, value, true);\n break;\n default:\n return EMPTY_IDS;\n }\n const ids = new Set<RowId>();\n for (let i = start; i < end; i++) {\n const entry = arr[i];\n if (entry !== undefined) ids.add(entry.id);\n }\n return ids;\n};\n\n// ─── Field-index maintenance ─────────────────────────────────────────────────\n\nconst unindexField = (fi: FieldIndex, id: RowId): void => {\n if (!fi.current.has(id)) return;\n const old = fi.current.get(id);\n if (Predicate.isNullish(old)) {\n fi.nulls.delete(id);\n } else {\n const bucket = fi.byValue.get(old);\n if (bucket !== undefined) {\n bucket.delete(id);\n if (bucket.size === 0) fi.byValue.delete(old);\n }\n if (P.isNumber(old)) removeSorted(fi.numbers, { value: old, id });\n else if (P.isString(old)) removeSorted(fi.strings, { value: old, id });\n }\n fi.current.delete(id);\n};\n\nconst indexField = (fi: FieldIndex, id: RowId, rowValue: unknown): void => {\n unindexField(fi, id);\n const raw = Predicate.fieldValue(rowValue, fi.field);\n fi.current.set(id, raw);\n if (Predicate.isNullish(raw)) {\n fi.nulls.add(id);\n return;\n }\n const bucket = fi.byValue.get(raw);\n if (bucket === undefined) fi.byValue.set(raw, new Set([id]));\n else bucket.add(id);\n if (P.isNumber(raw)) insertSorted(fi.numbers, { value: raw, id });\n else if (P.isString(raw)) insertSorted(fi.strings, { value: raw, id });\n};\n\nconst clearField = (fi: FieldIndex): void => {\n fi.byValue.clear();\n fi.nulls.clear();\n fi.numbers.length = 0;\n fi.strings.length = 0;\n fi.current.clear();\n};\n\n// ─── Collection-level maintenance ────────────────────────────────────────────\n\n/** Index (or re-index) one row across every field this index covers. */\nexport const upsertRow = (index: CollectionIndex, id: RowId, value: unknown): void => {\n for (const fi of index.fields.values()) indexField(fi, id, value);\n};\n\n/** Remove one row from every field this index covers. */\nexport const deleteRow = (index: CollectionIndex, id: RowId): void => {\n for (const fi of index.fields.values()) unindexField(fi, id);\n};\n\n/** Drop every indexed row (a `Clear` patch op, or the prelude to {@link rebuild}). */\nexport const clear = (index: CollectionIndex): void => {\n for (const fi of index.fields.values()) clearField(fi);\n};\n\n/** Rebuild the index from a full row snapshot (boot, `Rebuild`, store-version bust). */\nexport const rebuild = (\n index: CollectionIndex,\n rows: Iterable<{ readonly id: RowId; readonly value: unknown }>\n): void => {\n clear(index);\n for (const row of rows) upsertRow(index, row.id, row.value);\n};\n\n// ─── Planning ────────────────────────────────────────────────────────────────\n\n/** A narrowed candidate set plus the predicate still to test over it. */\nexport interface Plan {\n readonly candidateIds: ReadonlySet<RowId>;\n readonly residual: Predicate.Predicate;\n}\n\n/** The rows holding exactly `value`; a `null` literal matches no row (unknown everywhere). */\nconst hashLookup = (fi: FieldIndex, value: Predicate.Literal): ReadonlySet<RowId> =>\n value === null ? EMPTY_IDS : (fi.byValue.get(value) ?? EMPTY_IDS);\n\nconst hashLookupIn = (\n fi: FieldIndex,\n values: ReadonlyArray<Predicate.Literal>\n): ReadonlySet<RowId> => {\n if (Arr.isReadonlyArrayEmpty(values)) return EMPTY_IDS;\n const ids = new Set<RowId>();\n for (const value of values) for (const id of hashLookup(fi, value)) ids.add(id);\n return ids;\n};\n\n/**\n * A range `Compare` against a boolean literal, from the two boolean buckets:\n * Postgres orders `false < true` (ADR-0028 section 3), so the matching side\n * is whichever of the two values the operator admits.\n */\nconst booleanRangeIds = (\n fi: FieldIndex,\n op: Predicate.Comparison,\n value: boolean\n): ReadonlySet<RowId> =>\n hashLookupIn(\n fi,\n [false, true].filter((candidate) =>\n Predicate.holds(op, Predicate.compareLiterals(candidate, value) ?? 0)\n )\n );\n\ntype CompareNode = Extract<Predicate.Predicate, { readonly _tag: \"Compare\" }>;\n\n/** The ids a `Compare` conjunct narrows to on an indexed field, or `undefined` for `ne`. */\nconst compareIds = (fi: FieldIndex, conjunct: CompareNode): ReadonlySet<RowId> | undefined => {\n if (conjunct.op === \"ne\") return undefined; // complement of a bucket isn't narrowing\n if (conjunct.value === null) return EMPTY_IDS; // unknown for every row (ADR-0028 §5)\n if (conjunct.op === \"eq\") return hashLookup(fi, conjunct.value);\n if (P.isNumber(conjunct.value)) return rangeIds(fi.numbers, conjunct.op, conjunct.value);\n if (P.isString(conjunct.value)) return rangeIds(fi.strings, conjunct.op, conjunct.value);\n return booleanRangeIds(fi, conjunct.op, conjunct.value);\n};\n\n/** Apply `narrow` to the field's index when the field is indexed; `undefined` otherwise. */\nconst onField = (\n index: CollectionIndex,\n field: string,\n narrow: (fi: FieldIndex) => ReadonlySet<RowId> | undefined\n): ReadonlySet<RowId> | undefined => {\n const fi = index.fields.get(field);\n return fi === undefined ? undefined : narrow(fi);\n};\n\n/**\n * The narrowed id set an indexable conjunct yields, or `undefined` when it\n * can't narrow. Only `Compare`, `In` and a non-negated `IsNull` narrow; every\n * other node (`NotIn`, `Not`, `Or`, …) is residual by default, which is also\n * the safe answer for any node added later.\n */\nconst conjunctIds = (\n index: CollectionIndex,\n conjunct: Predicate.Predicate\n): ReadonlySet<RowId> | undefined => {\n switch (conjunct._tag) {\n case \"Compare\":\n return onField(index, conjunct.field, (fi) => compareIds(fi, conjunct));\n case \"In\":\n return onField(index, conjunct.field, (fi) => hashLookupIn(fi, conjunct.values));\n case \"IsNull\":\n // `IS NOT NULL` is the complement of a bucket: not narrowing.\n return conjunct.negated === true\n ? undefined\n : onField(index, conjunct.field, (fi) => fi.nulls);\n default:\n return undefined;\n }\n};\n\nconst intersect = (sets: ReadonlyArray<ReadonlySet<RowId>>): ReadonlySet<RowId> => {\n const bySize = sets.toSorted((a, b) => a.size - b.size);\n const [smallest, ...rest] = bySize;\n if (smallest === undefined) return EMPTY_IDS;\n if (Arr.isReadonlyArrayEmpty(rest)) return smallest;\n const result = new Set<RowId>();\n for (const id of smallest) {\n if (rest.every((set) => set.has(id))) result.add(id);\n }\n return result;\n};\n\n/**\n * Plan a predicate's evaluation against this index: decompose top-level `And`\n * conjuncts, narrow every indexable one, and intersect. Returns `undefined`\n * when no conjunct narrows — the caller's cue to fall back to a full scan.\n */\nexport const plan = (index: CollectionIndex, predicate: Predicate.Predicate): Plan | undefined => {\n const conjuncts = predicate._tag === \"And\" ? predicate.predicates : [predicate];\n const narrowing: Array<ReadonlySet<RowId>> = [];\n const residual: Array<Predicate.Predicate> = [];\n for (const conjunct of conjuncts) {\n const ids = conjunctIds(index, conjunct);\n if (ids === undefined) residual.push(conjunct);\n else narrowing.push(ids);\n }\n if (Arr.isReadonlyArrayEmpty(narrowing)) return undefined;\n return {\n candidateIds: intersect(narrowing),\n residual: Arr.isReadonlyArrayEmpty(residual) ? Predicate.always : Predicate.and(...residual),\n };\n};\n\n/**\n * Evaluate a predicate against `rowsById` using the index: `undefined` when\n * the predicate has no indexable conjunct (full-scan fallback), otherwise the\n * exact rows `rowsById` values filtered by `predicate` would yield — just\n * computed from `O(hits)` candidates instead of every row.\n */\nexport const evaluate = <R extends { readonly id: RowId; readonly value: unknown }>(\n index: CollectionIndex,\n rowsById: ReadonlyMap<RowId, R>,\n predicate: Predicate.Predicate\n): ReadonlyArray<R> | undefined => {\n const found = plan(index, predicate);\n if (found === undefined) return undefined;\n const results: Array<R> = [];\n for (const id of found.candidateIds) {\n const row = rowsById.get(id);\n if (row !== undefined && Predicate.test(found.residual, row.value)) results.push(row);\n }\n return results;\n};\n","/**\n * Subset\n *\n * A collection subset — `(collection, where, orderBy, limit, cursor)` — is\n * the subscription unit of the protocol (CONTEXT.md): the thing a client\n * registers with the server, the thing auth filters narrow, and the thing a\n * CVR tracks. Live queries reuse the same shape locally.\n *\n * This module is the plan-compiler's vocabulary — what a {@link Query}'s\n * read compiles to. Most callers should use {@link Query} instead; hand-built\n * subsets are for low-level protocol and backend work.\n */\n\nimport * as Schema from \"effect/Schema\";\nimport type { AnyCollection, RowOf } from \"./Collection.js\";\nimport * as Index from \"./CollectionIndex.js\";\nimport * as Predicate from \"./Predicate.js\";\n\n/** Sort direction. */\nexport type Direction = \"asc\" | \"desc\";\n\n/** Wire codec for one sort term: a top-level row field plus direction. */\nexport const OrderBy = Schema.Struct({\n field: Schema.String,\n direction: Schema.Literals([\"asc\", \"desc\"]),\n});\n\n/** One sort term: a top-level row field plus direction. */\nexport type OrderBy = typeof OrderBy.Type;\n\n/** Parse order tokens (`\"name\"`, `\"-createdAt\"`) into sort terms. */\nexport const parseOrder = (tokens: ReadonlyArray<string> | undefined): ReadonlyArray<OrderBy> =>\n (tokens ?? []).map((token) =>\n token.startsWith(\"-\")\n ? { field: token.slice(1), direction: \"desc\" as const }\n : { field: token, direction: \"asc\" as const }\n );\n\n/**\n * Wire codec for {@link Subset}. The schema is the source of truth: the\n * `Subset` type is derived from it (`typeof Subset.Type`) so the two\n * cannot drift.\n */\nexport const Subset = Schema.Struct({\n collection: Schema.String,\n where: Predicate.PredicateSchema,\n orderBy: Schema.Array(OrderBy),\n limit: Schema.optional(Schema.Number),\n /** Opaque continuation: sync rows ordered after this cursor. */\n cursor: Schema.optional(Schema.String),\n});\n\n/**\n * A collection subset. `limit` + `cursor` give cursor-based pagination:\n * \"load more\" widens the subset (re-register with a larger limit or a\n * cursor at the last row) rather than fetching detached pages.\n */\nexport type Subset = typeof Subset.Type;\n\n/** Define a subset; `where` defaults to the whole collection. */\nexport const make = (options: {\n readonly collection: string;\n readonly where?: Predicate.Predicate;\n readonly orderBy?: ReadonlyArray<OrderBy>;\n readonly limit?: number;\n readonly cursor?: string;\n}): Subset => ({\n collection: options.collection,\n where: options.where ?? Predicate.always,\n orderBy: options.orderBy ?? [],\n limit: options.limit,\n cursor: options.cursor,\n});\n\n/** Stable identity for a subset (used as CVR / subscription map keys). */\nexport const hash = (subset: Subset): string => JSON.stringify(subset);\n\n// ─── Typed builder ─────────────────────────────────────────────────────────────\n//\n// A compile-time layer over the untyped `make`: field names and literal types\n// are checked against a collection's row type, but the value erases to a plain\n// `Subset` at runtime (the phantom `_row` is never present). The untyped\n// surface stays the primitive — this is purely additive (ADR-0006).\n\n/**\n * A {@link Subset} carrying its row type as a phantom. Erases to a plain\n * `Subset` at runtime; `_row` is never actually set. A `TypedSubset<A>` is a\n * `Subset` wherever one is expected, so it flows through the untyped protocol\n * surface unchanged while typed reads (`ClientEngine.query`/`observe`) refine\n * their result to `A`.\n */\nexport interface TypedSubset<A> extends Subset {\n readonly _row?: A;\n}\n\n/**\n * Field-checked predicate constructors for a row type `A`: each mirrors the\n * matching untyped constructor in {@link Predicate}, but the field must be a\n * key of `A` and the literal must match the field's type. Composition\n * (`and`/`or`/`not`) and `always` are passed through unchanged.\n */\nexport interface TypedPredicate<A> {\n eq<K extends keyof A & string>(field: K, value: A[K]): Predicate.Predicate;\n ne<K extends keyof A & string>(field: K, value: A[K]): Predicate.Predicate;\n gt<K extends keyof A & string>(field: K, value: A[K]): Predicate.Predicate;\n gte<K extends keyof A & string>(field: K, value: A[K]): Predicate.Predicate;\n lt<K extends keyof A & string>(field: K, value: A[K]): Predicate.Predicate;\n lte<K extends keyof A & string>(field: K, value: A[K]): Predicate.Predicate;\n in<K extends keyof A & string>(field: K, values: ReadonlyArray<A[K]>): Predicate.Predicate;\n notIn<K extends keyof A & string>(field: K, values: ReadonlyArray<A[K]>): Predicate.Predicate;\n isNull<K extends keyof A & string>(field: K): Predicate.Predicate;\n isNotNull<K extends keyof A & string>(field: K): Predicate.Predicate;\n and(...predicates: ReadonlyArray<Predicate.Predicate>): Predicate.Predicate;\n or(...predicates: ReadonlyArray<Predicate.Predicate>): Predicate.Predicate;\n not(predicate: Predicate.Predicate): Predicate.Predicate;\n readonly always: Predicate.Predicate;\n}\n\n/** One typed sort term: a field of the row type plus a direction. */\nexport interface TypedOrderBy<A> {\n readonly field: keyof A & string;\n readonly direction: Direction;\n}\n\n/** Options for {@link TypedSubsetBuilder.make}; mirrors the untyped `make`. */\nexport interface TypedSubsetOptions<A> {\n readonly where?: (p: TypedPredicate<A>) => Predicate.Predicate;\n readonly orderBy?: ReadonlyArray<TypedOrderBy<A>>;\n readonly limit?: number;\n readonly cursor?: string;\n}\n\n/** A subset builder bound to one collection's row type. */\nexport interface TypedSubsetBuilder<A> {\n readonly make: (options?: TypedSubsetOptions<A>) => TypedSubset<A>;\n}\n\n// The constructors are field-agnostic at runtime (the typing lives in the\n// interface), so one shared implementation serves every row type.\nconst typedPredicate: TypedPredicate<unknown> = {\n eq: (field, value) => Predicate.eq(field, value as Predicate.Literal),\n ne: (field, value) => Predicate.ne(field, value as Predicate.Literal),\n gt: (field, value) => Predicate.gt(field, value as Predicate.Literal),\n gte: (field, value) => Predicate.gte(field, value as Predicate.Literal),\n lt: (field, value) => Predicate.lt(field, value as Predicate.Literal),\n lte: (field, value) => Predicate.lte(field, value as Predicate.Literal),\n in: (field, values) => Predicate.isIn(field, values as ReadonlyArray<Predicate.Literal>),\n notIn: (field, values) => Predicate.notIn(field, values as ReadonlyArray<Predicate.Literal>),\n isNull: (field) => Predicate.isNull(field),\n isNotNull: (field) => Predicate.isNotNull(field),\n and: (...predicates) => Predicate.and(...predicates),\n or: (...predicates) => Predicate.or(...predicates),\n not: (predicate) => Predicate.not(predicate),\n always: Predicate.always,\n};\n\n/**\n * Bind a subset builder to a collection: field names and literal types in\n * `where`/`orderBy` are then checked against the collection's row type. The\n * returned `make` just calls the untyped {@link make} and re-types the result\n * as a {@link TypedSubset}.\n *\n * `for` is a reserved word as a bare identifier, so the function is named\n * `forCollection` and re-exported as `for`; both are usable (`Subset.for` reads\n * best on the namespace import).\n */\nexport const forCollection = <C extends AnyCollection>(\n collection: C\n): TypedSubsetBuilder<RowOf<C>> => ({\n make: (options) => {\n const where = options?.where?.(typedPredicate as TypedPredicate<RowOf<C>>);\n return make({\n collection: collection.name,\n ...(where !== undefined ? { where } : {}),\n ...(options?.orderBy !== undefined\n ? { orderBy: options.orderBy as ReadonlyArray<OrderBy> }\n : {}),\n ...(options?.limit !== undefined ? { limit: options.limit } : {}),\n ...(options?.cursor !== undefined ? { cursor: options.cursor } : {}),\n }) as TypedSubset<RowOf<C>>;\n },\n});\n\nexport { forCollection as for };\n\n/** A `(id, value)` row — the unit subsets and live views operate over. */\nexport interface Row {\n readonly id: string;\n readonly value: unknown;\n}\n\nconst fieldOf = Predicate.fieldValue;\n\n/**\n * Compare two field values ascending, as Postgres orders a column (ADR-0028\n * section 4): NULL and absent are one value greater than every non-null one\n * (so they sort last ascending and first descending, Postgres's default);\n * same-typed values order numerically, by code point, or `false < true`.\n * Values of differing types never meet on a declared column (rule (d)); to\n * keep the comparator total anyway they order by type name, then by their\n * string form.\n */\nconst compareValues = (left: unknown, right: unknown): number => {\n const leftNull = Predicate.isNullish(left);\n const rightNull = Predicate.isNullish(right);\n if (leftNull || rightNull) return leftNull === rightNull ? 0 : leftNull ? 1 : -1;\n const ordered = Predicate.compareLiterals(left, right);\n if (ordered !== undefined) return ordered;\n const byType = Predicate.compareText(typeof left, typeof right);\n return byType !== 0 ? byType : Predicate.compareText(String(left), String(right));\n};\n\n/**\n * A total-order comparator over *rows* for an `orderBy`: `orderBy`'s fields\n * first, then row id ascending as a tie-break. The id tie-break is what\n * makes this a genuine total order even for an empty `orderBy` (every row\n * would otherwise tie) — `LiveView` relies on that to locate a delta's row\n * in O(log n) instead of scanning every same-key row (issue #112). Stable\n * across the same `orderBy`, so it can both sort a set from scratch\n * (`sortFiltered`) and place one row incrementally (`LiveView`).\n *\n * This is also **the collation seam**. Its order is fixed by ADR-0028\n * section 4 to be Postgres's: text (the id tie-break included) compares by\n * code point, the order of `COLLATE \"C\"` and SQLite `BINARY`; NULL and\n * absent sort after every value ascending and before every value descending\n * (`NULLS LAST` / `NULLS FIRST`, Postgres's default); booleans order\n * `false < true`. The differential harness in `@thomasfosterau/legation/sql` proves this\n * comparator agrees with `ORDER BY … COLLATE \"C\"`. Every backend\n * (`MemoryBackend`, `@thomasfosterau/legation/sql`'s `SqlBackend`, `@thomasfosterau/legation-jsonapi`'s\n * `JsonApiBackend`) and the client (`LiveView`) call this one comparator, so\n * client and server agree on cursor windows by construction. There is no\n * locale-aware or case-insensitive collation, and none can be a client-local\n * `observe` option (ADR-0026): it would tear cursor pages against a server\n * assuming code-point order. If one is ever needed it must be declared on\n * the `Subset`/collection, wire-serialized, and threaded here on both sides.\n */\nexport const comparator =\n (orderBy: ReadonlyArray<OrderBy>) =>\n (a: Row, b: Row): number => {\n for (const term of orderBy) {\n const ordered = compareValues(fieldOf(a.value, term.field), fieldOf(b.value, term.field));\n if (ordered !== 0) return term.direction === \"asc\" ? ordered : -ordered;\n }\n return Predicate.compareText(a.id, b.id);\n };\n\n/** Filter rows by the subset's predicate and sort by its `orderBy` (no window). */\nexport const sortFiltered = <R extends Row>(\n rows: ReadonlyArray<R>,\n subset: Subset\n): ReadonlyArray<R> => {\n const filtered = rows.filter((row) => Predicate.test(subset.where, row.value));\n return filtered.toSorted(comparator(subset.orderBy));\n};\n\n/**\n * Apply the subset's window to already-filtered, already-sorted rows: cursor\n * (rows strictly after the row whose id equals the cursor) then limit.\n */\nexport const window = <R extends Row>(rows: ReadonlyArray<R>, subset: Subset): ReadonlyArray<R> => {\n let result = rows;\n if (subset.cursor !== undefined) {\n const index = result.findIndex((row) => row.id === subset.cursor);\n result = index >= 0 ? result.slice(index + 1) : result;\n }\n if (subset.limit !== undefined) result = result.slice(0, subset.limit);\n return result;\n};\n\n/**\n * Reference in-memory evaluation of a subset over `(id, value)` rows: filter,\n * sort, then window (cursor + limit). Used by the memory backend, the client\n * mirror, and as the semantics other backends must match.\n */\nexport const apply = <R extends Row>(rows: ReadonlyArray<R>, subset: Subset): ReadonlyArray<R> =>\n window(sortFiltered(rows, subset), subset);\n\n// ─── Indexed evaluation (issue #113) ─────────────────────────────────────────\n//\n// Same semantics as `sortFiltered`/`apply`, but over an id-keyed row map with\n// an optional `Index.CollectionIndex` in front of the filter step: an\n// indexable `where` resolves via `O(hits)` index lookups instead of testing\n// every row. A predicate the index can't narrow (or no index at all) falls\n// back to exactly the full scan — the index only ever accelerates\n// `Predicate.evaluate`, never changes its answer.\n\nconst fullScan = <R extends Row>(\n rowsById: ReadonlyMap<string, R>,\n where: Predicate.Predicate\n): Array<R> => {\n const result: Array<R> = [];\n for (const row of rowsById.values()) {\n if (Predicate.test(where, row.value)) result.push(row);\n }\n return result;\n};\n\n/** {@link sortFiltered}, but reading rows from an id-keyed map with optional index acceleration. */\nexport const sortFilteredIndexed = <R extends Row>(\n rowsById: ReadonlyMap<string, R>,\n subset: Subset,\n index?: Index.CollectionIndex\n): ReadonlyArray<R> => {\n const filtered =\n (index !== undefined ? Index.evaluate(index, rowsById, subset.where) : undefined) ??\n fullScan(rowsById, subset.where);\n return filtered.toSorted(comparator(subset.orderBy));\n};\n\n/** {@link apply}, but reading rows from an id-keyed map with optional index acceleration. */\nexport const applyIndexed = <R extends Row>(\n rowsById: ReadonlyMap<string, R>,\n subset: Subset,\n index?: Index.CollectionIndex\n): ReadonlyArray<R> => window(sortFilteredIndexed(rowsById, subset, index), subset);\n","/**\n * Related\n *\n * Read-side relationship resolution over the local mirror, resolved via the\n * field mappings a collection declares (`Collection.Relationship`). Once the\n * foreign collections are synced, a declared relationship name resolves to the\n * actual related row value(s) — a client-side join over already-synced data, no\n * extra request (issue #38).\n *\n * This is the protocol-agnostic core of the \"relationships / joins\" gap. The\n * incremental-join plumbing (base `observe` → target collections → per-collection\n * index → `switchMap` on linkage shift → dedup; auto-subscribe the narrowed\n * foreign subsets + scope teardown) is generic and parameterised by a\n * {@link Strategy}: a `targets` function (which foreign collection + which\n * `foreignField` values to pin) and a `resolveRow` function (how a base row's\n * relationships resolve against the per-collection index). Core supplies the\n * field-mapping strategy ({@link fieldMappingStrategy}); an adapter such as\n * `@thomasfosterau/legation-jsonapi` supplies its own linkage-based strategy and reuses the\n * same machinery via {@link queryWith}/{@link observeWith}/{@link relatedWith}.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Fiber from \"effect/Fiber\";\nimport * as P from \"effect/Predicate\";\nimport * as Queue from \"effect/Queue\";\nimport * as Ref from \"effect/Ref\";\nimport * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\nimport * as Collection from \"./Collection.js\";\nimport type { ClientEngine, LocalRow } from \"./ClientEngine.js\";\nimport type * as ClientView from \"./ClientView.js\";\nimport * as Predicate from \"./Predicate.js\";\nimport * as Subset from \"./Subset.js\";\n\n/** A resolved relationship: a row value, a list of them, `null`, or `undefined`. */\nexport type RelatedValue = LocalRow[\"value\"] | ReadonlyArray<LocalRow[\"value\"]> | null | undefined;\n\n/** A base row with its named relationships resolved against the mirror. */\nexport interface RelatedRow {\n readonly id: string;\n readonly value: unknown;\n readonly related: Record<string, RelatedValue>;\n}\n\n/**\n * The foreign rows a set of base rows pin in one collection: the `foreignField`\n * to match on, and the values it must take. Drives both which collection to\n * index and the narrowed subsets an auto-subscription registers — one\n * `foreignField IN (...)` subset, or with a {@link Target.window}, one windowed\n * `foreignField = value` subset **per value** (ADR-0024).\n */\nexport interface Target {\n readonly field: string;\n readonly ids: ReadonlySet<Predicate.Literal>;\n /**\n * The per-parent sync window a paginated edge declares: each pinned value\n * registers its own `(field = value, orderBy, limit)` subset, so the\n * replica syncs the window instead of the whole dependent collection.\n */\n readonly window?: {\n readonly orderBy: ReadonlyArray<Subset.OrderBy>;\n readonly limit: number;\n };\n}\n\n/**\n * One edge of a relational read: the relationship name, plus the read's\n * per-edge window (`first`) for paginated edges. A bare string selects the\n * edge unwindowed.\n */\nexport interface EdgeSelect {\n readonly name: string;\n readonly first?: number;\n}\n\n/** Normalize an edge selection input. */\nexport const edgeSelect = (input: string | EdgeSelect): EdgeSelect =>\n P.isString(input) ? { name: input } : input;\n\n/**\n * The per-collection lookup the plumbing maintains: for each targeted\n * collection, its current rows grouped by the pinned `foreignField` value. A\n * `resolveRow` strategy reads related rows out of it by the base row's join key.\n */\nexport type CollectionIndex = ReadonlyMap<\n string,\n ReadonlyMap<Predicate.Literal, ReadonlyArray<LocalRow>>\n>;\n\n/**\n * The resolution strategy the generic plumbing is parameterised by. `targets`\n * decides which foreign rows to pin (per collection, a `foreignField` + its\n * values); `resolveRow` turns the maintained {@link CollectionIndex} into a base\n * row's resolved relationships. Core's {@link fieldMappingStrategy} resolves via\n * declared field mappings; an adapter can supply a different extraction model\n * (e.g. JSON:API linkage) over the same machinery.\n */\nexport interface Strategy {\n readonly targets: (baseRows: ReadonlyArray<LocalRow>) => ReadonlyMap<string, Target>;\n readonly resolveRow: (index: CollectionIndex, baseRow: LocalRow) => Record<string, RelatedValue>;\n}\n\n// ─── Shared helpers ──────────────────────────────────────────────────────────\n\n/** Group a collection's rows by the value of one field (the pinned join key). */\nconst groupByField = (\n rows: ReadonlyArray<LocalRow>,\n field: string\n): Map<Predicate.Literal, ReadonlyArray<LocalRow>> => {\n const map = new Map<Predicate.Literal, Array<LocalRow>>();\n for (const row of rows) {\n const key = Predicate.fieldValue(row.value, field) as Predicate.Literal;\n const bucket = map.get(key);\n if (bucket === undefined) map.set(key, [row]);\n else bucket.push(row);\n }\n return map;\n};\n\n/** Two resolved relationship values are equal when they share row references. */\nconst sameRelated = (a: RelatedValue, b: RelatedValue): boolean => {\n if (a === b) return true;\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((row, i) => row === b[i]);\n }\n return false;\n};\n\n/** Two joins are equal when base rows and every resolved relationship match by reference. */\nconst sameJoin = (a: ReadonlyArray<RelatedRow>, b: ReadonlyArray<RelatedRow>): boolean =>\n a.length === b.length &&\n a.every((row, i) => {\n const other = b[i];\n if (other === undefined || row.id !== other.id || row.value !== other.value) return false;\n const names = Object.keys(row.related);\n return (\n names.length === Object.keys(other.related).length &&\n names.every((name) => sameRelated(row.related[name], other.related[name]))\n );\n });\n\n// ─── Field-mapping strategy ──────────────────────────────────────────────────\n\n/** The per-parent window a selected relationship pins, when it does. */\nconst windowOf = (\n relationship: Collection.Relationship & { readonly first?: number }\n): Target[\"window\"] | undefined =>\n relationship.kind === \"paginated\" &&\n relationship.first !== undefined &&\n relationship.order !== undefined &&\n Arr.isReadonlyArrayNonEmpty(relationship.order)\n ? { orderBy: relationship.order, limit: relationship.first }\n : undefined;\n\n/** Collect the non-null `localField` values a relationship pins. */\nconst pinIds = (\n ids: Set<Predicate.Literal>,\n baseRows: ReadonlyArray<LocalRow>,\n localField: string\n): void => {\n for (const row of baseRows) {\n const value = Predicate.fieldValue(row.value, localField);\n if (value !== undefined && value !== null) ids.add(value as Predicate.Literal);\n }\n};\n\n/**\n * A resolution strategy over declared field mappings: `targets` pins each\n * relationship's foreign collection by its `foreignField` and the base rows'\n * `localField` values; `resolveRow` looks each base row up in the index by its\n * `localField` value, yielding the single foreign row (`\"one\"`) or the array of\n * them (`\"many\"`).\n *\n * All relationships pointing at the same collection are expected to share a\n * `foreignField` (the usual case: `\"id\"` for `\"one\"`, one FK for `\"many\"`);\n * `targets` pins the collection by the first relationship's `foreignField`.\n *\n * A `\"paginated\"` relationship carrying a `first` pins a **windowed** target\n * (its declared order + the read's limit — ADR-0024). When two relationships\n * pin the same collection, the target falls back to the unwindowed superset:\n * sound, merely over-syncs.\n */\nexport const fieldMappingStrategy = (\n relationships: ReadonlyArray<Collection.Relationship & { readonly first?: number }>\n): Strategy => ({\n targets: (baseRows) => {\n const entries = new Map<\n string,\n { field: string; ids: Set<Predicate.Literal>; window: Target[\"window\"] | undefined }\n >();\n for (const relationship of relationships) {\n const existing = entries.get(relationship.collection);\n const entry = existing ?? {\n field: relationship.foreignField,\n ids: new Set<Predicate.Literal>(),\n window: windowOf(relationship),\n };\n // A second relationship pinning the same collection: fall back to the\n // unwindowed superset (sound, merely over-syncs).\n if (existing !== undefined) entry.window = undefined;\n pinIds(entry.ids, baseRows, relationship.localField);\n entries.set(relationship.collection, entry);\n }\n const map = new Map<string, Target>();\n for (const [collection, entry] of entries) {\n map.set(collection, {\n field: entry.field,\n ids: entry.ids,\n ...(entry.window === undefined ? {} : { window: entry.window }),\n });\n }\n return map;\n },\n resolveRow: (index, baseRow) => {\n const related: Record<string, RelatedValue> = {};\n for (const relationship of relationships) {\n const key = Predicate.fieldValue(baseRow.value, relationship.localField) as Predicate.Literal;\n const bucket = index.get(relationship.collection)?.get(key);\n const first = bucket?.[0];\n related[relationship.name] =\n relationship.kind === \"one\"\n ? first === undefined\n ? null\n : first.value\n : (bucket ?? []).map((row) => row.value);\n }\n return related;\n },\n});\n\n/** The declared relationships an edge selection picks (unknown names skipped). */\nconst selectRelationships = (\n registry: Collection.CollectionRegistry,\n collectionName: string,\n edges: ReadonlyArray<string | EdgeSelect>\n): ReadonlyArray<Collection.Relationship & { readonly first?: number }> => {\n const all = Collection.relationshipsOf(registry, collectionName);\n const selected: Array<Collection.Relationship & { readonly first?: number }> = [];\n for (const input of edges) {\n const select = edgeSelect(input);\n const relationship = all.get(select.name);\n if (relationship !== undefined) {\n selected.push({\n ...relationship,\n ...(select.first === undefined ? {} : { first: select.first }),\n });\n }\n }\n return selected;\n};\n\n// ─── Generic plumbing (strategy-parameterised) ───────────────────────────────\n\nconst hydrate = (\n strategy: Strategy,\n base: ReadonlyArray<LocalRow>,\n index: CollectionIndex\n): ReadonlyArray<RelatedRow> =>\n base.map((row) => ({ id: row.id, value: row.value, related: strategy.resolveRow(index, row) }));\n\n/**\n * Prime one index entry per targeted collection from the current local view:\n * only the pinned `foreignField IN (...)` rows, not the whole collection\n * (issue #113) — exactly what `resolveRow` ever looks up, and an `eq`/`In`\n * lookup the engine's secondary index can resolve without a full scan when\n * `target.field` is indexed. A target with no pinned ids needs no query.\n */\nconst primeIndex = (\n view: ClientView.Reader,\n targets: ReadonlyMap<string, Target>\n): Effect.Effect<Map<string, ReadonlyMap<Predicate.Literal, ReadonlyArray<LocalRow>>>, never> =>\n Effect.gen(function* () {\n const index = new Map<string, ReadonlyMap<Predicate.Literal, ReadonlyArray<LocalRow>>>();\n for (const [collection, target] of targets) {\n const rows =\n target.ids.size === 0\n ? []\n : yield* view\n .query(\n Subset.make({ collection, where: Predicate.isIn(target.field, [...target.ids]) })\n )\n .pipe(Effect.orDie);\n index.set(collection, groupByField(rows, target.field));\n }\n return index;\n });\n\n/**\n * Resolve a subset's rows together with their relationships, reading the\n * targeted collections from the engine's local view (one-shot).\n */\nexport const queryWith = (\n view: ClientView.Reader,\n strategy: Strategy,\n subset: Subset.Subset\n): Effect.Effect<ReadonlyArray<RelatedRow>, never> =>\n Effect.gen(function* () {\n const base = yield* view.query(subset).pipe(Effect.orDie);\n return yield* joinRowsWith(view, strategy, base);\n });\n\n/**\n * The join of base rows already read: the foreign collections the rows pin\n * are read from the view, and the rows hydrated. {@link queryWith} is this\n * over a fresh read of the subset.\n */\nconst joinRowsWith = (\n view: ClientView.Reader,\n strategy: Strategy,\n base: ReadonlyArray<LocalRow>\n): Effect.Effect<ReadonlyArray<RelatedRow>, never> =>\n Effect.gen(function* () {\n const index = yield* primeIndex(view, strategy.targets(base));\n return hydrate(strategy, base, index);\n });\n\n/**\n * The delta-maintained join engine behind {@link observeWith} (issue #111).\n * Maintains, per targeted foreign collection, an incremental `fk → rows`\n * bucket index — a row put/del touches at most the one or two buckets its old\n * and new key select, never a full re-group (`groupByField` was the O(n)\n * offender) — plus a reverse index from `(collection, key)` to the base row\n * ids that key affects, so a foreign delta re-hydrates only the base rows it\n * actually touches, never the full base page. A base-row delta re-hydrates\n * only that row. Linkage shifts (which collections are targeted) are diffed\n * against the previously targeted set — the same diff-and-release shape as\n * {@link reconcile} — so already-targeted collections' indexes and observers\n * are left running instead of torn down and re-primed.\n *\n * `one`-edge presence transitions (a resolved edge appearing or disappearing)\n * need no special case: they fall out of re-running `resolveRow` for exactly\n * the affected base rows, same as any other bucket change.\n *\n * Pure and Effect-free — it consumes plain row snapshots, not streams or\n * subscriptions — so it can be driven directly by a property test comparing\n * it against {@link hydrateFromScratch} after every prefix of a randomized\n * delta sequence.\n */\nexport interface JoinEngine {\n /**\n * Apply a new base-page snapshot. `added`/`removed` are the collections the\n * caller must start/stop observing. `result` is the freshly hydrated page,\n * or `undefined` while any newly-targeted collection has not yet delivered\n * its first snapshot (the join isn't fully primed yet).\n */\n readonly applyBase: (rows: ReadonlyArray<LocalRow>) => {\n readonly added: ReadonlyArray<string>;\n readonly removed: ReadonlyArray<string>;\n readonly result: ReadonlyArray<RelatedRow> | undefined;\n };\n /** Apply a new snapshot for one currently-targeted foreign collection. */\n readonly applyForeign: (\n collection: string,\n rows: ReadonlyArray<LocalRow>\n ) => { readonly result: ReadonlyArray<RelatedRow> | undefined };\n}\n\n/** One targeted foreign collection's incrementally-maintained state. */\ninterface ForeignState {\n target: Target;\n /** Last-seen full snapshot, diffed against the next one to find the delta. */\n rowsById: Map<string, LocalRow>;\n /** `fk value → (row id → row)`, updated for only the touched key(s). */\n buckets: Map<Predicate.Literal, Map<string, LocalRow>>;\n /** `fk value → rows`: the {@link CollectionIndex} entry, cached from `buckets`. */\n results: Map<Predicate.Literal, ReadonlyArray<LocalRow>>;\n}\n\n/** The per-row key set a base row pins in each targeted collection. */\nconst rowKeysOf = (\n strategy: Strategy,\n row: LocalRow\n): ReadonlyMap<string, ReadonlySet<Predicate.Literal>> => {\n const map = new Map<string, ReadonlySet<Predicate.Literal>>();\n for (const [collection, target] of strategy.targets([row])) map.set(collection, target.ids);\n return map;\n};\n\n/** {@inheritDoc JoinEngine} */\nexport const makeJoinEngine = (strategy: Strategy): JoinEngine => {\n let baseOrder: ReadonlyArray<string> = [];\n const baseRowsById = new Map<string, LocalRow>();\n const baseKeysById = new Map<string, ReadonlyMap<string, ReadonlySet<Predicate.Literal>>>();\n const resolvedById = new Map<string, RelatedRow>();\n const foreignByCollection = new Map<string, ForeignState>();\n const reverseIndex = new Map<string, Map<Predicate.Literal, Set<string>>>();\n // Collections newly targeted whose first snapshot hasn't arrived yet: while\n // non-empty the join is incompletely primed, so `result` stays `undefined`.\n const pendingCollections = new Set<string>();\n\n const indexView = (): CollectionIndex => {\n const map = new Map<string, ReadonlyMap<Predicate.Literal, ReadonlyArray<LocalRow>>>();\n for (const [collection, state] of foreignByCollection) map.set(collection, state.results);\n return map;\n };\n\n const hydrateRow = (row: LocalRow): RelatedRow => ({\n id: row.id,\n value: row.value,\n related: strategy.resolveRow(indexView(), row),\n });\n\n const rehydrateById = (id: string): void => {\n const row = baseRowsById.get(id);\n if (row !== undefined) resolvedById.set(id, hydrateRow(row));\n };\n\n // Visit every (collection, key) a row's key set touches, skipping\n // collections that aren't (or are no longer) targeted. `indexRow` and\n // `unindexRow` differ only in what they do at each (byKey, key) — this is\n // the shared traversal.\n const forEachIndexed = (\n keys: ReadonlyMap<string, ReadonlySet<Predicate.Literal>>,\n f: (byKey: Map<Predicate.Literal, Set<string>>, key: Predicate.Literal) => void\n ): void => {\n for (const [collection, ids] of keys) {\n const byKey = reverseIndex.get(collection);\n if (byKey === undefined) continue;\n for (const key of ids) f(byKey, key);\n }\n };\n\n const indexRow = (id: string, keys: ReadonlyMap<string, ReadonlySet<Predicate.Literal>>): void =>\n forEachIndexed(keys, (byKey, key) => {\n const set = byKey.get(key) ?? new Set<string>();\n set.add(id);\n byKey.set(key, set);\n });\n\n const unindexRow = (\n id: string,\n keys: ReadonlyMap<string, ReadonlySet<Predicate.Literal>>\n ): void =>\n forEachIndexed(keys, (byKey, key) => {\n const set = byKey.get(key);\n if (set === undefined) return;\n set.delete(id);\n if (set.size === 0) byKey.delete(key);\n });\n\n const addCollection = (collection: string, target: Target): void => {\n foreignByCollection.set(collection, {\n target,\n rowsById: new Map(),\n buckets: new Map(),\n results: new Map(),\n });\n reverseIndex.set(collection, new Map());\n pendingCollections.add(collection);\n };\n\n const removeCollection = (collection: string): void => {\n foreignByCollection.delete(collection);\n reverseIndex.delete(collection);\n pendingCollections.delete(collection);\n };\n\n const currentOutput = (): ReadonlyArray<RelatedRow> =>\n baseOrder.flatMap((id) => {\n const row = resolvedById.get(id);\n return row === undefined ? [] : [row];\n });\n\n /**\n * Diff the targeted collection set (the `reconcile` pattern, :366-388):\n * start observing newly-targeted collections, stop observing stale ones,\n * leave already-targeted ones (with the same join field) untouched.\n */\n const diffTargets = (\n nextTargets: ReadonlyMap<string, Target>\n ): { readonly added: ReadonlyArray<string>; readonly removed: ReadonlyArray<string> } => {\n const added: Array<string> = [];\n const removed: Array<string> = [];\n for (const [collection, target] of nextTargets) {\n const existing = foreignByCollection.get(collection);\n if (existing === undefined) {\n addCollection(collection, target);\n added.push(collection);\n } else if (existing.target.field !== target.field) {\n // The join key itself changed collection-wide: the maintained buckets\n // no longer mean anything, so re-prime from scratch.\n removeCollection(collection);\n addCollection(collection, target);\n removed.push(collection);\n added.push(collection);\n } else {\n existing.target = target;\n }\n }\n for (const collection of foreignByCollection.keys()) {\n if (!nextTargets.has(collection)) {\n removeCollection(collection);\n removed.push(collection);\n }\n }\n return { added, removed };\n };\n\n /** Diff the base page against the last snapshot, updating the reverse\n * index and re-hydrating only added/changed rows. */\n const diffBaseRows = (rows: ReadonlyArray<LocalRow>): void => {\n const nextIds = new Set(rows.map((row) => row.id));\n for (const id of baseRowsById.keys()) {\n if (nextIds.has(id)) continue;\n const keys = baseKeysById.get(id);\n if (keys !== undefined) unindexRow(id, keys);\n baseRowsById.delete(id);\n baseKeysById.delete(id);\n resolvedById.delete(id);\n }\n for (const row of rows) {\n const prior = baseRowsById.get(row.id);\n if (prior === row) continue; // reference-stable: nothing to redo\n const keys = rowKeysOf(strategy, row);\n const priorKeys = baseKeysById.get(row.id);\n if (priorKeys !== undefined) unindexRow(row.id, priorKeys);\n indexRow(row.id, keys);\n baseKeysById.set(row.id, keys);\n baseRowsById.set(row.id, row);\n resolvedById.set(row.id, hydrateRow(row));\n }\n baseOrder = rows.map((row) => row.id);\n };\n\n const applyBase: JoinEngine[\"applyBase\"] = (rows) => {\n const { added, removed } = diffTargets(strategy.targets(rows));\n diffBaseRows(rows);\n return { added, removed, result: pendingCollections.size === 0 ? currentOutput() : undefined };\n };\n\n /**\n * Diff one foreign collection's new snapshot against its last one: an\n * unchanged row (same reference) is skipped; a changed or new row is\n * (re)placed in its current key's bucket, vacating its prior key's bucket\n * if the key moved; a row present before but not now is removed from its\n * bucket. Returns the keys whose bucket contents changed.\n */\n const diffForeignRows = (\n state: ForeignState,\n rows: ReadonlyArray<LocalRow>\n ): ReadonlySet<Predicate.Literal> => {\n const changedKeys = new Set<Predicate.Literal>();\n const keyOf = (row: LocalRow) =>\n Predicate.fieldValue(row.value, state.target.field) as Predicate.Literal;\n const putInto = (key: Predicate.Literal, row: LocalRow): void => {\n const bucket = state.buckets.get(key) ?? new Map<string, LocalRow>();\n bucket.set(row.id, row);\n state.buckets.set(key, bucket);\n state.results.set(key, [...bucket.values()]);\n changedKeys.add(key);\n };\n const removeFrom = (key: Predicate.Literal, id: string): void => {\n const bucket = state.buckets.get(key);\n if (bucket === undefined) return;\n bucket.delete(id);\n if (bucket.size === 0) {\n state.buckets.delete(key);\n state.results.delete(key);\n } else {\n state.results.set(key, [...bucket.values()]);\n }\n changedKeys.add(key);\n };\n\n const nextRowsById = new Map<string, LocalRow>();\n for (const row of rows) {\n nextRowsById.set(row.id, row);\n const prior = state.rowsById.get(row.id);\n if (prior === row) continue; // reference-stable: this row didn't change\n const key = keyOf(row);\n if (prior !== undefined && keyOf(prior) !== key) removeFrom(keyOf(prior), row.id);\n putInto(key, row);\n }\n for (const [id, prior] of state.rowsById) {\n if (!nextRowsById.has(id)) removeFrom(keyOf(prior), id); // deleted\n }\n state.rowsById = nextRowsById;\n return changedKeys;\n };\n\n /** The base row ids that depend on any of `changedKeys` in `collection`. */\n const affectedByKeys = (\n collection: string,\n changedKeys: ReadonlySet<Predicate.Literal>\n ): ReadonlySet<string> => {\n const affected = new Set<string>();\n const byKey = reverseIndex.get(collection);\n if (byKey === undefined) return affected;\n for (const key of changedKeys) {\n const ids = byKey.get(key);\n if (ids !== undefined) for (const id of ids) affected.add(id);\n }\n return affected;\n };\n\n const applyForeign: JoinEngine[\"applyForeign\"] = (collection, rows) => {\n const state = foreignByCollection.get(collection);\n // A stale event for a collection this base page no longer targets.\n if (state === undefined) return { result: undefined };\n\n const changedKeys = diffForeignRows(state, rows);\n // The first snapshot for a newly-targeted collection always primes it,\n // even if it touches no base row yet (e.g. an empty foreign collection).\n const justPrimed = pendingCollections.delete(collection);\n const affected = affectedByKeys(collection, changedKeys);\n for (const id of affected) rehydrateById(id);\n\n if (pendingCollections.size > 0) return { result: undefined };\n if (affected.size === 0 && !justPrimed) return { result: undefined };\n return { result: currentOutput() };\n };\n\n return { applyBase, applyForeign };\n};\n\n/**\n * Pure from-scratch join: group every targeted collection's given rows by\n * field and hydrate the base page against them — the semantics\n * {@link makeJoinEngine} must match after every incremental step. Exported\n * for the delta-maintenance property test.\n */\nexport const hydrateFromScratch = (\n strategy: Strategy,\n base: ReadonlyArray<LocalRow>,\n foreignRows: ReadonlyMap<string, ReadonlyArray<LocalRow>>\n): ReadonlyArray<RelatedRow> => {\n const targets = strategy.targets(base);\n const index = new Map<string, ReadonlyMap<Predicate.Literal, ReadonlyArray<LocalRow>>>();\n for (const [collection, target] of targets) {\n index.set(collection, groupByField(foreignRows.get(collection) ?? [], target.field));\n }\n return hydrate(strategy, base, index);\n};\n\n/** One raw snapshot arriving from the base subset or a targeted foreign collection. */\ntype JoinEvent =\n | { readonly _tag: \"base\"; readonly rows: ReadonlyArray<LocalRow> }\n | {\n readonly _tag: \"foreign\";\n readonly collection: string;\n readonly rows: ReadonlyArray<LocalRow>;\n };\n\n/**\n * Live version of {@link queryWith} as an incrementally-maintained join\n * (issue #111). A {@link makeJoinEngine} consumes the base page and every\n * targeted foreign collection's snapshots as they arrive over `view.observe`\n * and re-hydrates only the base rows a delta actually touches — never a full\n * re-group or a full base re-hydrate. A collection is observed for as long as\n * (and only as long as) the base page targets it: a linkage shift diffs the\n * targeted set and starts/stops just the newly (un)targeted collections'\n * observers, leaving the rest running.\n */\nexport const observeWith = (\n view: ClientView.Reader,\n strategy: Strategy,\n subset: Subset.Subset\n): Stream.Stream<ReadonlyArray<RelatedRow>, never> =>\n Stream.callback<ReadonlyArray<RelatedRow>>((output) =>\n Effect.gen(function* () {\n const engine = makeJoinEngine(strategy);\n const events = yield* Queue.unbounded<JoinEvent>();\n const collectionFibers = new Map<string, Fiber.Fiber<void, never>>();\n\n const emit = (result: ReadonlyArray<RelatedRow> | undefined) =>\n result === undefined ? Effect.void : Effect.asVoid(Queue.offer(output, result));\n\n const startCollection = (collection: string) =>\n Effect.gen(function* () {\n const fiber = yield* Effect.forkScoped(\n Stream.runForEach(\n view.observe(Subset.make({ collection })).pipe(Stream.orDie),\n (rows) => Queue.offer(events, { _tag: \"foreign\", collection, rows })\n )\n );\n collectionFibers.set(collection, fiber);\n });\n\n const stopCollection = (collection: string) =>\n Effect.gen(function* () {\n const fiber = collectionFibers.get(collection);\n collectionFibers.delete(collection);\n if (fiber !== undefined) yield* Fiber.interrupt(fiber);\n });\n\n // The base observer runs for the join's whole lifetime; foreign\n // observers come and go with `applyBase`'s targeted-set diff below.\n yield* Effect.forkScoped(\n Stream.runForEach(view.observe(subset).pipe(Stream.orDie), (rows) =>\n Queue.offer(events, { _tag: \"base\", rows })\n )\n );\n\n yield* Effect.forkScoped(\n Effect.forever(\n Queue.take(events).pipe(\n Effect.flatMap((event) =>\n event._tag === \"base\"\n ? Effect.gen(function* () {\n const { added, removed, result } = engine.applyBase(event.rows);\n for (const collection of removed) yield* stopCollection(collection);\n for (const collection of added) yield* startCollection(collection);\n yield* emit(result);\n })\n : emit(engine.applyForeign(event.collection, event.rows).result)\n )\n )\n )\n );\n })\n ).pipe(Stream.changesWith(sameJoin));\n\n/**\n * The narrowed subsets a base page's targets pin: one `foreignField IN (...)`\n * subset per unwindowed target; for windowed targets, one\n * `(foreignField = value, orderBy, limit)` subset **per pinned value** — the\n * per-parent sync windows of ADR-0024.\n */\nconst desiredSubsets = (\n strategy: Strategy,\n base: ReadonlyArray<LocalRow>\n): ReadonlyArray<Subset.Subset> => subsetsForTargets(strategy.targets(base));\n\n/**\n * The foreign windows a relational read holds for the root rows it reads: the\n * windows {@link related}'s reconcile subscribes for `baseRows` under the\n * declared edges (ADR-0024). A read whose rows link to them depends on exactly\n * these windows, so coverage asks only for them (ADR-0029 section 3, #426).\n */\nexport const windowsFor = (\n registry: Collection.CollectionRegistry,\n collectionName: string,\n edges: ReadonlyArray<string | EdgeSelect>,\n baseRows: ReadonlyArray<LocalRow>\n): ReadonlyArray<Subset.Subset> =>\n desiredSubsets(\n fieldMappingStrategy(selectRelationships(registry, collectionName, edges)),\n baseRows\n );\n\n/** The narrowed subsets a set of targets pins (see {@link desiredSubsets}). */\nconst subsetsForTargets = (targets: ReadonlyMap<string, Target>): ReadonlyArray<Subset.Subset> =>\n [...targets]\n .filter(([, target]) => target.ids.size > 0)\n .flatMap(([collection, target]) => {\n const window = target.window;\n return window === undefined\n ? [Subset.make({ collection, where: Predicate.isIn(target.field, [...target.ids]) })]\n : [...target.ids].map((id) =>\n Subset.make({\n collection,\n where: Predicate.eq(target.field, id),\n orderBy: window.orderBy,\n limit: window.limit,\n })\n );\n });\n\nconst hasSubset = (list: ReadonlyArray<Subset.Subset>, subset: Subset.Subset): boolean =>\n list.some((other) => Subset.hash(other) === Subset.hash(subset));\n\n/** Diff subscribed vs desired foreign subsets; returns whether anything changed. */\nconst reconcile = (\n engine: ClientEngine,\n subscribed: Ref.Ref<ReadonlyArray<Subset.Subset>>,\n desired: ReadonlyArray<Subset.Subset>\n): Effect.Effect<boolean> =>\n Effect.gen(function* () {\n const previous = yield* Ref.get(subscribed);\n let changed = false;\n for (const stale of previous) {\n if (!hasSubset(desired, stale)) {\n yield* engine.unsubscribe(stale);\n changed = true;\n }\n }\n for (const next of desired) {\n if (!hasSubset(previous, next)) {\n yield* engine.subscribe(next);\n changed = true;\n }\n }\n yield* Ref.set(subscribed, desired);\n return changed;\n });\n\n/** Whether a background pull is running, and whether another is wanted after it. */\ninterface PullState {\n readonly running: boolean;\n readonly wanted: boolean;\n}\n\n/**\n * A pull request that never blocks its caller: the pull runs on a fiber of\n * `scope`, at most one at a time, and a request made while one runs queues\n * exactly one more (so a subset registered mid-pull is still fetched). A\n * failed pull (an offline transport, a server away) only delays rows: the\n * engine's own sync loop recovers — local is always an answer.\n */\nconst makePullSoon = (\n engine: ClientEngine,\n scope: Scope.Scope\n): Effect.Effect<Effect.Effect<void>> =>\n Effect.map(Ref.make<PullState>({ running: false, wanted: false }), (state) => {\n const worker: Effect.Effect<void> = engine.pull.pipe(\n Effect.ignore,\n Effect.andThen(\n Ref.modify(state, (current) =>\n current.wanted\n ? ([true, { running: true, wanted: false }] as const)\n : ([false, { running: false, wanted: false }] as const)\n )\n ),\n Effect.flatMap((again) => (again ? worker : Effect.void))\n );\n return Ref.modify(state, (current) =>\n current.running\n ? ([false, { running: true, wanted: true }] as const)\n : ([true, { running: true, wanted: false }] as const)\n ).pipe(\n Effect.flatMap((start) => (start ? Effect.asVoid(Effect.forkIn(worker, scope)) : Effect.void))\n );\n });\n\n/**\n * Keep a base subset's narrowed foreign subsets registered for the scope's\n * lifetime — the reconcile loop alone, no join: the base is subscribed,\n * the foreign subsets are reconciled from its rows now and on every change\n * to it, and everything is released when the scope closes. The\n * registration is complete when this returns; the pulls that bring the\n * rows in run in the background ({@link makePullSoon}), so a stalled\n * transport delays rows and never blocks the caller.\n */\nconst trackWith = (\n engine: ClientEngine,\n strategy: Strategy,\n subset: Subset.Subset\n): Effect.Effect<void, never, Scope.Scope> =>\n Effect.gen(function* () {\n const scope = yield* Effect.scope;\n const subscribed = yield* Ref.make<ReadonlyArray<Subset.Subset>>([]);\n yield* engine.subscribe(subset);\n yield* Effect.addFinalizer(() =>\n Ref.get(subscribed).pipe(\n Effect.flatMap((subs) =>\n Effect.forEach([subset, ...subs], (s) => engine.unsubscribe(s), { discard: true })\n )\n )\n );\n const pullSoon = yield* makePullSoon(engine, scope);\n const refresh = Effect.gen(function* () {\n const base = yield* engine.query(subset).pipe(Effect.orDie);\n const changed = yield* reconcile(engine, subscribed, desiredSubsets(strategy, base));\n if (changed) yield* pullSoon;\n });\n // The base syncs in the background; the derivation runs over what the\n // replica holds now and again on every change to the base rows.\n yield* pullSoon;\n yield* refresh;\n yield* Effect.forkIn(\n Stream.runForEach(engine.observe(subset).pipe(Stream.orDie), () => refresh),\n scope\n );\n });\n\n/**\n * Auto-subscribing relational read: subscribes the base subset and, from its\n * rows, the narrowed `foreignField IN (...)` subsets of each targeted\n * collection — so the related rows sync without the caller wiring subscriptions.\n * The subscriptions track the live linkage (re-derived on every change to the\n * base rows) and are torn down when the scope closes. Returns a stream that\n * emits the resolved rows and re-emits on any change.\n */\nexport const relatedWith = (\n engine: ClientEngine,\n strategy: Strategy,\n subset: Subset.Subset\n): Effect.Effect<Stream.Stream<ReadonlyArray<RelatedRow>, never>, never, Scope.Scope> =>\n trackWith(engine, strategy, subset).pipe(Effect.as(observeWith(engine, strategy, subset)));\n\n/** A row from an external source, tagged with its collection. */\nexport interface SourcedRow {\n readonly collection: string;\n readonly id: string;\n readonly value: unknown;\n}\n\n/**\n * One-shot relational read over an **external row source** — the\n * server-fallthrough tier (ADR-0025). Fetches the base subset, derives the\n * foreign subsets exactly as the auto-subscribing read would (including\n * ADR-0024's per-parent windows), fetches them in one batch, and assembles\n * the join with the same field-mapping resolution. Nothing is subscribed\n * and nothing enters the replica.\n */\nexport const queryVia = <E>(\n fetchRows: (subsets: ReadonlyArray<Subset.Subset>) => Effect.Effect<ReadonlyArray<SourcedRow>, E>,\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | EdgeSelect>\n): Effect.Effect<ReadonlyArray<RelatedRow>, E> =>\n Effect.gen(function* () {\n const strategy = fieldMappingStrategy(selectRelationships(registry, collectionName, edges));\n const base = (yield* fetchRows([subset]))\n .filter((row) => row.collection === subset.collection)\n .map(({ id, value }) => ({ id, value }));\n const targets = strategy.targets(base);\n const foreignSubsets = subsetsForTargets(targets);\n const foreign = Arr.isReadonlyArrayEmpty(foreignSubsets)\n ? []\n : yield* fetchRows(foreignSubsets);\n const index = new Map<string, ReadonlyMap<Predicate.Literal, ReadonlyArray<LocalRow>>>();\n for (const [collection, target] of targets) {\n index.set(\n collection,\n groupByField(\n foreign\n .filter((row) => row.collection === collection)\n .map(({ id, value }) => ({ id, value })),\n target.field\n )\n );\n }\n return hydrate(strategy, base, index);\n });\n\n// ─── Public API (declared field mappings) ────────────────────────────────────\n\n/** Resolve a subset's declared relationships against the mirror (one-shot). */\nexport const query = (\n view: ClientView.Reader,\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | EdgeSelect>\n): Effect.Effect<ReadonlyArray<RelatedRow>, never> =>\n queryWith(\n view,\n fieldMappingStrategy(selectRelationships(registry, collectionName, edges)),\n subset\n );\n\n/**\n * {@link query} over base rows the caller has already read from the view:\n * the same join, judged and answered from one snapshot of the root (#426).\n * Never reads the subset itself, so a caller that judged coverage over\n * `base` answers from exactly those rows.\n */\nexport const queryRows = (\n view: ClientView.Reader,\n registry: Collection.CollectionRegistry,\n collectionName: string,\n base: ReadonlyArray<LocalRow>,\n edges: ReadonlyArray<string | EdgeSelect>\n): Effect.Effect<ReadonlyArray<RelatedRow>, never> =>\n joinRowsWith(\n view,\n fieldMappingStrategy(selectRelationships(registry, collectionName, edges)),\n base\n );\n\n/** Live, incrementally-maintained join over a subset's declared relationships. */\nexport const observe = (\n view: ClientView.Reader,\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | EdgeSelect>\n): Stream.Stream<ReadonlyArray<RelatedRow>, never> =>\n observeWith(\n view,\n fieldMappingStrategy(selectRelationships(registry, collectionName, edges)),\n subset\n );\n\n/**\n * Keep the foreign windows of a subset's selected edges registered for the\n * scope's lifetime, without resolving the join — what an explicit pin with\n * `include` holds (ADR-0029 section 2): {@link related}'s reconcile loop\n * alone, no rows materialised.\n */\nexport const trackEdges = (\n engine: ClientEngine,\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | EdgeSelect>\n): Effect.Effect<void, never, Scope.Scope> =>\n trackWith(\n engine,\n fieldMappingStrategy(selectRelationships(registry, collectionName, edges)),\n subset\n );\n\n/**\n * Auto-subscribing relational read over a subset's declared relationships: syncs\n * the base and the narrowed foreign subsets, tracks the live linkage, and tears\n * the subscriptions down when the scope closes.\n */\nexport const related = (\n engine: ClientEngine,\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | EdgeSelect>\n): Effect.Effect<Stream.Stream<ReadonlyArray<RelatedRow>, never>, never, Scope.Scope> =>\n relatedWith(\n engine,\n fieldMappingStrategy(selectRelationships(registry, collectionName, edges)),\n subset\n );\n\n/**\n * Rewrite every `Predicate.exists` node over a locally-synced collection to an\n * `In` over its `localField`, materialising the matching `foreignField` values\n * from the engine's local rows — the client-side analogue of the server's\n * `Predicate.resolveExists`. Once the foreign collection is synced, a subset\n * filtered by `Predicate.exists` evaluates correctly on the client.\n */\nexport const resolveExistsLocally = (\n view: ClientView.Reader,\n predicate: Predicate.Predicate\n): Effect.Effect<Predicate.Predicate, never> =>\n Predicate.resolveExists(predicate, (node) =>\n view.query(Subset.make({ collection: node.collection })).pipe(\n Effect.map((rows) =>\n Predicate.existsValues(\n node,\n rows.map((row) => row.value)\n )\n ),\n Effect.orDie\n )\n );\n","/**\n * Query\n *\n * THE read concept (ADR-0022). A query declares what to read — a node\n * collection, a `where`, `include`d edges (with per-edge windows), an\n * `order`, and cursor pagination — and compiles to a **plan** of sync\n * windows the engine tracks; `Subset`/`Predicate` are the plan's internal\n * representation.\n *\n * ```ts\n * Query.make({\n * collection: \"products\",\n * where: { categoryId: \"c-audio\" },\n * include: { variants: true, reviews: { first: 10 } },\n * order: [\"name\"],\n * first: 20,\n * });\n * ```\n *\n * **Named queries are the same concept with a name and an args schema**\n * (`Query.named`): defined once and resolved twice — the client resolves\n * args to the plan it renders locally; the server resolves the same args to\n * the *authoritative* window it syncs, with the request's identity in hand\n * (ADR-0009's \"what only the app can know\").\n *\n * A paginated edge's `first` is a true sync window (ADR-0024): plan\n * execution registers one windowed subset per parent row, so the replica\n * syncs the window — not the dependent collection — and the same\n * `(order, first)` is re-applied to the resolved join locally (the replica\n * is normalized and may hold rows beyond one parent's window).\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Order from \"effect/Order\";\nimport * as P from \"effect/Predicate\";\nimport * as Result from \"effect/Result\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\nimport type { SyncContext } from \"./Backend.js\";\nimport type { LocalRow } from \"./ClientEngine.js\";\nimport type * as ClientView from \"./ClientView.js\";\nimport { AuthorizationError, DuplicateNameError, QueryError } from \"./Errors.js\";\nimport type * as Node from \"./Node.js\";\nimport * as Predicate from \"./Predicate.js\";\nimport * as Related from \"./Related.js\";\nimport * as Subset from \"./Subset.js\";\n\n/** A named query definition: the shared, serializable contract (name + args). */\nexport interface Named<Name extends string, Args, ArgsEncoded = unknown> {\n readonly name: Name;\n readonly args: Schema.Codec<Args, ArgsEncoded>;\n}\n\n/** @deprecated The named-definition type is {@link Named}. */\nexport type Query<Name extends string, Args, ArgsEncoded = unknown> = Named<\n Name,\n Args,\n ArgsEncoded\n>;\n\n/** Any {@link Named} query definition, whatever its name and args. */\nexport type AnyQuery = Named<string, any, any>;\n\n/** Define a named query contract (the same concept as {@link Read}, with a name). */\nexport const named = <const Name extends string, Args, ArgsEncoded>(\n name: Name,\n args: Schema.Codec<Args, ArgsEncoded>\n): Named<Name, Args, ArgsEncoded> => ({ name, args });\n\n// ─── The declarative read ────────────────────────────────────────────────────\n\n/** Options for one `include`d edge. `first` windows the edge's rows. */\nexport interface IncludeOptions {\n readonly first?: number;\n}\n\n/**\n * A declarative read: what to read, shaped like the data. `where` is an\n * equality map over row fields (a full `Predicate` is the escape hatch);\n * `include` names edges on the node; `order` tokens are field names,\n * `-` prefixed for descending; `first`/`after` page the root window by\n * cursor, `offset` by position (issue #209 — mutually exclusive with\n * `after`; a caller compiling from a URL keeps them so, `JsonApiQuery`\n * rejects a request naming both).\n */\nexport interface Read {\n readonly collection: string;\n readonly where?: Readonly<Record<string, Predicate.Literal>> | Predicate.Predicate;\n readonly include?: Readonly<Record<string, true | IncludeOptions>>;\n readonly order?: ReadonlyArray<string>;\n readonly first?: number;\n readonly after?: string;\n /**\n * Offset pagination (#209): skip this many rows of the window before\n * `first`. The root window's compiled `limit` absorbs it\n * (`offset + first`, see {@link plan}) so the same `Subset` both answers\n * the read and lets `Coverage.covers` judge it by the ordinary\n * limit-prefix rule — a subscription covers an offset read iff its own\n * limit is at least `offset + first`, or it is unwindowed. `offset`\n * itself never reaches `Subset`: it is a read-time slice, applied where\n * the read resolves (`DocumentWriter`), never a subscription's identity —\n * the engine keeps cursors as the only windowed subscription shape\n * (ADR-0024).\n */\n readonly offset?: number;\n}\n\n/** Define a read ({@link Read}), or a named contract via `(name, args)`. */\nexport function make(read: Read): Read;\n/** Define a named query contract (the same as {@link named}). */\nexport function make<const Name extends string, Args, ArgsEncoded>(\n name: Name,\n args: Schema.Codec<Args, ArgsEncoded>\n): Named<Name, Args, ArgsEncoded>;\nexport function make(\n first: Read | string,\n args?: Schema.Codec<any, any>\n): Read | Named<string, any, any> {\n return P.isString(first) ? named(first, args ?? Schema.Unknown) : first;\n}\n\n/** Parse `order` tokens (\"name\", \"-createdAt\") into sort terms. */\nconst orderBy = Subset.parseOrder;\n\n/**\n * A plan's edge selections for the relational read: paginated edges carry\n * their window (`first`), so each parent registers its own windowed subset\n * (ADR-0024); other kinds select unwindowed. The same selects are what a\n * subscription's coverage of an `include` is judged by (ADR-0029 rule 4).\n */\nexport const edgeSelects = (compiled: Plan): ReadonlyArray<Related.EdgeSelect> =>\n compiled.edges.map((edge) => ({\n name: edge.edge,\n ...(edge.kind === \"paginated\" && edge.first !== undefined ? { first: edge.first } : {}),\n }));\n\n/**\n * The root window's compiled `limit`: `first` alone for cursor pagination,\n * or `offset + first` for offset pagination (#209) — the window\n * over-fetches by `offset` rows so a covering subscription is judged by\n * the ordinary limit-prefix rule and the read can slice its own page back\n * out of what it fetched. `offset` alone (no `first`) compiles to no\n * limit: the read wants every row past `offset`.\n */\nconst rootLimit = (read: Read): number | undefined =>\n read.offset === undefined\n ? read.first\n : read.first === undefined\n ? undefined\n : read.offset + read.first;\n\n/** Compile a `where` to the plan's predicate representation. */\nconst compileWhere = (where: Read[\"where\"]): Predicate.Predicate => {\n if (where === undefined) return Predicate.always;\n if (\"_tag\" in where) return where as Predicate.Predicate;\n const terms = Object.entries(where).map(([field, value]) =>\n Predicate.eq(field, value as Predicate.Literal)\n );\n const only = terms[0];\n return terms.length === 1 && only !== undefined ? only : Predicate.and(...terms);\n};\n\n/** One included edge, compiled: how to join and how to window the result. */\nexport interface EdgePlan {\n readonly edge: string;\n readonly kind: \"one\" | \"many\" | \"paginated\";\n readonly target: string;\n /** The edge's window: a per-parent sync window for paginated edges (ADR-0024). */\n readonly first?: number;\n /** The edge's declared order (paginated edges own their order). */\n readonly order: ReadonlyArray<Subset.OrderBy>;\n}\n\n/** A compiled read: the root sync window plus its edge plans. */\nexport interface Plan {\n readonly root: Subset.Subset;\n readonly edges: ReadonlyArray<EdgePlan>;\n}\n\n/**\n * Compile a read against the node graph: the root window as a `Subset`,\n * each `include`d edge resolved through the registry (its kind, target,\n * declared order) plus the read's per-edge window.\n */\nexport const plan = (nodes: Node.NodeRegistry, read: Read): Plan => {\n const limit = rootLimit(read);\n const root = Subset.make({\n collection: read.collection,\n where: compileWhere(read.where),\n orderBy: orderBy(read.order),\n ...(limit === undefined ? {} : { limit }),\n ...(read.after === undefined ? {} : { cursor: read.after }),\n });\n const node = nodes.nodes.get(read.collection);\n const edges: Array<EdgePlan> = [];\n Arr.forEach(Object.entries(read.include ?? {}), ([name, options]) => {\n if (node === undefined) {\n throw new QueryError({\n message: `Unknown collection for include: ${read.collection}`,\n query: read.collection,\n });\n }\n const edge = node.edges[name];\n if (edge === undefined) {\n throw new QueryError({\n message: `Unknown edge \"${name}\" on ${read.collection}`,\n query: read.collection,\n });\n }\n const window = options === true ? {} : options;\n edges.push({\n edge: name,\n kind: edge.kind,\n target: edge.target,\n ...(window.first === undefined ? {} : { first: window.first }),\n order: edge.kind === \"paginated\" ? orderBy(edge.order) : [],\n });\n });\n return { root, edges };\n};\n\n/**\n * {@link plan} as an effect: the `QueryError` it throws for an unknown\n * collection or edge becomes a typed failure, for callers that compile a\n * read they did not write (a URL, a message off a channel).\n */\nexport const tryPlan = (nodes: Node.NodeRegistry, read: Read): Effect.Effect<Plan, QueryError> =>\n Effect.suspend(() => {\n const compiled = Result.try(() => plan(nodes, read));\n if (Result.isSuccess(compiled)) return Effect.succeed(compiled.success);\n const error = compiled.failure;\n return error instanceof QueryError ? Effect.fail(error) : Effect.die(error);\n });\n\n/** The order an edge's terms put its resolved rows in (the first term that differs decides). */\nconst edgeOrder =\n (edgePlan: EdgePlan): Order.Order<unknown> =>\n (a, b) => {\n // The first term whose fields differ decides; equal on every term is a tie.\n const decided = Arr.findFirst(edgePlan.order, (term) => {\n const left = (a as Record<string, unknown>)[term.field] as string | number;\n const right = (b as Record<string, unknown>)[term.field] as string | number;\n if (left === right) return Option.none();\n const ascending = left < right;\n return Option.some<-1 | 0 | 1>(\n term.direction === \"asc\" ? (ascending ? -1 : 1) : ascending ? 1 : -1\n );\n });\n return Option.getOrElse(decided, (): -1 | 0 | 1 => 0);\n };\n\n/** Order + window one edge's resolved rows (the client-side edge window). */\nconst applyEdgeWindow = (\n values: ReadonlyArray<unknown>,\n edgePlan: EdgePlan\n): ReadonlyArray<unknown> => {\n let rows = values;\n if (Arr.isReadonlyArrayNonEmpty(edgePlan.order)) {\n rows = Arr.sort(rows, edgeOrder(edgePlan));\n }\n return edgePlan.first === undefined ? rows : rows.slice(0, edgePlan.first);\n};\n\n/** Apply a plan's edge windows to resolved rows (used by `Client`). */\nexport const applyWindows = (\n compiled: Plan,\n rows: ReadonlyArray<Related.RelatedRow>\n): ReadonlyArray<Related.RelatedRow> => rows.map((row) => windowRow(row, compiled.edges));\n\n/** Apply every collection-valued edge window to one resolved row. */\nconst windowRow = (row: Related.RelatedRow, edges: ReadonlyArray<EdgePlan>): Related.RelatedRow => {\n let related = row.related;\n Arr.forEach(edges, (edgePlan) => {\n const value = related[edgePlan.edge];\n if (!Array.isArray(value)) return;\n if (edgePlan.first === undefined && Arr.isReadonlyArrayEmpty(edgePlan.order)) return;\n related = { ...related, [edgePlan.edge]: applyEdgeWindow(value, edgePlan) };\n });\n return related === row.related ? row : { ...row, related };\n};\n\n/**\n * Run a read once over the local view: the root window's rows, with every\n * `include`d edge resolved (and windowed) onto each row.\n */\nexport const run = (\n view: ClientView.Reader,\n nodes: Node.NodeRegistry,\n read: Read\n): Effect.Effect<ReadonlyArray<Related.RelatedRow>, never> => {\n const compiled = plan(nodes, read);\n if (Arr.isReadonlyArrayEmpty(compiled.edges)) {\n return view.query(compiled.root).pipe(\n Effect.orDie,\n Effect.map((rows) => rows.map((row) => ({ ...row, related: {} })))\n );\n }\n return Related.query(\n view,\n nodes.collections,\n read.collection,\n compiled.root,\n edgeSelects(compiled)\n ).pipe(Effect.map((rows) => rows.map((row) => windowRow(row, compiled.edges))));\n};\n\n/**\n * {@link run} over the root rows already read from the view: the same\n * edges and windows, joined from `rows` rather than a fresh read of the root,\n * so a caller that judged coverage over `rows` answers from those rows (#426).\n */\nexport const runRows = (\n view: ClientView.Reader,\n nodes: Node.NodeRegistry,\n read: Read,\n rows: ReadonlyArray<LocalRow>\n): Effect.Effect<ReadonlyArray<Related.RelatedRow>, never> => {\n const compiled = plan(nodes, read);\n if (Arr.isReadonlyArrayEmpty(compiled.edges)) {\n return Effect.succeed(rows.map((row) => ({ ...row, related: {} })));\n }\n return Related.queryRows(\n view,\n nodes.collections,\n read.collection,\n rows,\n edgeSelects(compiled)\n ).pipe(Effect.map((joined) => joined.map((row) => windowRow(row, compiled.edges))));\n};\n\n/**\n * Run a read once over an **external row source** — the server-fallthrough\n * tier (ADR-0025) and the derived REST handlers alike: the root window is\n * fetched first, then the edge subsets its rows pin in one batch\n * (`Related.queryVia`: `id IN (…)` for `one` edges, `fk IN (…)` for `many`,\n * ADR-0024's per-parent windows for paginated edges), then the plan's edge\n * windows are applied. One plan, one join, whichever source answers.\n * Compiling the read happens inside the effect, so a read the graph\n * refuses (an unknown edge) is a defect of the effect, not of the caller.\n */\nexport const runVia = <E>(\n fetch: (\n subsets: ReadonlyArray<Subset.Subset>\n ) => Effect.Effect<ReadonlyArray<Related.SourcedRow>, E>,\n nodes: Node.NodeRegistry,\n read: Read\n): Effect.Effect<ReadonlyArray<Related.RelatedRow>, E> =>\n Effect.suspend(() => runPlanVia(fetch, nodes, plan(nodes, read)));\n\n/**\n * {@link runVia} over an already-compiled plan, for a caller that compiled\n * the read for its own purposes (the Client's coverage check keys its\n * ledger by the plan's root window) so the read is compiled once.\n */\nexport const runPlanVia = <E>(\n fetch: (\n subsets: ReadonlyArray<Subset.Subset>\n ) => Effect.Effect<ReadonlyArray<Related.SourcedRow>, E>,\n nodes: Node.NodeRegistry,\n compiled: Plan\n): Effect.Effect<ReadonlyArray<Related.RelatedRow>, E> =>\n Related.queryVia(\n fetch,\n nodes.collections,\n compiled.root.collection,\n compiled.root,\n edgeSelects(compiled)\n ).pipe(Effect.map((rows) => applyWindows(compiled, rows)));\n\n/**\n * Observe a read over the local view: emits current rows now and re-emits\n * as the root window or any included edge's rows change.\n */\nexport const observe = (\n view: ClientView.Reader,\n nodes: Node.NodeRegistry,\n read: Read\n): Stream.Stream<ReadonlyArray<Related.RelatedRow>, never> => {\n const compiled = plan(nodes, read);\n if (Arr.isReadonlyArrayEmpty(compiled.edges)) {\n return view.observe(compiled.root).pipe(\n Stream.orDie,\n Stream.map((rows) => rows.map((row) => ({ ...row, related: {} })))\n );\n }\n return Related.observe(\n view,\n nodes.collections,\n read.collection,\n compiled.root,\n edgeSelects(compiled)\n ).pipe(Stream.map((rows) => rows.map((row) => windowRow(row, compiled.edges))));\n};\n\n// ─── Client side ─────────────────────────────────────────────────────────────\n\n/** Resolve a query's args to the subset the client renders locally. */\nexport type LocalQuery<Args> = (args: Args) => Subset.Subset;\n\n/** Query definitions paired with their client-side subset factories. */\nexport interface QueryRegistry {\n readonly queries: ReadonlyMap<string, AnyQuery>;\n readonly locals: ReadonlyMap<string, LocalQuery<any>>;\n}\n\n/** Pair query definitions with client subset factories. Duplicate names throw. */\nexport const registry = (\n entries: ReadonlyArray<{ readonly query: AnyQuery; readonly local: LocalQuery<any> }>\n): QueryRegistry => {\n const queries = new Map<string, AnyQuery>();\n const locals = new Map<string, LocalQuery<any>>();\n Arr.forEach(entries, ({ query, local }) => {\n if (queries.has(query.name)) throw new DuplicateNameError({ kind: \"query\", name: query.name });\n queries.set(query.name, query);\n locals.set(query.name, local);\n });\n return { queries, locals };\n};\n\n// ─── Server side ─────────────────────────────────────────────────────────────\n\n/** Resolve a query's args + request identity to the authoritative subset. */\nexport type ServerQuery<Args> = (\n args: Args,\n context: SyncContext\n) => Effect.Effect<Subset.Subset, AuthorizationError>;\n\n/** Resolve a named subscription (name + encoded args) to a server subset. */\nexport interface QueryResolver {\n readonly resolve: (\n name: string,\n encodedArgs: unknown,\n context: SyncContext\n ) => Effect.Effect<Subset.Subset, AuthorizationError | QueryError>;\n}\n\n/** The {@link QueryResolver} service the sync server resolves named subscriptions with. */\nexport const QueryResolver = Context.Service<QueryResolver>(\n \"@thomasfosterau/legation/QueryResolver\"\n);\n\n/**\n * Build a server resolver from typed entries. Pushed args are untrusted, so\n * each is schema-validated before the server query runs; an unknown name is\n * denied (a `QueryError`).\n */\nexport const resolver = (\n entries: ReadonlyArray<{ readonly query: AnyQuery; readonly server: ServerQuery<any> }>\n): QueryResolver => {\n const map = new Map(entries.map((entry) => [entry.query.name, entry] as const));\n return {\n resolve: (name, encodedArgs, context) => {\n const entry = map.get(name);\n if (entry === undefined) {\n return Effect.fail(new QueryError({ message: `Unknown query: ${name}`, query: name }));\n }\n return Schema.decodeUnknownEffect(entry.query.args)(encodedArgs).pipe(\n Effect.mapError(\n (cause) =>\n new QueryError({ message: `Invalid args for query \"${name}\"`, query: name, cause })\n ),\n Effect.flatMap((args) => entry.server(args, context))\n );\n },\n };\n};\n","/**\n * Aggregate\n *\n * Serialisable aggregate descriptors over a subset's rows — count, sum, min,\n * max, average. Like {@link Predicate}, an aggregate is *data* (a tagged\n * value plus an Effect `Schema`), not an opaque function, so it can travel\n * over the wire: the local tier evaluates it in memory here, and a future\n * server-evaluated tier can carry the same descriptor unchanged.\n *\n * Evaluation is pure over already-filtered, already-sorted `(id, value)` rows\n * (the shape a subset produces): the engine hands `Subset.apply`'s result to\n * {@link compute} / {@link computeGrouped}.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as P from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\nimport * as Stream from \"effect/Stream\";\nimport * as Predicate from \"./Predicate.js\";\n\n/**\n * An aggregate descriptor.\n *\n * - `Count` counts the rows (no field).\n * - `Sum` / `Min` / `Max` / `Avg` fold a numeric row field; non-numeric field\n * values are skipped (see {@link AggregateValue} for the empty/absent\n * behaviour of each).\n */\nexport type Aggregate =\n | { readonly _tag: \"Count\" }\n | { readonly _tag: \"Sum\" | \"Min\" | \"Max\" | \"Avg\"; readonly field: string };\n\n/** Wire codec for {@link Aggregate} — a union of tagged structs (mirrors `PredicateSchema`). */\nexport const AggregateSchema: Schema.Codec<Aggregate> = Schema.Union([\n Schema.Struct({ _tag: Schema.tag(\"Count\") }),\n Schema.Struct({\n _tag: Schema.Literals([\"Sum\", \"Min\", \"Max\", \"Avg\"]),\n field: Schema.String,\n }),\n]) as Schema.Codec<Aggregate>;\n\n// ─── Constructors ────────────────────────────────────────────────────────────\n\n/** Count the rows. */\nexport const count: Aggregate = { _tag: \"Count\" };\n/** Sum a numeric field; non-numeric values are skipped. */\nexport const sum = (field: string): Aggregate => ({ _tag: \"Sum\", field });\n/** The smallest value of a numeric field; non-numeric values are skipped. */\nexport const min = (field: string): Aggregate => ({ _tag: \"Min\", field });\n/** The largest value of a numeric field; non-numeric values are skipped. */\nexport const max = (field: string): Aggregate => ({ _tag: \"Max\", field });\n/** The mean of a numeric field; non-numeric values are skipped. */\nexport const avg = (field: string): Aggregate => ({ _tag: \"Avg\", field });\n\n// ─── Evaluation ──────────────────────────────────────────────────────────────\n\n/**\n * An aggregate's value.\n *\n * - `Count` → the row count (`number`).\n * - `Sum` → the sum of numeric values; the empty (or all-non-numeric) sum is\n * `0`.\n * - `Avg` → the mean of numeric values, or `undefined` when there are none.\n * - `Min` / `Max` → the least/greatest numeric value, or `undefined` when there\n * are none.\n */\nexport type AggregateValue = number | undefined;\n\n/** A row's field as a finite number, or `undefined` if absent/non-numeric. */\nconst numericField = (value: unknown, field: string): number | undefined => {\n const raw = Predicate.fieldValue(value, field);\n return P.isNumber(raw) && Number.isFinite(raw) ? raw : undefined;\n};\n\n/** The numeric values of `field` across `rows`, skipping absent/non-numeric ones. */\nconst numericValues = (\n rows: ReadonlyArray<{ readonly value: unknown }>,\n field: string\n): ReadonlyArray<number> => {\n const values: Array<number> = [];\n for (const row of rows) {\n const value = numericField(row.value, field);\n if (value !== undefined) values.push(value);\n }\n return values;\n};\n\n/** Fold the numeric values of a non-`Count` aggregate to its value. */\nconst foldNumeric = (agg: Exclude<Aggregate, { _tag: \"Count\" }>, values: ReadonlyArray<number>) => {\n switch (agg._tag) {\n case \"Sum\":\n return values.reduce((total, value) => total + value, 0);\n case \"Avg\":\n return Arr.isReadonlyArrayEmpty(values)\n ? undefined\n : values.reduce((total, value) => total + value, 0) / values.length;\n case \"Min\":\n return Arr.isReadonlyArrayEmpty(values)\n ? undefined\n : values.reduce((a, b) => (a < b ? a : b));\n case \"Max\":\n return Arr.isReadonlyArrayEmpty(values)\n ? undefined\n : values.reduce((a, b) => (a > b ? a : b));\n }\n};\n\n/**\n * Evaluate an aggregate over already-filtered/sorted rows (a subset's result).\n * Pure and total; see {@link AggregateValue} for the empty/absent semantics.\n */\nexport const compute = (\n agg: Aggregate,\n rows: ReadonlyArray<{ readonly value: unknown }>\n): AggregateValue =>\n agg._tag === \"Count\" ? rows.length : foldNumeric(agg, numericValues(rows, agg.field));\n\n/** A row's group key: `String(row.value[groupBy])` (so `undefined` → `\"undefined\"`). */\nconst groupKey = (value: unknown, groupBy: string): string =>\n String(Predicate.fieldValue(value, groupBy));\n\n/** Partition `rows` by {@link groupKey}, preserving each group's row order. */\nconst bucketByGroup = <R extends { readonly value: unknown }>(\n rows: ReadonlyArray<R>,\n groupBy: string\n): Map<string, Array<R>> => {\n const buckets = new Map<string, Array<R>>();\n for (const row of rows) {\n const key = groupKey(row.value, groupBy);\n const bucket = buckets.get(key);\n if (bucket === undefined) buckets.set(key, [row]);\n else bucket.push(row);\n }\n return buckets;\n};\n\n/**\n * Evaluate an aggregate per group, keying the result by\n * `String(row.value[groupBy])`. Each group's value follows {@link compute}.\n */\nexport const computeGrouped = (\n agg: Aggregate,\n rows: ReadonlyArray<{ readonly value: unknown }>,\n groupBy: string\n): Record<string, AggregateValue> => {\n const result: Record<string, AggregateValue> = {};\n for (const [key, bucket] of bucketByGroup(rows, groupBy)) result[key] = compute(agg, bucket);\n return result;\n};\n\n/** Value equality for a scalar aggregate (`Object.is`, so `NaN` is stable). */\nexport const sameValue = (a: AggregateValue, b: AggregateValue): boolean => Object.is(a, b);\n\n/** Structural equality for a grouped aggregate: same keys, same values. */\nexport const sameGroupedValue = (\n a: Record<string, AggregateValue>,\n b: Record<string, AggregateValue>\n): boolean => {\n const keys = Object.keys(a);\n return (\n keys.length === Object.keys(b).length &&\n keys.every((key) => Object.hasOwn(b, key) && Object.is(a[key], b[key]))\n );\n};\n\n// ─── Incremental maintenance ───────────────────────────────────────────────\n//\n// `compute`/`computeGrouped` fold a full page; when a live subset's rows are\n// known to change by row-level delta (a `Patch`'s put/del ops — `ClientEngine`\n// feeds these directly, not pre-filtered), the fold can be *maintained*\n// instead of re-run every emission. `Count`/`Sum`/`Avg` update in O(1) per\n// delta (subtract on removal, add on insertion, both on an update).\n// `Min`/`Max` update in O(1) except when the row removed or updated away held\n// the current extremum, in which case the surviving values are refolded — the\n// same \"scan the bag\" approach `@tanstack/db-ivm` uses, since retracting a\n// min/max isn't subtractable in general.\n//\n// A delta's row is tested against `where` here (mirrors `LiveView.put`'s\n// match/no-longer-match handling), so the caller can feed raw put/del ops\n// without pre-filtering: a `Put` whose value now fails `where` is folded as a\n// removal, one that now passes is folded as an insertion (or update, if the\n// row was already present).\n//\n// This state is internal and mutated in place by `applyPut`/`applyDel` for\n// true O(1) amortized cost — callers (`ClientEngine`) own one `State` per live\n// subscription behind a `Ref`, so there is exactly one owner at a time and no\n// aliasing concern.\n\n/** A non-`Count` aggregate's field, or `undefined` for `Count` (no field). */\nconst fieldOf = (agg: Aggregate): string | undefined =>\n agg._tag === \"Count\" ? undefined : agg.field;\n\n/** One aggregate's running fold — mutated in place by `addToBucket`/`removeFromBucket`. */\ntype Bucket =\n | { readonly _tag: \"Count\"; count: number }\n | { readonly _tag: \"Sum\"; sum: number }\n | { readonly _tag: \"Avg\"; sum: number; count: number }\n | {\n readonly _tag: \"MinMax\";\n readonly pick: (a: number, b: number) => number;\n current: number | undefined;\n };\n\nconst emptyBucket = (agg: Aggregate): Bucket => {\n switch (agg._tag) {\n case \"Count\":\n return { _tag: \"Count\", count: 0 };\n case \"Sum\":\n return { _tag: \"Sum\", sum: 0 };\n case \"Avg\":\n return { _tag: \"Avg\", sum: 0, count: 0 };\n case \"Min\":\n return { _tag: \"MinMax\", pick: (a, b) => (a < b ? a : b), current: undefined };\n case \"Max\":\n return { _tag: \"MinMax\", pick: (a, b) => (a > b ? a : b), current: undefined };\n }\n};\n\nconst bucketValue = (bucket: Bucket): AggregateValue => {\n switch (bucket._tag) {\n case \"Count\":\n return bucket.count;\n case \"Sum\":\n return bucket.sum;\n case \"Avg\":\n return bucket.count === 0 ? undefined : bucket.sum / bucket.count;\n case \"MinMax\":\n return bucket.current;\n }\n};\n\n/** Fold one row's value into `bucket` (an insertion, or an update's \"add\" half). */\nconst addToBucket = (bucket: Bucket, value: unknown, field: string | undefined): void => {\n if (bucket._tag === \"Count\") {\n bucket.count += 1;\n return;\n }\n // Only `Count` has no field, and it returned above.\n if (field === undefined) return;\n const n = numericField(value, field);\n if (n === undefined) return;\n switch (bucket._tag) {\n case \"Sum\":\n bucket.sum += n;\n return;\n case \"Avg\":\n bucket.sum += n;\n bucket.count += 1;\n return;\n case \"MinMax\":\n bucket.current = bucket.current === undefined ? n : bucket.pick(bucket.current, n);\n return;\n }\n};\n\n/**\n * Retract one row's value from `bucket` (a removal, or an update's \"remove\"\n * half). `remainingValues` is called only when `Min`/`Max` loses its current\n * extremum — it must return the numeric values still present *after* this\n * row's removal, so the refold is O(the surviving bag), not O(1) but never\n * more than the group it belongs to.\n */\nconst removeFromBucket = (\n bucket: Bucket,\n value: unknown,\n field: string | undefined,\n remainingValues: () => ReadonlyArray<number>\n): void => {\n if (bucket._tag === \"Count\") {\n bucket.count -= 1;\n return;\n }\n // Only `Count` has no field, and it returned above.\n if (field === undefined) return;\n const n = numericField(value, field);\n if (n === undefined) return;\n switch (bucket._tag) {\n case \"Sum\":\n bucket.sum -= n;\n return;\n case \"Avg\":\n bucket.sum -= n;\n bucket.count -= 1;\n return;\n case \"MinMax\": {\n if (n !== bucket.current) return; // not the extremum: O(1), no refold needed\n const rest = remainingValues();\n bucket.current = Arr.isReadonlyArrayEmpty(rest) ? undefined : rest.reduce(bucket.pick);\n return;\n }\n }\n};\n\n/** The numeric values of `byId`'s field, skipping absent/non-numeric ones. */\nconst numericValuesOf = (\n byId: ReadonlyMap<string, unknown>,\n field: string\n): ReadonlyArray<number> => {\n const values: Array<number> = [];\n for (const value of byId.values()) {\n const n = numericField(value, field);\n if (n !== undefined) values.push(n);\n }\n return values;\n};\n\n/** A `(id, value)` row — the unit incremental maintenance operates over. */\nexport interface Row {\n readonly id: string;\n readonly value: unknown;\n}\n\n/**\n * Incremental state for one (ungrouped) aggregate: `byId` mirrors the rows\n * currently matching `where` (needed to tell an insert from an update from a\n * no-longer-matching removal), `bucket` is the running fold.\n */\nexport interface State {\n readonly byId: Map<string, unknown>;\n readonly bucket: Bucket;\n}\n\n/** Build state from already-filtered rows (mirrors {@link compute}'s input) — the Rebuild/subscribe-time path. */\nexport const initState = (agg: Aggregate, rows: ReadonlyArray<Row>): State => {\n const field = fieldOf(agg);\n const byId = new Map<string, unknown>();\n const bucket = emptyBucket(agg);\n for (const row of rows) {\n byId.set(row.id, row.value);\n addToBucket(bucket, row.value, field);\n }\n return { byId, bucket };\n};\n\n/**\n * Apply a row upsert against `where`: folds as an insertion, an update, a\n * removal (row matched before but not now), or a no-op (never matched),\n * exactly mirroring {@link LiveView.put}'s match/no-longer-match handling.\n * Mutates and returns `state`.\n */\nexport const applyPut = (\n state: State,\n agg: Aggregate,\n where: Predicate.Predicate,\n id: string,\n value: unknown\n): State => {\n const field = fieldOf(agg);\n const existing = state.byId.get(id);\n const matches = Predicate.test(where, value);\n if (existing === undefined && !matches) return state;\n if (existing !== undefined) {\n state.byId.delete(id);\n removeFromBucket(state.bucket, existing, field, () =>\n field === undefined ? [] : numericValuesOf(state.byId, field)\n );\n }\n if (matches) {\n state.byId.set(id, value);\n addToBucket(state.bucket, value, field);\n }\n return state;\n};\n\n/** Apply a row deletion. A no-op if `id` never matched. Mutates and returns `state`. */\nexport const applyDel = (state: State, agg: Aggregate, id: string): State => {\n const existing = state.byId.get(id);\n if (existing === undefined) return state;\n const field = fieldOf(agg);\n state.byId.delete(id);\n removeFromBucket(state.bucket, existing, field, () =>\n field === undefined ? [] : numericValuesOf(state.byId, field)\n );\n return state;\n};\n\n/** The current value of an incrementally-maintained (ungrouped) aggregate. */\nexport const stateValue = (state: State): AggregateValue => bucketValue(state.bucket);\n\n/**\n * Incremental state for a grouped aggregate: `groupKeyOf` tracks each\n * currently-matching row's group key (so a moved row's old group can be\n * found), `groups` holds one {@link State} per key present.\n */\nexport interface GroupedState {\n readonly groupKeyOf: Map<string, string>;\n readonly groups: Map<string, State>;\n}\n\n/** Build grouped state from already-filtered rows (mirrors {@link computeGrouped}'s input). */\nexport const initGroupedState = (\n agg: Aggregate,\n rows: ReadonlyArray<Row>,\n groupBy: string\n): GroupedState => {\n const groups = new Map<string, State>();\n const groupKeyOf = new Map<string, string>();\n for (const [key, bucketRows] of bucketByGroup(rows, groupBy)) {\n groups.set(key, initState(agg, bucketRows));\n for (const row of bucketRows) groupKeyOf.set(row.id, key);\n }\n return { groupKeyOf, groups };\n};\n\n/**\n * Apply a row upsert against `where`/`groupBy`: touches only the row's old\n * group (if it moved or left) and new group (if it now matches) — every\n * other group's {@link State} is untouched, so its value is unchanged by\n * reference as well as by value. A group whose last row leaves is dropped, so\n * the emitted record never carries an empty key (matching\n * {@link computeGrouped}). Mutates and returns `state`.\n */\nexport const applyGroupedPut = (\n state: GroupedState,\n agg: Aggregate,\n where: Predicate.Predicate,\n groupBy: string,\n id: string,\n value: unknown\n): GroupedState => {\n const matches = Predicate.test(where, value);\n const existingKey = state.groupKeyOf.get(id);\n const newKey = matches ? groupKey(value, groupBy) : undefined;\n if (existingKey === undefined && newKey === undefined) return state;\n\n if (existingKey !== undefined && existingKey !== newKey) {\n const oldGroup = state.groups.get(existingKey);\n if (oldGroup !== undefined) {\n applyDel(oldGroup, agg, id);\n if (oldGroup.byId.size === 0) state.groups.delete(existingKey);\n }\n }\n\n if (newKey === undefined) {\n state.groupKeyOf.delete(id);\n return state;\n }\n\n let newGroup = state.groups.get(newKey);\n if (newGroup === undefined) {\n newGroup = initState(agg, []);\n state.groups.set(newKey, newGroup);\n }\n applyPut(newGroup, agg, where, id, value);\n state.groupKeyOf.set(id, newKey);\n return state;\n};\n\n/** Apply a row deletion. A no-op if `id` never matched. Mutates and returns `state`. */\nexport const applyGroupedDel = (state: GroupedState, agg: Aggregate, id: string): GroupedState => {\n const existingKey = state.groupKeyOf.get(id);\n if (existingKey === undefined) return state;\n const group = state.groups.get(existingKey);\n if (group !== undefined) {\n applyDel(group, agg, id);\n if (group.byId.size === 0) state.groups.delete(existingKey);\n }\n state.groupKeyOf.delete(id);\n return state;\n};\n\n/** The current value of an incrementally-maintained grouped aggregate. */\nexport const groupedStateValue = (state: GroupedState): Record<string, AggregateValue> => {\n const result: Record<string, AggregateValue> = {};\n for (const [key, group] of state.groups) result[key] = bucketValue(group.bucket);\n return result;\n};\n\n/**\n * Live aggregate over a stream of row pages (any {@link ClientView.observe}\n * source — engine or mirror): {@link compute} per emission, deduped so the\n * stream re-emits only when the value actually changes.\n */\nexport const observe = <E>(\n rows: Stream.Stream<ReadonlyArray<{ readonly value: unknown }>, E>,\n agg: Aggregate\n): Stream.Stream<AggregateValue, E> =>\n rows.pipe(\n Stream.map((page) => compute(agg, page)),\n Stream.changesWith(sameValue)\n );\n\n/** Live grouped aggregate over a stream of row pages; see {@link observe}. */\nexport const observeGrouped = <E>(\n rows: Stream.Stream<ReadonlyArray<{ readonly value: unknown }>, E>,\n agg: Aggregate,\n groupBy: string\n): Stream.Stream<Record<string, AggregateValue>, E> =>\n rows.pipe(\n Stream.map((page) => computeGrouped(agg, page, groupBy)),\n Stream.changesWith(sameGroupedValue)\n );\n","/**\n * Mutator\n *\n * A mutator is a named, schema-validated write intent defined once and\n * executed twice: optimistically on the client and authoritatively on the\n * backend (ADR-0008). The two implementations may differ — the backend adds\n * validation, permissions, and side effects; conflict resolution IS replay.\n *\n * The mutator *definition* (name + args schema) is shared code. Client\n * handlers receive a local write surface (LocalWriter); backend handlers\n * are supplied by the app inside its own transaction (Backend.ts).\n */\n\nimport * as Arr from \"effect/Array\";\nimport type * as Effect from \"effect/Effect\";\nimport type * as Schema from \"effect/Schema\";\nimport type { RowId } from \"./Collection.js\";\nimport { DuplicateNameError, type MutatorError, type StoreError } from \"./Errors.js\";\n\n/** A mutator definition: the shared, serializable contract. */\nexport interface Mutator<Name extends string, Args, ArgsEncoded = unknown> {\n readonly name: Name;\n readonly args: Schema.Codec<Args, ArgsEncoded>;\n}\n\n/** Any {@link Mutator} definition, whatever its name and args. */\nexport type AnyMutator = Mutator<string, any, any>;\n\n/** Define a mutator contract. */\nexport const make = <const Name extends string, Args, ArgsEncoded>(\n name: Name,\n args: Schema.Codec<Args, ArgsEncoded>\n): Mutator<Name, Args, ArgsEncoded> => ({ name, args });\n\n/**\n * The local write surface handed to client-side mutator handlers. Writes\n * apply to the optimistic overlay only; authoritative versions arrive via\n * patches. Handlers must be re-runnable: they execute once optimistically\n * and again on every rebase.\n */\nexport interface LocalWriter {\n readonly put: (collection: string, id: RowId, value: unknown) => Effect.Effect<void, StoreError>;\n readonly del: (collection: string, id: RowId) => Effect.Effect<void, StoreError>;\n /** Read through confirmed rows + overlay (current local view). */\n readonly get: (collection: string, id: RowId) => Effect.Effect<unknown | undefined, StoreError>;\n}\n\n/** A client-side handler for one mutator. */\nexport type LocalHandler<Args> = (\n args: Args,\n writer: LocalWriter\n) => Effect.Effect<void, MutatorError | StoreError>;\n\n/** A set of mutator definitions plus their client-side handlers. */\nexport interface MutatorRegistry {\n readonly mutators: ReadonlyMap<string, AnyMutator>;\n readonly handlers: ReadonlyMap<string, LocalHandler<any>>;\n}\n\n/** Pair mutator definitions with client handlers. Duplicate names throw. */\nexport const registry = (\n entries: ReadonlyArray<{ readonly mutator: AnyMutator; readonly local: LocalHandler<any> }>\n): MutatorRegistry => {\n const mutators = new Map<string, AnyMutator>();\n const handlers = new Map<string, LocalHandler<any>>();\n Arr.forEach(entries, ({ mutator, local }) => {\n if (mutators.has(mutator.name)) {\n throw new DuplicateNameError({ kind: \"mutator\", name: mutator.name });\n }\n mutators.set(mutator.name, mutator);\n handlers.set(mutator.name, local);\n });\n return { mutators, handlers };\n};\n","/**\n * AtomicKeyValue\n *\n * An optional seam over a key-value store: a batch of `set` and `remove`\n * operations that commits all of its operations or none of them (#393). When\n * it is in context, {@link ClientStore.makeKeyValue} writes a pull's rows, its\n * cookie, its journal trim and its tail release as one batch, with no release\n * record; without it the store keeps the release-record path (#387), so a\n * third-party `KeyValueStore` behaves exactly as before.\n *\n * Effect's `KeyValueStore` has no transactions and no multi-key writes, so the\n * batch is a separate service that a host supplies over the same backing store\n * the `KeyValueStore` reads. The browser's IndexedDB binding is\n * `@thomasfosterau/legation-browser`'s `IndexedDbClientStore`.\n */\n\nimport * as Context from \"effect/Context\";\nimport type * as Effect from \"effect/Effect\";\nimport type { StoreError } from \"./Errors.js\";\n\n/**\n * One operation of an atomic batch. `key` is the full key the backing store\n * holds, namespace prefix included, exactly as the `KeyValueStore` underneath\n * stores it. `value` is the string the store would hold for a `set`.\n */\nexport type KeyValueOp =\n | { readonly _tag: \"Set\"; readonly key: string; readonly value: string }\n | { readonly _tag: \"Remove\"; readonly key: string };\n\n/** One string entry the backing store holds: its full key and its value. */\nexport interface KeyValueEntry {\n readonly key: string;\n readonly value: string;\n}\n\n/** The {@link AtomicKeyValue} service: an atomic batch over the store's keys. */\nexport interface AtomicKeyValue {\n /**\n * Commit `ops` in order as one all-or-nothing step. Up to the commit point, a\n * failure or an interruption leaves none of the operations durable. A failure\n * reported after the commit point may still have committed, so a caller must\n * treat that outcome as unknown and re-read the store before relying on it. On\n * success every operation is durable. A later operation on a key replaces an\n * earlier one in the same batch.\n */\n readonly apply: (ops: ReadonlyArray<KeyValueOp>) => Effect.Effect<void, StoreError>;\n /**\n * Every string entry the backing store holds, read in one read transaction, so the\n * result is one state of the store: a batch committed by another connection is\n * either wholly in it or wholly absent (#392). Optional: a store without it reads\n * its keys one at a time, which a concurrent connection can straddle.\n */\n readonly readAll?: Effect.Effect<ReadonlyArray<KeyValueEntry>, StoreError> | undefined;\n}\n\n/**\n * The atomic batch seam (#393), optional: a `ClientStore` reads it with\n * `Effect.serviceOption` and falls back to its release-record path when absent.\n */\nexport const AtomicKeyValue = Context.Service<AtomicKeyValue>(\n \"@thomasfosterau/legation/AtomicKeyValue\"\n);\n","/**\n * Identity\n *\n * The client half of the identity boundary. Identity itself is resolved\n * **server-side, per pull** (`Authorization.IdentityResolver`) — that is what\n * makes the auth filter trustworthy — but the durable replica a client keeps\n * on the device has to record *which* resolved identity authorised the rows\n * it holds, or the next principal to open the app boots onto them.\n *\n * The invariant (CONTEXT.md, \"Identity boundary\"): **a durable replica\n * belongs to exactly one resolved identity, and an identity change is a\n * reset, not a rebase.**\n *\n * The engine's handle on that identity is a {@link Fingerprint}: an opaque,\n * app-supplied token the store stamps beside the rows and compares on boot.\n * Everything else here is the transition rule — the single decision, applied\n * identically at boot (`ClientStore` open) and at runtime\n * (`Client.reset`), that says whether a replica survives an identity change.\n */\n\n/**\n * An opaque token standing for \"who this replica belongs to\".\n *\n * **Never PII and never a credential.** The obvious wrong things to pass are\n * a user id, an email address, a session token, or a JWT: this value is\n * written to durable device storage (IndexedDB in a browser), read back on\n * every boot, and — when used for namespacing — appears in store key\n * prefixes and database names. Pass a **hash of the session subject** (for\n * example `sha256(issuer + subject)` truncated), computed by the app.\n *\n * The engine never parses, interprets, or transmits a fingerprint; it only\n * ever compares two of them for equality. Two sessions of the same principal\n * must produce the same fingerprint, and two different principals must not\n * — that is the whole contract.\n *\n * Values beginning with `@legation/` are **reserved** for the sentinels\n * below; an app-computed fingerprint must not use that prefix.\n */\nexport type Fingerprint = string;\n\n/**\n * The signed-out principal: the replica holds only what a public, unauthenticated\n * session may read. Pass this explicitly while no one is signed in — it is what\n * makes the anonymous → signed-in {@link Transition} (\"Upgrade\") representable,\n * and a replica stamped anonymous is the only one a sign-in is allowed to keep.\n */\nexport const anonymous: Fingerprint = \"@legation/anonymous\";\n\n/**\n * The implied fingerprint of a store that has never been stamped — a replica\n * written by a build (or a configuration) with no identity boundary, whose\n * rows could belong to anyone.\n *\n * It is never equal to a real fingerprint and never equal to\n * {@link anonymous}, so adopting *any* identity over an unstamped replica is\n * a reset. That costs one full re-pull the first time an app turns identity\n * scoping on, which is the safe direction: an unstamped replica is exactly\n * the state this boundary exists to distrust.\n */\nexport const unstamped: Fingerprint = \"@legation/unstamped\";\n\n/**\n * What adopting a new fingerprint over the stamped one does to the replica.\n *\n * - `Unchanged` — same principal; nothing happens.\n * - `Upgrade` — anonymous → signed in. **The one benign transition**: the\n * rows a public session synced are a subset of what the new identity may\n * read, so the warm replica (and the journal — the same person made those\n * writes on this device moments earlier) survives. Needlessly discarding\n * here would be a real regression on the commonest first-sign-in path.\n * - `Reset` — every other change, sign-out included. Rows, cookie and\n * subscriptions go; unpushed journal entries are quarantined under the\n * superseded fingerprint rather than discarded or adopted.\n */\nexport type Transition = \"Unchanged\" | \"Upgrade\" | \"Reset\";\n\n/**\n * The transition rule, in one place, so boot and runtime cannot disagree\n * about it. `current` is the stamped fingerprint, or {@link unstamped} when\n * the store carries no stamp.\n */\nexport const transitionOf = (current: Fingerprint, next: Fingerprint): Transition => {\n if (current === next) return \"Unchanged\";\n return current === anonymous && next !== unstamped ? \"Upgrade\" : \"Reset\";\n};\n\n/**\n * A fingerprint rendered safe to embed in a storage key — a store key\n * prefix, an IndexedDB database name — for the namespacing alternative to\n * resetting (`IndexedDbClientStore.layerNamespaced`). Percent-encoding keeps\n * two distinct fingerprints distinct.\n */\nexport const keySegment = (fingerprint: Fingerprint): string => encodeURIComponent(fingerprint);\n","/**\n * Protocol\n *\n * The sync protocol's schema-defined messages (ADR-0008). Mutator intents\n * flow up (push); server-computed state patches flow down (pull). The\n * protocol is carrier-agnostic: any transport that can move these messages\n * qualifies (Transport.ts), with the RPC implementation as the default.\n *\n * `Pull(cookie) → patch` is the canonical correctness path: sync must be\n * correct over pull alone. Pokes and streamed patches are optimizations.\n */\n\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\nimport { ProtocolError } from \"./Errors.js\";\nimport { Subset } from \"./Subset.js\";\n\n// ─── Mutations (upstream) ────────────────────────────────────────────────────\n\n/**\n * One invocation of a mutator: name + args + per-client sequence number.\n * `mutationId` is sequential per client, giving the backend exactly-once,\n * in-order application and giving the client precise acknowledgement.\n */\nexport const Mutation = Schema.Struct({\n clientId: Schema.String,\n mutationId: Schema.Number,\n mutator: Schema.String,\n args: Schema.Unknown,\n /** Client wall-clock at creation; informational only. */\n createdAt: Schema.Number,\n});\n\n/** The type {@link Mutation} decodes to. */\nexport type Mutation = typeof Mutation.Type;\n\n/** Push request: pending mutations in journal order. */\nexport const PushRequest = Schema.Struct({\n clientGroupId: Schema.String,\n mutations: Schema.Array(Mutation),\n /**\n * The client build's schema version (#48). Additive and optional: an old\n * client omits it and still decodes, a new server tolerates its absence. The\n * server's acceptor may reject an unsupported version up front\n * (VersionNotSupportedError) so an obsolete build is told to update.\n */\n schemaVersion: Schema.optional(Schema.String),\n});\n\n/** The type {@link PushRequest} decodes to. */\nexport type PushRequest = typeof PushRequest.Type;\n\n/**\n * A mutation the backend permanently rejected: its id is acknowledged, but its\n * effects were not applied, and `reason` is the backend's stated cause.\n */\nexport const RejectedMutation = Schema.Struct({\n clientId: Schema.String,\n mutationId: Schema.Number,\n reason: Schema.String,\n});\n\n/** The type {@link RejectedMutation} decodes to. */\nexport type RejectedMutation = typeof RejectedMutation.Type;\n\n/**\n * Push response: the highest mutation id the backend has applied, per\n * client. Mutations at or below these ids are acknowledged; effects arrive\n * via the next pull's patch, which is when the optimistic overlay drops.\n */\nexport const PushResponse = Schema.Struct({\n lastMutationIds: Schema.Record(Schema.String, Schema.Number),\n /**\n * Mutations the backend permanently rejected: their `lastMutationId` is\n * bumped (so they are acknowledged and skipped, never poisoning the queue)\n * but their effects were not applied. Additive and optional, so older clients\n * ignore it; the per-mutation outcome surface (#36) reads it.\n */\n rejected: Schema.optional(Schema.Array(RejectedMutation)),\n});\n\n/** The type {@link PushResponse} decodes to. */\nexport type PushResponse = typeof PushResponse.Type;\n\n// ─── Patches (downstream) ────────────────────────────────────────────────────\n\n/**\n * One patch operation. `Put` and `Del` address rows; `Clear` resets the\n * client's view (sent when the server does not recognize the cookie).\n */\nexport const PatchOp = Schema.Union([\n Schema.Struct({\n _tag: Schema.tag(\"Put\"),\n collection: Schema.String,\n id: Schema.String,\n version: Schema.Union([Schema.String, Schema.Number]),\n value: Schema.Unknown,\n }),\n Schema.Struct({ _tag: Schema.tag(\"Del\"), collection: Schema.String, id: Schema.String }),\n Schema.Struct({ _tag: Schema.tag(\"Clear\") }),\n]);\n\n/** The type {@link PatchOp} decodes to. */\nexport type PatchOp = typeof PatchOp.Type;\n\n/** A named-query subscription: resolved to a Subset server-side (Query.ts). */\nexport const NamedSubscription = Schema.Struct({\n name: Schema.String,\n args: Schema.Unknown,\n});\n\n/** The type {@link NamedSubscription} decodes to. */\nexport type NamedSubscription = typeof NamedSubscription.Type;\n\n/** Pull request: what the client has (cookie) and wants (subsets). */\nexport const PullRequest = Schema.Struct({\n clientGroupId: Schema.String,\n /** Cookie from the previous pull; absent on first sync. */\n cookie: Schema.optional(Schema.String),\n subscriptions: Schema.Array(Subset),\n /** Named queries the server resolves to subsets (optional). */\n namedSubscriptions: Schema.optional(Schema.Array(NamedSubscription)),\n /** {@inheritDoc PushRequest.schemaVersion} */\n schemaVersion: Schema.optional(Schema.String),\n});\n\n/** The type {@link PullRequest} decodes to. */\nexport type PullRequest = typeof PullRequest.Type;\n\n/**\n * Pull response: patch to the new cookie, plus mutation acknowledgements.\n *\n * A pull acknowledges every id its `lastMutationIds` covers, and a permanently\n * rejected id is one of them (its bump is what makes it acknowledged). So the\n * response also carries the rejections the watermark covers (#365): the client\n * settles those entries as rejected, not applied, before it acknowledges the\n * rest. The list is additive and optional, like the push response's: an older\n * client ignores it and keeps its previous settlement, and a pull from an older\n * server omits it, which the client reads as none. No protocol version bump\n * is needed, since neither side fails to decode the other's response.\n */\nexport const PullResponse = Schema.Struct({\n cookie: Schema.String,\n patch: Schema.Array(PatchOp),\n lastMutationIds: Schema.Record(Schema.String, Schema.Number),\n /**\n * The permanently rejected mutations of this client group that\n * `lastMutationIds` covers, each with its reason. Omitted when none.\n */\n rejected: Schema.optional(Schema.Array(RejectedMutation)),\n});\n\n/** The type {@link PullResponse} decodes to. */\nexport type PullResponse = typeof PullResponse.Type;\n\n/**\n * Read request: a point-in-time batch subset evaluation (ADR-0025) — the\n * server-fallthrough tier. Evaluated under the same auth filters as pull,\n * with **no CVR involvement**: no cookie, no registration, no\n * `lastMutationIds`.\n */\nexport const ReadRequest = Schema.Struct({\n clientGroupId: Schema.String,\n subsets: Schema.Array(Subset),\n /** {@inheritDoc PushRequest.schemaVersion} */\n schemaVersion: Schema.optional(Schema.String),\n});\n\n/** The type {@link ReadRequest} decodes to. */\nexport type ReadRequest = typeof ReadRequest.Type;\n\n/** Read response: the matching rows, point-in-time. */\nexport const ReadResponse = Schema.Struct({\n rows: Schema.Array(\n Schema.Struct({\n collection: Schema.String,\n id: Schema.String,\n version: Schema.Union([Schema.String, Schema.Number]),\n value: Schema.Unknown,\n })\n ),\n});\n\n/** The type {@link ReadResponse} decodes to. */\nexport type ReadResponse = typeof ReadResponse.Type;\n\n/** A contentless \"pull soon\" hint. */\nexport const Poke = Schema.Struct({\n reason: Schema.optional(Schema.String),\n});\n\n/** The type {@link Poke} decodes to. */\nexport type Poke = typeof Poke.Type;\n\n// ─── Decode helpers ──────────────────────────────────────────────────────────\n\nconst decodeWith =\n <A>(schema: Schema.Codec<A>, what: string) =>\n (input: unknown): Effect.Effect<A, ProtocolError> =>\n Schema.decodeUnknownEffect(schema)(input).pipe(\n Effect.mapError((cause) => new ProtocolError({ message: `Invalid ${what}`, cause }))\n );\n\n/**\n * Decode an untrusted push request; fails with `ProtocolError` when it doesn't match the schema.\n */\nexport const decodePushRequest = decodeWith(PushRequest, \"push request\");\n/**\n * Decode an untrusted pull request; fails with `ProtocolError` when it doesn't match the schema.\n */\nexport const decodePullRequest = decodeWith(PullRequest, \"pull request\");\n/**\n * Decode an untrusted read request; fails with `ProtocolError` when it doesn't match the schema.\n */\nexport const decodeReadRequest = decodeWith(ReadRequest, \"read request\");\n/** Decode a push response; fails with `ProtocolError` when it doesn't match the schema. */\nexport const decodePushResponse = decodeWith(PushResponse, \"push response\");\n/** Decode a pull response; fails with `ProtocolError` when it doesn't match the schema. */\nexport const decodePullResponse = decodeWith(PullResponse, \"pull response\");\n/** Decode one patch operation; fails with `ProtocolError` when it doesn't match the schema. */\nexport const decodePatchOp = decodeWith(PatchOp, \"patch op\");\n","/**\n * ClientStore\n *\n * The client's durable state: confirmed rows per collection, the journal of\n * pending mutations, and the pull cookie. Every engine state transition is\n * persisted here so a killed host (notably a service worker, ADR-0010)\n * rehydrates losslessly.\n *\n * Rows stored here are *confirmed* (authoritative) state only; optimistic\n * effects live in the overlay and are recomputed by replay, never persisted\n * as rows.\n *\n * The store is also where the **identity boundary** lives (CONTEXT.md): it\n * stamps the {@link Identity.Fingerprint} whose session authorised the rows\n * it holds, compares that stamp on open, and owns the **quarantine** — the\n * keyspace a superseded identity's unpushed journal entries move to, so they\n * are neither discarded nor adopted by the next principal.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as P from \"effect/Predicate\";\nimport * as R from \"effect/Record\";\nimport * as Ref from \"effect/Ref\";\nimport * as Schema from \"effect/Schema\";\nimport * as Semaphore from \"effect/Semaphore\";\nimport { KeyValueStore } from \"effect/persistence\";\nimport { AtomicKeyValue, type KeyValueEntry, type KeyValueOp } from \"./AtomicKeyValue.js\";\nimport type { RowId } from \"./Collection.js\";\nimport { StoreError } from \"./Errors.js\";\nimport * as Identity from \"./Identity.js\";\nimport { Mutation, PatchOp } from \"./Protocol.js\";\n\n/**\n * A confirmed row as persisted: encoded value + authoritative version. The\n * schema validates the row *envelope* on read; `value` stays `Unknown` and\n * is carried through untouched, so additive schema changes round-trip\n * (ADR-0014: the engine never decodes row values on the read path).\n */\nexport const StoredRow = Schema.Struct({\n id: Schema.String,\n version: Schema.Union([Schema.String, Schema.Number]),\n value: Schema.Unknown,\n});\n\n/** The type {@link StoredRow} decodes to. */\nexport type StoredRow = typeof StoredRow.Type;\n\n/**\n * What a {@link ClientStore.compactPending} call did: the ids dropped, and the\n * surviving entries it moved (`from` is the id before, `to` the id after).\n * Both empty when nothing was eligible.\n */\nexport interface CompactionResult {\n readonly dropped: ReadonlyArray<number>;\n readonly renumbered: ReadonlyArray<{ readonly from: number; readonly to: number }>;\n}\n\n/** The empty {@link CompactionResult}: nothing was dropped or moved. */\nexport const NO_COMPACTION: CompactionResult = { dropped: [], renumbered: [] };\n\n/** What a journal entry must expose for {@link planCompaction}: its owner and id. */\ninterface Numbered {\n readonly clientId: string;\n readonly mutationId: number;\n}\n\n/** A computed compaction: its result plus the journal and counter it leaves behind. */\ninterface CompactionPlan<T extends Numbered> {\n readonly result: CompactionResult;\n /** The whole journal after the compaction, in order (other clients untouched). */\n readonly journal: ReadonlyArray<T>;\n /** The id `clientId`'s counter must hold afterwards, so the next id continues the run. */\n readonly counter: number;\n}\n\n/**\n * Plan a compaction over the whole `journal` for `clientId`. Pure and generic\n * over the entry shape, so the memory store plans over full mutations while\n * the durable store plans over its compact index (ids only, #249 review S3:\n * a paced flush must not read every body in the journal). Shared so both\n * agree on the rule.\n *\n * Eligible ids: pending, `clientId`'s own, above `sentUpTo`. Survivors above\n * `sentUpTo` take consecutive ids after the anchor, in journal order; the\n * anchor is the highest frozen id still pending, or the lowest pending id\n * minus one when nothing is frozen (the journal is contiguous from the last\n * acknowledged id, so that is `lastAcknowledged`). Frozen entries are never\n * touched.\n */\nconst planCompaction = <T extends Numbered>(\n journal: ReadonlyArray<T>,\n clientId: string,\n mutationIds: ReadonlyArray<number>,\n sentUpTo: number\n): CompactionPlan<T> | undefined => {\n const wanted = new Set(mutationIds);\n const mine = journal.filter((m) => m.clientId === clientId);\n const dropped = mine\n .filter((m) => m.mutationId > sentUpTo && wanted.has(m.mutationId))\n .map((m) => m.mutationId);\n if (Arr.isReadonlyArrayEmpty(dropped)) return undefined;\n const droppedSet = new Set(dropped);\n const frozen = mine.filter((m) => m.mutationId <= sentUpTo);\n const anchor = Arr.isReadonlyArrayNonEmpty(frozen)\n ? Math.max(...frozen.map((m) => m.mutationId))\n : Math.min(...mine.map((m) => m.mutationId)) - 1;\n const renumbered: Array<{ from: number; to: number }> = [];\n const after: Array<T> = [];\n let next = anchor;\n for (const m of journal) {\n if (m.clientId !== clientId || m.mutationId <= sentUpTo) {\n after.push(m);\n continue;\n }\n if (droppedSet.has(m.mutationId)) continue;\n next += 1;\n if (next === m.mutationId) {\n after.push(m);\n continue;\n }\n renumbered.push({ from: m.mutationId, to: next });\n after.push({ ...m, mutationId: next });\n }\n return { result: { dropped, renumbered }, journal: after, counter: next };\n};\n\n/**\n * A replica read as one state: the rows, the cookie, the journal, the unpulled tail and the mutation\n * counters (see {@link ClientStore.snapshot}, #392, #271).\n */\nexport interface ReplicaState {\n /** Every confirmed row, tagged with the collection it belongs to. */\n readonly rows: ReadonlyArray<{ readonly collection: string; readonly row: StoredRow }>;\n /** The pull cookie, or `undefined` when none is stored. */\n readonly cookie: string | undefined;\n /** The pending-mutation journal, in order. */\n readonly journal: ReadonlyArray<Mutation>;\n /** The acknowledged-but-unpulled tail, oldest first. */\n readonly unpulled: ReadonlyArray<Mutation>;\n /** Each client's mutation id counter, as {@link ClientStore.mutationCounters} reads it. */\n readonly counters: Readonly<Record<string, number>>;\n}\n\n/** A client's durable state: confirmed rows, the pending-mutation journal and the sync cookie. */\nexport interface ClientStore {\n // Confirmed rows\n readonly getRow: (\n collection: string,\n id: RowId\n ) => Effect.Effect<StoredRow | undefined, StoreError>;\n readonly listRows: (collection: string) => Effect.Effect<ReadonlyArray<StoredRow>, StoreError>;\n /** Every collection that currently holds confirmed rows — the enumeration `dehydrate` walks. */\n readonly listCollections: Effect.Effect<ReadonlyArray<string>, StoreError>;\n readonly putRow: (collection: string, row: StoredRow) => Effect.Effect<void, StoreError>;\n readonly delRow: (collection: string, id: RowId) => Effect.Effect<void, StoreError>;\n readonly clearRows: Effect.Effect<void, StoreError>;\n /**\n * Apply a batch of patch ops (`Put`/`Del`/`Clear`) in one pass. Additive\n * bulk write for the pull path: grouping ops by collection lets the durable\n * store rewrite each touched collection's id-index at most once per batch —\n * so a K-op patch on a large collection writes K row values plus ~1 index per\n * collection, not the whole collection K times (#47). A `Clear` resets rows.\n */\n readonly applyRowOps: (ops: ReadonlyArray<PatchOp>) => Effect.Effect<void, StoreError>;\n\n // Journal\n /**\n * Append `mutation` to the journal. Its precondition is that the unpulled tail does not hold the\n * entry: a journal copy of a parked entry would be double-counted by reads and pushed again. So an\n * append for an id the tail holds fails with a `StoreError` and writes nothing. A caller that\n * replays entries from elsewhere, such as `Hydration.hydrate`, skips the ids the tail holds first.\n */\n readonly appendMutation: (mutation: Mutation) => Effect.Effect<void, StoreError>;\n /**\n * Allocate the client's next mutation id **and** append the entry as one\n * store step (#258), returning the journaled mutation (id included).\n *\n * This is how the engine journals. Allocating with\n * {@link ClientStore.nextMutationId} and then calling\n * {@link ClientStore.appendMutation} burns the id whenever the append is\n * refused (`journalHighWater`) or fails (quota, an aborted transaction), and\n * the next mutation then carries `lastId + 2`, a gap every backend rejects\n * (ADR-0008) so the journal never drains. Here a refused or failed append\n * leaves the counter exactly where it was: no id is consumed unless the\n * entry is journaled.\n *\n * Atomic with respect to every operation that writes the journal, the\n * quarantine or the counters (`appendMutation`, `acknowledge`,\n * `compactPending`, `nextMutationId`, `raiseMutationCounters`, `quarantinePending`,\n * `releaseQuarantine`, `discardQuarantine`): none can land between this\n * call's read and its write, so concurrent callers get distinct,\n * consecutive ids in the order they are served and no concurrent write is\n * lost.\n */\n readonly appendNext: (draft: Omit<Mutation, \"mutationId\">) => Effect.Effect<Mutation, StoreError>;\n readonly pendingMutations: Effect.Effect<ReadonlyArray<Mutation>, StoreError>;\n /**\n * How many entries the journal holds, without reading them (#260).\n *\n * What the engine samples the journal-depth gauge from, on every append,\n * acknowledgement and paced compaction, so it must stay cheap on a long\n * journal: an implementation counts from whatever it already keeps (the\n * memory store's array, the key-value store's journal index), never by\n * loading each pending body. Equal to `pendingMutations`' length, except\n * that the key-value store counts an index entry whose body is missing,\n * which `pendingMutations` skips. A crash or failed write mid-acknowledge\n * can leave one; the key-value store drops such entries the next time it\n * opens (#294).\n */\n readonly pendingCount: Effect.Effect<number, StoreError>;\n /** Drop journal entries with `mutationId <= upTo` for the client. */\n readonly acknowledge: (clientId: string, upTo: number) => Effect.Effect<void, StoreError>;\n /**\n * Compact the unpushed tail of `clientId`'s journal (#117's pacing\n * strategies: debounce/throttle/coalesce drop a superseded entry) **and\n * renumber the survivors** (#249), as one atomic step.\n *\n * The backend's exactly-once ledger (ADR-0008) requires a client's mutation\n * ids to arrive gap-free: `id <= lastMutationId` is skipped, `id ===\n * lastMutationId + 1` is applied, anything above is rejected. Dropping an\n * entry and leaving the rest alone therefore strands the journal behind a\n * gap no backend will accept. So after dropping, the client's unpushed\n * survivors are renumbered contiguously — in journal order, continuing on\n * from the last entry that is frozen (or from the first pending id when\n * nothing is) — and the id counter is rewound so the next\n * {@link ClientStore.nextMutationId} continues the run.\n *\n * Only entries **above the {@link ClientStore.markSent} watermark** are\n * ever dropped or renumbered: anything a push attempt may have put on the\n * wire keeps its id forever (a renumbered, already-applied write would be\n * applied twice). Ids in `mutationIds` that are not pending, are frozen, or\n * belong to another client are silently skipped.\n *\n * Atomic and restartable: a durable implementation must finish or roll\n * forward an interrupted compaction on the next open, so a crash never\n * leaves a gap, a duplicate id, or a counter that disagrees with the\n * journal. The mutations dropped here were never sent, so no\n * acknowledgement is implied.\n */\n readonly compactPending: (\n clientId: string,\n mutationIds: ReadonlyArray<number>\n ) => Effect.Effect<CompactionResult, StoreError>;\n /**\n * Record that a push attempt may have sent `clientId`'s entries with\n * `mutationId <= upTo` (monotonic: a lower value is ignored). Written\n * *before* the request leaves, because a failed round trip does not prove\n * the backend did not apply it. The watermark is what\n * {@link ClientStore.compactPending} treats as frozen, and it is persisted\n * so the boundary survives a restart and is shared by every engine\n * instance over the same store.\n */\n readonly markSent: (clientId: string, upTo: number) => Effect.Effect<void, StoreError>;\n /**\n * Reserve the next mutation id without journaling anything. Low-level:\n * prefer {@link ClientStore.appendNext}, since an id reserved here and never\n * appended is a gap (#258).\n */\n readonly nextMutationId: (clientId: string) => Effect.Effect<number, StoreError>;\n /**\n * Each client's mutation id counter: the highest id the store has issued, journaled or seen leave\n * the journal for that client. A client with no counter is absent. The next id the store issues for\n * a client is above both its counter and the highest id its journal holds.\n */\n readonly mutationCounters: Effect.Effect<Readonly<Record<string, number>>, StoreError>;\n /**\n * Raise each client's counter to at least its value in `counters`, never lowering one (#271).\n * What `Hydration.hydrate` restores a snapshot's counters with, so a client id reused across the\n * hydration boundary continues above the ids it has already had acknowledged, which the backend\n * would skip as duplicates.\n */\n readonly raiseMutationCounters: (\n counters: Readonly<Record<string, number>>\n ) => Effect.Effect<void, StoreError>;\n\n // Unpulled tail (#336, ADR-0008)\n /**\n * The acknowledged-but-unpulled tail (CONTEXT.md, \"Unpulled tail\"): applied\n * mutations the journal no longer holds, oldest first. The overlay keeps\n * their effects until a pull's `lastMutationIds` covers them. Empty when\n * none. Never part of {@link ClientStore.pendingMutations}, so a tail entry\n * is never pushed again.\n */\n readonly unpulled: Effect.Effect<ReadonlyArray<Mutation>, StoreError>;\n /**\n * Park applied mutations at the end of the tail, at a push acknowledgement.\n * Idempotent per `(clientId, mutationId)`. The caller then trims the same\n * entries from the journal with {@link ClientStore.acknowledge}. A crash\n * between the two leaves each entry in both places; the next open keeps the\n * tail copy and drops the journal copy, so the entry is neither lost nor\n * pushed twice. Raises each client's id counter to cover the parked ids.\n */\n readonly parkUnpulled: (mutations: ReadonlyArray<Mutation>) => Effect.Effect<void, StoreError>;\n /**\n * Record, before a release writes anything, the whole release: its watermark\n * and, for a pull, the cookie and patch its rows come from. The durable half\n * of the release: an open that finds the record finishes the release rather\n * than reverting it. It re-applies the patch (idempotent, since every\n * operation sets a row or removes it), writes the cookie, trims the journal\n * and releases the tail to the watermark. So a crash at any point after this\n * call shows the pull's effects, never the rows without them (#387). A release\n * still outstanding is finished first, whichever engine on this store began it,\n * so a record is only overwritten once its own finish has run (the finish\n * applies the whole recorded patch, so the other engine's release is completed,\n * not lost). If that finish, or the read of the record, fails, this call fails and the outstanding\n * record stays for the next call or pull to finish (or, after a failure past its\n * read, the store seals). A call that fails may still have written the record, so\n * the caller finishes the release either way.\n */\n readonly beginRelease: (release: PullRelease) => Effect.Effect<void, StoreError>;\n /**\n * Release the tail entries `lastMutationIds` covers, and end the release\n * {@link ClientStore.beginRelease} started. Covered means the entry's id is\n * at or below its client's watermark. The entries leave the store, so no\n * open re-applies their effects over rows that already hold them.\n */\n readonly releaseUnpulled: (\n lastMutationIds: Readonly<Record<string, number>>\n ) => Effect.Effect<void, StoreError>;\n /**\n * Finish the release {@link ClientStore.beginRelease} recorded and that has not\n * ended: the roll-forward an open runs, in this process. It re-applies the\n * patch, writes the cookie, trims the journal and releases the tail, so the\n * store is in the state the release describes. With no release outstanding it\n * only settles the tail as an open does: a journal copy of a parked entry is\n * dropped (#336). A failed read of the record fails this call alone, with\n * nothing written. A failure after that read, in the roll-forward or the\n * journal trim, seals the store: every later call fails until it is reopened,\n * and the next open finishes the release from the same record (#387).\n */\n readonly finishRelease: Effect.Effect<void, StoreError>;\n /**\n * Drop the whole tail and any release in progress: the identity reset's\n * step, since the tail's effects belong to the rows the reset clears.\n */\n readonly clearUnpulled: Effect.Effect<void, StoreError>;\n\n // Atomic batches (#393, #411). Present on the in-memory store, and on the key-value store when it has\n // an {@link AtomicKeyValue} in context; the engine takes its release-record path, through the members\n // above, when they are absent. A push acknowledgement's park and trim are the batch; the tail never\n // takes an overflow release, so there is no batch for one (#429).\n /**\n * Write a pull's whole release as one atomic batch: its rows, its cookie, the journal trim and the\n * tail release that {@link ClientStore.beginRelease}, the patch, the cookie, the acknowledgement and\n * {@link ClientStore.releaseUnpulled} would make in turn. Nothing is recorded, so a crash or a\n * batch that fails before its commit point leaves the store at its state before the pull, and the\n * tail still shows the effects the pull would have released. A failure reported after the commit\n * point may still have committed: the caller re-reads the store.\n */\n readonly commitPull?: ((release: PullRelease) => Effect.Effect<void, StoreError>) | undefined;\n /**\n * Park `parked` at the end of the tail and trim the journal to `lastMutationIds`, as one atomic\n * batch. The batch form of {@link ClientStore.parkUnpulled} followed by\n * {@link ClientStore.acknowledge} for each client.\n */\n readonly commitAcknowledgement?:\n | ((\n parked: ReadonlyArray<Mutation>,\n lastMutationIds: Readonly<Record<string, number>>\n ) => Effect.Effect<void, StoreError>)\n | undefined;\n\n // Whole-replica read (#392)\n /**\n * The replica read as one state: the confirmed rows, the pull cookie, the journal and the unpulled\n * tail, with nothing landing between the reads, so the result is the state at one moment. A pull or a\n * push acknowledgement is either wholly before it or wholly after it. Optional: a store without it is\n * read member by member, and that read can straddle a pull or an acknowledgement.\n *\n * The memory store reads under its lock. The key-value store reads under its lock as well, and in one\n * read transaction when its {@link AtomicKeyValue} offers `readAll`, as the browser's IndexedDB binding does.\n */\n readonly snapshot?: Effect.Effect<ReplicaState, StoreError> | undefined;\n\n // Sync bookkeeping\n readonly getCookie: Effect.Effect<string | undefined, StoreError>;\n readonly setCookie: (cookie: string) => Effect.Effect<void, StoreError>;\n /**\n * Forget the pull cookie, so the next pull is a full reset (`Cvr` sends\n * `Clear` + full puts for an absent cookie). Part of dropping a replica on\n * an identity change — a cookie kept past its rows would ask the server for\n * a *diff* against rows this client no longer has.\n */\n readonly clearCookie: Effect.Effect<void, StoreError>;\n\n // Identity boundary\n /**\n * The fingerprint whose session authorised the rows this store holds, or\n * `undefined` when the store has never been stamped (see\n * {@link Identity.unstamped}).\n */\n readonly getIdentity: Effect.Effect<Identity.Fingerprint | undefined, StoreError>;\n /** Stamp the replica as belonging to `fingerprint`. */\n readonly setIdentity: (fingerprint: Identity.Fingerprint) => Effect.Effect<void, StoreError>;\n\n // Quarantine\n /**\n * Move every pending journal entry into the quarantine keyed by\n * `fingerprint`, emptying the journal. Returns how many entries moved.\n *\n * This is the answer to the one question an identity change has no safe\n * default for: discarding a user's unsynced writes on sign-out is data\n * loss, and adopting them into the next session is a security bug. A\n * quarantined entry is **outside the journal**, so `pendingMutations` — and\n * therefore every push — cannot see it: it is unpushable under any identity\n * but the one it is keyed by.\n *\n * Mutation ids are preserved exactly. A quarantined entry may have been\n * in flight when the reset happened, and the backend's exactly-once ledger\n * (ADR-0008) is keyed by mutation id: renumbering could apply a write\n * twice, where keeping the id at worst has it acknowledged and skipped.\n * Re-quarantining under a fingerprint that already holds one appends,\n * preserving causal order within each batch.\n */\n readonly quarantinePending: (\n fingerprint: Identity.Fingerprint\n ) => Effect.Effect<number, StoreError>;\n /** The entries held under `fingerprint`, in causal order; empty when none. */\n readonly quarantinedMutations: (\n fingerprint: Identity.Fingerprint\n ) => Effect.Effect<ReadonlyArray<Mutation>, StoreError>;\n /** Every fingerprint currently holding a quarantine — what an app lists to offer a discard. */\n readonly quarantines: Effect.Effect<ReadonlyArray<Identity.Fingerprint>, StoreError>;\n /**\n * Move `fingerprint`'s quarantined entries back into the journal, making\n * them pushable again — what re-signing in as that identity does. Returns\n * how many entries were released. Appends to whatever is already pending.\n */\n readonly releaseQuarantine: (\n fingerprint: Identity.Fingerprint\n ) => Effect.Effect<number, StoreError>;\n /**\n * Delete `fingerprint`'s quarantine outright. **The only path that destroys\n * a quarantined write intent**, and deliberately an explicit call: no reset\n * and no boot may trigger it, because the alternative is an engine that\n * quietly throws away a departed user's unsynced work.\n */\n readonly discardQuarantine: (\n fingerprint: Identity.Fingerprint\n ) => Effect.Effect<void, StoreError>;\n}\n\n/** The {@link ClientStore} service a Client or engine persists through. */\nexport const ClientStore = Context.Service<ClientStore>(\"@thomasfosterau/legation/ClientStore\");\n\n/** A journal or tail entry's identity: its client and mutation id. */\nconst entryKey = (entry: { readonly clientId: string; readonly mutationId: number }): string =>\n `${entry.clientId}\\u0000${entry.mutationId}`;\n\n/** `held` followed by whatever of `incoming` it does not already hold, in order (#336). */\nconst appendMissing = <T extends { readonly clientId: string; readonly mutationId: number }>(\n held: ReadonlyArray<T>,\n incoming: ReadonlyArray<T>\n): ReadonlyArray<T> => {\n const seen = new Set(held.map(entryKey));\n const added: Array<T> = [];\n for (const entry of incoming) {\n const key = entryKey(entry);\n if (seen.has(key)) continue;\n seen.add(key);\n added.push(entry);\n }\n return [...held, ...added];\n};\n\n/**\n * Whether a `lastMutationIds` watermark covers `mutation`: its client's\n * watermark is at or above the mutation's id. The same rule as the engine's\n * pull release, kept here so the store releases exactly what the engine does.\n */\nconst coveredBy = (\n lastMutationIds: Readonly<Record<string, number>>,\n entry: { readonly clientId: string; readonly mutationId: number }\n): boolean => {\n const upTo: number | undefined = lastMutationIds[entry.clientId];\n return upTo !== undefined && entry.mutationId <= upTo;\n};\n\n/**\n * Freeze everything currently pending: raise each client's sent watermark to\n * its highest pending id, so {@link ClientStore.compactPending} treats it as\n * possibly-sent and leaves it alone (#249). Used wherever entries arrive whose\n * push history this process cannot see: engine boot (a journal persisted by an\n * earlier session, or by a release that predates the watermark, may have been\n * pushed) and snapshot hydration (the entries came from another context). The\n * cost is only that such entries are never compacted, which is what a paced\n * caller, tracking ids in memory, would not have attempted anyway.\n */\nexport const freezePending = (store: ClientStore): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n const highest = new Map<string, number>();\n for (const m of yield* store.pendingMutations) {\n if (m.mutationId > (highest.get(m.clientId) ?? 0)) highest.set(m.clientId, m.mutationId);\n }\n yield* Effect.forEach(highest, ([clientId, upTo]) => store.markSent(clientId, upTo), {\n discard: true,\n });\n });\n\n/**\n * What a release will do, recorded by {@link ClientStore.beginRelease} before it writes (#387).\n */\nexport interface PullRelease {\n /** The watermark the release covers: the entries at or below it leave the tail. */\n readonly lastMutationIds: Readonly<Record<string, number>>;\n /**\n * The pull's cookie, written when the release finishes. Absent for a release\n * that carries no rows.\n */\n readonly cookie?: string | undefined;\n /**\n * The pull's patch, re-applied when the release finishes. Empty for a release\n * that carries no rows.\n */\n readonly patch: ReadonlyArray<PatchOp>;\n}\n\n/**\n * `current` with each client raised to the highest id among `entries`, never lowered (#411). The\n * pure form of the counter raise the record path makes one entry at a time, over the memory store's\n * `Map` counters.\n */\nconst raisedCounterMap = (\n current: ReadonlyMap<string, number>,\n entries: ReadonlyArray<Mutation>\n): Map<string, number> => {\n const next = new Map(current);\n for (const m of entries) {\n if (m.mutationId > (next.get(m.clientId) ?? 0)) next.set(m.clientId, m.mutationId);\n }\n return next;\n};\n\n/** In-memory implementation (tests, SSR, ephemeral clients). */\nexport const makeMemory: Effect.Effect<ClientStore> = Effect.gen(function* () {\n const rows = yield* Ref.make(new Map<string, Map<RowId, StoredRow>>());\n const journal = yield* Ref.make<ReadonlyArray<Mutation>>([]);\n const counters = yield* Ref.make(new Map<string, number>());\n const sentUpTo = yield* Ref.make(new Map<string, number>());\n const cookie = yield* Ref.make<string | undefined>(undefined);\n const identity = yield* Ref.make<Identity.Fingerprint | undefined>(undefined);\n const quarantine = yield* Ref.make(new Map<Identity.Fingerprint, ReadonlyArray<Mutation>>());\n // The acknowledged-but-unpulled tail (#336), oldest first.\n const tail = yield* Ref.make<ReadonlyArray<Mutation>>([]);\n // The release in progress, if any (#387). A memory store does not outlive the process, so the\n // record only serves a roll-forward in this process.\n const outstanding = yield* Ref.make<PullRelease | undefined>(undefined);\n // The journal, the quarantine and the counters are separate Refs, and several\n // operations read one and then write it back. Every operation that WRITES\n // any of the three therefore holds this permit for its whole body:\n // `appendMutation`, `appendNext`, `acknowledge`, `compactPending`,\n // `nextMutationId`, `raiseMutationCounters`, `quarantinePending`, `releaseQuarantine`,\n // `discardQuarantine`, and the tail writers `parkUnpulled`,\n // `releaseUnpulled`, `clearUnpulled` and the atomic batch members (#411). A read-then-write\n // holder is only safe if every other writer is also excluded; a writer that skipped the permit\n // could land between the read and the set and be overwritten (the lost-append and\n // lost-release races). Pure reads stay unlocked: each is one `Ref.get`.\n // Chosen over folding all three into one Ref because the existing\n // operations stay readable and `compactPending`'s two-step commit keeps its\n // shape. No permit holder calls another, so the (non-reentrant) permit\n // cannot deadlock; keep it that way.\n const lock = yield* Semaphore.make(1);\n const locked = <A, E>(effect: Effect.Effect<A, E>) => Semaphore.withPermit(lock, effect);\n\n /** Raise a client's counter to at least `id`, never lowering it. */\n const raiseCounter = (clientId: string, id: number) =>\n Ref.update(counters, (m) => ((m.get(clientId) ?? 0) >= id ? m : new Map(m).set(clientId, id)));\n /** Raise each client's counter to the highest id among `entries`. */\n const raiseCountersTo = (entries: ReadonlyArray<Mutation>) => {\n const highest = new Map<string, number>();\n for (const m of entries) {\n if (m.mutationId > (highest.get(m.clientId) ?? 0)) highest.set(m.clientId, m.mutationId);\n }\n return Effect.forEach(highest, ([clientId, id]) => raiseCounter(clientId, id), {\n discard: true,\n });\n };\n\n const collectionMap = (map: Map<string, Map<RowId, StoredRow>>, collection: string) =>\n map.get(collection) ?? new Map<RowId, StoredRow>();\n\n // The rows after `ops`: the body of `applyRowOps`, shared with the roll-forward below.\n const applyOpsTo = (map: Map<string, Map<RowId, StoredRow>>, ops: ReadonlyArray<PatchOp>) => {\n let next = map;\n for (const op of ops) {\n if (op._tag === \"Clear\") {\n next = new Map();\n continue;\n }\n const source = next === map ? new Map(map) : next;\n const c = new Map(collectionMap(source, op.collection));\n if (op._tag === \"Put\") c.set(op.id, { id: op.id, version: op.version, value: op.value });\n else c.delete(op.id);\n source.set(op.collection, c);\n next = source;\n }\n return next;\n };\n\n // Finish the release in progress, if any: the same steps the key-value store's open runs (#387).\n // Then settle the tail the way the key-value store's open does (#336): a journal copy of a\n // parked entry is dropped, so the entry is neither replayed twice nor pushed again. Runs under\n // the lock, and is a no-op on the journal when the tail holds no parked copy.\n const finishInner = Effect.gen(function* () {\n const pending = yield* Ref.get(outstanding);\n if (pending !== undefined) {\n yield* Ref.update(rows, (map) => applyOpsTo(map, pending.patch));\n if (pending.cookie !== undefined) yield* Ref.set(cookie, pending.cookie);\n const covered = (m: Mutation) => coveredBy(pending.lastMutationIds, m);\n yield* raiseCountersTo((yield* Ref.get(journal)).filter(covered));\n yield* Ref.update(journal, (entries) => entries.filter((m) => !covered(m)));\n yield* Ref.update(tail, (held) => held.filter((m) => !covered(m)));\n yield* Ref.set(outstanding, undefined);\n }\n const parked = new Set((yield* Ref.get(tail)).map(entryKey));\n if (parked.size === 0) return;\n const dropped = (yield* Ref.get(journal)).filter((m) => parked.has(entryKey(m)));\n if (Arr.isReadonlyArrayEmpty(dropped)) return;\n yield* raiseCountersTo(dropped);\n yield* Ref.update(journal, (entries) => entries.filter((m) => !parked.has(entryKey(m))));\n });\n\n // ─── Atomic batch members (#411) ─────────────────────────────────────────\n // The batch form of each record-path step, so the engine takes the batch path on this store as it\n // does on the key-value store. Each member is one step under `lock`: it finishes an outstanding\n // record first, as a row write does (#387), computes every new value from the current state, then\n // writes them together. Nothing is recorded, so the memory store cannot be left mid-release. The\n // writes run uninterruptible, so an interrupt cannot land between them.\n const finishOutstanding = Effect.gen(function* () {\n if ((yield* Ref.get(outstanding)) !== undefined) yield* finishInner;\n });\n\n const commitPull = (release: PullRelease) =>\n locked(\n Effect.uninterruptible(\n Effect.gen(function* () {\n yield* finishOutstanding;\n const currentJournal = yield* Ref.get(journal);\n const nextRows = applyOpsTo(yield* Ref.get(rows), release.patch);\n const nextCounters = raisedCounterMap(\n yield* Ref.get(counters),\n currentJournal.filter((m) => coveredBy(release.lastMutationIds, m))\n );\n const nextJournal = currentJournal.filter((m) => !coveredBy(release.lastMutationIds, m));\n const nextTail = (yield* Ref.get(tail)).filter(\n (m) => !coveredBy(release.lastMutationIds, m)\n );\n yield* Ref.set(rows, nextRows);\n if (release.cookie !== undefined) yield* Ref.set(cookie, release.cookie);\n yield* Ref.set(counters, nextCounters);\n yield* Ref.set(journal, nextJournal);\n yield* Ref.set(tail, nextTail);\n })\n )\n );\n\n const commitAcknowledgement = (\n parked: ReadonlyArray<Mutation>,\n lastMutationIds: Readonly<Record<string, number>>\n ) =>\n locked(\n Effect.uninterruptible(\n Effect.gen(function* () {\n yield* finishOutstanding;\n const currentJournal = yield* Ref.get(journal);\n const nextTail = appendMissing(yield* Ref.get(tail), parked);\n // The parked entries and the trimmed ones both keep the counters at their high-water mark.\n const nextCounters = raisedCounterMap(\n raisedCounterMap(yield* Ref.get(counters), parked),\n currentJournal.filter((m) => coveredBy(lastMutationIds, m))\n );\n const nextJournal = currentJournal.filter((m) => !coveredBy(lastMutationIds, m));\n yield* Ref.set(tail, nextTail);\n yield* Ref.set(counters, nextCounters);\n yield* Ref.set(journal, nextJournal);\n })\n )\n );\n\n return ClientStore.of({\n commitPull,\n commitAcknowledgement,\n getRow: (collection, id) => Ref.get(rows).pipe(Effect.map((m) => m.get(collection)?.get(id))),\n listRows: (collection) =>\n Ref.get(rows).pipe(Effect.map((m) => Array.from(collectionMap(m, collection).values()))),\n listCollections: Ref.get(rows).pipe(Effect.map((m) => Array.from(m.keys()))),\n // A row write finishes an outstanding release first, in the same permit hold, so the release's\n // patch cannot land over it on a later finish (#387). The release's own patch goes through\n // `applyRowOps`, which does not finish.\n putRow: (collection, row) =>\n locked(\n finishInner.pipe(\n Effect.andThen(\n Ref.update(rows, (m) => {\n const next = new Map(m);\n const c = new Map(collectionMap(m, collection));\n c.set(row.id, row);\n next.set(collection, c);\n return next;\n })\n )\n )\n ),\n delRow: (collection, id) =>\n locked(\n finishInner.pipe(\n Effect.andThen(\n Ref.update(rows, (m) => {\n const next = new Map(m);\n const c = new Map(collectionMap(m, collection));\n c.delete(id);\n next.set(collection, c);\n return next;\n })\n )\n )\n ),\n // An outstanding release is finished first, so its patch cannot land over the cleared rows (#387).\n clearRows: locked(finishInner.pipe(Effect.andThen(Ref.set(rows, new Map())))),\n applyRowOps: (ops) => locked(Ref.update(rows, (map) => applyOpsTo(map, ops))),\n\n // Refused for an id the tail holds (see `ClientStore.appendMutation`), as the key-value store refuses it.\n appendMutation: (mutation) =>\n locked(\n Effect.gen(function* () {\n if ((yield* Ref.get(tail)).some((held) => entryKey(held) === entryKey(mutation))) {\n return yield* alreadyParked(mutation);\n }\n yield* Ref.update(journal, (entries) => entries.concat(mutation));\n })\n ),\n // Uninterruptible and under the store lock: the counter and the journal\n // change together, and no other operation interleaves (#258). The id is\n // the larger of the counter and the highest id the journal already holds\n // for the client, the same healing the KeyValueStore store applies, so the\n // two implementations agree when an entry arrived by `appendMutation`.\n appendNext: (draft) =>\n locked(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const entries = yield* Ref.get(journal);\n let last = (yield* Ref.get(counters)).get(draft.clientId) ?? 0;\n for (const entry of entries) {\n if (entry.clientId === draft.clientId && entry.mutationId > last) {\n last = entry.mutationId;\n }\n }\n const mutation: Mutation = { ...draft, mutationId: last + 1 };\n yield* Ref.set(journal, entries.concat(mutation));\n yield* raiseCounter(draft.clientId, mutation.mutationId);\n return mutation;\n })\n )\n ),\n pendingMutations: Ref.get(journal),\n pendingCount: Ref.get(journal).pipe(Effect.map((entries) => entries.length)),\n // Raises the counter to the highest id it removes first, so an id that has\n // been acknowledged is never issued again once its entry is gone.\n acknowledge: (clientId, upTo) =>\n locked(\n Effect.gen(function* () {\n const entries = yield* Ref.get(journal);\n const removed = entries.filter((m) => m.clientId === clientId && m.mutationId <= upTo);\n yield* raiseCountersTo(removed);\n yield* Ref.set(\n journal,\n entries.filter((m) => m.clientId !== clientId || m.mutationId > upTo)\n );\n })\n ),\n // Uninterruptible: the journal and the counter must change together. An\n // interrupt between the two writes would leave a renumbered journal with a\n // counter that still hands out the old numbering, i.e. a gap (#249).\n compactPending: (clientId, mutationIds) =>\n locked(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const watermark = (yield* Ref.get(sentUpTo)).get(clientId) ?? 0;\n // Journal and plan move together in one `Ref.modify`, so a concurrent\n // append cannot slip between the read and the write.\n const plan = yield* Ref.modify(journal, (entries) => {\n const planned = planCompaction(entries, clientId, mutationIds, watermark);\n return planned === undefined ? [undefined, entries] : [planned, planned.journal];\n });\n if (plan === undefined) return NO_COMPACTION;\n // A yield point between the two writes: harmless here, and what lets\n // a test (and a real preemption) interrupt exactly in the window the\n // uninterruptible wrapper exists to close.\n yield* Effect.yieldNow;\n yield* Ref.update(counters, (m) => new Map(m).set(clientId, plan.counter));\n return plan.result;\n })\n )\n ),\n markSent: (clientId, upTo) =>\n Ref.update(sentUpTo, (m) =>\n (m.get(clientId) ?? 0) >= upTo ? m : new Map(m).set(clientId, upTo)\n ),\n // Heals from the journal like `appendNext`, so it can never return an id a\n // live entry already holds (for example after a counter that lagged).\n nextMutationId: (clientId) =>\n locked(\n Effect.gen(function* () {\n const entries = yield* Ref.get(journal);\n let last = (yield* Ref.get(counters)).get(clientId) ?? 0;\n for (const entry of entries) {\n if (entry.clientId === clientId && entry.mutationId > last) last = entry.mutationId;\n }\n const next = last + 1;\n yield* raiseCounter(clientId, next);\n return next;\n })\n ),\n mutationCounters: Ref.get(counters).pipe(Effect.map(R.fromEntries)),\n raiseMutationCounters: (raise) =>\n locked(\n Effect.forEach(R.toEntries(raise), ([clientId, id]) => raiseCounter(clientId, id), {\n concurrency: 1,\n discard: true,\n })\n ),\n\n unpulled: Ref.get(tail),\n parkUnpulled: (mutations) =>\n locked(\n Ref.update(tail, (held) => appendMissing(held, mutations)).pipe(\n Effect.andThen(raiseCountersTo(mutations))\n )\n ),\n // The record-path methods (`beginRelease`, `releaseUnpulled`) stay on this store for the\n // interface and the record-path contract tests, which run over both stores. The engine never\n // reaches them here now that the batch members are present (#411): the key-value store over a\n // plain KeyValueStore, with no AtomicKeyValue in context, is the store that still needs them.\n //\n // An outstanding release is finished first, as an open would finish it (#387), so a second\n // release begins rather than being refused. The finish cannot fail here: nothing is stored.\n beginRelease: (release) =>\n locked(\n Ref.get(outstanding).pipe(\n Effect.flatMap((pending) => (pending === undefined ? Effect.void : finishInner)),\n Effect.andThen(Ref.set(outstanding, release))\n )\n ),\n releaseUnpulled: (lastMutationIds) =>\n locked(\n Ref.update(tail, (held) => held.filter((m) => !coveredBy(lastMutationIds, m))).pipe(\n Effect.andThen(Ref.set(outstanding, undefined))\n )\n ),\n finishRelease: locked(finishInner),\n // Drops the release record with the tail, as the key-value store removes its record (#387).\n clearUnpulled: locked(Ref.set(tail, []).pipe(Effect.andThen(Ref.set(outstanding, undefined)))),\n\n // One read under the lock: every writer of the snapshot's state below takes the same lock, so the four reads see one state (#392).\n snapshot: locked(\n Effect.gen(function* () {\n const byCollection = yield* Ref.get(rows);\n const flat: Array<{ readonly collection: string; readonly row: StoredRow }> = [];\n for (const [collection, collectionRows] of byCollection) {\n for (const row of collectionRows.values()) flat.push({ collection, row });\n }\n return {\n rows: flat,\n cookie: yield* Ref.get(cookie),\n journal: yield* Ref.get(journal),\n unpulled: yield* Ref.get(tail),\n counters: R.fromEntries(yield* Ref.get(counters)),\n };\n })\n ),\n\n getCookie: Ref.get(cookie),\n // Locked so every writer of the snapshot's state takes the lock and the snapshot rule holds without case analysis (#392).\n setCookie: (value) => locked(Ref.set(cookie, value)),\n clearCookie: locked(Ref.set(cookie, undefined)),\n\n getIdentity: Ref.get(identity),\n setIdentity: (fingerprint) => Ref.set(identity, fingerprint),\n\n quarantinePending: (fingerprint) =>\n locked(\n Effect.gen(function* () {\n const entries = yield* Ref.get(journal);\n if (Arr.isReadonlyArrayEmpty(entries)) return 0;\n // The counters keep the high-water mark of what leaves the journal.\n yield* raiseCountersTo(entries);\n yield* Ref.set(journal, []);\n yield* Ref.update(quarantine, (held) =>\n new Map(held).set(fingerprint, [...(held.get(fingerprint) ?? []), ...entries])\n );\n return entries.length;\n })\n ),\n quarantinedMutations: (fingerprint) =>\n Ref.get(quarantine).pipe(Effect.map((held) => held.get(fingerprint) ?? [])),\n quarantines: Ref.get(quarantine).pipe(Effect.map((held) => [...held.keys()])),\n releaseQuarantine: (fingerprint) =>\n locked(\n Effect.gen(function* () {\n const held = yield* Ref.get(quarantine);\n const entries = held.get(fingerprint) ?? [];\n if (Arr.isReadonlyArrayEmpty(entries)) return 0;\n yield* Ref.update(journal, (pending) => [...pending, ...entries]);\n yield* Ref.update(quarantine, (map) => {\n const next = new Map(map);\n next.delete(fingerprint);\n return next;\n });\n return entries.length;\n })\n ),\n discardQuarantine: (fingerprint) =>\n locked(\n Ref.update(quarantine, (map) => {\n const next = new Map(map);\n next.delete(fingerprint);\n return next;\n })\n ),\n });\n});\n\n/** Layer providing the in-memory store. */\nexport const layerMemory: Layer.Layer<ClientStore> = Layer.effect(ClientStore)(makeMemory);\n\n/**\n * A store that refuses every operation with `cause`.\n *\n * The fail-closed end of the identity boundary (#212). If the open-time\n * identity transition cannot be completed — a corrupt journal blob, a KVS\n * that errors mid-reset — the replica's rows may still belong to the\n * superseded principal and its journal may still hold that principal's\n * unpushed intents. Serving either is the exact bug the boundary exists to\n * prevent, and neither clearing (data loss) nor continuing (a security bug)\n * is acceptable, so the store is sealed instead: reads and writes fail\n * loudly, nothing is pushed, and nothing is destroyed. The durable state is\n * untouched and the next open retries the whole transition.\n */\nconst sealed = (cause: StoreError): ClientStore => {\n // The reason is named in the message itself, so a backend's specific failure (a missing object\n // store, say) is not lost behind the generic wording (#393).\n const detail = causeDetail(cause);\n const refuse = <A>(): Effect.Effect<A, StoreError> =>\n Effect.fail(\n new StoreError({\n message:\n \"ClientStore is sealed: the identity boundary could not be established on open\" +\n (detail === \"\" ? \"\" : ` (${detail})`) +\n \", so this replica cannot safely be read or written. The durable state is intact; \" +\n \"retry by reopening the store.\",\n cause,\n })\n );\n return ClientStore.of({\n getRow: () => refuse(),\n listRows: () => refuse(),\n listCollections: refuse(),\n putRow: () => refuse(),\n delRow: () => refuse(),\n clearRows: refuse(),\n applyRowOps: () => refuse(),\n appendMutation: () => refuse(),\n appendNext: () => refuse(),\n pendingMutations: refuse(),\n pendingCount: refuse(),\n acknowledge: () => refuse(),\n compactPending: () => refuse(),\n markSent: () => refuse(),\n nextMutationId: () => refuse(),\n mutationCounters: refuse(),\n raiseMutationCounters: () => refuse(),\n unpulled: refuse(),\n parkUnpulled: () => refuse(),\n beginRelease: () => refuse(),\n releaseUnpulled: () => refuse(),\n finishRelease: refuse(),\n clearUnpulled: refuse(),\n getCookie: refuse(),\n setCookie: () => refuse(),\n clearCookie: refuse(),\n getIdentity: refuse(),\n setIdentity: () => refuse(),\n quarantinePending: () => refuse(),\n quarantinedMutations: () => refuse(),\n quarantines: refuse(),\n releaseQuarantine: () => refuse(),\n discardQuarantine: () => refuse(),\n });\n};\n\n/**\n * The messages down a cause chain, outermost first, joined with `: `: the reason a store failure\n * carries, for a sealed store's message. The walk stops at a non-object or after a few links.\n */\nconst causeDetail = (error: unknown): string => {\n const messages: Array<string> = [];\n let current: unknown = error;\n for (let depth = 0; depth < 8 && P.isObjectOrArray(current); depth++) {\n const link = current as { readonly message?: unknown; readonly cause?: unknown };\n if (P.isString(link.message) && link.message !== \"\") messages.push(link.message);\n current = link.cause;\n }\n return messages.join(\": \");\n};\n\n/**\n * The refusal an append gets for an entry the unpulled tail already holds (#336). A journal copy of a\n * parked entry would be double-counted by reads, and pushed again.\n */\nconst alreadyParked = (mutation: Mutation): StoreError =>\n new StoreError({\n message: `Mutation ${mutation.clientId}#${mutation.mutationId} is already in the unpulled tail, so it cannot also be journaled`,\n });\n\n/**\n * The error every member fails with once a release could not be finished in this process (#387).\n * Reopening the store finishes the release from its durable record.\n */\nconst sealedByRelease = (cause: StoreError): StoreError =>\n new StoreError({\n message:\n \"ClientStore is sealed: a pull release could not be finished in this process, \" +\n \"so the replica cannot safely be read or written. The durable record is intact; \" +\n \"reopen the store to finish the release.\",\n cause,\n });\n\n// ─── KeyValueStore-backed implementation ─────────────────────────────────────\n\n/** Options for a {@link ClientStore} over an Effect `KeyValueStore`. */\nexport interface KeyValueOptions {\n /** Key namespace inside the KeyValueStore. Defaults to `\"legation/\"`. */\n readonly prefix?: string;\n /**\n * Maximum number of pending mutations the journal will hold. When an\n * `appendMutation` would exceed it, the append fails with a `StoreError`\n * rather than silently dropping the intent (#47) — the failure surfaces\n * through `mutate` so the app can block writes or warn. KVS-only: the memory\n * store is ephemeral and imposes no bound. Unset means unbounded.\n */\n readonly journalHighWater?: number;\n /**\n * Local store-version buster (#48). On open, if the persisted store-version\n * key differs from this value, the confirmed rows and the pull cookie are\n * cleared — so the next pull is a full reset ({@link Cvr} sends `Clear` + full\n * puts for the now-absent cookie) — and the new version is persisted. The\n * **pending journal is preserved**: a store-version bump is a local cache\n * buster, not a reason to drop the user's unsynced intents, so they still\n * push once the fresh rows land. Unset means no buster (today's behaviour).\n */\n readonly storeVersion?: string;\n /**\n * The identity this replica belongs to (CONTEXT.md, \"Identity boundary\").\n * Supplying it turns the boundary on: the store compares this fingerprint\n * with its stamp on open and applies {@link Identity.transitionOf} —\n *\n * - **Unchanged**: the same principal, so nothing happens.\n * - **Upgrade** ({@link Identity.anonymous} → signed in): the warm replica\n * and the journal survive; only the stamp changes. Public rows are a\n * subset of what the new identity may read, and the pending writes are\n * the same person's, made on this device moments earlier.\n * - **Reset**: every other change, sign-out included. Unpushed journal\n * entries are quarantined under the **superseded** fingerprint (never\n * discarded, never inherited), then confirmed rows and the pull cookie\n * are dropped, so the next pull rehydrates from scratch under the new\n * identity. A replica that has never been stamped counts as\n * {@link Identity.unstamped} and therefore always resets — one full\n * re-pull the first time an app turns the boundary on, which is the safe\n * direction.\n *\n * Either way, a quarantine already held under the adopted fingerprint is\n * released back into the journal: re-signing in makes that identity's own\n * unpushed writes pushable again. Nothing here ever *discards* a\n * quarantine — that is {@link ClientStore.discardQuarantine} alone.\n *\n * Unset leaves the store unstamped and unchecked (today's behaviour). The\n * alternative to resetting is namespacing: derive {@link KeyValueOptions.prefix}\n * (or the IndexedDB database) from the fingerprint so each principal has\n * its own replica — see `IndexedDbClientStore.layerNamespaced`.\n */\n readonly identity?: Identity.Fingerprint;\n}\n\n/**\n * The current durable layout version. Stamped at `__layout` on first open; a\n * store found at an earlier (or absent) version is migrated forward once (#47).\n */\nconst CURRENT_LAYOUT = \"2\";\nconst LAYOUT_KEY = \"__layout\";\n/** Where the app-supplied {@link KeyValueOptions.storeVersion} is persisted (#48). */\nconst STORE_VERSION_KEY = \"__storeVersion\";\n/** Where the replica's {@link Identity.Fingerprint} stamp is persisted (#212). */\nconst IDENTITY_KEY = \"__identity\";\n/** The index of fingerprints currently holding a quarantine. */\nconst QUARANTINE_INDEX_KEY = \"quarantineIndex\";\n/** The in-progress compaction's write-ahead intent (#249); present only mid-compaction. */\nconst COMPACTION_KEY = \"compactionIntent\";\n/** Per-client highest mutation id a push attempt may have sent (#249). */\nconst SENT_KEY = \"sentUpTo\";\n/** The index of the acknowledged-but-unpulled tail, oldest first (#336). */\nconst UNPULLED_INDEX_KEY = \"unpulledIndex\";\n/**\n * The pull release in progress, present only mid-release (#336, #387): its\n * watermark, cookie and patch, so an open can finish it.\n */\nconst RELEASE_KEY = \"releaseIntent\";\n\n/** Per-row / per-mutation key builders (layout 2). */\nconst rowKey = (collection: string, id: string) => `row/${collection}/${id}`;\nconst rowIndexKey = (collection: string) => `rowIndex/${collection}`;\nconst journalBodyKey = (clientId: string, mutationId: number) =>\n `journal/${clientId}/${mutationId}`;\nconst unpulledBodyKey = (clientId: string, mutationId: number) =>\n `unpulled/${clientId}/${mutationId}`;\n/**\n * A quarantine's whole body, keyed by the fingerprint it is held under\n * (percent-encoded, since a fingerprint is opaque app-supplied text). Unlike\n * the journal this is a single blob: a quarantine is written once on reset\n * and read once on release, so the per-entry write amplification layout 2\n * exists to avoid never arises.\n */\nconst quarantineKey = (fingerprint: Identity.Fingerprint) =>\n `quarantine/${Identity.keySegment(fingerprint)}`;\n/** Legacy (layout 1) whole-collection / whole-journal blob keys. */\nconst legacyRowsKey = (collection: string) => `rows/${collection}`;\nconst LEGACY_JOURNAL_KEY = \"journal\";\n\n/** An entry in the compact ordered journal index — ids only, never the body. */\nconst JournalIndexEntry = Schema.Struct({\n clientId: Schema.String,\n mutationId: Schema.Number,\n});\ntype JournalIndexEntry = typeof JournalIndexEntry.Type;\n\n/** JSON codecs for the persisted values (envelope-validated on read). */\nconst RowFromJson = Schema.fromJsonString(StoredRow);\nconst IdsFromJson = Schema.fromJsonString(Schema.Array(Schema.String));\nconst CollectionsFromJson = Schema.fromJsonString(Schema.Array(Schema.String));\nconst MutationFromJson = Schema.fromJsonString(Mutation);\nconst JournalIndexFromJson = Schema.fromJsonString(Schema.Array(JournalIndexEntry));\nconst CountersFromJson = Schema.fromJsonString(Schema.Record(Schema.String, Schema.Number));\nconst ReleaseIntentFromJson = Schema.fromJsonString(\n Schema.Struct({\n lastMutationIds: Schema.Record(Schema.String, Schema.Number),\n cookie: Schema.optional(Schema.String),\n patch: Schema.Array(PatchOp),\n })\n);\n/**\n * The write-ahead record of an in-progress compaction (#249): everything\n * needed to finish it from scratch, so replaying it is idempotent.\n */\nconst CompactionIntentFromJson = Schema.fromJsonString(\n Schema.Struct({\n clientId: Schema.String,\n /** Body keys to clear first: every dropped id and every old id of a moved entry. */\n staleIds: Schema.Array(Schema.Number),\n /** The renumbered bodies, at their new ids. */\n moved: Schema.Array(Mutation),\n /** The complete journal index once the compaction has applied. */\n index: Schema.Array(JournalIndexEntry),\n /** The value `clientId`'s counter takes once it has applied. */\n counter: Schema.Number,\n })\n);\n/** A quarantine body, and the index of fingerprints holding one. */\nconst MutationsFromJson = Schema.fromJsonString(Schema.Array(Mutation));\nconst FingerprintsFromJson = Schema.fromJsonString(Schema.Array(Schema.String));\n/** Legacy whole-blob codecs, read only on the migration / fallback path. */\nconst RowMapFromJson = Schema.fromJsonString(Schema.Record(Schema.String, StoredRow));\nconst JournalFromJson = MutationsFromJson;\n\n/**\n * Append `incoming` to `held`, skipping entries already there by\n * (clientId, mutationId). Quarantining is not one atomic KVS write, so a\n * crash between writing the quarantine and emptying the journal leaves the\n * open path to re-quarantine the same entries on the next boot; deduping\n * makes that retry idempotent instead of doubling the batch.\n */\nconst appendDistinct = (\n held: ReadonlyArray<Mutation>,\n incoming: ReadonlyArray<Mutation>\n): ReadonlyArray<Mutation> => {\n const seen = new Set(held.map((m) => `${m.clientId}/${m.mutationId}`));\n return [...held, ...incoming.filter((m) => !seen.has(`${m.clientId}/${m.mutationId}`))];\n};\n\n/** The highest mutation id per client among `ids` (empty when none is positive). */\nconst highestIds = (ids: ReadonlyArray<JournalIndexEntry>): Record<string, number> => {\n const highest: Record<string, number> = {};\n for (const { clientId, mutationId } of ids) {\n if (mutationId > (highest[clientId] ?? 0)) highest[clientId] = mutationId;\n }\n return highest;\n};\n\n/**\n * `counters` with each client raised to at least its id in `highest`, or `undefined` when no counter\n * rises. The one rule both the record path and the atomic batch apply (#249, #258).\n */\nconst raisedCounters = (\n counters: Readonly<Record<string, number>>,\n highest: Readonly<Record<string, number>>\n): Record<string, number> | undefined => {\n const raised: Record<string, number> = { ...counters };\n let changed = false;\n for (const [clientId, id] of Object.entries(highest)) {\n if ((raised[clientId] ?? 0) < id) {\n raised[clientId] = id;\n changed = true;\n }\n }\n return changed ? raised : undefined;\n};\n\n/** A batch of row ops grouped by collection: `null` marks a deletion. */\ntype RowChanges = Map<string, StoredRow | null>;\ninterface RowOpPlan {\n readonly clear: boolean;\n readonly groups: Map<string, RowChanges>;\n}\n\n/**\n * Fold a patch into a per-collection plan, so the durable path can rewrite each\n * touched collection once (a K-op patch → K row-value writes + ~1 index write\n * per collection, never the whole collection K times). A `Clear` wipes the plan\n * so far and marks the store for a reset before the surviving ops apply.\n */\nconst planRowOps = (ops: ReadonlyArray<PatchOp>): RowOpPlan => {\n const groups = new Map<string, RowChanges>();\n let clear = false;\n for (const op of ops) {\n if (op._tag === \"Clear\") {\n clear = true;\n groups.clear();\n continue;\n }\n const changes = groups.get(op.collection) ?? new Map();\n groups.set(op.collection, changes);\n changes.set(\n op.id,\n op._tag === \"Put\" ? { id: op.id, version: op.version, value: op.value } : null\n );\n }\n return { clear, groups };\n};\n\n/** A typed read of one key: the value decoded through `codec`, or `undefined` when absent. */\ntype KeyReader = <A>(\n key: string,\n codec: Schema.Codec<A, string>\n) => Effect.Effect<A | undefined, StoreError>;\n\n/** A {@link KeyReader} over one read of the entries, decoding each value as the store reads it. */\nconst readerOver =\n (entries: ReadonlyMap<string, string>): KeyReader =>\n <A>(key: string, codec: Schema.Codec<A, string>) => {\n const raw = entries.get(key);\n return raw === undefined\n ? Effect.succeed(undefined)\n : Schema.decodeUnknownEffect(codec)(raw).pipe(\n Effect.mapError(\n (cause) => new StoreError({ message: `Corrupt persisted state at \"${key}\"`, cause })\n )\n );\n };\n\n// The reads of a replica's state, through `read`: the store's own keys, or one read of every entry (#392).\nconst collectionsWith = (read: KeyReader) =>\n read(\"collections\", CollectionsFromJson).pipe(Effect.map((list) => list ?? []));\n\nconst listRowsWith = (\n read: KeyReader,\n collection: string\n): Effect.Effect<ReadonlyArray<StoredRow>, StoreError> =>\n Effect.gen(function* () {\n const ids = yield* read(rowIndexKey(collection), IdsFromJson);\n if (ids === undefined) {\n const legacy = yield* read(legacyRowsKey(collection), RowMapFromJson);\n return legacy === undefined ? [] : Object.values(legacy);\n }\n const rows: Array<StoredRow> = [];\n for (const id of ids) {\n const row = yield* read(rowKey(collection, id), RowFromJson);\n if (row !== undefined) rows.push(row);\n }\n return rows;\n });\n\nconst pendingMutationsWith = (\n read: KeyReader\n): Effect.Effect<ReadonlyArray<Mutation>, StoreError> =>\n Effect.gen(function* () {\n const index = yield* read(\"journalIndex\", JournalIndexFromJson);\n if (index === undefined) {\n const legacy = yield* read(LEGACY_JOURNAL_KEY, JournalFromJson);\n return legacy ?? [];\n }\n const mutations: Array<Mutation> = [];\n for (const entry of index) {\n const body = yield* read(journalBodyKey(entry.clientId, entry.mutationId), MutationFromJson);\n if (body !== undefined) mutations.push(body);\n }\n return mutations;\n });\n\nconst unpulledWith = (read: KeyReader): Effect.Effect<ReadonlyArray<Mutation>, StoreError> =>\n Effect.gen(function* () {\n const index = (yield* read(UNPULLED_INDEX_KEY, JournalIndexFromJson)) ?? [];\n const mutations: Array<Mutation> = [];\n for (const entry of index) {\n const body = yield* read(unpulledBodyKey(entry.clientId, entry.mutationId), MutationFromJson);\n if (body !== undefined) mutations.push(body);\n }\n return mutations;\n });\n\n// The whole replica, read through `read`: the same reads the members make, in one order (#392).\nconst replicaStateWith = (read: KeyReader): Effect.Effect<ReplicaState, StoreError> =>\n Effect.gen(function* () {\n const rows: Array<{ readonly collection: string; readonly row: StoredRow }> = [];\n for (const collection of yield* collectionsWith(read)) {\n for (const row of yield* listRowsWith(read, collection)) rows.push({ collection, row });\n }\n return {\n rows,\n cookie: yield* read(\"cookie\", Schema.String),\n journal: yield* pendingMutationsWith(read),\n unpulled: yield* unpulledWith(read),\n counters: (yield* read(\"counters\", CountersFromJson)) ?? {},\n };\n });\n\n/**\n * The durable implementation (ADR-0007): ClientStore over\n * `effect/persistence` KeyValueStore, so any platform KVS —\n * browser IndexedDB/localStorage, Node file system, SQL — persists the\n * engine.\n *\n * Layout 2 (#47) stores state per row and per mutation, because the KVS has no\n * key enumeration: each confirmed row is a `row/{collection}/{id}` value with a\n * per-collection `rowIndex/{collection}` id-array; each pending mutation is a\n * `journal/{clientId}/{mutationId}` body with a compact ordered `journalIndex`.\n * A single `putRow`/`appendMutation` rewrites one value plus a small index —\n * never the whole collection or journal — and `acknowledge` drops acked bodies\n * without rewriting the survivors. `collections`, `counters`, and `cookie`\n * carry over unchanged. A store opened at an earlier layout is migrated forward\n * once, transparently.\n *\n * Read-modify-write operations are serialized through a semaphore, which\n * makes one store instance safe for concurrent fibers — not for concurrent\n * processes (the service-worker host is the per-origin singleton, ADR-0010).\n *\n * Two paths write a pull's release (#387, #393). With an {@link AtomicKeyValue}\n * in context, the release (`commitPull`, `commitAcknowledgement`) is one batch\n * and no release record is written. Without\n * it, the release goes through the record `beginRelease` writes first, which\n * an open finishes if a crash interrupted it. Both paths settle a leftover\n * record on open.\n *\n * Reads decode each persisted value through a `Schema` codec, so a corrupt or\n * format-drifted value on a rehydrating host fails as a `StoreError` instead\n * of a silent `as A` cast. Only the *envelopes* are validated — row values\n * and mutation args stay `Unknown` and round-trip untouched (ADR-0014).\n */\nexport const makeKeyValue = (\n options?: KeyValueOptions\n): Effect.Effect<ClientStore, never, KeyValueStore.KeyValueStore> =>\n Effect.gen(function* () {\n const namespace = options?.prefix ?? \"legation/\";\n const store = KeyValueStore.prefix(yield* KeyValueStore.KeyValueStore, namespace);\n const highWater = options?.journalHighWater;\n const lock = yield* Semaphore.make(1);\n // Set when an outstanding release could not be finished in this process. Every member checks it\n // (#387): the writers inside the permit, so a call queued behind the failing finish is refused\n // rather than run over the outstanding record; the readers before they read.\n const sealedBy = yield* Ref.make<StoreError | undefined>(undefined);\n // Set whenever a release record or a parked journal copy may exist. While it is clear the\n // in-process finish has nothing to do, so a row write reads neither (#387). Set before a write\n // that may land despite reporting failure; cleared only by a finish that completes.\n const finishPending = yield* Ref.make(false);\n const unsealed = <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E | StoreError> =>\n Effect.gen(function* () {\n const cause = yield* Ref.get(sealedBy);\n if (cause !== undefined) return yield* sealedByRelease(cause);\n return yield* effect;\n });\n const locked = <A, E>(effect: Effect.Effect<A, E>) =>\n Semaphore.withPermit(lock, unsealed(effect));\n\n const storeError = (message: string) => (cause: unknown) => new StoreError({ message, cause });\n\n const readDecoded = <A>(\n key: string,\n codec: Schema.Codec<A, string>\n ): Effect.Effect<A | undefined, StoreError> =>\n store.get(key).pipe(\n Effect.mapError(storeError(`Failed to read \"${key}\"`)),\n Effect.flatMap((raw) =>\n raw === undefined\n ? Effect.succeed(undefined)\n : Schema.decodeUnknownEffect(codec)(raw).pipe(\n Effect.mapError(storeError(`Corrupt persisted state at \"${key}\"`))\n )\n )\n );\n const writeJson = (key: string, value: unknown): Effect.Effect<void, StoreError> =>\n store\n .set(key, JSON.stringify(value))\n .pipe(Effect.mapError(storeError(`Failed to write \"${key}\"`)));\n const remove = (key: string): Effect.Effect<void, StoreError> =>\n store.remove(key).pipe(Effect.mapError(storeError(`Failed to remove \"${key}\"`)));\n\n const rowIndex = (collection: string): Effect.Effect<ReadonlyArray<string>, StoreError> =>\n readDecoded(rowIndexKey(collection), IdsFromJson).pipe(Effect.map((ids) => ids ?? []));\n const collections = collectionsWith(readDecoded);\n const trackCollection = (collection: string) =>\n collections.pipe(\n Effect.flatMap((list) =>\n list.includes(collection) ? Effect.void : writeJson(\"collections\", [...list, collection])\n )\n );\n const journalIndex = readDecoded(\"journalIndex\", JournalIndexFromJson).pipe(\n Effect.map((entries) => entries ?? [])\n );\n // Raise each client's persisted counter to the highest id among `ids`\n // (never lowering it). Run before journal entries are deleted, so the\n // counter is the high-water mark of everything that has ever left the\n // journal: `appendNext` heals the counter from the *live* index only, and\n // without this an acknowledged (or quarantined) id whose counter write was\n // lost would be issued again, and the backend would skip the new mutation\n // as an idempotent duplicate (`id <= lastMutationId`): a silent lost write.\n const raiseCounters = (\n ids: ReadonlyArray<JournalIndexEntry>\n ): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n const highest = highestIds(ids);\n if (R.isEmptyReadonlyRecord(highest)) return;\n const counters = (yield* readDecoded(\"counters\", CountersFromJson)) ?? {};\n const raised = raisedCounters(counters, highest);\n if (raised !== undefined) yield* writeJson(\"counters\", raised);\n });\n\n // ─── Compaction (unlocked inner forms; #249) ───────────────────────────\n //\n // Dropping superseded entries and renumbering the survivors rewrites\n // several keys, and the KVS has no transactions. So the whole outcome is\n // first written as ONE record (`compactionIntent`) — the commit point —\n // and then applied by steps that are each idempotent: clear the stale\n // bodies, write the renumbered bodies, write the index, rewind the\n // counter, delete the intent. A crash anywhere before the intent lands\n // leaves the old, contiguous journal untouched; a crash after it is\n // rolled forward by `recoverCompaction` on the next open. Either way the\n // journal, the index and the counter agree and the ids stay gap-free.\n // (Writing new bodies in place without the intent could overwrite a live\n // entry's body before the index moved, which is the corruption this\n // avoids.)\n const applyCompaction = (intent: typeof CompactionIntentFromJson.Type) =>\n Effect.gen(function* () {\n for (const id of intent.staleIds) yield* remove(journalBodyKey(intent.clientId, id));\n for (const m of intent.moved) yield* writeJson(journalBodyKey(m.clientId, m.mutationId), m);\n yield* writeJson(\"journalIndex\", intent.index);\n const counters = (yield* readDecoded(\"counters\", CountersFromJson)) ?? {};\n yield* writeJson(\"counters\", { ...counters, [intent.clientId]: intent.counter });\n yield* remove(COMPACTION_KEY);\n });\n // Set while an intent may still be on disk, so any journal operation\n // finishes it first (an earlier apply can fail without a crash, and an\n // append landing before the replay would be clobbered by it).\n let compactionPending = false;\n const recoverCompaction = Effect.gen(function* () {\n const intent = yield* readDecoded(COMPACTION_KEY, CompactionIntentFromJson);\n if (intent !== undefined) yield* applyCompaction(intent);\n compactionPending = false;\n });\n const settleCompaction: Effect.Effect<void, StoreError> = Effect.suspend(() =>\n compactionPending ? recoverCompaction : Effect.void\n );\n const sentMarks = readDecoded(SENT_KEY, CountersFromJson).pipe(\n Effect.map((marks) => marks ?? {})\n );\n\n // Read a collection's rows through the per-row index; a corrupt row value\n // fails as a StoreError (envelope-validated). When no index exists, fall\n // back to a legacy blob at `rows/{collection}` — the read side of the\n // transparent migration, so a store not yet split still reads correctly.\n const listRowsOf = (collection: string) => listRowsWith(readDecoded, collection);\n\n const pendingMutationsOf = pendingMutationsWith(readDecoded);\n\n // `pendingMutationsOf`'s count from the index alone: one read, no bodies\n // (#260). A store not yet migrated holds the legacy blob instead.\n const pendingCountOf: Effect.Effect<number, StoreError> = Effect.gen(function* () {\n const index = yield* readDecoded(\"journalIndex\", JournalIndexFromJson);\n if (index !== undefined) return index.length;\n const legacy = yield* readDecoded(LEGACY_JOURNAL_KEY, JournalFromJson);\n return legacy?.length ?? 0;\n });\n\n // ─── Unpulled tail (unlocked inner forms; #336) ────────────────────────\n //\n // The tail has its own keyspace, an index plus one body per entry, laid\n // out like the journal. A park writes the bodies and then the index, which\n // is the commit. A release writes the index and then removes the bodies. So\n // a crash leaves at worst an unreachable body, or an index entry whose body\n // is gone (reads skip it), and never a listed entry without its body.\n //\n // Two crash windows need the open-time settle below. (1) A park that\n // committed but did not trim the journal leaves each entry in both places;\n // the journal copy would be pushed again and replayed over the tail's, so\n // the open drops it from the journal. (2) A release that wrote\n // `beginRelease` but did not finish leaves the covered entries in the\n // journal and the tail; the open finishes it by re-applying the recorded\n // patch, which is idempotent, so the rows end up as the pull left them\n // whether or not any of them were written before the crash.\n const unpulledIndexOf = readDecoded(UNPULLED_INDEX_KEY, JournalIndexFromJson).pipe(\n Effect.map((entries) => entries ?? [])\n );\n const unpulledOf = unpulledWith(readDecoded);\n\n const parkUnpulledInner = (\n mutations: ReadonlyArray<Mutation>\n ): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n if (Arr.isReadonlyArrayEmpty(mutations)) return;\n // A journal copy may be left behind by the trim that follows, so the finish must run (#387).\n yield* Ref.set(finishPending, true);\n for (const m of mutations) yield* writeJson(unpulledBodyKey(m.clientId, m.mutationId), m);\n const index = yield* unpulledIndexOf;\n const next = appendMissing(\n index,\n mutations.map((m) => ({ clientId: m.clientId, mutationId: m.mutationId }))\n );\n if (next.length !== index.length) yield* writeJson(UNPULLED_INDEX_KEY, next);\n // The parked ids stay reserved even once their journal copies are gone.\n yield* raiseCounters(mutations);\n });\n\n // The bodies go before the index, so a crash cannot orphan one. A crash\n // (or a failed removal) between the two leaves index entries whose bodies\n // are gone: reads skip them. The marker that `beginRelease` wrote first is\n // still down, so the next open finishes the release.\n const releaseUnpulledInner = (\n lastMutationIds: Readonly<Record<string, number>>\n ): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n const index = yield* unpulledIndexOf;\n const released = index.filter((entry) => coveredBy(lastMutationIds, entry));\n for (const entry of released) {\n yield* remove(unpulledBodyKey(entry.clientId, entry.mutationId));\n }\n if (Arr.isReadonlyArrayNonEmpty(released)) {\n yield* writeJson(\n UNPULLED_INDEX_KEY,\n index.filter((entry) => !coveredBy(lastMutationIds, entry))\n );\n }\n yield* remove(RELEASE_KEY);\n });\n\n const clearUnpulledInner: Effect.Effect<void, StoreError> = Effect.gen(function* () {\n const index = yield* unpulledIndexOf;\n if (Arr.isReadonlyArrayNonEmpty(index)) yield* writeJson(UNPULLED_INDEX_KEY, []);\n for (const entry of index) {\n yield* remove(unpulledBodyKey(entry.clientId, entry.mutationId));\n }\n yield* remove(RELEASE_KEY);\n });\n\n // ─── Quarantine (unlocked inner forms; #212) ───────────────────────────\n //\n // A quarantine lives in its own keyspace, not in the journal — that is\n // the security property, not an implementation detail: `pendingMutations`\n // reads the journal, `push` reads `pendingMutations`, so an entry moved\n // here is structurally unreachable from any push, whatever identity is\n // signed in. Nothing but `discardQuarantine` ever deletes one.\n\n const quarantineIndexOf: Effect.Effect<\n ReadonlyArray<Identity.Fingerprint>,\n StoreError\n > = readDecoded(QUARANTINE_INDEX_KEY, FingerprintsFromJson).pipe(\n Effect.map((list) => list ?? [])\n );\n\n const quarantinedOf = (\n fingerprint: Identity.Fingerprint\n ): Effect.Effect<ReadonlyArray<Mutation>, StoreError> =>\n readDecoded(quarantineKey(fingerprint), MutationsFromJson).pipe(\n Effect.map((entries) => entries ?? [])\n );\n\n // Empty the journal outright — bodies, index, and any legacy blob — with\n // no acknowledgement implied. Only ever called with the entries already\n // safely written to a quarantine.\n const clearJournalInner = Effect.gen(function* () {\n for (const entry of yield* journalIndex) {\n yield* remove(journalBodyKey(entry.clientId, entry.mutationId));\n }\n yield* writeJson(\"journalIndex\", []);\n yield* remove(LEGACY_JOURNAL_KEY);\n });\n\n // Drop the journal entries `drop` selects, reserving their ids first (as\n // `acknowledge` does). Skipped on an un-migrated legacy blob, which has no\n // index to rewrite.\n const trimJournal = (\n drop: (entry: JournalIndexEntry) => boolean\n ): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n const index = yield* readDecoded(\"journalIndex\", JournalIndexFromJson);\n if (index === undefined) return;\n const dropped = index.filter(drop);\n if (Arr.isReadonlyArrayEmpty(dropped)) return;\n yield* raiseCounters(dropped);\n for (const entry of dropped)\n yield* remove(journalBodyKey(entry.clientId, entry.mutationId));\n yield* writeJson(\n \"journalIndex\",\n index.filter((entry) => !drop(entry))\n );\n });\n\n // Quarantine first, empty the journal second: a crash between the two\n // leaves the entries in both places, which the next boot re-quarantines\n // idempotently (`appendDistinct`) — where the opposite order would lose\n // them. The identity stamp is written after all of this, so an\n // interrupted reset simply runs again on the next open.\n const quarantinePendingInner = (\n fingerprint: Identity.Fingerprint\n ): Effect.Effect<number, StoreError> =>\n Effect.gen(function* () {\n const pending = yield* pendingMutationsOf;\n if (Arr.isReadonlyArrayEmpty(pending)) return 0;\n const held = yield* quarantinedOf(fingerprint);\n yield* writeJson(quarantineKey(fingerprint), appendDistinct(held, pending));\n const index = yield* quarantineIndexOf;\n if (!index.includes(fingerprint)) {\n yield* writeJson(QUARANTINE_INDEX_KEY, [...index, fingerprint]);\n }\n // Ids leaving the journal stay reserved (see `raiseCounters`).\n yield* raiseCounters(pending);\n yield* clearJournalInner;\n return pending.length;\n });\n\n const discardQuarantineInner = (\n fingerprint: Identity.Fingerprint\n ): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n yield* remove(quarantineKey(fingerprint));\n const index = yield* quarantineIndexOf;\n if (index.includes(fingerprint)) {\n yield* writeJson(\n QUARANTINE_INDEX_KEY,\n index.filter((held) => held !== fingerprint)\n );\n }\n });\n\n const releaseQuarantineInner = (\n fingerprint: Identity.Fingerprint\n ): Effect.Effect<number, StoreError> =>\n Effect.gen(function* () {\n const entries = yield* quarantinedOf(fingerprint);\n if (Arr.isReadonlyArrayEmpty(entries)) return 0;\n const index = yield* journalIndex;\n const restored: Array<JournalIndexEntry> = [];\n for (const entry of entries) {\n yield* writeJson(journalBodyKey(entry.clientId, entry.mutationId), entry);\n restored.push({ clientId: entry.clientId, mutationId: entry.mutationId });\n }\n yield* writeJson(\"journalIndex\", [...index, ...restored]);\n yield* discardQuarantineInner(fingerprint);\n return entries.length;\n });\n\n // Clear every tracked collection's rows and indexes (unlocked inner form,\n // reused by clearRows, applyRowOps, and the migration reset).\n const clearRowsInner = Effect.gen(function* () {\n for (const collection of yield* collections) {\n for (const id of yield* rowIndex(collection)) yield* remove(rowKey(collection, id));\n yield* remove(rowIndexKey(collection));\n yield* remove(legacyRowsKey(collection));\n }\n yield* writeJson(\"collections\", []);\n });\n\n // Apply one collection's grouped changes: write/remove each row value, then\n // rewrite the id-index once (the only O(collection) cost, paid once per\n // touched collection per batch — never once per op).\n const flushCollection = (collection: string, changes: RowChanges) =>\n Effect.gen(function* () {\n const ids = new Set(yield* rowIndex(collection));\n for (const [id, row] of changes) {\n if (row === null) {\n yield* remove(rowKey(collection, id));\n ids.delete(id);\n } else {\n yield* writeJson(rowKey(collection, id), row);\n ids.add(id);\n }\n }\n yield* writeJson(rowIndexKey(collection), [...ids]);\n yield* trackCollection(collection);\n });\n\n const applyRowOpsInner = (ops: ReadonlyArray<PatchOp>) =>\n Effect.gen(function* () {\n const plan = planRowOps(ops);\n if (plan.clear) yield* clearRowsInner;\n for (const [collection, changes] of plan.groups)\n yield* flushCollection(collection, changes);\n });\n\n // Split a legacy whole-collection blob into per-row keys + an id-index.\n const migrateCollection = (collection: string) =>\n Effect.gen(function* () {\n const map = yield* readDecoded(legacyRowsKey(collection), RowMapFromJson);\n if (map === undefined) return;\n const ids = Object.keys(map);\n for (const id of ids) yield* writeJson(rowKey(collection, id), map[id]);\n yield* writeJson(rowIndexKey(collection), ids);\n yield* remove(legacyRowsKey(collection));\n });\n\n // Split the legacy whole-journal array into per-mutation bodies + an index.\n const migrateJournal = Effect.gen(function* () {\n const legacy = yield* readDecoded(LEGACY_JOURNAL_KEY, JournalFromJson);\n if (legacy === undefined) return;\n const index: Array<JournalIndexEntry> = [];\n for (const m of legacy) {\n yield* writeJson(journalBodyKey(m.clientId, m.mutationId), m);\n index.push({ clientId: m.clientId, mutationId: m.mutationId });\n }\n yield* writeJson(\"journalIndex\", index);\n yield* remove(LEGACY_JOURNAL_KEY);\n });\n\n // Last resort when a legacy blob is corrupt beyond recovery: the store is a\n // cache of server state, so drop the rows + journal and reset the cookie,\n // leaving the client able to re-pull from scratch (counters survive).\n const resetToEmpty = Effect.gen(function* () {\n yield* clearRowsInner;\n yield* remove(LEGACY_JOURNAL_KEY);\n yield* remove(\"journalIndex\");\n yield* remove(\"cookie\");\n });\n\n // Migrate a layout-1 (or unstamped) store into layout 2 once, then stamp\n // the version. Envelope-validated; a corrupt legacy blob takes the\n // destructive fallback rather than wedging the store.\n const migrate = Effect.gen(function* () {\n for (const collection of yield* collections) yield* migrateCollection(collection);\n yield* migrateJournal;\n }).pipe(Effect.catch(() => resetToEmpty));\n\n // Transparent forward-migration on first open. Each collection migrates\n // atomically — the id-index is written only after every row value, and the\n // legacy blob removed only after the index — so a mid-flight failure leaves\n // the collection readable via the legacy fallback, and the version is\n // stamped only once migration completes, so the next open simply retries.\n // Kept infallible at construction (like the original zero-I/O open): a\n // transient store error here is swallowed, and reads still resolve through\n // the legacy fallback until the next open re-migrates.\n const openMigration = Effect.gen(function* () {\n const version = yield* store.get(LAYOUT_KEY);\n if (version !== CURRENT_LAYOUT) {\n yield* locked(migrate.pipe(Effect.andThen(store.set(LAYOUT_KEY, CURRENT_LAYOUT))));\n }\n });\n yield* openMigration.pipe(\n Effect.catchTag([\"KeyValueStoreError\", \"StoreError\"], () => Effect.void)\n );\n\n // Finish a compaction a previous run was interrupted in (#249). Kept\n // infallible at construction like the opens around it: if recovery fails\n // here the flag stays set, and the first journal operation retries it.\n yield* locked(recoverCompaction).pipe(\n Effect.catchTag(\"StoreError\", () =>\n Effect.sync(() => {\n compactionPending = true;\n })\n )\n );\n\n // Drop journal index entries whose body is gone (#294). Removals delete\n // the bodies before rewriting the index (`acknowledge`, the quarantine's\n // `clearJournalInner`), so a crash between the two leaves entries with\n // nothing to push. Reads already skip them, but `pendingCount` and the\n // high-water check count the index alone (#260), and `compactPending`\n // refuses a run with a missing body, so they are repaired here, once per\n // open, rather than paying a body read on every count. The dropped ids\n // stay reserved, as `acknowledge` keeps them (see `raiseCounters`). Runs\n // after the compaction roll-forward, whose index supersedes this one, and\n // writes nothing when every body is present.\n const repairJournalIndex = Effect.gen(function* () {\n const index = yield* readDecoded(\"journalIndex\", JournalIndexFromJson);\n if (index === undefined) return;\n const kept: Array<JournalIndexEntry> = [];\n const orphaned: Array<JournalIndexEntry> = [];\n for (const entry of index) {\n const key = journalBodyKey(entry.clientId, entry.mutationId);\n const present = yield* store\n .has(key)\n .pipe(Effect.mapError(storeError(`Failed to read \"${key}\"`)));\n (present ? kept : orphaned).push(entry);\n }\n if (Arr.isReadonlyArrayEmpty(orphaned)) return;\n yield* raiseCounters(orphaned);\n yield* writeJson(\"journalIndex\", kept);\n });\n // Infallible at construction like the opens around it: a failed repair\n // leaves the index as it was (reads still skip the missing bodies), and\n // the next open retries.\n yield* locked(settleCompaction.pipe(Effect.andThen(repairJournalIndex))).pipe(\n Effect.catch(() => Effect.void)\n );\n\n // Finish a pull release, or drop the journal copies of a park, that a\n // crash interrupted (#336). Not swallowed: the tail and the journal then\n // disagree, and serving either would double-count or revert, so the store\n // is sealed like an unestablished identity boundary. The next open retries.\n // Roll an outstanding release forward from its record (#336, #387). The patch is idempotent, so\n // re-applying it is correct whether or not the interrupted run had written rows.\n const rollForward = (release: PullRelease): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n yield* applyRowOpsInner(release.patch);\n if (release.cookie !== undefined) {\n yield* store\n .set(\"cookie\", release.cookie)\n .pipe(Effect.mapError(storeError(`Failed to write \"cookie\"`)));\n }\n yield* trimJournal((entry) => coveredBy(release.lastMutationIds, entry));\n yield* releaseUnpulledInner(release.lastMutationIds);\n });\n const finishReleaseInner: Effect.Effect<void, StoreError> = Effect.gen(function* () {\n const release = yield* readDecoded(RELEASE_KEY, ReleaseIntentFromJson);\n if (release !== undefined) yield* rollForward(release);\n });\n // The journal copies of whatever the tail still parks, dropped as an open drops them (#336). Read\n // after the roll-forward, which releases entries from the tail. A failed trim seals the store even\n // with no record outstanding: a copy left in both the journal and the tail would be double-counted\n // by reads and pushed again.\n const trimParkedCopies: Effect.Effect<void, StoreError> = Effect.gen(function* () {\n const parked = yield* unpulledIndexOf;\n if (Arr.isReadonlyArrayNonEmpty(parked)) {\n const keys = new Set(parked.map(entryKey));\n yield* trimJournal((entry) => keys.has(entryKey(entry)));\n }\n });\n // The tail settle: the roll-forward, then the journal copies of whatever is still parked. The\n // open runs this one body, so it leaves the same state as the in-process finish (#387).\n const settleTailInner = Effect.gen(function* () {\n yield* finishReleaseInner;\n yield* trimParkedCopies;\n });\n const tailFailure = yield* locked(settleTailInner).pipe(\n Effect.as<StoreError | undefined>(undefined),\n Effect.catchTag(\"StoreError\", (error) => Effect.succeed<StoreError | undefined>(error))\n );\n if (tailFailure !== undefined) return sealed(tailFailure);\n yield* Ref.set(finishPending, false);\n // The finish of a record already read: the roll-forward, then the parked copies. Any failure seals\n // the store (#387), since the writes may be part-way.\n const finishRead = (release: PullRelease | undefined): Effect.Effect<void, StoreError> =>\n Effect.gen(function* () {\n yield* Effect.gen(function* () {\n if (release !== undefined) yield* rollForward(release);\n yield* trimParkedCopies;\n }).pipe(Effect.tapError((error) => Ref.set(sealedBy, error)));\n yield* Ref.set(finishPending, false);\n });\n // The in-process finish, run by every row write and clear, and by `finishRelease`. It is a no-op\n // while `finishPending` is clear. Its first step is a read of the record, and a failure there\n // fails the call alone: nothing has been written. Every failure after that read seals the store,\n // because a roll-forward or a journal trim may have part-way written what the record describes,\n // and no later write may run over it. The open then finishes it from the same record (#387).\n const finishOrSeal = Effect.gen(function* () {\n if (!(yield* Ref.get(finishPending))) return;\n yield* finishRead(yield* readDecoded(RELEASE_KEY, ReleaseIntentFromJson));\n });\n\n // Local store-version buster (#48): a mismatch clears confirmed rows + the\n // cookie (so the next pull rehydrates fully) but preserves the journal, then\n // stamps the new version. Kept infallible at construction, like the\n // migration open above.\n const openStoreVersion = Effect.gen(function* () {\n const desired = options?.storeVersion;\n if (desired === undefined) return;\n const current = yield* store.get(STORE_VERSION_KEY);\n if (current === desired) return;\n const stampVersion = store\n .set(STORE_VERSION_KEY, desired)\n .pipe(Effect.mapError(storeError(`Failed to write \"${STORE_VERSION_KEY}\"`)));\n yield* locked(\n clearRowsInner.pipe(\n Effect.andThen(remove(\"cookie\")),\n // Journal deliberately untouched: pending intents survive the buster.\n Effect.andThen(stampVersion)\n )\n );\n });\n yield* openStoreVersion.pipe(Effect.catch(() => Effect.void));\n\n // The identity boundary on open (#212): compare the configured\n // fingerprint with the replica's stamp and apply `Identity.transitionOf`.\n // A `Reset` quarantines the unpushed journal under the **superseded**\n // fingerprint before dropping rows and the cookie, so the previous\n // principal's rows are never served to this one and their write intents\n // are neither lost nor inherited. The stamp is the last write of the\n // transition, so an interrupted reset re-runs on the next open rather\n // than leaving a replica stamped for an identity it was never cleared\n // for. The release runs on every open, `Unchanged` included: it is how\n // re-signing in makes this identity's own quarantined entries pushable\n // again, and it closes the crash window between stamping and releasing.\n //\n // Unset `identity` means the boundary is off — no stamp, no comparison,\n // behaviour identical to before. Kept infallible at construction, like\n // the migration and store-version opens above.\n const openIdentity = Effect.gen(function* () {\n const next = options?.identity;\n if (next === undefined) return;\n const stamped = yield* store\n .get(IDENTITY_KEY)\n .pipe(Effect.mapError(storeError(`Failed to read \"${IDENTITY_KEY}\"`)));\n const current = stamped ?? Identity.unstamped;\n const transition = Identity.transitionOf(current, next);\n const stamp = store\n .set(IDENTITY_KEY, next)\n .pipe(Effect.mapError(storeError(`Failed to write \"${IDENTITY_KEY}\"`)));\n yield* locked(\n Effect.gen(function* () {\n if (transition === \"Reset\") {\n yield* quarantinePendingInner(current);\n yield* clearRowsInner;\n yield* clearUnpulledInner;\n yield* remove(\"cookie\");\n }\n if (transition !== \"Unchanged\") yield* stamp;\n yield* releaseQuarantineInner(next);\n })\n );\n });\n // Unlike the two opens above, this one is NOT swallowed: a boundary that\n // could not be established must not be reported as established. The store\n // is sealed instead (see {@link sealed}) — nothing served, nothing pushed,\n // nothing destroyed, and the next open retries.\n const boundaryFailure = yield* openIdentity.pipe(\n Effect.as<StoreError | undefined>(undefined),\n Effect.catchTag(\"StoreError\", (error) => Effect.succeed<StoreError | undefined>(error))\n );\n if (boundaryFailure !== undefined) return sealed(boundaryFailure);\n\n // ─── Atomic batches (unlocked staged forms; #393) ──────────────────────\n //\n // With an AtomicKeyValue in context, a pull's release and a push ack's park-then-trim commit as ONE\n // batch, with no release record. Each batch stages every write the record path would make, reading\n // through its own staged values, and hands the whole set to the seam once. So the batch writes what\n // the record path writes, each row and index once, and a failed or interrupted batch leaves the store\n // at its state before the operation: nothing reached the store. Keys are staged unprefixed and given\n // the namespace when they are handed to the seam. Every batch runs under `lock`, after settling any\n // compaction an interrupted run left, as the journal operations do.\n const atomic = Option.getOrUndefined(yield* Effect.serviceOption(AtomicKeyValue));\n const stageBatch = () => {\n // A staged value: the text to write, or `undefined` for a removal.\n const staged = new Map<string, string | undefined>();\n // Decided when the read runs, not when it is built: a read built before a write must see it.\n const read = <A>(\n key: string,\n codec: Schema.Codec<A, string>\n ): Effect.Effect<A | undefined, StoreError> =>\n Effect.suspend(() => {\n if (!staged.has(key)) return readDecoded(key, codec);\n const raw = staged.get(key);\n return raw === undefined\n ? Effect.succeed(undefined)\n : Schema.decodeUnknownEffect(codec)(raw).pipe(\n Effect.mapError(storeError(`Corrupt persisted state at \"${key}\"`))\n );\n });\n return {\n read,\n /** A JSON value, as the record path's `writeJson` writes it. */\n putJson: (key: string, value: unknown) => {\n staged.set(key, JSON.stringify(value));\n },\n /** A value written verbatim, as the cookie is (`setCookie`). */\n putRaw: (key: string, raw: string) => {\n staged.set(key, raw);\n },\n drop: (key: string) => {\n staged.set(key, undefined);\n },\n ops: (): ReadonlyArray<KeyValueOp> =>\n Array.from(staged, ([key, raw]) =>\n raw === undefined\n ? ({ _tag: \"Remove\", key: `${namespace}${key}` } as const)\n : ({ _tag: \"Set\", key: `${namespace}${key}`, value: raw } as const)\n ),\n };\n };\n type Stage = ReturnType<typeof stageBatch>;\n\n // `raiseCounters`, staged.\n const stagedRaiseCounters = (b: Stage, ids: ReadonlyArray<JournalIndexEntry>) =>\n Effect.gen(function* () {\n const highest = highestIds(ids);\n if (R.isEmptyReadonlyRecord(highest)) return;\n const counters = (yield* b.read(\"counters\", CountersFromJson)) ?? {};\n const raised = raisedCounters(counters, highest);\n if (raised !== undefined) b.putJson(\"counters\", raised);\n });\n\n // `trimJournal`, staged: the same index rewrite, bodies removed before it, and the ids reserved.\n const stagedTrimJournal = (b: Stage, drop: (entry: JournalIndexEntry) => boolean) =>\n Effect.gen(function* () {\n const index = yield* b.read(\"journalIndex\", JournalIndexFromJson);\n if (index === undefined) return;\n const dropped = index.filter(drop);\n if (Arr.isReadonlyArrayEmpty(dropped)) return;\n yield* stagedRaiseCounters(b, dropped);\n for (const entry of dropped) b.drop(journalBodyKey(entry.clientId, entry.mutationId));\n b.putJson(\n \"journalIndex\",\n index.filter((entry) => !drop(entry))\n );\n });\n\n // `releaseUnpulledInner`, staged, without the record's removal: a batch writes no record.\n const stagedReleaseTail = (b: Stage, lastMutationIds: Readonly<Record<string, number>>) =>\n Effect.gen(function* () {\n const index = (yield* b.read(UNPULLED_INDEX_KEY, JournalIndexFromJson)) ?? [];\n const released = index.filter((entry) => coveredBy(lastMutationIds, entry));\n for (const entry of released) b.drop(unpulledBodyKey(entry.clientId, entry.mutationId));\n if (Arr.isReadonlyArrayNonEmpty(released)) {\n b.putJson(\n UNPULLED_INDEX_KEY,\n index.filter((entry) => !coveredBy(lastMutationIds, entry))\n );\n }\n });\n\n // `parkUnpulledInner`, staged.\n const stagedPark = (b: Stage, mutations: ReadonlyArray<Mutation>) =>\n Effect.gen(function* () {\n if (Arr.isReadonlyArrayEmpty(mutations)) return;\n for (const m of mutations) b.putJson(unpulledBodyKey(m.clientId, m.mutationId), m);\n const index = (yield* b.read(UNPULLED_INDEX_KEY, JournalIndexFromJson)) ?? [];\n const next = appendMissing(\n index,\n mutations.map((m) => ({ clientId: m.clientId, mutationId: m.mutationId }))\n );\n if (next.length !== index.length) b.putJson(UNPULLED_INDEX_KEY, next);\n yield* stagedRaiseCounters(b, mutations);\n });\n\n // `applyRowOpsInner`, staged: the same per-row writes, one id-index per touched collection, and the\n // collection list kept current, as the record path keeps it.\n const stagedRows = (b: Stage, ops: ReadonlyArray<PatchOp>) =>\n Effect.gen(function* () {\n const plan = planRowOps(ops);\n const collectionList = b\n .read(\"collections\", CollectionsFromJson)\n .pipe(Effect.map((list) => list ?? []));\n const rowIdsOf = (collection: string) =>\n b.read(rowIndexKey(collection), IdsFromJson).pipe(Effect.map((ids) => ids ?? []));\n if (plan.clear) {\n for (const collection of yield* collectionList) {\n for (const id of yield* rowIdsOf(collection)) b.drop(rowKey(collection, id));\n b.drop(rowIndexKey(collection));\n b.drop(legacyRowsKey(collection));\n }\n b.putJson(\"collections\", []);\n }\n for (const [collection, changes] of plan.groups) {\n const ids = new Set(yield* rowIdsOf(collection));\n for (const [id, row] of changes) {\n if (row === null) {\n b.drop(rowKey(collection, id));\n ids.delete(id);\n } else {\n b.putJson(rowKey(collection, id), row);\n ids.add(id);\n }\n }\n b.putJson(rowIndexKey(collection), [...ids]);\n const list = yield* collectionList;\n if (!list.includes(collection)) b.putJson(\"collections\", [...list, collection]);\n }\n });\n\n // Commit a staged batch as one seam call. Nothing is written for an empty batch.\n const commitStaged = (\n atomicSeam: NonNullable<typeof atomic>,\n b: Stage\n ): Effect.Effect<void, StoreError> =>\n Effect.suspend(() => {\n const ops = b.ops();\n return Arr.isReadonlyArrayEmpty(ops) ? Effect.void : atomicSeam.apply(ops);\n });\n\n // Each member first finishes an outstanding release record, as a row write does (#387). A record\n // left by a failed record-path write would otherwise replay over the batch's newer state on a later\n // finish; the finish reads the record, so a failure there fails the batch with nothing written.\n const batchMembers: Pick<ClientStore, \"commitPull\" | \"commitAcknowledgement\"> =\n atomic === undefined\n ? {}\n : {\n commitPull: (release) =>\n locked(\n Effect.gen(function* () {\n yield* finishOrSeal;\n yield* settleCompaction;\n const b = stageBatch();\n yield* stagedRows(b, release.patch);\n if (release.cookie !== undefined) b.putRaw(\"cookie\", release.cookie);\n yield* stagedTrimJournal(b, (entry) => coveredBy(release.lastMutationIds, entry));\n yield* stagedReleaseTail(b, release.lastMutationIds);\n yield* commitStaged(atomic, b);\n })\n ),\n commitAcknowledgement: (parked, lastMutationIds) =>\n locked(\n Effect.gen(function* () {\n yield* finishOrSeal;\n yield* settleCompaction;\n const b = stageBatch();\n yield* stagedPark(b, parked);\n yield* stagedTrimJournal(b, (entry) => coveredBy(lastMutationIds, entry));\n yield* commitStaged(atomic, b);\n })\n ),\n };\n\n // The snapshot (#392). Under `locked`, which excludes this store's writers. With an AtomicKeyValue that\n // reads every entry in one transaction, the state is decoded from that one read, so a batch another\n // connection commits cannot land between the reads either.\n const readAll = atomic?.readAll;\n const replicaState: Effect.Effect<ReplicaState, StoreError> =\n readAll === undefined\n ? replicaStateWith(readDecoded)\n : readAll.pipe(\n Effect.map((entries: ReadonlyArray<KeyValueEntry>) =>\n readerOver(\n new Map(\n entries\n .filter((entry) => entry.key.startsWith(namespace))\n .map((entry) => [entry.key.slice(namespace.length), entry.value] as const)\n )\n )\n ),\n Effect.flatMap(replicaStateWith)\n );\n\n return ClientStore.of({\n ...batchMembers,\n snapshot: locked(settleCompaction.pipe(Effect.andThen(replicaState))),\n getRow: (collection, id) => unsealed(readDecoded(rowKey(collection, id), RowFromJson)),\n listRows: (collection) => unsealed(listRowsOf(collection)),\n listCollections: unsealed(collections),\n // A row write finishes an outstanding release first, under the same permit hold, so the\n // release's patch cannot land over it on a later finish (#387). The release's own patch\n // goes through `applyRowOps`, which does not finish: it is the release's write.\n putRow: (collection, row) =>\n locked(\n Effect.gen(function* () {\n yield* finishOrSeal;\n yield* writeJson(rowKey(collection, row.id), row);\n const ids = yield* rowIndex(collection);\n if (!ids.includes(row.id)) yield* writeJson(rowIndexKey(collection), [...ids, row.id]);\n yield* trackCollection(collection);\n })\n ),\n delRow: (collection, id) =>\n locked(\n Effect.gen(function* () {\n yield* finishOrSeal;\n yield* remove(rowKey(collection, id));\n const ids = yield* rowIndex(collection);\n if (ids.includes(id))\n yield* writeJson(\n rowIndexKey(collection),\n ids.filter((x) => x !== id)\n );\n })\n ),\n // An outstanding release is finished under the same lock, before the rows go (#387).\n clearRows: locked(finishOrSeal.pipe(Effect.andThen(clearRowsInner))),\n applyRowOps: (ops) => locked(applyRowOpsInner(ops)),\n\n // Refused for an id the tail holds (see `ClientStore.appendMutation`): a copy written here would\n // sit in the journal and the tail until a row write trimmed it, and reads would count it twice.\n appendMutation: (mutation) =>\n locked(\n Effect.gen(function* () {\n yield* settleCompaction;\n if ((yield* unpulledIndexOf).some((held) => entryKey(held) === entryKey(mutation))) {\n return yield* alreadyParked(mutation);\n }\n const index = yield* journalIndex;\n if (highWater !== undefined && index.length >= highWater) {\n return yield* new StoreError({\n message: `Journal high-water exceeded (${highWater} pending mutations); refusing to drop the intent`,\n });\n }\n yield* writeJson(journalBodyKey(mutation.clientId, mutation.mutationId), mutation);\n yield* writeJson(\"journalIndex\", [\n ...index,\n { clientId: mutation.clientId, mutationId: mutation.mutationId },\n ]);\n })\n ),\n // Allocate and append under one lock hold (#258). The high-water check\n // runs first and the counter is written *last*: a refused or failed\n // append never advances it, and a crash between the index write and the\n // counter write is healed by taking the larger of the counter and the\n // highest id the journal already holds for the client, so an id is\n // neither skipped nor reissued over a live entry.\n appendNext: (draft) =>\n locked(\n // Uninterruptible: an interrupt between the index write and the\n // counter write would leave an entry journaled with its id not yet\n // reserved. Acknowledge/quarantine now raise the counter before they\n // delete, which closes the reissue window; this keeps the append\n // all-or-nothing as far as the caller can observe.\n Effect.uninterruptible(\n Effect.gen(function* () {\n yield* settleCompaction;\n const index = yield* journalIndex;\n if (highWater !== undefined && index.length >= highWater) {\n return yield* new StoreError({\n message: `Journal high-water exceeded (${highWater} pending mutations); refusing to drop the intent`,\n });\n }\n const counters = (yield* readDecoded(\"counters\", CountersFromJson)) ?? {};\n let last = counters[draft.clientId] ?? 0;\n for (const entry of index) {\n if (entry.clientId === draft.clientId && entry.mutationId > last) {\n last = entry.mutationId;\n }\n }\n const mutation: Mutation = { ...draft, mutationId: last + 1 };\n yield* writeJson(journalBodyKey(mutation.clientId, mutation.mutationId), mutation);\n yield* writeJson(\"journalIndex\", [\n ...index,\n { clientId: mutation.clientId, mutationId: mutation.mutationId },\n ]);\n // The entry is journaled; a failure to persist the counter must not\n // report the append as failed: the caller would believe the intent\n // was dropped while it sits in the journal and is pushed anyway.\n // The id is not lost: the live index heals the counter above, and\n // `acknowledge` / `quarantinePending` raise it to the highest id\n // they remove, so the id cannot be reissued after it leaves.\n yield* writeJson(\"counters\", {\n ...counters,\n [draft.clientId]: mutation.mutationId,\n }).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\"ClientStore: journaled but could not persist the id counter\", {\n error,\n })\n )\n );\n return mutation;\n })\n )\n ),\n pendingMutations: locked(settleCompaction.pipe(Effect.andThen(pendingMutationsOf))),\n // The index alone, no bodies (#260). Settling a compaction first matters:\n // a committed but unapplied intent's index is the one that counts.\n pendingCount: locked(settleCompaction.pipe(Effect.andThen(pendingCountOf))),\n acknowledge: (clientId, upTo) =>\n locked(\n Effect.gen(function* () {\n yield* settleCompaction;\n const kept: Array<JournalIndexEntry> = [];\n const dropped: Array<JournalIndexEntry> = [];\n for (const entry of yield* journalIndex) {\n if (entry.clientId === clientId && entry.mutationId <= upTo) dropped.push(entry);\n else kept.push(entry);\n }\n // Reserve the ids first: once the entries are gone the index can\n // no longer heal the counter, and a lost counter write would have\n // the next append reissue an acknowledged id.\n yield* raiseCounters(dropped);\n for (const entry of dropped) {\n yield* remove(journalBodyKey(entry.clientId, entry.mutationId));\n }\n yield* writeJson(\"journalIndex\", kept);\n })\n ),\n // The commit point is the durable intent. Everything from there is\n // uninterruptible, and a failure to *apply* the intent is not a failure\n // of the compaction: it is committed, `settleCompaction` rolls it\n // forward before the next journal operation, and the caller must learn\n // the renumbering now (returning the error instead would leave the\n // engine, Paced trackers and ack handles on ids the store has already\n // left behind: the newest paced write would be dropped, #249 review B1).\n compactPending: (clientId, mutationIds) =>\n locked(\n Effect.uninterruptible(\n Effect.gen(function* () {\n yield* settleCompaction;\n // An un-migrated legacy blob has no index to rewrite; leave it be.\n const index = yield* readDecoded(\"journalIndex\", JournalIndexFromJson);\n if (index === undefined) return NO_COMPACTION;\n const watermark = (yield* sentMarks)[clientId] ?? 0;\n // Plan over the index alone; read only the bodies that move.\n const plan = planCompaction(index, clientId, mutationIds, watermark);\n if (plan === undefined) return NO_COMPACTION;\n const moved: Array<Mutation> = [];\n for (const { from, to } of plan.result.renumbered) {\n const body = yield* readDecoded(journalBodyKey(clientId, from), MutationFromJson);\n // A missing body cannot be moved, and leaving its index entry\n // behind would strand an id with nothing to push. Refuse, before\n // anything is committed, rather than corrupt the run.\n if (body === undefined) {\n return yield* new StoreError({\n message: `Journal body missing for mutation ${from} of client ${clientId}; refusing to compact`,\n });\n }\n moved.push({ ...body, mutationId: to });\n }\n const intent = {\n clientId,\n staleIds: [...plan.result.dropped, ...plan.result.renumbered.map((r) => r.from)],\n moved,\n index: plan.journal,\n counter: plan.counter,\n };\n // Armed before the write: if the write lands but reports failure,\n // the next operation still looks for (and finishes) the intent.\n compactionPending = true;\n // A write that errors may still have landed (an ambiguous IndexedDB\n // abort): look for the intent before calling the compaction failed.\n // Present means committed, so proceed as if the write had succeeded.\n yield* writeJson(COMPACTION_KEY, intent).pipe(\n Effect.catch((error) =>\n readDecoded(COMPACTION_KEY, CompactionIntentFromJson).pipe(\n Effect.catchTag(\"StoreError\", () => Effect.succeed(undefined)),\n Effect.flatMap((found) =>\n found === undefined ? Effect.fail(error) : Effect.void\n )\n )\n )\n );\n yield* applyCompaction(intent).pipe(\n Effect.tap(() =>\n Effect.sync(() => {\n compactionPending = false;\n })\n ),\n // The compaction is committed; the roll-forward finishes it.\n // Not silent: a store that keeps failing here will keep failing\n // the next journal operation, and this is the first sign.\n Effect.catch((error) =>\n Effect.logWarning(\n \"ClientStore: compaction committed but not yet applied; will roll forward\",\n { error }\n )\n )\n );\n return plan.result;\n })\n )\n ),\n markSent: (clientId, upTo) =>\n locked(\n Effect.gen(function* () {\n const marks = yield* sentMarks;\n if ((marks[clientId] ?? 0) >= upTo) return;\n yield* writeJson(SENT_KEY, { ...marks, [clientId]: upTo });\n })\n ),\n nextMutationId: (clientId) =>\n locked(\n Effect.gen(function* () {\n yield* settleCompaction;\n const counters = (yield* readDecoded(\"counters\", CountersFromJson)) ?? {};\n // Heal from the live journal, as `appendNext` does, so a counter\n // write that was swallowed cannot hand out an id a live entry holds.\n let last = counters[clientId] ?? 0;\n for (const entry of yield* journalIndex) {\n if (entry.clientId === clientId && entry.mutationId > last) last = entry.mutationId;\n }\n const next = last + 1;\n yield* writeJson(\"counters\", { ...counters, [clientId]: next });\n return next;\n })\n ),\n // Settled first, so a compaction's rewound counter is what is read or raised.\n mutationCounters: locked(\n settleCompaction.pipe(\n Effect.andThen(readDecoded(\"counters\", CountersFromJson)),\n Effect.map((counters) => counters ?? {})\n )\n ),\n raiseMutationCounters: (raise) =>\n locked(\n Effect.gen(function* () {\n yield* settleCompaction;\n const counters = (yield* readDecoded(\"counters\", CountersFromJson)) ?? {};\n const raised = raisedCounters(counters, raise);\n if (raised !== undefined) yield* writeJson(\"counters\", raised);\n })\n ),\n\n unpulled: unsealed(unpulledOf),\n parkUnpulled: (mutations) => locked(parkUnpulledInner(mutations)),\n // An outstanding record is finished before this one is written (#387). If that finish fails, this\n // call fails and the record stays for the next call to finish; a failure after its read seals.\n beginRelease: (release) =>\n locked(\n // Set before the record is read or written, since a write that reports failure may still have landed.\n Ref.set(finishPending, true).pipe(\n Effect.andThen(readDecoded(RELEASE_KEY, ReleaseIntentFromJson)),\n Effect.flatMap((pending) =>\n pending === undefined ? Effect.void : finishRead(pending)\n ),\n // The finish clears the flag, and the record written below must set it again.\n Effect.andThen(Ref.set(finishPending, true)),\n Effect.andThen(writeJson(RELEASE_KEY, release))\n )\n ),\n releaseUnpulled: (lastMutationIds) => locked(releaseUnpulledInner(lastMutationIds)),\n finishRelease: locked(finishOrSeal),\n clearUnpulled: locked(clearUnpulledInner),\n\n getCookie: unsealed(\n store.get(\"cookie\").pipe(Effect.mapError(storeError(`Failed to read \"cookie\"`)))\n ),\n setCookie: (value) =>\n locked(\n store.set(\"cookie\", value).pipe(Effect.mapError(storeError(`Failed to write \"cookie\"`)))\n ),\n clearCookie: locked(remove(\"cookie\")),\n\n getIdentity: unsealed(\n store\n .get(IDENTITY_KEY)\n .pipe(Effect.mapError(storeError(`Failed to read \"${IDENTITY_KEY}\"`)))\n ),\n setIdentity: (fingerprint) =>\n locked(\n store\n .set(IDENTITY_KEY, fingerprint)\n .pipe(Effect.mapError(storeError(`Failed to write \"${IDENTITY_KEY}\"`)))\n ),\n\n quarantinePending: (fingerprint) =>\n locked(settleCompaction.pipe(Effect.andThen(quarantinePendingInner(fingerprint)))),\n quarantinedMutations: (fingerprint) => unsealed(quarantinedOf(fingerprint)),\n quarantines: unsealed(quarantineIndexOf),\n releaseQuarantine: (fingerprint) =>\n locked(settleCompaction.pipe(Effect.andThen(releaseQuarantineInner(fingerprint)))),\n discardQuarantine: (fingerprint) => locked(discardQuarantineInner(fingerprint)),\n });\n });\n\n/** Layer providing the KeyValueStore-backed store. */\nexport const layerKeyValue = (\n options?: KeyValueOptions\n): Layer.Layer<ClientStore, never, KeyValueStore.KeyValueStore> =>\n Layer.effect(ClientStore)(makeKeyValue(options));\n","/**\n * Hash\n *\n * A stable, order-independent content hash, used as a row version when a\n * backend exposes no native version token (CONTEXT.md: row version). The hash\n * changes iff the canonical value changes — exactly what CVR diffing needs —\n * so adapters that sync plain values (the JSON:API and SQL reference backends)\n * share one implementation here rather than each rolling their own.\n */\n\nimport * as P from \"effect/Predicate\";\n\nconst canonical = (value: unknown): string => {\n if (!P.isObjectOrArray(value)) return JSON.stringify(value) ?? \"null\";\n if (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n const record = value as Record<string, unknown>;\n return `{${Object.keys(record)\n .toSorted()\n .map((key) => `${JSON.stringify(key)}:${canonical(record[key])}`)\n .join(\",\")}}`;\n};\n\n/**\n * A canonical, key-order-insensitive JSON serialisation: two structurally\n * equal values always produce the same string, whatever the order their keys\n * were written in. The correct basis for cache/subscription keys derived from\n * args objects (where `JSON.stringify` would key on insertion order and split\n * one logical subscription across two entries).\n */\nexport const canonicalJson = (value: unknown): string => canonical(value);\n\n/** A content-hash row version (FNV-1a over the canonical value). */\nexport const contentHash = (value: unknown): string => {\n const text = canonical(value);\n let hash = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(16);\n};\n","/**\n * FractionalIndex\n *\n * Stable position keys for in-window rows (issue #112): a string that sorts\n * between any two others, so a row entering, leaving, or moving within a\n * maintained window can be given a key without renumbering its neighbors —\n * the primitive behind expressing a delta as `{ type: \"move\", key, position\n * }` instead of diffing pages (a future row-level delta feed's concern;\n * `LiveView` only assigns and maintains the keys today).\n *\n * Each key is a base-62 digit string (`0-9A-Za-z`, chosen so ASCII order\n * already matches digit order) read as a fraction in `[0, 1)`:\n * `digits[0] * 62⁻¹ + digits[1] * 62⁻² + …`. Keys compare by that *value*,\n * not raw string order — `compare` zero-pads the shorter key first, so e.g.\n * `\"5\"` and `\"50\"` (both 5/62) compare equal. This is what keeps\n * `generateBetween` total: two real numbers always have a value strictly\n * between them, so — unlike schemes that compare the raw strings\n * lexicographically (where, say, nothing sorts between `\"A\"` and `\"A0\"`,\n * since any extension of `\"A\"` is lexicographically ≥ `\"A0\"`) — there is no\n * pair of distinct keys this can fail to split.\n *\n * Repeatedly inserting at the same boundary (e.g. always \"before the\n * current first row\") grows key length by roughly one digit every ~5-6\n * insertions at that boundary (`log_2(62)`) — the standard, accepted cost of\n * any fractional-indexing scheme (TanStack DB's `generateKeyBetween`,\n * Figma's original algorithm) and not specific to this implementation.\n */\n\nconst DIGITS = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\nconst BASE = DIGITS.length;\nconst ZERO = DIGITS.charAt(0);\n\nconst digitValue = (char: string): number => DIGITS.indexOf(char);\nconst digitChar = (value: number): string => DIGITS.charAt(value);\n\n/** The digit of `key` at position `i`; a position past its end reads as 0. */\nconst digitAt = (key: string, i: number): number =>\n i < key.length ? digitValue(key.charAt(i)) : 0;\n\n/**\n * Compare two keys by the fraction they encode (zero-padding the shorter\n * one), not by raw string order — see the module doc for why that matters.\n */\nexport const compare = (a: string, b: string): number => {\n const length = Math.max(a.length, b.length);\n const pa = a.padEnd(length, ZERO);\n const pb = b.padEnd(length, ZERO);\n return pa < pb ? -1 : pa > pb ? 1 : 0;\n};\n\n/**\n * A key whose value lies strictly between `lo` and `hi` (each defaulting to\n * the open bound: `lo` omitted means 0, `hi` omitted means unbounded above).\n * Throws if `lo` is not strictly before `hi`.\n */\nexport const generateBetween = (lo?: string, hi?: string): string => {\n if (lo !== undefined && hi !== undefined && compare(lo, hi) >= 0) {\n throw new Error(\n `FractionalIndex.generateBetween: lo (${JSON.stringify(lo)}) must sort before hi (${JSON.stringify(hi)})`\n );\n }\n const digits: Array<number> = [];\n let unbounded = hi === undefined;\n for (let i = 0; ; i++) {\n const loDigit = lo === undefined ? 0 : digitAt(lo, i);\n const hiDigit = unbounded || hi === undefined ? BASE : digitAt(hi, i);\n const gap = hiDigit - loDigit;\n if (gap >= 2) {\n digits.push(loDigit + Math.floor(gap / 2));\n return digits.map(digitChar).join(\"\");\n }\n digits.push(loDigit);\n if (gap === 1) unbounded = true; // this digit already sorts below hi; no bound below it\n }\n};\n\n/**\n * `count` keys, all strictly between `lo` and `hi` and strictly increasing —\n * built by recursively bisecting the interval so the keys stay close in\n * length (O(log count) longer than a single `generateBetween`) rather than\n * chaining `generateBetween(lo, hi)` calls, which would grow the last key\n * by one digit per call.\n */\nexport const generateNBetween = (\n lo: string | undefined,\n hi: string | undefined,\n count: number\n): ReadonlyArray<string> => {\n if (count <= 0) return [];\n if (count === 1) return [generateBetween(lo, hi)];\n const mid = generateBetween(lo, hi);\n const left = Math.floor(count / 2);\n return [...generateNBetween(lo, mid, left), mid, ...generateNBetween(mid, hi, count - left - 1)];\n};\n","/**\n * OrderedTree\n *\n * A persistent (path-copying) weight-balanced binary search tree keyed by a\n * caller-supplied total order (bounded-balance / \"BB[α]\" trees, Adams 1992 —\n * the algorithm behind Haskell's `Data.Set`/`Data.Map`). Every mutation\n * returns a new tree sharing everything off the changed path, so an\n * insert/remove is *O(log n)* node allocations rather than an *O(n)* array\n * copy. Each node also carries its subtree size, so a value's 0-based rank\n * (and the reverse: the value at a given rank) resolve in *O(log n)*, and a\n * `count`-bounded slice starting at a rank costs *O(log n + count)* — this is\n * what lets `LiveView` reslice its window without rescanning the whole\n * maintained order (issue #112).\n *\n * Weight-balance (rather than a randomized treap) makes bulk construction\n * from an already-sorted array linear and deterministic: `fromSorted`\n * recursively roots each half at its middle element, which is already\n * within the balance bound, so no rotation is needed on the way up.\n *\n * Generic over the element type; the caller's `compare` must be a strict\n * total order (no ties) for `rankOf`/`remove` to behave — `LiveView` gets\n * this from `Subset.comparator`'s id tie-break.\n */\n\nimport * as Arr from \"effect/Array\";\n\ninterface Node<T> {\n readonly value: T;\n readonly left: Node<T> | undefined;\n readonly right: Node<T> | undefined;\n readonly size: number;\n}\n\n/** An immutable ordered tree; `undefined` is the empty tree. */\nexport type Tree<T> = Node<T> | undefined;\n\n/** Number of elements in the tree, O(1). */\nexport const size = <T>(tree: Tree<T>): number => tree?.size ?? 0;\n\nconst sizeOf = <T>(tree: Tree<T>): number => tree?.size ?? 0;\n\nconst node = <T>(left: Tree<T>, value: T, right: Tree<T>): Node<T> => ({\n value,\n left,\n right,\n size: sizeOf(left) + sizeOf(right) + 1,\n});\n\n// Bounded-balance factors (Adams 1992 / containers library defaults): a\n// subtree may outweigh its sibling by at most `delta`; a rotation chooses\n// single vs double based on whether the heavy child's own bias exceeds\n// `ratio`.\nconst DELTA = 3;\nconst RATIO = 2;\n\nconst rotateSingleLeft = <T>(left: Tree<T>, value: T, right: Node<T>): Node<T> =>\n node(node(left, value, right.left), right.value, right.right);\n\nconst rotateDoubleLeft = <T>(left: Tree<T>, value: T, right: Node<T>): Node<T> => {\n const rl = right.left as Node<T>; // right is heavier than left, so right.left exists\n return node(node(left, value, rl.left), rl.value, node(rl.right, right.value, right.right));\n};\n\nconst rotateSingleRight = <T>(left: Node<T>, value: T, right: Tree<T>): Node<T> =>\n node(left.left, left.value, node(left.right, value, right));\n\nconst rotateDoubleRight = <T>(left: Node<T>, value: T, right: Tree<T>): Node<T> => {\n const lr = left.right as Node<T>;\n return node(node(left.left, left.value, lr.left), lr.value, node(lr.right, value, right));\n};\n\n/** Re-balance a node whose children may be off by one insert/remove. */\nconst balance = <T>(left: Tree<T>, value: T, right: Tree<T>): Node<T> => {\n const ls = sizeOf(left);\n const rs = sizeOf(right);\n if (ls + rs <= 1) return node(left, value, right);\n if (rs > DELTA * ls) {\n const r = right as Node<T>;\n return sizeOf(r.left) < RATIO * sizeOf(r.right)\n ? rotateSingleLeft(left, value, r)\n : rotateDoubleLeft(left, value, r);\n }\n if (ls > DELTA * rs) {\n const l = left as Node<T>;\n return sizeOf(l.right) < RATIO * sizeOf(l.left)\n ? rotateSingleRight(l, value, right)\n : rotateDoubleRight(l, value, right);\n }\n return node(left, value, right);\n};\n\n/** Insert (or, if `compare` finds an exact match, replace) a value. O(log n). */\nexport const insert = <T>(tree: Tree<T>, value: T, compare: (a: T, b: T) => number): Tree<T> => {\n if (tree === undefined) return node(undefined, value, undefined);\n const ordered = compare(value, tree.value);\n if (ordered < 0) return balance(insert(tree.left, value, compare), tree.value, tree.right);\n if (ordered > 0) return balance(tree.left, tree.value, insert(tree.right, value, compare));\n return node(tree.left, value, tree.right);\n};\n\n/** The maximum value of a non-empty tree, paired with the tree minus it. */\nconst withoutMax = <T>(tree: Node<T>): { readonly rest: Tree<T>; readonly max: T } => {\n if (tree.right === undefined) return { rest: tree.left, max: tree.value };\n const { rest, max } = withoutMax(tree.right);\n return { rest: balance(tree.left, tree.value, rest), max };\n};\n\n/** The minimum value of a non-empty tree, paired with the tree minus it. */\nconst withoutMin = <T>(tree: Node<T>): { readonly rest: Tree<T>; readonly min: T } => {\n if (tree.left === undefined) return { rest: tree.right, min: tree.value };\n const { rest, min } = withoutMin(tree.left);\n return { rest: balance(rest, tree.value, tree.right), min };\n};\n\n/** Join two trees known to be entirely left-of / right-of each other. */\nconst glue = <T>(left: Tree<T>, right: Tree<T>): Tree<T> => {\n if (left === undefined) return right;\n if (right === undefined) return left;\n if (sizeOf(left) > sizeOf(right)) {\n const { rest, max } = withoutMax(left);\n return balance(rest, max, right);\n }\n const { rest, min } = withoutMin(right);\n return balance(left, min, rest);\n};\n\n/** Remove the value matching `compare`, if present. O(log n); a no-op returns the same reference. */\nexport const remove = <T>(tree: Tree<T>, value: T, compare: (a: T, b: T) => number): Tree<T> => {\n if (tree === undefined) return tree;\n const ordered = compare(value, tree.value);\n if (ordered < 0) {\n const left = remove(tree.left, value, compare);\n return left === tree.left ? tree : balance(left, tree.value, tree.right);\n }\n if (ordered > 0) {\n const right = remove(tree.right, value, compare);\n return right === tree.right ? tree : balance(tree.left, tree.value, right);\n }\n return glue(tree.left, tree.right);\n};\n\n/**\n * The value whose key matches `key` per `compare` (negative when `key`\n * belongs left of a node's value, positive when right, zero on a match), or\n * `undefined` if absent. O(log n) — a plain BST point lookup, independent of\n * rank, so a second tree can index the same elements by an unrelated key\n * (`LiveView`'s `byId` alongside its value-ordered `order`) just as cheaply\n * as a `Map`, but without a `Map`'s O(n) `new Map(bigMap)` copy on \"update\n * one entry, keep the rest\" (path-copying only touches O(log n) nodes).\n */\nexport const findBy = <T, K>(\n tree: Tree<T>,\n key: K,\n compare: (key: K, value: T) => number\n): T | undefined => {\n let cursor = tree;\n while (cursor !== undefined) {\n const ordered = compare(key, cursor.value);\n if (ordered < 0) cursor = cursor.left;\n else if (ordered > 0) cursor = cursor.right;\n else return cursor.value;\n }\n return undefined;\n};\n\n/**\n * The 0-based rank of the value matching `compare`, or `-1` if absent.\n * O(log n).\n */\nexport const rankOf = <T>(tree: Tree<T>, value: T, compare: (a: T, b: T) => number): number => {\n let cursor = tree;\n let rank = 0;\n while (cursor !== undefined) {\n const ordered = compare(value, cursor.value);\n if (ordered < 0) {\n cursor = cursor.left;\n } else if (ordered > 0) {\n rank += sizeOf(cursor.left) + 1;\n cursor = cursor.right;\n } else {\n return rank + sizeOf(cursor.left);\n }\n }\n return -1;\n};\n\n/** The value at 0-based rank `index`, or `undefined` if out of bounds. O(log n). */\nexport const at = <T>(tree: Tree<T>, index: number): T | undefined => {\n let cursor = tree;\n let remaining = index;\n while (cursor !== undefined) {\n const leftSize = sizeOf(cursor.left);\n if (remaining < leftSize) cursor = cursor.left;\n else if (remaining === leftSize) return cursor.value;\n else {\n remaining -= leftSize + 1;\n cursor = cursor.right;\n }\n }\n return undefined;\n};\n\n/**\n * In-order values starting at 0-based rank `from`, one at a time — descending\n * to the start rank costs O(log n), and each subsequent value is amortized\n * O(1), so consuming `count` of them (via `slice`) is O(log n + count).\n */\nfunction* inorderFrom<T>(tree: Tree<T>, from: number): IterableIterator<T> {\n const stack: Array<Node<T>> = [];\n let cursor = tree;\n let remaining = from;\n while (cursor !== undefined) {\n const leftSize = sizeOf(cursor.left);\n if (remaining < leftSize) {\n stack.push(cursor);\n cursor = cursor.left;\n } else if (remaining === leftSize) {\n stack.push(cursor);\n break;\n } else {\n remaining -= leftSize + 1;\n cursor = cursor.right;\n }\n }\n while (Arr.isReadonlyArrayNonEmpty(stack)) {\n const top = stack.pop();\n if (top === undefined) break;\n yield top.value;\n let right = top.right;\n while (right !== undefined) {\n stack.push(right);\n right = right.left;\n }\n }\n}\n\n/** Up to `count` in-order values starting at 0-based rank `from`. O(log n + count). */\nexport const slice = <T>(tree: Tree<T>, from: number, count: number): ReadonlyArray<T> => {\n if (count <= 0 || from >= sizeOf(tree)) return [];\n const out: Array<T> = [];\n for (const value of inorderFrom(tree, Math.max(from, 0))) {\n if (out.length >= count) break;\n out.push(value);\n }\n return out;\n};\n\n/** Every value, in order. O(n) — the reference/full-materialization path. */\nexport const toArray = <T>(tree: Tree<T>): ReadonlyArray<T> => slice(tree, 0, sizeOf(tree));\n\n/**\n * Build a tree from an array already sorted per `compare`. O(n): each half\n * roots at its middle element, which is already within the balance bound\n * (`|leftSize - rightSize| <= 1`), so `fromSorted` never rotates.\n */\nexport const fromSorted = <T>(sorted: ReadonlyArray<T>): Tree<T> => {\n const build = (lo: number, hi: number): Tree<T> => {\n if (lo >= hi) return undefined;\n const mid = (lo + hi) >>> 1;\n return node(build(lo, mid), Arr.getUnsafe(sorted, mid), build(mid + 1, hi));\n };\n return build(0, sorted.length);\n};\n","/**\n * LiveView\n *\n * A modular, incrementally-maintained materialized view: a subset's result\n * (filtered, sorted, windowed) kept current by row deltas instead of\n * re-scanning the collection. This is the caching/live-view primitive behind\n * paginated live queries, and the window is sliced from the maintained order,\n * so a change outside the page never re-sorts it.\n *\n * The maintained order lives in an {@link OrderedTree} (issue #112), not a\n * copied array: `Subset.comparator`'s id tie-break makes every row's sort key\n * distinct, so locating the row a `put`/`del` touches is genuinely *O(log\n * n)* — including for an empty `orderBy`, where every row used to tie and\n * `indexOf` degraded to a full scan. The tree's own insert/remove are\n * *O(log n)* node allocations (path-copying, not an array rebuild), and\n * `result` reslices the window from it in *O(log n + window)* — so a change\n * outside the visible page costs the same as one inside it: locate, no\n * rebuild. The id index (`byId`) is a *second* tree, ordered by id instead of\n * by the subset's comparator: an absent id is an O(log n) no-op, and —\n * unlike a `Map`, whose `new Map(bigMap)` is O(n) — updating one entry never\n * touches the rest, which is what keeps a genuine-change `put`/`del` at\n * O(log n) instead of silently degrading to O(n) on a large collection.\n *\n * The view holds the *full* filtered + sorted matching set so the window\n * stays correct across the limit boundary (an insert can push a row out of\n * the page; a delete can pull the next one in) and so `retarget` can widen\n * or advance the window over the *same* maintained order — no\n * re-materialization, the TanStack-DB-style `setWindowFn` analogue for\n * `Subset`'s cursor/limit widening (`useConnection`'s \"load more\"). It is\n * pure data: every update returns a new view (or the same reference when\n * nothing changed), composing cleanly with an `Effect` `Stream`.\n *\n * In-window rows carry a stable {@link FractionalIndex} `position`: assigned\n * when a row enters the window, dropped when it leaves, and left untouched\n * when neither the row nor its immediate neighbors moved — so a downstream\n * delta consumer (`RowChange.diff`, driving `ClientEngine.observeChanges`)\n * can tell \"entered\"/\"left\"/\"moved\" apart without diffing pages, the way\n * TanStack DB's `topKWithFractionalIndex` does for its own maintained window.\n */\n\nimport type * as Index from \"./CollectionIndex.js\";\nimport * as FractionalIndex from \"./FractionalIndex.js\";\nimport * as OrderedTree from \"./OrderedTree.js\";\nimport * as Predicate from \"./Predicate.js\";\nimport * as Subset from \"./Subset.js\";\n\n/** A materialized `(id, value)` row, as a subset produces it. */\nexport type Row = Subset.Row;\n\n/** A {@link Row} carrying its stable in-window position (see the module doc). */\nexport interface PositionedRow extends Row {\n readonly position: string;\n}\n\n/**\n * One subset's incrementally maintained window: the matching rows in subset order, plus an id\n * index over the same rows.\n */\nexport interface LiveView {\n readonly subset: Subset.Subset;\n /** The full filtered + sorted matching set, maintained as an ordered tree. */\n readonly order: OrderedTree.Tree<Row>;\n /**\n * The same rows, maintained as a second tree ordered by id — an id index\n * that supports an O(log n) presence check and O(log n) update, unlike a\n * `Map` (see the module doc for why that distinction matters here).\n */\n readonly byId: OrderedTree.Tree<Row>;\n /** id → stable position, for rows currently inside the window only. */\n readonly positions: ReadonlyMap<string, string>;\n}\n\n// Ids order by code point, the same order `Subset.comparator`'s tie-break uses (ADR-0028).\nconst byIdCompare = (a: Row, b: Row): number => Predicate.compareText(a.id, b.id);\nconst findById = (byId: OrderedTree.Tree<Row>, id: string): Row | undefined =>\n OrderedTree.findBy(byId, id, (key, row) => Predicate.compareText(key, row.id));\n\nconst compareOf = (subset: Subset.Subset) => Subset.comparator(subset.orderBy);\n\n/** The window's start rank (0 if no cursor, or the row after it) and length. */\nconst windowSlice = (\n order: OrderedTree.Tree<Row>,\n byId: OrderedTree.Tree<Row>,\n subset: Subset.Subset\n): ReadonlyArray<Row> => {\n let from = 0;\n if (subset.cursor !== undefined) {\n const cursorRow = findById(byId, subset.cursor);\n if (cursorRow !== undefined) {\n const rank = OrderedTree.rankOf(order, cursorRow, compareOf(subset));\n from = rank < 0 ? 0 : rank + 1;\n }\n }\n const count = subset.limit === undefined ? OrderedTree.size(order) - from : subset.limit;\n return OrderedTree.slice(order, from, Math.max(count, 0));\n};\n\n/**\n * Whether row `i`'s previous position is still ordered correctly against its\n * *previous* immediate neighbors — cheap to check, and exactly the \"row\n * didn't move relative to what's next to it\" condition that lets a position\n * survive unchanged.\n */\nconst stillOrdered = (\n windowRows: ReadonlyArray<Row>,\n previous: ReadonlyMap<string, string>,\n i: number,\n position: string\n): boolean => {\n const left = windowRows[i - 1];\n const right = windowRows[i + 1];\n const leftPrev = left === undefined ? undefined : previous.get(left.id);\n const rightPrev = right === undefined ? undefined : previous.get(right.id);\n const okLeft = leftPrev === undefined || FractionalIndex.compare(leftPrev, position) < 0;\n const okRight = rightPrev === undefined || FractionalIndex.compare(position, rightPrev) < 0;\n return okLeft && okRight;\n};\n\n/** Each window row's reusable previous position, or `undefined` where a fresh one is needed. */\nconst reusablePositions = (\n windowRows: ReadonlyArray<Row>,\n previous: ReadonlyMap<string, string>\n): ReadonlyArray<string | undefined> =>\n windowRows.map((row, i) => {\n const existing = previous.get(row.id);\n return existing !== undefined && stillOrdered(windowRows, previous, i, existing)\n ? existing\n : undefined;\n });\n\n/** Fill every gap between reused positions with a fresh, evenly-spaced batch. */\nconst fillGaps = (\n windowRows: ReadonlyArray<Row>,\n reused: ReadonlyArray<string | undefined>\n): ReadonlyMap<string, string> => {\n const n = windowRows.length;\n const next = new Map<string, string>();\n let left: string | undefined;\n let i = 0;\n while (i < n) {\n const kept = reused[i];\n if (kept !== undefined) {\n const row = windowRows[i];\n if (row !== undefined) next.set(row.id, kept);\n left = kept;\n i++;\n continue;\n }\n let j = i;\n while (j < n && reused[j] === undefined) j++;\n const right = j < n ? reused[j] : undefined;\n const fresh = FractionalIndex.generateNBetween(left, right, j - i);\n fresh.forEach((position, offset) => {\n const row = windowRows[i + offset];\n if (row !== undefined) next.set(row.id, position);\n });\n left = right;\n i = j;\n }\n return next;\n};\n\n/**\n * Assign positions to a freshly-computed window, reusing a row's previous\n * position whenever it is still ordered correctly against its previous\n * neighbors — everything else (freshly entered rows, and runs of rows whose\n * old position no longer fits) gets a batch of fresh keys spanning the gap\n * between the nearest reused neighbors, via\n * {@link FractionalIndex.generateNBetween}. O(window).\n */\nconst positionsFor = (\n windowRows: ReadonlyArray<Row>,\n previous: ReadonlyMap<string, string>\n): ReadonlyMap<string, string> => fillGaps(windowRows, reusablePositions(windowRows, previous));\n\n/** Build a view from an unordered collection snapshot. */\nexport const make = (subset: Subset.Subset, rows: ReadonlyArray<Row>): LiveView => {\n const sorted = Subset.sortFiltered(rows, subset);\n const order = OrderedTree.fromSorted(sorted);\n const byId = OrderedTree.fromSorted(sorted.toSorted(byIdCompare));\n const positions = positionsFor(windowSlice(order, byId, subset), new Map());\n return { subset, order, byId, positions };\n};\n\n/**\n * {@link make}, but reading rows from an id-keyed map with optional secondary-index\n * acceleration (issue #113) — the collection-scale rebuild path (`Rebuild`\n * view changes, a change-hub seq-gap collapse) shares the same narrowing as\n * one-shot `query`.\n */\nexport const makeIndexed = (\n subset: Subset.Subset,\n rowsById: ReadonlyMap<string, Row>,\n index?: Index.CollectionIndex\n): LiveView => {\n const sorted = Subset.sortFilteredIndexed(rowsById, subset, index);\n const order = OrderedTree.fromSorted(sorted);\n const byId = OrderedTree.fromSorted(sorted.toSorted(byIdCompare));\n const positions = positionsFor(windowSlice(order, byId, subset), new Map());\n return { subset, order, byId, positions };\n};\n\n/** The visible page: the subset's cursor + limit over the maintained order. */\nexport const result = (view: LiveView): ReadonlyArray<PositionedRow> =>\n windowSlice(view.order, view.byId, view.subset).flatMap((row): ReadonlyArray<PositionedRow> => {\n const position = view.positions.get(row.id);\n return position === undefined ? [] : [{ id: row.id, value: row.value, position }];\n });\n\n/**\n * Retarget the window — a new `limit` and/or `cursor`, e.g. \"load more\"\n * widening the page — without touching the maintained order: no re-fetch, no\n * re-sort, just a new O(log n + window) slice of the same tree.\n * `collection`/`where`/`orderBy` stay the view's own; only `limit`/`cursor`\n * move, matching `useConnection`'s \"load more widens one window\" (ADR-0024)\n * — the pure, comparator-shaped half of \"widen\"; the engine-level API that\n * reactively feeds a widened `limit` to an open subscription (so the client\n * never re-registers it) is `ClientEngine.observeWindow` (#133).\n * Same-reference-on-no-op: returns `view` unchanged if neither `limit` nor\n * `cursor` moved.\n */\nexport const retarget = (\n view: LiveView,\n window: { readonly limit?: number; readonly cursor?: string }\n): LiveView => {\n const limit = window.limit !== undefined ? window.limit : view.subset.limit;\n const cursor = window.cursor !== undefined ? window.cursor : view.subset.cursor;\n if (limit === view.subset.limit && cursor === view.subset.cursor) return view;\n const subset: Subset.Subset = {\n ...view.subset,\n ...(limit !== undefined ? { limit } : {}),\n ...(cursor !== undefined ? { cursor } : {}),\n };\n const positions = positionsFor(windowSlice(view.order, view.byId, subset), view.positions);\n return { ...view, subset, positions };\n};\n\n/**\n * Apply a row upsert: place it at its sorted position if it matches the\n * predicate, or remove it if it no longer does. Returns the same view\n * reference when the row neither matched before nor matches now (an O(log n)\n * `byId` check).\n */\nexport const put = (view: LiveView, row: Row): LiveView => {\n const matches = Predicate.test(view.subset.where, row.value);\n const existing = findById(view.byId, row.id);\n if (!matches && existing === undefined) return view;\n const compare = compareOf(view.subset);\n const withoutOld =\n existing === undefined ? view.order : OrderedTree.remove(view.order, existing, compare);\n if (!matches) {\n const byId = OrderedTree.remove(view.byId, row, byIdCompare);\n const positions = positionsFor(windowSlice(withoutOld, byId, view.subset), view.positions);\n return { ...view, order: withoutOld, byId, positions };\n }\n const byId = OrderedTree.insert(view.byId, row, byIdCompare);\n const order = OrderedTree.insert(withoutOld, row, compare);\n const positions = positionsFor(windowSlice(order, byId, view.subset), view.positions);\n return { ...view, order, byId, positions };\n};\n\n/** Apply a row deletion. Returns the same view reference if the id is absent. */\nexport const del = (view: LiveView, id: string): LiveView => {\n const existing = findById(view.byId, id);\n if (existing === undefined) return view;\n const order = OrderedTree.remove(view.order, existing, compareOf(view.subset));\n const byId = OrderedTree.remove(view.byId, existing, byIdCompare);\n const positions = positionsFor(windowSlice(order, byId, view.subset), view.positions);\n return { ...view, order, byId, positions };\n};\n","/**\n * MutationState\n *\n * A keyed, reactive mutation-state map (#116): the per-mutation lifecycle\n * `ClientEngine.mutationEvents` already streams, folded into a map anyone can\n * read as of now (`ClientEngine.mutationStates`) — TanStack Query's\n * `useMutationState` analogue. Seeded from the journal at boot (so a reload\n * shows pending intents), then folded forward as mutations are journaled,\n * acknowledged, and permanently rejected.\n *\n * The journal (`ClientStore.pendingMutations`) stays the durable source of\n * truth for *pending* mutations — this map never drops a pending entry.\n * Terminal entries (acknowledged/rejected) exist only for observability (a\n * success/failure toast, a \"recently synced\" indicator), so they are retained\n * up to a configurable bound and evicted oldest-settled-first beyond it —\n * bounded memory under a mutation storm without a background sweep.\n *\n * Backed by `HashMap` (structural sharing), not the native `Map`: `journal()`\n * folds one entry in on every mutation (ADR/#109's own hot path), so an\n * `O(size)` copy per fold would make a burst of N mutations cost `O(N^2)` —\n * exactly the class of regression #109 eliminated for the overlay. `HashMap`\n * keeps every fold `O(log N)` regardless of how many mutations are pending.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Option from \"effect/Option\";\nimport type { Mutation } from \"./Protocol.js\";\n\n/** Where a journaled mutation is in its lifecycle. */\nexport type MutationPhase = \"pending\" | \"acknowledged\" | \"rejected\" | \"dropped\";\n\n/**\n * One mutation's lifecycle state, keyed by `mutationId` in {@link\n * MutationStateMap}. `args` is the journal's encoded (wire/persistence) form,\n * so the whole shape is serializable — devtools-timeline ready.\n */\nexport interface MutationState {\n readonly mutationId: number;\n readonly mutator: string;\n readonly args: unknown;\n readonly phase: MutationPhase;\n /** Set only when `phase` is `\"rejected\"`: the backend's permanent-rejection reason. */\n readonly reason?: string;\n /** Client wall-clock when the mutation was journaled. */\n readonly journaledAt: number;\n /** Client wall-clock when the mutation left `\"pending\"`; unset while pending. */\n readonly settledAt?: number;\n}\n\n/** Every tracked mutation's {@link MutationState}, keyed by `mutationId`. */\nexport type MutationStateMap = HashMap.HashMap<number, MutationState>;\n\n/** How many settled entries a {@link MutationStateMap} keeps. */\nexport interface RetentionOptions {\n /**\n * Maximum terminal (acknowledged/rejected) entries retained; the\n * oldest-settled are evicted first once exceeded. Pending entries are never\n * evicted — they leave the map only by settling. Defaults to\n * {@link DEFAULT_MAX_TERMINAL}.\n */\n readonly maxTerminal?: number;\n}\n\n/**\n * Default terminal retention: generous enough that a normal session never\n * trims a state the UI still cares about, small enough to bound a storm.\n */\nexport const DEFAULT_MAX_TERMINAL = 200;\n\n/** Seed the map from the journal at boot: every pending mutation starts `\"pending\"`. */\nexport const seed = (pending: ReadonlyArray<Mutation>): MutationStateMap =>\n HashMap.fromIterable(\n pending.map((mutation): readonly [number, MutationState] => [\n mutation.mutationId,\n {\n mutationId: mutation.mutationId,\n mutator: mutation.mutator,\n args: mutation.args,\n phase: \"pending\",\n journaledAt: mutation.createdAt,\n },\n ])\n );\n\n/** Whether any of `pending` is not tracked by the map, so {@link adopt} would change it (#358). */\nexport const hasUntracked = (map: MutationStateMap, pending: ReadonlyArray<Mutation>): boolean =>\n pending.some((mutation) => !HashMap.has(map, mutation.mutationId));\n\n/**\n * Track the journal entries the map does not know yet as `\"pending\"` (#358): the entries a direct\n * store write (`Hydration.hydrate`) appended under a running engine, which never went through\n * `journaled`. An entry the map already tracks keeps its phase, whatever the journal says, so a\n * settled entry is never reset to pending. Returns the entries it adopted, in journal order, so\n * the caller can announce each one exactly once.\n */\nexport const adopt = (\n map: MutationStateMap,\n pending: ReadonlyArray<Mutation>\n): readonly [adopted: ReadonlyArray<Mutation>, map: MutationStateMap] => {\n let next = map;\n const adopted: Array<Mutation> = [];\n Arr.forEach(pending, (mutation) => {\n if (HashMap.has(next, mutation.mutationId)) return;\n next = journaled(next, {\n mutationId: mutation.mutationId,\n mutator: mutation.mutator,\n args: mutation.args,\n journaledAt: mutation.createdAt,\n });\n adopted.push(mutation);\n });\n return [adopted, next];\n};\n\n/** Fold a freshly-journaled mutation in as `\"pending\"`. */\nexport const journaled = (\n map: MutationStateMap,\n entry: {\n readonly mutationId: number;\n readonly mutator: string;\n readonly args: unknown;\n readonly journaledAt: number;\n }\n): MutationStateMap =>\n HashMap.set(map, entry.mutationId, {\n mutationId: entry.mutationId,\n mutator: entry.mutator,\n args: entry.args,\n phase: \"pending\",\n journaledAt: entry.journaledAt,\n });\n\n/**\n * Drop the oldest-settled terminal entries beyond `maxTerminal` (#116) — the\n * bound that keeps the map from growing without limit across a mutation\n * storm. Pending entries are never touched. `O(size)`: scans every entry to\n * find the terminal ones, so callers settling many mutations at once (a push\n * ack sweep) should fold every transition first and evict once — see\n * {@link acknowledgedMany} — rather than evicting after each one.\n */\nconst evictTerminal = (\n map: MutationStateMap,\n options: RetentionOptions | undefined\n): MutationStateMap => {\n const maxTerminal = options?.maxTerminal ?? DEFAULT_MAX_TERMINAL;\n const terminal = [...HashMap.values(map)]\n .filter((state) => state.phase !== \"pending\")\n .toSorted((a, b) => (a.settledAt ?? 0) - (b.settledAt ?? 0));\n const excess = terminal.length - maxTerminal;\n if (excess <= 0) return map;\n let next = map;\n Arr.forEach(terminal.slice(0, excess), (entry) => {\n next = HashMap.remove(next, entry.mutationId);\n });\n return next;\n};\n\n/**\n * The phase a mutation is in, or `undefined` when it is not tracked (already\n * evicted, or settled before this engine instance seeded its map).\n */\nexport const phaseOf = (map: MutationStateMap, mutationId: number): MutationPhase | undefined =>\n Option.getOrUndefined(Option.map(HashMap.get(map, mutationId), (state) => state.phase));\n\n/**\n * Fold one mutation's terminal outcome in, without applying retention. Only a\n * `\"pending\"` entry moves (#364): a settled phase is never overwritten, so the\n * first outcome the client observed stands and a later, repeated or\n * contradictory report folds nothing.\n */\nconst transition = (\n map: MutationStateMap,\n mutationId: number,\n phase: \"acknowledged\" | \"rejected\" | \"dropped\",\n settledAt: number,\n reason: string | undefined\n): MutationStateMap => {\n const current = HashMap.get(map, mutationId);\n // Not tracked (already evicted, or settled before this engine instance\n // seeded its map), or already settled: nothing to fold.\n if (Option.isNone(current) || current.value.phase !== \"pending\") return map;\n return HashMap.set(map, mutationId, {\n ...current.value,\n phase,\n settledAt,\n ...(reason !== undefined ? { reason } : {}),\n });\n};\n\n/** Fold the backend's `applied` outcome in for one mutation, then apply terminal retention. */\nexport const acknowledged = (\n map: MutationStateMap,\n mutationId: number,\n settledAt: number,\n options?: RetentionOptions\n): MutationStateMap =>\n evictTerminal(transition(map, mutationId, \"acknowledged\", settledAt, undefined), options);\n\n/** Fold the backend's permanent rejection in for one mutation, then apply terminal retention. */\nexport const rejected = (\n map: MutationStateMap,\n mutationId: number,\n reason: string,\n settledAt: number,\n options?: RetentionOptions\n): MutationStateMap =>\n evictTerminal(transition(map, mutationId, \"rejected\", settledAt, reason), options);\n\n/**\n * Fold a paced-compaction drop in for one mutation (`ClientEngine.dropIfPending`,\n * #117's debounce/throttle/coalesce strategies superseding a still-unpushed\n * entry), then apply terminal retention. Unlike {@link acknowledged} /\n * {@link rejected}, this is not a backend verdict — the entry never reached the\n * backend — but it must still leave `\"pending\"`: left untouched, a compacted\n * entry would stay `\"pending\"` forever (the journal no longer has it, but\n * nothing ever transitions the state map), a permanently stale entry a\n * mutation-timeline consumer (a devtools journal panel) would show as\n * eternally in flight.\n */\nexport const dropped = (\n map: MutationStateMap,\n mutationId: number,\n settledAt: number,\n options?: RetentionOptions\n): MutationStateMap =>\n evictTerminal(transition(map, mutationId, \"dropped\", settledAt, undefined), options);\n\n/**\n * Fold a batch of paced-compaction drops in, then apply terminal retention\n * exactly once — see {@link acknowledgedMany}'s rationale: `evictTerminal` is\n * `O(size)`, so folding every transition first and evicting once keeps a\n * K-entry drop `O(size)` rather than `O(K * size)`.\n */\nexport const droppedMany = (\n map: MutationStateMap,\n mutationIds: ReadonlyArray<number>,\n settledAt: number,\n options?: RetentionOptions\n): MutationStateMap => {\n let next = map;\n Arr.forEach(mutationIds, (mutationId) => {\n next = transition(next, mutationId, \"dropped\", settledAt, undefined);\n });\n return evictTerminal(next, options);\n};\n\n/**\n * Fold a paced compaction in (#117, #249): the `dropped` ids settle as\n * `\"dropped\"`, and each `renumbered` survivor's still-`\"pending\"` state moves\n * from its old id to its new one (the `mutationId` field follows the key).\n * The map is keyed by id and a survivor may take an id a dropped entry just\n * vacated, so the survivor wins the slot — the dropped record for that id is\n * overwritten (the `dropped` lifecycle event is still emitted). Retention is\n * applied once, after everything has moved.\n */\nexport const compacted = (\n map: MutationStateMap,\n compaction: {\n readonly dropped: ReadonlyArray<number>;\n readonly renumbered: ReadonlyArray<{ readonly from: number; readonly to: number }>;\n },\n settledAt: number,\n options?: RetentionOptions\n): MutationStateMap => {\n let next = map;\n Arr.forEach(compaction.dropped, (mutationId) => {\n next = transition(next, mutationId, \"dropped\", settledAt, undefined);\n });\n const moved: Array<MutationState> = [];\n Arr.forEach(compaction.renumbered, ({ from, to }) => {\n const current = HashMap.get(next, from);\n if (Option.isNone(current)) return;\n moved.push({ ...current.value, mutationId: to });\n next = HashMap.remove(next, from);\n });\n Arr.forEach(moved, (state) => {\n next = HashMap.set(next, state.mutationId, state);\n });\n return evictTerminal(next, options);\n};\n\n/**\n * Fold a push ack sweep's whole batch of newly-applied mutation ids in, then\n * apply terminal retention exactly once — not once per id. `settleApplied`\n * (ClientEngine.ts) can settle every still-pending id at or below a push's\n * `lastMutationId` in one sweep; folding each through {@link acknowledged}\n * individually would re-scan the whole map (`evictTerminal` is `O(size)`)\n * once per settled id, an `O(K*size)` cost for a K-mutation sweep.\n */\nexport const acknowledgedMany = (\n map: MutationStateMap,\n mutationIds: ReadonlyArray<number>,\n settledAt: number,\n options?: RetentionOptions\n): MutationStateMap => {\n let next = map;\n Arr.forEach(mutationIds, (mutationId) => {\n next = transition(next, mutationId, \"acknowledged\", settledAt, undefined);\n });\n return evictTerminal(next, options);\n};\n","/**\n * RowChange\n *\n * Row-level deltas anchored to a subset's *result* — its windowed page, not\n * its full matching set — so a predicate or limit-boundary crossing produces\n * the same `enter`/`exit` a consumer diffing two `observe()` pages by hand\n * would derive (#115). `update` marks a same-membership value change;\n * `move` marks a same-membership, same-value row whose stable position (#112)\n * shifted — a neighbor entering/leaving the window re-ranked it without its\n * own value changing; `reset` marks a batch the consumer cannot diff against\n * (a `ViewChange.Rebuild` or a seq-gap collapse — the view could have shifted\n * any row, mirroring the page-level fallback both `ClientEngine` and `Mirror`\n * already use) and is always followed, in the same batch, by fresh `enter`s\n * for the current window.\n *\n * `position` (on `enter`/`update`) and `previousPosition`/`position` (on\n * `move`) are the row's {@link FractionalIndex} sort key within the window —\n * present whenever the source rows carry one (`LiveView.PositionedRow`,\n * i.e. `ClientEngine.observeChanges`) and absent otherwise (a `Mirror`,\n * which has no incrementally-maintained window of its own and so cannot\n * derive stable positions from the whole-page snapshots it diffs — a\n * documented gap, not a silent one; see `Mirror.observeChanges`). A consumer\n * that doesn't need order can ignore `position` entirely and treat `move` as\n * a no-op (the row's `value` is unchanged).\n *\n * `diff`/`reset`/`enters` are the shared primitives `ClientEngine.\n * observeChanges` and `Mirror.observeChanges` both fold their inputs\n * through, so the two hosts (ADR-0021) emit identical batches from\n * identical page transitions (module the `position`/`move` gap above).\n */\nimport * as Arr from \"effect/Array\";\nimport * as P from \"effect/Predicate\";\nimport type { RowId } from \"./Collection.js\";\n\n/** One change in an observed window: a row entered, updated, moved or exited, or a `reset`. */\nexport type RowChange<Row> =\n | { readonly _tag: \"enter\"; readonly row: Row; readonly position?: string }\n | {\n readonly _tag: \"update\";\n readonly row: Row;\n readonly previous: Row;\n readonly position?: string;\n }\n | {\n readonly _tag: \"move\";\n readonly row: Row;\n readonly position: string;\n readonly previousPosition: string;\n }\n | { readonly _tag: \"exit\"; readonly id: RowId; readonly previous: Row }\n | { readonly _tag: \"reset\" };\n\ninterface Identified {\n readonly id: RowId;\n readonly value: unknown;\n}\n\n/** A row carrying a stable position key (`LiveView.PositionedRow`'s shape). */\ninterface Positioned extends Identified {\n readonly position: string;\n}\n\nconst positionOf = (row: Identified): string | undefined => {\n const position = (row as Partial<Positioned>).position;\n return P.isString(position) ? position : undefined;\n};\n\n/** One `enter` per row of `rows`, in order, carrying `position` when present. */\nexport const enters = <Row extends Identified>(\n rows: ReadonlyArray<Row>\n): ReadonlyArray<RowChange<Row>> =>\n rows.map((row) => {\n const position = positionOf(row);\n return position === undefined ? { _tag: \"enter\", row } : { _tag: \"enter\", row, position };\n });\n\n/** The Rebuild/gap-collapse batch: a `reset` marker followed by fresh `enter`s. */\nexport const reset = <Row extends Identified>(\n rows: ReadonlyArray<Row>\n): ReadonlyArray<RowChange<Row>> => [{ _tag: \"reset\" }, ...enters(rows)];\n\n/**\n * One `next` row's decision against its `previous` counterpart (`undefined`\n * when the row is new): `enter`, `update`, `move`, or `undefined` when\n * nothing about it changed. Split out of {@link diff} so the id-membership\n * scan stays a plain loop over this single-row decision.\n */\nconst changeFor = <Row extends Identified>(\n row: Row,\n before: Row | undefined\n): RowChange<Row> | undefined => {\n const position = positionOf(row);\n if (before === undefined) {\n return position === undefined ? { _tag: \"enter\", row } : { _tag: \"enter\", row, position };\n }\n if (before.value !== row.value) {\n return position === undefined\n ? { _tag: \"update\", row, previous: before }\n : { _tag: \"update\", row, previous: before, position };\n }\n const previousPosition = positionOf(before);\n if (position !== undefined && previousPosition !== undefined && position !== previousPosition) {\n return { _tag: \"move\", row, position, previousPosition };\n }\n return undefined;\n};\n\n/**\n * Diff two windowed pages by id: a row only in `next` enters, a row only in\n * `previous` exits (carrying its last value), a row in both whose `value`\n * reference changed updates, and — when both sides carry a `position` — a row\n * whose value is unchanged but whose position moved emits `move` instead of\n * being silently dropped ({@link changeFor}). Order: `enter`/`update`/`move`\n * in `next`'s order, then `exit`s — batched, not positional beyond the\n * `position` field itself. Returns `[]` when nothing changed (including the\n * `previous === next` fast path), which the observers filter out rather than\n * emit an empty batch.\n */\nexport const diff = <Row extends Identified>(\n previous: ReadonlyArray<Row>,\n next: ReadonlyArray<Row>\n): ReadonlyArray<RowChange<Row>> => {\n if (previous === next) return [];\n const previousById = new Map(previous.map((row) => [row.id, row]));\n const nextIds = new Set<RowId>();\n const changes: Array<RowChange<Row>> = [];\n Arr.forEach(next, (row) => {\n nextIds.add(row.id);\n const change = changeFor(row, previousById.get(row.id));\n if (change !== undefined) changes.push(change);\n });\n Arr.forEach(previous, (row) => {\n if (!nextIds.has(row.id)) changes.push({ _tag: \"exit\", id: row.id, previous: row });\n });\n return changes;\n};\n","/**\n * Telemetry\n *\n * Effect-native observability for the sync engine: a small set of metrics and\n * span names wired into the hot paths (client push/pull, server push/pull,\n * fan-out). Effect carries a `MetricRegistry` and `Tracer` in context, so\n * instrumentation here surfaces through whatever exporter the host installs\n * (OpenTelemetry, Prometheus, a test registry) with no extra dependency.\n *\n * Metric names follow the `legation_*` convention; spans the\n * `legation.*` convention.\n */\n\nimport * as Effect from \"effect/Effect\";\nimport * as Metric from \"effect/Metric\";\n\n/** Pulls completed by a client (a patch applied + rebase). */\nexport const pullsTotal = Metric.counter(\"legation_client_pulls_total\", { incremental: true });\n\n/** Pushes completed by a client. */\nexport const pushesTotal = Metric.counter(\"legation_client_pushes_total\", { incremental: true });\n\n/** Mutations delivered upstream across all pushes. */\nexport const mutationsPushedTotal = Metric.counter(\"legation_mutations_pushed_total\", {\n incremental: true,\n});\n\n/** Pull requests served by the sync server. */\nexport const serverPullsTotal = Metric.counter(\"legation_server_pulls_total\", {\n incremental: true,\n});\n\n/** Pokes published by server fan-out. */\nexport const pokesTotal = Metric.counter(\"legation_pokes_total\", { incremental: true });\n\n/**\n * Pokes suppressed by predicate-level fan-out matching: a group that a\n * collection-only match would have poked, but whose subscriptions no hinted\n * change plausibly affects. Over-matching is safe (a redundant poke costs an\n * empty pull), so this counts avoided-but-safe work, not correctness.\n */\nexport const pokesSuppressedTotal = Metric.counter(\"legation_pokes_suppressed_total\", {\n incremental: true,\n});\n\n/** Patch sizes (ops per pull) computed by the server. */\nexport const patchOps = Metric.histogram(\"legation_patch_ops\", {\n boundaries: [0, 1, 2, 5, 10, 25, 50, 100, 250, 500],\n});\n\n/**\n * Sync operations (push/pull/poke stream) that failed terminally after the\n * client's retry policy was exhausted. A rising count means the transport is\n * degraded — bindings can surface a \"sync degraded\" state from it.\n */\nexport const syncFailuresTotal = Metric.counter(\"legation_client_sync_failures_total\", {\n incremental: true,\n});\n\n/**\n * Invalidation-bus hints dropped because a bounded bus (in-process PubSub or\n * memory broker) overflowed while a consumer was behind. A dropped hint only\n * delays convergence — the next pull repairs it — so this counts safely-shed\n * work under backpressure, never lost correctness (ADR-0009).\n */\nexport const hintsDroppedTotal = Metric.counter(\"legation_hints_dropped_total\", {\n incremental: true,\n});\n\n/**\n * Times a stalled engine observer's bounded change hub dropped a view-change,\n * forcing the consumer to collapse the gap into a full `Rebuild`. A Rebuild\n * subsumes any dropped `Patch`es (ADR-0008), so the view stays correct; this\n * counts backpressure-induced recomputes, not lost updates.\n */\nexport const changeCollapsesTotal = Metric.counter(\"legation_change_collapses_total\", {\n incremental: true,\n});\n\n/**\n * Times a stalled mirror observer's bounded change hub dropped a subset\n * key, forcing a full re-read of the observed subset. The newest rows live in\n * the mirror's `Ref`, so the re-read is lossless; this counts refreshes forced\n * by backpressure.\n */\nexport const mirrorRefreshesTotal = Metric.counter(\"legation_mirror_refreshes_total\", {\n incremental: true,\n});\n\n/**\n * Depth of the client's journal — the number of pending (unacknowledged)\n * mutations. Sampled as an absolute gauge on every append (a new pending\n * mutation) and every acknowledgement (a trim), so it tracks the outbox\n * backlog: a persistently high value means pushes are not draining.\n */\nexport const journalDepth = Metric.gauge(\"legation_journal_depth\");\n\n/**\n * Time (ms) to rebuild the optimistic overlay — the rebase (ADR-0008): replay\n * every pending mutation over confirmed rows. Sampled around the actual\n * materialisation (cache misses only), so it measures replay cost, not cache\n * hits.\n */\nexport const rebaseDurationMs = Metric.histogram(\"legation_rebase_duration_ms\", {\n boundaries: [0.5, 1, 2, 5, 10, 25, 50, 100, 250, 500, 1000],\n});\n\n/**\n * Time (ms) the server fan-out loop spends processing one hint batch — from\n * taking the batch off the invalidation bus to poking every matching group.\n * A proxy for hint-published → poke-sent latency (the hints carry no publish\n * timestamp), so it measures the fan-out leg the server controls.\n */\nexport const fanoutLatencyMs = Metric.histogram(\"legation_fanout_latency_ms\", {\n boundaries: [0.5, 1, 2, 5, 10, 25, 50, 100, 250, 500],\n});\n\n/** Patch size (ops) a client applies per pull — the downstream volume per rebase. */\nexport const pullPatchOps = Metric.histogram(\"legation_pull_patch_ops\", {\n boundaries: [0, 1, 2, 5, 10, 25, 50, 100, 250, 500],\n});\n\n/** Mutations delivered per push — the upstream batch size the journal coalesced. */\nexport const pushMutations = Metric.histogram(\"legation_push_mutations\", {\n boundaries: [0, 1, 2, 5, 10, 25, 50, 100, 250, 500],\n});\n\n/**\n * Times a cached response's row count exceeded the HTTP cache's fine-tag\n * budget (`HttpCacheInvalidation.FINE_TAG_ROW_BUDGET` in `@thomasfosterau/legation-browser`)\n * and fell back to tagging that response with its coarse\n * `collection:{name}` tag alone, skipping the per-row `collection:{name}:{id}`\n * tags. Correctness is unaffected (the coarse tag still evicts it on any row\n * change in the collection) — this counts responses that lost fine-grained\n * eviction to the budget, so the fallback is observable rather than silent.\n */\nexport const cacheTagBudgetExceededTotal = Metric.counter(\n \"legation_cache_tag_budget_exceeded_total\",\n {\n incremental: true,\n }\n);\n\n/** Record an integer count against a counter (no-op-safe in any context). */\nexport const count = <Input extends number>(\n metric: Metric.Metric<Input, unknown>,\n amount: Input\n): Effect.Effect<void> => Metric.update(metric, amount);\n\n/** Names used for `Effect.withSpan` on the engine's hot paths. */\nexport const span = {\n clientPull: \"legation.client.pull\",\n clientPush: \"legation.client.push\",\n serverPull: \"legation.server.pull\",\n serverPush: \"legation.server.push\",\n serverRead: \"legation.server.read\",\n} as const;\n","/**\n * Transport\n *\n * The customisable carrier seam for protocol messages (CONTEXT.md: \"sync\n * transport\"). Core defines the service interfaces and an in-memory pair;\n * the RPC-backed implementation (RpcTransport.ts) is the shipped default,\n * and alternative carriers (HttpApi + SSE, BroadcastChannel mirror↔service-\n * worker, bespoke) implement the same interfaces.\n */\n\nimport * as Clock from \"effect/Clock\";\nimport * as Context from \"effect/Context\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Ref from \"effect/Ref\";\nimport * as Result from \"effect/Result\";\nimport * as Scope from \"effect/Scope\";\nimport * as Semaphore from \"effect/Semaphore\";\nimport * as Stream from \"effect/Stream\";\nimport * as SubscriptionRef from \"effect/SubscriptionRef\";\nimport { TransportError } from \"./Errors.js\";\nimport type { VersionNotSupportedError } from \"./Errors.js\";\nimport type {\n Poke,\n PullRequest,\n PullResponse,\n PushRequest,\n PushResponse,\n ReadRequest,\n ReadResponse,\n} from \"./Protocol.js\";\n\n/** Connectivity of a client transport. */\nexport type ConnectionStatus = \"connecting\" | \"connected\" | \"disconnected\";\n\n/** The client side of a sync connection. */\nexport interface ClientTransport {\n readonly push: (\n request: PushRequest\n ) => Effect.Effect<PushResponse, TransportError | VersionNotSupportedError>;\n readonly pull: (\n request: PullRequest\n ) => Effect.Effect<PullResponse, TransportError | VersionNotSupportedError>;\n /**\n * Point-in-time fallthrough read (ADR-0025). Optional: carriers that\n * don't offer it simply don't serve the third read tier — the Client\n * degrades to answering locally.\n */\n readonly read?: (\n request: ReadRequest\n ) => Effect.Effect<ReadResponse, TransportError | VersionNotSupportedError>;\n /** Pokes from the server; may be empty for pull-only carriers. */\n readonly pokes: Stream.Stream<Poke, TransportError>;\n readonly status: Effect.Effect<ConnectionStatus>;\n /**\n * Emits the current status first, then changes. It is an edge trigger for the\n * sync loop, not a mirror of `status`: a wrapper may emit `connected` to\n * start a push and pull while `status` still reads `disconnected` (as\n * `BrowserConnectivity` does on a navigator reconnect), so a label should\n * read `status`.\n */\n readonly statusChanges: Stream.Stream<ConnectionStatus>;\n}\n\n/** The {@link ClientTransport} service a Client syncs over. */\nexport const ClientTransport = Context.Service<ClientTransport>(\n \"@thomasfosterau/legation/ClientTransport\"\n);\n\n/**\n * The server side: what a carrier needs from the sync server to answer\n * clients. Implemented by SyncServer; bound by each carrier (RPC handlers,\n * HTTP routes, message listeners).\n */\nexport interface ServerHandler {\n readonly handlePush: (\n request: PushRequest\n ) => Effect.Effect<PushResponse, TransportError | VersionNotSupportedError>;\n readonly handlePull: (\n request: PullRequest\n ) => Effect.Effect<PullResponse, TransportError | VersionNotSupportedError>;\n /** Point-in-time fallthrough read (ADR-0025): auth-filtered, no CVR. */\n readonly handleRead: (\n request: ReadRequest\n ) => Effect.Effect<ReadResponse, TransportError | VersionNotSupportedError>;\n /** Pokes addressed to one client group. */\n readonly pokes: (clientGroupId: string) => Stream.Stream<Poke>;\n}\n\n/** The {@link ServerHandler} service a carrier answers clients with. */\nexport const ServerHandler = Context.Service<ServerHandler>(\n \"@thomasfosterau/legation/ServerHandler\"\n);\n\n/**\n * An in-memory client transport bound directly to a ServerHandler — the\n * loop-back carrier for tests and same-process client/server setups.\n */\nexport const makeInMemory = (\n handler: ServerHandler,\n clientGroupId: string\n): Effect.Effect<\n ClientTransport & { readonly setStatus: (status: ConnectionStatus) => Effect.Effect<void> },\n never,\n Scope.Scope\n> =>\n Effect.gen(function* () {\n const status = yield* SubscriptionRef.make<ConnectionStatus>(\"connected\");\n return {\n push: (request) => handler.handlePush(request),\n pull: (request) => handler.handlePull(request),\n read: (request) => handler.handleRead(request),\n pokes: handler.pokes(clientGroupId),\n status: SubscriptionRef.get(status),\n statusChanges: SubscriptionRef.changes(status),\n setStatus: (next) => SubscriptionRef.set(status, next),\n };\n });\n\n/**\n * The no-server transport: every wire call fails with a `TransportError`,\n * pokes never arrive, status is permanently `\"disconnected\"`. This is\n * `Client.make`'s default when nothing else is wired — a purely local,\n * optimistic Client (the journal retains every intent, so attaching a real\n * transport later pushes the backlog).\n */\nexport const offline: ClientTransport = {\n push: () => Effect.fail(new TransportError({ message: \"offline transport: no server wired\" })),\n pull: () => Effect.fail(new TransportError({ message: \"offline transport: no server wired\" })),\n read: () => Effect.fail(new TransportError({ message: \"offline transport: no server wired\" })),\n pokes: Stream.empty,\n status: Effect.succeed(\"disconnected\"),\n statusChanges: Stream.succeed(\"disconnected\"),\n};\n\n/** Layer wiring the in-memory transport to an in-context ServerHandler. */\nexport const layerInMemory = (\n clientGroupId: string\n): Layer.Layer<ClientTransport, never, ServerHandler> =>\n Layer.effect(ClientTransport)(\n Effect.gen(function* () {\n const handler = yield* ServerHandler;\n return yield* makeInMemory(handler, clientGroupId);\n })\n );\n\n/**\n * Internal helper: a poke hub keyed by client group (used by SyncServer).\n *\n * Delivery guarantee (#44): one `sliding(1)` PubSub per client group, so a\n * poke storm dedupes. A poke is a contentless \"pull soon\" hint, so an\n * outstanding, not-yet-consumed poke absorbs any number of fresh ones — the\n * sliding strategy replaces the queued poke rather than growing the queue, and\n * N hints in a tick still deliver at most one queued poke per group. Correctness\n * never depends on the poke: a dropped/collapsed poke only delays the next pull\n * (ADR-0008), which is the correctness path.\n *\n * `replay: 1` on each group's hub keeps the reconnect-race behaviour — a late\n * subscriber (a (re)connecting poke stream) still sees the most recent poke,\n * costing at most a redundant pull. `sliding(1)` already gives the\n * late-subscriber-sees-latest property for active buffers; `replay` extends it\n * across the subscribe gap.\n *\n * Hubs are created lazily per group under a lock (single-flight) and all shut\n * down together when the enclosing scope closes.\n */\nexport const makePokeHub: Effect.Effect<\n {\n readonly publish: (clientGroupId: string, poke: Poke) => Effect.Effect<void>;\n readonly subscribe: (clientGroupId: string) => Stream.Stream<Poke>;\n },\n never,\n Scope.Scope\n> = Effect.gen(function* () {\n const hubs = yield* Ref.make(new Map<string, PubSub.PubSub<Poke>>());\n const lock = yield* Semaphore.make(1);\n // One finalizer shuts every group's hub down when the scope closes.\n yield* Effect.addFinalizer(() =>\n Ref.get(hubs).pipe(\n Effect.flatMap((map) => Effect.forEach([...map.values()], (hub) => PubSub.shutdown(hub))),\n Effect.asVoid\n )\n );\n // Get-or-create a group's `sliding(1)` hub; the lock makes creation\n // single-flight so concurrent publish/subscribe for a new group share one hub.\n const hubFor = (clientGroupId: string): Effect.Effect<PubSub.PubSub<Poke>> =>\n Semaphore.withPermit(\n lock,\n Effect.gen(function* () {\n const existing = (yield* Ref.get(hubs)).get(clientGroupId);\n if (existing !== undefined) return existing;\n const hub = yield* PubSub.sliding<Poke>({ capacity: 1, replay: 1 });\n yield* Ref.update(hubs, (map) => new Map(map).set(clientGroupId, hub));\n return hub;\n })\n );\n return {\n publish: (clientGroupId, poke) =>\n hubFor(clientGroupId).pipe(Effect.flatMap((hub) => Effect.asVoid(PubSub.publish(hub, poke)))),\n subscribe: (clientGroupId) =>\n Stream.unwrap(hubFor(clientGroupId).pipe(Effect.map((hub) => Stream.fromPubSub(hub)))),\n };\n});\n\n/** Only a TransportError signals carrier trouble; version rejections pass through. */\nconst isTransportError = (error: TransportError | VersionNotSupportedError): boolean =>\n error._tag === \"TransportError\";\n\n/** A transport wrapped by {@link simulateOffline}, plus the toggle driving it. */\nexport interface SimulatedOffline {\n /** The wrapped transport: fails push/pull/read while simulated-offline. */\n readonly transport: ClientTransport;\n /** Flip simulated connectivity. */\n readonly setOffline: (offline: boolean) => Effect.Effect<void>;\n /** Current simulated-offline state. */\n readonly isOffline: Effect.Effect<boolean>;\n}\n\n/**\n * Wrap any transport with a simulated-offline gate: while toggled offline,\n * every push/pull/read *fails* with a `TransportError` (as a real network\n * would), so the engine keeps mutations in the journal and its sync loop\n * flushes them on reconnect — exactly the behaviour a devtools \"simulated\n * offline\" action needs (issue #120), generalising the demo examples'\n * hand-rolled offline-gate transport into reusable substrate.\n *\n * `status`/`statusChanges` report `\"disconnected\"` while the gate is closed,\n * otherwise defer to the wrapped transport's own reported status — so this\n * composes under {@link withInferredStatus} or over a carrier that already\n * tracks real connectivity.\n */\nexport const simulateOffline = (\n transport: ClientTransport\n): Effect.Effect<SimulatedOffline, never, Scope.Scope> =>\n Effect.gen(function* () {\n const offline = yield* SubscriptionRef.make(false);\n\n const gate = <A>(\n effect: Effect.Effect<A, TransportError | VersionNotSupportedError>\n ): Effect.Effect<A, TransportError | VersionNotSupportedError> =>\n SubscriptionRef.get(offline).pipe(\n Effect.flatMap((isOffline) =>\n isOffline ? Effect.fail(new TransportError({ message: \"simulated offline\" })) : effect\n )\n );\n\n const status = SubscriptionRef.get(offline).pipe(\n Effect.flatMap((isOffline): Effect.Effect<ConnectionStatus> =>\n isOffline ? Effect.succeed(\"disconnected\") : transport.status\n )\n );\n\n const statusChanges = Stream.zipLatestWith(\n SubscriptionRef.changes(offline),\n transport.statusChanges,\n (isOffline, real): ConnectionStatus => (isOffline ? \"disconnected\" : real)\n ).pipe(Stream.changesWith((a, b) => a === b));\n\n const read = transport.read;\n const wrapped: ClientTransport = {\n push: (request) => gate(transport.push(request)),\n pull: (request) => gate(transport.pull(request)),\n ...(read === undefined ? {} : { read: (request: ReadRequest) => gate(read(request)) }),\n pokes: transport.pokes,\n status,\n statusChanges,\n };\n\n return {\n transport: wrapped,\n setOffline: (next) => SubscriptionRef.set(offline, next),\n isOffline: SubscriptionRef.get(offline),\n };\n });\n\n/**\n * Wrap a transport with connectivity inferred from observed behaviour:\n * `\"connecting\"` until the first push/pull settles, then `\"connected\"` after\n * each success and `\"disconnected\"` after each `TransportError`. Carriers\n * that report their own status (the in-memory pair, a status-aware socket)\n * don't need this; the default RPC carrier does — it reports permanently\n * `\"connected\"` (RpcTransport.ts), so wrap it with this to give the engine's\n * reconnect trigger something real to react to.\n */\nexport const withInferredStatus = (\n transport: ClientTransport\n): Effect.Effect<ClientTransport, never, Scope.Scope> =>\n Effect.gen(function* () {\n const status = yield* SubscriptionRef.make<ConnectionStatus>(\"connecting\");\n const observe = <A>(\n effect: Effect.Effect<A, TransportError | VersionNotSupportedError>\n ): Effect.Effect<A, TransportError | VersionNotSupportedError> =>\n effect.pipe(\n Effect.tap(() => SubscriptionRef.set(status, \"connected\")),\n Effect.tapError((error) =>\n isTransportError(error) ? SubscriptionRef.set(status, \"disconnected\") : Effect.void\n )\n );\n return {\n push: (request) => observe(transport.push(request)),\n pull: (request) => observe(transport.pull(request)),\n pokes: transport.pokes,\n status: SubscriptionRef.get(status),\n // Dedup consecutive repeats so a burst of successful calls doesn't spam\n // the engine's reconnect trigger with \"connected\" re-emissions.\n statusChanges: SubscriptionRef.changes(status).pipe(Stream.changesWith((a, b) => a === b)),\n };\n });\n\n/** Options for {@link withFallback}. */\nexport interface FallbackOptions {\n /**\n * How long a failed primary is sidelined before a call probes it again.\n * Default 30 seconds.\n */\n readonly restoreAfter?: Duration.Input;\n /**\n * Time budget for each primary call. A primary that neither succeeds nor\n * fails within it is interrupted and treated as a `TransportError`:\n * sidelined, with the call falling to the fallback. Without a budget, a\n * carrier that hangs rather than fails stalls sync indefinitely — the\n * fallback never gets a chance. No default: a cold-start pull over a slow\n * link can legitimately be slow, so pick a budget suited to your payloads.\n * (A delivered-but-timed-out push re-sent through the fallback is safe:\n * the server's mutation ledger deduplicates by mutation id.)\n */\n readonly primaryTimeout?: Duration.Input;\n}\n\n/**\n * Layer a fallback carrier under a primary one (e.g. plain HTTP under\n * WebSockets): each push/pull tries the primary and falls back on a\n * `TransportError`. After a primary failure the primary is sidelined for\n * `restoreAfter`, so subsequent calls go straight to the fallback until the\n * cooldown elapses and a call probes the primary again.\n *\n * Status is inferred from observed behaviour: `\"connected\"` while either\n * carrier serves (sync is a progressive enhancement — a working fallback IS\n * connected), `\"disconnected\"` once a call exhausts both. Pokes from both\n * carriers are merged (they are contentless hints; duplicates cost at most a\n * redundant pull) and a failing primary poke stream is dropped rather than\n * killing the fallback's. A `VersionNotSupportedError` propagates without\n * falling back — it is the server's verdict, not carrier trouble.\n */\nexport const withFallback = (\n primary: ClientTransport,\n fallback: ClientTransport,\n options?: FallbackOptions\n): Effect.Effect<ClientTransport, never, Scope.Scope> =>\n Effect.gen(function* () {\n const restoreAfterMillis = Duration.toMillis(options?.restoreAfter ?? \"30 seconds\");\n const primaryTimeout = options?.primaryTimeout;\n const status = yield* SubscriptionRef.make<ConnectionStatus>(\"connecting\");\n const sidelinedUntil = yield* Ref.make(0);\n\n // A hang is carrier trouble just like a failure: interrupt the primary\n // and surface a TransportError so the sideline-and-fall-back path runs.\n const budgeted = <A>(\n effect: Effect.Effect<A, TransportError | VersionNotSupportedError>\n ): Effect.Effect<A, TransportError | VersionNotSupportedError> =>\n primaryTimeout === undefined\n ? effect\n : Effect.timeoutOrElse(effect, {\n duration: primaryTimeout,\n orElse: () =>\n Effect.fail(\n new TransportError({\n message: `primary transport call exceeded ${Duration.format(\n Duration.fromInputUnsafe(primaryTimeout)\n )}`,\n })\n ),\n });\n\n const call = <A>(\n f: (transport: ClientTransport) => Effect.Effect<A, TransportError | VersionNotSupportedError>\n ): Effect.Effect<A, TransportError | VersionNotSupportedError> =>\n Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n if ((yield* Ref.get(sidelinedUntil)) <= now) {\n const first = yield* Effect.result(budgeted(f(primary)));\n if (Result.isSuccess(first)) {\n yield* SubscriptionRef.set(status, \"connected\");\n return first.success;\n }\n if (!isTransportError(first.failure)) return yield* Effect.fail(first.failure);\n yield* Ref.set(sidelinedUntil, now + restoreAfterMillis);\n }\n const second = yield* Effect.result(f(fallback));\n if (Result.isSuccess(second)) {\n yield* SubscriptionRef.set(status, \"connected\");\n return second.success;\n }\n if (isTransportError(second.failure)) yield* SubscriptionRef.set(status, \"disconnected\");\n return yield* Effect.fail(second.failure);\n });\n\n return {\n push: (request) => call((transport) => transport.push(request)),\n pull: (request) => call((transport) => transport.pull(request)),\n pokes: Stream.merge(\n primary.pokes.pipe(Stream.catchCause(() => Stream.empty)),\n fallback.pokes\n ),\n status: SubscriptionRef.get(status),\n statusChanges: SubscriptionRef.changes(status).pipe(Stream.changesWith((a, b) => a === b)),\n };\n });\n","/**\n * ClientEngine\n *\n * The client-side engine: optimistic mutations into the journal, local\n * materialization (confirmed rows + optimistic overlay), subscriptions,\n * and the sync loop (push journal, pull patches, rebase).\n *\n * Rebase is recomputation (ADR-0008): the materialized view is always\n * \"confirmed rows with pending mutations replayed on top\", so applying a\n * patch and dropping acknowledged mutations IS the rebase — revealed\n * atomically through a single changes event.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Clock from \"effect/Clock\";\nimport * as Context from \"effect/Context\";\nimport * as Deferred from \"effect/Deferred\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Layer from \"effect/Layer\";\nimport * as Metric from \"effect/Metric\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Ref from \"effect/Ref\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport * as Semaphore from \"effect/Semaphore\";\nimport * as Stream from \"effect/Stream\";\nimport * as SubscriptionRef from \"effect/SubscriptionRef\";\nimport * as Aggregate from \"./Aggregate.js\";\nimport type { RowId, RowVersion } from \"./Collection.js\";\nimport { ClientStore, NO_COMPACTION, freezePending, type CompactionResult } from \"./ClientStore.js\";\nimport * as Hash from \"./Hash.js\";\nimport * as Identity from \"./Identity.js\";\nimport * as Index from \"./CollectionIndex.js\";\nimport {\n MutatorError,\n QueryError,\n StoreError,\n TransportError,\n VersionNotSupportedError,\n} from \"./Errors.js\";\nimport * as LiveView from \"./LiveView.js\";\nimport type { LocalWriter, MutatorRegistry } from \"./Mutator.js\";\nimport * as MutationState from \"./MutationState.js\";\nimport type * as PredicateModule from \"./Predicate.js\";\nimport type {\n Mutation,\n NamedSubscription,\n PatchOp,\n PullResponse,\n PushResponse,\n ReadResponse,\n} from \"./Protocol.js\";\nimport * as Query from \"./Query.js\";\nimport * as RowChange from \"./RowChange.js\";\nimport * as Telemetry from \"./Telemetry.js\";\nimport { ClientTransport } from \"./Transport.js\";\nimport * as Subset from \"./Subset.js\";\n\nexport type { RowChange } from \"./RowChange.js\";\n\n/** A locally-materialized row (no version: overlay rows have none yet). */\nexport interface LocalRow {\n readonly id: RowId;\n readonly value: unknown;\n}\n\n/**\n * A {@link LocalRow} whose `value` is refined to the collection's row type `A`.\n * Produced by the typed `query`/`observe` overloads when handed a\n * {@link Subset.TypedSubset}. The refinement is a trust-cast: server data\n * already passed the row schema on write, so the read path never decodes\n * (ADR-0014) — only the static type is narrowed.\n */\nexport interface TypedRow<A> {\n readonly id: RowId;\n readonly value: A;\n}\n\n/**\n * Options for a projected {@link ClientEngine.observe}: `select` maps each\n * emitted page to a derived value `B`; consecutive equal projections are\n * dropped by `equals` (reference equality by default), so a change to a field\n * the projection ignores never re-emits.\n */\nexport interface ObserveOptions<Row, B> {\n readonly select: (rows: ReadonlyArray<Row>) => B;\n readonly equals?: (a: B, b: B) => boolean;\n}\n\n/**\n * Options for {@link ClientEngine.observeChanges}. `includeInitial` emits the\n * current window as `enter`s in the first batch (TanStack's\n * `currentStateAsChanges`/`includeInitialState`); the default `false` waits\n * for the first live change.\n */\nexport interface ObserveChangesOptions {\n readonly includeInitial?: boolean;\n}\n\n/**\n * `limit`/`cursor` to widen or advance an open {@link ClientEngine.observeWindow}\n * observation (mirrors `LiveView.retarget`) — an omitted field leaves that\n * side of the window where it is.\n */\nexport interface WindowRetarget {\n readonly limit?: number;\n readonly cursor?: string;\n}\n\n/**\n * A reactively-retargetable live window (#133): `rows` is the same live page\n * stream {@link ClientEngine.observe} would give this subset; `retarget`\n * widens/advances its `limit`/`cursor` in place — reusing `LiveView`'s\n * maintained order (`LiveView.retarget`: no re-subscribe, no rebuild from\n * scratch) — and widens this subset's entry in the engine's subscription\n * list so the next `pull` fetches the wider window from the server too.\n * `collection`/`where`/`orderBy` are fixed at `observeWindow` time; only\n * `limit`/`cursor` move.\n */\nexport interface WindowObservation {\n readonly rows: Stream.Stream<ReadonlyArray<LocalRow>, StoreError | MutatorError>;\n readonly retarget: (window: WindowRetarget) => Effect.Effect<void>;\n}\n\n/**\n * A mutation's authoritative (server) outcome: `applied` once the backend\n * acknowledged it with effects, or `rejected` with a reason when the backend\n * permanently refused it (#35). Observed via {@link MutationHandle}.\n */\nexport type MutationOutcome =\n | { readonly _tag: \"applied\" }\n | { readonly _tag: \"rejected\"; readonly reason: string };\n\n/**\n * A handle to a journaled mutation whose backend outcome can be awaited. The\n * `acknowledged` effect resolves once the backend settles the mutation (via a\n * push or pull acknowledgement); it is interrupted if the engine scope closes\n * first, so it never hangs.\n *\n * `mutationId` is the id the mutation was journaled under. While the entry is\n * still unpushed a paced compaction (#249) may renumber it to keep the\n * journal gap-free (the backend rejects gaps), so treat the id as a label for\n * *now*: `acknowledged` follows the entry through any renumbering, and\n * `MutationRenumbered` on {@link ClientEngine.engineEvents} reports each move.\n * Once a push has claimed the entry its id never changes again. If a\n * compaction supersedes the entry instead, `acknowledged` is interrupted.\n */\nexport interface MutationHandle {\n readonly mutationId: number;\n readonly acknowledged: Effect.Effect<MutationOutcome>;\n}\n\n/**\n * The form client a form-action Mutation runs under (ADR-0030 #215 §2): a\n * fresh client id minted for one rendered form, with its mutation id (`1`).\n */\nexport interface FormClient {\n readonly clientId: string;\n readonly mutationId: number;\n}\n\n/** A form mutation's args in both forms: `encoded` as persisted, `decoded` as its handler runs on. */\ninterface FormArgs {\n readonly encoded: unknown;\n readonly decoded: unknown;\n}\n\n/**\n * The part of a form action's receipt the engine settles on: the backend's\n * ruling. `Server.Receipt` (what `Server.mutate` answers) has this shape.\n */\nexport type FormRuling =\n | { readonly phase: \"acknowledged\" }\n | { readonly phase: \"rejected\"; readonly reason: string };\n\n/**\n * An enhanced form submission's optimistic entry (ADR-0030 #215 §4), from\n * {@link ClientEngine.beginFormMutation}. Exactly one of `settle` or `abandon`\n * ends it; later calls do nothing.\n */\nexport interface FormSubmission {\n /** The form client the entry is overlaid under. */\n readonly form: FormClient;\n /**\n * Settle on the action's receipt. `acknowledged` moves the entry to the\n * unpulled tail, where it stays overlaid until a pull whose\n * `lastMutationIds` covers the form client releases it, exactly as for a\n * pushed mutation; `rejected` drops it now. Either way a pull is signalled.\n */\n readonly settle: (ruling: FormRuling) => Effect.Effect<void, StoreError>;\n /**\n * The action did not answer (the network failed, or the server errored):\n * drop the entry and signal a pull, which shows whatever the server did.\n */\n readonly abandon: Effect.Effect<void>;\n}\n\n/**\n * A mutation lifecycle event on {@link ClientEngine.mutationEvents}: emitted\n * when a mutation is `journaled` locally, then when the backend `acknowledged`\n * (applied) or `rejected` it — or, for a still-unpushed entry, when a paced\n * strategy (#117: debounce/throttle/coalesce) `dropped` it via\n * `dropIfPending` in favour of a newer entry for the same key. Every\n * journaled mutation emits `journaled`, whether it came from `mutate`,\n * `mutateEncoded`, or `mutateWithAck`.\n *\n * A paced compaction's `MutationRenumbered` (#249) is **not** projected onto\n * this stream: its `phase` union describes one mutation's lifecycle, and a\n * renumber is not a phase. Consumers that correlate by id read it from\n * {@link ClientEngine.engineEvents}, or just follow `mutationStates` (which\n * moves the state to the new id).\n */\nexport interface MutationEvent {\n readonly clientId: string;\n readonly mutationId: number;\n readonly phase: \"journaled\" | \"acknowledged\" | \"rejected\" | \"dropped\";\n readonly reason?: string;\n}\n\n/**\n * A unified sync-lifecycle event on {@link ClientEngine.engineEvents} (#45):\n * the single source of truth from which {@link ClientEngine.mutationEvents}\n * (#36) is derived. Every variant is emitted from one internal hub, kept\n * unbounded for the same reason #44 keeps `mutationEventsHub` unbounded:\n * lifecycle events are low-volume, consumer-driven, and must be lossless —\n * they are observability, not reconstructable via pull.\n *\n * - `MutationJournaled` — a mutation was journaled locally (from `mutate`,\n * `mutateEncoded`, or `mutateWithAck`), or a journal entry a direct store write\n * (`Hydration.hydrate`) appended was adopted into this engine (#358), once per entry.\n * - `MutationAcknowledged` — the backend applied a journaled mutation.\n * - `MutationRejected` — the backend permanently refused it, with a `reason`.\n * Each mutation settles once: a later response that repeats or contradicts\n * its outcome is ignored (#364), so no second event follows.\n * - `MutationDropped` — a paced strategy (#117) compacted a still-unpushed\n * entry out of the journal in favour of a newer one for the same key; the\n * entry never reached the backend.\n * - `MutationRenumbered` — the same compaction moved a surviving, still-\n * unpushed entry from `previousMutationId` to `mutationId` so the client's\n * ids stay contiguous (#249). Emitted after the compaction's `MutationDropped`\n * events; an id seen in either may now name a different entry.\n * - `PushStarted` / `PushCompleted` — a push began / finished (with the number\n * of `mutations` delivered).\n * - `PullStarted` / `PullCompleted` — a pull began / finished (with the number\n * of patch `ops` applied, the distinct `collections` those ops touched, and\n * the individual `rows` — (collection, id) pairs — a `Put`/`Del` touched; a\n * `Clear` stands for every collection the client currently holds, since it\n * resets the whole view, and contributes no `rows` (there is no finite row\n * list for \"everything\"). The touched collections and rows drive\n * collection- and row-scoped reactions such as HTTP-cache tag invalidation\n * (`@thomasfosterau/legation-browser`'s `HttpCacheInvalidation`, #207), which is why they\n * are reported even on a client with an empty journal (the common case,\n * where a pull emits a `Patch` change and no `ViewRebuilt`).\n * - `PokeReceived` — the sync loop observed a poke (with its optional `reason`).\n * - `ViewRebuilt` — the local view was rebuilt (rebase/seed/subscribe), scoped\n * to the `collections` the shift touched (absent means \"any collection\").\n * - `UpdateNeeded` — the server rejected this build's `schemaVersion` (#48);\n * emitted at most once per ongoing rejection (the latch resets on the next\n * successful push/pull), alongside the `onUpdateNeeded` hook.\n */\nexport type EngineEvent =\n | { readonly _tag: \"MutationJournaled\"; readonly clientId: string; readonly mutationId: number }\n | {\n readonly _tag: \"MutationAcknowledged\";\n readonly clientId: string;\n readonly mutationId: number;\n }\n | {\n readonly _tag: \"MutationRejected\";\n readonly clientId: string;\n readonly mutationId: number;\n readonly reason: string;\n }\n | {\n readonly _tag: \"MutationDropped\";\n readonly clientId: string;\n readonly mutationId: number;\n }\n | {\n readonly _tag: \"MutationRenumbered\";\n readonly clientId: string;\n readonly previousMutationId: number;\n readonly mutationId: number;\n }\n | { readonly _tag: \"PushStarted\" }\n | { readonly _tag: \"PushCompleted\"; readonly mutations: number }\n | { readonly _tag: \"PullStarted\" }\n | {\n readonly _tag: \"PullCompleted\";\n readonly ops: number;\n readonly collections: ReadonlyArray<string>;\n readonly rows: ReadonlyArray<{ readonly collection: string; readonly id: RowId }>;\n }\n | { readonly _tag: \"PokeReceived\"; readonly reason?: string }\n | { readonly _tag: \"ViewRebuilt\"; readonly collections?: ReadonlyArray<string> }\n | {\n readonly _tag: \"UpdateNeeded\";\n readonly schemaVersion?: string;\n readonly message: string;\n };\n\n/**\n * A row-level delta produced by a mutator's local handler (#109): unlike a\n * `PatchOp`, it carries no server version — the row is optimistic, not yet\n * confirmed. Structurally interchangeable with `PatchOp`'s `Put`/`Del` for\n * `LiveView` folding, which never reads `version`.\n */\ntype OverlayOp =\n | {\n readonly _tag: \"Put\";\n readonly collection: string;\n readonly id: RowId;\n readonly value: unknown;\n }\n | { readonly _tag: \"Del\"; readonly collection: string; readonly id: RowId };\n\n/**\n * A local-view change. `Patch` carries per-row deltas that drive incremental\n * `LiveView` maintenance: confirmed-row ops from a pull (only when the journal\n * was empty, so they equal the materialized-view deltas) or the ops a mutator's\n * local handler just performed on the optimistic overlay (#109). `Rebuild` is\n * the conservative fallback when the overlay could have shifted in a way we\n * did not track precisely, so observers re-materialize; its `collections`\n * names exactly which collections the shift touched, so an observer of a\n * collection outside the set skips the recompute. `collections` left\n * `undefined` means \"any collection\" — the global fallback for changes we\n * cannot scope precisely (a `Clear`, an unknown mutator, a handler that threw).\n */\ntype ViewChange =\n | { readonly _tag: \"Patch\"; readonly ops: ReadonlyArray<PatchOp | OverlayOp> }\n | { readonly _tag: \"Rebuild\"; readonly collections?: ReadonlySet<string> };\n\n/** The global rebuild: `collections` undefined, so every observer re-materializes. */\nconst REBUILD: ViewChange = { _tag: \"Rebuild\" };\n\n// What a journaled mutation's local effects are applied onto (#260): the warm\n// overlay cache, or the overlay journal from before the append to replay into\n// a cold one. Read under `overlayLock`, so the journal is only read when the\n// cache is cold.\ntype OverlayBase =\n | { readonly _tag: \"Warm\"; readonly view: Map<string, Map<RowId, LocalRow>> }\n | { readonly _tag: \"Cold\"; readonly journalBefore: ReadonlyArray<Mutation> };\n\n/** A rebuild scoped to `collections`, or the global {@link REBUILD} when undefined. */\nconst rebuildFor = (collections: ReadonlySet<string> | undefined): ViewChange =>\n collections === undefined ? REBUILD : { _tag: \"Rebuild\", collections };\n\n/**\n * Most acknowledged-but-unpulled mutations the engine keeps in the overlay\n * (#286). A push acknowledges entries that the next pull reports. The tail\n * never grows past this bound: a push sends only as many mutations as the\n * room left, and a full tail waits for a pull (#429). Nothing releases an\n * entry early.\n */\nconst UNPULLED_LIMIT = 1024;\n\n/**\n * Whether a `lastMutationIds` watermark covers `mutation`: its client's\n * watermark is at or above the mutation's id.\n */\nconst isCoveredBy = (\n lastMutationIds: Readonly<Record<string, number>>,\n mutation: Mutation\n): boolean => {\n const upTo: number | undefined = lastMutationIds[mutation.clientId];\n return upTo !== undefined && mutation.mutationId <= upTo;\n};\n\n// A windowed subset (limit/cursor) can't fold an aggregate incrementally\n// without also tracking window-boundary shifts (a delta outside the window\n// can still evict/admit a row at its edge, which a row-level delta alone\n// doesn't reveal) — `observeAggregate`/`observeAggregateGrouped` refold the\n// page each emission for these, same as before #110. An unwindowed subset\n// (the common case: aggregate over everything synced) folds `Patch` ops in\n// place instead.\nconst isWindowed = (subset: Subset.Subset): boolean =>\n subset.limit !== undefined || subset.cursor !== undefined;\n\n/**\n * Sync-loop scheduling knobs. `push`/`pull` stay the primitives; these grow\n * `runSync` into a configurable scheduler driven by `Effect.Schedule` and the\n * transport's `statusChanges` seam. Both are opt-in: unset means the loop\n * keeps only its baseline triggers (pull on poke, push+pull on reconnect).\n * Retry/backoff is a separate concern the loop composes with, not embeds.\n */\nexport interface SyncLoopOptions {\n /**\n * Auto-push after `mutate`/`mutateEncoded` journals a mutation, debounced so\n * a burst of mutations inside the window coalesces into a single push (the\n * journal already batches naturally). Unset, a journaled mutation is not\n * pushed until something else triggers one — a reconnect, a poke-driven\n * pull cycle, or an explicit `push` — so on an already-connected client it\n * can sit in the journal indefinitely, with nothing surfaced as an error.\n * The examples and `examples/commerce`'s host use `\"300 millis\"`.\n */\n readonly pushDebounce?: Duration.Input;\n /**\n * Periodic pull as the correctness backstop, so the client converges over\n * pull alone even when no pokes arrive (\"pull is the correctness path\").\n * Unset, convergence depends entirely on pokes arriving — if the poke\n * stream drops or never connects, nothing else notices until a reconnect\n * or an explicit `pull`.\n */\n readonly pullInterval?: Duration.Input;\n}\n\n/**\n * Retry/backoff policies for the sync loop's network legs (#34). The scheduler\n * (#33) decides *when* to attempt; these `Schedule`s decide *how* an attempt\n * survives transient failure — kept orthogonal to avoid double-retry. Only\n * `TransportError` is retried; `StoreError`/`MutatorError` are not transient and\n * propagate to the failure surface immediately. Unset legs use\n * {@link defaultRetryPolicy}.\n */\nexport interface RetryOptions {\n readonly push?: Schedule.Schedule<unknown, unknown>;\n readonly pull?: Schedule.Schedule<unknown, unknown>;\n /** Re-establishment policy for a failed poke stream. */\n readonly pokes?: Schedule.Schedule<unknown, unknown>;\n}\n\n/**\n * Default backoff: exponential from 1s (factor 2), the delay capped at 30s,\n * bounded to 5 retries — mirroring TanStack Query's 1s→30s policy. No jitter,\n * so it composes predictably; add `Schedule.jittered` to taste.\n */\nexport const defaultRetryPolicy: Schedule.Schedule<unknown, unknown> = Schedule.max([\n Schedule.min([\n Schedule.exponential(Duration.seconds(1), 2),\n Schedule.spaced(Duration.seconds(30)),\n ]),\n Schedule.recurs(5),\n]);\n\n/**\n * What {@link ClientEngine.reset} did — an identity change is not a silent\n * operation, so the caller is told which branch of the boundary's transition\n * rule ran and what it moved.\n */\nexport interface ResetOutcome {\n /** The branch {@link Identity.transitionOf} chose. */\n readonly transition: Identity.Transition;\n /** The superseded fingerprint the journal was quarantined under, on a `Reset`. */\n readonly quarantinedUnder?: Identity.Fingerprint;\n /** How many unpushed entries moved into that quarantine. */\n readonly quarantined: number;\n /** How many entries the adopted identity's own quarantine released back into the journal. */\n readonly released: number;\n}\n\n/** A terminal sync failure surfaced after the retry policy was exhausted. */\nexport interface SyncFailure {\n readonly operation: \"push\" | \"pull\" | \"pokes\";\n readonly error: TransportError | StoreError | MutatorError;\n}\n\n/**\n * Options for {@link make}: the client and group ids, the mutator registry, and sync-loop tuning.\n */\nexport interface ClientEngineOptions {\n readonly clientId: string;\n readonly clientGroupId: string;\n readonly mutators: MutatorRegistry;\n /** Named queries: client-side subset factories for local rendering. */\n readonly queries?: Query.QueryRegistry;\n /** Sync-loop scheduling (push-on-mutate debounce, interval pull). */\n readonly syncLoop?: SyncLoopOptions;\n /** Retry/backoff policies for push, pull, and the poke stream. */\n readonly retry?: RetryOptions;\n /**\n * Capacity of the bounded change hub (#44). A stalled observer cannot make\n * the hub grow without limit: at capacity the hub drops the newest\n * view-changes, and the consumer collapses the resulting seq gap into a\n * lossless `Rebuild` (see {@link make}). Defaults to\n * {@link DEFAULT_CHANGE_HUB_CAPACITY}.\n */\n readonly changeHubCapacity?: number;\n /**\n * Most acknowledged-but-unpulled mutations the overlay keeps (#286). Defaults to 1024. The bound holds\n * strictly: no entry is released early. A push that takes the tail to half this bound starts a pull\n * ahead of the bound (#337), so a healthy transport never has to wait, with or without pokes. A push\n * larger than half the bound goes in chunks of half the bound, with a pull between them (#429), and a\n * chunk never takes the tail past the bound. A tail that is at or above the bound (for example one\n * persisted under a lowered bound) makes a push pull first; if that pull fails, the push fails and the\n * journal stays. An internal seam: a test lowers it to reach the bound with a few mutations. Must be a\n * positive integer; any other value is a defect when the engine is made.\n */\n readonly unpulledLimit?: number;\n /**\n * This build's schema version (#48), sent on every push and pull request. The\n * server's acceptor may reject an unsupported version; omit it for today's\n * version-less behaviour.\n */\n readonly schemaVersion?: string;\n /**\n * Invoked when the server rejects this build's `schemaVersion`\n * (`VersionNotSupportedError`) — the app's cue to prompt an update. It can run while a pull holds the\n * pull lock (#412), so it must not await `engine.push` or `engine.pull`: a pull between chunks waits on\n * that lock, and the callback would wait on the push. Fired **exactly once per occurrence**: a latch\n * dedupes a retry storm / repeated pulls so an ongoing rejection refires it only after the next request\n * succeeds. The pending journal is retained across the rejection (a version\n * rejection is a transport-level \"your build is obsolete\", not a per-mutation\n * verdict), so intents survive an eventual update. Also emitted as an\n * `UpdateNeeded` engine event.\n */\n readonly onUpdateNeeded?: (info: {\n readonly schemaVersion?: string;\n readonly message: string;\n }) => Effect.Effect<void>;\n /**\n * Declared secondary-index fields per collection (issue #113): `eq`/`In`/\n * range predicates on these fields resolve via an in-memory index instead\n * of a full scan (`Client.make` derives this from the Node/Collection\n * registry's `indexes`). Unset means no declared indexes.\n */\n readonly indexes?: Readonly<Record<string, ReadonlyArray<string>>>;\n /**\n * Auto-discover indexable fields from registered subsets' predicates (the\n * top-level `eq`/`In`/range conjuncts' fields) and index them, in addition\n * to any declared `indexes` — TanStack DB's `autoIndex: \"eager\"`. Defaults\n * to `false`: zero-config behaviour is identical to no indexing.\n */\n readonly autoIndex?: boolean;\n /**\n * Retention for terminal (acknowledged/rejected) entries in {@link\n * ClientEngine.mutationStates} (#116). Unset uses {@link\n * MutationState.DEFAULT_MAX_TERMINAL}.\n */\n readonly mutationStateRetention?: MutationState.RetentionOptions;\n}\n\n/**\n * Default bound for the change hub. Large enough that no realistic burst of\n * mutations/pulls fills it under normal consumption, so behaviour is identical\n * to the old unbounded hub until an observer genuinely stalls.\n */\nconst DEFAULT_CHANGE_HUB_CAPACITY = 1024;\n\n/**\n * A {@link ViewChange} tagged with a monotonic sequence number. The consumer\n * tracks the last seq it saw; a non-contiguous seq means the bounded hub\n * dropped one or more changes, which it collapses into a full `Rebuild`.\n */\ninterface SeqChange {\n readonly seq: number;\n readonly change: ViewChange;\n}\n\n/**\n * The built secondary indexes (#113) and the counters that guard installing one (#339). Immutable:\n * every change makes a new value, so a build can compare the value it started from against the\n * current one inside a single `Ref.modify`.\n */\ninterface IndexState {\n /** The built index per collection; absent means not built yet (or nothing to index). */\n readonly built: ReadonlyMap<string, Index.CollectionIndex>;\n /**\n * Per collection, bumped by every confirmed-row write to it (built or not) and by a field-set\n * change, which makes any index built against the old set stale.\n */\n readonly generations: ReadonlyMap<string, number>;\n /** Bumped by a `Clear`, which touches every collection. */\n readonly clears: number;\n}\n\n/**\n * Whether no confirmed-row write or field-set change touching `collection` happened between two\n * states, so an index built from rows read in `from` is still current in `to` (#339).\n */\nconst indexUnchangedFor = (collection: string, from: IndexState, to: IndexState): boolean =>\n from.clears === to.clears &&\n (from.generations.get(collection) ?? 0) === (to.generations.get(collection) ?? 0);\n\n/** Attempts an index build gets when confirmed-row writes keep racing it; then it full-scans (#339). */\nconst MAX_INDEX_BUILD_ATTEMPTS = 3;\n\n/**\n * The re-read each running engine built over a store has registered, keyed by the store object. A\n * direct store write (`Hydration.hydrate`) runs them through {@link resyncAttachedEngines}.\n */\nconst liveEngines = new WeakMap<ClientStore, Set<Effect.Effect<void>>>();\n\n/**\n * Tell every running {@link ClientEngine} built over `store` that the store was written directly\n * (`Hydration.hydrate`): each drops its built indexes and materialized view and reveals the\n * result. A store with no running engine is a no-op. Without this a direct write leaves an\n * engine's built indexes and view showing the old rows (#350).\n */\nexport const resyncAttachedEngines = (store: ClientStore): Effect.Effect<void> =>\n // Read the attached set when the effect runs, not when it is built: a caller\n // that builds this before its writes (`Effect.ensuring`) must still reach an\n // engine attached during them (#350).\n Effect.suspend(() =>\n Effect.forEach([...(liveEngines.get(store) ?? [])], (resync) => resync, { discard: true })\n );\n\n/** One row of a fallthrough read (ADR-0025). */\nexport type ReadRow = ReadResponse[\"rows\"][number];\n\n/** The pull counters {@link ClientEngine.pullCounts} reports (#426). */\nexport interface PullCounts {\n /** The number of the last pull to start; a pull is numbered as it takes the pull lock. */\n readonly started: number;\n /** The number of the last pull applied to the replica. */\n readonly applied: number;\n}\n\n/**\n * The client-side engine: the journal, the materialized view (confirmed rows plus the optimistic\n * overlay), subscriptions and the push/pull sync loop. Apps reach it through a `Client`.\n */\nexport interface ClientEngine {\n /**\n * Run a mutator optimistically and journal it for push. Args are\n * validated against the mutator's schema and journaled in encoded\n * (wire/persistence) form; handlers always receive decoded args.\n */\n readonly mutate: (\n mutator: string,\n args: unknown\n ) => Effect.Effect<void, MutatorError | StoreError>;\n /**\n * Run a mutator whose args are already in encoded (wire) form — the\n * entry point for remote surfaces (mirrors, devtools) forwarding\n * mutations over a carrier. Args are validated by decoding.\n */\n readonly mutateEncoded: (\n mutator: string,\n args: unknown\n ) => Effect.Effect<void, MutatorError | StoreError>;\n /**\n * Like {@link mutate}, but returns a {@link MutationHandle} whose\n * `acknowledged` effect resolves with the mutation's authoritative outcome\n * (applied or permanently rejected). Validates and journals identically to\n * `mutate`; the returned handle lets a caller await the backend's verdict.\n */\n readonly mutateWithAck: (\n mutator: string,\n args: unknown\n ) => Effect.Effect<MutationHandle, MutatorError | StoreError>;\n /**\n * The client half of an enhanced form submit (ADR-0030 #215 §4): apply the\n * mutator's local handler to the overlay under the form client's id,\n * **without journaling it**, because the form action is its delivery and a\n * push would apply it twice. Settle the returned {@link FormSubmission} on\n * the action's receipt. The optimistic effect is released by the pull that\n * covers the form client, never by the receipt itself.\n *\n * The entry holds a place in the unpulled tail's bound from the start, so\n * an acknowledgement never takes the tail past it. When the tail has no\n * room, the entry is overlaid without one, and an acknowledgement drops it\n * instead of parking it; the pull it signals then shows the confirmed rows.\n * The entry lives in memory only: a reload before the receipt loses it, and\n * the next pull shows the server's state.\n */\n readonly beginFormMutation: (\n form: FormClient,\n mutator: string,\n args: unknown\n ) => Effect.Effect<FormSubmission, MutatorError | StoreError>;\n /**\n * {@link beginFormMutation} for args already in encoded (wire) form, as a\n * mirror forwards them (#536): validated by decoding against the Mutation's\n * args schema, the counterpart of {@link mutateEncoded}.\n */\n readonly beginFormMutationEncoded: ClientEngine[\"beginFormMutation\"];\n /**\n * Mutation lifecycle events: a `journaled` event for every journaled\n * mutation, then `acknowledged` or `rejected` once the backend settles it.\n * The first outcome the client observes is the one emitted: a settled\n * mutation emits no further settle event (#364).\n */\n readonly mutationEvents: Stream.Stream<MutationEvent>;\n /**\n * A keyed, reactive mutation-state map (#116) — TanStack Query's\n * `useMutationState` analogue: every journaled mutation's current lifecycle\n * state (`pending` → `acknowledged` | `rejected`), keyed by `mutationId`.\n * Seeded from the journal at boot (so a reload shows pending intents) and\n * folded forward as mutations are journaled and settled, regardless of\n * whether they were journaled via `mutate`, `mutateEncoded`, or\n * `mutateWithAck`. Emits the current map immediately, then on every change\n * ({@link SubscriptionRef.changes} semantics). Terminal entries are\n * retained only up to `mutationStateRetention` — the journal, not this map,\n * is the durable source of truth for pending mutations.\n */\n readonly mutationStates: Stream.Stream<MutationState.MutationStateMap>;\n /**\n * The unified sync-lifecycle event stream (#45): mutation, push, pull, poke,\n * and view-rebuild events from one hub. {@link mutationEvents} is a filtered\n * projection of this stream. Consumed read-only by `EngineIntrospection`.\n */\n readonly engineEvents: Stream.Stream<EngineEvent>;\n /**\n * A read-only snapshot of the engine's active subsets — the raw subscriptions\n * plus every named subscription resolved through its local subset factory.\n * The introspection seam (`Introspection.ts`); does not touch private state\n * from outside.\n */\n readonly activeSubscriptions: Effect.Effect<ReadonlyArray<Subset.Subset>>;\n /** Register/replace the engine's subscriptions (synced on next pull). */\n readonly subscribe: (subset: Subset.Subset) => Effect.Effect<void>;\n readonly unsubscribe: (subset: Subset.Subset) => Effect.Effect<void>;\n /**\n * Seed the local view with confirmed rows before any transport call, so\n * observers render them synchronously (the hydration path — pair with\n * `Hydration.hydrate` for a full store, or use `seed` for a targeted warm-up).\n * Writes the rows via the store and publishes one change scoped to exactly the\n * seeded collections.\n *\n * The `version`s must be genuine backend versions for CVR diffing to converge\n * cheaply on the next pull; self-invented versions are safe but degrade to the\n * reset path (the server sends a `Clear` + full puts). See `Hydration.ts`.\n */\n readonly seed: (\n rows: ReadonlyArray<{\n readonly collection: string;\n readonly id: RowId;\n readonly version: RowVersion;\n readonly value: unknown;\n }>\n ) => Effect.Effect<void, StoreError>;\n /**\n * Drop every confirmed row, then the materialized view and the built indexes with them, and\n * reveal the empty state (devtools' `clearStore`). The journal, cookie and subscriptions are\n * untouched. Use this rather than `ClientStore.clearRows` on a running engine: a direct store\n * write leaves the view and indexes showing the cleared rows (#350).\n */\n readonly clearRows: Effect.Effect<void, StoreError>;\n /**\n * Prefetch a subset: `subscribe` to it, and if it currently yields no local\n * rows, `pull` once so the rows are present before the caller proceeds.\n * Concurrent calls for the same subset dedupe — at most one pull runs per\n * `Subset.hash` in flight — so a burst of renders that all need the same data\n * triggers a single network round-trip.\n */\n readonly ensureSubset: (\n subset: Subset.Subset\n ) => Effect.Effect<void, TransportError | StoreError | MutatorError | VersionNotSupportedError>;\n /**\n * Subscribe a named query (Query.ts): the server resolves it to the\n * authoritative subset it syncs; the client renders it locally with its own\n * subset factory. Synced on the next pull.\n */\n readonly subscribeQuery: (name: string, args: unknown) => Effect.Effect<void, QueryError>;\n readonly unsubscribeQuery: (name: string, args: unknown) => Effect.Effect<void, QueryError>;\n /** Query a named query's local result (confirmed + overlay). */\n readonly queryNamed: (\n name: string,\n args: unknown\n ) => Effect.Effect<ReadonlyArray<LocalRow>, StoreError | MutatorError | QueryError>;\n /** Live named query: re-emits on every local change. */\n readonly observeNamed: (\n name: string,\n args: unknown\n ) => Stream.Stream<ReadonlyArray<LocalRow>, StoreError | MutatorError | QueryError>;\n /**\n * Query the current local view (confirmed + overlay). A\n * {@link Subset.TypedSubset} refines the rows to its row type; a plain\n * `Subset` keeps returning untyped {@link LocalRow}s.\n */\n readonly query: {\n <A>(\n subset: Subset.TypedSubset<A>\n ): Effect.Effect<ReadonlyArray<TypedRow<A>>, StoreError | MutatorError>;\n (subset: Subset.Subset): Effect.Effect<ReadonlyArray<LocalRow>, StoreError | MutatorError>;\n };\n /**\n * Live query: emits the result now and after every local change. With a\n * {@link ObserveOptions.select} it emits the projection instead, re-emitting\n * only when the projected value changes. A {@link Subset.TypedSubset} refines\n * the row type; a plain `Subset` keeps returning untyped {@link LocalRow}s.\n */\n readonly observe: {\n <A, B>(\n subset: Subset.TypedSubset<A>,\n options: ObserveOptions<TypedRow<A>, B>\n ): Stream.Stream<B, StoreError | MutatorError>;\n <B>(\n subset: Subset.Subset,\n options: ObserveOptions<LocalRow, B>\n ): Stream.Stream<B, StoreError | MutatorError>;\n <A>(\n subset: Subset.TypedSubset<A>\n ): Stream.Stream<ReadonlyArray<TypedRow<A>>, StoreError | MutatorError>;\n (subset: Subset.Subset): Stream.Stream<ReadonlyArray<LocalRow>, StoreError | MutatorError>;\n };\n /**\n * Reactive window retargeting (#133): like {@link observe}, but returns a\n * {@link WindowObservation} whose `retarget` widens/advances the SAME open\n * observation's `limit`/`cursor` — reusing `LiveView`'s maintained order\n * instead of requiring a fresh `observe(widerSubset)` (a re-subscribe and a\n * rebuild from scratch). The Svelte `useConnection` \"load more\" paging hook\n * is the reference consumer. Scoped: the underlying change-hub subscription\n * is released (and `retarget` becomes inert) when the scope closes — pair\n * with `Effect.scoped` or a long-lived component scope, the same as\n * {@link runSync}.\n */\n readonly observeWindow: (\n subset: Subset.Subset\n ) => Effect.Effect<WindowObservation, StoreError | MutatorError, Scope.Scope>;\n /**\n * Row-level deltas of a subset's live window (#115): `enter`/`exit` mark\n * predicate/limit-boundary crossings, `update` a same-membership value\n * change, `move` a same-membership/same-value position change (#112's\n * stable position keys) — batched per view-step (one array per\n * {@link ViewChange} application, mirroring `observe`'s one-page-per-step).\n * A confirmed-row pull `Patch` and a plain local mutation (#109 tracks a\n * mutator's local handler directly onto the cached overlay and publishes\n * exactly what it did) both diff precisely; `Rebuild`/seq-gap collapse — a\n * pull racing a still-pending mutation, an unknown mutator, a `Clear` —\n * emit a `reset` marker + fresh `enter`s instead of a diff, since the\n * overlay could have shifted any row (the same conservative fallback\n * `observe`'s page already takes). `LiveView.put`/`del` already decide\n * predicate/window membership per row; this surfaces that decision instead\n * of discarding it and rescanning two pages.\n *\n * `enter`/`update`/`move` carry the row's stable `position` (a\n * `LiveView.PositionedRow`'s `FractionalIndex` key): a row repositioned by\n * a neighbor's insert/delete without its own value changing is no longer\n * indistinguishable from \"unchanged\" — it emits `move` with its new and\n * previous position, so a keyed-list consumer re-sorts without diffing\n * pages (`docs/observing-row-changes.md`).\n */\n readonly observeChanges: {\n <A>(\n subset: Subset.TypedSubset<A>,\n options?: ObserveChangesOptions\n ): Stream.Stream<ReadonlyArray<RowChange.RowChange<TypedRow<A>>>, StoreError | MutatorError>;\n (\n subset: Subset.Subset,\n options?: ObserveChangesOptions\n ): Stream.Stream<ReadonlyArray<RowChange.RowChange<LocalRow>>, StoreError | MutatorError>;\n };\n /**\n * One-shot aggregate over the current local view (confirmed + overlay):\n * `query` the subset, then fold it with {@link Aggregate.compute}.\n *\n * Local tier only — the aggregate sees exactly the rows this client has\n * synced (a subset's window included); a server-evaluated tier that folds\n * the whole collection is explicit future work.\n */\n readonly queryAggregate: (\n subset: Subset.Subset,\n agg: Aggregate.Aggregate\n ) => Effect.Effect<Aggregate.AggregateValue, StoreError | MutatorError>;\n /** One-shot grouped aggregate over the current local view (see {@link queryAggregate}). */\n readonly queryAggregateGrouped: (\n subset: Subset.Subset,\n agg: Aggregate.Aggregate,\n groupBy: string\n ) => Effect.Effect<Record<string, Aggregate.AggregateValue>, StoreError | MutatorError>;\n /**\n * Live aggregate over a subset: emits now and after every local change.\n * For an unwindowed subset (no `limit`/`cursor`, the common case), the fold\n * is maintained incrementally from `Patch` row deltas rather than re-scanned\n * (#110); a windowed subset, or a change too large to diff (`Rebuild`),\n * refolds the subset from scratch. Deduped — a change that leaves the\n * aggregate value unchanged does not re-emit. Local tier only, as\n * {@link queryAggregate}.\n */\n readonly observeAggregate: (\n subset: Subset.Subset,\n agg: Aggregate.Aggregate\n ) => Stream.Stream<Aggregate.AggregateValue, StoreError | MutatorError>;\n /** Live grouped aggregate; deduped by structural equality of the record (see {@link observeAggregate}). */\n readonly observeAggregateGrouped: (\n subset: Subset.Subset,\n agg: Aggregate.Aggregate,\n groupBy: string\n ) => Stream.Stream<Record<string, Aggregate.AggregateValue>, StoreError | MutatorError>;\n /**\n * Push pending mutations now. The journal goes out in chunks of at most half the unpulled bound, with\n * a pull before each chunk after the first (#429), so an oversized journal does not take the\n * acknowledged tail past the bound on a healthy transport. One rule covers every stop: when a pull\n * between chunks fails or is refused, the push fails with a transient `TransportError` (a version\n * rejection by that pull included), and the unsent mutations stay journaled for the next push. A chunk\n * that fails stops the push the same way. Overlapping calls share the bound: each chunk reserves its room\n * before it is sent, so the tail stays within the bound across concurrent calls too. Do not await `pull`\n * or `push` inside `onUpdateNeeded`: a refused pull runs the callback under the pull lock, so an awaited\n * pull, or a push that has to pull first, waits on itself. Fails with\n * `VersionNotSupportedError` when the server rejects this build's `schemaVersion` (#48) — the journal\n * is retained, and `onUpdateNeeded` fires (deduped) as a side effect.\n */\n readonly push: Effect.Effect<void, TransportError | StoreError | VersionNotSupportedError>;\n /**\n * Compact the unpushed tail of the journal (#117's pacing strategies:\n * debounce/throttle/coalesce drop a superseded entry) and **renumber the\n * survivors so the client's mutation ids stay contiguous** (#249): the\n * backends reject an id gap (ADR-0008), so a bare drop would leave the\n * journal undrainable. The survivors take consecutive ids, in order,\n * continuing from the last entry that may already have been sent (or from\n * the first pending id), and the id counter is rewound to match.\n *\n * Only ever touches entries no push has claimed: it does nothing while a\n * push is in flight, and never drops or renumbers an entry at or below the\n * store's sent watermark (every id any push attempt, successful or not,\n * has included). An entry a push may have sent keeps its id forever — the\n * hard boundary of ADR-0008's exactly-once contract. It is skipped rather\n * than waited for: a caller that cannot compact just leaves one extra,\n * still-contiguous entry that the push delivers.\n *\n * Runs under the journal lock, so it is atomic with respect to `mutate`\n * (an id being allocated is never renumbered under it) and to a push's\n * claim of the pending set. Returns what it did: the `dropped` ids and the\n * `renumbered` `{ from, to }` moves. A caller holding ids for entries it\n * did not drop must apply the moves (`Paced` does) — an id it kept may now\n * name a different entry. `mutateWithAck` deferreds and `mutationStates`\n * follow the moves automatically; a dropped entry's deferred is\n * interrupted.\n */\n readonly dropIfPending: (\n mutationIds: ReadonlyArray<number>\n ) => Effect.Effect<CompactionResult, StoreError>;\n /**\n * Adopt an identity, applying the boundary's transition rule (#212,\n * CONTEXT.md \"Identity boundary\") — the same rule the store applies on\n * open, so boot and runtime cannot disagree:\n *\n * - **Unchanged** — the same principal; the replica is untouched.\n * - **Upgrade** — {@link Identity.anonymous} → signed in: the warm replica,\n * its subscriptions and its journal all survive. Public rows are a subset\n * of what the new identity may read.\n * - **Reset** — every other change, sign-out included. Unpushed journal\n * entries are quarantined under the **superseded** fingerprint; confirmed\n * rows, the pull cookie, and every registered subscription are dropped.\n *\n * A quarantine already held under the adopted fingerprint is released back\n * into the journal on every transition, `Unchanged` included: re-signing in\n * is what makes that identity's own unpushed writes pushable again. No\n * transition ever *discards* a quarantine — see\n * {@link ClientEngine.discardQuarantine}.\n *\n * Does not wait for an in-flight push. Quarantining preserves mutation ids\n * exactly, so an entry that was already on the wire is at worst\n * acknowledged and skipped by the backend's exactly-once ledger when it is\n * released, never applied twice.\n */\n readonly reset: (identity: Identity.Fingerprint) => Effect.Effect<ResetOutcome, StoreError>;\n /** The fingerprint this replica is stamped with, if any (see {@link reset}). */\n readonly identity: Effect.Effect<Identity.Fingerprint | undefined, StoreError>;\n /** Fingerprints currently holding quarantined write intents. */\n readonly quarantines: Effect.Effect<ReadonlyArray<Identity.Fingerprint>, StoreError>;\n /** The entries quarantined under a fingerprint, in causal order. */\n readonly quarantinedMutations: (\n identity: Identity.Fingerprint\n ) => Effect.Effect<ReadonlyArray<Mutation>, StoreError>;\n /**\n * Destroy a quarantine. The **only** path that discards a superseded\n * identity's unpushed write intents, and deliberately an explicit call —\n * no reset and no boot triggers it. Holding a departed user's intents on\n * the device indefinitely is the deliberate trade the quarantine makes, so\n * an app that needs them gone has to say so.\n */\n readonly discardQuarantine: (identity: Identity.Fingerprint) => Effect.Effect<void, StoreError>;\n /**\n * Pull a patch now and rebase. Fails with `VersionNotSupportedError` when the\n * server rejects this build's `schemaVersion` (#48); see {@link push}.\n *\n * Pulls run one at a time. A call made while a pull is in flight waits for it,\n * and resolves once a pull that started after the call has been applied, so\n * the rows and cookie it sees are never older than when it was made. A call\n * whose own pull fails fails with that error, and a call queued behind it then\n * pulls for itself.\n */\n readonly pull: Effect.Effect<\n void,\n TransportError | StoreError | MutatorError | VersionNotSupportedError\n >;\n /**\n * The pull counters, read-only (#426): `started` numbers the pulls that have\n * begun, `applied` the last pull whose rows and cookie are in the replica. A\n * registration made when `started` reads `n` is pulled once `applied`\n * exceeds `n`: a pull already in flight at that moment may predate it.\n */\n readonly pullCounts: Effect.Effect<PullCounts>;\n /**\n * Point-in-time fallthrough read over the transport (ADR-0025): the\n * server evaluates the subsets under its auth filters, with no CVR\n * involvement; results are returned to the caller and **never** written\n * to the local store. Present only when the transport offers `read`.\n */\n readonly readThrough?: (\n subsets: ReadonlyArray<Subset.Subset>\n ) => Effect.Effect<ReadonlyArray<ReadRow>, TransportError | VersionNotSupportedError>;\n /** Run the sync loop: pull on poke; push+pull on reconnect. */\n readonly runSync: Effect.Effect<void, TransportError | StoreError | MutatorError, Scope.Scope>;\n /**\n * Terminal sync failures surfaced after the retry policy is exhausted — so\n * bindings can show a \"sync degraded\" state. Also counted in\n * `Telemetry.syncFailuresTotal`.\n */\n readonly syncFailures: Stream.Stream<SyncFailure>;\n}\n\n/**\n * The {@link ClientEngine} service, for integrations that take the engine from context\n * (`JsonApiSync.start`).\n */\nexport const ClientEngine = Context.Service<ClientEngine>(\"@thomasfosterau/legation/ClientEngine\");\n\n/**\n * Build a {@link ClientEngine} over the `ClientStore` and `ClientTransport` in context; the engine\n * lives as long as the scope.\n */\nexport const make = (\n options: ClientEngineOptions\n): Effect.Effect<ClientEngine, never, ClientStore | ClientTransport | Scope.Scope> =>\n Effect.gen(function* () {\n const unpulledLimit = options.unpulledLimit ?? UNPULLED_LIMIT;\n if (!Number.isInteger(unpulledLimit) || unpulledLimit < 1) {\n return yield* Effect.die(\n new Error(`ClientEngine: unpulledLimit must be a positive integer, got ${unpulledLimit}`)\n );\n }\n // The pull-ahead threshold (#337), and the most mutations one push request carries (#429). A push\n // that takes the tail to this many starts a pull ahead of the bound; a push larger than this goes\n // in chunks of this size, with a pull between them.\n const pullAheadAt = Math.ceil(unpulledLimit / 2);\n const store = yield* ClientStore;\n const transport = yield* ClientTransport;\n // The keyed mutation-state map (#116), seeded from the journal so a\n // reload shows pending intents before any push/pull runs. A store read\n // failure here is not fatal to engine construction (mirrors\n // `sampleJournalDepth`'s tolerance elsewhere): the map starts empty and\n // catches up as mutations are journaled.\n const initialPending = yield* store.pendingMutations.pipe(\n Effect.catchTag(\"StoreError\", () => Effect.succeed<ReadonlyArray<Mutation>>([]))\n );\n // Entries journaled by an earlier session may already have been pushed (and\n // a store written before the sent watermark existed has no record of it),\n // so freeze them: paced compaction (#249) only ever renumbers entries this\n // session journaled itself.\n yield* freezePending(store).pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n \"ClientEngine: could not freeze the persisted journal at boot; paced compaction may renumber entries an earlier session pushed\",\n { error }\n )\n )\n );\n const mutationStates = yield* SubscriptionRef.make(MutationState.seed(initialPending));\n // Track journal entries the map does not know yet as pending (#358): entries a direct store\n // write appended under this engine, or entries whose boot-time read failed (`initialPending`\n // falls back to none). An entry already tracked keeps its phase. Runs on every reload and on\n // every push claim, so an untracked entry is tracked before the push that sends it can settle it.\n // Each adopted entry announces `MutationJournaled` once, as a local `journal` does, so the\n // outcome that follows it (`MutationAcknowledged` / `MutationRejected`) has its opening event.\n // Callers hold `overlayLock`, so the journal cannot change between the read and the fold. The\n // gate stays a read: `SubscriptionRef.modify` publishes even when nothing moved, so a no-op\n // adoption (the common case on every push) must not reach it.\n const adoptPending = (pending: ReadonlyArray<Mutation>): Effect.Effect<void> =>\n Effect.gen(function* () {\n if (!MutationState.hasUntracked(yield* SubscriptionRef.get(mutationStates), pending))\n return;\n const adopted = yield* SubscriptionRef.modify(mutationStates, (map) =>\n MutationState.adopt(map, pending)\n );\n for (const mutation of adopted) yield* emitEvent(mutation.mutationId, \"journaled\");\n });\n // #212: with the identity boundary on, the sync-protocol client identity\n // is scoped to the principal. It has to be: mutation ids are a per-client\n // sequence the backend requires to be contiguous (ADR-0008's exactly-once\n // ledger), so a second principal continuing the first's numbering pushes a\n // gap the backend rejects, and restarting it collides with ids the first\n // already had applied. A derived id gives each principal its own sequence\n // — and gives a returning principal back exactly the sequence they left,\n // so quarantined entries released later are still contiguous under the\n // client that authored them.\n //\n // Derived, not stored, so it survives a reload with no extra durable\n // state; and left exactly as configured when no identity is stamped, so\n // an app that does not use the boundary sees no change at all.\n const clientIdFor = (identity: Identity.Fingerprint | undefined): string =>\n identity === undefined\n ? options.clientId\n : `${options.clientId}#${Identity.keySegment(identity)}`;\n const clientIdRef = yield* Ref.make(\n clientIdFor(\n yield* store.getIdentity.pipe(\n Effect.catchTag(\"StoreError\", () =>\n Effect.succeed<Identity.Fingerprint | undefined>(undefined)\n )\n )\n )\n );\n const currentClientId: Effect.Effect<string> = Ref.get(clientIdRef);\n const subscriptions = yield* Ref.make<ReadonlyArray<Subset.Subset>>([]);\n // In-flight `ensureSubset` pulls, keyed by `Subset.hash`, so concurrent\n // prefetches of the same subset share one pull instead of racing N of them.\n const ensurePulls = yield* Ref.make(\n new Map<\n string,\n Deferred.Deferred<\n void,\n TransportError | StoreError | MutatorError | VersionNotSupportedError\n >\n >()\n );\n const namedSubs = yield* Ref.make<\n ReadonlyArray<{ readonly name: string; readonly argsEncoded: unknown; readonly key: string }>\n >([]);\n // Bounded, dropping change hub (#44). A stalled observer holds messages in\n // the shared hub; at capacity the hub drops the newest `SeqChange`s rather\n // than growing without limit. Each change carries a monotonic `seq`, so a\n // consumer detects a drop as a seq gap and collapses it into a `Rebuild`\n // that subsumes the dropped `Patch`es — lossless under pressure, identical\n // to the old hub under none (contiguous seqs → same incremental path).\n const changes = yield* Effect.acquireRelease(\n PubSub.dropping<SeqChange>({\n capacity: options.changeHubCapacity ?? DEFAULT_CHANGE_HUB_CAPACITY,\n }),\n (hub) => PubSub.shutdown(hub)\n );\n // Monotonic sequence stamped on every published change. The store mutation\n // a change describes always completes before its seq is assigned here, so\n // \"seqRef == R\" implies the store reflects every change with seq ≤ R — the\n // invariant the consumer's gap-collapse relies on to skip stale buffered\n // changes after a Rebuild.\n const changeSeq = yield* Ref.make(0);\n // The single unified event hub (#45): every sync-lifecycle event flows\n // through here, and `mutationEvents` (#36) is a filtered projection of it.\n // Unbounded for the same reason #44 kept `mutationEventsHub` unbounded —\n // lifecycle events are low-volume, consumer-driven, and lossless (they are\n // observability, not reconstructable via pull).\n const engineEventsHub = yield* Effect.acquireRelease(PubSub.unbounded<EngineEvent>(), (hub) =>\n PubSub.shutdown(hub)\n );\n const emitEngineEvent = (event: EngineEvent): Effect.Effect<void> =>\n Effect.asVoid(PubSub.publish(engineEventsHub, event));\n // A Rebuild change is a view rebuild; carry its scoped collections (#39).\n const viewRebuiltEvent = (change: ViewChange): Effect.Effect<void> =>\n change._tag === \"Rebuild\"\n ? emitEngineEvent({\n _tag: \"ViewRebuilt\",\n ...(change.collections !== undefined ? { collections: [...change.collections] } : {}),\n })\n : Effect.void;\n const publishChange = (change: ViewChange): Effect.Effect<void> =>\n Ref.updateAndGet(changeSeq, (n) => n + 1).pipe(\n Effect.flatMap((seq) => PubSub.publish(changes, { seq, change })),\n Effect.andThen(viewRebuiltEvent(change)),\n Effect.asVoid\n );\n\n // Fires whenever a mutation is journaled; the sync loop debounces it into\n // an auto-push when `syncLoop.pushDebounce` is set.\n const pushTrigger = yield* Effect.acquireRelease(PubSub.unbounded<void>(), (hub) =>\n PubSub.shutdown(hub)\n );\n const signalPush = Effect.asVoid(PubSub.publish(pushTrigger, undefined));\n\n // Terminal sync failures (retry exhausted) surfaced to bindings + metrics.\n const failures = yield* Effect.acquireRelease(PubSub.unbounded<SyncFailure>(), (hub) =>\n PubSub.shutdown(hub)\n );\n const surfaceFailure = (\n operation: SyncFailure[\"operation\"],\n error: SyncFailure[\"error\"]\n ): Effect.Effect<void> =>\n Metric.update(Telemetry.syncFailuresTotal, 1).pipe(\n Effect.andThen(PubSub.publish(failures, { operation, error })),\n Effect.asVoid\n );\n\n // Per-mutation outcome deferreds registered by `mutateWithAck`, keyed by\n // mutation id. `mutate`/`mutateEncoded` never register one, so their path\n // stays allocation-free.\n const acks = yield* Ref.make(new Map<number, Deferred.Deferred<MutationOutcome>>());\n // Count of `push` calls currently between reading their pending snapshot\n // and settling it (ack/reject) — i.e. mutations that MAY already be in\n // flight to the backend. `dropIfPending` (#117) refuses to compact any\n // entry while this is nonzero: a pending id it cannot prove is still\n // untouched by a push is left alone rather than risked (ADR-0008's hard\n // boundary — never mutate or reorder a pushed entry). Retries re-read\n // `pendingMutations` fresh each attempt, so a drop between attempts is\n // always safe; a counter (not a flag) covers overlapping pushes.\n const pushInFlight = yield* Ref.make(0);\n // Emit a mutation-lifecycle event onto the unified hub as its tagged\n // variant; `mutationEvents` projects these four tags back to `phase`s.\n const emitEvent = (\n mutationId: number,\n phase: MutationEvent[\"phase\"],\n reason?: string\n ): Effect.Effect<void> =>\n currentClientId.pipe(\n Effect.flatMap((clientId) => {\n switch (phase) {\n case \"journaled\":\n return emitEngineEvent({ _tag: \"MutationJournaled\", clientId, mutationId });\n case \"acknowledged\":\n return emitEngineEvent({ _tag: \"MutationAcknowledged\", clientId, mutationId });\n case \"rejected\":\n return emitEngineEvent({\n _tag: \"MutationRejected\",\n clientId,\n mutationId,\n reason: reason ?? \"\",\n });\n case \"dropped\":\n return emitEngineEvent({ _tag: \"MutationDropped\", clientId, mutationId });\n }\n })\n );\n // Project the four mutation variants back to the #36 `MutationEvent` shape.\n const toMutationEvent = (event: EngineEvent): MutationEvent | undefined => {\n switch (event._tag) {\n case \"MutationJournaled\":\n return { clientId: event.clientId, mutationId: event.mutationId, phase: \"journaled\" };\n case \"MutationAcknowledged\":\n return { clientId: event.clientId, mutationId: event.mutationId, phase: \"acknowledged\" };\n case \"MutationRejected\":\n return {\n clientId: event.clientId,\n mutationId: event.mutationId,\n phase: \"rejected\",\n reason: event.reason,\n };\n case \"MutationDropped\":\n return { clientId: event.clientId, mutationId: event.mutationId, phase: \"dropped\" };\n default:\n return undefined;\n }\n };\n // Sample the journal-depth gauge from the current pending count. Called on\n // every append (a new pending mutation), acknowledge (a trim) and paced\n // compaction, so it uses the store's count, which reads no pending bodies\n // (#260), rather than loading the whole journal to take its length.\n const sampleJournalDepth: Effect.Effect<void> = store.pendingCount.pipe(\n Effect.flatMap((count) => Metric.update(Telemetry.journalDepth, count)),\n Effect.catch(() => Effect.void)\n );\n // Time an effect and record its wall-clock duration (ms) as the rebase\n // histogram — wraps the actual overlay replay (cache misses only).\n const timedRebase = <A, E>(effect: Effect.Effect<A, E>): Effect.Effect<A, E> =>\n Effect.gen(function* () {\n const start = yield* Clock.currentTimeMillis;\n const result = yield* effect;\n const elapsed = (yield* Clock.currentTimeMillis) - start;\n yield* Metric.update(Telemetry.rebaseDurationMs, elapsed);\n return result;\n });\n const forgetAck = (id: number): Effect.Effect<void> =>\n Ref.update(acks, (map) => {\n const next = new Map(map);\n next.delete(id);\n return next;\n });\n // Interrupt any still-pending outcome deferreds on scope close, so a caller\n // awaiting `acknowledged` never hangs and nothing leaks.\n yield* Effect.addFinalizer(() =>\n Ref.get(acks).pipe(\n Effect.flatMap((map) => Effect.forEach([...map.values()], Deferred.interrupt)),\n Effect.asVoid\n )\n );\n\n // Shared materialized overlay: `materialize` replays the whole journal, so\n // without a cache K observers of one change cost K full replays. Cache the\n // overlay and invalidate it whenever the journal or confirmed rows shift\n // (append/trim/pull), so one change costs one replay. The semaphore makes\n // the fill single-flight: concurrent observers waiting on the same change\n // recompute once, not once each.\n const overlayCache = yield* Ref.make<Map<string, Map<RowId, LocalRow>> | undefined>(undefined);\n const overlayLock = yield* Semaphore.make(1);\n // Invalidation must serialize with the tracked-write path below (#109):\n // that path holds the permit for its whole read-modify-write of the\n // cache, so an invalidation racing it outside the lock could be clobbered\n // by a stale `Ref.set` once the tracked write finishes. Going through the\n // same semaphore makes \"invalidate\" and \"read cache, mutate, write cache\n // back\" mutually exclusive, so whichever runs first is fully visible to\n // the other. Callers inside a block that already holds the permit (the\n // tracked-write path's own failure fallback) must use `Ref.set` directly\n // to avoid deadlocking on the non-reentrant semaphore.\n const invalidateOverlay = Semaphore.withPermit(overlayLock, Ref.set(overlayCache, undefined));\n\n // The acknowledged-but-unpulled tail (#286, ADR-0008). A push trims the\n // entries the backend applied from the journal, so they are never sent\n // again, but parks them here, oldest first, so the overlay keeps showing\n // their effects until a pull's `lastMutationIds` covers them. That pull's\n // patch carries the effects, and the rebase reveals them in one change.\n // The store holds the tail too (#336), so a restart before the pull that\n // reports it still shows its effects. This is the in-memory copy: seeded\n // from the store at boot, written through under the same lock as every\n // change, and reloaded when the store is written directly. Written only\n // under `overlayLock`, so the tail and the journal read together form one\n // snapshot.\n const bootTail = yield* store.unpulled.pipe(\n Effect.map((entries) => ({ entries, stale: false })),\n Effect.catch((error) =>\n Effect.logWarning(\n \"ClientEngine: could not read the unpulled tail at boot; the copy is re-read from the store before its next use\",\n { error }\n ).pipe(\n Effect.as<{ readonly entries: ReadonlyArray<Mutation>; readonly stale: boolean }>({\n entries: [],\n stale: true,\n })\n )\n )\n );\n const unpulled = yield* Ref.make<ReadonlyArray<Mutation>>(bootTail.entries);\n // Enhanced form submissions awaiting their action's receipt (ADR-0030 #215\n // §4): overlaid, never journaled. Written only under `overlayLock`.\n const formsInFlight = yield* Ref.make<ReadonlyArray<Mutation>>([]);\n // Set while the copy may differ from the store: its boot read failed, or a reload did. The\n // next reader under `overlayLock` re-reads the store first, so a failed read cannot leave the\n // copy empty for good (#387).\n const unpulledStale = yield* Ref.make(bootTail.stale);\n // The tail as the store holds it, for a caller that holds `overlayLock`.\n const tailLocked: Effect.Effect<ReadonlyArray<Mutation>, StoreError> = Effect.gen(function* () {\n if (yield* Ref.get(unpulledStale)) {\n yield* Ref.set(unpulled, yield* store.unpulled);\n yield* Ref.set(unpulledStale, false);\n yield* Ref.set(overlayCache, undefined);\n }\n return yield* Ref.get(unpulled);\n });\n // The journal the overlay replays: the unpulled tail, the enhanced form\n // submissions awaiting their receipt, then the pending\n // journal. The caller holds `overlayLock`.\n const overlayJournalLocked: Effect.Effect<ReadonlyArray<Mutation>, StoreError> = Effect.gen(\n function* () {\n const tail = yield* tailLocked;\n const forms = yield* Ref.get(formsInFlight);\n return [...tail, ...forms, ...(yield* store.pendingMutations)];\n }\n );\n // The same snapshot, for a caller that does not already hold the lock.\n const overlayJournal = Semaphore.withPermit(overlayLock, overlayJournalLocked);\n\n // Ensure `view` holds a live, mutable map for `collection`, seeding it\n // lazily from confirmed rows the first time it's touched. Shared by\n // `computeOverlay` (fresh materialization, replayed sequentially so no\n // collection is seeded twice) and the tracked-write path (incremental\n // mutation onto the persisted cache) — both agree on what \"the\n // collection's rows\" means, and once a collection is seeded into a\n // cache-backed `view` it stays seeded across calls.\n const ensureCollectionMap = (\n view: Map<string, Map<RowId, LocalRow>>,\n collection: string\n ): Effect.Effect<Map<RowId, LocalRow>, StoreError> =>\n Effect.gen(function* () {\n const existing = view.get(collection);\n if (existing !== undefined) return existing;\n const created = new Map<RowId, LocalRow>();\n for (const row of yield* store.listRows(collection)) {\n created.set(row.id, { id: row.id, value: row.value });\n }\n view.set(collection, created);\n return created;\n });\n\n // A `LocalWriter` over `view`'s per-collection maps: `put`/`del` mutate\n // in place (through `ensureCollectionMap`'s lazy seeding) and, when\n // given, report each write via `onPut`/`onDel` — the one seam\n // `replayMutations`' plain replay and `trackedWriter`'s op-recording\n // variant (#109) both build on, rather than duplicating the put/del/get\n // wiring.\n const viewWriter = (\n view: Map<string, Map<RowId, LocalRow>>,\n onPut?: (collection: string, id: RowId, value: unknown) => void,\n onDel?: (collection: string, id: RowId) => void\n ): LocalWriter => ({\n put: (collection, id, value) =>\n ensureCollectionMap(view, collection).pipe(\n Effect.map((rows) => {\n rows.set(id, { id, value });\n onPut?.(collection, id, value);\n })\n ),\n del: (collection, id) =>\n ensureCollectionMap(view, collection).pipe(\n Effect.map((rows) => {\n rows.delete(id);\n onDel?.(collection, id);\n })\n ),\n get: (collection, id) =>\n ensureCollectionMap(view, collection).pipe(Effect.map((rows) => rows.get(id)?.value)),\n });\n\n // Replay `mutations` (in journal order) onto `view`, mutating its\n // per-collection maps in place. Journal args are encoded (they survive\n // persistence and the wire), so decode before replay. Shared by\n // `computeOverlay` (replays every currently-pending mutation) and the\n // tracked-write cold-cache path (replays every *other* pending mutation\n // before applying the new one on top via `trackedWriter` — passing the\n // pre-append snapshot avoids replaying the new mutation twice, since by\n // the time that path runs it has already been appended to the store).\n const replayMutations = (\n view: Map<string, Map<RowId, LocalRow>>,\n mutations: ReadonlyArray<Mutation>\n ): Effect.Effect<void, StoreError | MutatorError> =>\n Effect.gen(function* () {\n const writer = viewWriter(view);\n for (const mutation of mutations) {\n const definition = options.mutators.mutators.get(mutation.mutator);\n const handler = options.mutators.handlers.get(mutation.mutator);\n if (definition === undefined || handler === undefined) {\n return yield* new MutatorError({\n message: `Unknown mutator: ${mutation.mutator}`,\n mutator: mutation.mutator,\n });\n }\n const args = yield* Schema.decodeUnknownEffect(definition.args)(mutation.args).pipe(\n Effect.mapError(\n (cause) =>\n new MutatorError({\n message: `Invalid journaled args for mutator \"${mutation.mutator}\"`,\n mutator: mutation.mutator,\n cause,\n })\n )\n );\n yield* handler(args, writer);\n }\n });\n\n // Secondary field-value indexes over confirmed rows (issue #113).\n // `indexFields` is the declared-plus-auto-discovered field set per\n // collection; `indexState` holds the actual `Index.CollectionIndex`es,\n // built lazily from the store and kept current by `applyPatch`/`seed`\n // deltas. An absent `built` entry means \"not built yet\" (or the\n // collection has no indexed fields) — the next access rebuilds it.\n // `generations` guard that rebuild against writes racing it (#339).\n const indexFields = yield* Ref.make(\n new Map<string, Set<string>>(\n Object.entries(options.indexes ?? {}).map(([collection, fields]) => [\n collection,\n new Set(fields),\n ])\n )\n );\n const indexState = yield* Ref.make<IndexState>({\n built: new Map(),\n generations: new Map(),\n clears: 0,\n });\n\n // The fields a subset's `where` could narrow via an index: the top-level\n // (or top-level-`And`) `Compare`/`In` conjuncts' fields. Used only to\n // decide what `autoIndex` should index — never changes evaluation.\n const indexableFieldsOf = (where: PredicateModule.Predicate): ReadonlyArray<string> => {\n const conjuncts = where._tag === \"And\" ? where.predicates : [where];\n const fields: Array<string> = [];\n for (const conjunct of conjuncts) {\n // Mirrors `CollectionIndex.conjunctIds`: `IS NOT NULL` never narrows.\n if (\n conjunct._tag === \"Compare\" ||\n conjunct._tag === \"In\" ||\n (conjunct._tag === \"IsNull\" && conjunct.negated !== true)\n ) {\n fields.push(conjunct.field);\n }\n }\n return fields;\n };\n\n // Record a subset's indexable fields when `autoIndex` is on, widening\n // that collection's declared field set and invalidating its built index\n // so the next access rebuilds with the new field. No-op otherwise.\n const noteAutoIndexFields = (subset: Subset.Subset): Effect.Effect<void> => {\n if (!options.autoIndex) return Effect.void;\n const discovered = indexableFieldsOf(subset.where);\n if (Arr.isReadonlyArrayEmpty(discovered)) return Effect.void;\n return Ref.modify(indexFields, (map) => {\n const current = map.get(subset.collection) ?? new Set<string>();\n const grown = new Set(current);\n for (const field of discovered) grown.add(field);\n if (grown.size === current.size) return [false, map] as const;\n const next = new Map(map);\n next.set(subset.collection, grown);\n return [true, next] as const;\n }).pipe(\n Effect.flatMap((grew) =>\n grew\n ? Ref.update(indexState, (state) => {\n const built = new Map(state.built);\n built.delete(subset.collection); // force a rebuild with the widened field set\n // An in-flight build over the old field set must not install (#339).\n const generations = new Map(state.generations);\n generations.set(subset.collection, (generations.get(subset.collection) ?? 0) + 1);\n return { built, generations, clears: state.clears };\n })\n : Effect.void\n )\n );\n };\n\n // (Re)build a collection's index from confirmed store rows if it isn't\n // already built for its current declared field set. `undefined` means\n // the collection has no indexed fields, or the build kept losing a race\n // to a write (#339) — the caller's cue to full-scan.\n //\n // The build reads rows, yields, then installs, and a write can land in\n // that window: `updateIndexes` skips a collection with no built index, so\n // the write would be missing from `fresh`. The generation is therefore read\n // BEFORE `listRows` and compared inside the install's `Ref.modify`: a write\n // that bumped it after the read discards `fresh` and the build is retried.\n // A write that landed before the read is already in the rows.\n //\n // Serialising the build on `overlayLock` (the lock `applyPull` holds across\n // its patch write) was rejected: it would queue every read and mutation\n // behind a full-collection `listRows`, and the lock is not reentrant, so a\n // caller that already holds it would deadlock. The generation check keeps\n // reads unblocked and needs no lock.\n const ensureIndexBuilt = (\n collection: string\n ): Effect.Effect<Index.CollectionIndex | undefined, StoreError> =>\n Effect.gen(function* () {\n for (let attempt = 0; attempt < MAX_INDEX_BUILD_ATTEMPTS; attempt++) {\n // The generation is read BEFORE the field set. `noteAutoIndexFields` widens the\n // fields and then bumps the generation, so a widening that lands after this read\n // bumps past `before` and the install refuses the build. Read the other way round,\n // a widening between the two reads would install an index over the old field set,\n // with nothing left to invalidate it (a missed index until the next rebuild).\n const before = yield* Ref.get(indexState);\n const fields = (yield* Ref.get(indexFields)).get(collection);\n if (fields === undefined || fields.size === 0) return undefined;\n const existing = before.built.get(collection);\n if (existing !== undefined) return existing;\n const fresh = Index.empty(fields);\n Index.rebuild(fresh, yield* store.listRows(collection));\n const installed = yield* Ref.modify(indexState, (state) => {\n // Another build installed first; it is kept current like any built index.\n const current = state.built.get(collection);\n if (current !== undefined) return [current, state] as const;\n if (!indexUnchangedFor(collection, before, state)) return [undefined, state] as const;\n return [\n fresh,\n { ...state, built: new Map(state.built).set(collection, fresh) },\n ] as const;\n });\n if (installed !== undefined) return installed;\n }\n return undefined;\n });\n\n // Indexed evaluation is sound only while a collection's confirmed rows\n // equal its materialized view — i.e. no pending mutation's optimistic\n // overlay (or acknowledged-but-unpulled tail, #286) could have shifted it\n // (the index tracks confirmed rows only).\n // Scoped per-collection (#133): a pending mutation's touched collections\n // are already computed for the rebase path (`collectionsTouchedByMutations`,\n // #109's tracked-write machinery), so a mutation pending against\n // collection A no longer disables index acceleration for a query against\n // untouched collection B. An unscoped result (an unknown mutator,\n // undecodable args — same cases `collectionsTouchedByMutations`'\n // `undefined` already covers for scoped Rebuilds) conservatively falls\n // back to a full scan for every collection, same as before this change.\n const indexForCollection = (\n collection: string\n ): Effect.Effect<Index.CollectionIndex | undefined, StoreError> =>\n overlayJournal.pipe(\n Effect.flatMap((pending) => {\n if (Arr.isReadonlyArrayEmpty(pending)) return ensureIndexBuilt(collection);\n return collectionsTouchedByMutations(pending).pipe(\n Effect.flatMap((touched) =>\n touched !== undefined && !touched.has(collection)\n ? ensureIndexBuilt(collection)\n : Effect.succeed(undefined)\n )\n );\n })\n );\n\n // Forget every built index, and bump every collection's generation, so the next\n // access rebuilds from the store and an in-flight build discards its result. For a\n // confirmed-row write that does not name its rows (a cleared or rewritten store,\n // #350): unlike a `Clear` patch op, it does not assume the store is now empty.\n const invalidateAllIndexes: Effect.Effect<void> = Ref.update(indexState, (state) => ({\n built: new Map(),\n generations: state.generations,\n clears: state.clears + 1,\n }));\n\n // Apply confirmed-row deltas (patch ops / seeded rows) to already-built\n // indexes. A collection with no built index yet is left alone — it\n // rebuilds fully from the store (which already reflects these deltas) on\n // next access. Every touched collection's generation is bumped, built or\n // not, so a build that read the rows before this write discards its result\n // rather than installing a snapshot that lacks it (#339). The bump and the\n // `built` snapshot are one `Ref.modify`, so an install is ordered entirely\n // before or entirely after this write.\n const updateIndexes = (ops: ReadonlyArray<PatchOp>): Effect.Effect<void> => {\n if (Arr.isReadonlyArrayEmpty(ops)) return Effect.void;\n return Ref.modify(indexState, (state) => {\n let clears = state.clears;\n const generations = new Map(state.generations);\n for (const op of ops) {\n if (op._tag === \"Clear\") clears++;\n else generations.set(op.collection, (generations.get(op.collection) ?? 0) + 1);\n }\n return [state.built, { built: state.built, generations, clears }] as const;\n }).pipe(\n Effect.map((built) => {\n if (built.size === 0) return;\n for (const op of ops) {\n if (op._tag === \"Clear\") {\n for (const index of built.values()) Index.clear(index);\n continue;\n }\n const index = built.get(op.collection);\n if (index === undefined) continue;\n if (op._tag === \"Put\") Index.upsertRow(index, op.id, op.value);\n else Index.deleteRow(index, op.id);\n }\n })\n );\n };\n\n // Drop every confirmed row: the `reset` writer (#350). The store is cleared first and the\n // indexes second, so a build that read the rows before the clear sees its generation change\n // and discards its result. Under `overlayLock`, so no reader rebuilds the overlay from the\n // half-cleared store.\n const clearConfirmedRows: Effect.Effect<void, StoreError> = Semaphore.withPermit(\n overlayLock,\n store.clearRows\n ).pipe(Effect.andThen(invalidateAllIndexes));\n\n /** Confirmed rows + the overlay journal (unpulled tail, then pending) replayed on top. */\n const computeOverlay: Effect.Effect<\n Map<string, Map<RowId, LocalRow>>,\n StoreError | MutatorError\n > = Effect.gen(function* () {\n const view = new Map<string, Map<RowId, LocalRow>>();\n yield* replayMutations(view, yield* overlayJournalLocked);\n return view;\n });\n\n // Cached overlay getter: reuse the last materialization until it is\n // invalidated, computing under the lock so a burst of observers triggers a\n // single replay. Equivalent to `computeOverlay` by construction — the cache\n // is only ever reused inside a window where neither the journal nor the\n // confirmed rows changed (every append/trim/pull invalidates it first).\n const materialize: Effect.Effect<\n Map<string, Map<RowId, LocalRow>>,\n StoreError | MutatorError\n > = Semaphore.withPermit(\n overlayLock,\n Ref.get(overlayCache).pipe(\n Effect.flatMap((cached) =>\n cached !== undefined\n ? Effect.succeed(cached)\n : timedRebase(computeOverlay).pipe(Effect.tap((view) => Ref.set(overlayCache, view)))\n )\n )\n );\n\n // Which collections a mutation touches: run its local handler through a\n // writer that only records the collections its put/del name (get returns\n // undefined, nothing is mutated), so a scoped Rebuild can name exactly the\n // collections the mutation shifts. Returns undefined — the caller's cue to\n // fall back to a global rebuild — when the handler is unknown or errors.\n const collectionsTouchedBy = (\n mutator: string,\n decodedArgs: unknown\n ): Effect.Effect<ReadonlySet<string> | undefined> =>\n Effect.gen(function* () {\n const handler = options.mutators.handlers.get(mutator);\n if (handler === undefined) return undefined;\n const touched = new Set<string>();\n const record = (collection: string) =>\n Effect.sync(() => {\n touched.add(collection);\n });\n const writer: LocalWriter = {\n put: (collection) => record(collection),\n del: (collection) => record(collection),\n get: () => Effect.succeed(undefined),\n };\n yield* handler(decodedArgs, writer);\n return touched;\n }).pipe(Effect.catchTag([\"MutatorError\", \"StoreError\"], () => Effect.succeed(undefined)));\n\n // The union of collections a batch of journaled mutations touches (their\n // args are encoded, so decode before tracking). Any unknown/undecodable\n // mutation collapses to undefined → a global rebuild.\n const collectionsTouchedByMutations = (\n mutations: ReadonlyArray<Mutation>\n ): Effect.Effect<ReadonlySet<string> | undefined> =>\n Effect.gen(function* () {\n const union = new Set<string>();\n for (const mutation of mutations) {\n const definition = options.mutators.mutators.get(mutation.mutator);\n if (definition === undefined) return undefined;\n const decoded = yield* Schema.decodeUnknownEffect(definition.args)(mutation.args).pipe(\n Effect.catchTag(\"SchemaError\", () => Effect.succeed(undefined))\n );\n const touched = yield* collectionsTouchedBy(mutation.mutator, decoded);\n if (touched === undefined) return undefined;\n for (const collection of touched) union.add(collection);\n }\n return union;\n });\n\n // Run a mutator's local handler directly onto `view` (mutating its\n // per-collection maps in place) while recording the `put`/`del` it\n // performs as `OverlayOp`s — the delta an observer folds via the same\n // `LiveView.put`/`del` machinery a confirmed-row `Patch` already uses\n // (#109). `get` reads through the same lazily-seeded collection maps as\n // `computeOverlay`'s writer, so a read-modify-write handler sees exactly\n // what a fresh replay would show it.\n const trackedWriter = (\n view: Map<string, Map<RowId, LocalRow>>,\n ops: Array<PatchOp | OverlayOp>\n ): LocalWriter =>\n viewWriter(\n view,\n (collection, id, value) => ops.push({ _tag: \"Put\", collection, id, value }),\n (collection, id) => ops.push({ _tag: \"Del\", collection, id })\n );\n\n // Apply a journaled mutation's local effects onto the cached overlay in\n // place instead of invalidating it (#109's core optimization): the\n // mutate path then costs one `trackedWriter` run over the rows it\n // touches, not a full journal replay. Must run under `overlayLock` — the\n // caller (`journal`) holds the permit for its whole body, so this\n // reads/mutates/writes the cache without racing `materialize`'s fill or\n // another mutation's tracked write. `journalBefore` is the overlay journal\n // snapshot from *before* this mutation was appended to the store — the\n // cold-cache fallback replays exactly that (not a fresh overlay journal,\n // which would already include this mutation by\n // the time this runs), so `trackedWriter` below applies this mutation's\n // effect exactly once rather than once from the replay and once more from\n // the tracked write. Falls back to a Rebuild scoped to the mutator's\n // touched collections (or the unscoped `REBUILD` when that can't be\n // determined either) when the handler is unknown, when materializing a\n // cold cache fails, or when the handler itself fails partway through —\n // every fallback drops the cache via a direct `Ref.set` (not\n // `invalidateOverlay`, which would deadlock re-acquiring this same\n // permit), so the next `materialize` recomputes from scratch, which\n // already includes this mutation since it is appended before this call.\n //\n // `base` is what the caller found under the lock it holds throughout\n // (#260): the warm cache itself, or, only when the cache was cold, the\n // journal snapshot to rebuild it from. Every write of the cache holds\n // `overlayLock`, so the cache the caller saw is the cache this runs on,\n // and a warm cache costs no journal read at all.\n const applyMutationToOverlayLocked = (\n mutator: string,\n decodedArgs: unknown,\n base: OverlayBase\n ): Effect.Effect<ViewChange> =>\n Effect.gen(function* () {\n const handler = options.mutators.handlers.get(mutator);\n if (handler === undefined) {\n yield* Ref.set(overlayCache, undefined);\n return REBUILD;\n }\n let view: Map<string, Map<RowId, LocalRow>>;\n if (base._tag === \"Warm\") {\n view = base.view;\n } else {\n const journalBefore = base.journalBefore;\n const filled = yield* Effect.exit(\n timedRebase(\n Effect.gen(function* () {\n const fresh = new Map<string, Map<RowId, LocalRow>>();\n yield* replayMutations(fresh, journalBefore);\n return fresh;\n })\n )\n );\n if (filled._tag === \"Failure\") {\n yield* Ref.set(overlayCache, undefined);\n return REBUILD;\n }\n view = filled.value;\n }\n const ops: Array<PatchOp | OverlayOp> = [];\n const ran = yield* Effect.exit(handler(decodedArgs, trackedWriter(view, ops)));\n if (ran._tag === \"Failure\") {\n yield* Ref.set(overlayCache, undefined);\n const touched = yield* collectionsTouchedBy(mutator, decodedArgs);\n return rebuildFor(touched);\n }\n yield* Ref.set(overlayCache, view);\n return { _tag: \"Patch\", ops };\n });\n\n // All local rows of a collection (confirmed + overlay) as an id-keyed\n // map, loading confirmed rows the overlay didn't already touch. Returning\n // the map (not a spread array) lets indexed evaluation look candidates up\n // directly — no extra O(n) copy on top of the O(n) this already pays to\n // seed the map from the store; aggregate consumers below spread it into\n // an array themselves.\n const collectionRows = (collection: string) =>\n materialize.pipe(Effect.flatMap((view) => ensureCollectionMap(view, collection)));\n\n // The aggregate reducers below fold over a plain array (unindexed —\n // aggregate initialization isn't wired to the secondary-index planner).\n const collectionRowsArray = (collection: string) =>\n collectionRows(collection).pipe(Effect.map((rows) => [...rows.values()]));\n\n const query = (subset: Subset.Subset) =>\n Effect.gen(function* () {\n yield* noteAutoIndexFields(subset);\n const rowsById = yield* collectionRows(subset.collection);\n const index = yield* indexForCollection(subset.collection);\n return Subset.applyIndexed(rowsById, subset, index);\n });\n\n // Route the whole patch through the store's batched bulk write, so a K-op\n // patch on a large collection costs K row-value writes + ~1 index rewrite\n // per touched collection — I/O scales with patch size, not collection size\n // (#47) — instead of one read-whole/rewrite-whole per op. Also maintains\n // the secondary field-value indexes (#113) from the same ops.\n const applyPatch = (ops: ReadonlyArray<PatchOp>): Effect.Effect<void, StoreError> =>\n store.applyRowOps(ops).pipe(Effect.tap(() => updateIndexes(ops)));\n\n // Resolve a `mutateWithAck` deferred for `id`, if one is registered, and\n // drop it from `acks`. A no-op for mutations journaled via `mutate` or\n // `mutateEncoded`, which never register one.\n const resolveAck = (id: number, outcome: MutationOutcome): Effect.Effect<void> =>\n Ref.get(acks).pipe(\n Effect.flatMap((map) => {\n const deferred = map.get(id);\n return deferred === undefined\n ? Effect.void\n : Deferred.succeed(deferred, outcome).pipe(Effect.asVoid);\n }),\n Effect.andThen(forgetAck(id))\n );\n\n // Fold every still-`\"pending\"` mutation state at or below `lastId` to\n // `\"acknowledged\"` (#116) — every journaled mutation, not just ones with a\n // registered `mutateWithAck` deferred — then resolve any deferred that IS\n // registered and emit one `acknowledged` event per newly-settled id.\n // States already settled (e.g. rejected by `settleRejected` moments\n // earlier in the same push) are skipped, so this stays idempotent.\n const settleApplied = (lastId: number): Effect.Effect<void> =>\n Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) =>\n SubscriptionRef.modify(mutationStates, (map) => {\n const settledIds: Array<number> = [];\n for (const [id, state] of map) {\n if (id > lastId || state.phase !== \"pending\") continue;\n settledIds.push(id);\n }\n // Fold every transition first, evict once (#116's `HashMap`\n // rationale): retention's scan-and-sort is O(size), so evicting\n // per-id inside a K-mutation ack sweep would cost O(K * size).\n const next = MutationState.acknowledgedMany(\n map,\n settledIds,\n now,\n options.mutationStateRetention\n );\n return [settledIds, next] as const;\n })\n ),\n Effect.flatMap((settledIds) =>\n Effect.forEach(settledIds, (id) =>\n resolveAck(id, { _tag: \"applied\" }).pipe(Effect.andThen(emitEvent(id, \"acknowledged\")))\n )\n ),\n Effect.asVoid\n );\n\n // Fold one mutation's permanent rejection in (#116), resolve any\n // registered `mutateWithAck` deferred, and emit `rejected` — regardless of\n // whether it was journaled via `mutate`, `mutateEncoded`, or `mutateWithAck`.\n //\n // Only a still-`\"pending\"` entry settles (#364). A response can repeat a\n // rejection this client already holds (a losing copy's response, #355), or\n // contradict an outcome it already observed. The first committed outcome\n // stands: a settled entry gets no second state change, no second deferred\n // resolution and no second event. The report is logged at debug and ignored.\n const rejectAck = (id: number, reason: string): Effect.Effect<void> =>\n Clock.currentTimeMillis.pipe(\n Effect.flatMap((now) =>\n SubscriptionRef.modify(mutationStates, (map) => {\n const prior = MutationState.phaseOf(map, id);\n if (prior !== \"pending\") return [prior, map] as const;\n const next = MutationState.rejected(\n map,\n id,\n reason,\n now,\n options.mutationStateRetention\n );\n return [prior, next] as const;\n })\n ),\n Effect.flatMap((prior) => {\n if (prior === \"pending\") {\n return resolveAck(id, { _tag: \"rejected\", reason }).pipe(\n Effect.andThen(emitEvent(id, \"rejected\", reason))\n );\n }\n // A repeat of this rejection, or an id already evicted, is harmless. Any other settled\n // phase contradicts the outcome the client already observed: the server commits one\n // outcome per id (#355), so that means an invariant broke.\n if (prior === undefined || prior === \"rejected\") {\n return Effect.logDebug(\"ClientEngine: ignoring a repeated or evicted rejection\", {\n mutationId: id,\n phase: prior ?? \"untracked\",\n });\n }\n return Effect.logWarning(\n \"ClientEngine: ignoring a rejection that contradicts the outcome already observed\",\n { mutationId: id, phase: prior }\n );\n })\n );\n\n // Resolve deferreds for the mutations this client had permanently rejected. A push\n // response and a pull response both report them (#365).\n const settleRejected = (response: Pick<PushResponse, \"rejected\">): Effect.Effect<void> =>\n Effect.gen(function* () {\n const mine = yield* currentClientId;\n for (const entry of response.rejected ?? []) {\n if (entry.clientId !== mine) continue;\n yield* rejectAck(entry.mutationId, entry.reason);\n }\n });\n\n // Settle this client's own entries that a watermark covers as applied.\n const settleOwnApplied = (lastMutationIds: Readonly<Record<string, number>>) =>\n Effect.gen(function* () {\n const lastId = lastMutationIds[yield* currentClientId];\n if (lastId !== undefined) yield* settleApplied(lastId);\n });\n\n // Pull ack (ADR-0008). The pull's patch already carries the effects of\n // everything its `lastMutationIds` covers, so the acknowledged tail those\n // entries occupy is released here, under the same invalidation as the\n // journal trim (#286). The caller holds `overlayLock` for the whole of\n // `applyPull`, the patch write included: a read in between would see the\n // new rows with the tail still parked, and replay the tail over them.\n // Takes no lock itself (the lock is not reentrant).\n // The store is written first and the copy second, so a store failure leaves\n // the copy as it was. The store's release also ends the pull's durable\n // marker (`beginRelease`, #336).\n const acknowledgeLocked = (lastMutationIds: Readonly<Record<string, number>>) =>\n Effect.gen(function* () {\n for (const [clientId, upTo] of Object.entries(lastMutationIds)) {\n yield* store.acknowledge(clientId, upTo);\n }\n yield* settleOwnApplied(lastMutationIds);\n yield* store.releaseUnpulled(lastMutationIds);\n yield* Ref.update(unpulled, (tail) => tail.filter((m) => !isCoveredBy(lastMutationIds, m)));\n yield* Ref.set(overlayCache, undefined);\n yield* sampleJournalDepth; // the trim changed journal depth\n });\n\n // What a store write that failed part-way leaves behind (#387): the store may hold more or less of\n // the tail than the copy, so the copy re-reads it before its next use and the cached overlay is\n // dropped. The store then finishes the release it may have recorded. It seals itself only when that\n // finish fails after reading the record (#387). Holds `overlayLock`.\n const settleFailedTail: Effect.Effect<void> = Ref.set(unpulledStale, true).pipe(\n Effect.andThen(Ref.set(overlayCache, undefined)),\n Effect.andThen(store.finishRelease.pipe(Effect.ignore))\n );\n\n // Push ack (ADR-0008, #286). The backend applied every journal entry the\n // response covers, so trim them from the journal, where they must never be\n // sent again, and park the applied ones at the end of the unpulled tail:\n // their effects stay overlaid until a pull reports them, so the view does\n // not revert in between. A permanently rejected entry was not applied, so\n // it leaves the overlay now. Returns those rejected entries for the caller\n // to reveal. Holds `overlayLock`, so the store and the copy move together.\n // The store parks the applied entries before it trims the journal, so a\n // crash between the two leaves each entry in both places, which the next\n // open resolves to the tail alone (#336). It never leaves one in neither.\n const acknowledgePushed = (\n response: PushResponse\n ): Effect.Effect<ReadonlyArray<Mutation>, StoreError> =>\n Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n const rejectedKeys = new Set(\n (response.rejected ?? []).map((entry) => `${entry.clientId}\\u0000${entry.mutationId}`)\n );\n const isRejected = (m: Mutation) =>\n rejectedKeys.has(`${m.clientId}\\u0000${m.mutationId}`);\n const covered = (yield* store.pendingMutations).filter((m) =>\n isCoveredBy(response.lastMutationIds, m)\n );\n const applied = covered.filter((m) => !isRejected(m));\n // Read before the park, so a reload of a stale copy cannot already hold the\n // entries about to be added.\n const held = yield* tailLocked;\n if (store.commitAcknowledgement !== undefined) {\n // The park and the trim are one atomic batch (#393): a failure leaves neither written.\n yield* store\n .commitAcknowledgement(applied, response.lastMutationIds)\n .pipe(\n Effect.onExit((exit) => (Exit.isSuccess(exit) ? Effect.void : settleFailedTail))\n );\n } else {\n yield* store.parkUnpulled(applied);\n // A trim that fails part-way leaves a parked entry in the journal as well. The store settles\n // that in process, as an open does, and the copy re-reads the tail on its next use (#336).\n yield* Effect.gen(function* () {\n for (const [clientId, upTo] of Object.entries(response.lastMutationIds)) {\n yield* store.acknowledge(clientId, upTo);\n }\n }).pipe(\n Effect.onExit((exit) => (Exit.isSuccess(exit) ? Effect.void : settleFailedTail))\n );\n }\n // The store now holds the full tail, and the copy takes it. Nothing is released here: the\n // tail leaves only through a pull (#429), and a push never takes it past the bound, so the\n // copy is never over it.\n yield* Ref.set(unpulled, [...held, ...applied]);\n yield* Ref.set(overlayCache, undefined);\n return covered.filter(isRejected);\n })\n );\n\n // #117 / #249: compact superseded, still-pending journal entries for\n // pacing strategies, then renumber the survivors so the ids the backend\n // sees stay contiguous (it rejects a gap, ADR-0008).\n //\n // Safety, in three layers. (1) Everything below runs under `overlayLock`,\n // the same lock `journal` holds while it allocates and appends an id and\n // `push` holds while it claims the pending set, so no id is ever\n // renumbered between being allocated and being appended, and a push can\n // never read a snapshot this call is about to renumber. (2) It refuses\n // outright while a push is in flight (`pushInFlight`). (3) The store only\n // drops or renumbers entries above its sent watermark, which `push` raises\n // (durably) before a request leaves — so an entry any attempt may have\n // put on the wire, even one that failed, keeps its id. The hard boundary\n // is enforced here and in the store, once, rather than trusted to callers.\n //\n // Everything keyed by an old id is moved in step, inside the lock: the\n // `mutateWithAck` deferreds (`acks`) and the `mutationStates` map. The\n // dropped entries' deferreds are interrupted (nothing will ever settle\n // them, and their ids may be reused). A global rebuild is the safe\n // fallback since the dropped mutations' collections aren't known without\n // re-decoding args already gone from the journal.\n const dropIfPending: ClientEngine[\"dropIfPending\"] = (mutationIds) =>\n Effect.gen(function* () {\n if (Arr.isReadonlyArrayEmpty(mutationIds)) return NO_COMPACTION;\n const clientId = yield* currentClientId;\n // Uninterruptible from the store's commit to the last re-key (#249\n // review B1): the store has renumbered the journal by the time\n // `compactPending` returns, so an interrupt before the acks, states and\n // events catch up would leave this engine, Paced and every handle on\n // ids that no longer exist. Events and the cache invalidation run\n // inside the lock too, so no `mutate` can interleave a new id between\n // the renumbering and its announcement.\n return yield* Semaphore.withPermit(\n overlayLock,\n Effect.uninterruptible(\n Effect.gen(function* () {\n if ((yield* Ref.get(pushInFlight)) > 0) return NO_COMPACTION;\n const compaction = yield* store.compactPending(clientId, mutationIds);\n if (Arr.isReadonlyArrayEmpty(compaction.dropped)) return NO_COMPACTION;\n // Move the `mutateWithAck` deferreds: detach every old key first, so\n // a survivor landing on a slot a dropped entry vacated cannot clash.\n const orphans = yield* Ref.modify(acks, (map) => {\n const next = new Map(map);\n const dropped: Array<Deferred.Deferred<MutationOutcome>> = [];\n for (const id of compaction.dropped) {\n const deferred = next.get(id);\n if (deferred !== undefined) dropped.push(deferred);\n next.delete(id);\n }\n const moved: Array<readonly [number, Deferred.Deferred<MutationOutcome>]> = [];\n for (const { from, to } of compaction.renumbered) {\n const deferred = next.get(from);\n if (deferred === undefined) continue;\n moved.push([to, deferred]);\n next.delete(from);\n }\n for (const [to, deferred] of moved) next.set(to, deferred);\n return [dropped, next] as const;\n });\n // Fold the drop and the moves into `mutationStates` (#116) — without\n // the drop, a compacted entry's state would never leave `\"pending\"`,\n // leaving a devtools journal panel showing a phantom in-flight\n // mutation forever.\n const settledAt = yield* Clock.currentTimeMillis;\n yield* SubscriptionRef.update(mutationStates, (map) =>\n MutationState.compacted(map, compaction, settledAt, options.mutationStateRetention)\n );\n yield* Effect.forEach(orphans, (deferred) => Deferred.interrupt(deferred), {\n discard: true,\n });\n yield* Effect.forEach(compaction.dropped, (id) => emitEvent(id, \"dropped\"), {\n discard: true,\n });\n yield* Effect.forEach(\n compaction.renumbered,\n ({ from, to }) =>\n emitEngineEvent({\n _tag: \"MutationRenumbered\",\n clientId,\n previousMutationId: from,\n mutationId: to,\n }),\n { discard: true }\n );\n // Inside the lock `invalidateOverlay` would deadlock on it; the\n // cache is only ever cleared by setting it empty.\n yield* Ref.set(overlayCache, undefined);\n yield* sampleJournalDepth;\n yield* publishChange(REBUILD);\n return compaction;\n })\n )\n );\n });\n\n // #212: the identity boundary at runtime. The transition rule itself\n // lives in `Identity`, so this and the store's open-time check are the\n // same decision applied at two moments — a sign-out mid-session and a\n // reload under a new session must not disagree about whether the replica\n // survives.\n //\n // On a `Reset` the order matters: quarantine the journal FIRST (nothing\n // is destroyed, and the entries leave the keyspace `push` reads), then\n // drop rows, the cookie and every registered subscription. The stamp is\n // written last, so an interrupted reset leaves the store stamped for the\n // superseded identity and the next open re-runs the whole transition\n // rather than trusting a half-applied one.\n const reset: ClientEngine[\"reset\"] = (next) =>\n Effect.gen(function* () {\n const current = (yield* store.getIdentity) ?? Identity.unstamped;\n const transition = Identity.transitionOf(current, next);\n let quarantined = 0;\n if (transition === \"Reset\") {\n quarantined = yield* store.quarantinePending(current);\n // The unpulled tail's effects belong to the superseded identity's rows,\n // which are cleared just below, so the tail goes with them (#286).\n yield* Semaphore.withPermit(\n overlayLock,\n store.clearUnpulled.pipe(\n Effect.andThen(Ref.set(unpulled, [])),\n Effect.andThen(Ref.set(formsInFlight, []))\n )\n );\n yield* clearConfirmedRows;\n yield* store.clearCookie;\n yield* Ref.set(subscriptions, []);\n yield* Ref.set(namedSubs, []);\n // Outcome deferreds were issued to the superseded identity's\n // session; that session is over and the backend will never settle\n // them here. Interrupt them so no `mutateWithAck` caller hangs —\n // the same treatment scope close gives them.\n yield* Ref.getAndSet(acks, new Map()).pipe(\n Effect.flatMap((map) => Effect.forEach([...map.values()], Deferred.interrupt))\n );\n }\n if (transition !== \"Unchanged\") {\n yield* store.setIdentity(next);\n // The scoped client identity moves with the stamp, so this\n // principal's mutations get their own contiguous id sequence (see\n // `clientIdFor`). Journal entries already written keep the client\n // id they were authored under, and push under it — each ledger\n // stays contiguous on its own.\n yield* Ref.set(clientIdRef, clientIdFor(next));\n }\n // Every branch, `Unchanged` included: re-signing in is what makes an\n // identity's own quarantined entries pushable again, and running it\n // unconditionally also closes the window where a reset was\n // interrupted between stamping and releasing.\n const released = yield* store.releaseQuarantine(next);\n if (transition === \"Unchanged\" && released === 0) {\n return { transition, quarantined: 0, released: 0 };\n }\n // The journal and the confirmed rows both moved: reseed the keyed\n // state map from what is actually pending now, drop the materialized\n // overlay, and reveal the whole thing with one unscoped rebuild.\n yield* SubscriptionRef.set(\n mutationStates,\n MutationState.seed(yield* store.pendingMutations)\n );\n yield* invalidateOverlay;\n yield* sampleJournalDepth;\n yield* publishChange(REBUILD);\n return {\n transition,\n ...(transition === \"Reset\" ? { quarantinedUnder: current } : {}),\n quarantined,\n released,\n };\n });\n\n // Latch so an ongoing schema-version rejection (#48) fires `onUpdateNeeded`\n // and the `UpdateNeeded` event exactly once — a retry storm or repeated\n // pulls against the same rejection do not refire it. The latch resets on the\n // next successful request, so a fresh rejection after an interim success\n // notifies again. A version rejection never trims the journal: pending\n // intents are retained across it, ready to push once the build is updated.\n const updateNeededLatch = yield* Ref.make(false);\n const infoOf = (error: VersionNotSupportedError) => ({\n ...(error.schemaVersion !== undefined ? { schemaVersion: error.schemaVersion } : {}),\n message: error.message,\n });\n const onVersionError = (error: VersionNotSupportedError): Effect.Effect<void> =>\n Ref.getAndSet(updateNeededLatch, true).pipe(\n Effect.flatMap((already) =>\n already\n ? Effect.void\n : emitEngineEvent({ _tag: \"UpdateNeeded\", ...infoOf(error) }).pipe(\n Effect.andThen(options.onUpdateNeeded?.(infoOf(error)) ?? Effect.void)\n )\n )\n );\n const resetUpdateLatch = Ref.set(updateNeededLatch, false);\n // Fire `onVersionError` on a version rejection, reset the latch on success;\n // shared by push and pull so both dedupe against one latch.\n const isVersionNotSupported = (error: {\n readonly _tag: string;\n }): error is VersionNotSupportedError => error._tag === \"VersionNotSupportedError\";\n const withVersionLatch = <A, E extends { readonly _tag: string }, R>(\n effect: Effect.Effect<A, E, R>\n ): Effect.Effect<A, E, R> =>\n effect.pipe(\n Effect.tap(() => resetUpdateLatch),\n Effect.tapError((error) =>\n isVersionNotSupported(error) ? onVersionError(error) : Effect.void\n )\n );\n\n // Claim the pending set for one push (#249), atomically with respect to\n // `dropIfPending` and `journal` (all three hold `overlayLock`): read the\n // snapshot, count the push in flight, and durably raise the sent watermark\n // to the highest id per client in it — *before* the request can leave. A\n // failed or interrupted round trip does not prove the backend never\n // applied it, so from here on those ids are frozen: compaction may not\n // drop or renumber them. A chunked push (#429) claims its whole journal this way, so the chunks it\n // has not sent yet are frozen as well. The counter is released on every path that does\n // not hand the claim to the push body.\n const claimPending: Effect.Effect<ReadonlyArray<Mutation>, StoreError> = Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n const pending = yield* store.pendingMutations;\n yield* adoptPending(pending);\n if (Arr.isReadonlyArrayEmpty(pending)) return pending;\n const highest = new Map<string, number>();\n for (const m of pending) {\n if (m.mutationId > (highest.get(m.clientId) ?? 0)) highest.set(m.clientId, m.mutationId);\n }\n yield* Ref.update(pushInFlight, (n) => n + 1);\n yield* Effect.forEach(highest, ([clientId, upTo]) => store.markSent(clientId, upTo), {\n discard: true,\n }).pipe(Effect.onError(() => Ref.update(pushInFlight, (n) => n - 1)));\n return pending;\n })\n );\n\n // The room a chunk may take (#429). The bound less the acknowledged tail and the chunks other pushes\n // have sent and not yet settled. Overlapping pushes share it: a chunk reserves its room under\n // `overlayLock`, so the tail and the reservations together never exceed the bound, and the reservation\n // is given back when the chunk's acknowledgement or failure has settled, or when the chunk is\n // interrupted (`sendChunk`). The reservation takes no more than `pullAheadAt` and no more than the\n // mutations left to send.\n const reservedRoom = yield* Ref.make(0);\n const reserveChunk = (remaining: number) =>\n Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n const tail = yield* tailLocked;\n const room = unpulledLimit - tail.length - (yield* Ref.get(reservedRoom));\n const size = Math.max(0, Math.min(pullAheadAt, room, remaining));\n yield* Ref.update(reservedRoom, (n) => n + size);\n return size;\n })\n );\n const releaseChunk = (size: number) => Ref.update(reservedRoom, (n) => n - size);\n\n const pushClaimed = (pending: ReadonlyArray<Mutation>) =>\n Effect.gen(function* () {\n yield* emitEngineEvent({ _tag: \"PushStarted\" });\n // The claimed journal goes out in chunks of at most the pull-ahead threshold (#429), in id order,\n // one request at a time. Each chunk reserves the room the tail leaves (see `reserveChunk`), so a\n // chunk never takes the tail past the bound, and an odd bound, or a push that overlaps another,\n // is covered by the same reservation. Before every chunk after the first, a pull releases the tail\n // the earlier chunks left; a push whose first chunk finds no room pulls first. That pull is awaited,\n // and if it fails the push fails with it, so the unsent entries stay journaled for the next push.\n // Nothing is forked per chunk.\n // Reserve the room, send the chunk it sizes, and give the room back, as one acquire/use/release:\n // the reservation is taken uninterruptibly and released on every exit, so an interrupt cannot\n // leak it. Resolves to the mutations sent from `sent`, or 0 when the room is short.\n const sendChunk = (remaining: number, sent: number) =>\n Effect.acquireUseRelease(\n reserveChunk(remaining),\n (size) =>\n size < 1\n ? Effect.succeed(0)\n : Effect.gen(function* () {\n const response = yield* transport.push({\n clientGroupId: options.clientGroupId,\n mutations: pending.slice(sent, sent + size),\n ...(options.schemaVersion !== undefined\n ? { schemaVersion: options.schemaVersion }\n : {}),\n });\n // Settle permanently-rejected mutations before the ack sweep, so a\n // rejected id reports `rejected` rather than `applied`.\n yield* settleRejected(response);\n // The applied entries keep their overlay effects in the unpulled tail\n // until a pull reports them (#286), so the view does not change here.\n // Only a permanent rejection leaves the overlay now; reveal just those\n // collections.\n const rejected = yield* acknowledgePushed(response);\n yield* settleOwnApplied(response.lastMutationIds);\n yield* sampleJournalDepth; // the trim changed journal depth\n if (Arr.isReadonlyArrayNonEmpty(rejected)) {\n yield* publishChange(\n rebuildFor(yield* collectionsTouchedByMutations(rejected))\n );\n }\n return size;\n }),\n (size) => releaseChunk(size)\n );\n let sent = 0;\n while (sent < pending.length) {\n const remaining = pending.length - sent;\n if (sent > 0) yield* pullBetweenChunks;\n let size = yield* sendChunk(remaining, sent);\n if (size < 1 && sent === 0) {\n yield* pullBetweenChunks;\n size = yield* sendChunk(remaining, sent);\n }\n // A pull that succeeded but left no room has not released the tail. Sending over it would take\n // the tail past the bound, so the push stops here as it does on a failed pull.\n if (size < 1) {\n return yield* Effect.fail(\n new TransportError({\n message:\n \"A pull released no room for the next chunk: the unpulled tail and the chunks other pushes have in flight still fill the bound; the unsent mutations stay journaled\",\n })\n );\n }\n sent += size;\n }\n // A tail that has reached half the bound starts a pull ahead of the bound (#337).\n // The push does not wait for it. A push ended early still gets this check.\n if ((yield* Ref.get(unpulled)).length >= pullAheadAt) yield* pullAhead;\n yield* Metric.update(Telemetry.mutationsPushedTotal, sent);\n yield* Metric.update(Telemetry.pushesTotal, 1);\n yield* Metric.update(Telemetry.pushMutations, sent);\n yield* emitEngineEvent({ _tag: \"PushCompleted\", mutations: sent });\n });\n\n // The claim is held for the whole round trip (through the ack sweep) and\n // released on every exit path, including failure and interruption, so a\n // transient push error never wedges the counter.\n const push: ClientEngine[\"push\"] = withVersionLatch(\n Effect.acquireUseRelease(\n claimPending,\n (pending) => (Arr.isReadonlyArrayEmpty(pending) ? Effect.void : pushClaimed(pending)),\n (pending) =>\n Arr.isReadonlyArrayEmpty(pending) ? Effect.void : Ref.update(pushInFlight, (n) => n - 1)\n )\n ).pipe(Effect.withSpan(Telemetry.span.clientPush));\n\n // The distinct collections and individual rows a pulled patch touches,\n // computed before the patch is applied so a `Clear` can stand for every\n // collection the client currently holds (the patch would otherwise wipe\n // them). Put/Del name their collection and row id directly; a `Clear` has\n // no finite row list, so it contributes to `collections` only. Drives\n // collection- and row-scoped reactions (HTTP-cache tag invalidation, #207)\n // via the `PullCompleted` event.\n interface PullTouched {\n readonly collections: ReadonlyArray<string>;\n readonly rows: ReadonlyArray<{ readonly collection: string; readonly id: RowId }>;\n }\n const pullTouchedCollections = (\n patch: ReadonlyArray<PatchOp>\n ): Effect.Effect<PullTouched, StoreError> =>\n Effect.gen(function* () {\n const collections = new Set<string>();\n const rows: Array<{ readonly collection: string; readonly id: RowId }> = [];\n let cleared = false;\n for (const op of patch) {\n if (op._tag === \"Clear\") {\n cleared = true;\n continue;\n }\n collections.add(op.collection);\n rows.push({ collection: op.collection, id: op.id });\n }\n if (cleared) {\n for (const collection of yield* store.listCollections) collections.add(collection);\n }\n return { collections: [...collections], rows };\n });\n\n // The in-process roll-forward of a pull whose section failed after its release record (#387).\n // The store finishes the record, as an open would; the copy is re-read before its next use,\n // since the store has released the tail. A failed roll-forward is logged and the pull reports its\n // own error. The store finishes the record on its next write or pull, and seals itself only when\n // the failure came after its read of the record (#387). Holds `overlayLock`.\n const rollForwardPullLocked = (\n lastMutationIds: Readonly<Record<string, number>>\n ): Effect.Effect<void> =>\n // The store may have released part of the tail before it failed, so the copy and the cached\n // overlay are dropped whatever the outcome: a failed roll-forward must not leave a view that\n // still shows what the store no longer holds.\n Ref.set(unpulledStale, true).pipe(\n Effect.andThen(Ref.set(overlayCache, undefined)),\n Effect.andThen(store.finishRelease),\n Effect.andThen(settleOwnApplied(lastMutationIds)),\n Effect.andThen(publishChange(REBUILD)),\n Effect.catch((error) =>\n Effect.logError(\n \"ClientEngine: a pull release could not be finished; the store finishes it on its next write or pull, and seals itself only after a failure past its record read\",\n {\n error,\n }\n )\n )\n );\n\n const applyPull = (response: PullResponse): Effect.Effect<PullTouched, StoreError> =>\n Effect.gen(function* () {\n // Settle the entries the pull reports as rejected before its watermark acknowledges\n // them. The watermark covers a rejected id (its bump is what rejects it), so\n // `settleOwnApplied` below would otherwise fold it as applied (#365). The rejection\n // is a fact the server committed, so it settles now, before the store is written. A\n // failure after this point leaves the settlement in place: a repeat is a no-op (#364).\n yield* settleRejected(response);\n // With an empty journal the patch ops are exactly the materialized-view\n // deltas, so observers maintain incrementally. With a pending overlay,\n // rebase (confirmed patch + replay of whatever mutations remain\n // pending, and the vanishing of whatever just got acknowledged or\n // rejected) could shift any row the patch or those pending-before-this-\n // pull mutations touch — scope a Rebuild to their union rather than\n // forcing a global one (#109's \"stays a scoped Rebuild\" rebase path);\n // a reset (`Clear`) still forces the unscoped fallback.\n const hasClear = response.patch.some((op) => op._tag === \"Clear\");\n const touched = yield* pullTouchedCollections(response.patch);\n // One critical section (#286): the overlay journal before this pull\n // (the unpulled tail, then pending), the confirmed-row write and the tail\n // release. A read that runs between the row write and the release would\n // otherwise see the new rows with the tail still replayed over them.\n // Reads and mutations wait on the store's patch write while the lock is\n // held (one IndexedDB transaction in the browser store). The section is\n // not failure-atomic: a store error after `applyPatch` leaves the rows\n // written and the tail unreleased, so the view double-counts until the\n // next successful pull.\n const journalBefore = yield* Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n const before = yield* overlayJournalLocked;\n // With an atomic batch in the store (#393), the release is one commit: the rows, the cookie,\n // the journal trim and the tail release, with no record. A failure before the commit point\n // leaves the store as it was; a failure reported after it may still have committed, so the\n // outcome is unknown. Either way the copy is re-read and the view rebuilt, as the record path\n // does on a failed section (rollForwardPullLocked). The in-memory steps follow the commit, in\n // the order the record path runs them, and sit under the same exit handler: a pull that dies\n // or is interrupted after the commit point rolls forward too, rather than leaving the tail\n // replayed over the committed rows.\n const commitPull = store.commitPull;\n if (commitPull !== undefined) {\n yield* Effect.gen(function* () {\n yield* commitPull({\n lastMutationIds: response.lastMutationIds,\n cookie: response.cookie,\n patch: response.patch,\n });\n yield* updateIndexes(response.patch);\n yield* settleOwnApplied(response.lastMutationIds);\n yield* Ref.update(unpulled, (tail) =>\n tail.filter((m) => !isCoveredBy(response.lastMutationIds, m))\n );\n yield* Ref.set(overlayCache, undefined);\n yield* sampleJournalDepth;\n }).pipe(\n Effect.onExit((exit) =>\n Exit.isSuccess(exit)\n ? Effect.void\n : rollForwardPullLocked(response.lastMutationIds)\n )\n );\n return before;\n }\n // A failure in this scope is rolled forward here, from the same record, as the open does.\n // If that fails too, the store finishes the record on its next write or pull. It seals itself\n // only when the failure came after its read of the record, so no later write runs over a\n // part-written release (#387). The marker is written inside this scope too: a\n // `beginRelease` that reports failure may still have written it, so it is finished\n // either way, and finishing is a no-op when nothing landed (#387).\n yield* Effect.gen(function* () {\n // The durable marker goes down before the first row, so a crash mid-section\n // is finished on the next open rather than double-counting (#336).\n yield* store.beginRelease({\n lastMutationIds: response.lastMutationIds,\n cookie: response.cookie,\n patch: response.patch,\n });\n yield* applyPatch(response.patch);\n // The cookie goes down before the release removes the record, so a crash between the\n // two leaves the next open to write it again, not an old cookie over new rows (#387).\n yield* store.setCookie(response.cookie);\n yield* acknowledgeLocked(response.lastMutationIds);\n }).pipe(\n Effect.onExit((exit) =>\n Exit.isSuccess(exit) ? Effect.void : rollForwardPullLocked(response.lastMutationIds)\n )\n );\n return before;\n })\n );\n const hadPending = Arr.isReadonlyArrayNonEmpty(journalBefore);\n let change: ViewChange;\n if (hasClear) {\n change = REBUILD;\n } else if (!hadPending) {\n change = { _tag: \"Patch\", ops: response.patch };\n } else {\n const mutationCollections = yield* collectionsTouchedByMutations(journalBefore);\n change = rebuildFor(\n mutationCollections === undefined\n ? undefined\n : new Set([...touched.collections, ...mutationCollections])\n );\n }\n // Atomic reveal: one change event after patch + ack (rebase is\n // recomputation in `materialize`).\n yield* publishChange(change);\n return touched;\n });\n\n // Pulls are serialised (#412). Each pull runs in the fibre of the caller that holds `pullLock`,\n // so at most one request is in flight and the caller's context and interruption behave as they\n // always have. `pullsStarted` numbers each pull as it starts, and `pullsApplied` holds the number\n // of the last pull that was applied. A caller reads `pullsStarted` on entry and may skip its own\n // pull only when `pullsApplied > entry`: a pull that started after the caller's entry has been\n // applied while the caller waited, so it fetched everything the caller asked for. A pull that was\n // already in flight at entry may predate the caller's request, so it never counts. A failed pull\n // records nothing, so a caller queued behind it pulls for itself.\n const pullLock = yield* Semaphore.make(1);\n const pullsStarted = yield* Ref.make(0);\n const pullsApplied = yield* Ref.make(0);\n // `pullsApplied` moves to this pull's number as soon as its rows are applied, before\n // `PullCompleted` is published, so an observer of that event reads the new count.\n const pullOnce = (number: number) =>\n withVersionLatch(\n Effect.gen(function* () {\n yield* emitEngineEvent({ _tag: \"PullStarted\" });\n const cookie = yield* store.getCookie;\n const subsets = yield* Ref.get(subscriptions);\n const named = yield* Ref.get(namedSubs);\n const namedSubscriptions: ReadonlyArray<NamedSubscription> = named.map((entry) => ({\n name: entry.name,\n args: entry.argsEncoded,\n }));\n const response = yield* transport.pull({\n clientGroupId: options.clientGroupId,\n cookie,\n subscriptions: subsets,\n ...(Arr.isReadonlyArrayNonEmpty(namedSubscriptions) ? { namedSubscriptions } : {}),\n ...(options.schemaVersion !== undefined\n ? { schemaVersion: options.schemaVersion }\n : {}),\n });\n const touched = yield* applyPull(response);\n yield* Ref.set(pullsApplied, number);\n yield* Metric.update(Telemetry.pullsTotal, 1);\n yield* Metric.update(Telemetry.pullPatchOps, response.patch.length);\n yield* emitEngineEvent({\n _tag: \"PullCompleted\",\n ops: response.patch.length,\n collections: touched.collections,\n rows: touched.rows,\n });\n })\n );\n\n const pull: ClientEngine[\"pull\"] = Effect.gen(function* () {\n const entry = yield* Ref.get(pullsStarted);\n yield* Semaphore.withPermit(\n pullLock,\n Effect.gen(function* () {\n if ((yield* Ref.get(pullsApplied)) > entry) return;\n const number = yield* Ref.updateAndGet(pullsStarted, (started) => started + 1);\n yield* pullOnce(number);\n })\n );\n }).pipe(Effect.withSpan(Telemetry.span.clientPull));\n\n const pullCounts: Effect.Effect<PullCounts> = Effect.all({\n started: Ref.get(pullsStarted),\n applied: Ref.get(pullsApplied),\n });\n\n const subscribeSubset = (subset: Subset.Subset): Effect.Effect<void> =>\n Ref.update(subscriptions, (current) =>\n current.some((s) => Subset.hash(s) === Subset.hash(subset)) ? current : [...current, subset]\n );\n\n // Seed confirmed rows and reveal them with one scoped rebuild, so observers\n // of the seeded collections re-materialize while others stay put. Confirmed\n // rows shifted, so the overlay cache is invalidated first.\n const seed: ClientEngine[\"seed\"] = (rows) =>\n Effect.gen(function* () {\n const touched = new Set<string>();\n // The row writes run under `overlayLock`, so a pull's release cannot be in flight across\n // them: the rows it writes and the release it records stay one section (#387).\n yield* Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n for (const row of rows) {\n yield* store.putRow(row.collection, {\n id: row.id,\n version: row.version,\n value: row.value,\n });\n touched.add(row.collection);\n }\n })\n );\n yield* updateIndexes(\n rows.map((row): PatchOp => ({\n _tag: \"Put\",\n collection: row.collection,\n id: row.id,\n version: row.version,\n value: row.value,\n }))\n );\n yield* invalidateOverlay;\n yield* publishChange(rebuildFor(touched));\n });\n\n // A direct store write (`Hydration.hydrate`) appends journal entries the map does not track;\n // adopt them so they settle like a locally journaled mutation (#358). A failed read keeps the\n // map as it was (logged); the push claim adopts the journal again before it sends anything.\n // The read and the fold run under `overlayLock`, as every other journal writer does: a pull's\n // trim cannot land between them and leave an adopted id with no journal row behind it.\n const adoptJournal: Effect.Effect<void> = Semaphore.withPermit(\n overlayLock,\n store.pendingMutations.pipe(\n Effect.catch((error) =>\n Effect.logWarning(\n \"ClientEngine: could not read the journal to track entries written directly to the store\",\n { error }\n ).pipe(Effect.as<ReadonlyArray<Mutation>>([]))\n ),\n Effect.flatMap(adoptPending)\n )\n );\n\n // Reload the tail's in-memory copy from the store, as `adoptJournal` does for the journal: a\n // direct store write (`Hydration.hydrate`) parks entries the copy does not hold (#336). A failed\n // read keeps the copy as it was, and is logged.\n const adoptUnpulled: Effect.Effect<void> = Semaphore.withPermit(\n overlayLock,\n store.unpulled.pipe(\n Effect.flatMap((entries) =>\n Ref.set(unpulled, entries).pipe(Effect.andThen(Ref.set(unpulledStale, false)))\n ),\n Effect.catch((error) =>\n Ref.set(unpulledStale, true).pipe(\n Effect.andThen(\n Effect.logWarning(\n \"ClientEngine: could not reload the unpulled tail from the store; re-reading it before its next use\",\n { error }\n )\n )\n )\n )\n )\n );\n\n // Re-read everything derived from the store and reveal it: the built indexes, the overlay\n // (confirmed rows plus the journal) and every observer. Shared by `clearRows` and by a direct\n // store write (`resyncAttachedEngines`).\n const reloadFromStore: Effect.Effect<void> = invalidateAllIndexes.pipe(\n Effect.andThen(adoptJournal),\n Effect.andThen(adoptUnpulled),\n Effect.andThen(invalidateOverlay),\n Effect.andThen(sampleJournalDepth),\n Effect.andThen(publishChange(REBUILD))\n );\n\n // Drop every confirmed row and reveal the empty view. A direct `store.clearRows` would\n // leave the view and the indexes showing the cleared rows (#350).\n const clearRows: ClientEngine[\"clearRows\"] = Semaphore.withPermit(\n overlayLock,\n store.clearRows\n ).pipe(Effect.andThen(reloadFromStore));\n\n // Register this engine for direct store writes for as long as its scope lasts (#350).\n const attached = liveEngines.get(store) ?? new Set<Effect.Effect<void>>();\n attached.add(reloadFromStore);\n liveEngines.set(store, attached);\n yield* Effect.addFinalizer(() =>\n Effect.sync(() => attached.delete(reloadFromStore)).pipe(Effect.asVoid)\n );\n\n // Register or reuse the in-flight pull for a subset. Returns the deferred to\n // await plus whether this call owns the pull (only the owner runs it), so\n // concurrent prefetches of one subset collapse to a single pull.\n type PullDeferred = Deferred.Deferred<\n void,\n TransportError | StoreError | MutatorError | VersionNotSupportedError\n >;\n type PullMap = Map<string, PullDeferred>;\n type PullClaim = { readonly deferred: PullDeferred; readonly owner: boolean };\n const claimPull = (hash: string, own: PullDeferred): Effect.Effect<PullClaim> =>\n Ref.modify(ensurePulls, (map): readonly [PullClaim, PullMap] => {\n const existing = map.get(hash);\n return existing !== undefined\n ? [{ deferred: existing, owner: false }, map]\n : [{ deferred: own, owner: true }, new Map(map).set(hash, own)];\n });\n\n const releasePull = (hash: string): Effect.Effect<void> =>\n Ref.update(ensurePulls, (map) => {\n const next = new Map(map);\n next.delete(hash);\n return next;\n });\n\n // A single deduped pull for a subset: the owner runs `pull` and settles the\n // shared deferred; everyone else just awaits it.\n const dedupedPull = (\n subset: Subset.Subset\n ): Effect.Effect<void, TransportError | StoreError | MutatorError | VersionNotSupportedError> =>\n Effect.gen(function* () {\n const hash = Subset.hash(subset);\n const own = yield* Deferred.make<\n void,\n TransportError | StoreError | MutatorError | VersionNotSupportedError\n >();\n const { deferred, owner } = yield* claimPull(hash, own);\n if (!owner) return yield* Deferred.await(deferred);\n const exit = yield* Effect.exit(pull);\n yield* releasePull(hash);\n yield* Deferred.done(own, exit);\n return yield* Deferred.await(own);\n });\n\n const ensureSubset: ClientEngine[\"ensureSubset\"] = (subset) =>\n Effect.gen(function* () {\n yield* subscribeSubset(subset);\n const rows = yield* query(subset);\n if (Arr.isReadonlyArrayNonEmpty(rows)) return;\n yield* dedupedPull(subset);\n });\n\n // Retry only transient (transport) failures; store/mutator errors are not\n // transient and go straight to the failure surface.\n const isTransient = (error: { readonly _tag: string }): boolean =>\n error._tag === \"TransportError\";\n\n const pushPolicy = options.retry?.push ?? defaultRetryPolicy;\n const pullPolicy = options.retry?.pull ?? defaultRetryPolicy;\n const pokePolicy = options.retry?.pokes ?? defaultRetryPolicy;\n\n // A network leg that survives transient failure via its policy, then\n // surfaces (never raises) whatever it could not recover from.\n // A version rejection (#48) is already handled by `onUpdateNeeded` inside\n // push/pull and is not a transient failure to retry or a terminal\n // `SyncFailure` to surface, so the loop swallows it here (the app was\n // already told to update). The journal is untouched, so pending intents\n // wait for an updated build.\n const attemptPush = push.pipe(\n Effect.retry({ schedule: pushPolicy, while: isTransient }),\n Effect.catchTag(\"VersionNotSupportedError\", () => Effect.void),\n Effect.catch((error) => surfaceFailure(\"push\", error))\n );\n const attemptPull = pull.pipe(\n Effect.retry({ schedule: pullPolicy, while: isTransient }),\n Effect.catchTag(\"VersionNotSupportedError\", () => Effect.void),\n Effect.catch((error) => surfaceFailure(\"pull\", error))\n );\n\n // Pull ahead of the bound (#337). With no pokes and no `pullInterval`, nothing else pulls, so a long\n // run of pushes could fill the tail to the bound and stall. A push that takes the tail to half the bound\n // starts one `attemptPull` in the engine's scope, and the push does not wait for it. The flag\n // admits one such pull at a time and is cleared when it ends, failed or not, so a burst of pushes\n // past the threshold starts at most one pull in flight and a failed pull never blocks a later one.\n // Why half: the pull must land before the tail reaches the bound, and the headroom above the\n // threshold (the other half) has to absorb the pushes acknowledged while that pull is in flight.\n // A lower threshold pulls more often than a healthy transport needs; a higher one leaves too little\n // headroom for a slow pull.\n const pullAheadPending = yield* Ref.make(false);\n const pullAheadScope = yield* Effect.scope;\n const pullAhead: Effect.Effect<void> = Ref.modify(\n pullAheadPending,\n (pending) => [!pending, true] as const\n ).pipe(\n Effect.flatMap((claimed) =>\n claimed\n ? attemptPull.pipe(\n Effect.ensuring(Ref.set(pullAheadPending, false)),\n Effect.forkIn(pullAheadScope),\n Effect.asVoid\n )\n : Effect.void\n )\n );\n\n // The pull a push runs before a chunk that needs the tail released (#429). Unlike `attemptPull`, it\n // does not surface its failure: the push fails with it, and the sync loop's push retry and failure\n // surface take it from there. Transient failures are retried under `pullPolicy` first. A version\n // rejection already reached `onUpdateNeeded`, and a pull that is refused is still a stopped push, so\n // both fail the push as a TransportError. Stopping is the only safe choice: sending on over a tail\n // that no pull has released would take it past the bound.\n const pullBetweenChunks: Effect.Effect<void, TransportError | StoreError> = pull.pipe(\n Effect.retry({ schedule: pullPolicy, while: isTransient }),\n Effect.catchTag(\"VersionNotSupportedError\", (error) =>\n Effect.fail(\n new TransportError({\n message: `A pull between chunks was refused: ${error.message}`,\n cause: error,\n })\n )\n ),\n Effect.catchTag(\"MutatorError\", (error) =>\n Effect.fail(\n new TransportError({\n message: `A pull between chunks failed: ${error.message}`,\n cause: error,\n })\n )\n )\n );\n\n const runSync: ClientEngine[\"runSync\"] = Effect.gen(function* () {\n // Subscribe to the push trigger here, before anything is forked (#317).\n // `Stream.fromPubSub` would subscribe only once the debounce's forked\n // upstream fibre first pulls, a few scheduler turns after this returns,\n // and a trigger published in between is lost; the connect leg below has\n // already read the journal by then, so that mutation would wait for\n // some unrelated push. Subscribing first leaves no gap: a mutation\n // journaled before this point is in the journal the connect leg reads,\n // and every later one queues a trigger on this subscription.\n const pushDebounce = options.syncLoop?.pushDebounce;\n const pushTriggers =\n pushDebounce === undefined ? undefined : yield* PubSub.subscribe(pushTrigger);\n // Pull on every poke; re-establish the poke stream with backoff, and\n // surface if it stays down (the replay-1 hub covers the resubscribe race).\n yield* Effect.forkScoped(\n Stream.runForEach(\n transport.pokes.pipe(\n Stream.retry(pokePolicy),\n Stream.mapEffect((poke) =>\n emitEngineEvent({\n _tag: \"PokeReceived\",\n ...(poke.reason !== undefined ? { reason: poke.reason } : {}),\n }).pipe(Effect.as(poke))\n ),\n // While a pull is in flight the consumer below does not take the next poke, so pokes\n // wait here. The buffer keeps only the newest, so a burst costs one follow-up pull\n // (#412). That is sound: a dropped poke arrived before the newer one was taken, and the\n // pull the consumer runs next starts after that, so it covers the dropped poke too.\n // Nothing is forked per poke.\n Stream.buffer({ capacity: 1, strategy: \"sliding\" })\n ),\n () => attemptPull\n ).pipe(Effect.catch((error) => surfaceFailure(\"pokes\", error)))\n );\n // Push + pull on (re)connect.\n yield* Effect.forkScoped(\n Stream.runForEach(transport.statusChanges, (status) =>\n status === \"connected\" ? attemptPush.pipe(Effect.andThen(attemptPull)) : Effect.void\n )\n );\n // Auto-push after mutations, debounced so a burst coalesces into one push.\n if (pushDebounce !== undefined && pushTriggers !== undefined) {\n yield* Effect.forkScoped(\n Stream.fromSubscription(pushTriggers).pipe(\n Stream.debounce(pushDebounce),\n Stream.runForEach(() => attemptPush)\n )\n );\n }\n // Periodic pull: the correctness backstop when no pokes arrive.\n const pullInterval = options.syncLoop?.pullInterval;\n if (pullInterval !== undefined) {\n yield* Effect.forkScoped(attemptPull.pipe(Effect.repeat(Schedule.spaced(pullInterval))));\n }\n });\n\n const definitionOf = (mutator: string) => {\n const definition = options.mutators.mutators.get(mutator);\n return definition === undefined || !options.mutators.handlers.has(mutator)\n ? Effect.fail(new MutatorError({ message: `Unknown mutator: ${mutator}`, mutator }))\n : Effect.succeed(definition);\n };\n\n // Named queries: resolve a name to its client-side definition + subset.\n const queryDefOf = (\n name: string\n ): Effect.Effect<\n { readonly definition: Query.AnyQuery; readonly local: Query.LocalQuery<any> },\n QueryError\n > => {\n const definition = options.queries?.queries.get(name);\n const local = options.queries?.locals.get(name);\n return definition === undefined || local === undefined\n ? Effect.fail(new QueryError({ message: `Unknown query: ${name}`, query: name }))\n : Effect.succeed({ definition, local });\n };\n const localSubsetOf = (name: string, args: unknown): Effect.Effect<Subset.Subset, QueryError> =>\n queryDefOf(name).pipe(Effect.map(({ local }) => local(args)));\n const encodeQueryArgs = (name: string, args: unknown): Effect.Effect<unknown, QueryError> =>\n queryDefOf(name).pipe(\n Effect.flatMap(({ definition }) =>\n Schema.encodeUnknownEffect(definition.args)(args).pipe(\n Effect.mapError(\n (cause) =>\n new QueryError({ message: `Invalid args for query \"${name}\"`, query: name, cause })\n )\n )\n )\n );\n const namedKey = (name: string, argsEncoded: unknown) =>\n `${name}:${Hash.canonicalJson(argsEncoded)}`;\n // Encode + key a named subscription, then update the registry with both.\n const updateNamedSubs = (\n name: string,\n args: unknown,\n update: (\n current: ReadonlyArray<{ name: string; argsEncoded: unknown; key: string }>,\n entry: { name: string; argsEncoded: unknown; key: string }\n ) => ReadonlyArray<{ name: string; argsEncoded: unknown; key: string }>\n ): Effect.Effect<void, QueryError> =>\n encodeQueryArgs(name, args).pipe(\n Effect.flatMap((argsEncoded) =>\n Ref.update(namedSubs, (current) =>\n update(current, { name, argsEncoded, key: namedKey(name, argsEncoded) })\n )\n )\n );\n // Apply a Patch's deltas for one collection to a LiveView — confirmed-row\n // ops from a pull, or optimistic `OverlayOp`s from a mutate (#109); both\n // shapes carry the `_tag`/`collection`/`id`/`value` this only reads.\n const applyOps = (\n view: LiveView.LiveView,\n collection: string,\n ops: ReadonlyArray<PatchOp | OverlayOp>\n ): LiveView.LiveView => {\n let next = view;\n for (const op of ops) {\n if (op._tag === \"Clear\" || op.collection !== collection) continue;\n next =\n op._tag === \"Put\"\n ? LiveView.put(next, { id: op.id, value: op.value })\n : LiveView.del(next, op.id);\n }\n return next;\n };\n\n const sameResult = (a: ReadonlyArray<LocalRow>, b: ReadonlyArray<LocalRow>): boolean =>\n a.length === b.length &&\n a.every((row, i) => row.id === b[i]?.id && row.value === b[i]?.value);\n\n // A scoped rebuild that doesn't name the observed collection cannot have\n // moved it, so the observer keeps its page (and `changesWith` dedups the\n // re-emit). An unscoped rebuild (collections undefined) always recomputes.\n const rebuildSkips = (change: ViewChange, collection: string): boolean =>\n change._tag === \"Rebuild\" &&\n change.collections !== undefined &&\n !change.collections.has(collection);\n\n // One sequenced step's page transition for a query's LiveView: `before`/\n // `after` are the window slices pre/post this step, `reset` marks a\n // Rebuild-touching-this-collection or a gap collapse — the overlay could\n // have shifted any row, so a consumer cannot diff `before` against\n // `after`. `observeSubset` always takes `after` (a scoped rebuild that\n // skips this collection returns `before === after`, so `changesWith`\n // dedups it); `observeSubsetChanges` diffs `before`/`after`, or emits a\n // `reset` batch when `reset` is set — the single seq/gap/rebuild-skip\n // decision both observers share, so they can never step out of sync with\n // each other. Mutates `viewRef`/`lastSeenRef` as a side effect.\n interface ViewStep {\n readonly before: ReadonlyArray<LocalRow>;\n readonly after: ReadonlyArray<LocalRow>;\n readonly reset: boolean;\n }\n // `readSubset` re-reads the *current* subset on every step rather than\n // closing over a fixed one, so a retargeted window (`observeWindow`\n // below) picks up its widened `limit`/advanced `cursor` on the very next\n // Rebuild/gap-collapse — `observeSubset`/`observeSubsetChanges` (whose\n // subset never changes) just pass `Effect.succeed(subset)`.\n const advanceView = (\n viewRef: Ref.Ref<LiveView.LiveView>,\n lastSeenRef: Ref.Ref<number>,\n readSubset: Effect.Effect<Subset.Subset>,\n item: SeqChange\n ): Effect.Effect<ViewStep, StoreError | MutatorError> =>\n Effect.gen(function* () {\n const lastSeen = yield* Ref.get(lastSeenRef);\n if (item.seq <= lastSeen) {\n const page = LiveView.result(yield* Ref.get(viewRef));\n return { before: page, after: page, reset: false };\n }\n const subset = yield* readSubset;\n if (item.seq === lastSeen + 1) {\n yield* Ref.set(lastSeenRef, item.seq);\n const view = yield* Ref.get(viewRef);\n const before = LiveView.result(view);\n if (rebuildSkips(item.change, subset.collection)) {\n return { before, after: before, reset: false };\n }\n const isRebuild = item.change._tag === \"Rebuild\";\n const next = isRebuild\n ? LiveView.makeIndexed(\n subset,\n yield* collectionRows(subset.collection),\n yield* indexForCollection(subset.collection)\n )\n : applyOps(view, subset.collection, item.change.ops);\n if (next !== view) yield* Ref.set(viewRef, next);\n return { before, after: LiveView.result(next), reset: isRebuild };\n }\n // A drop happened before this seq: collapse it into a full Rebuild.\n // Read the latest assigned seq FIRST, then re-materialize — the store\n // then reflects every change with seq ≤ latest, so advancing\n // `lastSeenRef` to `latest` safely skips any still-buffered changes\n // already folded into this rebuild (they would otherwise re-apply as\n // stale, regressing rows). A Rebuild subsumes the dropped Patches\n // (ADR-0008), so the view is correct.\n yield* Metric.update(Telemetry.changeCollapsesTotal, 1);\n const before = LiveView.result(yield* Ref.get(viewRef));\n const latest = yield* Ref.get(changeSeq);\n const next = LiveView.makeIndexed(\n subset,\n yield* collectionRows(subset.collection),\n yield* indexForCollection(subset.collection)\n );\n yield* Ref.set(viewRef, next);\n yield* Ref.set(lastSeenRef, latest);\n return { before, after: LiveView.result(next), reset: true };\n });\n\n const stepView = (\n viewRef: Ref.Ref<LiveView.LiveView>,\n lastSeenRef: Ref.Ref<number>,\n readSubset: Effect.Effect<Subset.Subset>,\n item: SeqChange\n ): Effect.Effect<ReadonlyArray<LocalRow>, StoreError | MutatorError> =>\n advanceView(viewRef, lastSeenRef, readSubset, item).pipe(Effect.map((step) => step.after));\n\n const stepViewChanges = (\n viewRef: Ref.Ref<LiveView.LiveView>,\n lastSeenRef: Ref.Ref<number>,\n readSubset: Effect.Effect<Subset.Subset>,\n item: SeqChange\n ): Effect.Effect<ReadonlyArray<RowChange.RowChange<LocalRow>>, StoreError | MutatorError> =>\n advanceView(viewRef, lastSeenRef, readSubset, item).pipe(\n Effect.map((step) =>\n step.reset ? RowChange.reset(step.after) : RowChange.diff(step.before, step.after)\n )\n );\n\n // Shared setup for `observeSubset`/`observeSubsetChanges`: establish the\n // live window a step at a time, so the two observers can never drift in\n // how they get there. Subscribe BEFORE snapshotting (#84): the hub only\n // delivers to live subscribers, so a change published while we\n // materialize must land in this subscription's buffer — subscribing\n // after the snapshot silently loses it, and with no later change to\n // reveal the seq gap the observer sleeps through the write forever. The\n // seq is captured before materializing so the view reflects the store at\n // ≥ that seq, making the first live change contiguous.\n const initSubsetView = (subset: Subset.Subset) =>\n Effect.gen(function* () {\n yield* noteAutoIndexFields(subset);\n const subscription = yield* PubSub.subscribe(changes);\n const startSeq = yield* Ref.get(changeSeq);\n const viewRef = yield* Ref.make(\n LiveView.makeIndexed(\n subset,\n yield* collectionRows(subset.collection),\n yield* indexForCollection(subset.collection)\n )\n );\n const lastSeenRef = yield* Ref.make(startSeq);\n return { subscription, viewRef, lastSeenRef };\n });\n\n const observeSubset = (subset: Subset.Subset) =>\n Stream.unwrap(\n Effect.gen(function* () {\n const { subscription, viewRef, lastSeenRef } = yield* initSubsetView(subset);\n const initial = LiveView.result(yield* Ref.get(viewRef));\n // Emit the page on each change, dropping re-emits when it didn't move\n // (e.g. a change outside the limit window, or a skipped stale seq).\n const readSubset = Effect.succeed(subset);\n return Stream.concat(\n Stream.succeed(initial),\n Stream.fromSubscription(subscription).pipe(\n Stream.mapEffect((item) => stepView(viewRef, lastSeenRef, readSubset, item))\n )\n ).pipe(Stream.changesWith(sameResult));\n })\n );\n\n const observeSubsetChanges = (\n subset: Subset.Subset,\n changeOptions?: ObserveChangesOptions\n ): Stream.Stream<ReadonlyArray<RowChange.RowChange<LocalRow>>, StoreError | MutatorError> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const { subscription, viewRef, lastSeenRef } = yield* initSubsetView(subset);\n const initialRows = LiveView.result(yield* Ref.get(viewRef));\n // `includeInitial` emits the current window as `enter`s in its own\n // batch — no `reset` marker, since there is nothing to reset from.\n const initial: ReadonlyArray<ReadonlyArray<RowChange.RowChange<LocalRow>>> =\n changeOptions?.includeInitial === true && Arr.isReadonlyArrayNonEmpty(initialRows)\n ? [RowChange.enters(initialRows)]\n : [];\n const readSubset = Effect.succeed(subset);\n return Stream.concat(\n Stream.fromIterable(initial),\n Stream.fromSubscription(subscription).pipe(\n Stream.mapEffect((item) => stepViewChanges(viewRef, lastSeenRef, readSubset, item)),\n Stream.filter((batch) => Arr.isReadonlyArrayNonEmpty(batch))\n )\n );\n })\n );\n\n // Engine-level reactive window retargeting (#133): unlike `observeSubset`\n // (whose subset is fixed for the stream's lifetime), this tracks the\n // *current* subset in a `Ref` that `retarget` can widen/advance, and a\n // `retargetTick` that wakes the stream to reslice immediately — without\n // waiting for an unrelated engine change, and without the caller\n // resubscribing (`observe(widerSubset)`, which would rebuild `LiveView`\n // from scratch instead of reusing the maintained order).\n const observeWindow = (\n subset: Subset.Subset\n ): Effect.Effect<WindowObservation, StoreError | MutatorError, Scope.Scope> =>\n Effect.gen(function* () {\n const { subscription, viewRef, lastSeenRef } = yield* initSubsetView(subset);\n const subsetRef = yield* Ref.make(subset);\n const retargetTick = yield* SubscriptionRef.make(0);\n // Subscribe to the retarget tick NOW, not when `rows` is eventually\n // pulled (#84's \"subscribe before snapshotting\" discipline, applied\n // here too): `SubscriptionRef.changes` builds a lazily-subscribing\n // stream, so a `retarget()` call between `observeWindow` returning\n // and the caller actually consuming `rows` would otherwise publish\n // to a PubSub nobody is listening to yet and be silently missed.\n const retargetSubscription = yield* PubSub.subscribe(retargetTick.pubsub);\n const initial = LiveView.result(yield* Ref.get(viewRef));\n\n const retarget: WindowObservation[\"retarget\"] = (window) =>\n Effect.gen(function* () {\n const previous = yield* Ref.get(subsetRef);\n const limit = window.limit !== undefined ? window.limit : previous.limit;\n const cursor = window.cursor !== undefined ? window.cursor : previous.cursor;\n if (limit === previous.limit && cursor === previous.cursor) return;\n const nextSubset: Subset.Subset = {\n ...previous,\n ...(limit !== undefined ? { limit } : {}),\n ...(cursor !== undefined ? { cursor } : {}),\n };\n yield* Ref.set(subsetRef, nextSubset);\n yield* Ref.update(viewRef, (view) => LiveView.retarget(view, window));\n // Widen this observation's tracked subscription entry in place —\n // matched by the *previous* subset's hash, since limit/cursor are\n // part of what `Subset.hash` covers — so the next pull fetches the\n // wider window from the server too. A caller that never\n // `subscribe`d this exact subset has no server-tracked entry to\n // widen; the local reslice above still runs over whatever rows\n // are already synced.\n const previousHash = Subset.hash(previous);\n yield* Ref.update(subscriptions, (current) =>\n current.map((s) => (Subset.hash(s) === previousHash ? nextSubset : s))\n );\n yield* SubscriptionRef.update(retargetTick, (n) => n + 1);\n });\n\n const readSubset = Ref.get(subsetRef);\n const engineChanges = Stream.fromSubscription(subscription).pipe(\n Stream.mapEffect((item) => stepView(viewRef, lastSeenRef, readSubset, item))\n );\n // The eager subscription above only ever delivers ticks published\n // *after* it was established — no replay of the seeded current\n // value (0) to skip, unlike `SubscriptionRef.changes`.\n const retargetChanges = Stream.fromSubscription(retargetSubscription).pipe(\n Stream.mapEffect(() => Ref.get(viewRef).pipe(Effect.map(LiveView.result)))\n );\n const rows = Stream.concat(\n Stream.succeed(initial),\n Stream.merge(engineChanges, retargetChanges)\n ).pipe(Stream.changesWith(sameResult));\n\n return { rows, retarget };\n });\n\n // Projected observe: map each page through `select` and drop consecutive\n // equal projections, so a change to a field the projection ignores never\n // re-emits. Without `select` it is the plain rows stream (whole-page dedup\n // still handled inside `observeSubset`).\n const observeProjected = <B>(\n subset: Subset.Subset,\n options?: ObserveOptions<LocalRow, B>\n ): Stream.Stream<B | ReadonlyArray<LocalRow>, StoreError | MutatorError> => {\n const base = observeSubset(subset);\n if (options === undefined) return base;\n const equals = options.equals ?? ((a: B, b: B) => a === b);\n return base.pipe(Stream.map(options.select), Stream.changesWith(equals));\n };\n\n const queryAggregate = (subset: Subset.Subset, agg: Aggregate.Aggregate) =>\n query(subset).pipe(Effect.map((rows) => Aggregate.compute(agg, rows)));\n const queryAggregateGrouped = (\n subset: Subset.Subset,\n agg: Aggregate.Aggregate,\n groupBy: string\n ) => query(subset).pipe(Effect.map((rows) => Aggregate.computeGrouped(agg, rows, groupBy)));\n\n // Route a Patch's ops (this subset's collection only) through an\n // incremental aggregate state. A Patch's ops are confirmed-row deltas\n // from a pull, or optimistic `OverlayOp`s a mutate's local handler just\n // performed (#109) — both shapes carry the `_tag`/`collection`/`id`/`value`\n // this reads. `Put` carries the raw new value — `Aggregate.applyPut`\n // re-tests `subset.where` itself to decide insert/update/remove, exactly\n // as `applyOps` does for `LiveView` above.\n const applyAggregatePatch = (\n state: Aggregate.State,\n agg: Aggregate.Aggregate,\n subset: Subset.Subset,\n ops: ReadonlyArray<PatchOp | OverlayOp>\n ): Aggregate.State => {\n let next = state;\n for (const op of ops) {\n if (op._tag === \"Clear\" || op.collection !== subset.collection) continue;\n next =\n op._tag === \"Put\"\n ? Aggregate.applyPut(next, agg, subset.where, op.id, op.value)\n : Aggregate.applyDel(next, agg, op.id);\n }\n return next;\n };\n const applyAggregateGroupedPatch = (\n state: Aggregate.GroupedState,\n agg: Aggregate.Aggregate,\n subset: Subset.Subset,\n groupBy: string,\n ops: ReadonlyArray<PatchOp | OverlayOp>\n ): Aggregate.GroupedState => {\n let next = state;\n for (const op of ops) {\n if (op._tag === \"Clear\" || op.collection !== subset.collection) continue;\n next =\n op._tag === \"Put\"\n ? Aggregate.applyGroupedPut(next, agg, subset.where, groupBy, op.id, op.value)\n : Aggregate.applyGroupedDel(next, agg, op.id);\n }\n return next;\n };\n\n /**\n * A push-based reducer over a subset's raw row ops, feeding\n * {@link observeAggregateSubset}: `init` builds state from a full\n * collection scan (subscribe time, `Rebuild`, and gap-collapse), `applyOps`\n * folds a `Patch`'s row-level deltas in place, and `value`/`sameValue`\n * extract + dedupe the observable result.\n */\n interface AggregateReducer<S, V> {\n readonly init: (rows: ReadonlyArray<LocalRow>) => S;\n readonly applyOps: (state: S, ops: ReadonlyArray<PatchOp | OverlayOp>) => S;\n readonly value: (state: S) => V;\n readonly sameValue: (a: V, b: V) => boolean;\n }\n\n // Live aggregate over a subset's raw row ops: mirrors `observeSubset`'s\n // seq/gap-collapse handling, but folds a `reducer`'s state instead of\n // maintaining a `LiveView`. A `Patch` folds only the ops it carries, in\n // place; a `Rebuild` (or a seq-gap collapse) re-derives state from a full\n // collection scan, same as the page-observing path's `LiveView.make`.\n const observeAggregateSubset = <S, V>(\n subset: Subset.Subset,\n reducer: AggregateReducer<S, V>\n ): Stream.Stream<V, StoreError | MutatorError> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const subscription = yield* PubSub.subscribe(changes);\n const startSeq = yield* Ref.get(changeSeq);\n const stateRef = yield* Ref.make(\n reducer.init(yield* collectionRowsArray(subset.collection))\n );\n const lastSeenRef = yield* Ref.make(startSeq);\n const initial = reducer.value(yield* Ref.get(stateRef));\n\n const applyContiguousAgg = (\n change: ViewChange\n ): Effect.Effect<V, StoreError | MutatorError> =>\n Effect.gen(function* () {\n const state = yield* Ref.get(stateRef);\n if (rebuildSkips(change, subset.collection)) return reducer.value(state);\n const next =\n change._tag === \"Rebuild\"\n ? reducer.init(yield* collectionRowsArray(subset.collection))\n : reducer.applyOps(state, change.ops);\n yield* Ref.set(stateRef, next);\n return reducer.value(next);\n });\n\n const collapseAggregateToRebuild: Effect.Effect<V, StoreError | MutatorError> =\n Effect.gen(function* () {\n yield* Metric.update(Telemetry.changeCollapsesTotal, 1);\n const latest = yield* Ref.get(changeSeq);\n const next = reducer.init(yield* collectionRowsArray(subset.collection));\n yield* Ref.set(stateRef, next);\n yield* Ref.set(lastSeenRef, latest);\n return reducer.value(next);\n });\n\n const stepAggregateView = (\n item: SeqChange\n ): Effect.Effect<V, StoreError | MutatorError> =>\n Effect.gen(function* () {\n const lastSeen = yield* Ref.get(lastSeenRef);\n if (item.seq <= lastSeen) return reducer.value(yield* Ref.get(stateRef));\n if (item.seq === lastSeen + 1) {\n yield* Ref.set(lastSeenRef, item.seq);\n return yield* applyContiguousAgg(item.change);\n }\n return yield* collapseAggregateToRebuild;\n });\n\n return Stream.concat(\n Stream.succeed(initial),\n Stream.fromSubscription(subscription).pipe(Stream.mapEffect(stepAggregateView))\n ).pipe(Stream.changesWith(reducer.sameValue));\n })\n );\n\n const observeAggregate = (subset: Subset.Subset, agg: Aggregate.Aggregate) =>\n isWindowed(subset)\n ? Aggregate.observe(observeSubset(subset), agg)\n : observeAggregateSubset(subset, {\n init: (rows) => Aggregate.initState(agg, Subset.apply(rows, subset)),\n applyOps: (state, ops) => applyAggregatePatch(state, agg, subset, ops),\n value: Aggregate.stateValue,\n sameValue: Aggregate.sameValue,\n });\n const observeAggregateGrouped = (\n subset: Subset.Subset,\n agg: Aggregate.Aggregate,\n groupBy: string\n ) =>\n isWindowed(subset)\n ? Aggregate.observeGrouped(observeSubset(subset), agg, groupBy)\n : observeAggregateSubset(subset, {\n init: (rows) => Aggregate.initGroupedState(agg, Subset.apply(rows, subset), groupBy),\n applyOps: (state, ops) => applyAggregateGroupedPatch(state, agg, subset, groupBy, ops),\n value: Aggregate.groupedStateValue,\n sameValue: Aggregate.sameGroupedValue,\n });\n\n const invalidArgs = (mutator: string) => (cause: unknown) =>\n new MutatorError({ message: `Invalid args for mutator \"${mutator}\"`, mutator, cause });\n // Journal a mutation and reveal its local effects. The whole body runs\n // under `overlayLock` (#109): appending to the store then tracking the\n // handler's effects directly onto the cached overlay must be atomic with\n // respect to `materialize`'s fill and any other mutation's tracked write,\n // or a concurrent invalidation (push ack, pull, seed) could be clobbered\n // by this call's stale `Ref.set` once it finishes (see `invalidateOverlay`).\n const journal = (\n mutator: string,\n encoded: unknown,\n decodedArgs: unknown,\n outcome?: Deferred.Deferred<MutationOutcome>\n ) =>\n Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n // Snapshot the journal *before* appending, so the tracked-write\n // fallback below replays exactly the mutations already pending —\n // not this one too (it is appended next, so `store.pendingMutations`\n // would otherwise double-count it: once from the replay, once from\n // `trackedWriter`). Only a cold overlay cache needs that replay: a\n // warm one already holds the pending set's effects, so the journal\n // (every pending body, on a durable store) is read only when the\n // cache is cold (#260). The lock held here keeps the cache as found\n // until `applyMutationToOverlayLocked` writes it.\n const cachedBefore = yield* Ref.get(overlayCache);\n const base: OverlayBase =\n cachedBefore === undefined\n ? { _tag: \"Cold\", journalBefore: yield* overlayJournalLocked }\n : { _tag: \"Warm\", view: cachedBefore };\n const clientId = yield* currentClientId;\n const journaledAt = yield* Clock.currentTimeMillis;\n // Allocate the id and append as one store step (#258): a refused or\n // failed append must not consume an id, or the next push hits a gap\n // the backends reject.\n const { mutationId } = yield* store.appendNext({\n clientId,\n mutator,\n args: encoded,\n createdAt: journaledAt,\n });\n // Register the `mutateWithAck` deferred before the lock is released:\n // a compaction (#249) also takes it, so the id cannot be renumbered\n // between being allocated and being keyed here.\n if (outcome !== undefined) {\n yield* Ref.update(acks, (map) => new Map(map).set(mutationId, outcome));\n }\n yield* sampleJournalDepth; // the append changed journal depth\n yield* SubscriptionRef.update(mutationStates, (map) =>\n MutationState.journaled(map, { mutationId, mutator, args: encoded, journaledAt })\n );\n yield* emitEvent(mutationId, \"journaled\");\n // Apply the handler's effects onto the cached overlay in place and\n // publish exactly what it did as a Patch, rather than invalidating\n // the cache and forcing every observer to re-materialize (#109).\n const change = yield* applyMutationToOverlayLocked(mutator, decodedArgs, base);\n yield* publishChange(change);\n yield* signalPush; // the sync loop may auto-push this (debounced)\n return mutationId;\n })\n );\n // Validate the decoded args now (fail fast at the call site) and produce the\n // journal's encoded (wire/persistence) form — shared by `mutate` and\n // `mutateWithAck`.\n const encodeFor = (mutator: string, args: unknown): Effect.Effect<unknown, MutatorError> =>\n Effect.gen(function* () {\n const definition = yield* definitionOf(mutator);\n return yield* Schema.encodeUnknownEffect(definition.args)(args).pipe(\n Effect.mapError(invalidArgs(mutator))\n );\n });\n\n // Validate encoded (wire) args by decoding them against the mutator's schema\n // — shared by `mutateEncoded` and `beginFormMutationEncoded`.\n const decodeFor = (mutator: string, encoded: unknown): Effect.Effect<unknown, MutatorError> =>\n Effect.gen(function* () {\n const definition = yield* definitionOf(mutator);\n return yield* Schema.decodeUnknownEffect(definition.args)(encoded).pipe(\n Effect.mapError(invalidArgs(mutator))\n );\n });\n\n // The client half of an enhanced form submit (ADR-0030 #215 §4). The entry\n // is overlaid under the form client's id but never journaled: the form\n // action delivers it. It holds one place of the tail's bound from the start\n // (`reserveChunk`), so parking it on acknowledgement never takes the tail\n // past the bound. A pull that covers the form client releases it from the\n // tail as it releases a pushed mutation (`acknowledgeLocked`).\n const engineScope = yield* Effect.scope;\n const signalPull = Effect.forkIn(pull.pipe(Effect.ignore), engineScope).pipe(Effect.asVoid);\n // `args.encoded` is what the tail persists; `args.decoded` is what the\n // local handler runs on.\n const beginForm = (form: FormClient, mutator: string, args: FormArgs) =>\n Effect.gen(function* () {\n const entry: Mutation = {\n clientId: form.clientId,\n mutationId: form.mutationId,\n mutator,\n args: args.encoded,\n createdAt: yield* Clock.currentTimeMillis,\n };\n const reserved = yield* reserveChunk(1);\n const change = yield* Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n const cachedBefore = yield* Ref.get(overlayCache);\n const base: OverlayBase =\n cachedBefore === undefined\n ? { _tag: \"Cold\", journalBefore: yield* overlayJournalLocked }\n : { _tag: \"Warm\", view: cachedBefore };\n yield* Ref.update(formsInFlight, (forms) => [...forms, entry]);\n return yield* applyMutationToOverlayLocked(mutator, args.decoded, base);\n })\n ).pipe(Effect.onError(() => releaseChunk(reserved)));\n yield* publishChange(change);\n const open = yield* Ref.make(true);\n // End the entry once: take it out of the in-flight list, park it when\n // `park` and it holds a place, give the place back, and pull.\n const end = (park: boolean) =>\n Effect.gen(function* () {\n if (!(yield* Ref.getAndSet(open, false))) return;\n // Whether parking succeeds or the store fails it, the entry has\n // left the in-flight list: rebuild the overlay and pull, so a\n // failed park shows the server's state rather than a stale overlay.\n yield* Semaphore.withPermit(\n overlayLock,\n Effect.gen(function* () {\n yield* Ref.update(formsInFlight, (forms) => forms.filter((m) => m !== entry));\n if (park && reserved > 0) {\n const held = yield* tailLocked;\n yield* store.parkUnpulled([entry]);\n yield* Ref.set(unpulled, [...held, entry]);\n }\n }).pipe(Effect.ensuring(Ref.set(overlayCache, undefined)))\n ).pipe(\n Effect.ensuring(\n releaseChunk(reserved).pipe(\n Effect.andThen(publishChange(REBUILD)),\n Effect.andThen(signalPull)\n )\n )\n );\n });\n const submission: FormSubmission = {\n form,\n settle: (ruling) => end(ruling.phase === \"acknowledged\"),\n abandon: end(false).pipe(Effect.ignore),\n };\n return submission;\n });\n\n // Resolve one named subscription to its local subset, skipping (undefined)\n // any whose args can no longer decode or whose query is unregistered — a\n // read-only best effort for introspection, never a failure.\n const resolveNamedSubset = (entry: {\n readonly name: string;\n readonly argsEncoded: unknown;\n }): Effect.Effect<Subset.Subset | undefined> =>\n queryDefOf(entry.name).pipe(\n Effect.flatMap(({ definition, local }) =>\n Schema.decodeUnknownEffect(definition.args)(entry.argsEncoded).pipe(\n Effect.map((decoded) => local(decoded))\n )\n ),\n Effect.catchTag([\"QueryError\", \"SchemaError\"], () => Effect.succeed(undefined))\n );\n\n // Read-only snapshot of every active subset: raw subscriptions plus each\n // named subscription resolved through its local factory. The introspection\n // seam — reads the Refs internally, exposes only the resolved subsets.\n const activeSubscriptions: Effect.Effect<ReadonlyArray<Subset.Subset>> = Effect.gen(\n function* () {\n const raw = yield* Ref.get(subscriptions);\n const named = yield* Ref.get(namedSubs);\n const resolved: Array<Subset.Subset> = [];\n for (const entry of named) {\n const subset = yield* resolveNamedSubset(entry);\n if (subset !== undefined) resolved.push(subset);\n }\n return [...raw, ...resolved];\n }\n );\n\n const transportRead = transport.read;\n return ClientEngine.of({\n mutate: (mutator, args) =>\n encodeFor(mutator, args).pipe(\n Effect.flatMap((encoded) => journal(mutator, encoded, args)),\n Effect.asVoid\n ),\n // Decoding validates the encoded form; the journal keeps it as-is.\n mutateEncoded: (mutator, args) =>\n decodeFor(mutator, args).pipe(\n Effect.flatMap((decoded) => journal(mutator, args, decoded)),\n Effect.asVoid\n ),\n mutateWithAck: (mutator, args) =>\n Effect.gen(function* () {\n const encoded = yield* encodeFor(mutator, args);\n const deferred = yield* Deferred.make<MutationOutcome>();\n const mutationId = yield* journal(mutator, encoded, args, deferred);\n return { mutationId, acknowledged: Deferred.await(deferred) };\n }),\n beginFormMutation: (form, mutator, args) =>\n encodeFor(mutator, args).pipe(\n Effect.flatMap((encoded) => beginForm(form, mutator, { encoded, decoded: args }))\n ),\n beginFormMutationEncoded: (form, mutator, args) =>\n // Decoding validates the encoded form; the tail keeps it as-is.\n decodeFor(mutator, args).pipe(\n Effect.flatMap((decoded) => beginForm(form, mutator, { encoded: args, decoded }))\n ),\n subscribe: subscribeSubset,\n seed,\n clearRows,\n ensureSubset,\n unsubscribe: (subset) =>\n Ref.update(subscriptions, (current) =>\n current.filter((s) => Subset.hash(s) !== Subset.hash(subset))\n ),\n subscribeQuery: (name, args) =>\n updateNamedSubs(name, args, (current, entry) =>\n current.some((e) => e.key === entry.key) ? current : [...current, entry]\n ).pipe(Effect.andThen(publishChange(REBUILD))),\n unsubscribeQuery: (name, args) =>\n updateNamedSubs(name, args, (current, entry) => current.filter((e) => e.key !== entry.key)),\n query: query as ClientEngine[\"query\"],\n queryNamed: (name, args) => localSubsetOf(name, args).pipe(Effect.flatMap(query)),\n observe: observeProjected as ClientEngine[\"observe\"],\n observeWindow,\n observeChanges: observeSubsetChanges as ClientEngine[\"observeChanges\"],\n queryAggregate,\n queryAggregateGrouped,\n observeAggregate,\n observeAggregateGrouped,\n observeNamed: (name, args) =>\n Stream.unwrap(localSubsetOf(name, args).pipe(Effect.map(observeSubset))),\n push,\n pull,\n pullCounts,\n dropIfPending,\n reset,\n identity: store.getIdentity,\n quarantines: store.quarantines,\n quarantinedMutations: store.quarantinedMutations,\n discardQuarantine: store.discardQuarantine,\n ...(transportRead === undefined\n ? {}\n : {\n readThrough: (subsets: ReadonlyArray<Subset.Subset>) =>\n transportRead({\n clientGroupId: options.clientGroupId,\n subsets,\n ...(options.schemaVersion === undefined\n ? {}\n : { schemaVersion: options.schemaVersion }),\n }).pipe(Effect.map((response) => response.rows)),\n }),\n runSync,\n syncFailures: Stream.fromPubSub(failures),\n engineEvents: Stream.fromPubSub(engineEventsHub),\n activeSubscriptions,\n // #36's mutation stream, now a filtered projection of the one hub (#45).\n mutationEvents: Stream.fromPubSub(engineEventsHub).pipe(\n Stream.map(toMutationEvent),\n Stream.filter((event): event is MutationEvent => event !== undefined)\n ),\n // #116's keyed mutation-state map: current value now, then every change.\n mutationStates: SubscriptionRef.changes(mutationStates),\n });\n });\n\n/** Layer building the engine from ClientStore + ClientTransport. */\nexport const layer = (\n options: ClientEngineOptions\n): Layer.Layer<ClientEngine, never, ClientStore | ClientTransport> =>\n Layer.effect(ClientEngine)(make(options));\n","/**\n * RpcTransport\n *\n * The default sync transport (ADR-0007): the protocol's push/pull/pokes\n * exposed as a typed `RpcGroup` over `effect/rpc`. The carrier is\n * whichever RPC protocol layer is provided — HTTP, WebSocket, worker, or\n * the in-memory test transport — so the customisable seam (ADR-0008) costs\n * nothing: bind `layerHandlers` to a ServerHandler server-side, provide an\n * `RpcClient.Protocol` client-side, and schema serialization, streaming,\n * and interruption are Effect's RPC machinery.\n */\n\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\nimport { FetchHttpClient } from \"effect/http\";\nimport { Rpc, RpcClient, RpcGroup, RpcSerialization } from \"effect/rpc\";\nimport * as Socket from \"effect/socket/Socket\";\nimport { TransportError } from \"./Errors.js\";\nimport {\n Poke,\n PullRequest,\n PullResponse,\n PushRequest,\n PushResponse,\n ReadRequest,\n ReadResponse,\n} from \"./Protocol.js\";\nimport { ClientTransport, ServerHandler } from \"./Transport.js\";\nimport * as Transport from \"./Transport.js\";\n\n/** The wire-serializable failure carried on sync RPCs. */\nexport class SyncRpcError extends Schema.TaggedError<\n SyncRpcError,\n { readonly brand: unique symbol }\n>()(\"SyncRpcError\", {\n message: Schema.String,\n}) {}\n\n/**\n * The sync protocol as a typed RPC group. Apps embedding it next to their\n * own RPCs can namespace it with `SyncRpcs.prefix(\"sync.\")`.\n */\nexport const SyncRpcs = RpcGroup.make(\n Rpc.make(\"push\", {\n payload: PushRequest,\n success: PushResponse,\n error: SyncRpcError,\n }),\n Rpc.make(\"pull\", {\n payload: PullRequest,\n success: PullResponse,\n error: SyncRpcError,\n }),\n Rpc.make(\"read\", {\n payload: ReadRequest,\n success: ReadResponse,\n error: SyncRpcError,\n }),\n Rpc.make(\"pokes\", {\n payload: { clientGroupId: Schema.String },\n success: Poke,\n stream: true,\n })\n);\n\n/** The sync RPCs ({@link SyncRpcs}) as a union of their definitions. */\nexport type SyncRpc = RpcGroup.Rpcs<typeof SyncRpcs>;\n\n// The RPC carrier's wire error schema carries only a message (SyncRpcError), so\n// a typed `VersionNotSupportedError` cannot survive it — it is mapped\n// best-effort to a SyncRpcError and reaches the client as a `TransportError`\n// (the tag is lost). Carriers that can carry the tag — notably the in-memory\n// `ServerHandler`/`ClientTransport` seam — preserve it, so `onUpdateNeeded`\n// fires there; over RPC the version rejection degrades to a transport failure\n// (#48). Preserving the tag over RPC would mean adding a schema-typed variant to\n// this group's error union — deferred.\nconst toRpcError = (error: { readonly message: string }): SyncRpcError =>\n new SyncRpcError({ message: error.message });\n\n/** Server side: implement the sync RPCs from an in-context ServerHandler. */\nexport const layerHandlers: Layer.Layer<\n Rpc.ToHandler<SyncRpc>,\n never,\n ServerHandler\n> = SyncRpcs.toLayer(\n Effect.gen(function* () {\n const handler = yield* ServerHandler;\n return SyncRpcs.of({\n push: (request) => handler.handlePush(request).pipe(Effect.mapError(toRpcError)),\n pull: (request) => handler.handlePull(request).pipe(Effect.mapError(toRpcError)),\n read: (request) => handler.handleRead(request).pipe(Effect.mapError(toRpcError)),\n pokes: ({ clientGroupId }) => handler.pokes(clientGroupId),\n });\n })\n);\n\nconst asTransportError = (cause: { readonly message: string }): TransportError =>\n new TransportError({ message: cause.message, cause });\n\n/** Options for the RPC client transport. */\nexport interface RpcTransportOptions {\n readonly clientGroupId: string;\n}\n\n/**\n * Adapt a generated `SyncRpcs` client into a ClientTransport. Connectivity\n * is reported as permanently \"connected\": RPC protocols reconnect (or fail\n * per call) internally, and sync stays correct over pull alone. Wrap the\n * result with `Transport.withInferredStatus` for behaviour-derived status\n * (and `Transport.withFallback` to degrade to a second carrier); in browsers\n * add `BrowserConnectivity.withBrowserConnectivity` on top.\n */\nexport const fromRpcClient = <E extends { readonly message: string }>(\n client: RpcClient.RpcClient<SyncRpc, E>,\n options: RpcTransportOptions\n): ClientTransport => ({\n push: (request) => client.push(request).pipe(Effect.mapError(asTransportError)),\n pull: (request) => client.pull(request).pipe(Effect.mapError(asTransportError)),\n read: (request) => client.read(request).pipe(Effect.mapError(asTransportError)),\n pokes: client\n .pokes({ clientGroupId: options.clientGroupId })\n .pipe(Stream.mapError(asTransportError)),\n status: Effect.succeed(\"connected\"),\n statusChanges: Stream.succeed(\"connected\"),\n});\n\n/** Build a ClientTransport over a real RPC protocol (HTTP, WebSocket, …). */\nexport const make = (\n options: RpcTransportOptions\n): Effect.Effect<ClientTransport, never, RpcClient.Protocol | Scope.Scope> =>\n RpcClient.make(SyncRpcs).pipe(Effect.map((client) => fromRpcClient(client, options)));\n\n/** Layer building the ClientTransport from an in-context RPC protocol. */\nexport const layer = (\n options: RpcTransportOptions\n): Layer.Layer<ClientTransport, never, RpcClient.Protocol> =>\n Layer.effect(ClientTransport)(make(options));\n\n// ─── The standard remote composition ─────────────────────────────────────────\n\n/** Options for {@link fromOrigin}. */\nexport interface FromOriginOptions {\n readonly clientGroupId: string;\n /** The sync server's origin, e.g. `https://sync.example.com`. */\n readonly origin: string;\n /** The HTTP POST route (the fallback carrier). Default `/sync`. */\n readonly httpPath?: string;\n /** The WebSocket route (the live carrier). Default `/sync-ws`. */\n readonly wsPath?: string;\n /**\n * Fallback tuning ({@link Transport.withFallback}). Defaults: sidelined\n * primaries retry after 30 seconds; each WebSocket call gets a 10-second\n * budget before the call falls to HTTP.\n */\n readonly fallback?: Transport.FallbackOptions;\n}\n\n/**\n * The standard remote transport: sync RPCs over a WebSocket (the live\n * path, pokes included) with plain HTTP POST as the fallback carrier —\n * `Client.make`'s `transport: { url }` shorthand builds exactly this.\n * Wrap with `BrowserConnectivity.withBrowserConnectivity`\n * (`@thomasfosterau/legation-browser`) for navigator-aware status in browsers.\n */\nexport const fromOrigin = (\n options: FromOriginOptions\n): Effect.Effect<ClientTransport, never, Scope.Scope> =>\n Effect.gen(function* () {\n const httpUrl = `${options.origin}${options.httpPath ?? \"/sync\"}`;\n const wsUrl = `${options.origin.replace(/^http/, \"ws\")}${options.wsPath ?? \"/sync-ws\"}`;\n // Layer.build ties each protocol's resources to the enclosing scope\n // (Effect.provide here would finalize them on return).\n const wsContext = yield* Layer.build(\n RpcClient.layerProtocolSocket().pipe(\n Layer.provide(Socket.layerWebSocket(wsUrl)),\n Layer.provide(Socket.layerWebSocketConstructorGlobal),\n Layer.provide(RpcSerialization.layerNdjson)\n )\n );\n const ws = yield* make({ clientGroupId: options.clientGroupId }).pipe(\n Effect.provide(wsContext)\n );\n const httpContext = yield* Layer.build(\n RpcClient.layerProtocolHttp({ url: httpUrl }).pipe(\n Layer.provide(RpcSerialization.layerNdjson),\n Layer.provide(FetchHttpClient.layer)\n )\n );\n const http = yield* make({ clientGroupId: options.clientGroupId }).pipe(\n Effect.provide(httpContext)\n );\n // primaryTimeout: a hanging WebSocket must not stall sync — time it\n // out, sideline it, serve through HTTP.\n return yield* Transport.withFallback(ws, http, {\n restoreAfter: options.fallback?.restoreAfter ?? \"30 seconds\",\n primaryTimeout: options.fallback?.primaryTimeout ?? \"10 seconds\",\n });\n });\n","/**\n * MirrorProtocol\n *\n * Schema-defined messages between mirrors and the engine host (ADR-0010).\n *\n * A **mirror** is the light half of the split the seam exists for: the\n * engine proper holds the durable replica and runs the sync loop — one per\n * origin — while each client context (a browser tab, an Electron window,\n * an extension, a CLI instance) holds a mirror: an in-memory copy of just\n * the subsets that context registered, hydrated and kept current by host\n * broadcasts, serving reads synchronously and forwarding writes to the\n * host journal. A read-replica + write-proxy of the engine, cheap enough\n * to have one per window; it holds no durable state (a mirror that dies\n * loses nothing — a new one re-registers and rehydrates) and can only\n * answer for registered keys (hence observing auto-registers). Mutations, subset subscriptions, named-query registrations,\n * and relational (`related`) registrations flow mirror → host;\n * acknowledgements, mirror updates (materialized subset rows, already\n * overlay-applied by the engine), and resolved relational updates flow\n * host → mirrors.\n *\n * Registrations carry a `mirrorId` so the host can refcount them across\n * mirrors (tear an engine registration down only when the last mirror\n * leaves) and release everything a departing mirror held via `Disconnect`.\n *\n * Mutator args travel in encoded (wire) form: the mirror validates/encodes\n * against its registry before posting, the host re-validates by decoding\n * (`ClientEngine.mutateEncoded`). Named-query args travel encoded the same\n * way (the host's engine decodes against its query registry).\n */\n\nimport type * as ClientEngine from \"./ClientEngine.js\";\nimport type * as Coverage from \"./Coverage.js\";\nimport * as Hash from \"./Hash.js\";\nimport type * as MutationState from \"./MutationState.js\";\nimport type * as Related from \"./Related.js\";\nimport * as Subset from \"./Subset.js\";\nimport * as Arr from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Order from \"effect/Order\";\nimport * as P from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\n\n/** Wire codec for one selected edge of a `related` registration. */\nexport const EdgeSelect = Schema.Struct({\n name: Schema.String,\n first: Schema.optional(Schema.Number),\n});\n\n/** The type {@link EdgeSelect} decodes to. */\nexport type EdgeSelect = typeof EdgeSelect.Type;\n\n/** Wire codec for one {@link MutationState.MutationState} entry (#116). */\nexport const MutationStateEntry = Schema.Struct({\n mutationId: Schema.Number,\n mutator: Schema.String,\n args: Schema.Unknown,\n phase: Schema.Literals([\"pending\", \"acknowledged\", \"rejected\", \"dropped\"]),\n reason: Schema.optional(Schema.String),\n journaledAt: Schema.Number,\n settledAt: Schema.optional(Schema.Number),\n});\n\n/** The type {@link MutationStateEntry} decodes to. */\nexport type MutationStateEntry = typeof MutationStateEntry.Type;\n\n// ─── Broadcast keys ──────────────────────────────────────────────────────────\n\n/** The broadcast key a named query's results are mirrored under. */\nexport const namedKey = (name: string, args: unknown): string =>\n `named:${name}:${Hash.contentHash(args)}`;\n\n/**\n * The broadcast key {@link ClientEngine.ClientEngine.mutationStates} is\n * mirrored under (#116) — a singleton, unparameterized registration (unlike\n * subsets/named queries, there is exactly one mutation-state map per engine).\n */\nexport const MUTATION_STATES_KEY = \"mutationStates\";\n\n/**\n * The broadcast key a `related` registration's resolved rows are mirrored\n * under. Each edge's window (`first`) is part of the key: reads differing\n * only in window are distinct registrations (ADR-0024).\n */\nexport const relatedKey = (\n collection: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | Related.EdgeSelect>\n): string => {\n const parts = edges\n .map((input) => (P.isString(input) ? { name: input } : input))\n .map((select) => (select.first === undefined ? select.name : `${select.name}#${select.first}`));\n return `related:${collection}:${Subset.hash(subset)}:${Arr.sort(parts, Order.String).join(\"+\")}`;\n};\n\n// ─── Enhanced form submits (#536) ─────────────────────────────────────────────\n\n/**\n * The reserved mutator name an enhanced form submit's begin travels under\n * (ADR-0030 #215 §4, #536). A mirror asks its host to begin a form mutation\n * with a `Mutate` naming this mutator, its args a {@link FormMutationBegin}.\n * A host that knows it answers `FormMutationBegun` or `FormMutationFailed`\n * and journals nothing. It travels as a `Mutate`, not a tag of its own, so a\n * host that predates it answers too: its engine has no such mutator, so it\n * replies `MutateError` and journals nothing, and the mirror reports that\n * the host is too old instead of waiting on a message the host dropped as\n * foreign traffic. No app mutator may take this name.\n */\nexport const FORM_MUTATION_MUTATOR = \"@thomasfosterau/legation/beginFormMutation\";\n\n/**\n * The args of a {@link FORM_MUTATION_MUTATOR} `Mutate`: the mirror the entry\n * belongs to (its `Disconnect`, or the liveness sweep, abandons it), the form\n * client, and the Mutation with its args in encoded (wire) form, which the\n * host decodes.\n */\nexport const FormMutationBegin = Schema.Struct({\n mirrorId: Schema.String,\n form: Schema.Struct({ clientId: Schema.String, mutationId: Schema.Number }),\n mutator: Schema.String,\n args: Schema.Unknown,\n});\n\n/** The decoded {@link FormMutationBegin}. */\nexport type FormMutationBegin = typeof FormMutationBegin.Type;\n\n/** Wire codec for {@link ClientEngine.FormRuling}: the ruling an `EndFormMutation` settles on. */\nexport const FormRuling = Schema.Union([\n Schema.Struct({ phase: Schema.Literal(\"acknowledged\") }),\n Schema.Struct({ phase: Schema.Literal(\"rejected\"), reason: Schema.String }),\n]);\n\n/** The decoded {@link FormRuling}; the same shape as {@link ClientEngine.FormRuling}. */\nexport type FormRuling = typeof FormRuling.Type;\n\n// ─── Mirror → host ────────────────────────────────────────────────────────────\n\n/** A message a mirror sends to the host. */\nexport type MirrorMessage =\n | {\n readonly _tag: \"Mutate\";\n readonly requestId: number;\n /**\n * The requesting mirror (#546). Its replies echo it, so a mirror ignores a\n * reply to another tab's request of the same `requestId`. Absent from a\n * mirror that predates it.\n */\n readonly mirrorId?: string;\n readonly mutator: string;\n readonly args: unknown;\n }\n | { readonly _tag: \"Subscribe\"; readonly mirrorId: string; readonly subset: Subset.Subset }\n | { readonly _tag: \"Unsubscribe\"; readonly mirrorId: string; readonly subset: Subset.Subset }\n | {\n readonly _tag: \"SubscribeNamed\";\n readonly mirrorId: string;\n readonly name: string;\n readonly args: unknown;\n }\n | {\n readonly _tag: \"UnsubscribeNamed\";\n readonly mirrorId: string;\n readonly name: string;\n readonly args: unknown;\n }\n | {\n readonly _tag: \"SubscribeRelated\";\n readonly mirrorId: string;\n readonly collection: string;\n readonly subset: Subset.Subset;\n /** The selected edges, each optionally windowed (ADR-0024). */\n readonly edges: ReadonlyArray<Related.EdgeSelect>;\n }\n | {\n readonly _tag: \"UnsubscribeRelated\";\n readonly mirrorId: string;\n readonly collection: string;\n readonly subset: Subset.Subset;\n readonly edges: ReadonlyArray<Related.EdgeSelect>;\n }\n /**\n * A URL-keyed subscription (ADR-0029 section 2, #159) from a party with\n * no `Client` of its own — a page posting on the channel. The host parses\n * the URL through its `UrlReads`, and registers the read's root window\n * and edge windows under `mirrorId` exactly as a mirror's `Subscribe` and\n * `SubscribeRelated` would: refcounted per party, replayed on `HostReady`\n * by the party, and reclaimed by the liveness sweep unless the party\n * heartbeats. A URL the host cannot parse registers nothing.\n */\n | { readonly _tag: \"SubscribeUrl\"; readonly mirrorId: string; readonly url: string }\n | { readonly _tag: \"UnsubscribeUrl\"; readonly mirrorId: string; readonly url: string }\n /** A server-fallthrough read (ADR-0025), answered by `ReadResult`. */\n | {\n readonly _tag: \"Read\";\n readonly requestId: number;\n /**\n * The requesting mirror (#546). Its replies echo it, so a mirror ignores a\n * reply to another tab's request of the same `requestId`. Absent from a\n * mirror that predates it.\n */\n readonly mirrorId?: string;\n readonly subsets: ReadonlyArray<Subset.Subset>;\n }\n /** Register interest in the mutation-state map (#116); see {@link MUTATION_STATES_KEY}. */\n | { readonly _tag: \"SubscribeMutationStates\"; readonly mirrorId: string }\n | { readonly _tag: \"UnsubscribeMutationStates\"; readonly mirrorId: string }\n /** A mirror leaving: release every subscription it held. */\n | { readonly _tag: \"Disconnect\"; readonly mirrorId: string }\n /** Liveness ping: lets the host reclaim subsets from mirrors that crash. */\n | { readonly _tag: \"Heartbeat\"; readonly mirrorId: string }\n /**\n * End an enhanced form submission begun with a {@link FORM_MUTATION_MUTATOR}\n * `Mutate` (#536): `ruling` settles it on the form action's receipt, and its\n * absence abandons it. `requestId` is the begin's. Answered by\n * `FormMutationEnded`, also when the host no longer holds the entry.\n */\n | {\n readonly _tag: \"EndFormMutation\";\n readonly mirrorId: string;\n readonly requestId: number;\n readonly ruling?: ClientEngine.FormRuling;\n };\n\n/** Wire codec for {@link MirrorMessage}. */\nexport const MirrorMessageSchema: Schema.Codec<MirrorMessage> = Schema.Union([\n Schema.Struct({\n _tag: Schema.tag(\"Mutate\"),\n requestId: Schema.Number,\n mirrorId: Schema.optional(Schema.String),\n mutator: Schema.String,\n args: Schema.Unknown,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"Subscribe\"),\n mirrorId: Schema.String,\n subset: Subset.Subset,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"Unsubscribe\"),\n mirrorId: Schema.String,\n subset: Subset.Subset,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"SubscribeNamed\"),\n mirrorId: Schema.String,\n name: Schema.String,\n args: Schema.Unknown,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"UnsubscribeNamed\"),\n mirrorId: Schema.String,\n name: Schema.String,\n args: Schema.Unknown,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"SubscribeRelated\"),\n mirrorId: Schema.String,\n collection: Schema.String,\n subset: Subset.Subset,\n edges: Schema.Array(EdgeSelect),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"UnsubscribeRelated\"),\n mirrorId: Schema.String,\n collection: Schema.String,\n subset: Subset.Subset,\n edges: Schema.Array(EdgeSelect),\n }),\n Schema.Struct({ _tag: Schema.tag(\"SubscribeUrl\"), mirrorId: Schema.String, url: Schema.String }),\n Schema.Struct({\n _tag: Schema.tag(\"UnsubscribeUrl\"),\n mirrorId: Schema.String,\n url: Schema.String,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"Read\"),\n requestId: Schema.Number,\n mirrorId: Schema.optional(Schema.String),\n subsets: Schema.Array(Subset.Subset),\n }),\n Schema.Struct({ _tag: Schema.tag(\"SubscribeMutationStates\"), mirrorId: Schema.String }),\n Schema.Struct({ _tag: Schema.tag(\"UnsubscribeMutationStates\"), mirrorId: Schema.String }),\n Schema.Struct({ _tag: Schema.tag(\"Disconnect\"), mirrorId: Schema.String }),\n Schema.Struct({ _tag: Schema.tag(\"Heartbeat\"), mirrorId: Schema.String }),\n Schema.Struct({\n _tag: Schema.tag(\"EndFormMutation\"),\n mirrorId: Schema.String,\n requestId: Schema.Number,\n ruling: Schema.optional(FormRuling),\n }),\n]) as Schema.Codec<MirrorMessage>;\n\n// ─── Host → mirrors ───────────────────────────────────────────────────────────\n\n/** A row as the host sends it to a mirror. */\nexport interface MirrorRow {\n readonly id: string;\n readonly value: unknown;\n}\n\n/** A resolved relational row on the wire: base row + its resolved names. */\nexport interface MirrorRelatedRow {\n readonly id: string;\n readonly value: unknown;\n readonly related: Readonly<Record<string, unknown>>;\n}\n\n/** A message the host sends to its mirrors. */\nexport type HostMessage =\n /**\n * Broadcast once when a host starts serving. Mirrors answer by re-posting\n * every registration they hold, so subscriptions survive a host that\n * (re)starts after the mirror — a killed service worker, or a client context\n * that raced the worker's boot.\n */\n | { readonly _tag: \"HostReady\" }\n | {\n readonly _tag: \"MutateAck\";\n readonly requestId: number;\n /**\n * The mirror the request came from (#546), echoed from the request. A\n * mirror ignores a reply addressed to another; a host that predates it\n * sends none, and the reply is taken by `requestId` alone.\n */\n readonly mirrorId?: string;\n }\n | {\n readonly _tag: \"MutateError\";\n readonly requestId: number;\n /**\n * The mirror the request came from (#546), echoed from the request. A\n * mirror ignores a reply addressed to another; a host that predates it\n * sends none, and the reply is taken by `requestId` alone.\n */\n readonly mirrorId?: string;\n readonly message: string;\n }\n /**\n * The backend's authoritative outcome for a forwarded mutation, correlated by\n * `requestId`. Sent in addition to `MutateAck` (which still fires on journal),\n * so a mirror can await the backend verdict via `Mirror.mutateWithAck`.\n */\n | {\n readonly _tag: \"MutateSettled\";\n readonly requestId: number;\n /**\n * The mirror the request came from (#546), echoed from the request. A\n * mirror ignores a reply addressed to another; a host that predates it\n * sends none, and the reply is taken by `requestId` alone.\n */\n readonly mirrorId?: string;\n readonly outcome: \"applied\" | \"rejected\";\n readonly reason?: string;\n }\n | {\n readonly _tag: \"MirrorUpdate\";\n /** `Subset.hash` of the subset (or {@link namedKey}) these rows materialize. */\n readonly key: string;\n readonly rows: ReadonlyArray<MirrorRow>;\n }\n | {\n readonly _tag: \"RelatedUpdate\";\n /** {@link relatedKey} of the registration these resolved rows materialize. */\n readonly key: string;\n readonly rows: ReadonlyArray<MirrorRelatedRow>;\n }\n /** The answer to a `Read` request (ADR-0025), correlated by `requestId`. */\n | {\n readonly _tag: \"ReadResult\";\n readonly requestId: number;\n /**\n * The mirror the request came from (#546), echoed from the request. A\n * mirror ignores a reply addressed to another; a host that predates it\n * sends none, and the reply is taken by `requestId` alone.\n */\n readonly mirrorId?: string;\n readonly rows: ReadonlyArray<{\n readonly collection: string;\n readonly id: string;\n readonly value: unknown;\n }>;\n /** Set instead of rows when the host could not serve the read. */\n readonly error?: string;\n }\n /** The whole mutation-state map, broadcast on every fold (#116). */\n | {\n readonly _tag: \"MutationStatesUpdate\";\n readonly states: ReadonlyArray<MutationState.MutationState>;\n }\n /**\n * The pulled summaries of the host's registrations (#426): per key (a\n * `Subscribe`'s subset hash, or a `SubscribeRelated`'s {@link relatedKey}),\n * each window the registration holds with whether its rows are in the\n * replica. A mirror answers a covered read locally only when the windows\n * the read's rows link to are pulled (`Coverage.pulledFor`). Sent whenever it\n * changes and on `HostReady`. A mirror that predates it ignores the message\n * (foreign traffic) and judges coverage from its registrations alone, as it\n * did before #426: it answers covered reads locally, so the #422 race (a\n * covered answer before its linked windows are pulled) persists for it until\n * it is upgraded.\n */\n | {\n readonly _tag: \"PulledRegistrations\";\n readonly registrations: ReadonlyArray<PulledRegistration>;\n }\n /**\n * A {@link FORM_MUTATION_MUTATOR} begin overlaid under its form client\n * (#536). The form replies carry the begin's `mirrorId` as well as its\n * `requestId`: host messages are broadcast to every mirror, and each\n * mirror numbers its requests from zero, so a `requestId` alone could\n * complete another tab's request.\n */\n | { readonly _tag: \"FormMutationBegun\"; readonly mirrorId: string; readonly requestId: number }\n /**\n * A {@link FORM_MUTATION_MUTATOR} begin the host refused (unknown Mutation,\n * args that do not decode, a store failure): nothing was overlaid. A\n * dedicated tag, so that `MutateError` for a begin means only \"this host\n * predates enhanced form submits\".\n */\n | {\n readonly _tag: \"FormMutationFailed\";\n readonly mirrorId: string;\n readonly requestId: number;\n readonly message: string;\n }\n /**\n * The answer to `EndFormMutation`, correlated by the begin's `requestId`.\n * `error` is set when settling failed in the host's store (the entry could\n * not be parked in the unpulled tail); the host rebuilt its overlay and\n * pulled regardless.\n */\n | {\n readonly _tag: \"FormMutationEnded\";\n readonly mirrorId: string;\n readonly requestId: number;\n readonly error?: string;\n };\n\n/** One registration's pulled summary, keyed as the host keys it. */\nexport interface PulledRegistration {\n readonly key: string;\n readonly pulled: Coverage.Pulled;\n}\n\n/** Wire codec for {@link HostMessage}. */\nexport const HostMessageSchema: Schema.Codec<HostMessage> = Schema.Union([\n Schema.Struct({ _tag: Schema.tag(\"HostReady\") }),\n Schema.Struct({\n _tag: Schema.tag(\"MutateAck\"),\n requestId: Schema.Number,\n mirrorId: Schema.optional(Schema.String),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"MutateError\"),\n requestId: Schema.Number,\n mirrorId: Schema.optional(Schema.String),\n message: Schema.String,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"MutateSettled\"),\n requestId: Schema.Number,\n mirrorId: Schema.optional(Schema.String),\n outcome: Schema.Literals([\"applied\", \"rejected\"]),\n reason: Schema.optional(Schema.String),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"MirrorUpdate\"),\n key: Schema.String,\n rows: Schema.Array(Schema.Struct({ id: Schema.String, value: Schema.Unknown })),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"RelatedUpdate\"),\n key: Schema.String,\n rows: Schema.Array(\n Schema.Struct({\n id: Schema.String,\n value: Schema.Unknown,\n related: Schema.Record(Schema.String, Schema.Unknown),\n })\n ),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"ReadResult\"),\n requestId: Schema.Number,\n mirrorId: Schema.optional(Schema.String),\n rows: Schema.Array(\n Schema.Struct({\n collection: Schema.String,\n id: Schema.String,\n value: Schema.Unknown,\n })\n ),\n error: Schema.optional(Schema.String),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"MutationStatesUpdate\"),\n states: Schema.Array(MutationStateEntry),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"PulledRegistrations\"),\n registrations: Schema.Array(\n Schema.Struct({\n key: Schema.String,\n pulled: Schema.Struct({\n windows: Schema.Array(\n Schema.Struct({\n subset: Subset.Subset,\n // oxlint-disable-next-line effect/require-is-prefix-for-boolean-schema-field -- `pulled` is a wire field of the mirror protocol (and mirrors `Coverage.Window.pulled`); renaming it breaks the protocol.\n pulled: Schema.Boolean,\n })\n ),\n }),\n })\n ),\n }),\n Schema.Struct({\n _tag: Schema.tag(\"FormMutationBegun\"),\n mirrorId: Schema.String,\n requestId: Schema.Number,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"FormMutationFailed\"),\n mirrorId: Schema.String,\n requestId: Schema.Number,\n message: Schema.String,\n }),\n Schema.Struct({\n _tag: Schema.tag(\"FormMutationEnded\"),\n mirrorId: Schema.String,\n requestId: Schema.Number,\n error: Schema.optional(Schema.String),\n }),\n]) as Schema.Codec<HostMessage>;\n\n/** Build a MirrorUpdate from materialized engine rows. */\nexport const mirrorUpdate = (\n key: string,\n rows: ReadonlyArray<ClientEngine.LocalRow>\n): HostMessage => ({\n _tag: \"MirrorUpdate\",\n key,\n rows: rows.map((row) => ({ id: row.id, value: row.value })),\n});\n\n/** Build a RelatedUpdate from resolved relational rows. */\nexport const relatedUpdate = (\n key: string,\n rows: ReadonlyArray<Related.RelatedRow>\n): HostMessage => ({\n _tag: \"RelatedUpdate\",\n key,\n rows: rows.map((row) => ({ id: row.id, value: row.value, related: row.related })),\n});\n\n/** Build a MutationStatesUpdate from the engine's current mutation-state map (#116). */\nexport const mutationStatesUpdate = (states: MutationState.MutationStateMap): HostMessage => ({\n _tag: \"MutationStatesUpdate\",\n states: [...HashMap.values(states)],\n});\n\nconst decodeTab = Schema.decodeUnknownEffect(MirrorMessageSchema);\nconst decodeHost = Schema.decodeUnknownEffect(HostMessageSchema);\n\n/** Decode an inbound mirror message; `undefined` for foreign traffic. */\nexport const decodeMirrorMessage = (input: unknown): Effect.Effect<MirrorMessage | undefined> =>\n decodeTab(input).pipe(Effect.orElseSucceed(() => undefined));\n\n/** Decode an inbound host message; `undefined` for foreign traffic. */\nexport const decodeHostMessage = (input: unknown): Effect.Effect<HostMessage | undefined> =>\n decodeHost(input).pipe(Effect.orElseSucceed(() => undefined));\n","/**\n * Coverage\n *\n * Whether a subscription in a Client's ledger **covers** a read, so the\n * read can be answered from the replica (ADR-0029 section 3, superseding\n * ADR-0025's exact-hash rule). Pure functions over compiled windows: no\n * evaluator runs at coverage time, so the check is syntactic and total and\n * cannot disagree with ADR-0028's semantics. A false negative costs one\n * server round trip; a false positive is impossible by construction.\n *\n * A subscription covers a request iff all of the following hold.\n *\n * 1. **Collection.** The same collection.\n * 2. **Window.** The subscription is unwindowed (neither `limit` nor\n * `cursor`), or the request asks for a prefix of the identical window:\n * the same `orderBy`, the same cursor and, when the subscription is\n * limited, a limit at most the subscription's. A windowed subscription\n * never covers an unwindowed request, a different sort or a different\n * cursor. A cursor alone is a window: `Subset.window` applies it\n * regardless of `limit`, so a cursored subscription holds only the rows\n * after its cursor in its order.\n * 3. **Predicate.** Both predicates canonicalise to a set of top-level\n * conjuncts (nested `And` flattened, then sorted structurally; an absent\n * `where`, `True` and an empty `And` are the empty set). An unwindowed\n * subscription covers when its set is a subset of the request's: every\n * row the request wants satisfies the subscription's conjuncts too, so\n * it is in the replica, and the request's extra conjuncts filter\n * locally. A windowed subscription holds a window of *its* predicate's\n * rows and nothing else is promised, so it covers only the same\n * conjunct set: a narrower request over a window may need rows past the\n * limit, or place its cursor differently, than what synced (the ADR's\n * \"strict window\").\n * 4. **Include.** Every edge the request includes is among the\n * subscription's edge selects (those are what register the foreign\n * windows, ADR-0024), and a paginated edge's `first` is at most the\n * subscription's, or the subscription's select is unwindowed.\n *\n * Structural equality is by {@link structuralKey}: `Compare`, `In`, `NotIn`\n * and `IsNull` nodes agree on operator, field and typed literal, with\n * `In`/`NotIn` lists in canonical order; `Or`, `Not` and `Exists` subtrees\n * compare as whole conjuncts and nothing is inferred through them. Full\n * implication (`lt(\"price\", 10)` under `lt(\"price\", 20)`, an `In` over a\n * superset list) is deliberately not built (ADR-0029 section 3).\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Order from \"effect/Order\";\nimport type * as Collection from \"./Collection.js\";\nimport type { LocalRow } from \"./ClientEngine.js\";\nimport type * as Node from \"./Node.js\";\nimport * as Predicate from \"./Predicate.js\";\nimport * as Query from \"./Query.js\";\nimport * as Related from \"./Related.js\";\nimport * as Subset from \"./Subset.js\";\n\n/**\n * What a subscription registers and a request asks for: the root window\n * plus the edge selects that register (or would resolve through) the\n * foreign windows. The unit {@link coversRegistration} compares.\n */\nexport interface Registration {\n readonly root: Subset.Subset;\n readonly edges: ReadonlyArray<Related.EdgeSelect>;\n}\n\n/** The registration a compiled read declares: its root window and edge selects. */\nexport const ofPlan = (plan: Query.Plan): Registration => ({\n root: plan.root,\n edges: Query.edgeSelects(plan),\n});\n\n/**\n * A registration as a ledger holds it: what it covers, and its canonical\n * URL — the subscription identity of ADR-0029 section 2 — when the ledger\n * knows one. A Client's ledger entries and the registrations an\n * `EngineHost` holds on mirrors' behalf are both this shape, so one\n * {@link verdictOf} scans either.\n */\nexport interface Subscription extends Registration {\n readonly url?: string;\n}\n\n/**\n * The outcome of a coverage check, recorded for devtools: which\n * subscription (by registration, subset hash and — when the subscription\n * has a URL form — canonical URL, the identity of ADR-0029 section 2)\n * answered a read locally, or that none did and the read fell through.\n */\nexport type Verdict =\n | {\n readonly _tag: \"Covered\";\n readonly by: Registration;\n readonly hash: string;\n readonly url?: string;\n }\n | { readonly _tag: \"Uncovered\" };\n\n// ─── Structural keys ─────────────────────────────────────────────────────────\n\n/** A literal's key: its type and its value, so `\"1\"` and `1` never collide. */\nconst literalKey = (literal: Predicate.Literal): string =>\n literal === null ? \"null\" : `${typeof literal}:${JSON.stringify(literal)}`;\n\n/** Deduplicate and sort keys (plain string order; only determinism matters). */\nconst sortedUnique = (keys: ReadonlyArray<string>): ReadonlyArray<string> =>\n Arr.sort(new Set(keys), Order.String);\n\ntype Junction = \"And\" | \"Or\";\n\n/** Flatten nested junctions of one kind: `And(a, And(b, c))` is `And(a, b, c)`. */\nconst flatten = (\n tag: Junction,\n members: ReadonlyArray<Predicate.Predicate>\n): ReadonlyArray<Predicate.Predicate> =>\n members.flatMap((member) => (member._tag === tag ? flatten(tag, member.predicates) : [member]));\n\n/**\n * The key of a junction: members flattened, keyed, deduplicated and sorted\n * (commutativity and idempotence are syntactic facts of `And`/`Or`). A\n * single member is the member itself; an empty `And` is `True`.\n */\nconst junctionKey = (tag: Junction, members: ReadonlyArray<Predicate.Predicate>): string => {\n const keys = sortedUnique(flatten(tag, members).map(structuralKey));\n const first = keys[0];\n if (keys.length === 1 && first !== undefined) return first;\n if (Arr.isReadonlyArrayEmpty(keys) && tag === \"And\") return \"True\";\n return `${tag}(${keys.join(\",\")})`;\n};\n\ntype Leaf = Extract<\n Predicate.Predicate,\n { _tag: \"True\" | \"Compare\" | \"In\" | \"NotIn\" | \"IsNull\" | \"InSet\" }\n>;\n\n/** The key of a leaf: operator, field and typed literal(s), lists in canonical order. */\nconst leafKey = (leaf: Leaf): string => {\n switch (leaf._tag) {\n case \"True\":\n return \"True\";\n case \"Compare\":\n return `Compare(${leaf.op},${JSON.stringify(leaf.field)},${literalKey(leaf.value)})`;\n case \"In\":\n case \"NotIn\":\n return `${leaf._tag}(${JSON.stringify(leaf.field)},[${sortedUnique(leaf.values.map(literalKey)).join(\",\")}])`;\n case \"IsNull\":\n return `IsNull(${JSON.stringify(leaf.field)},${leaf.negated === true})`;\n case \"InSet\":\n return `InSet(${literalKey(leaf.field)},${literalKey(leaf.set)})`;\n }\n};\n\n/**\n * A deterministic serialisation of a predicate for structural equality and\n * sorting. Unlike `Subset.hash` (`JSON.stringify`, key-order dependent) it\n * is canonical: junctions are flattened and their members sorted, `In` and\n * `NotIn` lists are sorted and deduplicated, literals carry their type, and\n * `IsNull` with `negated: false` keys as without it. Two predicates with\n * the same key are equal as `WHERE` clauses; the converse is not claimed.\n */\nexport const structuralKey = (predicate: Predicate.Predicate): string => {\n switch (predicate._tag) {\n case \"And\":\n case \"Or\":\n return junctionKey(predicate._tag, predicate.predicates);\n case \"Not\":\n return `Not(${structuralKey(predicate.predicate)})`;\n case \"Exists\":\n return `Exists(${JSON.stringify(predicate.collection)},${JSON.stringify(predicate.localField)},${JSON.stringify(predicate.foreignField)},${structuralKey(predicate.where)})`;\n default:\n return leafKey(predicate);\n }\n};\n\n// ─── Canonical conjuncts (rule 3) ────────────────────────────────────────────\n\n/** One top-level conjunct with its structural key (computed once). */\nexport interface Conjunct {\n readonly key: string;\n readonly predicate: Predicate.Predicate;\n}\n\n/**\n * A predicate as its set of top-level conjuncts: nested `And` flattened,\n * `True` members dropped, duplicates removed, sorted by\n * {@link structuralKey}. An absent `where`, `True` and an empty `And` all\n * yield the empty set. `Or`, `Not` and `Exists` members stay whole.\n */\nexport const canonicalConjuncts = (predicate: Predicate.Predicate): ReadonlyArray<Conjunct> => {\n const byKey = new Map<string, Predicate.Predicate>();\n Arr.forEach(flatten(\"And\", [predicate]), (member) => {\n const key = structuralKey(member);\n if (key !== \"True\" && !byKey.has(key)) byKey.set(key, member);\n });\n return Arr.sort(\n byKey.entries(),\n Order.mapInput(Order.String, ([key]: readonly [string, Predicate.Predicate]) => key)\n ).map(([key, member]) => ({ key, predicate: member }));\n};\n\nconst conjunctKeys = (predicate: Predicate.Predicate): ReadonlyArray<string> =>\n canonicalConjuncts(predicate).map((conjunct) => conjunct.key);\n\n/** A request's predicate canonicalised once, for a scan across many subscriptions. */\ninterface RequestedKeys {\n readonly keys: ReadonlyArray<string>;\n readonly keySet: ReadonlySet<string>;\n}\n\nconst requestedKeysOf = (predicate: Predicate.Predicate): RequestedKeys => {\n const keys = conjunctKeys(predicate);\n return { keys, keySet: new Set(keys) };\n};\n\nconst subsumedBy = (subscribed: ReadonlyArray<string>, requested: ReadonlySet<string>): boolean =>\n subscribed.every((key) => requested.has(key));\n\nconst sameKeys = (subscribed: ReadonlyArray<string>, requested: ReadonlyArray<string>): boolean =>\n subscribed.length === requested.length &&\n subscribed.every((key, index) => key === requested[index]);\n\n/**\n * Rule 3 for an unwindowed subscription: the subscription's conjunct set is\n * a subset of the request's under structural equality, so every row the\n * request wants is in the replica.\n */\nexport const subsumes = (\n subscribed: Predicate.Predicate,\n requested: Predicate.Predicate\n): boolean => subsumedBy(conjunctKeys(subscribed), new Set(conjunctKeys(requested)));\n\n/** Whether two predicates are the same conjunct set (rule 3 under a windowed subscription). */\nexport const sameConjuncts = (\n subscribed: Predicate.Predicate,\n requested: Predicate.Predicate\n): boolean => sameKeys(conjunctKeys(subscribed), conjunctKeys(requested));\n\n// ─── Windows (rule 2) ────────────────────────────────────────────────────────\n\n/**\n * Whether a subset holds a window rather than the whole predicate: a\n * `limit`, a `cursor`, or both. `Query.plan` emits a cursor without a limit\n * for `{ after }` alone, and `Subset.window` applies it regardless.\n */\nexport const isWindowed = (subset: Subset.Subset): boolean =>\n subset.limit !== undefined || subset.cursor !== undefined;\n\nconst sameOrder = (\n subscribed: ReadonlyArray<Subset.OrderBy>,\n requested: ReadonlyArray<Subset.OrderBy>\n): boolean =>\n subscribed.length === requested.length &&\n subscribed.every(\n (term, index) =>\n term.field === requested[index]?.field && term.direction === requested[index]?.direction\n );\n\n/** An unlimited subscription holds every row after its cursor; a limited one a prefix. */\nconst limitPrefix = (subscribed: number | undefined, requested: number | undefined): boolean =>\n subscribed === undefined || (requested !== undefined && requested <= subscribed);\n\n/**\n * Rule 2: an unwindowed subscription covers any window; a windowed one\n * covers only a prefix of the identical window (same order, same cursor,\n * and a limit at most its own when it has one).\n */\nexport const coversWindow = (subscribed: Subset.Subset, requested: Subset.Subset): boolean =>\n !isWindowed(subscribed) ||\n (requested.cursor === subscribed.cursor &&\n sameOrder(subscribed.orderBy, requested.orderBy) &&\n limitPrefix(subscribed.limit, requested.limit));\n\n/** Rule 3 as it depends on rule 2, over a request canonicalised once. */\nconst coversKeys = (subscribed: Subset.Subset, requested: RequestedKeys): boolean =>\n isWindowed(subscribed)\n ? sameKeys(conjunctKeys(subscribed.where), requested.keys)\n : subsumedBy(conjunctKeys(subscribed.where), requested.keySet);\n\n/**\n * Rule 3 as it depends on rule 2: an unwindowed subscription's conjuncts\n * need only be a subset of the request's; a windowed subscription holds a\n * window of *its* predicate's rows, so the conjunct sets must be the same.\n */\nexport const coversPredicate = (subscribed: Subset.Subset, requested: Subset.Subset): boolean =>\n coversKeys(subscribed, requestedKeysOf(requested.where));\n\n/** Rules 1 to 3: whether a subscribed root window covers a requested one. */\nexport const covers = (subscribed: Subset.Subset, requested: Subset.Subset): boolean =>\n subscribed.collection === requested.collection &&\n coversWindow(subscribed, requested) &&\n coversPredicate(subscribed, requested);\n\n// ─── Includes (rule 4) ───────────────────────────────────────────────────────\n\n/** One requested edge select against one held select: same edge, window a prefix. */\nconst coversEdge = (subscribed: Related.EdgeSelect, requested: Related.EdgeSelect): boolean =>\n subscribed.name === requested.name && limitPrefix(subscribed.first, requested.first);\n\n/**\n * Rule 4: every requested edge is among the subscription's edge selects,\n * and a paginated edge's window is at most the subscription's (or the\n * subscription's select is unwindowed). Edge order is declared by the edge\n * (ADR-0024), so it never differs.\n */\nexport const coversEdges = (\n subscribed: ReadonlyArray<Related.EdgeSelect>,\n requested: ReadonlyArray<Related.EdgeSelect>\n): boolean => requested.every((edge) => subscribed.some((held) => coversEdge(held, edge)));\n\n// ─── The rule ────────────────────────────────────────────────────────────────\n\n/** A request canonicalised once for a scan: its registration plus its conjunct keys. */\ninterface CanonicalRequest extends Registration, RequestedKeys {}\n\nconst canonical = (requested: Registration): CanonicalRequest => ({\n ...requested,\n ...requestedKeysOf(requested.root.where),\n});\n\n/** All four rules against a request canonicalised once. */\nconst coversCanonical = (subscribed: Registration, requested: CanonicalRequest): boolean =>\n subscribed.root.collection === requested.root.collection &&\n coversWindow(subscribed.root, requested.root) &&\n coversKeys(subscribed.root, requested) &&\n coversEdges(subscribed.edges, requested.edges);\n\n/** All four rules: whether a subscription's registration covers a request's. */\nexport const coversRegistration = (subscribed: Registration, requested: Registration): boolean =>\n coversCanonical(subscribed, canonical(requested));\n\n/**\n * The first subscription, in iteration order, covering a request — or\n * `undefined` when none does. The request is canonicalised once; each\n * check is then a small structural comparison, O(#subscriptions) in all. A\n * ledger index by collection is the refinement if a real app holds\n * hundreds.\n */\nexport const covering = <S extends Registration>(\n subscriptions: Iterable<S>,\n requested: Registration\n): S | undefined => {\n const request = canonical(requested);\n return Option.getOrUndefined(\n Arr.findFirst(subscriptions, (subscription) => coversCanonical(subscription, request))\n );\n};\n\n// ─── Pulled windows (#426) ───────────────────────────────────────────────────\n\n/**\n * One window a registration holds and whether its rows are in the replica:\n * pulled once a pull that started after it was held has applied, or once an\n * already-pulled window covers it (`PullMarks`).\n */\nexport interface PulledWindow {\n readonly subset: Subset.Subset;\n readonly pulled: boolean;\n}\n\n/**\n * What a registration's windows hold in the replica (ADR-0029 section 3,\n * #426): every window it holds, the root included, each with its own mark.\n * Marked per window by `PullMarks`, so a window added later does not move\n * the others, and a read is judged only by the windows its rows link to.\n */\nexport interface Pulled {\n readonly windows: ReadonlyArray<PulledWindow>;\n}\n\n/** A registration none of whose windows is pulled. */\nexport const NOT_PULLED: Pulled = { windows: [] };\n\n/**\n * A window's identity: its collection, canonical predicate, order, limit and\n * cursor. Unlike `Subset.hash`, key order does not matter, so a window a\n * mirror decoded from a message matches the one a read builds locally.\n */\nexport const windowKey = (window: Subset.Subset): string =>\n JSON.stringify([\n window.collection,\n structuralKey(window.where),\n window.orderBy.map((term) => [term.field, term.direction]),\n window.limit ?? null,\n window.cursor ?? null,\n ]);\n\n/** The field and the values an unwindowed window pins: `field IN (...)` or `field = value`. */\nconst pinnedOf = (\n where: Predicate.Predicate\n): { readonly field: string; readonly values: ReadonlyArray<string> } | undefined => {\n if (where._tag === \"In\") return { field: where.field, values: where.values.map(literalKey) };\n if (where._tag === \"Compare\" && where.op === \"eq\") {\n return { field: where.field, values: [literalKey(where.value)] };\n }\n return undefined;\n};\n\n/** Whether a window is held and pulled exactly (its identity), with no covering: the root's check. */\nconst heldPulled = (held: ReadonlyArray<PulledWindow>, window: Subset.Subset): boolean => {\n const key = windowKey(window);\n return held.some((entry) => entry.pulled && windowKey(entry.subset) === key);\n};\n\n/**\n * Whether the rows of one window are in the replica. A pulled window that\n * covers it under rules 1 to 3 is (the same window, or a prefix of it, or an\n * unwindowed window over its predicate; ADR-0029 section 3). An unwindowed\n * window (`field IN (...)` or `field = value`) is also, when pulled unwindowed\n * windows of its collection pin every one of its values: their rows are the\n * rows it reads.\n */\nconst windowPulled = (held: ReadonlyArray<PulledWindow>, window: Subset.Subset): boolean => {\n const key = windowKey(window);\n if (\n held.some(\n (entry) => entry.pulled && (windowKey(entry.subset) === key || covers(entry.subset, window))\n )\n ) {\n return true;\n }\n if (isWindowed(window)) return false;\n const wanted = pinnedOf(window.where);\n if (wanted === undefined) return false;\n const have = new Set<string>();\n Arr.forEach(held, (entry) => {\n if (!entry.pulled || isWindowed(entry.subset)) return;\n if (entry.subset.collection !== window.collection) return;\n const pinned = pinnedOf(entry.subset.where);\n if (pinned === undefined || pinned.field !== wanted.field) return;\n Arr.forEach(pinned.values, (value) => {\n have.add(value);\n });\n });\n return wanted.values.every((value) => have.has(value));\n};\n\n/**\n * The root rows a caller read once for a request, with the subset they are of. A\n * verdict judged over `rows` is judged over exactly the rows the caller answers from,\n * not a second read that a pull may have moved (#426).\n */\nexport interface Snapshot {\n readonly subset: Subset.Subset;\n readonly rows: ReadonlyArray<LocalRow>;\n}\n\n/**\n * How a coverage check is judged. `snapshot` is used only for the subset it names:\n * any other subset is read through the ledger's own rows, so a snapshot of another\n * collection cannot under-judge a read. An options bag rather than a positional\n * argument, so a caller that passes the check to `Effect.forEach` (which passes an\n * index second) gets no snapshot instead of a wrong one.\n */\nexport interface JudgeOptions {\n readonly snapshot?: Snapshot | undefined;\n}\n\n/**\n * The rows of a snapshot as a {@link RowsOf}: the snapshot's rows for the subset it\n * is of (#426), and `rowsOf` for any other subset.\n */\nexport const snapshotOf =\n <E>(snapshot: Snapshot, rowsOf: RowsOf<E>): RowsOf<E> =>\n (subset) =>\n Subset.hash(subset) === Subset.hash(snapshot.subset)\n ? Effect.succeed(snapshot.rows)\n : rowsOf(subset);\n\n/**\n * A request as the coverage scan takes it: its registration, plus the edge\n * windows its rows link to (`Related.windowsFor` over the root rows it reads).\n * A read whose rows link to no edge window needs only its root pulled.\n */\nexport interface Requested extends Registration {\n readonly windows: ReadonlyArray<Subset.Subset>;\n}\n\n/** The replica's rows of a subset, as the coverage check reads them. */\nexport type RowsOf<E> = (subset: Subset.Subset) => Effect.Effect<ReadonlyArray<LocalRow>, E>;\n\n/**\n * A compiled read's request: its registration, and the edge windows its root\n * rows link to, read from the replica through `rowsOf`. Fails with what\n * `rowsOf` fails with; callers judge that as uncovered.\n */\nexport const requestedOf = <E>(\n registry: Collection.CollectionRegistry,\n plan: Query.Plan,\n rowsOf: RowsOf<E>\n): Effect.Effect<Requested, E> => {\n const registration = ofPlan(plan);\n if (Arr.isReadonlyArrayEmpty(registration.edges))\n return Effect.succeed({ ...registration, windows: [] });\n return rowsOf(plan.root).pipe(\n Effect.map((rows) => ({\n ...registration,\n windows: Related.windowsFor(registry, plan.root.collection, registration.edges, rows),\n }))\n );\n};\n\n/** A ledger entry as the scan takes it: a subscription with its pulled summary. */\nexport interface Entry extends Subscription {\n readonly pulled: Pulled;\n}\n\n/**\n * Whether a ledger entry's windows cover a request's: its root window is held\n * and pulled, and every edge window the request's rows link to is pulled\n * (`windowPulled`). An edge window the request needs and the entry does not\n * hold is not pulled, so a read is never answered from the replica before the\n * rows it links to have arrived (#426).\n */\nexport const pulledFor = (entry: Entry, requested: Requested): boolean =>\n heldPulled(entry.pulled.windows, entry.root) &&\n requested.windows.every((window) => windowPulled(entry.pulled.windows, window));\n\n// ─── The verdict ─────────────────────────────────────────────────────────────\n\n/**\n * The verdict of one scan: the first pulled entry, in iteration order,\n * covering the request — named by registration, subset hash and canonical\n * URL when it has one — or `Uncovered`. `Client.coverageOf` and a façade's\n * coverage check over a host's registrations both answer with this.\n */\nexport const verdictOf = (entries: Iterable<Entry>, requested: Requested): Verdict => {\n const by = covering(\n [...entries].filter((entry) => pulledFor(entry, requested)),\n requested\n );\n return by === undefined\n ? { _tag: \"Uncovered\" }\n : {\n _tag: \"Covered\",\n by: { root: by.root, edges: by.edges },\n hash: Subset.hash(by.root),\n ...(by.url === undefined ? {} : { url: by.url }),\n };\n};\n\n/**\n * A coverage check in `Client.coverageOf`'s shape over any ledger: the read\n * is compiled against the graph, its root rows read through `rowsOf` (the\n * replica's `query`), and its\n * registration scanned against the entries the ledger holds at that moment. A\n * façade in a service worker builds its check from the host's registrations\n * (`EngineHost.Host.registrations`), where no Client's ledger sees the\n * mirrors' pins. A failed read of the rows is uncovered: the read goes to the\n * server. `options.snapshot`, when given, is judged over for the subset it names (see {@link JudgeOptions}).\n */\nexport const coverageOf =\n <E>(nodes: Node.NodeRegistry, rowsOf: RowsOf<E>, entries: Effect.Effect<Iterable<Entry>>) =>\n (read: Query.Read, options?: JudgeOptions): Effect.Effect<Verdict> =>\n requestedOf(\n nodes.collections,\n Query.plan(nodes, read),\n options?.snapshot === undefined ? rowsOf : snapshotOf(options.snapshot, rowsOf)\n ).pipe(\n Effect.flatMap((requested) => Effect.map(entries, (held) => verdictOf(held, requested))),\n // oxlint-disable-next-line effect/effect-catchall-default -- `E` is the caller's generic row-read error, so its tags are not known here; any failed read is uncovered by contract.\n Effect.catch(() => Effect.succeed<Verdict>({ _tag: \"Uncovered\" }))\n );\n","/**\n * PullMarks\n *\n * Whether a registration's windows have their rows in the replica yet\n * (ADR-0029 section 3, #426). Marks are kept **per window**: each subset an\n * engine is asked to hold gets its own mark, taken when it is first held.\n * A window is **pulled** once a pull numbered above the engine's count at\n * that moment has applied: a pull already in flight may predate it, so it\n * never counts. A window is also pulled when some other pulled window\n * covers it under {@link Coverage.covers}, since then its rows are in the\n * replica already. Adding a window to a relational registration therefore\n * leaves the windows it already had as they were.\n *\n * A registration (its ledger key: the subset hash, or the relational key of\n * {@link MirrorProtocol.relatedKey}) reports a {@link Coverage.Pulled}\n * summary: each window it holds, root included, with its mark. A read is\n * covered only when the windows its rows link to are pulled\n * (`Coverage.pulledFor`); an edge window the registration does not hold is\n * not pulled, so a root that is pulled alone never covers a relational read.\n *\n * Marks are recomputed on every construction, never persisted: after a\n * restart nothing is pulled and a covered read is forwarded until a pull\n * lands.\n */\n\nimport * as Effect from \"effect/Effect\";\nimport * as Ref from \"effect/Ref\";\nimport * as Coverage from \"./Coverage.js\";\nimport type { ClientEngine } from \"./ClientEngine.js\";\nimport * as Subset from \"./Subset.js\";\n\n/** One held window: how many holds it has, and the engine's pull count when it was first held. */\ninterface Window {\n readonly subset: Subset.Subset;\n readonly holds: number;\n /**\n * The engine's `started` count when the window was first held; absent until then.\n * A window held by several registrations keeps the mark of its first hold: it is\n * one engine window, so one pull marks it for all of them (N1, #426).\n */\n readonly since: number | undefined;\n}\n\n/** One registration: its root window, its holds, and how many holds it has on each window. */\ninterface Owner {\n readonly root: Subset.Subset;\n readonly holds: number;\n readonly members: ReadonlyMap<string, number>;\n}\n\ninterface State {\n readonly windows: ReadonlyMap<string, Window>;\n readonly owners: ReadonlyMap<string, Owner>;\n}\n\n/** The marks of one engine's registrations. */\nexport interface PullMarks {\n /**\n * Open a registration under `key`, whose root window is `root`. Opens\n * nest; the registration's marks go with the last {@link close}.\n */\n readonly open: (key: string, root: Subset.Subset) => Effect.Effect<void>;\n /** Close one open of `key`. */\n readonly close: (key: string) => Effect.Effect<void>;\n /**\n * An engine whose `subscribe` and `unsubscribe` hold and release windows\n * under `key`: a window is marked when it is first held, and unmarked\n * when the last hold of it goes.\n */\n readonly wrap: (key: string) => ClientEngine;\n /** The pulled summary of the registration under `key`. */\n readonly pulled: (key: string) => Effect.Effect<Coverage.Pulled>;\n /** The pulled summary of every open registration, by key. */\n readonly registrations: Effect.Effect<\n ReadonlyArray<{ readonly key: string; readonly pulled: Coverage.Pulled }>\n >;\n}\n\nconst summarize = (state: State, key: string, applied: number): Coverage.Pulled => {\n const owner = state.owners.get(key);\n if (owner === undefined) return Coverage.NOT_PULLED;\n const ownPulled = (window: Window): boolean =>\n window.since !== undefined && applied > window.since;\n const pulledSubsets = [...state.windows.values()]\n .filter(ownPulled)\n .map((window) => window.subset);\n const pulled = (window: Window): boolean =>\n ownPulled(window) || pulledSubsets.some((subset) => Coverage.covers(subset, window.subset));\n // Every window the registration holds, root included, with its own mark: a read\n // is judged only by the windows its rows link to (`Coverage.pulledFor`).\n const windows = [...owner.members.keys()].toSorted().flatMap((member) => {\n const window = state.windows.get(member);\n return window === undefined ? [] : [{ subset: window.subset, pulled: pulled(window) }];\n });\n return { windows };\n};\n\nconst withOwner = (\n map: ReadonlyMap<string, Owner>,\n key: string,\n owner: Owner\n): Map<string, Owner> => new Map(map).set(key, owner);\n\n/** Marks over `engine`, which must be the engine the registrations are made on. */\nexport const make = (engine: ClientEngine): PullMarks => {\n const state = Ref.makeUnsafe<State>({ windows: new Map(), owners: new Map() });\n\n const ownerOf = (current: State, key: string, root: Subset.Subset): Owner =>\n current.owners.get(key) ?? { root, holds: 0, members: new Map() };\n\n const subscribe = (key: string, subset: Subset.Subset): Effect.Effect<void> =>\n engine.subscribe(subset).pipe(\n Effect.andThen(engine.pullCounts),\n Effect.flatMap(({ started }) =>\n Ref.update(state, (current) => {\n const hash = Subset.hash(subset);\n const owner = ownerOf(current, key, subset);\n const window = current.windows.get(hash);\n const next = new Map(current.windows).set(hash, {\n subset,\n holds: (window?.holds ?? 0) + 1,\n since: window === undefined ? started : window.since,\n });\n const members = new Map(owner.members).set(hash, (owner.members.get(hash) ?? 0) + 1);\n return {\n windows: next,\n owners: withOwner(current.owners, key, { ...owner, members }),\n };\n })\n )\n );\n\n const unsubscribe = (key: string, subset: Subset.Subset): Effect.Effect<void> =>\n engine.unsubscribe(subset).pipe(\n Effect.andThen(\n Ref.update(state, (current) => {\n const hash = Subset.hash(subset);\n const owner = current.owners.get(key);\n if (owner === undefined || !owner.members.has(hash)) return current;\n const memberHolds = (owner.members.get(hash) ?? 0) - 1;\n const members = new Map(owner.members);\n if (memberHolds <= 0) members.delete(hash);\n else members.set(hash, memberHolds);\n const window = current.windows.get(hash);\n const windows = new Map(current.windows);\n if (window !== undefined && window.holds > 1) {\n windows.set(hash, { ...window, holds: window.holds - 1 });\n } else {\n windows.delete(hash);\n }\n return { windows, owners: withOwner(current.owners, key, { ...owner, members }) };\n })\n )\n );\n\n return {\n open: (key, root) =>\n Ref.update(state, (current) => {\n const owner = ownerOf(current, key, root);\n return {\n ...current,\n owners: withOwner(current.owners, key, { ...owner, holds: owner.holds + 1 }),\n };\n }),\n close: (key) =>\n Ref.update(state, (current) => {\n const owner = current.owners.get(key);\n if (owner === undefined) return current;\n const owners = new Map(current.owners);\n if (owner.holds <= 1) owners.delete(key);\n else owners.set(key, { ...owner, holds: owner.holds - 1 });\n return { ...current, owners };\n }),\n wrap: (key) => ({\n ...engine,\n subscribe: (subset) => subscribe(key, subset),\n unsubscribe: (subset) => unsubscribe(key, subset),\n }),\n pulled: (key) =>\n Effect.all({ current: Ref.get(state), counts: engine.pullCounts }).pipe(\n Effect.map(({ current, counts }) => summarize(current, key, counts.applied))\n ),\n registrations: Effect.all({ current: Ref.get(state), counts: engine.pullCounts }).pipe(\n Effect.map(({ current, counts }) =>\n [...current.owners.keys()].toSorted().map((key) => ({\n key,\n pulled: summarize(current, key, counts.applied),\n }))\n )\n ),\n };\n};\n","/**\n * Subscriptions\n *\n * Subscription lifecycle on top of `ClientEngine`: reference-counted acquire /\n * release, a time-to-live grace period before an unused subscription is\n * dropped, and preload (a subscription pinned for the session). This is the\n * home for the read-side lifecycle Zero expresses as query `ttl` and\n * `preload()` — built on named queries (Query.ts) or raw subsets.\n *\n * When the last holder releases a subscription it is kept for `ttl` (default\n * 5 minutes) so a quick re-subscribe reuses the already-synced rows; if the\n * grace elapses, the engine unsubscribes and the next pull drops the rows\n * (CONTEXT.md: time to live / expiry, never \"garbage collection\"). Preloading\n * acquires without ever releasing.\n */\n\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as Fiber from \"effect/Fiber\";\nimport * as Ref from \"effect/Ref\";\nimport * as Scope from \"effect/Scope\";\nimport * as Semaphore from \"effect/Semaphore\";\nimport type { ClientEngine, WindowObservation } from \"./ClientEngine.js\";\nimport type { MutatorError, QueryError, StoreError } from \"./Errors.js\";\nimport * as Subset from \"./Subset.js\";\n\n/** A held subscription. `release` is idempotent; the grace timer starts when\n * the last holder releases. */\nexport interface SubscriptionHandle {\n readonly release: Effect.Effect<void>;\n}\n\n/**\n * A held, reactively-retargetable window (#133): `rows`/`retarget` are\n * {@link WindowObservation}'s (see `ClientEngine.observeWindow`); `release`\n * drops the subscription this window's *current* (possibly retargeted)\n * subset holds — unlike {@link acquire}, not refcounted, since a window's\n * subset identity (its `limit`/`cursor`) changes over its lifetime and so\n * cannot be shared under one hash-keyed entry the way a plain subset\n * subscription is. Each retargetable window should be its own observation\n * (the common case: one user's one paginated view); two independent\n * `acquireWindow` calls that happen to start from equivalently-hashed\n * subsets are not coordinated with each other.\n */\nexport interface WindowHandle extends WindowObservation {\n readonly release: Effect.Effect<void>;\n}\n\n/**\n * Subscription lifecycle over a `ClientEngine`: refcounted acquire/release, a grace period\n * before an unused subscription is dropped, and preload.\n */\nexport interface Subscriptions {\n /** Acquire a raw-subset subscription (refcounted). */\n readonly acquire: (subset: Subset.Subset) => Effect.Effect<SubscriptionHandle>;\n /**\n * Acquire a reactively-retargetable window (#133): composes `acquire`'s\n * subscribe/release with {@link ClientEngine.observeWindow}, so `retarget`\n * widens/advances the window in place (reusing `LiveView`'s maintained\n * order) and keeps the server-synced subscription in step — the\n * `useConnection` \"load more\" paging hook's engine-level seam.\n */\n readonly acquireWindow: (\n subset: Subset.Subset\n ) => Effect.Effect<WindowHandle, StoreError | MutatorError, Scope.Scope>;\n /** Acquire a named-query subscription (refcounted). */\n readonly acquireQuery: (\n name: string,\n args: unknown\n ) => Effect.Effect<SubscriptionHandle, QueryError>;\n /** Pin a subset for the session (never released). */\n readonly preload: (subset: Subset.Subset) => Effect.Effect<void>;\n /** Pin a named query for the session (never released). */\n readonly preloadQuery: (name: string, args: unknown) => Effect.Effect<void, QueryError>;\n}\n\n/** The engines {@link counted} built, so counting one again returns it. */\nconst countedEngines = new WeakSet<ClientEngine>();\n\n/**\n * One counted voice over the engine's set-based subscription list. The\n * engine's `subscribe` / `unsubscribe` register or drop a window outright,\n * so two independent registrations of one window — an explicit pin beside\n * a relational read's own root subscription, two relational reads pinning\n * one foreign window — would drop it for both when the first released.\n * Registrations made through the returned engine hold a count per window:\n * the engine hears `subscribe` on the first hold and `unsubscribe` on the\n * last. A window this facade never counted (registered on the engine\n * directly) is released as before, so the engine's own semantics survive\n * for callers that bypass it. Everything else passes through untouched.\n *\n * Idempotent: counting a counted engine returns it, so one engine handed\n * to several fronts — an `EngineHost` and a `ClientView.fromEngine` in the\n * same tab, ADR-0010's main-thread path — has one voice, not one per front.\n */\nexport const counted = (engine: ClientEngine): ClientEngine => {\n if (countedEngines.has(engine)) return engine;\n const holds = new Map<string, number>();\n const facade: ClientEngine = {\n ...engine,\n subscribe: (subset) =>\n Effect.suspend(() => {\n const key = Subset.hash(subset);\n const count = holds.get(key) ?? 0;\n holds.set(key, count + 1);\n return count === 0 ? engine.subscribe(subset) : Effect.void;\n }),\n unsubscribe: (subset) =>\n Effect.suspend(() => {\n const key = Subset.hash(subset);\n const count = holds.get(key);\n if (count === undefined) return engine.unsubscribe(subset);\n if (count > 1) {\n holds.set(key, count - 1);\n return Effect.void;\n }\n holds.delete(key);\n return engine.unsubscribe(subset);\n }),\n };\n countedEngines.add(facade);\n return facade;\n};\n\ninterface Entry {\n count: number;\n readonly unsubscribe: Effect.Effect<void>;\n expiry: Fiber.Fiber<void> | undefined;\n}\n\n/** Options for {@link make}. */\nexport interface SubscriptionsOptions {\n /** Grace period a released subscription is kept before being dropped. */\n readonly ttl?: Duration.Duration;\n}\n\n/** Build a subscription manager bound to an engine. Scoped: pending grace\n * timers are interrupted when the scope closes. */\nexport const make = (\n engine: ClientEngine,\n options?: SubscriptionsOptions\n): Effect.Effect<Subscriptions, never, Scope.Scope> =>\n Effect.gen(function* () {\n const ttl = options?.ttl ?? Duration.minutes(5);\n const scope = yield* Effect.scope;\n const lock = yield* Semaphore.make(1);\n const entries = new Map<string, Entry>();\n const withLock = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n Semaphore.withPermit(lock, effect);\n\n const dropAfterTtl = (key: string) =>\n Effect.forkIn(\n Effect.sleep(ttl).pipe(\n Effect.andThen(\n withLock(\n Effect.gen(function* () {\n const entry = entries.get(key);\n if (entry !== undefined && entry.count === 0) {\n yield* entry.unsubscribe;\n entries.delete(key);\n }\n })\n )\n )\n ),\n scope\n );\n\n const releaseKey = (key: string) =>\n withLock(\n Effect.gen(function* () {\n const entry = entries.get(key);\n if (entry === undefined || entry.count === 0) return;\n entry.count -= 1;\n if (entry.count === 0) entry.expiry = yield* dropAfterTtl(key);\n })\n );\n\n const handleFor = (key: string): Effect.Effect<SubscriptionHandle> =>\n Effect.sync(() => {\n let released = false;\n return {\n release: Effect.suspend(() => {\n if (released) return Effect.void;\n released = true;\n return releaseKey(key);\n }),\n };\n });\n\n const acquireKey = <E>(\n key: string,\n subscribe: Effect.Effect<void, E>,\n unsubscribe: Effect.Effect<void>\n ): Effect.Effect<SubscriptionHandle, E> =>\n withLock(\n Effect.gen(function* () {\n const existing = entries.get(key);\n if (existing !== undefined) {\n if (existing.expiry !== undefined) {\n yield* Fiber.interrupt(existing.expiry);\n existing.expiry = undefined;\n }\n existing.count += 1;\n } else {\n yield* subscribe;\n entries.set(key, { count: 1, unsubscribe, expiry: undefined });\n }\n })\n ).pipe(Effect.andThen(handleFor(key)));\n\n const acquire = (subset: Subset.Subset) =>\n acquireKey(Subset.hash(subset), engine.subscribe(subset), engine.unsubscribe(subset));\n\n const acquireQuery = (name: string, args: unknown) =>\n acquireKey(\n `@query:${name}:${JSON.stringify(args)}`,\n engine.subscribeQuery(name, args),\n engine.unsubscribeQuery(name, args).pipe(Effect.orDie)\n );\n\n // A window's own lifecycle, deliberately NOT routed through `acquireKey`'s\n // hash-keyed `entries` map: `retarget` changes the subset's `limit`/\n // `cursor` (and so its hash) over the observation's lifetime, which the\n // refcounted map has no way to track (it would either leak the original\n // entry or, worse, silently release a DIFFERENT acquirer's subscription\n // that happens to now share the retargeted hash). `currentRef` tracks\n // this window's own current subset so `release` unsubscribes the right\n // one regardless of how many times it was retargeted.\n const acquireWindow = (\n subset: Subset.Subset\n ): Effect.Effect<WindowHandle, StoreError | MutatorError, Scope.Scope> =>\n Effect.gen(function* () {\n yield* engine.subscribe(subset);\n const currentRef = yield* Ref.make(subset);\n const observation = yield* engine.observeWindow(subset);\n const retarget: WindowHandle[\"retarget\"] = (window) =>\n observation.retarget(window).pipe(\n Effect.andThen(\n Ref.update(currentRef, (current): Subset.Subset => ({\n ...current,\n ...(window.limit !== undefined ? { limit: window.limit } : {}),\n ...(window.cursor !== undefined ? { cursor: window.cursor } : {}),\n }))\n )\n );\n let released = false;\n const release = Effect.suspend(() => {\n if (released) return Effect.void;\n released = true;\n return Ref.get(currentRef).pipe(Effect.flatMap((current) => engine.unsubscribe(current)));\n });\n return { rows: observation.rows, retarget, release };\n });\n\n return {\n acquire,\n acquireWindow,\n acquireQuery,\n preload: (subset) => Effect.asVoid(acquire(subset)),\n preloadQuery: (name, args) => Effect.asVoid(acquireQuery(name, args)),\n };\n });\n","/**\n * Client view\n *\n * The narrow surface a component binding needs — local reads (`query` /\n * `observe`), subscription registration, write intents, named queries, and\n * auto-subscribing relational reads — abstracted over *where* the engine\n * runs. A main-thread {@link ClientEngine} satisfies it via\n * {@link fromEngine}; a client context's mirror (`Mirror`,\n * whose shape this interface is drawn from) satisfies it structurally. The\n * same bindings therefore drive both hosts of ADR-0010's deployment —\n * engine-in-the-UI-context and engine-in-the-service-worker — without changing\n * component code (ADR-0021).\n *\n * `mutateWithAck` has awaited-outcome semantics (it resolves with the\n * backend's authoritative {@link MutationOutcome}), matching the mirror; the\n * engine's handle-based variant is folded by {@link fromEngine}.\n *\n * Named queries and `related` cross the mirror protocol since ADR-0021's\n * follow-up landed: a mirror forwards the registration to its host, which\n * owns the server round-trip (and, for `related`, the reconcile loop and the\n * join itself — mirrors receive resolved rows, keeping join work off the main\n * thread). Engine-only capabilities that remain (explicit push/pull, undo\n * history) still require the full engine from context.\n */\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\nimport { ClientEngine, type LocalRow, type MutationOutcome } from \"./ClientEngine.js\";\nimport type * as ClientEngineModule from \"./ClientEngine.js\";\nimport type * as Collection from \"./Collection.js\";\nimport type * as Coverage from \"./Coverage.js\";\nimport { TransportError } from \"./Errors.js\";\nimport type { MutatorError, QueryError, StoreError } from \"./Errors.js\";\nimport type * as Identity from \"./Identity.js\";\nimport type * as MutationState from \"./MutationState.js\";\nimport type { Mutation } from \"./Protocol.js\";\nimport * as MirrorProtocol from \"./MirrorProtocol.js\";\nimport * as PullMarks from \"./PullMarks.js\";\nimport * as Related from \"./Related.js\";\nimport type { RowChange } from \"./RowChange.js\";\nimport * as Subset from \"./Subset.js\";\nimport * as Subscriptions from \"./Subscriptions.js\";\n\n/**\n * The union of what either host may fail a view operation with: the engine\n * fails on its store/mutators/query registry, a mirror on its channel. Each\n * implementation's channels are narrower.\n */\nexport type ClientViewError = MutatorError | StoreError | TransportError | QueryError;\n\n/** {@inheritDoc ClientViewError} */\nexport interface ClientView {\n /** Materialise a subset from the local view (confirmed + overlay). */\n readonly query: (\n subset: Subset.Subset\n ) => Effect.Effect<ReadonlyArray<LocalRow>, ClientViewError>;\n /** Live results of a subset, emitting current rows first. */\n readonly observe: (\n subset: Subset.Subset\n ) => Stream.Stream<ReadonlyArray<LocalRow>, ClientViewError>;\n /**\n * Reactive window retargeting (#133): like {@link observe}, but the\n * returned {@link ClientEngineModule.WindowObservation}'s `retarget` widens\n * or advances the SAME open observation's `limit`/`cursor` in place —\n * see {@link ClientEngineModule.ClientEngine.observeWindow}. Present only\n * for an engine-backed view (`fromEngine`): a `Mirror` has no local\n * `LiveView` of its own to retarget — a documented gap, not a silent one\n * (`docs/observing-row-changes.md`) — a mirror-backed consumer that needs\n * this re-`subscribe`s with a wider subset instead.\n */\n readonly observeWindow?: (subset: Subset.Subset) => Effect.Effect<\n {\n readonly rows: Stream.Stream<ReadonlyArray<LocalRow>, ClientViewError>;\n readonly retarget: (window: ClientEngineModule.WindowRetarget) => Effect.Effect<void>;\n },\n ClientViewError,\n Scope.Scope\n >;\n /**\n * Row-level deltas of a subset's live window (#115) — see\n * {@link ClientEngineModule.ClientEngine.observeChanges}. Satisfied\n * structurally by `Mirror` (ADR-0021's one-surface principle), which folds\n * its own page-diffing over the keyed row broadcasts it already receives.\n */\n readonly observeChanges: (\n subset: Subset.Subset,\n options?: ClientEngineModule.ObserveChangesOptions\n ) => Stream.Stream<ReadonlyArray<RowChange<LocalRow>>, ClientViewError>;\n /**\n * The pulled summary of a registration (#426): the registration under `key`\n * (the subset hash, or the relational key of {@link MirrorProtocol.relatedKey})\n * with each window it holds and whether that window's rows are in the\n * replica. A Client answers a covered read from the replica only when the\n * windows the read's rows link to are pulled (`Coverage.pulledFor`). Over an\n * engine the marks are kept here; a `Mirror` has the host's answer, sent over\n * the channel.\n */\n readonly pulled: (key: string) => Effect.Effect<Coverage.Pulled>;\n /** Register/release a subscription (synced by the engine host). */\n readonly subscribe: (subset: Subset.Subset) => Effect.Effect<void, ClientViewError>;\n readonly unsubscribe: (subset: Subset.Subset) => Effect.Effect<void, ClientViewError>;\n /**\n * Register/release a named query (Query.ts). The engine host owns the\n * server-authoritative resolution; results render locally.\n */\n readonly subscribeQuery: (name: string, args: unknown) => Effect.Effect<void, ClientViewError>;\n readonly unsubscribeQuery: (name: string, args: unknown) => Effect.Effect<void, ClientViewError>;\n /** A named query's current local result. */\n readonly queryNamed: (\n name: string,\n args: unknown\n ) => Effect.Effect<ReadonlyArray<LocalRow>, ClientViewError>;\n /** Live named query results, emitting current rows first. */\n readonly observeNamed: (\n name: string,\n args: unknown\n ) => Stream.Stream<ReadonlyArray<LocalRow>, ClientViewError>;\n /**\n * Auto-subscribing relational read over a subset's declared relationships:\n * the host syncs the base and the narrowed foreign subsets, tracks the live\n * linkage, and tears the subscriptions down when the scope closes. The\n * stream emits resolved {@link Related.RelatedRow}s.\n */\n readonly related: (\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | Related.EdgeSelect>\n ) => Effect.Effect<Stream.Stream<ReadonlyArray<Related.RelatedRow>, never>, never, Scope.Scope>;\n /**\n * Hold a subset's edge windows registered for the scope's lifetime\n * without resolving the join — what an explicit pin with `include` needs\n * (ADR-0029 section 2): the narrowed foreign windows keep tracking the\n * base rows, and are released when the scope closes. Over an engine this\n * is `Related.trackEdges`; a mirror registers the relational read with\n * its host and never reads the resolved rows.\n */\n readonly pinEdges: (\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | Related.EdgeSelect>\n ) => Effect.Effect<void, never, Scope.Scope>;\n /**\n * Point-in-time server-fallthrough read (ADR-0025): auth-filtered,\n * no CVR, results never enter the replica. Present only when the\n * underlying tier can reach a server (a transport with `read`, or a\n * host that forwards).\n */\n readonly read?: (\n subsets: ReadonlyArray<Subset.Subset>\n ) => Effect.Effect<ReadonlyArray<ClientEngineModule.ReadRow>, ClientViewError>;\n /**\n * The identity boundary (#212), present only for an engine-backed view.\n * A `Mirror` holds no durable state of its own — the replica lives in the\n * host — so resetting a connected Client is the host's Client's job, not\n * something a mirror can do on its behalf; `Client.reset` says so rather\n * than pretending to have succeeded.\n */\n readonly identityBoundary?: {\n readonly reset: (\n identity: Identity.Fingerprint\n ) => Effect.Effect<ClientEngineModule.ResetOutcome, StoreError>;\n readonly current: Effect.Effect<Identity.Fingerprint | undefined, StoreError>;\n readonly quarantines: Effect.Effect<ReadonlyArray<Identity.Fingerprint>, StoreError>;\n readonly quarantinedMutations: (\n identity: Identity.Fingerprint\n ) => Effect.Effect<ReadonlyArray<Mutation>, StoreError>;\n readonly discardQuarantine: (identity: Identity.Fingerprint) => Effect.Effect<void, StoreError>;\n };\n /** Journal a mutation and apply it optimistically; resolves on journal. */\n readonly mutate: (mutator: string, args: unknown) => Effect.Effect<void, ClientViewError>;\n /** Like {@link ClientView.mutate}, resolving with the backend's authoritative outcome. */\n readonly mutateWithAck: (\n mutator: string,\n args: unknown\n ) => Effect.Effect<MutationOutcome, ClientViewError>;\n /**\n * The client half of an enhanced form submit (ADR-0030 #215 §4): see\n * {@link ClientEngineModule.ClientEngine.beginFormMutation}. An\n * engine-backed view (`fromEngine`) begins it on its engine; a `Mirror`\n * asks its host to (#536), which holds the in-flight entry for every\n * mirror. Absent from a view that can do neither.\n */\n readonly beginFormMutation?: (\n form: ClientEngineModule.FormClient,\n mutator: string,\n args: unknown\n ) => Effect.Effect<ClientEngineModule.FormSubmission, ClientViewError>;\n /**\n * The keyed mutation-state map (#116): current value now, then every fold.\n * A main-thread engine emits its own {@link ClientEngineModule.ClientEngine.mutationStates};\n * a mirror mirrors the host's — the same states either way (ADR-0021).\n */\n readonly mutationStates: Stream.Stream<MutationState.MutationStateMap>;\n}\n\n/** The read half of a {@link ClientView} — what a local join needs. */\nexport type Reader = Pick<ClientView, \"query\" | \"observe\">;\n\n/** The {@link ClientView} service: where a Client's reads and writes go, owned engine or mirror. */\nexport const ClientView = Context.Service<ClientView>(\"@thomasfosterau/legation/ClientView\");\n\n/**\n * Present a {@link ClientEngine} as a {@link ClientView}. Subscriptions go\n * through one counted voice (`Subscriptions.counted`): an explicit\n * `subscribe` of a window and a `related` read's own registration of the\n * same window release independently, and the engine drops the window only\n * when the last of them lets go.\n */\nexport const fromEngine = (raw: ClientEngine): ClientView => {\n const engine = Subscriptions.counted(raw);\n const marks = PullMarks.make(engine);\n const readThrough = engine.readThrough;\n return {\n query: (subset) => engine.query(subset),\n observe: (subset) => engine.observe(subset),\n observeWindow: (subset) => engine.observeWindow(subset),\n observeChanges: (subset, options) => engine.observeChanges(subset, options),\n pulled: (key) => marks.pulled(key),\n subscribe: (subset) => {\n const key = Subset.hash(subset);\n return marks.open(key, subset).pipe(\n Effect.andThen(\n marks\n .wrap(key)\n .subscribe(subset)\n .pipe(Effect.tapError(() => marks.close(key)))\n )\n );\n },\n unsubscribe: (subset) => {\n const key = Subset.hash(subset);\n return marks\n .wrap(key)\n .unsubscribe(subset)\n .pipe(Effect.andThen(marks.close(key)));\n },\n subscribeQuery: (name, args) => engine.subscribeQuery(name, args),\n unsubscribeQuery: (name, args) => engine.unsubscribeQuery(name, args),\n queryNamed: (name, args) => engine.queryNamed(name, args),\n observeNamed: (name, args) => engine.observeNamed(name, args),\n related: (registry, collectionName, subset, edges) =>\n Related.related(engine, registry, collectionName, subset, edges),\n pinEdges: (registry, collectionName, subset, edges) => {\n const key = MirrorProtocol.relatedKey(collectionName, subset, edges);\n return Effect.acquireRelease(marks.open(key, subset), () => marks.close(key)).pipe(\n Effect.andThen(Related.trackEdges(marks.wrap(key), registry, collectionName, subset, edges))\n );\n },\n ...(readThrough === undefined\n ? {}\n : {\n read: (subsets: ReadonlyArray<Subset.Subset>) =>\n readThrough(subsets).pipe(\n Effect.mapError((error) =>\n error._tag === \"VersionNotSupportedError\"\n ? new TransportError({ message: error.message, cause: error })\n : error\n )\n ),\n }),\n identityBoundary: {\n reset: (identity) => engine.reset(identity),\n current: engine.identity,\n quarantines: engine.quarantines,\n quarantinedMutations: (identity) => engine.quarantinedMutations(identity),\n discardQuarantine: (identity) => engine.discardQuarantine(identity),\n },\n mutate: (mutator, args) => engine.mutate(mutator, args),\n mutateWithAck: (mutator, args) =>\n engine.mutateWithAck(mutator, args).pipe(Effect.flatMap((handle) => handle.acknowledged)),\n beginFormMutation: (form, mutator, args) => engine.beginFormMutation(form, mutator, args),\n mutationStates: engine.mutationStates,\n };\n};\n\n/**\n * Derive the {@link ClientView} from the in-context engine. Compose with\n * `Layer.provideMerge(engineLayer)` so a runtime exposes both the view (for\n * bindings) and the engine (for engine-only capabilities).\n */\nexport const layer: Layer.Layer<ClientView, never, ClientEngine> = Layer.effect(ClientView)(\n Effect.map(ClientEngine, fromEngine)\n);\n","/**\n * Mirror\n *\n * The consumer side of ADR-0010: an in-memory copy of subscribed subsets\n * held by a client context — a browser tab, an Electron window, an\n * extension, a CLI instance —\n * hydrated and kept current by engine-host broadcasts, with queries served\n * synchronously from the mirror. Mutations validate locally against the\n * shared mutator registry (fail fast in the mirror), then forward to the host\n * journal in encoded form and await the host's acknowledgement.\n */\n\nimport type * as ClientEngine from \"./ClientEngine.js\";\nimport type * as ClientView from \"./ClientView.js\";\nimport type * as Collection from \"./Collection.js\";\nimport * as Coverage from \"./Coverage.js\";\nimport { MutatorError, StoreError, TransportError } from \"./Errors.js\";\nimport type * as Mutator from \"./Mutator.js\";\nimport type * as MutationState from \"./MutationState.js\";\nimport * as Related from \"./Related.js\";\nimport * as RowChange from \"./RowChange.js\";\nimport * as Subset from \"./Subset.js\";\nimport * as Telemetry from \"./Telemetry.js\";\nimport * as Arr from \"effect/Array\";\nimport * as Deferred from \"effect/Deferred\";\nimport type * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Metric from \"effect/Metric\";\nimport * as Option from \"effect/Option\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Ref from \"effect/Ref\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport * as Stream from \"effect/Stream\";\nimport type { MirrorChannel } from \"./MirrorChannel.js\";\nimport * as MirrorProtocol from \"./MirrorProtocol.js\";\n\n/** Options for {@link make}: the channel to the host and the shared mutator registry. */\nexport interface MirrorOptions {\n readonly channel: MirrorChannel;\n /** The shared mutator registry (same definitions the host engine runs). */\n readonly mutators: Mutator.MutatorRegistry;\n /**\n * How often to send a liveness heartbeat to the host. Keep it shorter\n * than the host's `mirrorTimeout` so a live mirror is never reclaimed. Defaults\n * to 10 seconds.\n */\n readonly heartbeatInterval?: Duration.Input;\n /**\n * Capacity of the bounded change hub (#44). A stalled observer cannot\n * make the hub grow without limit: at capacity the hub drops the newest\n * subset keys, and the observer collapses the resulting seq gap into a full\n * re-read of its subset — lossless because the newest rows live in the\n * mirror's `Ref`. Defaults to {@link DEFAULT_CHANGE_HUB_CAPACITY}.\n */\n readonly changeHubCapacity?: number;\n}\n\n/**\n * Default bound for the mirror's change hub. Large enough that no realistic\n * burst of mirror updates fills it under normal consumption, so behaviour is\n * identical to the old unbounded hub until an observer genuinely stalls.\n */\nconst DEFAULT_CHANGE_HUB_CAPACITY = 1024;\n\n/**\n * A subset key published on the change hub, tagged with a monotonic seq. A\n * consumer tracks the last seq it saw; a non-contiguous seq means the bounded\n * hub dropped a key, so the observer re-reads its subset (a full refresh)\n * rather than risk missing its own key.\n */\ninterface SeqKey {\n readonly seq: number;\n readonly key: string;\n}\n\n/** A backend outcome message reduced to the engine's {@link ClientEngine.MutationOutcome}. */\nconst outcomeOf = (\n message: MirrorProtocol.HostMessage & { readonly _tag: \"MutateSettled\" }\n): ClientEngine.MutationOutcome =>\n message.outcome === \"applied\"\n ? { _tag: \"applied\" }\n : { _tag: \"rejected\", reason: message.reason ?? \"\" };\n\n/**\n * Raised for a request whose answer can never arrive: the host that would\n * have answered it is gone (a restart this mirror observed via `HostReady`,\n * or this mirror's own scope closing while requests were still in flight).\n * Never left hanging — if the mutation was already journaled by the old\n * host, it is durable in its store and the next host will push it, but this\n * caller must not assume that without checking; retry is only safe once the\n * caller has verified the mutation didn't already apply.\n */\nconst hostUnavailable = new TransportError({\n message: \"Mirror: the engine host is gone — outcome unknown, verify before retrying\",\n});\n\n/**\n * Raised when an enhanced form submit's begin reaches a host that predates\n * carrying it over the mirror protocol (#536): that host answers the begin's\n * `Mutate` as an unknown mutator, and nothing was overlaid or journaled.\n */\nconst hostPredatesFormMutations = new TransportError({\n message:\n \"Mirror.beginFormMutation: the engine host predates enhanced form submits over the mirror protocol; upgrade it\",\n});\n\n/**\n * What a host that predates #536 answers a form begin with: its engine's\n * unknown-mutator message for {@link MirrorProtocol.FORM_MUTATION_MUTATOR}.\n * That host's code is fixed, so its wording is too.\n */\nconst unknownFormMutator = `Unknown mutator: ${MirrorProtocol.FORM_MUTATION_MUTATOR}`;\n\n/** An empty map of requests awaiting the host's answer, keyed by requestId. */\nconst makePending = <A>() =>\n Ref.make(new Map<number, Deferred.Deferred<A, MutatorError | TransportError>>());\n\n/** Fail (and clear) every deferred still waiting in `ref`, never leaving a caller hanging. */\nconst failPending = <A>(\n ref: Ref.Ref<Map<number, Deferred.Deferred<A, MutatorError | TransportError>>>\n): Effect.Effect<void> =>\n Ref.getAndSet(ref, new Map()).pipe(\n Effect.flatMap((requests) =>\n Effect.forEach(requests.values(), (deferred) => Deferred.fail(deferred, hostUnavailable), {\n discard: true,\n })\n )\n );\n\n/**\n * A client context's in-memory copy of a host engine's subscribed subsets: queries are answered\n * synchronously from it, and writes are forwarded to the host's journal.\n */\nexport interface Mirror {\n /** Validate args locally, forward to the host journal, await the ack. */\n readonly mutate: (\n mutator: string,\n args: unknown\n ) => Effect.Effect<void, MutatorError | TransportError>;\n /**\n * Like {@link mutate}, but resolves with the mutation's authoritative backend\n * outcome (applied or permanently rejected) once the host forwards it, rather\n * than on the host journal ack.\n */\n readonly mutateWithAck: (\n mutator: string,\n args: unknown\n ) => Effect.Effect<ClientEngine.MutationOutcome, MutatorError | TransportError>;\n /**\n * The client half of an enhanced form submit (ADR-0030 #215 §4), carried to\n * the host (#536): the host's engine overlays the Mutation under the form\n * client's id without journaling it, and holds the in-flight entry, so its\n * overlay and unpulled tail serve every mirror. Settling or abandoning the\n * returned submission tells the host; as on an engine, an acknowledgement\n * parks the effect until the pull that covers the form client releases it.\n * Fails with a `TransportError` when the host predates this, and with a\n * `MutatorError` when the args do not fit the Mutation or the host refuses\n * the begin. The signature is `ClientView`'s. A submission whose host is gone (restarted, or this mirror's\n * scope closed) settles as a no-op: its entry went with the host.\n */\n readonly beginFormMutation: NonNullable<ClientView.ClientView[\"beginFormMutation\"]>;\n /** Register a subset with the host; rows arrive as mirror updates. */\n readonly subscribe: (subset: Subset.Subset) => Effect.Effect<void, TransportError>;\n readonly unsubscribe: (subset: Subset.Subset) => Effect.Effect<void, TransportError>;\n /**\n * Register a named query with the host (which owns the server-authoritative\n * resolution); results arrive as mirror updates under the named key.\n */\n readonly subscribeQuery: (name: string, args: unknown) => Effect.Effect<void, TransportError>;\n readonly unsubscribeQuery: (name: string, args: unknown) => Effect.Effect<void, TransportError>;\n /** The mirror's current rows for a subset (empty until hydrated). */\n readonly query: (subset: Subset.Subset) => Effect.Effect<ReadonlyArray<ClientEngine.LocalRow>>;\n /**\n * Server-fallthrough read (ADR-0025), forwarded to the host — which owns\n * the transport — and answered point-in-time, never entering the mirror.\n */\n readonly read: (\n subsets: ReadonlyArray<Subset.Subset>\n ) => Effect.Effect<ReadonlyArray<ClientEngine.ReadRow>, MutatorError | TransportError>;\n /** The mirror's current rows for a named query (empty until hydrated). */\n readonly queryNamed: (\n name: string,\n args: unknown\n ) => Effect.Effect<ReadonlyArray<ClientEngine.LocalRow>>;\n /** Emits the current rows now and on every mirror update for the subset. */\n readonly observe: (subset: Subset.Subset) => Stream.Stream<ReadonlyArray<ClientEngine.LocalRow>>;\n /** The host's pulled summary of the registration under `key` (#426); see {@link ClientView.ClientView.pulled}. */\n readonly pulled: (key: string) => Effect.Effect<Coverage.Pulled>;\n /**\n * Row-level deltas of a subset's live window (#115) — see\n * {@link ClientEngine.ClientEngine.observeChanges}. The mirror has no\n * incremental `LiveView` of its own: it diffs consecutive whole-page\n * `MirrorUpdate`s (`RowChange.diff`), which is exact because the host\n * already delivers the full current page on every change. A gap on the\n * mirror's change hub (a dropped key — CONTEXT.md's hub table) re-reads\n * the always-current `rows` Ref, same as `observe`, and is folded into a\n * `reset` batch here rather than a diff, since the skipped updates in\n * between are unknown.\n */\n readonly observeChanges: (\n subset: Subset.Subset,\n options?: { readonly includeInitial?: boolean }\n ) => Stream.Stream<ReadonlyArray<RowChange.RowChange<ClientEngine.LocalRow>>>;\n /**\n * The host engine's keyed mutation-state map (#116), mirrored so every tab\n * sees the same states the host holds. Registers interest with the host for\n * the stream's lifetime (refcounted like `observe`); emits the current map\n * now and on every host-side fold.\n */\n readonly mutationStates: Stream.Stream<MutationState.MutationStateMap>;\n /** Emits the named query's current rows now and on every mirror update. */\n readonly observeNamed: (\n name: string,\n args: unknown\n ) => Stream.Stream<ReadonlyArray<ClientEngine.LocalRow>>;\n /**\n * Auto-subscribing relational read: the HOST syncs the base and narrowed\n * foreign subsets and computes the join — the mirror receives resolved rows\n * (main-thread work stays minimal). The registration is released when the\n * scope closes. The `registry` parameter exists for {@link ClientView}\n * signature parity; the host resolves against its own registry.\n */\n readonly related: (\n registry: Collection.CollectionRegistry,\n collectionName: string,\n subset: Subset.Subset,\n edges: ReadonlyArray<string | Related.EdgeSelect>\n ) => Effect.Effect<Stream.Stream<ReadonlyArray<Related.RelatedRow>, never>, never, Scope.Scope>;\n /**\n * Hold a relational registration with the host for the scope's lifetime\n * without reading its resolved rows — an explicit pin's edge windows\n * (ADR-0029 section 2). The host runs the same reconcile loop it runs for\n * {@link related}; the signature is `ClientView`'s (the `registry`\n * parameter exists for that parity alone).\n */\n readonly pinEdges: ClientView.ClientView[\"pinEdges\"];\n}\n\n/**\n * Connect a {@link Mirror} to the host on `options.channel`; its subscriptions are released when\n * the scope closes.\n */\nexport const make = (options: MirrorOptions): Effect.Effect<Mirror, never, Scope.Scope> =>\n Effect.gen(function* () {\n const { channel, mutators } = options;\n const mirrorId = crypto.randomUUID();\n const inbox = yield* channel.subscribe;\n // Release every subscription this mirror holds when its scope closes —\n // the host refcounts subsets by mirror and tears down the last one's fiber.\n yield* Effect.addFinalizer(() =>\n channel.post({ _tag: \"Disconnect\", mirrorId }).pipe(Effect.ignore)\n );\n // Heartbeat so the host keeps this mirror's subsets alive (and reclaims\n // them if the mirror's context crashes without disconnecting). Fires immediately,\n // then on the interval.\n const heartbeatInterval = options.heartbeatInterval ?? \"10 seconds\";\n yield* Effect.forkScoped(\n Effect.forever(\n channel\n .post({ _tag: \"Heartbeat\", mirrorId })\n .pipe(Effect.ignore, Effect.andThen(Effect.sleep(heartbeatInterval)))\n )\n );\n // This mirror's interest ledger, keyed by subscription key. The host\n // refcounts by MIRROR (a set), so this side must speak with one voice\n // per key: Subscribe\n // when the first local interest appears (an explicit `subscribe` or an\n // observer's stream starting), Unsubscribe only when the LAST one ends.\n // The ledger doubles as the replay set for a host that (re)starts after\n // us (HostReady).\n interface Interest {\n /** Live observers of this key. */\n readonly observers: number;\n /** Pinned by an explicit `subscribe` (survives observer teardowns). */\n readonly explicit: boolean;\n readonly subscribe: MirrorProtocol.MirrorMessage;\n readonly unsubscribe: MirrorProtocol.MirrorMessage;\n }\n const interests = yield* Ref.make(new Map<string, Interest>());\n // Distinguishes a host's first-ever readiness announcement (routine — this\n // mirror has nothing in flight worth failing, and racing to fail it here\n // would clobber a request this same host is about to answer) from a later\n // one (a genuine restart, whose old in-memory bookkeeping is gone).\n const seenHostReady = yield* Ref.make(false);\n /** Add one unit of interest; posts Subscribe when it is the first. */\n const acquireInterest = (\n key: string,\n messages: {\n subscribe: MirrorProtocol.MirrorMessage;\n unsubscribe: MirrorProtocol.MirrorMessage;\n },\n kind: \"observer\" | \"explicit\"\n ) =>\n Ref.modify(interests, (map) => {\n const next = new Map(map);\n const current = next.get(key);\n const updated: Interest = {\n observers: (current?.observers ?? 0) + (kind === \"observer\" ? 1 : 0),\n explicit: (current?.explicit ?? false) || kind === \"explicit\",\n subscribe: messages.subscribe,\n unsubscribe: messages.unsubscribe,\n };\n next.set(key, updated);\n return [current === undefined, next] as const;\n }).pipe(\n Effect.flatMap((first) =>\n first ? channel.post(messages.subscribe).pipe(Effect.ignore) : Effect.void\n )\n );\n /** Drop one unit of interest; posts Unsubscribe when it was the last. */\n const releaseInterest = (key: string, kind: \"observer\" | \"explicit\") =>\n Ref.modify(interests, (map) => {\n const current = map.get(key);\n if (current === undefined) return [undefined, map] as const;\n const updated: Interest = {\n ...current,\n observers: Math.max(0, current.observers - (kind === \"observer\" ? 1 : 0)),\n explicit: kind === \"explicit\" ? false : current.explicit,\n };\n const next = new Map(map);\n if (updated.observers === 0 && !updated.explicit) {\n next.delete(key);\n return [current.unsubscribe, next] as const;\n }\n next.set(key, updated);\n return [undefined, next] as const;\n }).pipe(\n Effect.flatMap((unsubscribe) =>\n unsubscribe === undefined ? Effect.void : channel.post(unsubscribe).pipe(Effect.ignore)\n )\n );\n // Registers one unit of observer interest in `key` for as long as\n // `stream` is subscribed, releasing it when the subscriber unsubscribes.\n const withObserverRegistration = <A, E>(\n key: string,\n messages: {\n readonly subscribe: MirrorProtocol.MirrorMessage;\n readonly unsubscribe: MirrorProtocol.MirrorMessage;\n },\n stream: Stream.Stream<A, E>\n ): Stream.Stream<A, E> =>\n Stream.unwrap(\n Effect.acquireRelease(acquireInterest(key, messages, \"observer\"), () =>\n releaseInterest(key, \"observer\")\n ).pipe(Effect.as(stream))\n );\n const rows = yield* Ref.make(new Map<string, ReadonlyArray<ClientEngine.LocalRow>>());\n // Resolved relational rows, keyed by the host's related key. Kept apart\n // from `rows` because the row shape differs (base value + resolved names).\n const relatedRows = yield* Ref.make(new Map<string, ReadonlyArray<Related.RelatedRow>>());\n // The mirrored mutation-state map (#116), kept apart from `rows` because\n // it is a singleton (one map, not one per subset/named-query key) whose\n // shape differs from `LocalRow`.\n const mutationStatesRow = yield* Ref.make<MutationState.MutationStateMap>(HashMap.empty());\n // The host's pulled summaries of its registrations (#426); see `PulledRegistrations`.\n const pulledKeys = yield* Ref.make<ReadonlyMap<string, Coverage.Pulled>>(new Map());\n // Monotonic seq stamped on every published key. The `rows` Ref is updated\n // before the key is published, so a re-read after a gap always sees the\n // latest rows even for a dropped key.\n const keySeq = yield* Ref.make(0);\n // Bounded, dropping change hub (#44): a stalled observer holds keys in the\n // shared hub; at capacity the hub drops the newest keys rather than growing\n // without limit. A consumer detects a drop as a seq gap and re-reads its\n // subset from the always-current `rows` Ref — lossless under pressure,\n // identical under none.\n const keyHubCapacity = options.changeHubCapacity ?? DEFAULT_CHANGE_HUB_CAPACITY;\n const keyHub = yield* Effect.acquireRelease(\n PubSub.dropping<SeqKey>({ capacity: keyHubCapacity }),\n (hub) => PubSub.shutdown(hub)\n );\n const publishKey = (key: string): Effect.Effect<void> =>\n Effect.flatMap(\n Ref.updateAndGet(keySeq, (n) => n + 1),\n (seq) => Effect.asVoid(PubSub.publish(keyHub, { seq, key }))\n );\n const pending = yield* makePending<void>();\n // `mutateWithAck` callers awaiting the backend outcome, keyed by the same\n // requestId space as `pending` (a requestId lives in exactly one map).\n const pendingSettled = yield* makePending<ClientEngine.MutationOutcome>();\n // Fallthrough reads awaiting their host answer (ADR-0025), same\n // requestId space.\n const pendingReads = yield* makePending<ReadonlyArray<ClientEngine.ReadRow>>();\n // Enhanced form submits awaiting the host (#536): a begin and its end,\n // keyed by the begin's requestId. Kept apart from `pending` because the\n // generic `MutateAck` / `MutateError` replies carry no mirror id, and\n // another tab's request may share this requestId; only the form replies\n // (which name the mirror) complete these. An end resolves with the\n // host's settlement error, if any.\n const pendingForms = yield* makePending<Option.Option<string>>();\n const requestIds = yield* Ref.make(0);\n // Set as this mirror's scope begins to close, before the pending requests\n // are failed: a request registered after that is failed by `awaitReply`\n // itself, since no reply can reach it any more.\n const closed = yield* Ref.make(false);\n\n // A request left in flight when this mirror's scope closes can never be\n // answered (its host may still be alive, but nobody will read the reply)\n // — fail it rather than leave the caller hanging forever.\n yield* Effect.addFinalizer(() =>\n Ref.set(closed, true).pipe(\n Effect.andThen(\n Effect.all(\n [\n failPending(pending),\n failPending(pendingSettled),\n failPending(pendingReads),\n failPending(pendingForms),\n ],\n { discard: true }\n )\n )\n )\n );\n\n // Take a request's deferred out of its map and complete it. A no-op when the\n // requestId is not in this map (so both maps can be swept on `MutateError`).\n const resolveIn = <A>(\n ref: Ref.Ref<Map<number, Deferred.Deferred<A, MutatorError | TransportError>>>,\n requestId: number,\n complete: (\n deferred: Deferred.Deferred<A, MutatorError | TransportError>\n ) => Effect.Effect<boolean>\n ) =>\n Effect.gen(function* () {\n const deferred = (yield* Ref.get(ref)).get(requestId);\n if (deferred === undefined) return;\n yield* Ref.update(ref, (map) => {\n const next = new Map(map);\n next.delete(requestId);\n return next;\n });\n yield* complete(deferred);\n });\n\n // Complete this mirror's waiting form request (#536) from the host's reply;\n // a reply addressed to another mirror is not ours, whatever its requestId.\n const resolveForm = (\n message: { readonly mirrorId: string; readonly requestId: number },\n complete: (\n deferred: Deferred.Deferred<Option.Option<string>, MutatorError | TransportError>\n ) => Effect.Effect<boolean>\n ) =>\n message.mirrorId === mirrorId\n ? resolveIn(pendingForms, message.requestId, complete)\n : Effect.void;\n\n // Complete this mirror's waiting request in `ref` from a `Mutate` or `Read`\n // reply (#546). Every tab hears the host's replies and numbers its requests\n // from zero, so a reply addressed to another mirror is not ours, whatever\n // its requestId. A reply with no mirror id comes from a host that predates\n // the field, and is taken by its requestId as before.\n const resolveReply = <A>(\n ref: Ref.Ref<Map<number, Deferred.Deferred<A, MutatorError | TransportError>>>,\n message: { readonly mirrorId?: string; readonly requestId: number },\n complete: (\n deferred: Deferred.Deferred<A, MutatorError | TransportError>\n ) => Effect.Effect<boolean>\n ) =>\n message.mirrorId === undefined || message.mirrorId === mirrorId\n ? resolveIn(ref, message.requestId, complete)\n : Effect.void;\n\n // Mirror update loop: established before `make` returns.\n yield* Effect.forkScoped(\n Effect.forever(\n inbox.take.pipe(\n Effect.flatMap(MirrorProtocol.decodeHostMessage),\n Effect.flatMap((message) => {\n if (message === undefined) return Effect.void;\n switch (message._tag) {\n case \"HostReady\":\n // A host (re)started: replay every interest we hold. Past the\n // first HostReady we've ever seen, this also means whatever\n // was in flight with the OLD host is unanswerable — its\n // in-memory request bookkeeping is gone, so those replies are\n // never coming (the old host may still have journaled the\n // mutation before it died; the new host's sync loop picks\n // that up from the durable store regardless of what this\n // caller is told).\n return Ref.get(interests).pipe(\n Effect.flatMap((map) =>\n Effect.forEach(map.values(), (interest) =>\n channel.post(interest.subscribe).pipe(Effect.ignore)\n )\n ),\n Effect.andThen(Ref.getAndSet(seenHostReady, true)),\n Effect.flatMap((hadSeenBefore) =>\n hadSeenBefore\n ? Effect.all(\n [\n failPending(pending),\n failPending(pendingSettled),\n failPending(pendingReads),\n failPending(pendingForms),\n ],\n { discard: true }\n )\n : Effect.void\n ),\n Effect.asVoid\n );\n case \"MirrorUpdate\":\n return Ref.update(rows, (map) =>\n new Map(map).set(\n message.key,\n message.rows.map((row) => ({ id: row.id, value: row.value }))\n )\n ).pipe(Effect.andThen(publishKey(message.key)));\n case \"RelatedUpdate\":\n return Ref.update(relatedRows, (map) =>\n new Map(map).set(\n message.key,\n message.rows.map((row) => ({\n id: row.id,\n value: row.value,\n related: row.related as Record<string, Related.RelatedValue>,\n }))\n )\n ).pipe(Effect.andThen(publishKey(message.key)));\n case \"MutationStatesUpdate\":\n return Ref.set(\n mutationStatesRow,\n HashMap.fromIterable(\n message.states.map((state): readonly [number, MutationState.MutationState] => [\n state.mutationId,\n state,\n ])\n )\n ).pipe(Effect.andThen(publishKey(MirrorProtocol.MUTATION_STATES_KEY)));\n case \"PulledRegistrations\":\n return Ref.set(\n pulledKeys,\n new Map(message.registrations.map((entry) => [entry.key, entry.pulled]))\n );\n case \"MutateAck\":\n return resolveReply(pending, message, (deferred) =>\n Deferred.succeed(deferred, undefined)\n );\n case \"MutateError\": {\n // A host-side failure (never journaled): fail whichever caller\n // is waiting — `mutate` or `mutateWithAck`. Only a host that\n // predates #536 answers a form begin this way, with exactly\n // this message; it carries no mirror id, but every tab whose\n // begin it answers is talking to the same old host.\n if (message.message === unknownFormMutator) {\n return resolveIn(pendingForms, message.requestId, (deferred) =>\n Deferred.fail(deferred, hostPredatesFormMutations)\n );\n }\n const error = new MutatorError({ message: message.message });\n return resolveReply(pending, message, (deferred) =>\n Deferred.fail(deferred, error)\n ).pipe(\n Effect.andThen(\n resolveReply(pendingSettled, message, (deferred) =>\n Deferred.fail(deferred, error)\n )\n )\n );\n }\n // A form begin's or end's answer (#536), addressed to one mirror.\n case \"FormMutationBegun\":\n return resolveForm(message, (deferred) =>\n Deferred.succeed(deferred, Option.none())\n );\n case \"FormMutationEnded\":\n // An end succeeds, carrying the host's settlement error if any.\n return resolveForm(message, (deferred) =>\n Deferred.succeed(deferred, Option.fromUndefinedOr(message.error))\n );\n case \"FormMutationFailed\":\n return resolveForm(message, (deferred) =>\n Deferred.fail(deferred, new MutatorError({ message: message.message }))\n );\n case \"MutateSettled\":\n return resolveReply(pendingSettled, message, (deferred) =>\n Deferred.succeed(deferred, outcomeOf(message))\n );\n case \"ReadResult\":\n return resolveReply(pendingReads, message, (deferred) =>\n message.error === undefined\n ? Deferred.succeed(\n deferred,\n message.rows.map((row) => ({ ...row, version: \"\" }))\n )\n : Deferred.fail(deferred, new TransportError({ message: message.error }))\n );\n }\n })\n )\n )\n );\n\n const query = (subset: Subset.Subset) =>\n Ref.get(rows).pipe(Effect.map((map) => map.get(Subset.hash(subset)) ?? []));\n const readKey = (key: string) => Ref.get(rows).pipe(Effect.map((map) => map.get(key) ?? []));\n const readRelated = (key: string) =>\n Ref.get(relatedRows).pipe(Effect.map((map) => map.get(key) ?? []));\n const readMutationStates = Ref.get(mutationStatesRow);\n\n // Validate + encode args against the shared registry (fail fast in the mirror;\n // the host re-validates by decoding), then forward as a `Mutate` message and\n // register a deferred so the correlated reply resolves the caller.\n const encodeArgs = (mutator: string, args: unknown) =>\n Effect.gen(function* () {\n const definition = mutators.mutators.get(mutator);\n if (definition === undefined) {\n return yield* new MutatorError({ message: `Unknown mutator: ${mutator}`, mutator });\n }\n return yield* Schema.encodeUnknownEffect(definition.args)(args).pipe(\n Effect.mapError(\n (cause) =>\n new MutatorError({\n message: `Invalid args for mutator \"${mutator}\"`,\n mutator,\n cause,\n })\n )\n );\n });\n\n // Post `message` and wait for the host's answer, correlated by `requestId`\n // through `ref`. Registered after this mirror began closing, the request\n // can never be answered, so it fails at once instead of hanging.\n const awaitReply = <A>(\n ref: Ref.Ref<Map<number, Deferred.Deferred<A, MutatorError | TransportError>>>,\n requestId: number,\n message: MirrorProtocol.MirrorMessage\n ) =>\n Effect.gen(function* () {\n const deferred = yield* Deferred.make<A, MutatorError | TransportError>();\n yield* Ref.update(ref, (map) => new Map(map).set(requestId, deferred));\n if (yield* Ref.get(closed)) {\n return yield* resolveIn(ref, requestId, (waiting) =>\n Deferred.fail(waiting, hostUnavailable)\n ).pipe(Effect.andThen(Deferred.await(deferred)));\n }\n yield* channel.post(message);\n return yield* Deferred.await(deferred);\n });\n\n const forward = <A>(\n ref: Ref.Ref<Map<number, Deferred.Deferred<A, MutatorError | TransportError>>>,\n mutator: string,\n encoded: unknown\n ) =>\n Ref.modify(requestIds, (id) => [id + 1, id + 1] as const).pipe(\n Effect.flatMap((requestId) =>\n awaitReply(ref, requestId, {\n _tag: \"Mutate\",\n requestId,\n mirrorId,\n mutator,\n args: encoded,\n })\n )\n );\n\n // Subscribe BEFORE the first read (#84): a key published while the\n // initial read runs must land in this subscription's buffer, or a quiet\n // mirror never re-reads (gap detection needs a next item).\n const subscribeToKeyHub = Effect.gen(function* () {\n const subscription = yield* PubSub.subscribe(keyHub);\n const startSeq = yield* Ref.get(keySeq);\n const lastSeenRef = yield* Ref.make(startSeq);\n return { subscription, lastSeenRef };\n });\n\n // Decide whether one sequenced key warrants re-emitting: skip a\n // stale/duplicate seq; on a gap (a dropped key) refresh (the dropped key\n // might have been ours — the backing Ref holds latest); otherwise trigger\n // only when our own key changed. Under no pressure (contiguous seqs) this\n // is exactly a key-filter.\n const decideTrigger = (\n key: string,\n lastSeenRef: Ref.Ref<number>,\n item: SeqKey\n ): Effect.Effect<Option.Option<{ readonly gapped: boolean }>> =>\n Effect.gen(function* () {\n const lastSeen = yield* Ref.get(lastSeenRef);\n if (item.seq <= lastSeen) return Option.none();\n const gapped = item.seq > lastSeen + 1;\n yield* Ref.set(lastSeenRef, item.seq);\n if (gapped) yield* Metric.update(Telemetry.mirrorRefreshesTotal, 1);\n return gapped || item.key === key ? Option.some({ gapped }) : Option.none();\n });\n\n // Emits `read`'s current value now and again whenever `key` changes on\n // the hub, per {@link decideTrigger}.\n const observeKey = <A>(key: string, read: Effect.Effect<A>): Stream.Stream<A> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const { subscription, lastSeenRef } = yield* subscribeToKeyHub;\n return Stream.concat(\n Stream.fromEffect(read),\n Stream.fromSubscription(subscription).pipe(\n Stream.mapEffect((item) => decideTrigger(key, lastSeenRef, item)),\n Stream.filter(Option.isSome),\n Stream.mapEffect(() => read)\n )\n );\n })\n );\n\n // Row-level deltas over `key`'s whole-page reads (#115): a trigger\n // decision like {@link observeKey}, but also carrying whether the\n // trigger was a gap (`reset`, since the skipped updates are unknown) so\n // the caller can diff or reset instead of just re-reading.\n const observeKeyChanges = (\n key: string,\n read: Effect.Effect<ReadonlyArray<ClientEngine.LocalRow>>,\n options?: { readonly includeInitial?: boolean }\n ): Stream.Stream<ReadonlyArray<RowChange.RowChange<ClientEngine.LocalRow>>> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const { subscription, lastSeenRef } = yield* subscribeToKeyHub;\n const initialRows = yield* read;\n const previousRef = yield* Ref.make(initialRows);\n const initial: ReadonlyArray<ReadonlyArray<RowChange.RowChange<ClientEngine.LocalRow>>> =\n options?.includeInitial === true && Arr.isReadonlyArrayNonEmpty(initialRows)\n ? [RowChange.enters(initialRows)]\n : [];\n const live = Stream.fromSubscription(subscription).pipe(\n Stream.mapEffect((item) => decideTrigger(key, lastSeenRef, item)),\n Stream.filter(Option.isSome),\n Stream.mapEffect((option) =>\n Effect.gen(function* () {\n const previous = yield* Ref.get(previousRef);\n const next = yield* read;\n yield* Ref.set(previousRef, next);\n return option.value.gapped ? RowChange.reset(next) : RowChange.diff(previous, next);\n })\n ),\n Stream.filter((batch) => Arr.isReadonlyArrayNonEmpty(batch))\n );\n return Stream.concat(Stream.fromIterable(initial), live);\n })\n );\n\n // One unit of interest in a relational registration for the scope's\n // lifetime (counted like an observer's: pins of one registration add\n // up, and the host is told once). Returns the key the rows arrive under.\n const holdRelated = (\n collectionName: string,\n subset: Subset.Subset,\n edgeInputs: ReadonlyArray<string | Related.EdgeSelect>\n ): Effect.Effect<string, never, Scope.Scope> =>\n Effect.gen(function* () {\n const edges = edgeInputs.map(Related.edgeSelect);\n const key = MirrorProtocol.relatedKey(collectionName, subset, edges);\n const registration = { mirrorId, collection: collectionName, subset, edges };\n yield* acquireInterest(\n key,\n {\n subscribe: { _tag: \"SubscribeRelated\", ...registration },\n unsubscribe: { _tag: \"UnsubscribeRelated\", ...registration },\n },\n \"observer\"\n );\n yield* Effect.addFinalizer(() => releaseInterest(key, \"observer\"));\n return key;\n });\n\n // Ask the host to end a form submission (settle on a ruling, or abandon\n // it) and wait for it to have done so. A host that is gone, or a mirror\n // that has closed, took the entry with it, so that is an end too; a\n // settlement the host's store failed is the caller's `StoreError`.\n const endForm = (requestId: number, ruling: Option.Option<ClientEngine.FormRuling>) =>\n awaitReply(\n pendingForms,\n requestId,\n Option.match(ruling, {\n onNone: () => ({ _tag: \"EndFormMutation\", mirrorId, requestId }) as const,\n onSome: (value) =>\n ({ _tag: \"EndFormMutation\", mirrorId, requestId, ruling: value }) as const,\n })\n ).pipe(\n Effect.catchTag([\"TransportError\", \"MutatorError\"], () =>\n Effect.succeed(Option.none<string>())\n ),\n Effect.flatMap(\n Option.match({\n onNone: () => Effect.void,\n onSome: (message) => Effect.fail(new StoreError({ message })),\n })\n )\n );\n\n return {\n mutate: (mutator, args) =>\n encodeArgs(mutator, args).pipe(\n Effect.flatMap((encoded) => forward(pending, mutator, encoded))\n ),\n beginFormMutation: (form, mutator, args) =>\n Effect.gen(function* () {\n const encoded = yield* encodeArgs(mutator, args);\n const requestId = yield* Ref.updateAndGet(requestIds, (n) => n + 1);\n const begin: MirrorProtocol.FormMutationBegin = {\n mirrorId,\n form,\n mutator,\n args: encoded,\n };\n yield* awaitReply(pendingForms, requestId, {\n _tag: \"Mutate\",\n requestId,\n mutator: MirrorProtocol.FORM_MUTATION_MUTATOR,\n args: begin,\n });\n // Exactly one of settle or abandon ends it; later calls do nothing.\n const open = yield* Ref.make(true);\n const end = (ruling: Option.Option<ClientEngine.FormRuling>) =>\n Ref.getAndSet(open, false).pipe(\n Effect.flatMap((wasOpen) => (wasOpen ? endForm(requestId, ruling) : Effect.void))\n );\n const submission: ClientEngine.FormSubmission = {\n form,\n settle: (ruling) => end(Option.some(ruling)),\n abandon: end(Option.none()).pipe(Effect.ignore),\n };\n return submission;\n }),\n mutateWithAck: (mutator, args) =>\n encodeArgs(mutator, args).pipe(\n Effect.flatMap((encoded) => forward(pendingSettled, mutator, encoded))\n ),\n subscribe: (subset) =>\n acquireInterest(\n Subset.hash(subset),\n {\n subscribe: { _tag: \"Subscribe\", mirrorId, subset },\n unsubscribe: { _tag: \"Unsubscribe\", mirrorId, subset },\n },\n \"explicit\"\n ),\n unsubscribe: (subset) => releaseInterest(Subset.hash(subset), \"explicit\"),\n subscribeQuery: (name, args) =>\n acquireInterest(\n MirrorProtocol.namedKey(name, args),\n {\n subscribe: { _tag: \"SubscribeNamed\", mirrorId, name, args },\n unsubscribe: { _tag: \"UnsubscribeNamed\", mirrorId, name, args },\n },\n \"explicit\"\n ),\n unsubscribeQuery: (name, args) =>\n releaseInterest(MirrorProtocol.namedKey(name, args), \"explicit\"),\n query,\n // The server-fallthrough read (ADR-0025): forwarded to the host, which\n // owns the transport; correlated by requestId like mutations.\n read: (subsets) =>\n Effect.gen(function* () {\n const requestId = yield* Ref.updateAndGet(requestIds, (n) => n + 1);\n const deferred = yield* Deferred.make<\n ReadonlyArray<ClientEngine.ReadRow>,\n MutatorError | TransportError\n >();\n yield* Ref.update(pendingReads, (map) => new Map(map).set(requestId, deferred));\n yield* channel.post({ _tag: \"Read\", requestId, mirrorId, subsets });\n return yield* Deferred.await(deferred);\n }),\n queryNamed: (name, args) => readKey(MirrorProtocol.namedKey(name, args)),\n pulled: (key: string) =>\n Ref.get(pulledKeys).pipe(Effect.map((map) => map.get(key) ?? Coverage.NOT_PULLED)),\n // Observing auto-registers with the host for the stream's lifetime:\n // the mirror only carries keys someone subscribed, so a live read IS a\n // subscription intent (refcounted; an explicit `subscribe` still pins a\n // subset beyond any observer's lifetime).\n observe: (subset) => {\n const key = Subset.hash(subset);\n return withObserverRegistration(\n key,\n {\n subscribe: { _tag: \"Subscribe\", mirrorId, subset },\n unsubscribe: { _tag: \"Unsubscribe\", mirrorId, subset },\n },\n observeKey(key, query(subset))\n );\n },\n observeChanges: (subset, changeOptions) => {\n const key = Subset.hash(subset);\n return withObserverRegistration(\n key,\n {\n subscribe: { _tag: \"Subscribe\", mirrorId, subset },\n unsubscribe: { _tag: \"Unsubscribe\", mirrorId, subset },\n },\n observeKeyChanges(key, query(subset), changeOptions)\n );\n },\n observeNamed: (name, args) => {\n const key = MirrorProtocol.namedKey(name, args);\n return withObserverRegistration(\n key,\n {\n subscribe: { _tag: \"SubscribeNamed\", mirrorId, name, args },\n unsubscribe: { _tag: \"UnsubscribeNamed\", mirrorId, name, args },\n },\n observeKey(key, readKey(key))\n );\n },\n mutationStates: withObserverRegistration(\n MirrorProtocol.MUTATION_STATES_KEY,\n {\n subscribe: { _tag: \"SubscribeMutationStates\", mirrorId },\n unsubscribe: { _tag: \"UnsubscribeMutationStates\", mirrorId },\n },\n observeKey(MirrorProtocol.MUTATION_STATES_KEY, readMutationStates)\n ),\n related: (_registry, collectionName, subset, edgeInputs) =>\n holdRelated(collectionName, subset, edgeInputs).pipe(\n Effect.map((key) => observeKey(key, readRelated(key)))\n ),\n pinEdges: (_registry, collectionName, subset, edgeInputs) =>\n Effect.asVoid(holdRelated(collectionName, subset, edgeInputs)),\n };\n });\n","/**\n * Authorization\n *\n * Read authorization for collection-subset subscriptions: deny by default.\n * Every collection a server exposes must declare an auth filter — a\n * function from the request's SyncContext to a predicate that is AND-ed\n * into every client subscription before evaluation, so client predicates\n * can only narrow the authorized set. Write authorization is plain code\n * inside backend mutators.\n *\n * Before the auth filter is AND-ed in, a client-authored subset is checked\n * against its collection's **filterable set** (FilterPolicy.ts, ADR-0028\n * rule d, #154): every field it filters or sorts by must be declared with\n * that operator and a literal of the declared kind, and `Exists` is refused\n * outright. The auth filter's own predicate and server-resolved named\n * queries are server-authored and exempt.\n *\n * Cross-cutting concerns (tenancy, cost control, telemetry) attach via\n * SyncMiddleware, which can rewrite or reject requests around the core\n * push/pull handling.\n */\n\nimport * as Context from \"effect/Context\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as Match from \"effect/Match\";\nimport * as Option from \"effect/Option\";\nimport * as P from \"effect/Predicate\";\nimport { AuthorizationError } from \"./Errors.js\";\nimport type { SyncContext } from \"./Backend.js\";\nimport * as Collection from \"./Collection.js\";\nimport * as FilterPolicy from \"./FilterPolicy.js\";\nimport type { Predicate } from \"./Predicate.js\";\nimport * as Predicates from \"./Predicate.js\";\nimport type { PullRequest, PushRequest, ReadRequest } from \"./Protocol.js\";\nimport type { Subset } from \"./Subset.js\";\n\n/**\n * A named, session-resolved set an auth filter's predicate refers to by name\n * (`Predicate.inSet(field, name)`, ADR-0015's #205 amendment): the viewer's\n * following ids, the tenants they belong to. The name, not the members, is\n * part of the predicate, so a subscription keeps its identity while the set\n * moves.\n */\nexport interface NamedSet {\n /**\n * The collection the set is computed from. A committed write to it marks the\n * set stale for every session that resolved it and pokes those sessions, so\n * their next pull resolves it again.\n */\n readonly source: string;\n /**\n * Resolve the set's members for the request's identity. A failure binds the\n * set to nothing: an unresolvable set narrows, never widens (rule 5).\n */\n readonly resolve: (\n context: SyncContext\n ) => Effect.Effect<ReadonlyArray<Predicates.Literal>, AuthorizationError>;\n /**\n * The safety net under droppable hints: a set resolved longer ago than this is\n * resolved again on the next pull, even with no write to its source.\n */\n readonly maxAge: Duration.Input;\n}\n\n/**\n * What an auth filter decides for a request (ADR-0015's #205 amendment, the\n * same shape as effect-auth's compiled read scope): every row of the collection\n * (`AllowAll`, the role short-circuit), none of them (`Deny`), or the rows a\n * predicate admits (`Filter`), which may refer to named sets by name.\n */\nexport type ReadScope =\n | { readonly _tag: \"AllowAll\" }\n | { readonly _tag: \"Deny\" }\n | {\n readonly _tag: \"Filter\";\n readonly predicate: Predicate;\n readonly sets: Readonly<Record<string, NamedSet>>;\n };\n\n/** The {@link ReadScope} that admits every row. */\nexport const AllowAll: ReadScope = { _tag: \"AllowAll\" };\n\n/** The {@link ReadScope} that admits no row. */\nexport const Deny: ReadScope = { _tag: \"Deny\" };\n\n/**\n * The {@link ReadScope} admitting the rows `predicate` matches, with the named\n * sets its `inSet` nodes refer to. A name the predicate uses that `sets` does\n * not declare binds to nothing.\n */\nexport const filter = (\n predicate: Predicate,\n sets: Readonly<Record<string, NamedSet>> = {}\n): ReadScope => ({ _tag: \"Filter\", predicate, sets });\n\n/**\n * Produce a collection's read scope, per request. A bare `Predicate` is a\n * `Filter` without named sets (the pre-#205 form, still accepted).\n */\nexport type AuthFilter = (\n context: SyncContext\n) => Effect.Effect<ReadScope | Predicate, AuthorizationError>;\n\n/**\n * Allow every row (public collection): a filter that returns `AllowAll`. It\n * must be declared for the collection; an undeclared collection stays denied.\n */\nexport const allowAll: AuthFilter = () => Effect.succeed(AllowAll);\n\n/** The scope a filter's output stands for: a bare predicate is a `Filter` without sets. */\nexport const scopeOf = (output: ReadScope | Predicate): ReadScope =>\n isReadScope(output) ? output : filter(output);\n\n/** Whether a filter's output is a {@link ReadScope} rather than a bare predicate. */\nconst isReadScope = (output: ReadScope | Predicate): output is ReadScope =>\n P.isTagged(output, \"AllowAll\") || P.isTagged(output, \"Deny\") || P.isTagged(output, \"Filter\");\n\n/**\n * How {@link authorize} binds a named set for one request: the members, or\n * `Option.none()` when the set cannot be resolved, which narrows. The sync\n * server passes one that caches per session and records what it bound, for the\n * scope epoch; the default resolves each set afresh.\n */\nexport type SetBinder = (\n context: SyncContext,\n collection: string,\n name: string,\n set: NamedSet\n) => Effect.Effect<Option.Option<ReadonlyArray<Predicates.Literal>>>;\n\n/** Resolve a set afresh, binding nothing when its resolver fails. */\nexport const resolveSet: SetBinder = (context, _collection, _name, set) =>\n set.resolve(context).pipe(Effect.option);\n\n/** Per-collection auth filters. Subscribing to an unlisted collection fails. */\nexport interface AuthPolicy {\n readonly filters: ReadonlyMap<string, AuthFilter>;\n /**\n * The filterable set per collection (#154), from the collection registry\n * the policy was built with. When present, every client-authored subset\n * is checked against its collection's declaration — a collection the\n * registry does not know gets {@link FilterPolicy.bare} (`id` by `eq` /\n * `in`, sortable by `id`). Absent (a policy built without `collections`),\n * the filter surface is not enforced: the pre-#154 open behaviour, kept\n * for policies that never see a Node graph.\n */\n readonly declarations?: ReadonlyMap<string, FilterPolicy.FilterDeclaration>;\n}\n\n/** The {@link AuthPolicy} service the sync server authorizes every request against. */\nexport const AuthPolicy = Context.Service<AuthPolicy>(\"@thomasfosterau/legation/AuthPolicy\");\n\n/** Options for {@link policy}. */\nexport interface PolicyOptions {\n /**\n * The collection registry (`Node.registry(...).collections`) whose\n * `filterable` / `sortable` declarations `authorize` enforces. Pass it:\n * without it, nothing bounds what a client may filter or sort by.\n */\n readonly collections?: Collection.CollectionRegistry;\n}\n\n/**\n * Build an {@link AuthPolicy} from per-collection filters; unlisted collections are denied.\n * Pass `options.collections` so the collections' filterable sets are enforced too.\n */\nexport const policy = (\n filters: Readonly<Record<string, AuthFilter>>,\n options?: PolicyOptions\n): AuthPolicy => ({\n filters: new Map(Object.entries(filters)),\n ...(options?.collections === undefined\n ? {}\n : {\n declarations: new Map(\n [...options.collections.values()].map(\n (collection) => [collection.name, Collection.filterDeclarationOf(collection)] as const\n )\n ),\n }),\n});\n\n/**\n * Who authored a subset. A `\"client\"` subset came off the wire and is\n * checked against the filterable set; a `\"server\"` subset (a named-query\n * resolver's output) is trusted and only narrowed by the auth filter.\n */\nexport type SubsetOrigin = \"client\" | \"server\";\n\n/**\n * Admit a client subset's `where` / `orderBy` against its collection's\n * filterable set, or fail naming the collection, field and operator.\n * A no-op for a policy without declarations.\n */\nexport const checkFilterable = (\n authPolicy: AuthPolicy,\n subset: Subset\n): Effect.Effect<void, AuthorizationError> => {\n if (authPolicy.declarations === undefined) return Effect.void;\n const declaration = authPolicy.declarations.get(subset.collection) ?? FilterPolicy.bare;\n const failure = FilterPolicy.check(subset.collection, declaration, subset);\n return failure === undefined ? Effect.void : Effect.fail(failure);\n};\n\n/**\n * Narrow a subset with its collection's auth filter (deny by default). A\n * `\"client\"` subset is first checked against the filterable set (#154) —\n * before the filter runs, so nothing undeclared reaches `Backend.evaluate`.\n */\nexport const authorize = (\n authPolicy: AuthPolicy,\n context: SyncContext,\n subset: Subset,\n origin: SubsetOrigin = \"client\",\n bindSet: SetBinder = resolveSet\n): Effect.Effect<Subset, AuthorizationError> => {\n const declared = authPolicy.filters.get(subset.collection);\n if (declared === undefined) {\n return Effect.fail(\n new AuthorizationError({\n message: `No auth filter declared for collection \"${subset.collection}\" (deny by default)`,\n collection: subset.collection,\n })\n );\n }\n const admitted = origin === \"client\" ? checkFilterable(authPolicy, subset) : Effect.void;\n return admitted.pipe(\n Effect.andThen(declared(context)),\n Effect.flatMap((output) => {\n return Match.valueTags(scopeOf(output), {\n AllowAll: () => Effect.succeed(subset),\n Deny: () => Effect.succeed({ ...subset, where: Predicates.isIn(\"id\", []) }),\n Filter: (scope) =>\n bindScope(scope, context, subset.collection, bindSet).pipe(\n Effect.map((mandatory) => ({\n ...subset,\n where: Predicates.and(mandatory, subset.where),\n }))\n ),\n });\n })\n );\n};\n\n/**\n * A `Filter` scope's predicate with every named set bound to its members. A\n * set the predicate names that the scope does not declare, or that the binder\n * cannot resolve, is left unbound, and `Predicate.bindSets` makes an unbound\n * set narrow: its branch admits no row (rule 5).\n */\nconst bindScope = (\n scope: Extract<ReadScope, { readonly _tag: \"Filter\" }>,\n context: SyncContext,\n collection: string,\n bindSet: SetBinder\n): Effect.Effect<Predicate> =>\n Effect.forEach(\n Predicates.setNames(scope.predicate),\n (name) => {\n const set = scope.sets[name];\n return set === undefined\n ? Effect.succeed([name, Option.none()] as const)\n : bindSet(context, collection, name, set).pipe(\n Effect.map((values) => [name, values] as const)\n );\n },\n { concurrency: 1 }\n ).pipe(\n Effect.map((entries) =>\n Predicates.bindSets(\n scope.predicate,\n HashMap.fromIterable(\n entries.flatMap(([name, values]) => Option.toArray(values).map((v) => [name, v] as const))\n )\n )\n )\n );\n\n/** Interception seam around push/pull/read handling. */\nexport interface SyncMiddleware {\n readonly onPush: (\n context: SyncContext,\n request: PushRequest\n ) => Effect.Effect<PushRequest, AuthorizationError>;\n readonly onPull: (\n context: SyncContext,\n request: PullRequest\n ) => Effect.Effect<PullRequest, AuthorizationError>;\n /**\n * Around fallthrough reads (ADR-0025). Optional — absent means\n * passthrough — so middleware written before the read tier keeps working.\n */\n readonly onRead?: (\n context: SyncContext,\n request: ReadRequest\n ) => Effect.Effect<ReadRequest, AuthorizationError>;\n}\n\n/** The {@link SyncMiddleware} service; absent means {@link passthroughMiddleware}. */\nexport const SyncMiddleware = Context.Service<SyncMiddleware>(\n \"@thomasfosterau/legation/SyncMiddleware\"\n);\n\n/** The identity middleware (no interception). */\nexport const passthroughMiddleware: SyncMiddleware = {\n onPush: (_context, request) => Effect.succeed(request),\n onPull: (_context, request) => Effect.succeed(request),\n onRead: (_context, request) => Effect.succeed(request),\n};\n\n/**\n * Resolve the request's identity for a connected client group — the decoded,\n * never-client-forgeable principal the auth filters and middleware see on\n * `SyncContext.identity`. A real carrier derives it from the authenticated\n * connection (a verified token); the resolver is the seam where that lands.\n * Optional: absent ⇒ `identity` stays `undefined` (public/deny-by-default).\n */\nexport interface IdentityResolver {\n readonly resolve: (clientGroupId: string) => Effect.Effect<unknown, AuthorizationError>;\n}\n\n/** The {@link IdentityResolver} service; absent leaves `SyncContext.identity` undefined. */\nexport const IdentityResolver = Context.Service<IdentityResolver>(\n \"@thomasfosterau/legation/IdentityResolver\"\n);\n","/**\n * The forgetting bound for a backend's rejection memory (#355, #366, #468): the\n * per-client rule that drops a remembered rejection once the client's next push\n * has moved past it. MemoryBackend and JsonApiBackend bound their memory with\n * `forgetBelow`; SqlBackend shares only `floorsOf` and keeps its own forgetting\n * loop over its ledger rows.\n */\n\nimport * as Arr from \"effect/Array\";\n\n/**\n * The lowest mutation id a push carries, per client: the push's floors (#355).\n * A client resends only ids it has not had acknowledged, so a push whose lowest\n * id for a client is `f` proves the client has seen the outcome of every id below `f`.\n */\nexport const floorsOf = (\n mutations: ReadonlyArray<{ readonly clientId: string; readonly mutationId: number }>\n): Map<string, number> => {\n const floors = new Map<string, number>();\n Arr.forEach(mutations, ({ clientId, mutationId }) => {\n floors.set(clientId, Math.min(floors.get(clientId) ?? Infinity, mutationId));\n });\n return floors;\n};\n\n/**\n * Forget the rejections a client's push has moved past (#355): drop each client's\n * remembered rejections whose mutation id is below its floor, and keep the rest.\n * `clients` maps each client in one client group to its remembered rejections\n * (mutation id → reason); `floors` maps each client in a push to the lowest\n * mutation id that push carries (see {@link floorsOf}). A client with no\n * rejections left is removed from the result, and a pull never forgets, so only\n * a push calls this. Returns `clients` itself when nothing is forgotten, so a\n * caller can detect the no-op by reference.\n */\nexport const forgetBelow = (\n clients: ReadonlyMap<string, ReadonlyMap<number, string>>,\n floors: ReadonlyMap<string, number>\n): ReadonlyMap<string, ReadonlyMap<number, string>> => {\n let kept: Map<string, ReadonlyMap<number, string>> | undefined;\n Arr.forEach(floors, ([clientId, floor]) => {\n const ids = clients.get(clientId);\n if (ids === undefined) return;\n const remaining = new Map([...ids].filter(([mutationId]) => mutationId >= floor));\n if (remaining.size === ids.size) return;\n kept ??= new Map(clients);\n if (remaining.size === 0) kept.delete(clientId);\n else kept.set(clientId, remaining);\n });\n return kept ?? clients;\n};\n","/**\n * UnknownMutator\n *\n * The typed failure a Backend raises when a pushed mutation names a mutator\n * with no registered handler. Backends build it with `make`, and the backend\n * contract recognises it with `isError`, so the check does not depend on the\n * wording of the message. The contract falls back to the message text for a\n * backend that does not use `make` yet.\n */\n\nimport * as P from \"effect/Predicate\";\nimport { BackendError } from \"./Errors.js\";\n\n/** The `cause` of a {@link BackendError} raised for a mutator with no registered handler. */\nexport interface Cause {\n readonly _tag: \"UnknownMutator\";\n readonly mutator: string;\n}\n\n/** Build the transient `BackendError` for a mutator with no registered handler. */\nexport const make = (mutator: string): BackendError =>\n new BackendError({\n message: `Unknown mutator: ${mutator}`,\n cause: { _tag: \"UnknownMutator\", mutator } satisfies Cause,\n });\n\n/**\n * True when `error` is a `BackendError` built by {@link make}, so its `cause` is\n * the typed unknown-mutator cause, whatever its message says.\n */\nexport const isError = (error: unknown): boolean => {\n if (!P.isObjectOrArray(error)) return false;\n if (!(\"_tag\" in error) || error._tag !== \"BackendError\") return false;\n if (!(\"cause\" in error)) return false;\n const cause = error.cause;\n return P.isObjectOrArray(cause) && \"_tag\" in cause && cause._tag === \"UnknownMutator\";\n};\n","/**\n * Backend\n *\n * The BYO server contract (ADR-0009): the app owns canonical storage and\n * mutator execution; the library owns everything mechanical (CVR diffing,\n * patches, cookies, fan-out). An implementation must guarantee:\n *\n * 1. `applyMutations` executes each mutation's authoritative mutator\n * transactionally, with the per-client `lastMutationId` bump atomic with\n * the effects. Mutations with `mutationId <= lastMutationId` are skipped\n * (idempotency); a gap (`> lastMutationId + 1`) is a `BackendError`. A\n * handler that fails with `BackendError` aborts the batch (transient — the\n * client retries); one that fails with `MutationRejected` is permanent — the\n * id is bumped atomically *without* applying effects, so the mutation is\n * acknowledged and skipped rather than poisoning the queue, and mutations\n * behind it still apply. Calls for one client group may overlap (a retry\n * while the first push is in flight): each mutation must still apply at most\n * once, and `lastMutationId` must never move backwards, so a copy whose\n * mutation a concurrent call already committed is skipped. Every copy\n * reports the committed outcome (#355): a copy that is skipped, whether as\n * a replay or because a concurrent call committed first, lists its mutation\n * in `rejected` when that mutation was committed as rejected, with the same\n * reason. So a client's outcome does not depend on which response reaches\n * it first. A backend may forget a committed rejection once the client's\n * next push starts past it, since a client resends only ids it has not had\n * acknowledged.\n *\n * Mutations from different client groups are serialisable (#353): the\n * effects of all committed mutations are equivalent to some serial order,\n * and a handler's reads see a state consistent with that order. So no\n * committed write is lost to a concurrent call from another group that read\n * the same row. A backend meets this with a store-wide lock, with a commit\n * that re-checks each row the handler read and runs the handler again when\n * one changed, or, on a database, with serialisable isolation. A backend may\n * therefore run a handler more than once, so a handler's effects outside its\n * writer must be safe to repeat. A backend that does not meet this does not\n * conform to guarantee 1.\n * 2. `evaluate` returns the **current** (row id, row version) set for an\n * authorized subset — versions change on every authoritative write. An\n * optional `evaluateMany` evaluates several subsets at once (#505), so a\n * backend can answer a pull's subsets in a bounded number of round trips;\n * its result for each subset must equal `evaluate`'s for that subset, in\n * the same order.\n * 3. `getRows` returns encoded row values for explicit ids.\n * 4. `rejections` lists the permanent rejections a client group still remembers,\n * each with its reason (#365). A pull reports those its watermark covers, so\n * a client whose push response was lost settles the rejection as rejected\n * rather than applied. A rejection is remembered from the commit until a\n * later push moves past it (guarantee 1), so it is listed for as long as a\n * client could still need it.\n *\n * `MemoryBackend.ts` is the reference implementation;\n * `BackendContract.verifyBackendContract` checks these guarantees against\n * any implementation. {@link transaction} builds an `applyMutations` that\n * keeps guarantee 1's ordering and bump rules by construction from a store's\n * steps (#177); `MemoryBackend` and `SqlBackend` use it, and a hand-assembled\n * backend remains possible.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as P from \"effect/Predicate\";\nimport type { RowId, RowVersion } from \"./Collection.js\";\nimport { BackendError, type MutationRejected } from \"./Errors.js\";\nimport type { Mutation } from \"./Protocol.js\";\nimport * as RejectionMemory from \"./RejectionMemory.js\";\nimport type { Subset } from \"./Subset.js\";\nimport * as UnknownMutator from \"./UnknownMutator.js\";\n\n/** Request-scoped context for authorization decisions. */\nexport interface SyncContext {\n readonly clientGroupId: string;\n /** App-defined identity (e.g. decoded token); never client-forgeable. */\n readonly identity?: unknown;\n}\n\n/** A change hint emitted after a committed push, for fan-out matching. */\nexport interface ChangeHint {\n readonly collection: string;\n readonly ids: ReadonlyArray<RowId>;\n /**\n * The current values of the rows PUT in this change, when the backend has\n * them cheaply to hand. Lets the server match hints against subscription\n * predicates instead of only their collection. Best-effort and additive: a\n * backend that can't produce values omits the field, and the server falls\n * back to a collection-level match. Deletes are ids present in `ids` but\n * absent from `values`; an omitted `values` means \"no value information\",\n * not \"all deletes\".\n */\n readonly values?: ReadonlyArray<{ readonly id: RowId; readonly value: unknown }> | undefined;\n /**\n * The pre-write values of the changed rows, when the backend has them\n * cheaply to hand (additive, like {@link values}). Old values let\n * topic-derived fan-out (ADR-0023) poke the windows a row **moved away\n * from** — an update that changes a foreign key derives both parents'\n * fine topics; a delete derives from the old row. Backends without them\n * degrade gracefully: moved-away windows converge on the interval pull.\n */\n readonly oldValues?: ReadonlyArray<{ readonly id: RowId; readonly value: unknown }> | undefined;\n}\n\n/** The (row id, row version) set an evaluated subset currently contains. */\nexport interface SubsetEntry {\n readonly id: RowId;\n readonly version: RowVersion;\n}\n\n/** A mutation the backend acknowledged but permanently rejected. */\nexport interface RejectedMutation {\n readonly clientId: string;\n readonly mutationId: number;\n readonly reason: string;\n}\n\n/**\n * What {@link Backend.applyMutations} reports: the new per-client mutation ids and change hints.\n */\nexport interface ApplyResult {\n /** Highest applied (or permanently rejected) mutation id per client. */\n readonly lastMutationIds: Readonly<Record<string, number>>;\n readonly hints: ReadonlyArray<ChangeHint>;\n /**\n * Mutations acknowledged but permanently rejected (`MutationRejected`): their\n * id was bumped without applying effects. Includes a rejected mutation a\n * replayed copy names (guarantee 1). Omitted/empty when none were.\n */\n readonly rejected?: ReadonlyArray<RejectedMutation>;\n}\n\n/**\n * The BYO server storage contract: apply mutations transactionally, evaluate an authorized\n * subset, fetch rows by id. The guarantees are in the module header.\n */\nexport interface Backend {\n readonly applyMutations: (\n context: SyncContext,\n mutations: ReadonlyArray<Mutation>\n ) => Effect.Effect<ApplyResult, BackendError>;\n\n /** Current per-client lastMutationIds for a group (used by pull). */\n readonly lastMutationIds: (\n context: SyncContext\n ) => Effect.Effect<Readonly<Record<string, number>>, BackendError>;\n\n /**\n * The permanent rejections the group's clients still remember, each with its\n * reason (guarantee 4). The sync server filters them by the pull's watermark\n * and returns them in the pull response (#365). Each entry's `mutationId` is\n * covered by its client's `lastMutationIds`, since a rejection is committed\n * with its id's bump.\n */\n readonly rejections: (\n context: SyncContext\n ) => Effect.Effect<ReadonlyArray<RejectedMutation>, BackendError>;\n\n /**\n * Evaluate an **already-authorized** subset (auth filters are AND-ed in\n * by the sync server before this call) to its current entries, in subset\n * order, respecting limit/cursor.\n */\n readonly evaluate: (\n context: SyncContext,\n subset: Subset\n ) => Effect.Effect<ReadonlyArray<SubsetEntry>, BackendError>;\n\n /**\n * Evaluate several **already-authorized** subsets at once (#505): one entry\n * list per subset, in the order of `subsets`, each equal to what\n * {@link Backend.evaluate} returns for that subset (guarantee 2). Optional:\n * a backend that can batch (one SQL statement for a pull's subsets) provides\n * it, and callers fall back to per-subset `evaluate` through\n * {@link evaluateAll} when it is absent. `BackendContract` checks the\n * equivalence on every backend that provides it.\n */\n readonly evaluateMany?:\n | ((\n context: SyncContext,\n subsets: ReadonlyArray<Subset>\n ) => Effect.Effect<ReadonlyArray<ReadonlyArray<SubsetEntry>>, BackendError>)\n | undefined;\n\n /** Fetch encoded row values for explicit ids. Missing ids are omitted. */\n readonly getRows: (\n context: SyncContext,\n collection: string,\n ids: ReadonlyArray<RowId>\n ) => Effect.Effect<\n ReadonlyArray<{ readonly id: RowId; readonly version: RowVersion; readonly value: unknown }>,\n BackendError\n >;\n}\n\n/**\n * Evaluate `subsets` to their entries, one list per subset in order: through\n * the backend's {@link Backend.evaluateMany} when it provides one, else one\n * {@link Backend.evaluate} per subset, in sequence. An empty `subsets` makes\n * no backend call, and an `evaluateMany` that returns a different number of\n * lists than it was given subsets fails with a `BackendError`.\n *\n * @example\n * ```ts\n * import { Backend, MemoryBackend } from \"@thomasfosterau/legation\";\n * import { Subset } from \"@thomasfosterau/legation/internal\";\n * import * as Effect from \"effect/Effect\";\n *\n * const program = Effect.gen(function* () {\n * const backend = yield* MemoryBackend.make({});\n * return yield* Backend.evaluateAll(backend, { clientGroupId: \"g\" }, [\n * Subset.make({ collection: \"todos\" }),\n * ]);\n * });\n * ```\n */\nexport const evaluateAll = (\n backend: Backend,\n context: SyncContext,\n subsets: ReadonlyArray<Subset>\n): Effect.Effect<ReadonlyArray<ReadonlyArray<SubsetEntry>>, BackendError> => {\n if (Arr.isReadonlyArrayEmpty(subsets)) return Effect.succeed([]);\n const many = backend.evaluateMany;\n return many === undefined\n ? Effect.forEach(subsets, (subset) => backend.evaluate(context, subset), { concurrency: 1 })\n : many(context, subsets).pipe(\n Effect.filterOrFail(\n (lists) => lists.length === subsets.length,\n (lists) =>\n new BackendError({\n message: `evaluateMany returned ${lists.length} entry lists for ${subsets.length} subsets`,\n })\n )\n );\n};\n\n/** The {@link Backend} service the sync server reads and writes through. */\nexport const Backend = Context.Service<Backend>(\"@thomasfosterau/legation/Backend\");\n\n/**\n * Build change hints from a push's touched ids and the values of its PUTs:\n * each touched collection becomes one hint whose `values` carry the current\n * row value of every PUT there. Ids touched but absent from `puts` are deletes,\n * so they appear in `ids` but not `values`. Backends that track writes as\n * `(touched, puts)` share this to emit predicate-matchable hints (ADR-0009).\n * Passing the pre-write rows (`olds`) additionally fills `oldValues`, which\n * topic-derived fan-out uses to poke moved-away edge windows (ADR-0023).\n */\nexport const buildChangeHints = (\n touched: ReadonlyMap<string, ReadonlySet<RowId>>,\n puts: ReadonlyMap<string, ReadonlyMap<RowId, unknown>>,\n olds?: ReadonlyMap<string, ReadonlyMap<RowId, unknown>>\n): ReadonlyArray<ChangeHint> =>\n [...touched].map(([collection, ids]) => {\n const putMap = puts.get(collection);\n const oldMap = olds?.get(collection);\n const values = [...ids].flatMap((id) =>\n putMap?.has(id) === true ? [{ id, value: putMap.get(id) }] : []\n );\n const oldValues = [...ids].flatMap((id) =>\n oldMap?.has(id) === true ? [{ id, value: oldMap.get(id) }] : []\n );\n return {\n collection,\n ids: [...ids],\n values,\n ...(Arr.isReadonlyArrayEmpty(oldValues) ? {} : { oldValues }),\n };\n });\n\n// ─── The transactional combinator (#177) ────────────────────────────────────\n\n/**\n * What a store found when {@link transaction} asked it to open a pushed\n * mutation: the mutation is the client's next one and the store opened a unit\n * of work for it (`Opened`), or it is not, and the store reports the client's\n * committed watermark instead (`Watermark`), with the rejection it remembers\n * for the mutation's id when there is one. The combinator, not the store,\n * decides from a watermark whether the mutation is a replay or a gap.\n */\nexport type Opened<Unit> =\n | { readonly _tag: \"Opened\"; readonly unit: Unit }\n | {\n readonly _tag: \"Watermark\";\n readonly lastMutationId: number;\n readonly rejection: Option.Option<string>;\n };\n\n/**\n * What {@link transaction} asks a store to commit for one opened mutation,\n * together with the client's mutation-id bump. An applied mutation carries the\n * effects its handler staged; a rejected one carries only its reason, so the\n * combinator never hands a rejected mutation's effects to the store.\n */\nexport type Outcome<Staged> =\n | { readonly _tag: \"Applied\"; readonly staged: Staged }\n | { readonly _tag: \"Rejected\"; readonly reason: string };\n\n/**\n * How a store's commit settled: it committed the outcome with the bump\n * (`Committed`), a concurrent call had already committed the mutation, whose\n * rejection reason it reports when there was one (`Replayed`), or a row the\n * handler read changed before the commit, so nothing was written and the\n * handler must run again (`Conflicted`, guarantee 1's serialisability).\n */\nexport type Commit =\n | { readonly _tag: \"Committed\" }\n | { readonly _tag: \"Replayed\"; readonly rejection: Option.Option<string> }\n | { readonly _tag: \"Conflicted\" };\n\n/**\n * The storage steps {@link transaction} composes into an `applyMutations`.\n * `Handler` is the store's app-handler type, `Batch` its per-push state, `Unit`\n * its per-mutation unit of work and `Staged` what a handler's run leaves to\n * commit.\n *\n * The store's obligations shrink to these: `commit` writes an applied\n * outcome's effects and the bump as one atomic step, and a rejected outcome's\n * bump and remembered rejection with none of the unit's effects; `atomically`,\n * when given, runs the whole push as one transaction. The ordering, skip, gap\n * and reporting rules are the combinator's.\n */\nexport interface TransactionSteps<Handler, Batch, Unit, Staged> {\n /** The app's authoritative handlers, by mutator name. A mutator without one is an `UnknownMutator` error. */\n readonly handlers: Readonly<Record<string, Handler>>;\n /**\n * Run the whole push inside the store's transaction (`SqlExecutor.transaction`).\n * A store without one passes {@link withoutTransaction}, and each `commit` is\n * then the atomic unit.\n */\n readonly atomically: <A>(\n context: SyncContext,\n effect: Effect.Effect<A, BackendError>\n ) => Effect.Effect<A, BackendError>;\n /**\n * Start a push: forget the remembered rejections below `floors` (the push's\n * lowest id per client, `RejectionMemory.floorsOf`) and take whatever per-push\n * state the store needs (a snapshot for hint old values, a savepoint counter).\n */\n readonly begin: (\n context: SyncContext,\n floors: ReadonlyMap<string, number>\n ) => Effect.Effect<Batch, BackendError>;\n /**\n * Open the mutation's unit of work when it is its client's next one\n * (`mutationId` is the committed watermark plus one); otherwise report the\n * watermark. A store may move the watermark here (SQL's claim) as long as\n * the move is undone with the unit's effects.\n */\n readonly open: (batch: Batch, mutation: Mutation) => Effect.Effect<Opened<Unit>, BackendError>;\n /**\n * Run the app's handler for the mutation in the unit. Fails with\n * `MutationRejected` for a permanent rejection (the combinator commits it as\n * `Rejected`) or `BackendError` for a transient one (the push aborts).\n */\n readonly run: (\n unit: Unit,\n handler: Handler,\n mutation: Mutation\n ) => Effect.Effect<Staged, BackendError | MutationRejected>;\n /** Commit the outcome with the bump, atomically (see {@link TransactionSteps}). */\n readonly commit: (unit: Unit, outcome: Outcome<Staged>) => Effect.Effect<Commit, BackendError>;\n /**\n * Give a unit back after its handler failed transiently or named no handler:\n * undo anything `open` moved. Best effort: `Effect.void` when `open` moves\n * nothing.\n */\n readonly release: (unit: Unit) => Effect.Effect<void>;\n /** The push's result from what committed as applied, in push order. */\n readonly finish: (\n batch: Batch,\n applied: ReadonlyArray<Staged>\n ) => Effect.Effect<\n {\n readonly lastMutationIds: ApplyResult[\"lastMutationIds\"];\n readonly hints: ApplyResult[\"hints\"];\n },\n BackendError\n >;\n /**\n * How many times one mutation's handler runs while its commit keeps coming\n * back `Conflicted` before it fails transiently. A store whose commit never\n * conflicts passes 1.\n */\n readonly maxAttempts: number;\n}\n\n/** How one pushed mutation settled under {@link transaction}. */\ntype Settled<Staged> =\n | { readonly _tag: \"Applied\"; readonly staged: Staged }\n | { readonly _tag: \"Reported\"; readonly rejection: Option.Option<string> };\n\n/** What a watermark makes of a mutation: a replay when it covers the id, a gap when it is behind. */\nconst fromWatermark = <Staged>(\n mutation: Mutation,\n lastMutationId: number,\n rejection: Option.Option<string>\n): Effect.Effect<Settled<Staged>, BackendError> =>\n mutation.mutationId <= lastMutationId\n ? Effect.succeed({ _tag: \"Reported\", rejection })\n : Effect.fail(\n new BackendError({\n message:\n mutation.mutationId === lastMutationId + 1\n ? `The store did not open mutation ${mutation.mutationId} of client ${mutation.clientId}, its next one`\n : `Mutation id gap for client ${mutation.clientId}: got ${mutation.mutationId}, expected ${lastMutationId + 1}`,\n })\n );\n\n/**\n * Build a backend's `applyMutations` from its storage steps (#177). The\n * combinator owns the ledger rules, so a backend built through it gets them by\n * construction rather than by convention:\n *\n * - **In order, exactly once** (`BackendContract` rules 1–3): mutations settle\n * one at a time in push order; a mutation the watermark covers is skipped,\n * reporting its committed rejection; one past the next expected id is a gap,\n * a `BackendError`; a non-positive id is never new and opens nothing.\n * - **The bump travels with the outcome** (rules 4, 9 and 10): the only way a\n * handler's effects reach `commit` is with the bump, a `MutationRejected` is\n * committed as a bump with its reason and no effects, and a transient\n * failure commits nothing and releases the unit.\n * - **Every copy reports the committed outcome** (#355): a replay or a copy a\n * concurrent call committed first lists the committed rejection.\n *\n * What stays with the store, and with the runtime `BackendContract` suite: that\n * `commit` (or `atomically`) is really atomic and isolated, and everything\n * about evaluation (rule 6, settled by ADR-0028 and the differential harness).\n * Hand-assembled backends remain possible (ADR-0009); they get none of this\n * and must pass the suite on their own.\n *\n * @example\n * ```ts\n * import { Backend } from \"@thomasfosterau/legation\";\n * import * as Effect from \"effect/Effect\";\n * import * as Option from \"effect/Option\";\n *\n * // A ledger-only store: handlers stage nothing, commits bump an in-memory watermark.\n * const ledger = new Map<string, number>();\n * const applyMutations = Backend.transaction({\n * handlers: { \"todo/noop\": () => Effect.void },\n * atomically: Backend.withoutTransaction,\n * maxAttempts: 1,\n * begin: (context) => Effect.succeed(context),\n * open: (_context, mutation) => {\n * const last = ledger.get(mutation.clientId) ?? 0;\n * return Effect.succeed(\n * mutation.mutationId === last + 1\n * ? ({ _tag: \"Opened\", unit: mutation } as const)\n * : ({ _tag: \"Watermark\", lastMutationId: last, rejection: Option.none() } as const)\n * );\n * },\n * run: (_mutation, handler) => handler(),\n * commit: (mutation) =>\n * Effect.sync(() => {\n * ledger.set(mutation.clientId, mutation.mutationId);\n * return { _tag: \"Committed\" } as const;\n * }),\n * release: () => Effect.void,\n * finish: () => Effect.sync(() => ({ lastMutationIds: Object.fromEntries(ledger), hints: [] })),\n * });\n *\n * const result = Effect.runSync(\n * applyMutations({ clientGroupId: \"g\" }, [\n * { clientId: \"c\", mutationId: 1, mutator: \"todo/noop\", args: {}, createdAt: 0 },\n * ])\n * );\n * console.log(result.lastMutationIds); // { c: 1 }\n * ```\n */\nexport const transaction =\n <Handler, Batch, Unit, Staged>(\n steps: TransactionSteps<Handler, Batch, Unit, Staged>\n ): Backend[\"applyMutations\"] =>\n (context, mutations) => {\n // Settle what a commit reported: run again after a conflict, up to the cap.\n const afterCommit = (\n batch: Batch,\n mutation: Mutation,\n attempt: number,\n outcome: Outcome<Staged>,\n committed: Commit\n ): Effect.Effect<Settled<Staged>, BackendError> => {\n if (P.isTagged(committed, \"Conflicted\")) {\n return attempt >= steps.maxAttempts\n ? Effect.fail(\n new BackendError({\n message:\n `serialization conflict: mutation ${mutation.mutationId} of client ${mutation.clientId} ` +\n `read rows that changed before its commit on each of ${steps.maxAttempts} attempts`,\n })\n )\n : settle(batch, mutation, attempt + 1);\n }\n if (P.isTagged(committed, \"Replayed\")) {\n return Effect.succeed({ _tag: \"Reported\", rejection: committed.rejection });\n }\n return Effect.succeed(\n P.isTagged(outcome, \"Applied\")\n ? { _tag: \"Applied\", staged: outcome.staged }\n : { _tag: \"Reported\", rejection: Option.some(outcome.reason) }\n );\n };\n\n const settle = Effect.fnUntraced(function* (\n batch: Batch,\n mutation: Mutation,\n attempt: number\n ): Effect.fn.Return<Settled<Staged>, BackendError> {\n const opened = yield* steps.open(batch, mutation);\n if (P.isTagged(opened, \"Watermark\")) {\n return yield* fromWatermark<Staged>(mutation, opened.lastMutationId, opened.rejection);\n }\n const unit = opened.unit;\n const handler = steps.handlers[mutation.mutator];\n if (handler === undefined) {\n yield* steps.release(unit);\n return yield* UnknownMutator.make(mutation.mutator);\n }\n const outcome = yield* steps.run(unit, handler, mutation).pipe(\n Effect.map((staged): Outcome<Staged> => ({ _tag: \"Applied\", staged })),\n Effect.catchTag(\"MutationRejected\", (error) =>\n Effect.succeed<Outcome<Staged>>({ _tag: \"Rejected\", reason: error.reason })\n ),\n Effect.onError(() => steps.release(unit))\n );\n const committed = yield* steps.commit(unit, outcome);\n return yield* afterCommit(batch, mutation, attempt, outcome, committed);\n });\n\n const push = Effect.fnUntraced(function* () {\n const batch = yield* steps.begin(context, RejectionMemory.floorsOf(mutations));\n // Ids start at 1 and a watermark at 0, so a non-positive id is never new:\n // it opens nothing.\n const settled = yield* Effect.forEach(\n mutations.filter((mutation) => mutation.mutationId > 0),\n (mutation) =>\n settle(batch, mutation, 1).pipe(Effect.map((outcome) => ({ mutation, outcome }))),\n { concurrency: 1 }\n );\n const applied = settled.flatMap(({ outcome }) =>\n P.isTagged(outcome, \"Applied\") ? [outcome.staged] : []\n );\n const rejected = settled.flatMap(({ mutation, outcome }): Array<RejectedMutation> =>\n P.isTagged(outcome, \"Reported\")\n ? Option.toArray(outcome.rejection).map((reason) => ({\n clientId: mutation.clientId,\n mutationId: mutation.mutationId,\n reason,\n }))\n : []\n );\n const { lastMutationIds, hints } = yield* steps.finish(batch, applied);\n const result: ApplyResult = { lastMutationIds, hints };\n // `rejected` is set only when a mutation was rejected.\n return Arr.isReadonlyArrayNonEmpty(rejected) ? { ...result, rejected } : result;\n });\n return steps.atomically(context, push());\n };\n\n/**\n * The {@link TransactionSteps.atomically} of a store without a transaction:\n * the push runs as it is, and each `commit` is the atomic unit.\n */\nexport const withoutTransaction = <A>(\n _context: SyncContext,\n effect: Effect.Effect<A, BackendError>\n): Effect.Effect<A, BackendError> => effect;\n","/**\n * Cvr — Client View Record\n *\n * The server-side record of exactly which row versions a client group\n * holds (ADR-0008). Each pull: evaluate the client's authorized subsets to\n * the current (id, version) sets, diff against the CVR identified by the\n * presented cookie, send the difference as a patch, store the new CVR under\n * a fresh cookie.\n *\n * CVR storage may be ephemeral: an unrecognized cookie degrades safely to a\n * reset patch (Clear + full Puts).\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Context from \"effect/Context\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Ref from \"effect/Ref\";\nimport * as Schema from \"effect/Schema\";\nimport { KeyValueStore } from \"effect/persistence\";\nimport type { RowId, RowVersion } from \"./Collection.js\";\nimport { StoreError } from \"./Errors.js\";\n\n/** What one client group holds: collection → row id → row version. */\nexport interface Cvr {\n readonly rows: ReadonlyMap<string, ReadonlyMap<RowId, RowVersion>>;\n}\n\n/** The CVR of a group that holds nothing yet. */\nexport const empty: Cvr = { rows: new Map() };\n\n/** The desired next view, computed from evaluated subsets + fetched rows. */\nexport interface NextView {\n readonly rows: ReadonlyMap<string, ReadonlyMap<RowId, RowVersion>>;\n}\n\n/** A diff between a CVR and the next view, in row-id terms. */\nexport interface CvrDiff {\n /** Rows the client is missing or holds at a stale version. */\n readonly puts: ReadonlyArray<{ readonly collection: string; readonly id: RowId }>;\n /** Rows the client holds that left the view. */\n readonly dels: ReadonlyArray<{ readonly collection: string; readonly id: RowId }>;\n}\n\n/** Pure CVR diff: what to put (missing/stale) and what to delete (gone). */\nexport const diff = (previous: Cvr, next: NextView): CvrDiff => {\n const puts: Array<{ collection: string; id: RowId }> = [];\n const dels: Array<{ collection: string; id: RowId }> = [];\n\n Arr.forEach(next.rows, ([collection, nextRows]) => {\n const prevRows = previous.rows.get(collection);\n Arr.forEach(nextRows, ([id, version]) => {\n if (prevRows?.get(id) !== version) puts.push({ collection, id });\n });\n });\n Arr.forEach(previous.rows, ([collection, prevRows]) => {\n const nextRows = next.rows.get(collection);\n Arr.forEach(prevRows.keys(), (id) => {\n if (!nextRows?.has(id)) dels.push({ collection, id });\n });\n });\n return { puts, dels };\n};\n\n/** CVR persistence, keyed by cookie. */\nexport interface CvrStore {\n readonly get: (cookie: string) => Effect.Effect<Cvr | undefined, StoreError>;\n readonly set: (cookie: string, cvr: Cvr) => Effect.Effect<void, StoreError>;\n /** Forget CVRs for cookies no longer presentable (optional hygiene). */\n readonly remove: (cookie: string) => Effect.Effect<void, StoreError>;\n}\n\n/** The {@link CvrStore} service the sync server keeps CVRs in. */\nexport const CvrStore = Context.Service<CvrStore>(\"@thomasfosterau/legation/CvrStore\");\n\n/** In-memory CVR store (tests, single-instance servers, sync rooms). */\nexport const makeMemoryStore: Effect.Effect<CvrStore> = Effect.gen(function* () {\n const state = yield* Ref.make(new Map<string, Cvr>());\n return CvrStore.of({\n get: (cookie) => Ref.get(state).pipe(Effect.map((m) => m.get(cookie))),\n set: (cookie, cvr) =>\n Ref.update(state, (m) => {\n const next = new Map(m);\n next.set(cookie, cvr);\n return next;\n }),\n remove: (cookie) =>\n Ref.update(state, (m) => {\n const next = new Map(m);\n next.delete(cookie);\n return next;\n }),\n });\n});\n\n/** A layer providing {@link makeMemoryStore}. */\nexport const layerMemoryStore: Layer.Layer<CvrStore> = Layer.effect(CvrStore)(makeMemoryStore);\n\n// ─── Shared-storage CVR store (distributed) ──────────────────────────────────\n\n/**\n * The JSON-serializable shape of a CVR on disk: rows as nested entry pairs.\n * The schema is the source of truth for the on-disk form and for decoding\n * untrusted stored bytes; `WireCvr` is derived from it.\n */\nconst WireCvr = Schema.fromJsonString(\n Schema.Struct({\n rows: Schema.Array(\n Schema.Tuple([\n Schema.String,\n Schema.Array(Schema.Tuple([Schema.String, Schema.Union([Schema.String, Schema.Number])])),\n ])\n ),\n })\n);\n\ntype WireCvr = typeof WireCvr.Type;\n\nconst decodeCvr = Schema.decodeUnknownEffect(WireCvr);\n\nconst toWire = (cvr: Cvr): WireCvr => ({\n rows: [...cvr.rows].map(([collection, versions]) => [collection, [...versions]] as const),\n});\n\nconst fromWire = (wire: WireCvr): Cvr => ({\n rows: new Map(wire.rows.map(([collection, versions]) => [collection, new Map(versions)])),\n});\n\n/**\n * Options for a {@link CvrStore} over an Effect `KeyValueStore` (a store shared across instances).\n */\nexport interface KeyValueCvrOptions {\n /** Key namespace inside the store. Defaults to `\"legation/cvr/\"`. */\n readonly prefix?: string;\n}\n\n/**\n * A CVR store over `effect/persistence` KeyValueStore (ADR-0009):\n * back it with a *shared* KVS — Redis, SQL, a Durable Object's storage — and\n * every server instance reads the same client view records, so a client can\n * present a cookie minted by one instance and pull a minimal patch from\n * another. CVR storage may be ephemeral (an unrecognized cookie degrades to\n * a reset), so eviction/TTL is the backing store's concern.\n */\nexport const makeKeyValueStore = (\n options?: KeyValueCvrOptions\n): Effect.Effect<CvrStore, never, KeyValueStore.KeyValueStore> =>\n Effect.gen(function* () {\n const store = KeyValueStore.prefix(\n yield* KeyValueStore.KeyValueStore,\n options?.prefix ?? \"legation/cvr/\"\n );\n const storeError = (message: string) => (cause: unknown) => new StoreError({ message, cause });\n return CvrStore.of({\n get: (cookie) =>\n store.get(cookie).pipe(\n Effect.mapError(storeError(`Failed to read CVR \"${cookie}\"`)),\n Effect.flatMap((raw) =>\n raw === undefined\n ? Effect.succeed(undefined)\n : decodeCvr(raw).pipe(\n Effect.map(fromWire),\n Effect.mapError(storeError(`Corrupt CVR at \"${cookie}\"`))\n )\n )\n ),\n set: (cookie, cvr) =>\n store\n .set(cookie, JSON.stringify(toWire(cvr)))\n .pipe(Effect.mapError(storeError(`Failed to write CVR \"${cookie}\"`))),\n remove: (cookie) =>\n store.remove(cookie).pipe(Effect.mapError(storeError(`Failed to remove CVR \"${cookie}\"`))),\n });\n });\n\n/** Layer providing the KeyValueStore-backed CVR store. */\nexport const layerKeyValueStore = (\n options?: KeyValueCvrOptions\n): Layer.Layer<CvrStore, never, KeyValueStore.KeyValueStore> =>\n Layer.effect(CvrStore)(makeKeyValueStore(options));\n","/**\n * InvalidationBus\n *\n * The pluggable channel carrying committed-write hints from the backend to\n * sync sessions, possibly across instances (ADR-0009). Fan-out is\n * poke-then-pull over this bus: instances match hints against their\n * sessions' subscriptions and poke affected client groups. Correctness\n * never depends on the bus — a missed hint only delays the next pull.\n *\n * The in-process PubSub implementation is the default. For multi-instance\n * deployments, `makeSerialized` runs the bus over a {@link BusBroker} — a\n * single string pub/sub channel — so a Durable Object broadcast, Redis\n * pub/sub, or Postgres LISTEN/NOTIFY becomes a distributed bus by\n * implementing one tiny interface.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Context from \"effect/Context\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Metric from \"effect/Metric\";\nimport * as PubSub from \"effect/PubSub\";\nimport * as Schema from \"effect/Schema\";\nimport * as Scope from \"effect/Scope\";\nimport type { ChangeHint } from \"./Backend.js\";\nimport * as Telemetry from \"./Telemetry.js\";\n\n/**\n * Default capacity for the bounded in-process bus and memory broker. Hints are\n * small \"pull soon\" batches; 1024 buffered batches is ample headroom before a\n * slow consumer sheds load, and correctness never depends on the bus.\n */\nconst DEFAULT_CAPACITY = 1024;\n\n/** Bounding options shared by the in-process bus and the memory broker. */\nexport interface BusCapacityOptions {\n /** PubSub capacity before publishes are dropped. Defaults to 1024. */\n readonly capacity?: number;\n}\n\n/**\n * Count a dropped publish: a bounded bus PubSub returns `false` when a publish\n * overflows (dropping strategy at capacity). A dropped hint only delays the\n * next pull (ADR-0009), so we tally it and move on.\n */\nconst countIfDropped = (published: boolean): Effect.Effect<void> =>\n published ? Effect.void : Metric.update(Telemetry.hintsDroppedTotal, 1);\n\n/** Subscribe to a PubSub and expose a `take`-only handle (shared by the bus and broker). */\nconst takeHandle = <A>(\n pubsub: PubSub.PubSub<A>\n): Effect.Effect<{ readonly take: Effect.Effect<A> }, never, Scope.Scope> =>\n PubSub.subscribe(pubsub).pipe(\n Effect.map((subscription) => ({ take: PubSub.take(subscription) }))\n );\n\n/**\n * Allocate a bounded, dropping PubSub (shut down with the scope) plus a\n * `publish` that tallies overflows — the backpressure primitive shared by the\n * in-process bus and the memory broker (#44).\n */\nconst droppingHub = <A>(\n capacity?: number\n): Effect.Effect<\n { readonly pubsub: PubSub.PubSub<A>; readonly publish: (value: A) => Effect.Effect<void> },\n never,\n Scope.Scope\n> =>\n Effect.gen(function* () {\n const pubsub = yield* Effect.acquireRelease(\n PubSub.dropping<A>({ capacity: capacity ?? DEFAULT_CAPACITY }),\n (hub) => PubSub.shutdown(hub)\n );\n return {\n pubsub,\n publish: (value) => PubSub.publish(pubsub, value).pipe(Effect.flatMap(countIfDropped)),\n };\n });\n\n/** A live subscription to the bus. */\nexport interface HintSubscription {\n /** The next hint batch; suspends until one arrives. */\n readonly take: Effect.Effect<ReadonlyArray<ChangeHint>>;\n}\n\n/**\n * The channel carrying committed-write hints from the backend to sync sessions; a missed hint\n * only delays the next pull.\n */\nexport interface InvalidationBus {\n readonly publish: (hints: ReadonlyArray<ChangeHint>) => Effect.Effect<void>;\n /**\n * Subscribe to hint batches. The subscription is established once the\n * effect completes, so a consumer can subscribe first and start its\n * processing loop later. Hints published afterwards are never missed, with\n * one exception: the Redis Streams broker may miss a publish that races\n * `subscribe` while Redis is unreachable.\n */\n readonly subscribe: Effect.Effect<HintSubscription, never, Scope.Scope>;\n}\n\n/** The {@link InvalidationBus} service the sync server and hint sources use. */\nexport const InvalidationBus = Context.Service<InvalidationBus>(\n \"@thomasfosterau/legation/InvalidationBus\"\n);\n\n/**\n * In-process bus over a bounded, dropping PubSub (#44).\n *\n * Delivery guarantee: the hub is bounded (`dropping` at `capacity`) so a bus\n * consumer that falls behind cannot make the publisher grow the queue without\n * limit. On overflow the newest hint batch is dropped and\n * `legation_hints_dropped_total` is incremented. Dropping a hint only delays\n * convergence — the next pull recovers the missed change (ADR-0009), so\n * correctness never depends on the bus. Capacity is configurable; the default\n * is generous ({@link DEFAULT_CAPACITY}).\n */\nexport const makeInProcessWith = (\n options?: BusCapacityOptions\n): Effect.Effect<InvalidationBus, never, Scope.Scope> =>\n Effect.gen(function* () {\n const hub = yield* droppingHub<ReadonlyArray<ChangeHint>>(options?.capacity);\n return InvalidationBus.of({\n publish: (hints) => (Arr.isReadonlyArrayEmpty(hints) ? Effect.void : hub.publish(hints)),\n subscribe: takeHandle(hub.pubsub),\n });\n });\n\n/** In-process bus with the default capacity. */\nexport const makeInProcess: Effect.Effect<InvalidationBus, never, Scope.Scope> =\n makeInProcessWith();\n\n/** A layer providing the in-process bus with the default capacity ({@link makeInProcess}). */\nexport const layerInProcess: Layer.Layer<InvalidationBus> =\n Layer.effect(InvalidationBus)(makeInProcess);\n\n/** In-process bus layer with a configurable capacity. */\nexport const layerInProcessWith = (options?: BusCapacityOptions): Layer.Layer<InvalidationBus> =>\n Layer.effect(InvalidationBus)(makeInProcessWith(options));\n\n// ─── Distributed adapters ────────────────────────────────────────────────────\n\n/**\n * A string pub/sub channel — the one primitive a distributed bus needs.\n * Every subscriber on the channel (across instances) sees every published\n * payload; the publisher's own subscriptions see it too, which is correct:\n * each instance fans the hint out to *its* local sessions.\n *\n * Concrete brokers (runtime packages or app code) implement this over a\n * Cloudflare Durable Object broadcast, Redis pub/sub, Postgres\n * LISTEN/NOTIFY, NATS, etc. — that is the entire distributed surface.\n */\nexport interface BusBroker {\n readonly publish: (payload: string) => Effect.Effect<void>;\n /**\n * Subscribe to the channel; established when the effect completes. While the\n * transport is unreachable, a publish that races this call may be missed (the\n * Redis Streams broker may miss one while Redis is unreachable).\n */\n readonly subscribe: Effect.Effect<{ readonly take: Effect.Effect<string> }, never, Scope.Scope>;\n}\n\n/**\n * Wire form of a change-hint batch: a JSON array of `{ collection, ids }`,\n * plus an optional `values` carrying the current row values of the PUTs (for\n * predicate-level fan-out matching). The field is optional for wire\n * compatibility: an old hint with no `values` decodes and behaves exactly as\n * before (a collection-level match).\n */\nconst HintsFromJson = Schema.fromJsonString(\n Schema.Array(\n Schema.Struct({\n collection: Schema.String,\n ids: Schema.Array(Schema.String),\n values: Schema.optional(\n Schema.Array(Schema.Struct({ id: Schema.String, value: Schema.Unknown }))\n ),\n })\n )\n);\n\n/**\n * Decode a channel payload to a hint batch. Correctness never depends on the\n * bus (ADR-0009), so malformed traffic fails the decode and the consumer\n * skips it (the next pull repairs any missed poke) rather than propagating.\n */\nconst decodeHints = Schema.decodeUnknownEffect(HintsFromJson);\n\n/** Options for {@link makeSerialized}. */\nexport interface SerializedBusOptions {\n /**\n * Bound on the broker's `publish`. A publish that exceeds it is logged and dropped, since a\n * lost poke only delays the next pull (ADR-0009). `publish` runs inside the sync server's\n * uninterruptible commit-and-publish region, so this bound is what keeps a hung broker from\n * holding that region open. Default 5 seconds.\n */\n readonly timeout?: Duration.Input | undefined;\n}\n\n/**\n * An InvalidationBus over a {@link BusBroker}: hints are JSON-serialized\n * onto the channel and decoded back on the other side. Correctness still\n * never depends on the bus (ADR-0009), so malformed payloads are skipped\n * rather than failed — the next pull repairs any missed poke, and a publish\n * that the broker does not finish within its `timeout` is logged and dropped.\n */\nexport const makeSerialized = (\n broker: BusBroker,\n options?: SerializedBusOptions\n): InvalidationBus => {\n const timeout = options?.timeout ?? \"5 seconds\";\n return InvalidationBus.of({\n publish: (hints) =>\n Arr.isReadonlyArrayEmpty(hints)\n ? Effect.void\n : broker.publish(JSON.stringify(hints)).pipe(\n Effect.timeoutOrElse({\n duration: timeout,\n orElse: () =>\n Effect.logWarning(\n \"InvalidationBus: broker publish timed out; dropped (the next pull recovers it)\"\n ),\n })\n ),\n subscribe: broker.subscribe.pipe(\n Effect.map((subscription) => {\n const take: Effect.Effect<ReadonlyArray<ChangeHint>> = subscription.take.pipe(\n Effect.flatMap((payload) => decodeHints(payload).pipe(Effect.catch(() => take)))\n );\n return { take };\n })\n ),\n });\n};\n\n/** Layer for a serialized bus over an in-context broker ({@link makeSerialized}). */\nexport const layerSerialized = (\n broker: BusBroker,\n options?: SerializedBusOptions\n): Layer.Layer<InvalidationBus> => Layer.succeed(InvalidationBus)(makeSerialized(broker, options));\n\n/**\n * An in-memory broker over a shared, bounded PubSub: every bus built on the\n * same broker exchanges hints, modelling several instances on one process. The\n * reference broker for tests and the executable shape a real broker mimics.\n *\n * Delivery guarantee (#44): bounded with a `dropping` strategy, matching the\n * in-process bus — a lagging subscriber cannot make a publisher grow the queue\n * without limit. An overflowing publish is dropped and counted in\n * `legation_hints_dropped_total`; the next pull repairs any missed hint\n * (ADR-0009). Capacity is configurable, defaulting to {@link DEFAULT_CAPACITY}.\n */\nexport const makeMemoryBrokerWith = (\n options?: BusCapacityOptions\n): Effect.Effect<BusBroker, never, Scope.Scope> =>\n Effect.gen(function* () {\n const hub = yield* droppingHub<string>(options?.capacity);\n return { publish: hub.publish, subscribe: takeHandle(hub.pubsub) };\n });\n\n/** In-memory broker with the default capacity. */\nexport const makeMemoryBroker: Effect.Effect<BusBroker, never, Scope.Scope> =\n makeMemoryBrokerWith();\n","/**\n * SyncServer\n *\n * The library-owned server orchestration (ADR-0009): authorizes\n * subscriptions (deny-by-default auth filters + middleware), delegates\n * mutator execution and subset evaluation to the app's Backend, performs\n * CVR bookkeeping and patch computation, and fans out pokes over the\n * InvalidationBus. Carriers (RpcTransport, HTTP routes, in-memory) bind the\n * resulting ServerHandler.\n *\n * Fan-out matching is predicate-aware: a change hint pokes a client group\n * only when some hinted change plausibly affects one of its subscriptions.\n * A value-carrying PUT matches against the subset predicate, a delete against\n * the group's last-synced CVR; value-less hints and `Exists` predicates fall\n * back to the collection-level match. Soundness first — over-matching is safe\n * (a redundant poke costs an empty pull), under-matching would delay\n * convergence, so anything a single row can't decide matches (ADR-0009).\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Clock from \"effect/Clock\";\nimport * as Duration from \"effect/Duration\";\nimport * as Effect from \"effect/Effect\";\nimport * as HashMap from \"effect/HashMap\";\nimport * as HashSet from \"effect/HashSet\";\nimport * as Layer from \"effect/Layer\";\nimport * as Metric from \"effect/Metric\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as Scope from \"effect/Scope\";\nimport { Backend, type ChangeHint, evaluateAll, type SyncContext } from \"./Backend.js\";\nimport {\n AuthPolicy,\n IdentityResolver,\n type SetBinder,\n SyncMiddleware,\n authorize,\n checkFilterable,\n passthroughMiddleware,\n} from \"./Authorization.js\";\nimport * as Cvr from \"./Cvr.js\";\nimport * as Hash from \"./Hash.js\";\nimport { InvalidationBus } from \"./InvalidationBus.js\";\nimport {\n AuthorizationError,\n BackendError,\n QueryError,\n StoreError,\n TransportError,\n VersionNotSupportedError,\n} from \"./Errors.js\";\nimport type {\n PatchOp,\n PullRequest,\n PullResponse,\n PushRequest,\n PushResponse,\n ReadRequest,\n ReadResponse,\n} from \"./Protocol.js\";\nimport * as Predicate from \"./Predicate.js\";\nimport * as Query from \"./Query.js\";\nimport * as Telemetry from \"./Telemetry.js\";\n// oxlint-disable-next-line effect/no-service-constructor-imports -- the poke hub is a private per-handler instance, not a service; exposing it as one would add a requirement to the public sync-server layers.\nimport { ServerHandler, makePokeHub } from \"./Transport.js\";\nimport type { Subset } from \"./Subset.js\";\nimport * as Subsets from \"./Subset.js\";\n\nconst asTransportError = (cause: { readonly message: string }): TransportError =>\n new TransportError({ message: cause.message, cause });\n\n// Whether two `lastMutationIds` watermarks name the same ids at the same values (#286).\nconst sameWatermark = (\n a: Readonly<Record<string, number>>,\n b: Readonly<Record<string, number>>\n): boolean =>\n Object.keys(a).length === Object.keys(b).length &&\n Object.keys(a).every((key) => a[key] === b[key]);\n\n/** One row a read returns: its collection beside the backend's `(id, version, value)`. */\nexport type ReadRow = ReadResponse[\"rows\"][number];\n\n/** What ADR-0025's read needs beside the request: the backend, the policy, and the middleware seam. */\nexport interface ReadDeps {\n readonly backend: Backend;\n readonly authPolicy: AuthPolicy;\n /** The interception seam; absent means passthrough. */\n readonly middleware?: SyncMiddleware;\n}\n\n/** A row's key across collections, for the read's row lookup. */\nconst rowKey = (collection: string, id: string): string => Hash.canonicalJson([collection, id]);\n\n/**\n * Evaluate already-authorized subsets to their current rows (#534): one\n * `Backend.evaluateAll` for the `(id, version)` sets, in subset order (a\n * bounded number of statements on a backend with `evaluateMany`), then one\n * `getRows` per collection over the union of its ids, as a pull's patch\n * assembly fetches. Each subset's rows come back in its **evaluated order**:\n * `getRows` promises nothing about order (a SQL `IN` returns whatever the engine\n * likes), and the order is the window's identity (ADR-0026). A row two subsets\n * share is returned once for each, as before.\n */\nconst evaluateRows = (\n backend: Backend,\n context: SyncContext,\n subsets: ReadonlyArray<Subset>\n): Effect.Effect<ReadonlyArray<ReadRow>, BackendError> =>\n Effect.gen(function* () {\n const evaluated = yield* evaluateAll(backend, context, subsets);\n const idsOf = (index: number): ReadonlyArray<string> =>\n (evaluated[index] ?? []).map((entry) => entry.id);\n const collections = Arr.dedupe(subsets.map((subset) => subset.collection));\n const fetched = yield* Effect.forEach(\n collections,\n (collection) =>\n backend\n .getRows(\n context,\n collection,\n Arr.dedupe(\n subsets.flatMap((subset, index) =>\n subset.collection === collection ? idsOf(index) : []\n )\n )\n )\n .pipe(Effect.map((rows) => [collection, rows] as const)),\n { concurrency: 1 }\n );\n const byKey = HashMap.fromIterable(\n fetched.flatMap(([collection, rows]) =>\n rows.map((row): readonly [string, ReadRow] => [\n rowKey(collection, row.id),\n { collection, ...row },\n ])\n )\n );\n return subsets.flatMap((subset, index) =>\n idsOf(index).flatMap((id) =>\n Option.toArray(HashMap.get(byKey, rowKey(subset.collection, id)))\n )\n );\n });\n\n/**\n * ADR-0025's read without its carrier: pull's front half, then\n * `Backend.evaluate` + `getRows`, and nothing else. The subsets are checked\n * against the filterable set as the client's own text (#154), handed to\n * `SyncMiddleware.onRead`, narrowed by the deny-by-default auth filters —\n * every subset before any is evaluated, so a denied subset anywhere in the\n * batch means no backend call at all — then each is evaluated to its\n * current rows in subset order, the evaluation batched through\n * `Backend.evaluateAll` and the values through one `getRows` per collection\n * (#534). No cookie, no CVR read or write, no\n * `lastMutationIds`. `handleRead` is this behind the protocol's identity\n * resolution; a derived REST handler is this behind an HTTP request's —\n * one read path, two carriers.\n */\nexport const readSubsets = (\n deps: ReadDeps,\n context: SyncContext,\n request: ReadRequest\n): Effect.Effect<ReadonlyArray<ReadRow>, AuthorizationError | BackendError> =>\n Effect.gen(function* () {\n yield* Effect.forEach(request.subsets, (subset) => checkFilterable(deps.authPolicy, subset), {\n discard: true,\n });\n const onRead = deps.middleware?.onRead;\n const checked = onRead === undefined ? request : yield* onRead(context, request);\n const authorized = yield* Effect.forEach(\n checked.subsets,\n (subset) => authorize(deps.authPolicy, context, subset, \"server\"),\n { concurrency: 1 }\n );\n return yield* evaluateRows(deps.backend, context, authorized);\n });\n\n/**\n * Server construction options (#48). Both default to today's behaviour: an\n * absent `acceptSchemaVersion` accepts every version, and an absent\n * `cookieNamespace` mints bare cookies.\n */\nexport interface SyncServerOptions {\n /**\n * Schema-version acceptor: decide whether a request's declared\n * `schemaVersion` (possibly `undefined` for an old client) is one this build\n * serves. Returning `false` makes `handlePush`/`handlePull` fail up front with\n * a {@link VersionNotSupportedError} — before applying mutations or computing a\n * patch — so an obsolete build is told to update and the journal is not\n * poisoned. Default: accept everything.\n */\n readonly acceptSchemaVersion?: (version: string | undefined) => boolean;\n /**\n * Fleet cookie-reset namespace (#48). Every cookie this server mints is\n * tagged with this namespace; a presented cookie carrying a *different*\n * namespace is treated as unknown, so its next pull degrades to a reset patch\n * (`Clear` + full puts, exactly as an unrecognised cookie does). Bumping this\n * value on deploy therefore forces every previously-issued cookie to reset in\n * one place — the runtime side of ADR-0014's schema-epoch bump. Default: `\"\"`\n * (bare cookies, today's format).\n */\n readonly cookieNamespace?: string;\n}\n\n/** Separator between a cookie's fleet namespace and its monotonic body. */\nconst COOKIE_NAMESPACE_SEP = \"::\";\n\n/** The fleet namespace a cookie was minted under (`\"\"` for a bare cookie). */\nconst cookieNamespaceOf = (cookie: string): string => {\n const index = cookie.indexOf(COOKIE_NAMESPACE_SEP);\n return index === -1 ? \"\" : cookie.slice(0, index);\n};\n\n/** Separator between a cookie's body and its scope epoch (#205). */\nconst COOKIE_EPOCH_SEP = \"~e\";\n/** A cookie's trailing scope epoch: the separator, then the hex `scopeEpochOf` mints. */\nconst COOKIE_EPOCH_PATTERN = /~e([0-9a-f]+)$/;\n\n/**\n * The scope epoch a cookie was minted under (#205; `\"\"` when the pull bound no\n * named set, the cookie format before #205).\n */\nconst cookieEpochOf = (cookie: string): string =>\n // Read only a trailing `~e<hex>`: a separator inside the fleet namespace must\n // not be taken for an epoch, or every pull without one would reset.\n COOKIE_EPOCH_PATTERN.exec(cookie)?.[1] ?? \"\";\n\n/**\n * A pull's scope epoch (ADR-0015's #205 amendment): a hash of the named sets it\n * bound, by name, with their members, so servers sharing a CVR store agree on\n * it, and it moves exactly when a bound set's members do. `\"\"` when the pull\n * bound no set: such a cookie carries no epoch.\n */\nconst scopeEpochOf = (bound: HashMap.HashMap<string, BoundSet>): string =>\n HashMap.isEmpty(bound)\n ? \"\"\n : Hash.contentHash(\n HashMap.toEntries(bound)\n .toSorted(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([name, values]) => [\n name,\n Option.match(values, {\n onNone: () => null,\n onSome: (members) =>\n [...members].map((member) => Hash.canonicalJson(member)).toSorted(),\n }),\n ])\n );\n\n/** A bound named set's members: `None` when its resolution failed (it narrows). */\ntype BoundSet = Option.Option<ReadonlyArray<Predicate.Literal>>;\n\n/** One session's cached named sets, by {@link setKey}. */\ntype SessionSets = HashMap.HashMap<string, CachedSet>;\n\n/** A cached named set's key: the collection whose scope declares it, and its name. */\nconst setKey = (collection: string, name: string): string => Hash.canonicalJson([collection, name]);\n\n/**\n * One session's cached resolution of a named set (#205): the members (`None`\n * when the resolver failed), when they were resolved, the collection a write to\n * which makes them stale, and whether one has.\n */\ninterface CachedSet {\n /** The identity the set was resolved for, canonically serialised. */\n readonly identity: string;\n readonly values: Option.Option<ReadonlyArray<Predicate.Literal>>;\n readonly resolvedAt: number;\n readonly maxAgeMillis: number;\n readonly source: string;\n readonly stale: boolean;\n}\n\n// ─── Fan-out matching ────────────────────────────────────────────────────────\n//\n// Correctness invariant (ADR-0009): over-matching is safe — a redundant poke\n// costs an empty pull — but under-matching would delay convergence (the next\n// interval pull still recovers it). So every rule below matches when a single\n// row can't decide the question.\n\n/** Whether a group's subsets touch any of the hinted collections (today's match). */\nconst collectionMatch = (touched: ReadonlySet<string>, subsets: ReadonlyArray<Subset>): boolean =>\n subsets.some((subset) => touched.has(subset.collection));\n\n/** Does any hinted PUT value satisfy some subset's predicate? */\nconst someValueMatches = (\n values: ReadonlyArray<{ readonly value: unknown }>,\n subsets: ReadonlyArray<Subset>\n): boolean => values.some(({ value }) => subsets.some((s) => Predicate.test(s.where, value)));\n\n/** Does the group's last-synced view hold a row this hint deletes? */\nconst someDeleteHeld = (\n hint: ChangeHint,\n putIds: ReadonlySet<string>,\n groupCvr: Cvr.Cvr | undefined\n): boolean => {\n const held = groupCvr?.rows.get(hint.collection);\n return held !== undefined && hint.ids.some((id) => !putIds.has(id) && held.has(id));\n};\n\n/**\n * Whether one hint plausibly affects some of a group's subsets on the hint's\n * collection. An `Exists` node is relational (a single row can't decide it) and\n * a value-less hint carries no row to test, so both fall back to a match; a\n * value-carrying PUT matches by predicate, a delete by the group's CVR.\n */\nconst hintAffects = (\n hint: ChangeHint,\n subsets: ReadonlyArray<Subset>,\n groupCvr: Cvr.Cvr | undefined\n): boolean => {\n if (subsets.some((s) => Predicate.hasExists(s.where))) return true;\n if (hint.values === undefined) return true;\n const putIds = new Set(hint.values.map((v) => v.id));\n return someValueMatches(hint.values, subsets) || someDeleteHeld(hint, putIds, groupCvr);\n};\n\n/**\n * Predicate-level match for a group: some hint on a collection the group\n * subscribes plausibly affects one of its subsets there.\n */\nconst predicateMatch = (\n hints: ReadonlyArray<ChangeHint>,\n subsets: ReadonlyArray<Subset>,\n groupCvr: Cvr.Cvr | undefined\n): boolean =>\n hints.some((hint) => {\n const onCollection = subsets.filter((s) => s.collection === hint.collection);\n return Arr.isReadonlyArrayNonEmpty(onCollection) && hintAffects(hint, onCollection, groupCvr);\n });\n\n// ─── Server introspection ─────────────────────────────────────────────────────\n\n/** One active client group as the server sees it: its authorised subsets and CVR size. */\nexport interface ServerGroup {\n readonly clientGroupId: string;\n /** The subsets authorised on the group's most recent pull. */\n readonly subsets: ReadonlyArray<Subset>;\n /** Rows tracked in the group's last-synced CVR, summed across collections. */\n readonly cvrSize: number;\n}\n\n/**\n * A read-only view of the sync server's live fan-out state (#45): the active\n * client groups with their authorised subsets and CVR sizes, plus poke\n * counters. Reads the handler's internal `activeSubsets`/`activeCvrs` Refs and\n * the `legation_*` poke metrics; does not change fan-out behaviour.\n */\nexport interface ServerIntrospection {\n /** Active client groups with their authorised subsets and CVR sizes. */\n readonly groups: Effect.Effect<ReadonlyArray<ServerGroup>>;\n /** Total pokes published by fan-out (cumulative counter snapshot). */\n readonly pokesPublished: Effect.Effect<number>;\n /** Total pokes suppressed by predicate matching (cumulative counter snapshot). */\n readonly pokesSuppressed: Effect.Effect<number>;\n}\n\n/** Rows a CVR holds, summed across its collections. */\nconst cvrSize = (cvr: Cvr.Cvr): number => {\n let total = 0;\n Arr.forEach(cvr.rows.values(), (rows) => {\n total += rows.size;\n });\n return total;\n};\n\n/** The handler paired with its introspection view. */\nexport interface ServerHandlerWithIntrospection {\n readonly handler: ServerHandler;\n readonly introspection: ServerIntrospection;\n}\n\n/** Build the ServerHandler together with its introspection view (with options, #48). */\nexport const makeWithIntrospectionWith = (\n options?: SyncServerOptions\n): Effect.Effect<\n ServerHandlerWithIntrospection,\n never,\n Backend | AuthPolicy | Cvr.CvrStore | InvalidationBus | Scope.Scope\n> =>\n Effect.gen(function* () {\n const acceptSchemaVersion = options?.acceptSchemaVersion ?? (() => true);\n const cookieNamespace = options?.cookieNamespace ?? \"\";\n // Reject an unsupported schema version up front, before any mutation is\n // applied or patch computed, so the journal is never poisoned (#48).\n const checkVersion = (\n version: string | undefined\n ): Effect.Effect<void, VersionNotSupportedError> =>\n acceptSchemaVersion(version)\n ? Effect.void\n : Effect.fail(\n new VersionNotSupportedError({\n schemaVersion: version,\n message: `Schema version ${version ?? \"(unset)\"} is not supported by this server`,\n })\n );\n const backend = yield* Backend;\n const authPolicy = yield* AuthPolicy;\n const cvrStore = yield* Cvr.CvrStore;\n const bus = yield* InvalidationBus;\n const middleware = (yield* Effect.serviceOption(SyncMiddleware)).pipe((option) =>\n option._tag === \"Some\" ? option.value : passthroughMiddleware\n );\n // Optional: resolve named-query subscriptions to subsets (Query.ts).\n const resolverOption = yield* Effect.serviceOption(Query.QueryResolver);\n // Optional: resolve the request's identity onto SyncContext.identity.\n const identityOption = yield* Effect.serviceOption(IdentityResolver);\n\n const contextFor = (clientGroupId: string): Effect.Effect<SyncContext, AuthorizationError> =>\n identityOption._tag === \"None\"\n ? Effect.succeed({ clientGroupId })\n : identityOption.value\n .resolve(clientGroupId)\n .pipe(Effect.map((identity) => ({ clientGroupId, identity })));\n\n const pokeHub = yield* makePokeHub;\n // Each session's named-set resolutions (#205), by client group, then by the\n // set's key: the collection whose scope declares it and its name, so two\n // collections that declare different sets under one name never share an\n // entry.\n const setCache = yield* Ref.make(HashMap.empty<string, SessionSets>());\n const sessionSetsOf = (all: HashMap.HashMap<string, SessionSets>, clientGroupId: string) =>\n Option.getOrElse(HashMap.get(all, clientGroupId), () => HashMap.empty<string, CachedSet>());\n // How many writes each source collection has seen (#205). A resolution that\n // overlaps a write to its source is cached as stale, so the write's hint,\n // which found no entry to mark while the resolution was in flight, is not\n // lost until the set's maxAge passes.\n const sourceWrites = yield* Ref.make(HashMap.empty<string, number>());\n const writesTo = (source: string) =>\n Effect.map(Ref.get(sourceWrites), (counts) =>\n Option.getOrElse(HashMap.get(counts, source), () => 0)\n );\n\n // Bind a named set for a pull, from the session's cache while it is fresh:\n // not marked stale by a write to its source, and younger than its maxAge.\n // Otherwise the set is resolved again and cached; a failed resolution binds\n // nothing (it narrows). Every set bound is recorded in `bound`, which the\n // pull's scope epoch is computed from.\n const cachedBinder =\n (bound: Ref.Ref<HashMap.HashMap<string, BoundSet>>): SetBinder =>\n (context, collection, name, set) =>\n Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const key = setKey(collection, name);\n // A session's cache holds one identity's resolutions. When the identity\n // behind the client group changes (a sign-out, another user), every\n // entry resolved for the previous one is dropped, never served.\n const identity = Hash.canonicalJson(context.identity ?? null);\n const sessionSets = sessionSetsOf(yield* Ref.get(setCache), context.clientGroupId);\n const sameIdentity = HashMap.every(sessionSets, (entry) => entry.identity === identity);\n const cached = sameIdentity\n ? Option.getOrUndefined(HashMap.get(sessionSets, key))\n : undefined;\n const fresh =\n cached !== undefined &&\n !cached.stale &&\n cached.source === set.source &&\n now - cached.resolvedAt < cached.maxAgeMillis;\n const writesBefore = yield* writesTo(set.source);\n const values = fresh ? cached.values : yield* set.resolve(context).pipe(Effect.option);\n if (!fresh) {\n // A write to the source landed while the set resolved: the members may\n // predate it. Cache them as stale, so the next pull resolves again,\n // and poke the session, whose windows do not yet lease the source.\n const overlapped = (yield* writesTo(set.source)) !== writesBefore;\n const entry: CachedSet = {\n identity,\n values,\n resolvedAt: now,\n maxAgeMillis: Duration.toMillis(set.maxAge),\n source: set.source,\n stale: overlapped,\n };\n yield* Ref.update(setCache, (all) => {\n const current = sessionSetsOf(all, context.clientGroupId);\n const kept = HashMap.every(current, (other) => other.identity === identity)\n ? current\n : HashMap.empty<string, CachedSet>();\n return HashMap.set(all, context.clientGroupId, HashMap.set(kept, key, entry));\n });\n if (overlapped) {\n yield* pokeHub.publish(context.clientGroupId, { reason: undefined });\n yield* Metric.update(Telemetry.pokesTotal, 1);\n }\n }\n yield* Ref.update(bound, HashMap.set(key, values));\n return values;\n });\n\n // Mark every cached set whose source a hint touched stale, and return the\n // client groups that held one, so they are poked (#205): their next pull\n // resolves the set again, and resets if its members moved.\n const staleSets = (touched: HashSet.HashSet<string>) =>\n Ref.modify(\n setCache,\n (all): readonly [HashSet.HashSet<string>, HashMap.HashMap<string, SessionSets>] => {\n const groups = HashSet.fromIterable(\n HashMap.keys(\n HashMap.filter(all, (sets) =>\n HashMap.some(sets, (cached) => HashSet.has(touched, cached.source))\n )\n )\n );\n const next = HashMap.map(all, (sets) =>\n HashMap.map(sets, (cached) =>\n HashSet.has(touched, cached.source) ? { ...cached, stale: true } : cached\n )\n );\n return [groups, HashSet.isEmpty(groups) ? all : next];\n }\n );\n // Active subscriptions per client group, for fan-out matching.\n const activeSubsets = yield* Ref.make(new Map<string, ReadonlyArray<Subset>>());\n // Each group's last-synced view (collection → id → version), for matching a\n // delete against the rows a group actually holds.\n const activeCvrs = yield* Ref.make(new Map<string, Cvr.Cvr>());\n\n // Monotonic cookie minting, scoped to this handler instead of a module\n // global. The Clock makes the timestamp injectable (TestClock in tests).\n const cookieCounter = yield* Ref.make(0);\n const freshCookie = Effect.gen(function* () {\n const now = yield* Clock.currentTimeMillis;\n const seq = yield* Ref.updateAndGet(cookieCounter, (n) => n + 1);\n const body = `cvr-${now}-${seq}`;\n // Tag the cookie with the fleet namespace so a later namespace bump makes\n // every pre-bump cookie unknown → a reset patch on its next pull (#48).\n return cookieNamespace === \"\" ? body : `${cookieNamespace}${COOKIE_NAMESPACE_SEP}${body}`;\n });\n\n // Fan-out loop: hints → poke each group some hinted change plausibly\n // affects. A group the collection-level match would poke but predicate\n // matching rules out is suppressed (counted, never dropped for\n // correctness). Poke-then-pull; correctness never depends on it.\n // Subscribing before `make` returns guarantees the loop sees every hint\n // published after construction, even ones racing the forked fiber's start.\n // The exception is a Redis Streams broker while Redis is unreachable, which\n // may miss a publish that races `subscribe`; a hint so missed only delays the\n // next pull.\n const hintSubscription = yield* bus.subscribe;\n yield* Effect.forkScoped(\n Effect.forever(\n hintSubscription.take.pipe(\n Effect.flatMap((hints) =>\n Effect.gen(function* () {\n const start = yield* Clock.currentTimeMillis;\n const touched = new Set(hints.map((hint) => hint.collection));\n const groups = yield* Ref.get(activeSubsets);\n const cvrs = yield* Ref.get(activeCvrs);\n // A write to a named set's source may move the set (#205): those\n // sessions are poked whatever their windows hold.\n const sources = HashSet.fromIterable(touched);\n yield* Ref.update(sourceWrites, (counts) =>\n HashSet.reduce(sources, counts, (next, collection) =>\n HashMap.set(\n next,\n collection,\n Option.getOrElse(HashMap.get(next, collection), () => 0) + 1\n )\n )\n );\n const scoped = yield* staleSets(sources);\n yield* Effect.forEach(\n groups,\n ([clientGroupId, subsets]) =>\n Effect.gen(function* () {\n if (HashSet.has(scoped, clientGroupId)) {\n yield* pokeHub.publish(clientGroupId, { reason: undefined });\n yield* Metric.update(Telemetry.pokesTotal, 1);\n return;\n }\n if (!collectionMatch(touched, subsets)) return;\n if (predicateMatch(hints, subsets, cvrs.get(clientGroupId))) {\n yield* pokeHub.publish(clientGroupId, { reason: undefined });\n yield* Metric.update(Telemetry.pokesTotal, 1);\n } else {\n yield* Metric.update(Telemetry.pokesSuppressedTotal, 1);\n }\n }),\n { concurrency: 1, discard: true }\n );\n yield* Metric.update(\n Telemetry.fanoutLatencyMs,\n (yield* Clock.currentTimeMillis) - start\n );\n })\n )\n )\n )\n );\n\n const handlePush = (\n request: PushRequest\n ): Effect.Effect<PushResponse, TransportError | VersionNotSupportedError> =>\n checkVersion(request.schemaVersion).pipe(\n Effect.andThen(\n Effect.gen(function* () {\n const context = yield* contextFor(request.clientGroupId);\n const checked = yield* middleware.onPush(context, request);\n // The commit and the fan-out of its hints are one uninterruptible\n // region (#356): an interrupt landing after the backend commits must\n // not skip the publish, because a replayed retry carries no hints and\n // would never repair the loss. The Backend contract cannot tell\n // \"committed\" from \"not yet\", so the whole applyMutations call is\n // protected. Trade-off: a slow applyMutations cannot be cancelled\n // mid-push; an interrupt waits for the commit and its publish. The\n // publish's broker I/O is uninterruptible too, but every broker call is\n // bounded, so a hung broker drops its poke instead of holding the region\n // open: the FanoutBus (its publish and lease registration), the Durable\n // Object shard calls (DurableFanoutBroker), the Redis broker's XADD, and\n // the publish of a custom BusBroker under makeSerialized each take a\n // `timeout` (default 5 seconds). Middleware\n // above stays interruptible, since nothing has been committed there.\n const result = yield* Effect.uninterruptible(\n backend\n .applyMutations(context, checked.mutations)\n .pipe(Effect.tap((applied) => bus.publish(applied.hints)))\n );\n return {\n lastMutationIds: result.lastMutationIds,\n ...(result.rejected !== undefined && Arr.isReadonlyArrayNonEmpty(result.rejected)\n ? { rejected: result.rejected }\n : {}),\n };\n }).pipe(Effect.mapError(asTransportError))\n ),\n Effect.withSpan(Telemetry.span.serverPush)\n );\n\n // Resolve a named subscription to a subset, or fail if no resolver is set.\n const resolveNamed = (\n context: SyncContext,\n named: { readonly name: string; readonly args: unknown }\n ) =>\n resolverOption._tag === \"None\"\n ? new TransportError({\n message: `No QueryResolver registered for named subscription \"${named.name}\"`,\n })\n : resolverOption.value.resolve(named.name, named.args, context);\n\n // The filterable set (#154) is checked against the client's OWN text —\n // the request as it arrived, before middleware may rewrite it — so what\n // a tenancy middleware ANDs in (a scoping key, an `Exists`) stays\n // server-authored, like the auth filter and a named query's resolution.\n const checkClientSubsets = (\n subsets: ReadonlyArray<Subset>\n ): Effect.Effect<void, AuthorizationError> =>\n Effect.forEach(subsets, (subset) => checkFilterable(authPolicy, subset), {\n discard: true,\n });\n\n // Authorize middleware-checked subsets and server-resolved named queries\n // alike: AND each with its collection's mandatory filter. Both are\n // server-authored by now (the client's text was checked above), so\n // `authorize` narrows without re-checking.\n const authorizeAll = (\n context: SyncContext,\n request: PullRequest,\n bindSet: SetBinder\n ): Effect.Effect<ReadonlyArray<Subset>, AuthorizationError | TransportError | QueryError> =>\n Effect.gen(function* () {\n const direct = yield* Effect.forEach(\n request.subscriptions,\n (subset) => authorize(authPolicy, context, subset, \"server\", bindSet),\n { concurrency: 1 }\n );\n const named = yield* Effect.forEach(\n request.namedSubscriptions ?? [],\n (entry) =>\n Effect.gen(function* () {\n return yield* authorize(\n authPolicy,\n context,\n yield* resolveNamed(context, entry),\n \"server\",\n bindSet\n );\n }),\n { concurrency: 1 }\n );\n return [...direct, ...named];\n });\n\n // Evaluate the desired next view: (collection → id → version) per subset.\n // The subsets go to the backend together (`Backend.evaluateAll`), so a\n // backend with `evaluateMany` answers the pull in a bounded number of\n // round trips (#505); one without it is asked per subset.\n const evaluateView = (context: SyncContext, subsets: ReadonlyArray<Subset>) =>\n Effect.gen(function* () {\n const evaluated = yield* evaluateAll(backend, context, subsets);\n const rows = new Map<string, Map<string, string | number>>();\n Arr.forEach(subsets, (subset, index) => {\n const collection = rows.get(subset.collection) ?? new Map<string, string | number>();\n Arr.forEach(evaluated[index] ?? [], (entry) => {\n collection.set(entry.id, entry.version);\n });\n rows.set(subset.collection, collection);\n });\n return { rows } satisfies Cvr.NextView;\n });\n\n // Assemble the patch from a CVR diff: a reset clear, then puts (rows fetched\n // per collection) then deletes.\n const assemblePatch = (context: SyncContext, difference: Cvr.CvrDiff, isReset: boolean) =>\n Effect.gen(function* () {\n const patch: Array<PatchOp> = isReset ? [{ _tag: \"Clear\" }] : [];\n const putsByCollection = new Map<string, Array<string>>();\n Arr.forEach(difference.puts, (put) => {\n putsByCollection.set(put.collection, [\n ...(putsByCollection.get(put.collection) ?? []),\n put.id,\n ]);\n });\n yield* Effect.forEach(\n putsByCollection,\n ([collection, ids]) =>\n Effect.gen(function* () {\n Arr.forEach(yield* backend.getRows(context, collection, ids), (row) => {\n patch.push({\n _tag: \"Put\",\n collection,\n id: row.id,\n version: row.version,\n value: row.value,\n });\n });\n }),\n { concurrency: 1, discard: true }\n );\n Arr.forEach(difference.dels, (del) => {\n patch.push({ _tag: \"Del\", collection: del.collection, id: del.id });\n });\n return patch;\n });\n\n // Resolve the CVR the presented cookie names. A cookie minted under a\n // different fleet namespace (a bumped deploy) is treated as unknown, so the\n // pull degrades to a reset patch exactly as an unrecognised cookie does (#48).\n // So is a cookie minted under another scope epoch (#205): its CVR was\n // computed under another scope, so no patch is computed against it, and a\n // narrowed scope can never leave a row behind on the client.\n const resolvePrevious = (\n cookie: string | undefined,\n epoch: string\n ): Effect.Effect<Cvr.Cvr | undefined, StoreError> => {\n if (cookie === undefined) return Effect.succeed(undefined);\n if (cookieNamespaceOf(cookie) !== cookieNamespace) return Effect.succeed(undefined);\n if (cookieEpochOf(cookie) !== epoch) return Effect.succeed(undefined);\n return cvrStore.get(cookie);\n };\n\n // How many passes a pull makes over its view before it stops retrying a\n // moving watermark (#286). A pass only repeats when a push committed during\n // it, so a bound of 3 is ample under normal load.\n const PULL_VIEW_ATTEMPTS = 3;\n\n // One pass over a pull's view: the watermark, the evaluated rows and the\n // patch, then the watermark again. `consistent` is true when the two\n // watermarks agree. Writes nothing: the CVR is recorded once, by the caller,\n // for the view it returns.\n const readPullOnce = (\n context: SyncContext,\n authorized: ReadonlyArray<Subset>,\n cookie: string | undefined,\n epoch: string\n ) =>\n Effect.gen(function* () {\n const before = yield* backend.lastMutationIds(context);\n const next = yield* evaluateView(context, authorized);\n const previous = yield* resolvePrevious(cookie, epoch);\n const isReset = cookie !== undefined && previous === undefined;\n const patch = yield* assemblePatch(context, Cvr.diff(previous ?? Cvr.empty, next), isReset);\n const after = yield* backend.lastMutationIds(context);\n return { next, patch, lastMutationIds: after, consistent: sameWatermark(before, after) };\n });\n\n // The pull's view as one snapshot (#286), for a backend that meets Backend\n // guarantee 1: a client's `lastMutationId` bumped in the same commit as its\n // effects. Then a watermark that reads the same before and after the rows\n // means no push committed in between: every push the watermark covers is in\n // the rows, and no push is in the rows without being covered. That is the\n // invariant the client's overlay relies on to release an acknowledged\n // mutation without a revert or a double application. A backend that exposes\n // effects before the bump (MemoryBackend today, #341; SqlBackend on D1, #342)\n // can still hand a pull an effect its watermark does not cover; this check\n // cannot see that window.\n //\n // A push that lands mid-read moves the watermark, so the view is read again,\n // up to PULL_VIEW_ATTEMPTS passes. Each pass costs a full evaluation (for\n // JsonApiBackend, an HTTP list per subset, plus its `getRows` cache refresh,\n // which is harmless because a pass evaluates before it fetches). If every\n // pass is disturbed, the last pass's watermark is returned, read after its\n // patch. It may then cover a push whose effects the patch lacks, which is a\n // transient revert until the next pull; it never covers less than the patch\n // carries, so it cannot double-apply.\n const readPullView = (\n context: SyncContext,\n authorized: ReadonlyArray<Subset>,\n cookie: string | undefined,\n epoch: string\n ) =>\n Effect.gen(function* () {\n // Read again while a push commits mid-read, up to PULL_VIEW_ATTEMPTS reads.\n const read = (\n attempt: number\n ): Effect.Effect<\n Effect.Success<ReturnType<typeof readPullOnce>>,\n Effect.Error<ReturnType<typeof readPullOnce>>\n > =>\n Effect.flatMap(readPullOnce(context, authorized, cookie, epoch), (view) =>\n view.consistent || attempt >= PULL_VIEW_ATTEMPTS\n ? Effect.succeed(view)\n : read(attempt + 1)\n );\n const view = yield* read(1);\n if (!view.consistent) {\n yield* Effect.logWarning(\n \"SyncServer.handlePull: a push committed on every view pass; returning the watermark read after the patch, so a client may briefly revert an acknowledged mutation\",\n { attempts: PULL_VIEW_ATTEMPTS, clientGroupId: context.clientGroupId }\n );\n }\n return view;\n });\n\n const handlePull = (\n request: PullRequest\n ): Effect.Effect<PullResponse, TransportError | VersionNotSupportedError> =>\n checkVersion(request.schemaVersion).pipe(\n Effect.andThen(\n Effect.gen(function* () {\n const context = yield* contextFor(request.clientGroupId);\n yield* checkClientSubsets(request.subscriptions);\n const checked = yield* middleware.onPull(context, request);\n\n // The named sets this pull binds (#205), for its scope epoch.\n const binding = yield* Ref.make(HashMap.empty<string, BoundSet>());\n const authorized = yield* authorizeAll(context, checked, cachedBinder(binding));\n const bound = yield* Ref.get(binding);\n const epoch = scopeEpochOf(bound);\n // The session holds a lease on each bound set's source as it does on\n // a window (ADR-0015's #205 amendment): the source's collection rides\n // with the group's windows, so a room's fan-out registration (from\n // introspection) leases its topic too.\n const sources = HashMap.toValues(\n HashMap.filter(\n sessionSetsOf(yield* Ref.get(setCache), request.clientGroupId),\n (_, key) => HashMap.has(bound, key)\n )\n ).map((cached) => cached.source);\n const leased = Arr.dedupe(sources).map((collection) => Subsets.make({ collection }));\n yield* Ref.update(activeSubsets, (m) =>\n new Map(m).set(request.clientGroupId, [...authorized, ...leased])\n );\n\n const { next, patch, lastMutationIds } = yield* readPullView(\n context,\n authorized,\n checked.cookie,\n epoch\n );\n\n // The permanent rejections this pull's watermark covers (#365). A\n // rejected id is bumped into the watermark, so the client must learn\n // its outcome here, or it would settle the mutation as applied. Each\n // rejection is committed with its id's bump, so it is covered once the\n // watermark reaches the id; the filter keeps the response to that view,\n // even when a push commits between the watermark read and this one.\n const rejected = (yield* backend.rejections(context)).filter(\n (entry) => entry.mutationId <= (lastMutationIds[entry.clientId] ?? 0)\n );\n\n const minted = yield* freshCookie;\n const cookie = epoch === \"\" ? minted : `${minted}${COOKIE_EPOCH_SEP}${epoch}`;\n yield* cvrStore.set(cookie, { rows: next.rows });\n // Track this group's latest view so fan-out can match a delete against\n // the rows the group actually holds (CVR-precise deletes).\n yield* Ref.update(activeCvrs, (m) =>\n new Map(m).set(request.clientGroupId, { rows: next.rows })\n );\n yield* Metric.update(Telemetry.patchOps, patch.length);\n yield* Metric.update(Telemetry.serverPullsTotal, 1);\n return {\n cookie,\n patch,\n lastMutationIds,\n ...(Arr.isReadonlyArrayNonEmpty(rejected) ? { rejected } : {}),\n };\n }).pipe(Effect.mapError(asTransportError))\n ),\n Effect.withSpan(Telemetry.span.serverPull)\n );\n\n // The fallthrough read (ADR-0025): identity, then `readSubsets` — pull's\n // front half (filterable check, middleware, deny-by-default auth), then\n // evaluate + fetch. No cookie, no CVR read or write, no lastMutationIds:\n // a read never perturbs sync state, so the worst it can be is stale\n // (pull stays the correctness path).\n const handleRead = (\n request: ReadRequest\n ): Effect.Effect<ReadResponse, TransportError | VersionNotSupportedError> =>\n checkVersion(request.schemaVersion).pipe(\n Effect.andThen(\n Effect.gen(function* () {\n const context = yield* contextFor(request.clientGroupId);\n const rows = yield* readSubsets({ backend, authPolicy, middleware }, context, request);\n return { rows };\n }).pipe(Effect.mapError(asTransportError))\n ),\n Effect.withSpan(Telemetry.span.serverRead)\n );\n\n const handler = ServerHandler.of({\n handlePush,\n handlePull,\n handleRead,\n pokes: (clientGroupId) => pokeHub.subscribe(clientGroupId),\n });\n\n const introspection: ServerIntrospection = {\n groups: Effect.gen(function* () {\n const subs = yield* Ref.get(activeSubsets);\n const cvrs = yield* Ref.get(activeCvrs);\n const result: Array<ServerGroup> = [];\n Arr.forEach(subs, ([clientGroupId, subsets]) => {\n const cvr = cvrs.get(clientGroupId);\n result.push({ clientGroupId, subsets, cvrSize: cvr === undefined ? 0 : cvrSize(cvr) });\n });\n return result;\n }),\n pokesPublished: Metric.value(Telemetry.pokesTotal).pipe(Effect.map((state) => state.count)),\n pokesSuppressed: Metric.value(Telemetry.pokesSuppressedTotal).pipe(\n Effect.map((state) => state.count)\n ),\n };\n\n return { handler, introspection };\n });\n\n/** Build the ServerHandler together with its introspection view (default options). */\nexport const makeWithIntrospection: Effect.Effect<\n ServerHandlerWithIntrospection,\n never,\n Backend | AuthPolicy | Cvr.CvrStore | InvalidationBus | Scope.Scope\n> = makeWithIntrospectionWith();\n\n/** Build the ServerHandler with options (#48: schema-version acceptor, fleet cookie namespace). */\nexport const makeWith = (\n options?: SyncServerOptions\n): Effect.Effect<\n ServerHandler,\n never,\n Backend | AuthPolicy | Cvr.CvrStore | InvalidationBus | Scope.Scope\n> => makeWithIntrospectionWith(options).pipe(Effect.map((built) => built.handler));\n\n/** Build the ServerHandler. */\nexport const make: Effect.Effect<\n ServerHandler,\n never,\n Backend | AuthPolicy | Cvr.CvrStore | InvalidationBus | Scope.Scope\n> = makeWith();\n\n/** Layer providing the ServerHandler from Backend + policy + CVR + bus (with options, #48). */\nexport const layerWith = (\n options?: SyncServerOptions\n): Layer.Layer<ServerHandler, never, Backend | AuthPolicy | Cvr.CvrStore | InvalidationBus> =>\n Layer.effect(ServerHandler)(makeWith(options));\n\n/** Layer providing the ServerHandler from Backend + policy + CVR + bus. */\nexport const layer: Layer.Layer<\n ServerHandler,\n never,\n Backend | AuthPolicy | Cvr.CvrStore | InvalidationBus\n> = layerWith();\n","/**\n * MemoryBackend\n *\n * The reference implementation of the Backend contract (ADR-0009): rows in\n * memory with a monotonic version counter, per-client lastMutationIds, and\n * app-supplied authoritative mutator handlers. Used in tests, demos, and\n * same-process sync rooms — and as the executable specification of the\n * contract's semantics (idempotent skip, gap rejection, atomic bump).\n *\n * Each mutation runs against a stage: its `put`/`del` writes are held in a\n * local overlay that its handler reads through, and nothing reaches the\n * committed rows until the handler returns. The staged writes and the\n * `lastMutationId` bump then commit in one state update, so a concurrent\n * `evaluate`, `getRows` or `lastMutationIds` sees both or neither. A\n * `BackendError` discards the stage and skips the bump.\n *\n * Concurrent `applyMutations` calls for one client group are safe (#346): the\n * commit re-checks the client's committed `lastMutationId`, so a copy of a\n * mutation that another call committed while its handler ran is dropped (its\n * stage discarded, reported as a replay skip), and the watermark only rises.\n *\n * Calls from different client groups are serialisable (#353). Every row a\n * handler reads from committed state is recorded with the version it had, and\n * the commit re-checks those versions inside the same state update that applies\n * the writes. A row another group changed since the read makes the commit\n * stale, so nothing is written and the handler runs again against the new\n * state. A counter read and incremented by two groups therefore loses no\n * increment. Reads of a handler's own staged writes are not recorded, since\n * those writes commit with the handler. A handler can run more than once, so\n * its effects outside the writer must be safe to repeat (see {@link BackendHandler}).\n * A handler still stale after a fixed number of runs fails with a transient\n * `BackendError` and writes nothing, so a hot row cannot loop it forever.\n *\n * Every copy reports the committed outcome (#355). A mutation committed as\n * permanently rejected is remembered with its reason, so a copy that loses the\n * race, or a later replay, lists it in `rejected` just as the copy that\n * committed it did. The client's outcome therefore does not depend on which\n * response arrives first. A remembered rejection is forgotten once the client's\n * next push starts past it (see {@link forgetRejectionsBelow}). The memory is\n * bounded per client: a client that never pushes again keeps its last push's\n * rejections. It assumes one journal per `clientId`, which backend contiguity\n * already requires.\n */\n\nimport * as Arr from \"effect/Array\";\nimport * as Effect from \"effect/Effect\";\nimport * as Layer from \"effect/Layer\";\nimport * as Option from \"effect/Option\";\nimport * as Ref from \"effect/Ref\";\nimport * as Schema from \"effect/Schema\";\nimport {\n Backend,\n buildChangeHints,\n transaction,\n withoutTransaction,\n type Commit,\n type Opened,\n type Outcome,\n type RejectedMutation,\n type SyncContext,\n} from \"./Backend.js\";\nimport { BackendError, MutationRejected } from \"./Errors.js\";\nimport type { Mutator } from \"./Mutator.js\";\nimport type { Mutation } from \"./Protocol.js\";\nimport * as Predicate from \"./Predicate.js\";\nimport * as RejectionMemory from \"./RejectionMemory.js\";\nimport * as Subset from \"./Subset.js\";\n\n/**\n * The write surface handed to authoritative mutator handlers. Writes become\n * visible to other readers only when the mutation commits; `get` sees the\n * handler's own earlier writes.\n */\nexport interface BackendWriter {\n readonly put: (collection: string, id: string, value: unknown) => Effect.Effect<void>;\n readonly del: (collection: string, id: string) => Effect.Effect<void>;\n readonly get: (collection: string, id: string) => Effect.Effect<unknown | undefined>;\n}\n\n/**\n * An authoritative mutator handler. Fail with `BackendError` for a transient\n * error (aborts the batch, client retries) or `MutationRejected` for a\n * permanent one (id bumped without effects; the mutation is skipped). A handler\n * may run more than once when a row it read changed before its commit (#353),\n * so anything it does outside the writer must be safe to repeat.\n */\nexport type BackendHandler = (\n args: unknown,\n writer: BackendWriter,\n context: SyncContext\n) => Effect.Effect<void, BackendError | MutationRejected>;\n\n/** A mutator definition paired with its typed authoritative handler. */\nexport interface HandlerEntry<Args> {\n readonly mutator: Mutator<string, Args, any>;\n readonly handle: (\n args: Args,\n writer: BackendWriter,\n context: SyncContext\n ) => Effect.Effect<void, BackendError | MutationRejected>;\n}\n\n/** Pair a mutator definition with its authoritative handler (typed). */\nexport const handler = <Args>(\n mutator: Mutator<string, Args, any>,\n handle: HandlerEntry<Args>[\"handle\"]\n): HandlerEntry<Args> => ({ mutator, handle });\n\n/**\n * Build the handler record from typed entries: pushed args are untrusted\n * input, so each handler schema-validates them (ADR-0008's \"named,\n * schema-validated intent\") before executing. Invalid args fail the push\n * with a BackendError.\n */\nexport const validatedHandlers = (\n entries: ReadonlyArray<HandlerEntry<any>>\n): Record<string, BackendHandler> =>\n Object.fromEntries(\n entries.map(({ handle, mutator }) => [\n mutator.name,\n ((args, writer, context) =>\n Schema.decodeUnknownEffect(mutator.args)(args).pipe(\n Effect.mapError(\n (cause) =>\n new BackendError({\n message: `Invalid args for mutator \"${mutator.name}\"`,\n cause,\n })\n ),\n Effect.flatMap((decoded) => handle(decoded, writer, context))\n )) satisfies BackendHandler,\n ])\n );\n\ninterface MemoryRow {\n readonly id: string;\n readonly version: number;\n readonly value: unknown;\n}\n\n/**\n * How many times one mutation's handler runs while a row it read keeps changing\n * before its commit (#353). A handler still stale after this many runs fails\n * with a transient `BackendError` instead of looping on a hot row.\n */\nconst MAX_HANDLER_ATTEMPTS = 16;\n\ninterface MemoryState {\n readonly rows: ReadonlyMap<string, ReadonlyMap<string, MemoryRow>>;\n readonly versionCounter: number;\n /** clientGroupId → clientId → last applied mutation id. */\n readonly lastMutationIds: ReadonlyMap<string, ReadonlyMap<string, number>>;\n /**\n * clientGroupId → clientId → mutationId → reason, for mutations committed as\n * permanently rejected and not yet forgotten (see {@link forgetRejectionsBelow}).\n */\n readonly rejections: ReadonlyMap<string, ReadonlyMap<string, ReadonlyMap<number, string>>>;\n}\n\nconst emptyState: MemoryState = {\n rows: new Map(),\n versionCounter: 0,\n lastMutationIds: new Map(),\n rejections: new Map(),\n};\n\n/** A write a handler made: a `put` of a value, or a `del`. */\ntype StagedWrite = { readonly _tag: \"put\"; readonly value: unknown } | { readonly _tag: \"del\" };\n\n/** One staged write, tagged with the row it targets. */\ninterface StagedEntry {\n readonly collection: string;\n readonly id: string;\n readonly write: StagedWrite;\n}\n\n/**\n * The committed rows a handler read: for each row, the version it had at the\n * first read (`undefined` when the row was absent). The commit re-checks them.\n */\ntype ReadSet = Map<string, Map<string, number | undefined>>;\n\n/**\n * A mutation's writes, not yet committed. `log` keeps them in handler order so\n * the commit assigns row versions exactly as an unstaged run would; `overlay`\n * keeps the latest write per row so the handler's reads see its own writes;\n * `reads` is what the handler saw in committed state (#353).\n */\ninterface Stage {\n readonly log: Array<StagedEntry>;\n readonly overlay: Map<string, Map<string, StagedWrite>>;\n readonly reads: ReadSet;\n}\n\n/** A fresh stage that records committed reads into `reads`. */\nconst newStage = (reads: ReadSet): Stage => ({ log: [], overlay: new Map(), reads });\n\nconst stageWrite = (stage: Stage, entry: StagedEntry): void => {\n stage.log.push(entry);\n const rowOverlay = stage.overlay.get(entry.collection) ?? new Map<string, StagedWrite>();\n rowOverlay.set(entry.id, entry.write);\n stage.overlay.set(entry.collection, rowOverlay);\n};\n\n/** Record the version a committed read saw; the first read of a row is the one checked. */\nconst recordRead = (\n stage: Stage,\n collection: string,\n id: string,\n version: number | undefined\n): void => {\n const rows = stage.reads.get(collection) ?? new Map<string, number | undefined>();\n if (!rows.has(id)) rows.set(id, version);\n stage.reads.set(collection, rows);\n};\n\n/**\n * Whether a row the handler read has changed since: its committed version is no\n * longer the one it read. Versions only ever rise, so a row written again never\n * matches an old version, even if it was deleted in between.\n */\nconst readsStale = (s: MemoryState, reads: ReadSet): boolean => {\n return [...reads].some(([collection, ids]) => {\n const rows = s.rows.get(collection);\n return [...ids].some(([id, seen]) => rows?.get(id)?.version !== seen);\n });\n};\n\n/** The client's committed `lastMutationId` in a group; 0 before its first mutation. */\nconst lastIdOf = (s: MemoryState, clientGroupId: string, clientId: string): number =>\n s.lastMutationIds.get(clientGroupId)?.get(clientId) ?? 0;\n\n/**\n * The state after one mutation commits: its `log` applied in order (each put\n * takes the next version) and the client's `lastMutationId` bumped. Pure, so\n * the caller can hand it to a single `Ref.modify`. The bump takes the max, so\n * the watermark never falls, even if a caller commits a lower id.\n */\nconst commitMutation = (\n s: MemoryState,\n context: SyncContext,\n mutation: Mutation,\n log: ReadonlyArray<StagedEntry>\n): MemoryState => {\n const working = new Map<string, Map<string, MemoryRow>>();\n let versionCounter = s.versionCounter;\n Arr.forEach(log, ({ collection, id, write }) => {\n const collectionRows =\n working.get(collection) ?? new Map<string, MemoryRow>(s.rows.get(collection) ?? []);\n working.set(collection, collectionRows);\n if (write._tag === \"put\") {\n versionCounter += 1;\n collectionRows.set(id, { id, version: versionCounter, value: write.value });\n } else {\n collectionRows.delete(id);\n }\n });\n const rows = new Map(s.rows);\n Arr.forEach(working, ([collection, collectionRows]) => {\n rows.set(collection, collectionRows);\n });\n const lastIds = new Map(s.lastMutationIds);\n const groupIds = new Map(lastIds.get(context.clientGroupId) ?? []);\n groupIds.set(\n mutation.clientId,\n Math.max(lastIdOf(s, context.clientGroupId, mutation.clientId), mutation.mutationId)\n );\n lastIds.set(context.clientGroupId, groupIds);\n return { ...s, rows, versionCounter, lastMutationIds: lastIds };\n};\n\n/** The reason a mutation was committed as rejected, while that rejection is remembered. */\nconst rejectionOf = (\n s: MemoryState,\n clientGroupId: string,\n clientId: string,\n mutationId: number\n): string | undefined => s.rejections.get(clientGroupId)?.get(clientId)?.get(mutationId);\n\n/** The state with a permanent rejection of one mutation remembered (#355). */\nconst withRejection = (\n s: MemoryState,\n clientGroupId: string,\n clientId: string,\n mutationId: number,\n reason: string\n): MemoryState => {\n const groups = new Map(s.rejections);\n const clients = new Map(groups.get(clientGroupId) ?? []);\n const ids = new Map(clients.get(clientId) ?? []);\n ids.set(mutationId, reason);\n clients.set(clientId, ids);\n groups.set(clientGroupId, clients);\n return { ...s, rejections: groups };\n};\n\n/**\n * Forget the rejections a client has moved past (#355). The rule, with its\n * floors, is {@link RejectionMemory.forgetBelow}.\n */\nconst forgetRejectionsBelow = (\n s: MemoryState,\n clientGroupId: string,\n floors: ReadonlyMap<string, number>\n): MemoryState => {\n const clients = s.rejections.get(clientGroupId);\n if (clients === undefined) return s;\n const kept = RejectionMemory.forgetBelow(clients, floors);\n if (kept === clients) return s;\n const groups = new Map(s.rejections);\n if (kept.size === 0) groups.delete(clientGroupId);\n else groups.set(clientGroupId, kept);\n return { ...s, rejections: groups };\n};\n\n/**\n * The pre-batch values of the rows a batch touched, from the snapshot taken\n * before it (`before`): what topic-derived fan-out derives moved-away topics\n * from (ADR-0023). A row absent before the batch has no old value.\n */\nconst oldValuesOf = (\n before: MemoryState,\n touched: ReadonlyMap<string, ReadonlySet<string>>\n): Map<string, Map<string, unknown>> =>\n new Map(\n [...touched].flatMap(([collection, ids]) => {\n const rows = before.rows.get(collection);\n const values = new Map(\n [...ids].flatMap((id) => {\n const row = rows?.get(id);\n return row === undefined ? [] : [[id, row.value] as const];\n })\n );\n return values.size === 0 ? [] : [[collection, values] as const];\n })\n );\n\n/**\n * Fold a committed stage into a batch's hint inputs: the ids it touched and\n * the values of its PUTs. A delete removes the id from the values, so it is\n * absent from what the hint emits, even when an earlier mutation of the same\n * batch put the row (#344): the hint describes the batch's final state, and a\n * row deleted later in the batch carries no value.\n */\nconst foldStage = (\n stage: Stage,\n touched: Map<string, Set<string>>,\n puts: Map<string, Map<string, unknown>>\n): void => {\n Arr.forEach(stage.overlay, ([collection, writes]) => {\n const ids = touched.get(collection) ?? new Set<string>();\n Arr.forEach(writes, ([id, write]) => {\n ids.add(id);\n const values = puts.get(collection) ?? new Map<string, unknown>();\n if (write._tag === \"put\") {\n values.set(id, write.value);\n } else {\n values.delete(id);\n }\n puts.set(collection, values);\n });\n touched.set(collection, ids);\n });\n};\n\n/** One opened mutation: the context it runs in, and the committed rows its handler reads (#353). */\ninterface MemoryUnit {\n readonly context: SyncContext;\n readonly mutation: Mutation;\n readonly reads: ReadSet;\n}\n\n/** A push's state: its context and the rows before it, for hint old values (ADR-0023). */\ninterface MemoryBatch {\n readonly context: SyncContext;\n readonly before: MemoryState;\n}\n\n/**\n * Build a memory backend with the given authoritative handlers. Its\n * `applyMutations` is {@link transaction} over the memory store's steps, so the\n * ledger rules (order, skip, gap, the bump with each outcome, reporting) are\n * the combinator's (#177).\n */\nexport const make = (handlers: Readonly<Record<string, BackendHandler>>): Effect.Effect<Backend> =>\n Effect.gen(function* () {\n const state = yield* Ref.make(emptyState);\n\n // The writer a handler sees. Writes land in the mutation's stage, not in\n // `state`, so nothing is visible before the mutation commits. Reads check\n // the stage first, so the handler sees its own writes.\n const stagingWriter = (stage: Stage): BackendWriter => ({\n put: (collection, id, value) =>\n Effect.sync(() => stageWrite(stage, { collection, id, write: { _tag: \"put\", value } })),\n del: (collection, id) =>\n Effect.sync(() => stageWrite(stage, { collection, id, write: { _tag: \"del\" } })),\n get: (collection, id) => {\n const staged = stage.overlay.get(collection)?.get(id);\n if (staged !== undefined) {\n return Effect.succeed(staged._tag === \"put\" ? staged.value : undefined);\n }\n return Ref.get(state).pipe(\n Effect.map((s) => {\n const row = s.rows.get(collection)?.get(id);\n recordRead(stage, collection, id, row?.version);\n return row?.value;\n })\n );\n },\n });\n\n // Commit one mutation's outcome and its bump in one state update, so\n // readers see both or neither. The client's committed watermark is\n // re-checked inside that update: a concurrent call may have committed this\n // mutation while its handler was running, and then this copy's outcome is\n // dropped (#346) and the committed one is reported instead (#355).\n //\n // The start-of-mutation gap rule needs no re-check here: `open` proved\n // `mutationId = watermark + 1`, and the watermark only rises, so the bound\n // still holds at commit.\n //\n // The reads the handler made are re-checked here too (#353), after the\n // replay check and before any write. A changed read means nothing commits\n // and the combinator runs the handler again. Because the check and the\n // write are one state update, no other group's commit can land between them.\n // A rejected outcome carries no stage, so none of its writes can commit.\n const commit = (unit: MemoryUnit, outcome: Outcome<Stage>): Effect.Effect<Commit> =>\n Ref.modify(state, (s): readonly [Commit, MemoryState] => {\n const { context, mutation } = unit;\n if (lastIdOf(s, context.clientGroupId, mutation.clientId) >= mutation.mutationId) {\n const rejection = rejectionOf(\n s,\n context.clientGroupId,\n mutation.clientId,\n mutation.mutationId\n );\n return [{ _tag: \"Replayed\", rejection: Option.fromUndefinedOr(rejection) }, s];\n }\n if (readsStale(s, unit.reads)) return [{ _tag: \"Conflicted\" }, s];\n const log = outcome._tag === \"Applied\" ? outcome.staged.log : [];\n const next = commitMutation(s, context, mutation, log);\n const committed =\n outcome._tag === \"Rejected\"\n ? withRejection(\n next,\n context.clientGroupId,\n mutation.clientId,\n mutation.mutationId,\n outcome.reason\n )\n : next;\n return [{ _tag: \"Committed\" }, committed];\n });\n\n // A handler runs against a fresh stage each time it is opened, so a run\n // after a conflict (#353) starts from the committed state it now reads.\n // A handler still stale after `transaction`'s attempt cap fails\n // transiently, like a serialization failure on PostgreSQL.\n const applyMutations = transaction<BackendHandler, MemoryBatch, MemoryUnit, Stage>({\n handlers,\n atomically: withoutTransaction,\n maxAttempts: MAX_HANDLER_ATTEMPTS,\n begin: (context, floors) =>\n // The rejections below this push's floors are ones each client has\n // already seen the outcome of (#355). The snapshot after forgetting is\n // the pre-batch state hints take old values from (ADR-0023).\n Ref.update(state, (s) => forgetRejectionsBelow(s, context.clientGroupId, floors)).pipe(\n Effect.andThen(Ref.get(state)),\n Effect.map((before) => ({ context, before }))\n ),\n open: ({ context }, mutation) =>\n Ref.get(state).pipe(\n Effect.map((s): Opened<MemoryUnit> => {\n const last = lastIdOf(s, context.clientGroupId, mutation.clientId);\n return mutation.mutationId === last + 1\n ? { _tag: \"Opened\", unit: { context, mutation, reads: new Map() } }\n : {\n _tag: \"Watermark\",\n lastMutationId: last,\n rejection: Option.fromUndefinedOr(\n rejectionOf(s, context.clientGroupId, mutation.clientId, mutation.mutationId)\n ),\n };\n })\n ),\n run: (unit, handle, mutation) => {\n const stage = newStage(unit.reads);\n return handle(mutation.args, stagingWriter(stage), unit.context).pipe(Effect.as(stage));\n },\n commit,\n // Opening moves nothing: the bump is part of the commit.\n release: () => Effect.void,\n finish: ({ context, before }, stages) =>\n Ref.get(state).pipe(\n Effect.map((final) => {\n const touched = new Map<string, Set<string>>();\n const puts = new Map<string, Map<string, unknown>>();\n Arr.forEach(stages, (stage) => foldStage(stage, touched, puts));\n return {\n lastMutationIds: Object.fromEntries(\n final.lastMutationIds.get(context.clientGroupId) ?? new Map()\n ),\n hints: buildChangeHints(touched, puts, oldValuesOf(before, touched)),\n };\n })\n ),\n });\n\n return Backend.of({\n applyMutations,\n lastMutationIds: (context) =>\n Ref.get(state).pipe(\n Effect.map((s) =>\n Object.fromEntries(s.lastMutationIds.get(context.clientGroupId) ?? new Map())\n )\n ),\n rejections: (context) =>\n Ref.get(state).pipe(\n Effect.map((s) =>\n [...(s.rejections.get(context.clientGroupId) ?? [])].flatMap(([clientId, ids]) =>\n [...ids].map(([mutationId, reason]): RejectedMutation => ({\n clientId,\n mutationId,\n reason,\n }))\n )\n )\n ),\n evaluate: (_context, subset) =>\n Effect.gen(function* () {\n const s = yield* Ref.get(state);\n const collectionValues = (collection: string) =>\n [...(s.rows.get(collection) ?? new Map<string, MemoryRow>()).values()].map(\n (r) => r.value\n );\n // Resolve correlated Exists nodes against in-memory storage.\n const where = yield* Predicate.resolveExists(subset.where, (node) =>\n Effect.succeed(Predicate.existsValues(node, collectionValues(node.collection)))\n );\n const rows = [...(s.rows.get(subset.collection) ?? new Map()).values()];\n return Subset.apply(rows, { ...subset, where }).map((row) => ({\n id: row.id,\n version: row.version,\n }));\n }),\n getRows: (_context, collection, ids) =>\n Ref.get(state).pipe(\n Effect.map((s) => {\n const collectionRows = s.rows.get(collection);\n const result: Array<{ id: string; version: number; value: unknown }> = [];\n Arr.forEach(ids, (id) => {\n const row = collectionRows?.get(id);\n if (row !== undefined) result.push(row);\n });\n return result;\n })\n ),\n });\n });\n\n/** Layer providing the memory backend. */\nexport const layer = (handlers: Readonly<Record<string, BackendHandler>>): Layer.Layer<Backend> =>\n Layer.effect(Backend)(make(handlers));\n"],"mappings":"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"}