{"version":3,"sources":["../src/store/claims/sites.ts","../src/store/claims/node-claims.ts","../src/store/claims/resolved-node-claims.ts","../src/store/embedding-sync.ts","../src/store/fulltext-sync.ts","../src/store/operations/node-write-pipeline.ts"],"names":["disjointnessClaimAxis","DISJOINT_CONSTRAINT_NAME","uniquenessClaimTarget","checkWherePredicate","computeUniqueKey","UniquenessError","DisjointError","constraintFenceRefusal","uniquenessProbeKinds","encodeTupleKey","isSameClaimOwner","compareClaimTargets","bindExtraIfReachable","UNIQUE_SIDECAR_BATCH","requireDefined","ConfigurationError","missingRequiredExtras","claimOwnerKey","resolveEmbeddingFields","readOwnProperty","UnsupportedBackendCapabilityError","DEFAULT_SEARCHABLE_LANGUAGE","getSearchableFields","resolveBackendFulltext","RestrictedDeleteError","purgeEdgeClaims","rowPropsToObject","assertsStoredLowerBound","canonicalEqual","validateNodeProps","ValidationError"],"mappings":"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","file":"chunk-VNJMM2QQ.cjs","sourcesContent":["/**\n * What claims a node of a given kind owes, before its props are known.\n *\n * This is the DECLARATION-level half of the claim set, and it is deliberately\n * separate from the props-level half: the same list answers \"which claim rows\n * does this kind write?\" (the entries, once a row's props select the applying\n * constraints and supply their keys) and \"does a write of this kind need the\n * per-graph lock?\" (the projection in `../constraints.ts`). Two consumers, one\n * classification — a second spelling at either of them is what this module\n * exists to prevent.\n *\n * It imports registry, core types and the axis vocabulary only, so the\n * constraint probes can project it without importing the claim seam.\n */\nimport { type UniqueConstraint } from \"../../core/types\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport {\n  DISJOINT_CONSTRAINT_NAME,\n  disjointnessClaimAxis,\n  uniquenessClaimTarget,\n} from \"./axis\";\nimport { type ConstraintFenceReason } from \"./backing\";\n\n/**\n * WHEN a claim is issued relative to the row write it gates.\n *\n * `\"pre-insert\"` means the claim is the ONLY fence for a violation the row\n * write itself would not surface, so it must precede the row — and a failure\n * between the two leaves a live claim with no row, which is why it is also the\n * subject of the non-transactional refusal. `\"post-insert\"` means the claim\n * follows the row, which is the order those entries ship in today and the order\n * their own primary key already makes sufficient.\n */\nexport type ClaimPlacement = \"pre-insert\" | \"post-insert\";\n\n/**\n * WHICH declared refusal a foreign owner of this claim produces, and the\n * payload that refusal needs.\n *\n * Two constraint families share one claim relation, so the row alone cannot say\n * what refusing it means. Carrying the answer on the site — decided where the\n * site is decided — is what lets the claim seam re-raise the family's own error\n * without re-deriving which family it was from the axis string.\n */\nexport type ClaimRefusal =\n  | Readonly<{ kind: \"uniqueness\"; constraint: UniqueConstraint }>\n  | Readonly<{ kind: \"disjointness\"; ownKind: string; otherKind: string }>;\n\n/** One claim a node of this kind owes, before its props are known. */\nexport type NodeClaimSite = Readonly<{\n  /** The value the claim row's `node_kind` carries — what the PK fences on. */\n  axis: string;\n  /** The claim row's `constraint_name`. */\n  constraintName: string;\n  /**\n   * Whether this site is ALSO a reason to take the per-graph write lock — i.e.\n   * whether its probe reads state the uniques primary key does not already\n   * fence. True for a scope spanning more than the node's own kind; false for a\n   * single-kind scope, whose own key IS the fence.\n   */\n  needsLockFence: boolean;\n  /**\n   * WHEN this site's claim must be issued relative to the row write it gates,\n   * for the operation this list was built for. It is DATA, not a caller's\n   * choice: the claim seam partitions on it, and the non-transactional refusal\n   * asks whether a write owes a `pre-insert` entry.\n   */\n  placement: ClaimPlacement;\n  /**\n   * The class a REFUSAL names when this site's claim cannot be undone. A scope\n   * spanning more than the node's own kind is `nodeUniquenessScope` — the class\n   * the lock path already reports for it; a single-kind scope is\n   * `nodeUniquenessClaim`, whose advice is about the reservation row rather\n   * than about the scope it does not have.\n   */\n  refusalReason: ConstraintFenceReason;\n  /** Which typed error a foreign owner of this claim produces. */\n  refusal: ClaimRefusal;\n}>;\n\n/**\n * The disjointness sites a write BRINGING A NODE INTO EXISTENCE under this kind\n * owes: one per declared partner.\n *\n * `\"create\"` and `\"resurrect\"` only, matching the two places a node comes into\n * existence under a kind — never `\"update\"`, because an in-place update cannot\n * change a node's kind and so re-derives no cross-kind verdict and owes no\n * claim for one. A resurrect owes exactly what a create owes here: reviving a\n * tombstone re-introduces the same live id under the same kind that a fresh\n * insert would, and {@link file://./node-claims.ts deleteUniquenessEntries}\n * released this node's own disjointness reservations at soft-delete time (it\n * reads the `\"create\"` extent precisely because it is the wider of the two), so\n * a resurrect starts from the same \"holds nothing yet\" state a create does and\n * must re-claim from scratch rather than diff.\n *\n * Pairwise rather than per component, because the registry's disjoint pairs are\n * literal unordered pairs: a node disjoint from two partners owes two claims,\n * on two axes, and the two partners are not thereby disjoint from each other.\n *\n * Every one of them is `pre-insert` and `needsLockFence`: the nodes primary key\n * is `(graph_id, kind, id)`, so a disjoint namesake's row does not collide with\n * this node's own insert — the claim is the ONLY fence for the axis, and a\n * fence issued after the write it fences is not a fence. `needsLockFence` is\n * read only by the lock projection (`nodeWriteNeedsConstraintFence`, consulted\n * with `\"create\"` or `\"update\"` alone — never `\"resurrect\"`), so it stays inert\n * for a resurrect: the per-graph lock's trigger set is unchanged by this site\n * applying to a third operation, and the claim's own primary key — the same\n * `INSERT … ON CONFLICT … RETURNING` `insertUnique` already uses for an\n * own-kind uniqueness claim, which needs no lock either — is what fences a\n * resurrect racing a disjoint partner's create.\n */\nfunction disjointnessSites(\n  registry: KindRegistry,\n  kind: string,\n): readonly NodeClaimSite[] {\n  return registry.getDisjointKinds(kind).map((otherKind) => ({\n    axis: disjointnessClaimAxis(kind, otherKind, registry),\n    constraintName: DISJOINT_CONSTRAINT_NAME,\n    needsLockFence: true,\n    placement: \"pre-insert\" as const,\n    refusalReason: \"nodeDisjointness\" as const,\n    refusal: { kind: \"disjointness\" as const, ownKind: kind, otherKind },\n  }));\n}\n\n/**\n * The three shapes a node write can take, for claim purposes.\n *\n * `\"create\"` is a fresh id under a kind that has never held it live.\n * `\"update\"` is an in-place change to a row that stays live throughout — it\n * cannot change the node's kind, so it never owes a disjointness claim.\n * `\"resurrect\"` is a tombstoned row coming back to life under its own kind —\n * the SAME cross-kind event a create is, reached through the transition seam\n * instead of the insert seam, which is why its uniqueness claims are placed\n * like an update's (claim-first, {@link file://./node-claims.ts\n * withNodeClaimTransition} is the only correct sequence for a transition) while\n * its disjointness claims are owed like a create's.\n *\n * Two consumers read this vocabulary and each other's classification would be\n * the wrong one to reuse: {@link nodeClaimEntries} (what a ROW owes, given its\n * operation) reaches `\"resurrect\"`; `nodeWriteNeedsConstraintFence` (the lock\n * projection, `../constraints.ts`) and its callers reach only `\"create\"` and\n * `\"update\"`, by design — see {@link disjointnessSites}'s note on why that\n * keeps the per-graph lock's trigger set unchanged.\n */\nexport type NodeClaimOperation = \"create\" | \"update\" | \"resurrect\";\n\n/**\n * THE owner of \"what claims does a node of this kind owe, and when is each\n * due?\".\n *\n * Two families, one list. Disjointness sites come first, so a kind qualifying\n * on both counts reports the class the lock path already reports for it, and so\n * the two families cannot be maintained by two different sets of write paths: a\n * path that remembers uniqueness cannot forget disjointness when both arrive\n * through the same list.\n *\n * Every uniqueness field but `constraintName` is derived from ONE computation —\n * the {@link uniquenessClaimTarget} of this kind and scope — so the four readers\n * of this list (the entries, the claim seam's partition, the non-transactional\n * refusal, and the lock projection in `../constraints.ts`) read one\n * classification rather than four predicates that agree until one is edited.\n * The fact all of them turn on is the same one: does this claim's axis span\n * kinds beyond the writer's own? Disjointness always does; a uniqueness scope\n * does exactly when it covers more than the node's own kind.\n *\n * - `needsLockFence` reads it as \"the probe reads state the uniques primary key\n *   does not fence\", which is what the per-graph lock is taken for;\n * - `placement` reads it as \"the claim is the only fence for this axis, so it\n *   must precede the row it gates\". On the CREATE path an own-kind claim keeps\n *   its shipped position after the row: the uniques primary key at that axis is\n *   already the complete fence for it, so moving it would buy no fence and cost\n *   a refusal on backends with no transactions. On the UPDATE and RESURRECT\n *   paths every claim is pre-insert, because the transition seam claims before\n *   its gated write for every scope — see `withNodeClaimTransition`, which\n *   explains why that is the only correct sequence for a transition.\n *\n * A future claim family that breaks the coincidence between those two readings\n * must say WHICH it changes; that is why they are two named fields and not one.\n */\nexport function nodeClaimSites(\n  registry: KindRegistry,\n  kind: string,\n  uniqueConstraints: readonly UniqueConstraint[],\n  operation: NodeClaimOperation,\n): readonly NodeClaimSite[] {\n  const uniqueness = uniqueConstraints.map((constraint) => {\n    const target = uniquenessClaimTarget(kind, constraint.scope, registry);\n    return {\n      axis: target.axis,\n      constraintName: constraint.name,\n      needsLockFence: target.crossKind,\n      placement:\n        operation !== \"create\" || target.crossKind ?\n          \"pre-insert\"\n        : (\"post-insert\" as const),\n      refusalReason:\n        target.crossKind ?\n          (\"nodeUniquenessScope\" as const)\n        : (\"nodeUniquenessClaim\" as const),\n      refusal: { kind: \"uniqueness\" as const, constraint },\n    } satisfies NodeClaimSite;\n  });\n\n  return operation === \"update\" ? uniqueness : (\n      [...disjointnessSites(registry, kind), ...uniqueness]\n    );\n}\n","/**\n * Node claims — what a node row reserves, and how each reservation moves.\n *\n * A declared constraint is a CLAIM on an axis (see {@link file://./axis.ts}):\n * the write reserves the row `(graph_id, axis, constraint_name, key)` and is\n * refused when that reservation comes back owned by somebody else. This module\n * decides which claims a row owes, probes them, writes them, releases them, and\n * sequences each of those against the primary row write it gates.\n *\n * Two families reserve in that one relation — a uniqueness constraint at its\n * scope's axis, and a `disjointWith` pair at the pair's axis with the node's id\n * as the key — so every path that already maintained uniqueness reservations\n * maintains disjointness reservations too, by reading one list rather than by\n * being edited twice.\n */\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport {\n  type BundleVerdictOf,\n  type ClaimsVerdictThunk,\n} from \"../../backend/capabilities/resolve\";\nimport {\n  type GraphBackend,\n  type InsertUniqueParams,\n  type NodeInsertClaim,\n  type TransactionBackend,\n  type UniqueConstraintBackend,\n  type UniqueRow,\n} from \"../../backend/types\";\nimport { checkWherePredicate, computeUniqueKey } from \"../../constraints\";\nimport { type UniqueConstraint } from \"../../core/types\";\nimport {\n  type ConfigurationError,\n  DisjointError,\n  UniquenessError,\n} from \"../../errors\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { requireDefined } from \"../../utils/presence\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport { constraintFenceRefusal } from \"../operations/write-transaction\";\nimport { type GraphWriteLock } from \"../recorded-capture/clock\";\nimport {\n  type ClaimOwner,\n  type ClaimTarget,\n  compareClaimTargets,\n  isSameClaimOwner,\n  uniquenessProbeKinds,\n} from \"./axis\";\nimport { type ConstraintFenceReason } from \"./backing\";\nimport {\n  type ClaimPlacement,\n  type ClaimRefusal,\n  type NodeClaimOperation,\n  nodeClaimSites,\n} from \"./sites\";\n\n/**\n * Context for node claim operations.\n */\nexport type UniquenessContext = Readonly<{\n  graphId: string;\n  registry: KindRegistry;\n  backend: GraphBackend | TransactionBackend;\n  /** The threaded `uniqueSidecarBatch` verdict — never re-resolved here. */\n  uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}>;\n\n/**\n * Context for the claim PROBE, whose single backend member is the read.\n *\n * Stated separately because the probe runs on handles that cannot write: a\n * write frame's row work holds the read-only `WriteTarget`, and pre-checking a\n * key there is the whole point of the probe. Every {@link UniquenessContext}\n * satisfies this one, so a writer passes its own context unchanged.\n */\nexport type UniquenessProbeContext = Readonly<{\n  graphId: string;\n  registry: KindRegistry;\n  backend: Pick<UniqueConstraintBackend, \"checkUnique\">;\n}>;\n\n/**\n * Builds a claim context — the one constructor every call site shares.\n *\n * Generic in the handle so it yields exactly what it was given: a full backend\n * produces a {@link UniquenessContext} that can also write the claim rows, and\n * a read-only projection produces a {@link UniquenessProbeContext}, which is\n * all the probe needs and all row work can offer.\n */\nexport function createUniquenessContext<\n  T extends Pick<UniqueConstraintBackend, \"checkUnique\">,\n>(\n  graphId: string,\n  registry: KindRegistry,\n  backend: T,\n  uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>,\n): Readonly<{\n  graphId: string;\n  registry: KindRegistry;\n  backend: T;\n  uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}> {\n  return { graphId, registry, backend, uniqueSidecarBatch };\n}\n\n/** One claim a node row owes, decided but not written. */\nexport type NodeClaimEntry = Readonly<{\n  /** `uniques.node_kind` — the axis the primary key fences on. */\n  axis: string;\n  /** `uniques.constraint_name`. */\n  constraintName: string;\n  /** `uniques.key`. */\n  key: string;\n  /**\n   * WHEN this claim is issued relative to the row write it gates — carried\n   * through from the entry's {@link NodeClaimSite}, which is the one owner of\n   * the decision. The claim seam issues the two groups on either side of its\n   * gated write, and {@link claimFenceRefusal} is keyed on the pre-insert group\n   * alone.\n   */\n  placement: ClaimPlacement;\n  /**\n   * The class a refusal names when this claim cannot be rolled back — carried\n   * through from the site, so no consumer re-derives it.\n   */\n  refusalReason: ConstraintFenceReason;\n  /** Which typed error a foreign owner produces — carried through from the site. */\n  refusal: ClaimRefusal;\n}>;\n\n/**\n * The key one site reserves for THIS row, or `undefined` when the site does not\n * apply to it.\n *\n * A uniqueness site applies when its `where` predicate holds, and its key is\n * the constraint's own composite key. A disjointness site always applies, and\n * its key is the node's ID — which is the axis `disjointWith` declares: \"no two\n * live nodes of these two kinds share an id\" is a reservation on the id, taken\n * at the pair.\n */\nfunction claimKeyFor(\n  refusal: ClaimRefusal,\n  id: string,\n  props: Record<string, unknown>,\n): string | undefined {\n  if (refusal.kind === \"disjointness\") return id;\n  return checkWherePredicate(refusal.constraint, props) ?\n      computeUniqueKey(\n        props,\n        refusal.constraint.fields,\n        refusal.constraint.collation,\n      )\n    : undefined;\n}\n\n/**\n * THE single owner of \"what claims does THIS ROW owe, and when is each due?\":\n * the kind's claim sites ({@link nodeClaimSites}, the declaration-level extent\n * for this operation) filtered to the ones that apply to this row and completed\n * with each one's key. `placement`, `refusalReason` and `refusal` are carried\n * through unchanged; this function decides none of them.\n *\n * Every path that maintains a node's reservations — create, update diff,\n * resurrect, delete, batch, import — reads its work from this one list, so no\n * path can compute a key one way and an axis another, and no path that\n * remembers one family can forget the other.\n *\n * `operation` is threaded rather than assumed because the sites function needs\n * it twice: to place each claim (a transition claims before the row it gates for\n * every scope, while a create only does so for an axis spanning kinds beyond its\n * own) and to decide the disjointness arm, which only a write bringing a node\n * into existence under a kind owes — `\"create\"` and `\"resurrect\"` alike, never\n * `\"update\"`.\n */\nexport function nodeClaimEntries(\n  registry: KindRegistry,\n  kind: string,\n  id: string,\n  props: Record<string, unknown>,\n  constraints: readonly UniqueConstraint[],\n  operation: NodeClaimOperation,\n): readonly NodeClaimEntry[] {\n  return nodeClaimSites(registry, kind, constraints, operation).flatMap(\n    (site) => {\n      const key = claimKeyFor(site.refusal, id, props);\n      return key === undefined ?\n          []\n        : [\n            {\n              axis: site.axis,\n              constraintName: site.constraintName,\n              key,\n              placement: site.placement,\n              refusalReason: site.refusalReason,\n              refusal: site.refusal,\n            },\n          ];\n    },\n  );\n}\n\n/** An entry whose family is disjointness — the one family that needs mapping. */\ntype DisjointnessClaimEntry = NodeClaimEntry &\n  Readonly<{ refusal: Extract<ClaimRefusal, { kind: \"disjointness\" }> }>;\n\n/**\n * THE one place a backend claim refusal becomes the refusal its FAMILY\n * declares.\n *\n * Both families reserve in the `uniques` relation, and `insertUnique` /\n * `insertUniqueBatch` report every foreign owner the same way — as a\n * `UniquenessError` naming the constraint, the holder's concrete kind and the\n * two ids. That contract is deliberately unchanged (a third-party backend\n * implementing it keeps working), so the translation happens here, once, where\n * the entries that produced the claim are still in hand.\n *\n * The reserved `constraintName` alone locates the FAMILY (any entry it matches\n * is a disjointness entry, never a declared constraint's — `assertClaimAxisSafe`\n * makes the name unspellable by one), but not the PAIR: every `disjointWith`\n * pair shares that one literal, so a batch carrying disjointness entries for\n * two different pairs that happen to claim the same id (`Person \"X\"` disjoint\n * with `Company`, `Vehicle \"X\"` disjoint with `Boat`, same batch) would match\n * either indiscriminately on `(constraintName, key)` alone. The entry is\n * additionally required to have written the SAME claim axis the backend\n * reports — the row's actual primary key, and therefore unambiguous — so the\n * one located is provably the one that lost. `error.details.axis` is optional\n * (a third-party backend need not carry it to keep working); when a backend\n * omits it the match falls back to `(constraintName, key)` alone, which is\n * HEAD's behavior and no worse than today's. The payload is built from what\n * the BACKEND reported — the holder's own concrete kind — so the fence's error\n * is identical to the probe's, which is what makes a caller unable to tell\n * which layer refused.\n */\nfunction mapClaimRefusal(\n  error: UniquenessError,\n  entries: readonly NodeClaimEntry[],\n  verdicts: readonly NodeCreateClaimVerdict[] = [],\n): never {\n  const verdict = verdicts.find(\n    (candidate) =>\n      candidate.claim.constraintName === error.details.constraintName &&\n      (candidate.refusal.kind === \"uniqueness\" ||\n        candidate.claim.key === error.details.newId) &&\n      (error.details.axis === undefined ||\n        candidate.claim.axis === error.details.axis ||\n        (candidate.claim.verdict.kind === \"uniqueness\" &&\n          candidate.claim.verdict.probeAxes.includes(error.details.axis))),\n  );\n  const uniquenessVerdict =\n    verdict !== undefined && isNodeCreateUniquenessVerdict(verdict) ?\n      verdict\n    : undefined;\n  if (uniquenessVerdict !== undefined && error.details.fields.length === 0) {\n    throw new UniquenessError(\n      {\n        ...error.details,\n        fields: uniquenessVerdict.refusal.constraint.fields,\n      },\n      { cause: error },\n    );\n  }\n  const owed = entries.find(\n    (entry): entry is DisjointnessClaimEntry =>\n      entry.refusal.kind === \"disjointness\" &&\n      entry.constraintName === error.details.constraintName &&\n      entry.key === error.details.newId &&\n      (error.details.axis === undefined || entry.axis === error.details.axis),\n  );\n  if (owed === undefined) throw error;\n  throw new DisjointError(\n    {\n      nodeId: error.details.newId,\n      attemptedKind: owed.refusal.ownKind,\n      conflictingKind: error.details.kind,\n    },\n    { cause: error },\n  );\n}\n\n/** Re-raises a planned claim failure through the claim family's typed error. */\nexport function refuseNodeCreateClaimError(\n  error: unknown,\n  plan: NodeCreateClaimPlan,\n): never {\n  if (error instanceof UniquenessError) {\n    mapClaimRefusal(error, plan.entries, plan.verdicts);\n  }\n  throw error;\n}\n\n/**\n * Runs a claim statement, re-raising a foreign owner as the declared refusal of\n * whichever family owed the claim.\n *\n * One wrapper around every claim write, rather than a translation at each of\n * them: a claim statement that skipped it would report a `disjointWith`\n * violation as a uniqueness violation on a constraint name no caller ever\n * declared. Both the CREATE seam's `withNodeCreateClaimsIssuedBy` and the\n * transition seam's {@link claimUniqueKeysThen} reuse it — a resurrect's plan\n * can carry a disjointness entry exactly as a create's claim list does (see\n * {@link planNodeClaimReinsert}), so the transition seam needs the same\n * translation the create seam always did. For a plan whose claims are all\n * uniqueness (an in-place update's diff), `mapClaimRefusal` finds no\n * disjointness entry to remap and rethrows the original `UniquenessError`\n * unchanged, so this is a no-op there.\n */\nasync function issuingClaims(\n  entries: readonly NodeClaimEntry[],\n  issue: () => Promise<void>,\n): Promise<void> {\n  try {\n    await issue();\n  } catch (error) {\n    if (error instanceof UniquenessError) mapClaimRefusal(error, entries);\n    throw error;\n  }\n}\n\n/**\n * THE refusal for \"this write owes a claim it must issue BEFORE the row that\n * claim gates, and this backend cannot roll that pair back together\".\n *\n * A claim row that outlives the write it was taken for is invisible to every\n * read path and blocks its key forever, with no repair path: `deleteUnique` is\n * reached only by a node whose row exists. So a write that would open that\n * window on a backend with no transactions is refused, exactly as a write whose\n * fence is the per-graph lock has been since the lock became the fence. A\n * claim that follows its row opens no such window — a leaked ENTITY row is\n * visible, deletable, and is what that backend already does today — which is\n * why the subject is the pre-insert group and not the claim set.\n *\n * Takes the ENTRIES this write is about to issue rather than the kind's sites:\n * a row whose `where` predicates all fail writes no claim and must not be\n * refused. For a batch, any member's non-empty pre-insert group makes the batch\n * constrained — the same \"any member\" shape the batch lock probe uses.\n *\n * Delegates the error itself to {@link constraintFenceRefusal}, so there is one\n * refusal body, one code and one advice map.\n */\nfunction claimFenceRefusal(\n  ctx: Readonly<{ graphId: string }>,\n  backend: GraphBackend | TransactionBackend,\n  entries: readonly NodeClaimEntry[],\n): ConfigurationError | undefined {\n  const gating = entries.find((entry) => entry.placement === \"pre-insert\");\n  if (gating === undefined) return undefined;\n  return constraintFenceRefusal(ctx, backend, gating.refusalReason);\n}\n\n/** An entry whose family is uniqueness — the only family a claim probe reads. */\nexport type UniquenessClaimEntry = NodeClaimEntry &\n  Readonly<{ refusal: Extract<ClaimRefusal, { kind: \"uniqueness\" }> }>;\n\n/**\n * THE narrowing to the uniqueness family, for every path that probes claim rows.\n *\n * Disjointness entries have their own probe (`checkDisjointnessConstraint`,\n * which reads the NODE rows the constraint is declared over) and deliberately\n * do not get a second one here: a claim-row read would be a second spelling of\n * that verdict, and the two would drift.\n *\n * Exported because it is also what \"an ingestion branch defers node UNIQUENESS\n * and nothing else\" means, operationally: the clone's registrations produce\n * claim entries and this predicate is false for every one of them, while the\n * disjointness entries the same list carries are unaffected (see\n * {@link file://../../graph-merge/working-copy.ts graphWithoutNodeUniqueness}).\n */\nexport function isUniquenessClaimEntry(\n  entry: NodeClaimEntry,\n): entry is UniquenessClaimEntry {\n  return entry.refusal.kind === \"uniqueness\";\n}\n\n/** One set-oriented uniqueness read shared by every batch probe consumer. */\nexport type NodeUniquenessProbeGroup = Readonly<{\n  nodeKind: string;\n  constraintName: string;\n  keys: readonly string[];\n}>;\n\n/**\n * THE owner of grouping node uniqueness entries into backend batch reads.\n *\n * Preparation-cache priming and post-rollback diagnosis consume the same\n * groups, including every canonical and legacy axis covered by a scoped claim.\n * Keeping the grouping here prevents one path from silently probing a narrower\n * hierarchy than the other.\n */\nexport function groupNodeUniquenessProbes(\n  registry: KindRegistry,\n  items: readonly Readonly<{\n    kind: string;\n    entries: readonly NodeClaimEntry[];\n  }>[],\n): readonly NodeUniquenessProbeGroup[] {\n  type MutableProbeGroup = Readonly<{\n    nodeKind: string;\n    constraintName: string;\n    keys: Set<string>;\n  }>;\n  const groups = new Map<string, MutableProbeGroup>();\n  for (const item of items) {\n    for (const entry of item.entries) {\n      if (!isUniquenessClaimEntry(entry)) continue;\n      for (const nodeKind of uniquenessProbeKinds(\n        item.kind,\n        entry.refusal.constraint.scope,\n        registry,\n      )) {\n        const identity = encodeTupleKey([nodeKind, entry.constraintName]);\n        const group = groups.get(identity) ?? {\n          nodeKind,\n          constraintName: entry.constraintName,\n          keys: new Set<string>(),\n        };\n        group.keys.add(entry.key);\n        groups.set(identity, group);\n      }\n    }\n  }\n  return [...groups.values()].map((group) => ({\n    nodeKind: group.nodeKind,\n    constraintName: group.constraintName,\n    keys: [...group.keys],\n  }));\n}\n\n/**\n * Probes ONE entry's key across every kind its scope covers, the axis first.\n *\n * THE SINGLE OWNER of \"is this key available to this node?\" — the conflict\n * verdict and the ownership reading are one read, so no caller can consult one\n * without the other. {@link checkUniquenessConstraints} is this probe run for\n * its refusal alone; the plan builders below additionally keep what it read.\n *\n * Ownership is the pair `(concrete_kind, node_id)`, never the id alone: ids are\n * unique only per kind, so a namesake under another kind holds a DIFFERENT\n * node's reservation and must be refused — which is exactly what a scope\n * spanning kinds exists to catch. The refusal reports the holder's concrete\n * kind rather than the axis it was found at, because the axis need not be that\n * node's kind and, after this move, usually is not.\n *\n * @returns whether THIS node already holds the key live AT THE AXIS it is about\n *   to claim, in which case a claim would be a no-op and a compensating release\n *   would strip a reservation the node is entitled to. A row this node owns at\n *   a LEGACY axis deliberately does not suppress the claim: the axis row is a\n *   genuinely new reservation whose compensation must run.\n * @throws UniquenessError when a DIFFERENT node holds the key under any kind in\n *   scope.\n */\nexport async function probeUniqueKey(\n  ctx: UniquenessProbeContext,\n  kind: string,\n  id: string,\n  entry: UniquenessClaimEntry,\n  lookup: (\n    nodeKind: string,\n    entry: UniquenessClaimEntry,\n  ) => UniqueRow | undefined | Promise<UniqueRow | undefined> = async (\n    nodeKind,\n    claimEntry,\n  ) =>\n    ctx.backend.checkUnique({\n      graphId: ctx.graphId,\n      nodeKind,\n      constraintName: claimEntry.constraintName,\n      key: claimEntry.key,\n    }),\n): Promise<boolean> {\n  // `let` earns its place: the loop must visit EVERY kind in scope to reach its\n  // refusal, so the ownership reading cannot be an early return.\n  let heldByThisNode = false;\n  for (const kindToCheck of uniquenessProbeKinds(\n    kind,\n    entry.refusal.constraint.scope,\n    ctx.registry,\n  )) {\n    const existing = await lookup(kindToCheck, entry);\n\n    if (existing === undefined) continue;\n    const refusal = uniquenessClaimRefusal(kind, id, entry, existing);\n    if (refusal !== undefined) throw refusal;\n    if (kindToCheck === entry.axis) heldByThisNode = true;\n  }\n  return heldByThisNode;\n}\n\n/**\n * THE owner of the conflict verdict for one uniqueness probe result.\n *\n * The scalar probe and post-rollback batch diagnosis both call this function,\n * so owner-pair equality and the public error payload cannot drift between the\n * portable preflight and the native program's exceptional diagnostic path.\n */\nfunction uniquenessClaimRefusal(\n  kind: string,\n  id: string,\n  entry: UniquenessClaimEntry,\n  existing: UniqueRow,\n): UniquenessError | undefined {\n  const proposedOwner: ClaimOwner = { concreteKind: kind, nodeId: id };\n  if (\n    isSameClaimOwner(\n      { concreteKind: existing.concrete_kind, nodeId: existing.node_id },\n      proposedOwner,\n    )\n  ) {\n    return;\n  }\n  return new UniquenessError({\n    constraintName: entry.constraintName,\n    kind: existing.concrete_kind,\n    existingId: existing.node_id,\n    newId: id,\n    fields: entry.refusal.constraint.fields,\n  });\n}\n\n/**\n * Checks uniqueness constraints for a new or existing node.\n *\n * @throws ValidationError if any constraint is violated\n */\nexport async function checkUniquenessConstraints(\n  ctx: UniquenessProbeContext,\n  kind: string,\n  id: string,\n  props: Record<string, unknown>,\n  constraints: readonly UniqueConstraint[],\n): Promise<void> {\n  // The create extent, which is the wider of the two: a probe wants every claim\n  // this row could owe, and placement — the only thing the operation decides\n  // for a uniqueness site — says nothing about what is read. The disjointness\n  // entries the create extent also carries belong to the other probe, which\n  // reads node rows rather than claim rows.\n  for (const entry of nodeClaimEntries(\n    ctx.registry,\n    kind,\n    id,\n    props,\n    constraints,\n    \"create\",\n  )) {\n    if (isUniquenessClaimEntry(entry))\n      await probeUniqueKey(ctx, kind, id, entry);\n  }\n}\n\n/**\n * What the create claim seam needs from its caller.\n *\n * `lock` is compile-time evidence that the per-graph write-lock discipline was\n * satisfied BEFORE any row work (see {@link GraphWriteLock}); the seam performs\n * no locking of its own, so requiring the token here makes \"claim before lock\"\n * a type error at the call site instead of a lock-order inversion in review.\n *\n * `claimsVerdict` is the `claims` bundle's memoized, at-most-once verdict\n * thunk (ruling B7 refinement 2). This module's own uniqueness/disjointness\n * claims never read it — they are a different fence family, backed by the\n * `uniques` relation — but `node-write-pipeline.ts`'s hard-delete cascade\n * shares this same context and calls `purgeEdgeClaims` (the `claims` bundle's\n * edge-cardinality housekeeping) off it, so the field lives here rather than\n * on a second, parallel context only that one caller would build.\n */\nexport type NodeClaimContext = Readonly<{\n  graphId: string;\n  registry: KindRegistry;\n  lock: GraphWriteLock;\n  claimsVerdict: ClaimsVerdictThunk;\n  /** Threaded `uniqueSidecarBatch` verdict — never re-resolved here. */\n  uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>;\n}>;\n\n/** One row whose claims a create-shaped write is about to issue. */\nexport type NodeClaimItem = Readonly<{\n  kind: string;\n  id: string;\n  props: Record<string, unknown>;\n  constraints: readonly UniqueConstraint[];\n}>;\n\n/**\n * The ownership verdict metadata a planned claim would have produced if the\n * store had read the claim relation first.\n *\n * The authoritative insert uses the claim row's primary key instead of these\n * probe coordinates, but carrying the coordinates with the plan keeps the\n * typed refusal complete: uniqueness errors regain their declared fields, and\n * disjoint errors retain the exact partner kind that made the claim apply.\n */\ntype NodeCreateClaimVerdict =\n  | Readonly<{\n      claim: NodeInsertClaim;\n      probeKinds: readonly string[];\n      disjointOtherKind: undefined;\n      refusal: Extract<ClaimRefusal, { kind: \"uniqueness\" }>;\n    }>\n  | Readonly<{\n      claim: NodeInsertClaim;\n      probeKinds: readonly string[];\n      disjointOtherKind: string;\n      refusal: Extract<ClaimRefusal, { kind: \"disjointness\" }>;\n    }>;\n\nfunction isNodeCreateUniquenessVerdict(\n  verdict: NodeCreateClaimVerdict,\n): verdict is Extract<\n  NodeCreateClaimVerdict,\n  { refusal: { kind: \"uniqueness\" } }\n> {\n  return verdict.refusal.kind === \"uniqueness\";\n}\n\n/** One row's claim, with the owner it will be written under. */\ntype PlacedClaim = Readonly<{\n  item: NodeClaimItem;\n  entry: NodeClaimEntry;\n  target: ClaimTarget;\n}>;\n\n/** The complete, canonically ordered claim portion of one node insert plan. */\nexport type NodeCreateClaimPlan = Readonly<{\n  entries: readonly NodeClaimEntry[];\n  claims: readonly NodeInsertClaim[];\n  verdicts: readonly NodeCreateClaimVerdict[];\n}>;\n\n/**\n * How one placement group.s statements are issued.\n *\n * `onIssued` reports which claims actually landed, and it is optional because\n * only the pre-insert group has a use for the answer: that group is compensated\n * when its gated write fails, while a post-insert claim belongs to a row that is\n * already written and has nothing to undo.\n */\ntype ClaimIssuer = (\n  ctx: UniquenessContext,\n  claims: readonly PlacedClaim[],\n  onIssued?: (issued: readonly PlacedClaim[]) => void,\n) => Promise<void>;\n\nfunction claimTarget(graphId: string, entry: NodeClaimEntry): ClaimTarget {\n  return {\n    relation: \"uniques\",\n    graphId,\n    axis: entry.axis,\n    constraintName: entry.constraintName,\n    key: entry.key,\n  };\n}\n\nfunction claimInsertParams(\n  graphId: string,\n  claim: PlacedClaim,\n): InsertUniqueParams {\n  return {\n    graphId,\n    nodeKind: claim.entry.axis,\n    constraintName: claim.entry.constraintName,\n    key: claim.entry.key,\n    nodeId: claim.item.id,\n    concreteKind: claim.item.kind,\n  };\n}\n\nfunction placedNodeCreateClaims(\n  ctx: Pick<NodeClaimContext, \"graphId\" | \"registry\">,\n  items: readonly NodeClaimItem[],\n): readonly PlacedClaim[] {\n  return items.flatMap((item) =>\n    nodeClaimEntries(\n      ctx.registry,\n      item.kind,\n      item.id,\n      item.props,\n      item.constraints,\n      \"create\",\n    ).map((entry) => ({\n      item,\n      entry,\n      target: claimTarget(ctx.graphId, entry),\n    })),\n  );\n}\n\n/**\n * Resolves one create's claims once for either the atomic plan or fallback\n * seam. The returned list preserves the claim-site placement decision and the\n * same canonical target order standalone claim statements use.\n */\nexport function planNodeCreateClaims(\n  ctx: Pick<NodeClaimContext, \"graphId\" | \"registry\">,\n  item: NodeClaimItem,\n): NodeCreateClaimPlan {\n  const placed = placedNodeCreateClaims(ctx, [item]).toSorted((left, right) => {\n    if (left.entry.placement !== right.entry.placement) {\n      return left.entry.placement === \"pre-insert\" ? -1 : 1;\n    }\n    return compareClaimTargets(left.target, right.target);\n  });\n  const verdicts = placed.map((claim) => {\n    const baseClaim = {\n      axis: claim.entry.axis,\n      constraintName: claim.entry.constraintName,\n      key: claim.entry.key,\n      placement: claim.entry.placement,\n    };\n    if (claim.entry.refusal.kind === \"uniqueness\") {\n      const probeKinds = uniquenessProbeKinds(\n        claim.item.kind,\n        claim.entry.refusal.constraint.scope,\n        ctx.registry,\n      );\n      return {\n        claim: {\n          ...baseClaim,\n          verdict: {\n            kind: \"uniqueness\" as const,\n            probeAxes: probeKinds,\n            fields: claim.entry.refusal.constraint.fields,\n          },\n        } satisfies NodeInsertClaim,\n        probeKinds,\n        disjointOtherKind: undefined,\n        refusal: claim.entry.refusal,\n      } satisfies NodeCreateClaimVerdict;\n    }\n    return {\n      claim: {\n        ...baseClaim,\n        verdict: {\n          kind: \"disjointness\" as const,\n          conflictingKinds: [claim.entry.refusal.otherKind],\n        },\n      } satisfies NodeInsertClaim,\n      probeKinds: [],\n      disjointOtherKind: claim.entry.refusal.otherKind,\n      refusal: claim.entry.refusal,\n    } satisfies NodeCreateClaimVerdict;\n  });\n  return {\n    entries: placed.map((claim) => claim.entry),\n    claims: verdicts.map((verdict) => verdict.claim),\n    verdicts,\n  };\n}\n\n/** One statement per claim — the shape the single-row create path ships. */\nasync function issueClaimsIndividually(\n  ctx: UniquenessContext,\n  claims: readonly PlacedClaim[],\n  onIssued?: (issued: readonly PlacedClaim[]) => void,\n): Promise<void> {\n  for (const claim of claims) {\n    await issuingClaims([claim.entry], () =>\n      ctx.backend.insertUnique(claimInsertParams(ctx.graphId, claim)),\n    );\n    onIssued?.([claim]);\n  }\n}\n\n/**\n * ONE statement for the whole group, which is also what makes it deadlock-free\n * against itself: a single multi-row statement takes its row locks in a fixed\n * order. Falls back to the per-claim shape on a backend with no batch\n * primitive.\n */\nasync function issueClaimsBatched(\n  ctx: UniquenessContext,\n  claims: readonly PlacedClaim[],\n  onIssued?: (issued: readonly PlacedClaim[]) => void,\n): Promise<void> {\n  if (claims.length === 0) return;\n  const bound = bindExtraIfReachable(\n    ctx.backend,\n    ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n    UNIQUE_SIDECAR_BATCH.id,\n  );\n  if (bound === undefined) {\n    await issueClaimsIndividually(ctx, claims, onIssued);\n    return;\n  }\n  await issuingClaims(\n    claims.map((claim) => claim.entry),\n    async () => {\n      await bound.insertUniqueBatch(\n        claims.map((claim) => claimInsertParams(ctx.graphId, claim)),\n      );\n    },\n  );\n  onIssued?.(claims);\n}\n\n/**\n * Reserves the gating group, runs the row write it gates, and gives those\n * reservations back if the write does not land.\n *\n * Compensate, not swallow — the same give-back {@link withNodeClaimTransition}\n * makes, for the same reason: the reservations this write took are returned and\n * the original failure is rethrown, so the caller sees the error it would have\n * seen with no reservation attempted at all. Only rows that actually landed are\n * given back, and each is named in full (owner pair and claim axis), so nothing\n * a namesake under another kind or an older axis holds is touched.\n */\nasync function claimGroupThenWrite<T>(\n  ctx: UniquenessContext,\n  issue: ClaimIssuer,\n  gating: readonly PlacedClaim[],\n  gatedWrite: () => Promise<T>,\n): Promise<T> {\n  const issued: PlacedClaim[] = [];\n  try {\n    await issue(ctx, gating, (landed) => {\n      issued.push(...landed);\n    });\n    return await gatedWrite();\n  } catch (error) {\n    for (const claim of issued.toReversed()) {\n      await releaseClaimedUniqueKeys(ctx, claim.item.kind, claim.item.id, [\n        {\n          axis: claim.entry.axis,\n          constraintName: claim.entry.constraintName,\n          key: claim.entry.key,\n        },\n      ]);\n    }\n    throw error;\n  }\n}\n\n/**\n * Issues a create's claims on the two sides of the row write they gate, and\n * compensates the PRE-INSERT ones away if that write does not land.\n *\n * The entries are partitioned by their {@link ClaimPlacement} and the two\n * groups are issued around `gatedInsert`:\n *\n *  1. the `pre-insert` group — the create path's twin of\n *     {@link withNodeClaimTransition}, with the same claim → gated write →\n *     compensate sequence and the same reasoning: the claim is the only fence\n *     for that axis, and a fence issued after the write it fences is not a\n *     fence. A refusal here therefore happens with zero rows written, and a\n *     refusal from the write compensates the reservations away;\n *  2. `gatedInsert()`;\n *  3. the `post-insert` group — the position those entries ship in, unchanged,\n *     and with that position's failure behavior: a throw propagates and nothing\n *     compensates it, because the row it belongs to is already written and\n *     visible.\n *\n * Each group is sorted by {@link compareClaimTargets} and the pre-insert group\n * is always issued first, so every writer of a given row computes the same\n * acquisition order. A row owing claims in both groups therefore emits two\n * claim statements where one placement alone emits one.\n */\nasync function withNodeCreateClaimsIssuedBy<T>(\n  ctx: NodeClaimContext,\n  items: readonly NodeClaimItem[],\n  backend: GraphBackend | TransactionBackend,\n  issue: ClaimIssuer,\n  gatedInsert: () => Promise<T>,\n): Promise<T> {\n  const claimContext = createUniquenessContext(\n    ctx.graphId,\n    ctx.registry,\n    backend,\n    ctx.uniqueSidecarBatch,\n  );\n  const claims = placedNodeCreateClaims(ctx, items);\n\n  const refusal = claimFenceRefusal(\n    ctx,\n    backend,\n    claims.map((claim) => claim.entry),\n  );\n  if (refusal !== undefined) throw refusal;\n\n  const inPlacement = (placement: ClaimPlacement): readonly PlacedClaim[] =>\n    claims\n      .filter((claim) => claim.entry.placement === placement)\n      .toSorted((left, right) =>\n        compareClaimTargets(left.target, right.target),\n      );\n\n  const result = await claimGroupThenWrite(\n    claimContext,\n    issue,\n    inPlacement(\"pre-insert\"),\n    gatedInsert,\n  );\n  await issue(claimContext, inPlacement(\"post-insert\"));\n  return result;\n}\n\n/**\n * The create claim seam for ONE row: one statement per claim, matching the\n * statement shape the single-row create path ships.\n */\nexport function withNodeCreateClaims<T>(\n  ctx: NodeClaimContext,\n  item: NodeClaimItem,\n  backend: GraphBackend | TransactionBackend,\n  gatedInsert: () => Promise<T>,\n): Promise<T> {\n  return withNodeCreateClaimsIssuedBy(\n    ctx,\n    [item],\n    backend,\n    issueClaimsIndividually,\n    gatedInsert,\n  );\n}\n\n/**\n * The create claim seam for a BATCH: one statement per placement group across\n * every row, instead of the per-row statement fan.\n */\nexport function withNodeCreateClaimsBatch<T>(\n  ctx: NodeClaimContext,\n  items: readonly NodeClaimItem[],\n  backend: GraphBackend | TransactionBackend,\n  gatedInsert: () => Promise<T>,\n): Promise<T> {\n  return withNodeCreateClaimsIssuedBy(\n    ctx,\n    items,\n    backend,\n    issueClaimsBatched,\n    gatedInsert,\n  );\n}\n\n/**\n * The gate for a claim set whose row write has ALREADY been applied — a\n * re-claim after a set update, or a test seeding a reservation.\n *\n * Such a write reaches the seam with nothing left to gate, which is exactly why\n * it owes no pre-insert claim: there is no row write left for a claim to\n * precede. Naming it makes that reading explicit at the call site instead of\n * leaving an inline no-op for a reader to interpret.\n */\nexport function alreadyAppliedRowWrite(): Promise<undefined> {\n  return Promise.resolve(undefined);\n}\n\n/**\n * Releases the claims a node being deleted holds — the LIFECYCLE shape: every\n * claim this node owns for each applying constraint's key, at whatever axis the\n * claim sits on.\n */\nexport async function deleteUniquenessEntries(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  props: Record<string, unknown>,\n  constraints: readonly UniqueConstraint[],\n): Promise<void> {\n  // The create extent: a delete gives back everything a create wrote, so the\n  // release must be read from the wider of the two lists.\n  await releaseOwnedUniqueKeys(\n    ctx,\n    kind,\n    id,\n    nodeClaimEntries(ctx.registry, kind, id, props, constraints, \"create\"),\n  );\n}\n\n/**\n * Drops EVERY claim a set of nodes holds under one concrete kind, key-blind, so\n * the rebuild that follows can re-claim from the after-images.\n *\n * The key-blind drop is what a set update needs and the per-key\n * {@link deleteUniquenessEntries} cannot give it: the statement rewrote whole\n * rows without reading their before-images, so nobody knows which keys those\n * rows used to hold. It drops BOTH families — every claim the owner pair holds —\n * which is why the rebuild must go back through {@link withNodeCreateClaimsBatch}\n * rather than a uniqueness-only reinsert.\n *\n * Requiring the member rather than probing it: the only caller\n * ({@link file://../operations/node-write-pipeline.ts applyNodeSetUpdate})\n * refuses the write up front when a constrained kind's backend lacks it, with a\n * code that names the operation. A second fallback here would be a quieter\n * answer to a question already asked.\n */\nexport async function hardDeleteClaimsByNodeIds(\n  ctx: UniquenessContext,\n  concreteKind: string,\n  nodeIds: readonly string[],\n): Promise<void> {\n  await requireDefined(\n    bindExtraIfReachable(\n      ctx.backend,\n      ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n      UNIQUE_SIDECAR_BATCH.id,\n    )?.hardDeleteUniquesByNodeIds,\n  )({\n    graphId: ctx.graphId,\n    concreteKind,\n    nodeIds,\n  });\n}\n\n/**\n * A single constraint's sidecar transition, decided by a plan builder and\n * carried out by {@link withNodeClaimTransition}.\n *\n * The two keys move at DIFFERENT times relative to the primary row write, so\n * they are named for when they move rather than for old/new:\n * `claim` is reserved BEFORE the write (it is the write's conflict gate),\n * `release` is given up AFTER it (it is history the write supersedes).\n */\ntype PendingUniqueMutation = Readonly<{\n  constraintName: string;\n  /** The key to give up once the primary write lands; undefined = none. */\n  release: string | undefined;\n  /**\n   * The entry to reserve before the primary write; undefined = none, either\n   * because the constraint stopped applying or because {@link probeUniqueKey}\n   * found this node already holding it live. It is the whole entry rather than\n   * a bare key so the compensation names the row this transition wrote instead\n   * of re-deriving which axis that was, and so the refusal reads the placement\n   * and class the entry's site decided.\n   */\n  claim: NodeClaimEntry | undefined;\n}>;\n\n/**\n * The sidecar transition a node write owes, decided but not yet performed.\n *\n * Opaque to its holder on purpose: the only thing a caller does with a plan is\n * hand it to {@link withNodeClaimTransition} together with the primary row\n * write it belongs to.\n */\nexport type UniquenessUpdatePlan = readonly PendingUniqueMutation[];\n\n/**\n * Decides the claim changes a node's new props require, WITHOUT writing any of\n * them.\n *\n * Preflights EVERY changed constraint before anything is written. A node can\n * carry several unique constraints; probing them one at a time as they are\n * applied would let a later constraint's conflict throw after earlier sidecars\n * already moved. Probing all of them first means a refusal here happens with\n * zero writes, and the probes are independent per `constraintName`, so one\n * constraint's verdict is unaffected by the others' still-unapplied changes.\n *\n * Handles the cases where a constraint starts applying, stops applying, or\n * keeps applying under a different key.\n *\n * @throws UniquenessError if an updated value is already held by another node\n */\nexport async function planNodeClaimUpdate(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  oldProps: Record<string, unknown>,\n  newProps: Record<string, unknown>,\n  constraints: readonly UniqueConstraint[],\n): Promise<UniquenessUpdatePlan> {\n  // Both sides of the diff are read from the one entries function, so the key\n  // a release names is computed exactly the way the key a claim names is.\n  const oldKeys = new Map(\n    nodeClaimEntries(\n      ctx.registry,\n      kind,\n      id,\n      oldProps,\n      constraints,\n      \"update\",\n    ).map((entry) => [entry.constraintName, entry.key]),\n  );\n  const newEntries = new Map(\n    nodeClaimEntries(ctx.registry, kind, id, newProps, constraints, \"update\")\n      .filter((entry): entry is UniquenessClaimEntry =>\n        isUniquenessClaimEntry(entry),\n      )\n      .map((entry) => [entry.constraintName, entry]),\n  );\n\n  const pending: PendingUniqueMutation[] = [];\n  for (const constraint of constraints) {\n    const oldKey = oldKeys.get(constraint.name);\n    const newEntry = newEntries.get(constraint.name);\n\n    // No change - constraint didn't apply and still doesn't\n    if (oldKey === undefined && newEntry === undefined) continue;\n\n    // Key is the same and the constraint still applies - nothing to do\n    if (oldKey !== undefined && oldKey === newEntry?.key) continue;\n\n    // Probe the new key: refuse a value another node holds, and note a value\n    // this node somehow holds already so the transition neither re-claims nor\n    // releases it.\n    const alreadyHeld =\n      newEntry === undefined ? false : (\n        await probeUniqueKey(ctx, kind, id, newEntry)\n      );\n\n    pending.push({\n      constraintName: constraint.name,\n      release: oldKey,\n      claim: newEntry === undefined || alreadyHeld ? undefined : newEntry,\n    });\n  }\n\n  return pending;\n}\n\n/**\n * The plan a RESURRECTING write needs: every applying constraint re-reserved\n * from scratch, uniqueness AND disjointness alike.\n *\n * A tombstoned node holds no live reservations — {@link deleteUniquenessEntries}\n * released them at soft-delete time, reading the wider `\"create\"` extent that\n * already covers both families — so the diff-based {@link planNodeClaimUpdate}\n * cannot be used here: it would skip an unchanged key and leave the revived\n * node holding NO reservation, letting a later create (of this node's own key,\n * or of a disjoint partner under this node's id) silently duplicate the value.\n *\n * Reads its entries at `\"resurrect\"`, the {@link NodeClaimOperation} that owes\n * the same disjointness sites a create owes (see `nodeClaimSites`) — a\n * resurrect brings a node back into existence under its kind exactly as a\n * create does, so it owes the same cross-kind claim. A disjointness entry can\n * never already be held by THIS node (its own reservation was released at\n * soft-delete time, and nothing else could have taken it under this node's\n * OWN id/kind pair), so unlike a uniqueness entry it needs no \"already held by\n * myself\" probe — it is claimed fresh, exactly as a create claims it fresh.\n *\n * @throws UniquenessError if a key this node held was taken while it was\n *   tombstoned\n * @throws DisjointError if a disjoint partner now holds this id (translated by\n *   {@link claimUniqueKeysThen} from the `UniquenessError` `insertUnique`\n *   itself reports)\n */\nexport async function planNodeClaimReinsert(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  props: Record<string, unknown>,\n  constraints: readonly UniqueConstraint[],\n): Promise<UniquenessUpdatePlan> {\n  const pending: PendingUniqueMutation[] = [];\n  for (const entry of nodeClaimEntries(\n    ctx.registry,\n    kind,\n    id,\n    props,\n    constraints,\n    \"resurrect\",\n  )) {\n    const alreadyHeld =\n      isUniquenessClaimEntry(entry) ?\n        await probeUniqueKey(ctx, kind, id, entry)\n      : false;\n\n    pending.push({\n      constraintName: entry.constraintName,\n      release: undefined,\n      claim: alreadyHeld ? undefined : entry,\n    });\n  }\n  return pending;\n}\n\n/** One reservation a release names. */\ntype ReleasableKey = Readonly<{ constraintName: string; key: string }>;\n\n/**\n * A reservation a write actually took, remembered together with the claim axis\n * it was written at so the compensation can name the same row rather than\n * re-deriving it.\n */\ntype ClaimedKey = ReleasableKey & Readonly<{ axis: string }>;\n\n/**\n * LIFECYCLE release: gives up every reservation THIS node holds for each\n * `(constraintName, key)`, in plan order, whatever axis the reservation sits\n * on.\n *\n * Scoping to the owner pair `(concreteKind, id)` rather than to the axis is\n * what lets a claim written under an older axis be released by newer code, and\n * what keeps a namesake — same id, different kind — holding its own.\n */\nasync function releaseOwnedUniqueKeys(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  keys: readonly ReleasableKey[],\n): Promise<void> {\n  for (const entry of keys) {\n    await ctx.backend.deleteUnique({\n      graphId: ctx.graphId,\n      constraintName: entry.constraintName,\n      key: entry.key,\n      concreteKind: kind,\n      nodeId: id,\n    });\n  }\n}\n\n/**\n * COMPENSATING release: undoes exactly the rows a failed write just claimed —\n * the owner's reservation AT the axis it claimed on, and nothing else.\n *\n * Deliberately narrower than {@link releaseOwnedUniqueKeys}: a rollback must\n * touch neither a reservation at another axis that predates this write nor one\n * another node holds. Conflating the two would make a refused write strip\n * claims it never took.\n */\nasync function releaseClaimedUniqueKeys(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  keys: readonly ClaimedKey[],\n): Promise<void> {\n  for (const entry of keys) {\n    await ctx.backend.deleteUnique({\n      graphId: ctx.graphId,\n      nodeKind: entry.axis,\n      constraintName: entry.constraintName,\n      key: entry.key,\n      concreteKind: kind,\n      nodeId: id,\n    });\n  }\n}\n\n/**\n * Reserves the plan's new keys, runs the primary row write they gate, and undoes\n * the reservations if that write does not land.\n *\n * Each claim statement runs through {@link issuingClaims} — a resurrect's plan\n * can carry a disjointness entry ({@link planNodeClaimReinsert}), and a foreign\n * owner of THAT reservation must surface as `DisjointError`, not the raw\n * `UniquenessError` `insertUnique` reports for every family alike.\n */\nasync function claimUniqueKeysThen<T>(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  plan: UniquenessUpdatePlan,\n  gatedWrite: () => Promise<T>,\n): Promise<T> {\n  const claimed: ClaimedKey[] = [];\n  try {\n    for (const mutation of plan) {\n      const claim = mutation.claim;\n      if (claim === undefined) continue;\n      await issuingClaims([claim], () =>\n        ctx.backend.insertUnique({\n          graphId: ctx.graphId,\n          nodeKind: claim.axis,\n          constraintName: mutation.constraintName,\n          key: claim.key,\n          nodeId: id,\n          concreteKind: kind,\n        }),\n      );\n      claimed.push({\n        axis: claim.axis,\n        constraintName: mutation.constraintName,\n        key: claim.key,\n      });\n    }\n    return await gatedWrite();\n  } catch (error) {\n    // Compensate, not swallow: the reservations this transition took are given\n    // back and the original failure is rethrown, so the caller sees the SAME\n    // error it would have seen with no reservation attempted at all.\n    //\n    // The give-back names the exact rows this transition wrote — owner pair and\n    // claim axis both — so it can strip neither a reservation at another axis\n    // that predates this write nor one a namesake under a different kind holds.\n    //\n    // The give-back is exact because of what a claim can be. `probeUniqueKey`\n    // refuses a key another node holds and reports one THIS node already holds\n    // (which the plan then does not claim), so every claimed key was free or\n    // tombstoned beforehand and releasing it restores precisely that. And no\n    // peer can have taken it in between: this transaction holds the row.\n    //\n    // One detail is restored in kind rather than exactly: a claim that took over\n    // a TOMBSTONED reservation rewrites its recorded owner, and the give-back\n    // re-tombstones it under THIS node's id instead of the previous holder's.\n    // The key reads as free either way — `checkUnique` skips tombstoned rows —\n    // and the one reader that looks at them, `getOrCreateByConstraint`'s\n    // resurrect-by-key lookup, writes the props it was called with onto whatever\n    // row it revives, so the reservation and the row holding the value stay\n    // consistent. Which tombstone that lookup revives can differ. If the\n    // compensation itself fails the row is genuinely half-written, and the\n    // error that then surfaces is a raw backend failure no per-row consumer\n    // catches — the enclosing transaction aborts, which is the only honest\n    // outcome left.\n    await releaseClaimedUniqueKeys(ctx, kind, id, claimed);\n    throw error;\n  }\n}\n\n/**\n * Runs one node's primary row write with its claim transition wrapped around\n * it, so the pair commits or fails AS ONE UNIT.\n *\n * ## Why the sequence is claim, gate, release\n *\n * A node update is two independently fallible writes — the row itself and its\n * claim rows — with no rollback between them: nothing here is\n * savepoint-protected (see `operations/write-transaction.ts`), and the backends\n * this supports do not all have savepoints to reach for. Sequencing is the only\n * atomicity available, and only ONE sequence makes both failures leave zero net\n * effect:\n *\n *  - **Claim first.** `insertUnique` is an upsert that reports the key's final\n *    owner, so claiming IS the conflict gate — and once this transaction holds\n *    the row, no concurrent writer can take the key from under it. Probing and\n *    then claiming later leaves a window (wide open under PostgreSQL READ\n *    COMMITTED, where a peer commits between the two) in which the claim fails\n *    AFTER the row was already updated.\n *  - **Then the row write.** It can legitimately match nothing —\n *    `expectedValidFrom`, `deleted_at` — and callers that catch that per row and\n *    commit the rest (interchange import) must not be left with reservations for\n *    a row that never changed. A refusal here compensates the claims away.\n *  - **Release last.** Giving up the old key before the row write would free a\n *    value for a write that may never land; giving it up after is safe because\n *    nothing can fail on it.\n *\n * The predecessor of this helper ordered the whole sidecar transition after the\n * row write, which closed the second failure and left the first: a caught\n * `UniquenessError` then reported `updated: 0` for a row whose props HAD\n * changed, whose old reservation was gone, and whose new one belonged to someone\n * else.\n *\n * Because that sequence is claim-first for EVERY scope, every claim this seam\n * issues is `pre-insert`, and a backend that cannot roll the pair back together\n * is refused before the first of them — see {@link claimFenceRefusal}. The\n * subject is the plan's claims rather than the kind's constraints: an update\n * that does not move a key issues no reservation and must not be refused.\n */\nexport async function withNodeClaimTransition<T>(\n  ctx: UniquenessContext,\n  kind: string,\n  id: string,\n  plan: UniquenessUpdatePlan,\n  gatedWrite: () => Promise<T>,\n): Promise<T> {\n  const refusal = claimFenceRefusal(\n    ctx,\n    ctx.backend,\n    plan.flatMap((mutation) =>\n      mutation.claim === undefined ? [] : [mutation.claim],\n    ),\n  );\n  if (refusal !== undefined) throw refusal;\n\n  const result = await claimUniqueKeysThen(ctx, kind, id, plan, gatedWrite);\n  await releaseOwnedUniqueKeys(\n    ctx,\n    kind,\n    id,\n    plan.flatMap((mutation) =>\n      mutation.release === undefined ?\n        []\n      : [{ constraintName: mutation.constraintName, key: mutation.release }],\n    ),\n  );\n  return result;\n}\n","/**\n * Node claims for a RESOLVED WRITE SET — a whole after-image validated at once,\n * then applied.\n *\n * Every other claim path in this directory decides one row at a time, which is\n * what an ordinary write is. Two callers instead know their complete final state\n * before writing any of it — a graph merge's resolved plan\n * ({@link file://../../graph-merge/merge.ts}) and a set update\n * ({@link file://../operations/node-operations.ts}) — and for them \"one row at a\n * time\" is the wrong verdict: an atomic SWAP of two nodes' keys, or a handoff of\n * one key from a node the set deletes to a node the set writes, is legal in the\n * final state and refused by every intermediate one.\n *\n * So this module reads the set's claims TOGETHER, decides them against each\n * other first and the persisted relation second, and treats every reservation\n * the set itself releases as available. It decides nothing on its own: the\n * entries come from {@link nodeClaimEntries}, the axis fold from\n * {@link uniquenessProbeKinds}, the ownership verdict from\n * {@link isSameClaimOwner} / {@link claimOwnerKey}, and the rebuild from the\n * same claim writer every create-shaped write uses.\n */\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport { missingRequiredExtras } from \"../../backend/capabilities/resolve\";\nimport { type GraphBackend } from \"../../backend/types\";\nimport { type UniqueConstraint } from \"../../core/types\";\nimport { ConfigurationError, UniquenessError } from \"../../errors\";\nimport { requireDefined } from \"../../utils/presence\";\nimport { encodeTupleKey } from \"../../utils/tuple-key\";\nimport {\n  type ClaimOwner,\n  claimOwnerKey,\n  isSameClaimOwner,\n  uniquenessProbeKinds,\n} from \"./axis\";\nimport {\n  alreadyAppliedRowWrite,\n  isUniquenessClaimEntry,\n  type NodeClaimContext,\n  nodeClaimEntries,\n  type UniquenessClaimEntry,\n  type UniquenessContext,\n  withNodeCreateClaimsBatch,\n} from \"./node-claims\";\n\n/** A complete node after-image whose claims belong to one resolved write set. */\nexport type ResolvedNodeUpsert = Readonly<{\n  kind: string;\n  id: string;\n  props: Readonly<Record<string, unknown>>;\n  constraints: readonly UniqueConstraint[];\n}>;\n\n/** A node whose current claims the resolved write set gives back. */\nexport type ResolvedNodeRelease = Readonly<{\n  kind: string;\n  id: string;\n}>;\n\n/**\n * One uniqueness claim the set proposes: who takes it, the row it writes, and\n * the rows its probe reads.\n *\n * `probeKinds` is carried rather than recomputed because it is BOTH halves of\n * the conflict test — the persisted probe issues one read per member, and the\n * in-set test asks whether one claim's write lands in another claim's read set.\n */\ntype ProposedClaim = Readonly<{\n  owner: ClaimOwner;\n  entry: UniquenessClaimEntry;\n  probeKinds: readonly string[];\n}>;\n\nfunction resolvedNodeUniquenessOperationsRefusal(): ConfigurationError {\n  return new ConfigurationError(\n    \"Resolved node writes require batched uniqueness operations\",\n    { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n  );\n}\n\n/**\n * The one admission decision for a resolved node batch whose sidecars must\n * operate as a complete set. The root verdict and the concrete write port are\n * both required: a derived transaction port can legitimately narrow a member\n * that was available when the Store resolved its root verdict.\n */\nexport function resolvedNodeUniqueSidecarBatchIsReachable(\n  ctx: Readonly<{\n    backend: Readonly<\n      Partial<\n        Pick<\n          GraphBackend,\n          | \"checkUniqueBatch\"\n          | \"hardDeleteUniquesByNodeIds\"\n          | \"insertUniqueBatch\"\n        >\n      >\n    >;\n    uniqueSidecarBatch: UniquenessContext[\"uniqueSidecarBatch\"];\n  }>,\n): boolean {\n  if (\n    missingRequiredExtras(\n      UNIQUE_SIDECAR_BATCH,\n      ctx.uniqueSidecarBatch,\n      \"resolved node write\",\n    ).length > 0\n  ) {\n    return false;\n  }\n  return [\n    ctx.uniqueSidecarBatch.extras.checkUniqueBatch,\n    ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n    ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n  ].every(\n    (extra) =>\n      bindExtraIfReachable(ctx.backend, extra, UNIQUE_SIDECAR_BATCH.id) !==\n      undefined,\n  );\n}\n\n/**\n * Whether a resolved update preserves every unique claim key it already owns.\n * `bulkUpsertById` is sequential by contract, so only a key-stable group may\n * take the set-based row path; a key transfer remains on the established\n * rowwise ordering and therefore has the same result either way.\n */\nexport function resolvedNodeUpdatePreservesClaimKeys(\n  registry: UniquenessContext[\"registry\"],\n  kind: string,\n  id: string,\n  previousProps: Record<string, unknown>,\n  nextProps: Record<string, unknown>,\n  constraints: readonly UniqueConstraint[],\n): boolean {\n  const footprint = (props: Record<string, unknown>): readonly string[] =>\n    nodeClaimEntries(registry, kind, id, props, constraints, \"update\")\n      .map((entry) =>\n        encodeTupleKey([entry.axis, entry.constraintName, entry.key]),\n      )\n      .toSorted();\n  const previous = footprint(previousProps);\n  const next = footprint(nextProps);\n  return (\n    previous.length === next.length &&\n    previous.every((entry, index) => entry === next[index])\n  );\n}\n\n/** The claim rows two proposals share a competition for. */\nfunction claimRowKey(entry: UniquenessClaimEntry): string {\n  return encodeTupleKey([entry.constraintName, entry.key]);\n}\n\n/**\n * Whether two proposals in one set are competing — one writes a row the other\n * reads.\n *\n * Reachability in EITHER direction, not axis equality: after the axis fold a\n * `kind`-scoped constraint writes under the writer's own kind while a\n * `kindWithSubClasses` constraint of the same name writes under the component's\n * fold, so two claims can compete without sharing an axis. The wider scope's\n * probe is what would have caught the narrower one's row had it been persisted,\n * and inside one set neither row is persisted yet — which is the whole reason\n * this test exists rather than leaving it to the relation.\n */\nfunction claimsCompete(left: ProposedClaim, right: ProposedClaim): boolean {\n  return (\n    claimRowKey(left.entry) === claimRowKey(right.entry) &&\n    (right.probeKinds.includes(left.entry.axis) ||\n      left.probeKinds.includes(right.entry.axis))\n  );\n}\n\nfunction proposedClaimRefusal(\n  incumbent: ProposedClaim,\n  challenger: ProposedClaim,\n): UniquenessError {\n  return new UniquenessError({\n    constraintName: challenger.entry.constraintName,\n    kind: incumbent.owner.concreteKind,\n    existingId: incumbent.owner.nodeId,\n    newId: challenger.owner.nodeId,\n    fields: challenger.entry.refusal.constraint.fields,\n  });\n}\n\n/**\n * The set's uniqueness claims, with every in-set competition already refused.\n *\n * Reads its work from {@link nodeClaimEntries} at the CREATE extent — the wider\n * of the two, exactly as {@link file://./node-claims.ts checkUniquenessConstraints}\n * does — and narrows to the uniqueness family. The disjointness entries the same\n * list carries are NOT probed here: they have their own probe over node rows,\n * and each write inside the set's `apply()` reaches it. Filtering rather than\n * asking for a narrower list is what keeps that omission a stated decision\n * instead of an absence nobody notices.\n *\n * @throws UniquenessError when two members of the set compete for one claim.\n */\nfunction proposedClaims(\n  ctx: UniquenessContext,\n  upserts: readonly ResolvedNodeUpsert[],\n): readonly ProposedClaim[] {\n  const accepted: ProposedClaim[] = [];\n  for (const upsert of upserts) {\n    const owner: ClaimOwner = {\n      concreteKind: upsert.kind,\n      nodeId: upsert.id,\n    };\n    const entries = nodeClaimEntries(\n      ctx.registry,\n      upsert.kind,\n      upsert.id,\n      { ...upsert.props },\n      upsert.constraints,\n      \"create\",\n    );\n    for (const entry of entries) {\n      if (!isUniquenessClaimEntry(entry)) continue;\n      const proposal: ProposedClaim = {\n        owner,\n        entry,\n        probeKinds: uniquenessProbeKinds(\n          upsert.kind,\n          entry.refusal.constraint.scope,\n          ctx.registry,\n        ),\n      };\n      const incumbent = accepted.find(\n        (candidate) =>\n          !isSameClaimOwner(candidate.owner, proposal.owner) &&\n          claimsCompete(candidate, proposal),\n      );\n      if (incumbent !== undefined) {\n        throw proposedClaimRefusal(incumbent, proposal);\n      }\n      accepted.push(proposal);\n    }\n  }\n  return accepted;\n}\n\n/** One `checkUniqueBatch` round trip: every key this set claims at one axis. */\ntype ClaimProbeGroup = Readonly<{\n  probeKind: string;\n  constraintName: string;\n  claimsByKey: ReadonlyMap<string, ProposedClaim>;\n}>;\n\n/**\n * Folds the proposals into one probe per `(kind in scope, constraint)`.\n *\n * Keyed on {@link uniquenessProbeKinds} rather than on the axis alone for the\n * reason that function documents: rows written before the axis move sit under\n * their own concrete kind, so a probe that read only the axis would not see them\n * and the move would need a data migration.\n */\nfunction groupClaimsForProbe(\n  claims: readonly ProposedClaim[],\n): readonly ClaimProbeGroup[] {\n  const groups = new Map<\n    string,\n    {\n      probeKind: string;\n      constraintName: string;\n      claimsByKey: Map<string, ProposedClaim>;\n    }\n  >();\n  for (const claim of claims) {\n    for (const probeKind of claim.probeKinds) {\n      const groupKey = encodeTupleKey([probeKind, claim.entry.constraintName]);\n      const existing = groups.get(groupKey);\n      if (existing === undefined) {\n        groups.set(groupKey, {\n          probeKind,\n          constraintName: claim.entry.constraintName,\n          claimsByKey: new Map([[claim.entry.key, claim]]),\n        });\n        continue;\n      }\n      existing.claimsByKey.set(claim.entry.key, claim);\n    }\n  }\n  return [...groups.values()];\n}\n\n/**\n * The batch probe this validation is defined in terms of, or a typed refusal.\n *\n * Keyed on this ONE extra's own presence, not the operation's full 3-extra\n * `requires` set: widening this to `missingRequiredExtras` would move\n * {@link prepareResolvedNodeClaims}'s refusal earlier for\n * `validateResolvedNodeClaims`'s direct caller\n * ({@link file://../operations/node-write-pipeline.ts applyNodeSetUpdate}),\n * which probes and refuses on the full set itself before reaching this call.\n *\n * Binds through {@link bindExtraIfReachable}, not {@link bindExtra}: this\n * refusal is keyed on \"is the probe reachable at all\" — the verdict says\n * present AND the port (`ctx.backend`, the transaction target the call\n * actually executes on) can serve it — and either failure mode collapses\n * into this SAME typed refusal, preserved byte-for-byte from before the\n * capability model existed\n * (`tests/graph-merge/ingestion-branch.test.ts`'s \"refuses final validation\n * when the target transaction lacks batch uniqueness operations\" pins a\n * transaction target narrower than the verdict it was resolved against, and\n * still expects this exact code). `bindExtra`'s generic\n * `BUNDLE_PORT_SURFACE_MISMATCH` would replace that pinned, operation-specific\n * message with the bundle's own — an acceptable disposition for a call site\n * with no existing refusal to preserve, but not for this one.\n */\nfunction requireBatchProbe(\n  ctx: UniquenessContext,\n): NonNullable<UniquenessContext[\"backend\"][\"checkUniqueBatch\"]> {\n  const bound = bindExtraIfReachable(\n    ctx.backend,\n    ctx.uniqueSidecarBatch.extras.checkUniqueBatch,\n    UNIQUE_SIDECAR_BATCH.id,\n  );\n  if (bound === undefined) {\n    throw new ConfigurationError(\n      \"Resolved node writes require batched uniqueness probes\",\n      { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n    );\n  }\n  return bound.checkUniqueBatch;\n}\n\n/**\n * Validates node uniqueness against the FINAL state of a resolved write set.\n *\n * All proposed after-images are compared together before persisted claim rows\n * are consulted. Owners the set itself releases or replaces are ignored, which\n * permits atomic swaps and handoffs while still refusing every owner outside the\n * set. The probe is batch-only by contract: a caller that needs this set\n * semantic must not quietly degrade to sequential checks.\n */\nexport async function validateResolvedNodeClaims(\n  ctx: UniquenessContext,\n  upserts: readonly ResolvedNodeUpsert[],\n  releases: readonly ResolvedNodeRelease[] = [],\n): Promise<void> {\n  const checkUniqueBatch = requireBatchProbe(ctx);\n  const claims = proposedClaims(ctx, upserts);\n  if (claims.length === 0) return;\n\n  const affectedOwners = new Set(\n    [...upserts, ...releases].map((reference) =>\n      claimOwnerKey({ concreteKind: reference.kind, nodeId: reference.id }),\n    ),\n  );\n  for (const group of groupClaimsForProbe(claims)) {\n    const existingRows = await checkUniqueBatch({\n      graphId: ctx.graphId,\n      nodeKind: group.probeKind,\n      constraintName: group.constraintName,\n      keys: [...group.claimsByKey.keys()],\n    });\n    for (const existing of existingRows) {\n      if (\n        affectedOwners.has(\n          claimOwnerKey({\n            concreteKind: existing.concrete_kind,\n            nodeId: existing.node_id,\n          }),\n        )\n      ) {\n        continue;\n      }\n      const claim = group.claimsByKey.get(existing.key);\n      if (claim === undefined) continue;\n      throw new UniquenessError({\n        constraintName: group.constraintName,\n        // The holder's own kind, never `group.probeKind`: that is the claim\n        // AXIS, which a shared scope folds across kinds and which the caller\n        // never wrote. The probe and the fence report the same value.\n        kind: existing.concrete_kind,\n        existingId: existing.node_id,\n        newId: claim.owner.nodeId,\n        fields: claim.entry.refusal.constraint.fields,\n      });\n    }\n  }\n}\n\n/**\n * Prepares a transaction to apply a resolved write set row by row.\n *\n * Validation happens before any mutation. Once it succeeds, every affected\n * node's claims are batch-cleared so the later per-node upserts can take the\n * validated final keys in any order (including swaps and handoffs).\n */\nasync function prepareResolvedNodeClaims(\n  ctx: UniquenessContext,\n  upserts: readonly ResolvedNodeUpsert[],\n  releases: readonly ResolvedNodeRelease[],\n): Promise<void> {\n  if (!resolvedNodeUniqueSidecarBatchIsReachable(ctx)) {\n    throw resolvedNodeUniquenessOperationsRefusal();\n  }\n  const boundHardDelete = bindExtraIfReachable(\n    ctx.backend,\n    ctx.uniqueSidecarBatch.extras.hardDeleteUniquesByNodeIds,\n    UNIQUE_SIDECAR_BATCH.id,\n  );\n  const { hardDeleteUniquesByNodeIds } = requireDefined(boundHardDelete);\n  await validateResolvedNodeClaims(ctx, upserts, releases);\n\n  const idsByKind = new Map<string, Set<string>>();\n  for (const reference of [...upserts, ...releases]) {\n    const ids = idsByKind.get(reference.kind) ?? new Set<string>();\n    ids.add(reference.id);\n    idsByKind.set(reference.kind, ids);\n  }\n  for (const [concreteKind, nodeIds] of idsByKind) {\n    await hardDeleteUniquesByNodeIds({\n      graphId: ctx.graphId,\n      concreteKind,\n      nodeIds: [...nodeIds],\n    });\n  }\n}\n\n/**\n * Applies a resolved write set between the set preflight and one final claim\n * rebuild.\n *\n * The rebuild is required even though ordinary upserts take their own claims: an\n * unchanged upsert may be coalesced and skip all of its normal side effects\n * after preparation cleared its reservations. Re-taking every approved claim is\n * idempotent and makes the transition independent of whether individual writes\n * were coalesced.\n *\n * It goes through {@link withNodeCreateClaimsBatch} — the claim writer every\n * create-shaped write uses — and not through a uniqueness-only insert, for a\n * reason the preparation step makes load-bearing: `hardDeleteUniquesByNodeIds`\n * clears every claim the affected nodes OWN, and after WS2 that includes their\n * `disjointWith` reservations. A rebuild that restored only the uniqueness\n * family would leave each merged node unfenced against a disjoint namesake for\n * the rest of the graph's life. The claim writer restores what\n * {@link nodeClaimEntries} says the row owes, both families, so the set's claims\n * cannot fall out of step with an ordinary create's.\n *\n * `lock` is the caller's evidence that the per-graph write lock was taken before\n * any row work; this function performs no locking of its own.\n */\nexport async function applyResolvedNodeClaims<Output>(\n  ctx: NodeClaimContext,\n  backend: UniquenessContext[\"backend\"],\n  upserts: readonly ResolvedNodeUpsert[],\n  releases: readonly ResolvedNodeRelease[],\n  apply: () => Promise<Output>,\n): Promise<Output> {\n  const claimContext: UniquenessContext = {\n    graphId: ctx.graphId,\n    registry: ctx.registry,\n    backend,\n    uniqueSidecarBatch: ctx.uniqueSidecarBatch,\n  };\n  await prepareResolvedNodeClaims(claimContext, upserts, releases);\n  const result = await apply();\n  await withNodeCreateClaimsBatch(\n    ctx,\n    upserts.map((upsert) => ({\n      kind: upsert.kind,\n      id: upsert.id,\n      props: { ...upsert.props },\n      constraints: upsert.constraints,\n    })),\n    backend,\n    alreadyAppliedRowWrite,\n  );\n  return result;\n}\n","/**\n * Embedding Sync Utilities\n *\n * Handles automatic synchronization of embedding fields with the embeddings table.\n * When nodes with embedding properties are created, updated, or deleted,\n * these utilities ensure the embeddings table stays in sync.\n */\nimport { type z } from \"zod\";\n\nimport type { AtomicNodeProjection } from \"../backend/capabilities/atomic-mutation-program\";\nimport {\n  type GraphBackend,\n  type NodeInsertProjection,\n  type TransactionBackend,\n} from \"../backend/types\";\nimport {\n  type ResolvedEmbeddingField,\n  resolveEmbeddingFields,\n} from \"../core/embedding\";\nimport { readOwnProperty } from \"../utils/object\";\n\n// ============================================================\n// Types\n// ============================================================\n\n/**\n * Information about an embedding field in a node schema.\n *\n * Re-exports the canonical {@link ResolvedEmbeddingField} so the backend\n * gets `dimensions` plus the resolved index `(metric, indexType)` — all\n * three needed to address the field's typed per-`(kind, field)` storage\n * slot when upserting.\n */\ntype EmbeddingFieldInfo = ResolvedEmbeddingField;\n\n/**\n * Context for embedding sync operations.\n */\nexport type EmbeddingSyncContext = Readonly<{\n  graphId: string;\n  nodeKind: string;\n  nodeId: string;\n  backend: GraphBackend | TransactionBackend;\n}>;\n\ntype EmbeddingProjectionDecision =\n  | Readonly<{ kind: \"upsert\"; embedding: readonly number[] }>\n  | Readonly<{ kind: \"delete\" }>\n  | Readonly<{ kind: \"ignore\" }>;\n\n/** The single owner for how stored embedding values affect projection state. */\nfunction resolveEmbeddingProjectionDecision(\n  value: unknown,\n): EmbeddingProjectionDecision {\n  if (isValidEmbeddingValue(value)) {\n    return { kind: \"upsert\", embedding: value };\n  }\n  return value === undefined ? { kind: \"delete\" } : { kind: \"ignore\" };\n}\n\n// ============================================================\n// Schema Introspection\n// ============================================================\n\n/**\n * Cache keyed by the Zod schema instance. Schemas are immutable at\n * runtime; the same reference recurs across every CRUD call.\n */\nconst embeddingFieldsCache = new WeakMap<\n  z.ZodType,\n  readonly EmbeddingFieldInfo[]\n>();\n\n/**\n * Extracts embedding field information from a Zod schema.\n * Returns all embedding fields found at the top level of an object schema.\n *\n * Thin per-schema-instance memoization over the canonical\n * {@link resolveEmbeddingFields}; the same schema reference recurs across\n * every CRUD call, so caching avoids re-walking the shape each time.\n */\nexport function getEmbeddingFields(\n  schema: z.ZodType,\n): readonly EmbeddingFieldInfo[] {\n  const cached = embeddingFieldsCache.get(schema);\n  if (cached) return cached;\n  const fields = resolveEmbeddingFields(schema);\n  embeddingFieldsCache.set(schema, fields);\n  return fields;\n}\n\n// ============================================================\n// Embedding Sync Operations\n// ============================================================\n\n/**\n * Resolves the present embedding sidecar for a fresh generated-id node.\n * Missing optional values are intentionally omitted because no row can exist\n * for a generated id before this insert. Caller-supplied ids use the regular\n * sync path, which retains its delete semantics for missing values.\n */\nexport function resolveNodeEmbeddingProjections(\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n): readonly NodeInsertProjection[] {\n  return getEmbeddingFields(schema).flatMap(\n    (field): readonly NodeInsertProjection[] => {\n      const value = readOwnProperty(props, field.fieldPath);\n      const decision = resolveEmbeddingProjectionDecision(value);\n      return decision.kind === \"upsert\" ?\n          [\n            {\n              kind: \"embedding\",\n              fieldPath: field.fieldPath,\n              embedding: decision.embedding,\n              dimensions: field.dimensions,\n              metric: field.metric,\n              indexType: field.indexType,\n            },\n          ]\n        : [];\n    },\n  );\n}\n\n/**\n * Resolves every embedding transition owed by a replacement postimage.\n * Unlike fresh generated-id insertion, an absent value is an explicit delete:\n * caller-id resurrection and updates may be replacing an older projection.\n */\nexport function resolveNodeEmbeddingProjectionTransitions(\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n  options?: Readonly<{ omitDeletes?: boolean }>,\n): readonly AtomicNodeProjection[] {\n  return getEmbeddingFields(schema).flatMap(\n    (field): readonly AtomicNodeProjection[] => {\n      const value = readOwnProperty(props, field.fieldPath);\n      const common = {\n        kind: \"embedding\" as const,\n        fieldPath: field.fieldPath,\n        dimensions: field.dimensions,\n        metric: field.metric,\n        indexType: field.indexType,\n      };\n      const decision = resolveEmbeddingProjectionDecision(value);\n      if (decision.kind === \"upsert\") {\n        return [\n          {\n            ...common,\n            action: \"upsert\" as const,\n            embedding: decision.embedding,\n          },\n        ];\n      }\n      return decision.kind === \"delete\" && options?.omitDeletes !== true ?\n          [{ ...common, action: \"delete\" as const }]\n        : [];\n    },\n  );\n}\n\n/**\n * Syncs embeddings after a node create or update operation.\n *\n * For each embedding field in the schema:\n * - If the props contain an embedding value, upsert it to the embeddings table\n * - If the props don't contain an embedding value (undefined), delete any existing embedding\n */\nexport async function syncEmbeddings(\n  ctx: EmbeddingSyncContext,\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n): Promise<void> {\n  const { backend } = ctx;\n\n  // Check if backend supports embedding operations\n  if (!backend.upsertEmbedding || !backend.deleteEmbedding) {\n    return;\n  }\n\n  const embeddingFields = getEmbeddingFields(schema);\n  if (embeddingFields.length === 0) {\n    return;\n  }\n\n  for (const field of embeddingFields) {\n    const value = readOwnProperty(props, field.fieldPath);\n\n    const decision = resolveEmbeddingProjectionDecision(value);\n    if (decision.kind === \"upsert\") {\n      // Upsert the embedding\n      await backend.upsertEmbedding({\n        graphId: ctx.graphId,\n        nodeKind: ctx.nodeKind,\n        nodeId: ctx.nodeId,\n        fieldPath: field.fieldPath,\n        embedding: decision.embedding,\n        dimensions: field.dimensions,\n        metric: field.metric,\n        indexType: field.indexType,\n      });\n    } else if (decision.kind === \"delete\") {\n      // Delete any existing embedding for this field\n      await backend.deleteEmbedding({\n        graphId: ctx.graphId,\n        nodeKind: ctx.nodeKind,\n        nodeId: ctx.nodeId,\n        fieldPath: field.fieldPath,\n        dimensions: field.dimensions,\n        metric: field.metric,\n        indexType: field.indexType,\n      });\n    }\n    // If value is null or invalid, skip (validation should have caught this)\n  }\n}\n\n/**\n * Syncs embeddings for a batch of same-kind node creates through one\n * `upsertEmbeddingBatch` per field (falling back to per-row\n * `upsertEmbedding` when the backend lacks the batch primitive). Mirrors\n * `syncEmbeddings` per row: present values upsert, `undefined` values\n * delete any existing embedding for the field.\n */\nexport async function syncEmbeddingsBatchForKind(\n  args: Readonly<{\n    graphId: string;\n    nodeKind: string;\n    backend: GraphBackend | TransactionBackend;\n  }>,\n  schema: z.ZodType,\n  items: readonly Readonly<{\n    nodeId: string;\n    props: Record<string, unknown>;\n  }>[],\n): Promise<void> {\n  const { graphId, nodeKind, backend } = args;\n  if (!backend.upsertEmbedding || !backend.deleteEmbedding) {\n    return;\n  }\n\n  const embeddingFields = getEmbeddingFields(schema);\n  if (embeddingFields.length === 0) {\n    return;\n  }\n\n  for (const field of embeddingFields) {\n    const rows: { nodeId: string; embedding: readonly number[] }[] = [];\n    const deletionIds: string[] = [];\n    for (const item of items) {\n      const value = readOwnProperty(item.props, field.fieldPath);\n      const decision = resolveEmbeddingProjectionDecision(value);\n      if (decision.kind === \"upsert\") {\n        rows.push({ nodeId: item.nodeId, embedding: decision.embedding });\n      } else if (decision.kind === \"delete\") {\n        deletionIds.push(item.nodeId);\n      }\n    }\n\n    if (rows.length > 0) {\n      if (backend.upsertEmbeddingBatch === undefined) {\n        for (const row of rows) {\n          await backend.upsertEmbedding({\n            graphId,\n            nodeKind,\n            nodeId: row.nodeId,\n            fieldPath: field.fieldPath,\n            embedding: row.embedding,\n            dimensions: field.dimensions,\n            metric: field.metric,\n            indexType: field.indexType,\n          });\n        }\n      } else {\n        await backend.upsertEmbeddingBatch({\n          graphId,\n          nodeKind,\n          fieldPath: field.fieldPath,\n          dimensions: field.dimensions,\n          metric: field.metric,\n          indexType: field.indexType,\n          rows,\n        });\n      }\n    }\n\n    if (deletionIds.length > 0 && backend.deleteEmbeddingBatch !== undefined) {\n      await backend.deleteEmbeddingBatch({\n        graphId,\n        nodeKind,\n        nodeIds: deletionIds,\n        fieldPath: field.fieldPath,\n        dimensions: field.dimensions,\n        metric: field.metric,\n        indexType: field.indexType,\n      });\n    } else {\n      for (const nodeId of deletionIds) {\n        await backend.deleteEmbedding({\n          graphId,\n          nodeKind,\n          nodeId,\n          fieldPath: field.fieldPath,\n          dimensions: field.dimensions,\n          metric: field.metric,\n          indexType: field.indexType,\n        });\n      }\n    }\n  }\n}\n\n/**\n * Deletes a node's embeddings for the embedding fields its kind CURRENTLY\n * declares. A field dropped from the schema after the node was written is\n * intentionally NOT swept here — its entire per-field table is reclaimed\n * wholesale by `store.materializeRemovals()` (the deferred-cleanup verb), which\n * also covers live (never-deleted) nodes' rows. So a hard/soft delete can leave\n * a transient orphan row in a removed field's table until the next reclaim pass;\n * that is the deferred-cleanup design, not a leak.\n */\nexport async function deleteNodeEmbeddings(\n  ctx: EmbeddingSyncContext,\n  schema: z.ZodType,\n): Promise<void> {\n  const { backend } = ctx;\n\n  // Check if backend supports embedding operations\n  if (!backend.deleteEmbedding) {\n    return;\n  }\n\n  const embeddingFields = getEmbeddingFields(schema);\n  if (embeddingFields.length === 0) {\n    return;\n  }\n\n  for (const field of embeddingFields) {\n    await backend.deleteEmbedding({\n      graphId: ctx.graphId,\n      nodeKind: ctx.nodeKind,\n      nodeId: ctx.nodeId,\n      fieldPath: field.fieldPath,\n      dimensions: field.dimensions,\n      metric: field.metric,\n      indexType: field.indexType,\n    });\n  }\n}\n\n// ============================================================\n// Validation Helpers\n// ============================================================\n\n/**\n * Checks if a value is a valid embedding (array of numbers).\n */\nfunction isValidEmbeddingValue(value: unknown): value is readonly number[] {\n  if (!Array.isArray(value)) {\n    return false;\n  }\n  return value.every((n) => typeof n === \"number\" && Number.isFinite(n));\n}\n","/**\n * Keeps the fulltext index in sync with node data. One row per node:\n * the values of every `searchable()` field are concatenated (joined by\n * `\\n`) and stored as the indexed `content`, so a single FTS query can\n * match terms spanning multiple source fields — which a per-field\n * layout cannot, since FTS5 / Postgres MATCH require all terms in one\n * indexed document.\n *\n * Sync runs inline in the node-operation call path, so it inherits the\n * caller's transaction context.\n */\nimport { type z } from \"zod\";\n\nimport { resolveBackendFulltext } from \"../backend/capabilities/fulltext\";\nimport {\n  type GraphBackend,\n  type NodeFulltextSync,\n  type NodeInsertProjection,\n  type TransactionBackend,\n} from \"../backend/types\";\nimport {\n  DEFAULT_SEARCHABLE_LANGUAGE,\n  getSearchableFields,\n  type SearchableFieldInfo,\n} from \"../core/searchable\";\nimport {\n  ConfigurationError,\n  UnsupportedBackendCapabilityError,\n} from \"../errors\";\nimport { readOwnProperty } from \"../utils/object\";\n\nexport { getSearchableFields } from \"../core/searchable\";\n\nexport type FulltextSyncContext = Readonly<{\n  graphId: string;\n  nodeKind: string;\n  nodeId: string;\n  backend: GraphBackend | TransactionBackend;\n}>;\n\nconst FIELD_SEPARATOR = \"\\n\";\n\n/**\n * Refuses with a typed error, rather than silently dropping the write, when\n * a node kind declares `searchable()` fields but `resolveBackendFulltext`\n * reports the backend has no fulltext support at all (`fulltext: false`).\n * Used by `syncFulltext` / `syncFulltextBatchForKind` on the create/update\n * paths, where an unavailable backend cannot honor the write. Deletes are\n * exempt: a fulltext-off backend maintains no sidecar to remove a row\n * from, so `deleteNodeFulltext` succeeds instead of refusing.\n *\n * Exported for the set-based update paths (`executeNodeSetUpdate` /\n * `applyNodeSetUpdate`), which reach the same \"unavailable\" branch ahead of\n * their own batch-member presence checks, and so need the same refusal\n * without duplicating its error shape.\n */\nexport function refuseFulltextUnavailable(\n  backend: GraphBackend | TransactionBackend,\n  nodeKind: string,\n): never {\n  throw new UnsupportedBackendCapabilityError(\n    `Node kind \"${nodeKind}\" declares searchable() fields`,\n    \"fulltext\",\n    { backend: backend.dialect, nodeKind, reason: \"fulltext_unsupported\" },\n    \"This backend declares no fulltext capability. Remove the \" +\n      \"searchable() declaration, or use a backend with fulltext support.\",\n  );\n}\n\n/**\n * Narrows an optional fulltext member to defined. Called only after\n * `resolveBackendFulltext` has already confirmed the backend declares\n * fulltext support, so a member missing at this point is not an\n * availability decision but a backend contract violation — a bundled\n * backend never reaches this, and a third-party one that declares the\n * capability without the member gets a `ConfigurationError` naming exactly\n * which member is missing, not `refuseFulltextUnavailable`'s\n * capability-absent error.\n */\nexport function assertFulltextMember<T>(\n  member: T | undefined,\n  memberName: string,\n  backend: GraphBackend | TransactionBackend,\n): asserts member is T {\n  if (member !== undefined) return;\n  throw new ConfigurationError(\n    `Backend declares a fulltext capability but is missing the \"${memberName}\" member`,\n    {\n      backend: backend.dialect,\n      capability: \"fulltext\",\n      missingMember: memberName,\n    },\n  );\n}\n\n/**\n * Picks a representative language when a node has searchable fields with\n * different language settings. Users who need true per-field\n * multilingual indexing should split the data across node kinds.\n */\nfunction resolveCombinedLanguage(\n  fields: readonly SearchableFieldInfo[],\n): string {\n  return fields[0]?.metadata.language ?? DEFAULT_SEARCHABLE_LANGUAGE;\n}\n\n/**\n * Computes the combined fulltext content for a node, or `undefined`\n * if the node has no non-empty searchable fields.\n *\n * Shared between `syncFulltext` (per-write) and `rebuildFulltextIndex`\n * (bulk) so the two never drift.\n */\nexport function computeFulltextContent(\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n): { content: string; language: string } | undefined {\n  const searchableFields = getSearchableFields(schema);\n  if (searchableFields.length === 0) return undefined;\n\n  const parts: string[] = [];\n  for (const field of searchableFields) {\n    const value = readOwnProperty(props, field.fieldPath);\n    if (typeof value === \"string\" && value.length > 0) {\n      parts.push(value);\n    }\n  }\n  if (parts.length === 0) return undefined;\n\n  return {\n    content: parts.join(FIELD_SEPARATOR),\n    language: resolveCombinedLanguage(searchableFields),\n  };\n}\n\n/**\n * Resolves the complete fulltext side effect for one node row.\n * `undefined` means the schema has no searchable fields; an explicit delete\n * keeps an all-empty searchable row from being mistaken for no projection.\n */\nexport function resolveNodeFulltextProjection(\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n): Extract<NodeInsertProjection, { kind: \"fulltext\" }> | undefined {\n  if (getSearchableFields(schema).length === 0) return undefined;\n  const computed = computeFulltextContent(schema, props);\n  return computed === undefined ?\n      { kind: \"fulltext\", action: \"delete\" }\n    : { kind: \"fulltext\", action: \"upsert\", ...computed };\n}\n\n/** Resolves the ordinary identity-carrying fulltext synchronization input. */\nfunction resolveNodeFulltextSync(\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n  identity: Readonly<{\n    graphId: string;\n    nodeKind: string;\n    nodeId: string;\n  }>,\n): NodeFulltextSync | undefined {\n  if (getSearchableFields(schema).length === 0) return undefined;\n  const computed = computeFulltextContent(schema, props);\n  return computed === undefined ?\n      { ...identity, action: \"delete\" }\n    : { ...identity, action: \"upsert\", ...computed };\n}\n\n/**\n * Syncs the fulltext index row after a node create or update.\n *\n * Concatenates the values of all searchable fields into a single content\n * string and upserts it. If every field is empty / undefined, deletes\n * any existing row for the node.\n */\nexport async function syncFulltext(\n  ctx: FulltextSyncContext,\n  schema: z.ZodType,\n  props: Record<string, unknown>,\n): Promise<void> {\n  const { backend } = ctx;\n\n  if (getSearchableFields(schema).length === 0) return;\n\n  // `resolveBackendFulltext` is the one decision for \"is fulltext\n  // available on this backend\"; a missing member past that point is a\n  // contract violation asserted separately below, never re-derived here.\n  if (resolveBackendFulltext(backend) === false) {\n    refuseFulltextUnavailable(backend, ctx.nodeKind);\n  }\n  assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n  assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n  const sync = resolveNodeFulltextSync(schema, props, ctx);\n  if (sync?.action === \"upsert\") {\n    await backend.upsertFulltext({\n      graphId: ctx.graphId,\n      nodeKind: ctx.nodeKind,\n      nodeId: ctx.nodeId,\n      content: sync.content,\n      language: sync.language,\n    });\n    return;\n  }\n  if (sync === undefined) return;\n  await backend.deleteFulltext({\n    graphId: ctx.graphId,\n    nodeKind: ctx.nodeKind,\n    nodeId: ctx.nodeId,\n  });\n}\n\n/**\n * Syncs the fulltext rows for a batch of same-kind node creates through\n * one `upsertFulltextBatch` call (falling back to per-row `upsertFulltext`\n * when the backend lacks the batch primitive). Mirrors `syncFulltext`\n * per row: computed content upserts, empty content deletes any stale row\n * when the schema declares searchable fields.\n */\nexport async function syncFulltextBatchForKind(\n  args: Readonly<{\n    graphId: string;\n    nodeKind: string;\n    backend: GraphBackend | TransactionBackend;\n  }>,\n  schema: z.ZodType,\n  items: readonly Readonly<{\n    nodeId: string;\n    props: Record<string, unknown>;\n  }>[],\n): Promise<void> {\n  const { graphId, nodeKind, backend } = args;\n  if (getSearchableFields(schema).length === 0) return;\n\n  // `resolveBackendFulltext` is the one decision for \"is fulltext\n  // available on this backend\"; a missing member past that point is a\n  // contract violation asserted separately below, never re-derived here.\n  if (resolveBackendFulltext(backend) === false) {\n    refuseFulltextUnavailable(backend, nodeKind);\n  }\n  assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n  assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n  // The bail-out above guarantees the schema has searchable fields for\n  // every remaining line, so an item with no computed content always\n  // means \"clear its row\" rather than \"not applicable\".\n  const rows: { nodeId: string; content: string; language: string }[] = [];\n  const emptyContentIds: string[] = [];\n  for (const item of items) {\n    const computed = computeFulltextContent(schema, item.props);\n    if (computed === undefined) {\n      emptyContentIds.push(item.nodeId);\n    } else {\n      rows.push({\n        nodeId: item.nodeId,\n        content: computed.content,\n        language: computed.language,\n      });\n    }\n  }\n\n  if (rows.length > 0) {\n    if (backend.upsertFulltextBatch === undefined) {\n      for (const row of rows) {\n        await backend.upsertFulltext({\n          graphId,\n          nodeKind,\n          nodeId: row.nodeId,\n          content: row.content,\n          language: row.language,\n        });\n      }\n    } else {\n      await backend.upsertFulltextBatch({ graphId, nodeKind, rows });\n    }\n  }\n\n  if (emptyContentIds.length > 0) {\n    if (backend.deleteFulltextBatch === undefined) {\n      for (const nodeId of emptyContentIds) {\n        await backend.deleteFulltext({ graphId, nodeKind, nodeId });\n      }\n    } else {\n      await backend.deleteFulltextBatch({\n        graphId,\n        nodeKind,\n        nodeIds: emptyContentIds,\n      });\n    }\n  }\n}\n\n/**\n * Deletes the fulltext row for a node.\n * Called on soft-delete; hard-delete is handled by the backend cascade.\n */\nexport async function deleteNodeFulltext(\n  ctx: FulltextSyncContext,\n  schema: z.ZodType,\n): Promise<void> {\n  const { backend } = ctx;\n\n  if (getSearchableFields(schema).length === 0) return;\n\n  // Unlike `syncFulltext`, an unavailable backend does not refuse here: a\n  // delete removes data rather than accepting a write the backend cannot\n  // index, and this backend maintains no fulltext sidecar to issue that\n  // removal against, so the delete is a no-op rather than a refusal. If\n  // fulltext was active before this backend was reconfigured with\n  // `fulltext: false`, an existing row is left in place, unmaintained.\n  if (resolveBackendFulltext(backend) === false) return;\n\n  assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n\n  await backend.deleteFulltext({\n    graphId: ctx.graphId,\n    nodeKind: ctx.nodeKind,\n    nodeId: ctx.nodeId,\n  });\n}\n","/**\n * Composable node write steps — the integrity side effects that every node\n * mutation must apply, extracted so there is a single implementation instead of\n * one hand-stitched copy per write path.\n *\n * A node mutation is the core row write plus a fixed set of side effects:\n * uniqueness entries, embedding sync, fulltext sync, and — for deletes —\n * delete-behavior enforcement over connected edges. These steps are shared by\n * the canonical collection operations (create / update / delete) and by\n * provenance retraction, which drives the same close/reopen of a fact node's\n * currency but skips delete-behavior enforcement so every connected edge\n * survives for a later reopen.\n *\n * The steps assume they run inside a write transaction (see\n * {@link runInWriteTransaction}); they perform no transaction management of\n * their own.\n */\nimport { type z } from \"zod\";\n\nimport { bindExtraIfReachable } from \"../../backend/capabilities/bind\";\nimport { UNIQUE_SIDECAR_BATCH } from \"../../backend/capabilities/bundle-registry\";\nimport { resolveBackendFulltext } from \"../../backend/capabilities/fulltext\";\nimport {\n  type BundleVerdictOf,\n  type ClaimsVerdictThunk,\n  missingRequiredExtras,\n} from \"../../backend/capabilities/resolve\";\nimport {\n  type GraphBackend,\n  type LiveNodeRow,\n  type NodePropertyExpectation,\n  type NodeRow,\n  type ResolvedNodeUpdateBatchEntry,\n  rowPropsToObject,\n  type TombstonedNodeRow,\n  type TransactionBackend,\n  type UpdateNodeSetResult,\n} from \"../../backend/types\";\nimport {\n  type DeleteBehavior,\n  type JsonValue,\n  type UniqueConstraint,\n} from \"../../core/types\";\nimport {\n  ConfigurationError,\n  RestrictedDeleteError,\n  ValidationError,\n} from \"../../errors\";\nimport { validateNodeProps } from \"../../errors/validation\";\nimport type { CompiledSelectSql } from \"../../query/sql-intent\";\nimport { type KindRegistry } from \"../../registry/kind-registry\";\nimport { canonicalEqual } from \"../../schema/canonical\";\nimport { assertsStoredLowerBound } from \"../../utils/date\";\nimport { purgeEdgeClaims } from \"../claims/edge-claims\";\nimport {\n  alreadyAppliedRowWrite,\n  createUniquenessContext,\n  deleteUniquenessEntries,\n  hardDeleteClaimsByNodeIds,\n  type NodeClaimContext,\n  planNodeClaimReinsert,\n  planNodeClaimUpdate,\n  type UniquenessUpdatePlan,\n  withNodeClaimTransition,\n  withNodeCreateClaimsBatch,\n} from \"../claims/node-claims\";\nimport {\n  resolvedNodeUniqueSidecarBatchIsReachable,\n  validateResolvedNodeClaims,\n} from \"../claims/resolved-node-claims\";\nimport {\n  deleteNodeEmbeddings,\n  getEmbeddingFields,\n  syncEmbeddings,\n  syncEmbeddingsBatchForKind,\n} from \"../embedding-sync\";\nimport {\n  assertFulltextMember,\n  deleteNodeFulltext,\n  getSearchableFields,\n  refuseFulltextUnavailable,\n  syncFulltext,\n  syncFulltextBatchForKind,\n} from \"../fulltext-sync\";\nimport { type GraphWriteLock } from \"../recorded-capture/clock\";\n\ntype Backend = GraphBackend | TransactionBackend;\n\n/**\n * The graph-scoped state the node write steps need. `lock` is compile-time\n * evidence that the per-graph write-lock discipline was satisfied BEFORE any\n * row work (see {@link GraphWriteLock}): the pipeline performs no locking of\n * its own, so requiring the token here makes \"sidecar write before lock\" a\n * type error at the call site instead of a lock-order inversion in review.\n *\n * It is the claim seam's context by definition rather than by coincidence: a\n * write path hands the same value to {@link withNodeCreateClaims} and to the\n * sync fans, so the two halves of one insert cannot be given different graphs,\n * registries, or lock evidence.\n */\nexport type NodeWriteContext = NodeClaimContext;\n\n/** Builds a {@link NodeWriteContext} — the one constructor every call site shares. */\nexport function createNodeWriteContext(\n  graphId: string,\n  registry: KindRegistry,\n  lock: GraphWriteLock,\n  claimsVerdict: ClaimsVerdictThunk,\n  uniqueSidecarBatch: BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH>,\n): NodeWriteContext {\n  return { graphId, registry, lock, claimsVerdict, uniqueSidecarBatch };\n}\n\n/** Whether a delete removes the node (`hard`) or tombstones it (`soft`). */\ntype NodeDeleteMode = \"soft\" | \"hard\";\n\n/**\n * Tunes how a delete treats the node's connected edges.\n *\n * By default delete behavior is enforced: connected edges block a `restrict`\n * node and are removed under `cascade` / `disconnect`. Provenance retraction\n * passes `enforceDeleteBehavior: false` — closing a fact's currency is a\n * belief-status change, not a domain delete, so its edges neither block the\n * close nor get removed; they survive untouched so a later reopen is an exact\n * inverse.\n */\nexport type NodeDeletePolicy = Readonly<{\n  enforceDeleteBehavior: boolean;\n}>;\n\nfunction uniquenessContext(ctx: NodeWriteContext, backend: Backend) {\n  return createUniquenessContext(\n    ctx.graphId,\n    ctx.registry,\n    backend,\n    ctx.uniqueSidecarBatch,\n  );\n}\n\n/**\n * The `(graphId, nodeKind, nodeId, backend)` context shared by the embedding and\n * fulltext sync helpers — `EmbeddingSyncContext` and `FulltextSyncContext` are\n * structurally identical, so one builder serves both.\n */\nfunction nodeSyncContext(\n  ctx: NodeWriteContext,\n  kind: string,\n  id: string,\n  backend: Backend,\n) {\n  return { graphId: ctx.graphId, nodeKind: kind, nodeId: id, backend };\n}\n\n/**\n * Enforces a node's delete behavior against its connected edges: they block\n * the delete (`restrict`) or are removed alongside the node (`cascade` /\n * `disconnect`). Skipped entirely when the caller's {@link NodeDeletePolicy}\n * disables enforcement.\n */\nasync function enforceNodeDeleteBehavior(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    kind: string;\n    id: string;\n    mode: NodeDeleteMode;\n    onDelete: DeleteBehavior | undefined;\n  }>,\n  backend: Backend,\n  policy?: NodeDeletePolicy,\n): Promise<void> {\n  if (policy?.enforceDeleteBehavior === false) return;\n  const behavior = args.onDelete ?? \"restrict\";\n  const connectedEdges = await backend.findEdgesConnectedTo({\n    graphId: ctx.graphId,\n    nodeKind: args.kind,\n    nodeId: args.id,\n  });\n\n  if (connectedEdges.length === 0) return;\n\n  switch (behavior) {\n    case \"restrict\": {\n      throw new RestrictedDeleteError({\n        nodeKind: args.kind,\n        nodeId: args.id,\n        edgeCount: connectedEdges.length,\n        edgeKinds: [...new Set(connectedEdges.map((edge) => edge.kind))],\n      });\n    }\n\n    case \"cascade\":\n    case \"disconnect\": {\n      // Both behaviors remove connected edges. \"cascade\" signals intent to\n      // remove dependent data; \"disconnect\" signals intent to sever the\n      // relationship. The effect is identical because edges cannot exist\n      // without both endpoints. One batched statement per bind-budget\n      // chunk instead of one statement per edge; the per-edge loop remains\n      // for backends without the batch members.\n      const connectedEdgeIds = connectedEdges.map((edge) => edge.id);\n      const batchDelete =\n        args.mode === \"hard\" ?\n          backend.hardDeleteEdgesBatch\n        : backend.deleteEdgesBatch;\n      if (batchDelete === undefined) {\n        for (const edge of connectedEdges) {\n          await (args.mode === \"hard\" ?\n            backend.hardDeleteEdge({ graphId: ctx.graphId, id: edge.id })\n          : backend.deleteEdge({ graphId: ctx.graphId, id: edge.id }));\n        }\n      } else {\n        await batchDelete({\n          graphId: ctx.graphId,\n          ids: connectedEdgeIds,\n        });\n      }\n      // Hard-deleted holders are already takeable through the liveness probe;\n      // this is housekeeping so node cascades do not grow edgeClaims forever.\n      // Soft-deleted edges retain their rows for resurrection and are not\n      // reaped here.\n      if (args.mode === \"hard\") {\n        await purgeEdgeClaims(\n          backend,\n          ctx.claimsVerdict(),\n          ctx.graphId,\n          connectedEdgeIds,\n        );\n      }\n      break;\n    }\n  }\n}\n\n/** One inserted row, as the post-insert sync fans read it. */\nexport type NodeInsertSyncItem = Readonly<{\n  kind: string;\n  id: string;\n  schema: z.ZodType;\n  props: Record<string, unknown>;\n  uniqueConstraints: readonly UniqueConstraint[];\n  /** True only when the fused node statement wrote every requested projection. */\n  projectionsFused?: boolean;\n}>;\n\n/**\n * The sync fans that follow a node insert: embedding and fulltext.\n *\n * The claims this row owes are NOT here. They are issued by\n * {@link withNodeCreateClaims}, on the two sides of the insert their placement\n * names — a claim that is the only fence for its axis has to precede the row it\n * gates, and a function that runs entirely after the insert cannot issue one.\n * The fans have no such constraint: they are derived data, they fence nothing,\n * and they stay where they have always been.\n */\nexport async function applyNodeInsertSyncFans(\n  ctx: NodeWriteContext,\n  args: NodeInsertSyncItem,\n  backend: Backend,\n): Promise<void> {\n  const syncContext = nodeSyncContext(ctx, args.kind, args.id, backend);\n  if (args.projectionsFused === true) return;\n  await Promise.all([\n    syncEmbeddings(syncContext, args.schema, args.props),\n    syncFulltext(syncContext, args.schema, args.props),\n  ]);\n}\n\n/**\n * Batched {@link applyNodeInsertSyncFans}: one embedding batch per (kind,\n * field) and one fulltext batch per kind, instead of the per-row statement fan\n * the single-op path issues.\n */\nexport async function applyNodeInsertSyncFansBatch(\n  ctx: NodeWriteContext,\n  items: readonly NodeInsertSyncItem[],\n  backend: Backend,\n): Promise<void> {\n  if (items.length === 0) return;\n\n  interface KindGroup {\n    schema: z.ZodType;\n    rows: { nodeId: string; props: Record<string, unknown> }[];\n  }\n  const byKind = new Map<string, KindGroup>();\n  for (const item of items) {\n    const group = byKind.get(item.kind) ?? { schema: item.schema, rows: [] };\n    group.rows.push({ nodeId: item.id, props: item.props });\n    byKind.set(item.kind, group);\n  }\n\n  await Promise.all(\n    [...byKind.entries()].flatMap(([kind, group]) => {\n      const syncArguments = { graphId: ctx.graphId, nodeKind: kind, backend };\n      return [\n        syncEmbeddingsBatchForKind(syncArguments, group.schema, group.rows),\n        syncFulltextBatchForKind(syncArguments, group.schema, group.rows),\n      ];\n    }),\n  );\n}\n\nfunction parseRowProps(row: NodeRow): Record<string, unknown> {\n  return rowPropsToObject(row.props);\n}\n\n/**\n * The row a node update targets. A plain update runs live-row side effects\n * (uniqueness diff, embedding/fulltext sync), so it must be handed a\n * {@link LiveNodeRow}; only an explicit `clearDeleted: true` resurrecting\n * upsert may target a possibly-tombstoned row. Encoding the pairing as a\n * union makes \"live-row update pipeline on a tombstoned row\" a type error.\n */\nexport type NodeUpdateTarget =\n  | Readonly<{ existing: LiveNodeRow; clearDeleted?: false }>\n  | Readonly<{ existing: NodeRow; clearDeleted: true }>;\n\n/**\n * Decides a node update's uniqueness transition, writing nothing.\n *\n * Two shapes behind one seam. A live row diffs its old and new keys; a\n * resurrecting update (`clearDeleted` on a tombstoned row) cannot, because the\n * soft delete already removed its entries — the diff would skip an unchanged\n * key and leave the resurrected node holding NO reservation, so a later create\n * could silently duplicate the value. It re-reserves every applying key\n * instead. Both refuse a conflict before returning, and both hand the caller a\n * plan that only {@link withNodeClaimTransition} may carry out.\n */\nasync function planNodeUpdateUniqueness(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    existing: NodeRow;\n    validatedProps: Record<string, unknown>;\n    uniqueConstraints: readonly UniqueConstraint[];\n  }>,\n  backend: Backend,\n): Promise<UniquenessUpdatePlan> {\n  const { kind, id } = args.existing;\n\n  if (args.existing.deleted_at !== undefined) {\n    return planNodeClaimReinsert(\n      uniquenessContext(ctx, backend),\n      kind,\n      id,\n      args.validatedProps,\n      args.uniqueConstraints,\n    );\n  }\n\n  return planNodeClaimUpdate(\n    uniquenessContext(ctx, backend),\n    kind,\n    id,\n    parseRowProps(args.existing),\n    args.validatedProps,\n    args.uniqueConstraints,\n  );\n}\n\n/**\n * Applies a node update: uniqueness maintenance (diff-based for a live row;\n * check-and-reinsert for a resurrecting update, whose entries the soft delete\n * removed), the core row update, then embedding and fulltext sync. Returns\n * the updated row.\n *\n * ## The row write and its uniqueness transition are ONE unit\n *\n * Both can fail — the row write matches nothing when `expectedValidFrom` or the\n * `deleted_at` fence stopped holding, the uniqueness claim loses a race for a\n * key — and a caller that catches either PER ROW and commits the rest of the\n * transaction (interchange import) must never be left with half of the pair\n * applied. {@link withNodeClaimTransition} owns that sequencing and documents\n * why claim/gate/release is the only order that works; this function just hands\n * it the plan and the write.\n *\n * The embedding and fulltext syncs stay AFTER the gate: they are derived data\n * with no claim to make, so a row write that lands on nothing must not rewrite\n * a fulltext row or re-embed props no row ever received.\n */\nexport async function applyNodeUpdate(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    schema: z.ZodType;\n    validatedProps: Record<string, unknown>;\n    uniqueConstraints: readonly UniqueConstraint[];\n    validFrom?: string | null;\n    validTo?: string;\n    clearValidTo?: true;\n    /** See {@link UpdateNodeParams.expectedValidFrom}. */\n    expectedValidFrom?: string | null;\n  }> &\n    NodeUpdateTarget,\n  backend: Backend,\n): Promise<NodeRow> {\n  const { kind, id } = args.existing;\n\n  // Read-only phase: decide the sidecar changes, refuse a conflict, write\n  // nothing.\n  const plan = await planNodeUpdateUniqueness(\n    ctx,\n    {\n      existing: args.existing,\n      validatedProps: args.validatedProps,\n      uniqueConstraints: args.uniqueConstraints,\n    },\n    backend,\n  );\n\n  const updateParams: {\n    graphId: string;\n    kind: string;\n    id: string;\n    props: Record<string, unknown>;\n    validFrom?: string | null;\n    expectedValidFrom?: string | null;\n    incrementVersion?: boolean;\n    clearDeleted?: boolean;\n  } = {\n    graphId: ctx.graphId,\n    kind,\n    id,\n    props: args.validatedProps,\n    incrementVersion: true,\n  };\n  if (args.validFrom !== undefined) updateParams.validFrom = args.validFrom;\n  // `assertsStoredLowerBound` owns \"does this fence state anything?\" — the same\n  // predicate the fence appliers consult, so the step that CARRIES the fence\n  // and the seam that VALIDATES it cannot disagree about what an empty fence is.\n  if (assertsStoredLowerBound(args)) {\n    updateParams.expectedValidFrom = args.expectedValidFrom;\n  }\n  if (args.clearDeleted) updateParams.clearDeleted = true;\n\n  const row = await withNodeClaimTransition(\n    uniquenessContext(ctx, backend),\n    kind,\n    id,\n    plan,\n    () =>\n      backend.updateNode({\n        ...updateParams,\n        ...(args.clearValidTo === true ? { clearValidTo: true as const }\n        : args.validTo === undefined ? {}\n        : { validTo: args.validTo }),\n      }),\n  );\n\n  await Promise.all([\n    syncEmbeddings(\n      nodeSyncContext(ctx, kind, id, backend),\n      args.schema,\n      args.validatedProps,\n    ),\n    syncFulltext(\n      nodeSyncContext(ctx, kind, id, backend),\n      args.schema,\n      args.validatedProps,\n    ),\n  ]);\n\n  return row;\n}\n\n/**\n * Applies distinct, already-resolved live-node replacements as one row write,\n * then rebuilds the same claim and projection fans as a set update. Returning\n * `undefined` is the portable version-gate miss: callers re-read and recover\n * through the established per-row race semantics rather than treating it as a\n * partial success.\n */\nexport async function applyResolvedNodeUpdateBatch(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    schema: z.ZodType<Record<string, unknown>>;\n    uniqueConstraints: readonly UniqueConstraint[];\n    entries: readonly ResolvedNodeUpdateBatchEntry[];\n  }>,\n  backend: Backend,\n): Promise<readonly NodeRow[] | undefined> {\n  if (\n    args.uniqueConstraints.length > 0 &&\n    !resolvedNodeUniqueSidecarBatchIsReachable(uniquenessContext(ctx, backend))\n  ) {\n    throw new ConfigurationError(\n      \"Resolved node writes require batched uniqueness operations\",\n      { code: \"RESOLVED_NODE_UNIQUENESS_UNSUPPORTED\" },\n    );\n  }\n  const updateResolvedNodesBatch = backend.updateResolvedNodesBatch;\n  if (updateResolvedNodesBatch === undefined) return;\n  const rows = await updateResolvedNodesBatch({ entries: args.entries });\n  if (rows.length === 0) return;\n  if (rows.length !== args.entries.length) {\n    throw new ConfigurationError(\n      \"Resolved node update batch returned a partial result\",\n      { operation: \"updateResolvedNodesBatch\" },\n    );\n  }\n  const entriesById = new Map(\n    args.entries.map((entry) => [entry.id, entry] as const),\n  );\n  const items = rows.map((row) => {\n    const entry = entriesById.get(row.id);\n    if (entry?.kind !== row.kind) {\n      throw new ConfigurationError(\n        \"Resolved node update batch returned an unexpected row\",\n        { operation: \"updateResolvedNodesBatch\", rowId: row.id },\n      );\n    }\n    const props = rowPropsToObject(row.props);\n    if (!canonicalEqual(entry.props, props)) {\n      throw new ConfigurationError(\n        \"Resolved node update batch returned props that differ from its input\",\n        { operation: \"updateResolvedNodesBatch\", rowId: row.id },\n      );\n    }\n    return {\n      kind: row.kind,\n      id: row.id,\n      props,\n      constraints: args.uniqueConstraints,\n      uniqueConstraints: args.uniqueConstraints,\n      schema: args.schema,\n    };\n  });\n  if (args.uniqueConstraints.length > 0) {\n    await validateResolvedNodeClaims(\n      createUniquenessContext(\n        ctx.graphId,\n        ctx.registry,\n        backend,\n        ctx.uniqueSidecarBatch,\n      ),\n      items,\n      [],\n    );\n    await hardDeleteClaimsByNodeIds(\n      uniquenessContext(ctx, backend),\n      items[0]?.kind ?? \"\",\n      items.map((item) => item.id),\n    );\n  }\n  await withNodeCreateClaimsBatch(ctx, items, backend, alreadyAppliedRowWrite);\n  await applyNodeInsertSyncFansBatch(ctx, items, backend);\n  return rows;\n}\n\n/**\n * Applies a node soft delete: delete-behavior enforcement, the tombstone\n * write, then removal of uniqueness entries, embeddings, and fulltext.\n * Requires a {@link LiveNodeRow}: deleting an already-tombstoned row would\n * re-run sidecar cleanup against entries the first delete already removed.\n */\nexport async function applyNodeSoftDelete(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    existing: LiveNodeRow;\n    schema: z.ZodType;\n    uniqueConstraints: readonly UniqueConstraint[];\n    onDelete: DeleteBehavior | undefined;\n  }>,\n  backend: Backend,\n  policy?: NodeDeletePolicy,\n): Promise<void> {\n  const { kind, id } = args.existing;\n  await enforceNodeDeleteBehavior(\n    ctx,\n    { kind, id, mode: \"soft\", onDelete: args.onDelete },\n    backend,\n    policy,\n  );\n  await backend.deleteNode({\n    graphId: ctx.graphId,\n    kind,\n    id,\n  });\n  await deleteUniquenessEntries(\n    uniquenessContext(ctx, backend),\n    kind,\n    id,\n    parseRowProps(args.existing),\n    args.uniqueConstraints,\n  );\n  await deleteNodeEmbeddings(\n    nodeSyncContext(ctx, kind, id, backend),\n    args.schema,\n  );\n  await deleteNodeFulltext(\n    nodeSyncContext(ctx, kind, id, backend),\n    args.schema,\n  );\n}\n\n/**\n * Applies a node hard delete: delete-behavior enforcement, permanent removal,\n * then embedding cleanup. Uniqueness and fulltext rows are removed by the\n * backend's `hardDeleteNode` cascade; embeddings live in strategy-owned\n * per-`(kind, field)` tables the graph-agnostic cascade cannot reach, so they\n * are cleaned here.\n */\nexport async function applyNodeHardDelete(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    kind: string;\n    id: string;\n    schema: z.ZodType;\n    onDelete: DeleteBehavior | undefined;\n  }>,\n  backend: Backend,\n): Promise<void> {\n  await enforceNodeDeleteBehavior(\n    ctx,\n    { kind: args.kind, id: args.id, mode: \"hard\", onDelete: args.onDelete },\n    backend,\n  );\n  await backend.hardDeleteNode({\n    graphId: ctx.graphId,\n    kind: args.kind,\n    id: args.id,\n  });\n  await deleteNodeEmbeddings(\n    nodeSyncContext(ctx, args.kind, args.id, backend),\n    args.schema,\n  );\n}\n\n/**\n * Reopens a soft-deleted node with its stored props (no merge, no\n * re-validation): re-checks and re-inserts uniqueness entries (the delete\n * removed them), clears the tombstone, then re-syncs embeddings and fulltext.\n * Used by provenance to reinstate a fact whose currency is restored. Returns\n * the reopened row.\n *\n * @throws {UniquenessError} when a unique key the node held was taken by\n *   another node while it was tombstoned.\n */\nexport async function applyNodeResurrect(\n  ctx: NodeWriteContext,\n  args: Readonly<{\n    existing: TombstonedNodeRow;\n    schema: z.ZodType;\n    uniqueConstraints: readonly UniqueConstraint[];\n  }>,\n  backend: Backend,\n): Promise<NodeRow> {\n  const { kind, id } = args.existing;\n  const props = parseRowProps(args.existing);\n  // One unit, exactly as `applyNodeUpdate`, and for the same reason: the\n  // resurrecting UPDATE carries `deleted_at IS NOT NULL`, so a peer that revived\n  // this tombstone first makes it match zero rows — and the reservations that\n  // revival is entitled to are the peer's, not this caller's.\n  // `withNodeClaimTransition` gives them back when the gate refuses.\n  const plan = await planNodeClaimReinsert(\n    uniquenessContext(ctx, backend),\n    kind,\n    id,\n    props,\n    args.uniqueConstraints,\n  );\n  const row = await withNodeClaimTransition(\n    uniquenessContext(ctx, backend),\n    kind,\n    id,\n    plan,\n    () =>\n      backend.updateNode({\n        graphId: ctx.graphId,\n        kind,\n        id,\n        props,\n        incrementVersion: true,\n        clearDeleted: true,\n      }),\n  );\n  await Promise.all([\n    syncEmbeddings(nodeSyncContext(ctx, kind, id, backend), args.schema, props),\n    syncFulltext(nodeSyncContext(ctx, kind, id, backend), args.schema, props),\n  ]);\n  return row;\n}\n\n/**\n * The inputs of one set-based node update: the patch the statement applies and\n * the candidate query that selects the rows it applies to.\n *\n * There is no fence field. `UpdateNodeSetParams` has no `expectedValidFrom`,\n * so a validity lower bound cannot be carried here — it is refused by\n * `NODE_SET_UPDATE_FENCE_APPLIERS` before this step is reached, rather than\n * accepted into a record that would quietly drop it.\n */\ntype NodeSetUpdateCommonWork = Readonly<{\n  kind: string;\n  schema: z.ZodType<Record<string, unknown>>;\n  uniqueConstraints: readonly UniqueConstraint[];\n  patch: Readonly<Record<string, JsonValue>>;\n  unsetProperties: readonly string[];\n  candidateIds: CompiledSelectSql;\n  candidateIdColumn: string;\n}>;\n\nexport type NodeSetUpdateWork = NodeSetUpdateCommonWork &\n  (\n    | Readonly<{ operation: \"updateWhere\" }>\n    | Readonly<{\n        operation: \"compareAndSet\";\n        expected: Readonly<Record<string, NodePropertyExpectation>>;\n      }>\n  );\n\n/** What a set update reports: how many live rows it rewrote. */\nexport type NodeSetUpdateResult = Readonly<{ affectedCount: number }>;\n\n/**\n * Applies a set-based node update: one UPDATE over every candidate row, then a\n * full rebuild of the sidecars those after-images oblige.\n *\n * ## Why the capability refusals are HERE and not at the entry point\n *\n * The caller probes the backend it was handed before opening the transaction;\n * these four probe the transaction target, which is a different object — a\n * backend may hand out a transaction handle that implements less than the\n * top-level one. They keep the entry point's error codes, so a caller that\n * refuses before the transaction and one that refuses inside it report the\n * same class.\n *\n * ## Why the order is row -> probe -> drop -> re-claim\n *\n * Unlike every other node write, the uniqueness claim happens AFTER the row\n * write: the statement rewrites whole rows without reading their before-images,\n * so the keys to release are not knowable until the after-images come back.\n * The cross-kind re-check below is what makes that safe — it re-probes every\n * changed key across the constraint's scope and refuses the whole transaction\n * before a single entry is dropped. The per-graph write fence (which a\n * shared-scope constraint forces this write to take) is what keeps a concurrent\n * claim from landing between the probe and the reinsert.\n */\nexport async function applyNodeSetUpdate(\n  ctx: NodeWriteContext,\n  args: NodeSetUpdateWork,\n  backend: Backend,\n): Promise<NodeSetUpdateResult> {\n  const { kind, schema, uniqueConstraints } = args;\n  const commonParams = {\n    graphId: ctx.graphId,\n    kind,\n    patch: args.patch,\n    unsetProperties: args.unsetProperties,\n    candidateIds: args.candidateIds,\n    candidateIdColumn: args.candidateIdColumn,\n  } as const;\n  let executeNodeSetUpdate: () => Promise<UpdateNodeSetResult>;\n  if (args.operation === \"compareAndSet\") {\n    const compareAndSetNode = backend.compareAndSetNode;\n    if (compareAndSetNode === undefined) {\n      throw new ConfigurationError(\n        \"The transaction backend does not support node compare-and-set\",\n        { code: \"COMPARE_AND_SET_UNSUPPORTED\", kind },\n      );\n    }\n    executeNodeSetUpdate = () =>\n      compareAndSetNode({\n        ...commonParams,\n        operation: \"compareAndSet\",\n        expected: args.expected,\n      });\n  } else {\n    const updateNodeSet = backend.updateNodeSet;\n    if (updateNodeSet === undefined) {\n      throw new ConfigurationError(\n        \"The transaction backend does not support set-based node updates\",\n        { code: \"SET_UPDATE_UNSUPPORTED\", kind },\n      );\n    }\n    executeNodeSetUpdate = () =>\n      updateNodeSet({ ...commonParams, operation: \"updateWhere\" });\n  }\n  if (\n    uniqueConstraints.length > 0 &&\n    missingRequiredExtras(\n      UNIQUE_SIDECAR_BATCH,\n      ctx.uniqueSidecarBatch,\n      \"set-based node update\",\n    ).length > 0\n  ) {\n    throw new ConfigurationError(\n      \"The transaction backend lacks batched uniqueness operations\",\n      { code: \"SET_UPDATE_UNIQUENESS_UNSUPPORTED\", kind },\n    );\n  }\n  if (getSearchableFields(schema).length > 0) {\n    // A fulltext-off backend (`resolveBackendFulltext` returns `false`) gets\n    // the same typed capability refusal every other fulltext entry point\n    // raises, rather than the member-presence assertions below — those are\n    // for a backend that DOES have fulltext but lacks one of the four\n    // members the write plan calls, mirroring the batched-uniqueness and\n    // batched-vector checks around it.\n    if (resolveBackendFulltext(backend) === false) {\n      refuseFulltextUnavailable(backend, kind);\n    }\n    // Fulltext is available, so a missing batch member here is not an\n    // availability decision but a backend contract violation — the same\n    // invariant `syncFulltextBatchForKind` asserts on its own members.\n    assertFulltextMember(backend.upsertFulltext, \"upsertFulltext\", backend);\n    assertFulltextMember(backend.deleteFulltext, \"deleteFulltext\", backend);\n    assertFulltextMember(\n      backend.upsertFulltextBatch,\n      \"upsertFulltextBatch\",\n      backend,\n    );\n    assertFulltextMember(\n      backend.deleteFulltextBatch,\n      \"deleteFulltextBatch\",\n      backend,\n    );\n  }\n  if (\n    getEmbeddingFields(schema).length > 0 &&\n    (backend.upsertEmbedding === undefined ||\n      backend.deleteEmbedding === undefined ||\n      backend.upsertEmbeddingBatch === undefined ||\n      backend.deleteEmbeddingBatch === undefined)\n  ) {\n    throw new ConfigurationError(\n      \"The transaction backend lacks batched vector operations\",\n      { code: \"SET_UPDATE_VECTOR_UNSUPPORTED\", kind },\n    );\n  }\n  const result = await executeNodeSetUpdate();\n  if (result.affectedCount === 0) return { affectedCount: 0 };\n\n  const sidecarItems = result.rows.map((row) => {\n    const props = rowPropsToObject(row.props);\n    const validatedProps = validateNodeProps(schema, props, {\n      kind,\n      operation: \"update\",\n      id: row.id,\n    });\n    if (!canonicalEqual(validatedProps, props)) {\n      throw new ValidationError(\n        `Set update would persist a non-canonical ${kind} row`,\n        {\n          entityType: \"node\",\n          kind,\n          operation: \"update\",\n          id: row.id,\n          issues: [\n            {\n              path: \"props\",\n              message: \"The complete row requires schema normalization\",\n            },\n          ],\n        },\n      );\n    }\n    return {\n      kind,\n      id: row.id,\n      schema,\n      props: validatedProps,\n      uniqueConstraints,\n    };\n  });\n\n  const claimItems = sidecarItems.map((item) => ({\n    kind: item.kind,\n    id: item.id,\n    props: item.props,\n    constraints: item.uniqueConstraints,\n  }));\n  if (uniqueConstraints.length > 0) {\n    // The re-claim below (`withNodeCreateClaimsBatch`) reaches `insertUniqueBatch`\n    // only through the shared, fallback-dispositioned `issueClaimsBatched`\n    // (`../claims/node-claims.ts`), which silently degrades to per-row inserts\n    // when the PORT lacks the member — the right answer for a plain create,\n    // but not for this REFUSE operation. Re-checking the port here, before the\n    // destructive hard-delete below, closes that gap: the later call binds off\n    // the same `backend`/verdict pair checked here, so its internal fallback\n    // branch can never fire for this call.\n    if (\n      bindExtraIfReachable(\n        backend,\n        ctx.uniqueSidecarBatch.extras.insertUniqueBatch,\n        UNIQUE_SIDECAR_BATCH.id,\n      ) === undefined\n    ) {\n      throw new ConfigurationError(\n        \"The transaction backend lacks batched uniqueness operations\",\n        { code: \"SET_UPDATE_UNIQUENESS_UNSUPPORTED\", kind },\n      );\n    }\n    // The RESOLVED-SET verdict, not a row-at-a-time one: the statement rewrote\n    // every candidate at once, so a swap or a handoff of one key between two\n    // rows it touched is legal in the final state and refused by every\n    // intermediate one. One owner of that verdict, shared with the graph merge.\n    await validateResolvedNodeClaims(\n      createUniquenessContext(\n        ctx.graphId,\n        ctx.registry,\n        backend,\n        ctx.uniqueSidecarBatch,\n      ),\n      claimItems,\n      [],\n    );\n    await hardDeleteClaimsByNodeIds(\n      uniquenessContext(ctx, backend),\n      kind,\n      result.rows.map((row) => row.id),\n    );\n  }\n  // The same claim seam every create-shaped writer uses, with an ALREADY-APPLIED\n  // row write as its gate: the rows landed above and the old claims were\n  // hard-deleted, so what is left is a re-claim and there is no row write left\n  // for a claim to precede. Inverting it would mean reserving keys the update has\n  // not written. What covers this site on a backend that cannot fence is stated\n  // per kind shape: a kind whose scope spans siblings declares\n  // `fencesConstraintProbe` at the entry point and is refused before this body\n  // runs; a kind-scoped one is not refused, before or after — its\n  // delete-then-rebuild window is unchanged in shape and extent here.\n  await withNodeCreateClaimsBatch(\n    ctx,\n    claimItems,\n    backend,\n    alreadyAppliedRowWrite,\n  );\n  await applyNodeInsertSyncFansBatch(ctx, sidecarItems, backend);\n  return { affectedCount: result.affectedCount };\n}\n"]}