latticesql 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -666,6 +666,224 @@ declare class InMemoryStateStore implements WritebackStateStore {
666
666
  */
667
667
  declare function createSQLiteStateStore(db: Database.Database): WritebackStateStore;
668
668
 
669
+ /**
670
+ * Reranking — an optional second-stage scorer applied to the top candidates of
671
+ * a first-stage retrieval (vector / FTS / hybrid). A cross-encoder reranker
672
+ * typically lifts precision@k meaningfully over bi-encoder similarity, at the
673
+ * cost of one model call over the (small) candidate set.
674
+ *
675
+ * Bring your own reranker: Lattice never calls a model. The reranker is given
676
+ * the query and the candidate texts and returns a score per candidate; higher =
677
+ * more relevant. If it throws or returns nothing usable, retrieval falls back to
678
+ * the first-stage order — a reranker is an enhancement, never a hard dependency.
679
+ */
680
+ /** A candidate handed to a reranker: an id and the text to score against the query. */
681
+ interface RerankCandidate {
682
+ id: string;
683
+ content: string;
684
+ }
685
+ /** A reranker's verdict for one candidate. */
686
+ interface RerankScore {
687
+ id: string;
688
+ score: number;
689
+ }
690
+ /**
691
+ * Rerank `candidates` for `query`, returning a score per id (higher = better).
692
+ * May be sync or async. Ids absent from the result keep their prior order after
693
+ * any that were scored.
694
+ */
695
+ type RerankerFn = (query: string, candidates: RerankCandidate[]) => Promise<RerankScore[]> | RerankScore[];
696
+ /**
697
+ * Apply a reranker to an ordered list of items, returning a new order. Each item
698
+ * supplies its `id` and the `content` to rerank on. On any reranker failure (or
699
+ * an empty/garbage result) the original order is returned unchanged — reranking
700
+ * never breaks retrieval.
701
+ *
702
+ * Returns `{ order, applied }`: `order` is the reordered items, `applied` is true
703
+ * only when the reranker actually contributed scores. Items the reranker didn't
704
+ * score retain their relative first-stage order, after the scored ones.
705
+ */
706
+ declare function applyReranker<T extends {
707
+ id: string;
708
+ content: string;
709
+ }>(query: string, items: T[], reranker: RerankerFn): Promise<{
710
+ order: T[];
711
+ applied: boolean;
712
+ scores: Map<string, number>;
713
+ }>;
714
+
715
+ /**
716
+ * Text chunking for embedding.
717
+ *
718
+ * Embedding a whole row as one vector blurs many topics into a single point,
719
+ * which loses precision and forces a retriever to send large units to the model.
720
+ * Splitting text into smaller, semantically coherent chunks — each embedded
721
+ * separately — raises precision@k and lets a retriever return a few small,
722
+ * on-point units instead of one big one (fewer tokens to a correct answer).
723
+ *
724
+ * The default `semanticChunker` is dependency-free and boundary-aware: it packs
725
+ * text up to a character budget, preferring to break at paragraph, then
726
+ * sentence, then word boundaries, with optional overlap so context that
727
+ * straddles a boundary is not lost. Bring your own {@link ChunkerFn} (e.g. a
728
+ * token-aware or code-aware splitter) when the default heuristic isn't enough.
729
+ */
730
+ /** A single chunk of source text with its character offsets in the original. */
731
+ interface TextChunk {
732
+ /** 0-based position of this chunk in the sequence. */
733
+ index: number;
734
+ /** The chunk text (already includes any leading overlap). */
735
+ content: string;
736
+ /** Inclusive start offset in the source string. */
737
+ start: number;
738
+ /** Exclusive end offset in the source string. */
739
+ end: number;
740
+ }
741
+ /** Splits source text into ordered chunks. */
742
+ type ChunkerFn = (text: string) => TextChunk[];
743
+ interface SemanticChunkerOptions {
744
+ /** Target maximum characters per chunk. Default 1000. */
745
+ maxChars?: number;
746
+ /**
747
+ * Characters of trailing context to repeat at the start of the next chunk.
748
+ * Default 0. Must be < maxChars.
749
+ */
750
+ overlap?: number;
751
+ /**
752
+ * Minimum chunk size — a trailing remainder smaller than this is merged into
753
+ * the previous chunk rather than emitted on its own. Default 0.
754
+ */
755
+ minChars?: number;
756
+ }
757
+ /**
758
+ * Create a boundary-aware chunker. Empty/whitespace-only input yields no chunks.
759
+ * Text shorter than `maxChars` yields a single chunk.
760
+ */
761
+ declare function semanticChunker(opts?: SemanticChunkerOptions): ChunkerFn;
762
+ /**
763
+ * Apply chunking to a piece of text using the table's config. When no chunker is
764
+ * configured the whole text is one chunk (index 0) — the historical behavior.
765
+ * A `contextPrefix` (e.g. a title or breadcrumb) is prepended to every chunk's
766
+ * embedded content so each chunk carries enough context to be retrieved well.
767
+ */
768
+ declare function chunkText(text: string, chunker?: ChunkerFn, contextPrefix?: string): {
769
+ chunkIndex: number;
770
+ content: string;
771
+ }[];
772
+
773
+ /**
774
+ * Declarative computed columns + materialized rollups.
775
+ *
776
+ * **Computed columns** are stored columns derived from other columns on the same
777
+ * row by a pure function. They are recomputed on every write (and on a full
778
+ * `refreshComputedColumns`), so a consumer can index / filter / sort on a derived
779
+ * value without recomputing it per query, and an external edit to the rendered
780
+ * file can't desync it — the next write recomputes it.
781
+ *
782
+ * **Materialized rollups** are stored aggregates over a child table (e.g.
783
+ * `post.comment_count`). They are recomputed incrementally when the child table
784
+ * changes and in full via `refreshMaterializedRollups`.
785
+ *
786
+ * Both are opt-in per table and inert otherwise.
787
+ */
788
+
789
+ interface ComputedColumnSpec {
790
+ /** Columns this value is derived from. Drives recompute-on-change + cycle check. */
791
+ deps: string[];
792
+ /** Pure derivation from the row. Receives the full (merged) row. */
793
+ compute: (row: Row) => unknown;
794
+ /** SQL column type. Default `TEXT`. */
795
+ type?: string;
796
+ }
797
+ type RollupFunction = 'count' | 'sum' | 'avg' | 'min' | 'max';
798
+ interface MaterializedRollupSpec {
799
+ /** Child table to aggregate. */
800
+ sourceTable: string;
801
+ /** Column on the child table that references this table's primary key. */
802
+ foreignKey: string;
803
+ /** Aggregate function. */
804
+ fn: RollupFunction;
805
+ /** Child column to aggregate (omit for `count`). */
806
+ column?: string;
807
+ /** SQL column type for the stored rollup. Default `REAL`. */
808
+ type?: string;
809
+ }
810
+ /**
811
+ * Thrown when computed columns form a dependency cycle (A→B→A), which would make
812
+ * the recompute order undefined. Detected once at init.
813
+ */
814
+ declare class ComputedColumnCycleError extends Error {
815
+ readonly table: string;
816
+ readonly cycle: string[];
817
+ constructor(table: string, cycle: string[]);
818
+ }
819
+ /**
820
+ * Validate that computed columns have no dependency cycle and return a safe
821
+ * recompute order (dependencies before dependents). Only deps that are
822
+ * themselves computed columns participate in ordering; deps on plain columns are
823
+ * leaves. Throws {@link ComputedColumnCycleError} on a cycle.
824
+ */
825
+ declare function computedColumnOrder(table: string, computed: Record<string, ComputedColumnSpec>): string[];
826
+ /**
827
+ * Compute the values for `computed` columns from a (full) row, in dependency
828
+ * order, mutating the working row so later computed columns can read earlier
829
+ * ones. Returns a map of computed column → value.
830
+ */
831
+ declare function computeColumns(computed: Record<string, ComputedColumnSpec>, order: string[], row: Row): Record<string, unknown>;
832
+ /** The DDL column spec map computed columns contribute. */
833
+ declare function computedColumnDdl(computed: Record<string, ComputedColumnSpec>): Record<string, string>;
834
+ /** The DDL column spec map materialized rollups contribute. */
835
+ declare function rollupColumnDdl(rollups: Record<string, MaterializedRollupSpec>): Record<string, string>;
836
+ /** The set of all dep columns across computed specs (for change detection). */
837
+ declare function allComputedDeps(computed: Record<string, ComputedColumnSpec>): Set<string>;
838
+
839
+ /**
840
+ * Data governance primitives — provenance and trust.
841
+ *
842
+ * **Provenance** records, immutably, where a row came from: how it was ingested,
843
+ * the source URI, and when. Stamped at creation and frozen — an update that tries
844
+ * to change a provenance column fails loudly, so the lineage a risk/compliance
845
+ * reviewer signs off on can't be quietly rewritten.
846
+ *
847
+ * **Trust** gates untrusted ingest: a table opted into trust gives every new row a
848
+ * `_trust_state` (default `unverified`), and a verification workflow
849
+ * (`markRowForReview` / `verifyRow`) moves rows to `needs_review` / `verified`.
850
+ * Downstream consumers can filter to verified rows only.
851
+ *
852
+ * Both are opt-in per table and add no overhead to tables that don't use them.
853
+ */
854
+ type ProvenanceField = 'ingested_via' | 'source_uri' | 'ingested_at';
855
+ interface ProvenanceConfig {
856
+ /**
857
+ * Which immutable provenance columns to add and stamp. Defaults to all three
858
+ * (`ingested_via`, `source_uri`, `ingested_at`). `ingested_at` is auto-stamped
859
+ * on insert when not supplied.
860
+ */
861
+ fields?: ProvenanceField[];
862
+ }
863
+ type TrustState = 'unverified' | 'needs_review' | 'verified';
864
+ interface TrustConfig {
865
+ /** State assigned to a row on insert. Default `'unverified'`. */
866
+ defaultState?: TrustState;
867
+ }
868
+ declare const ALL_PROVENANCE_FIELDS: readonly ProvenanceField[];
869
+ /** Trust bookkeeping columns (internal-prefixed-ish, opt-in per table). */
870
+ declare const TRUST_COLUMNS: Record<string, string>;
871
+ /** Resolve a `provenance` config (boolean | object) to its column list. */
872
+ declare function resolveProvenanceFields(config: boolean | ProvenanceConfig | undefined): ProvenanceField[];
873
+ /** The DDL column spec map a provenance config contributes. */
874
+ declare function provenanceColumns(config: boolean | ProvenanceConfig | undefined): Record<string, string>;
875
+ /** Resolve a `trust` config (boolean | object) to its default state. */
876
+ declare function resolveTrustDefault(config: boolean | TrustConfig | undefined): TrustState | null;
877
+ /**
878
+ * Thrown when an update tries to change an immutable provenance column. Lineage
879
+ * is creation-time only; surfacing this loudly prevents silent provenance drift.
880
+ */
881
+ declare class ProvenanceImmutableError extends Error {
882
+ readonly table: string;
883
+ readonly column: string;
884
+ constructor(table: string, column: string);
885
+ }
886
+
669
887
  type Row = Record<string, unknown>;
670
888
 
671
889
  interface LatticeOptions {
@@ -711,6 +929,14 @@ interface LatticeOptions {
711
929
  * ...")` on violation, so callers can catch it.
712
930
  */
713
931
  maxRowBytes?: number;
932
+ /**
933
+ * Default bounded-read cap for `query()` (4.1+). When set, a `query()` with no
934
+ * explicit `limit` and no per-call `maxRows` returns at most this many rows and
935
+ * throws `BoundedReadError` if more match — a guardrail against an accidental
936
+ * unbounded full-table load on a hot path. A per-call `maxRows` or an explicit
937
+ * `limit` overrides it. Off by default (unbounded, preserving prior behavior).
938
+ */
939
+ defaultMaxRows?: number;
714
940
  }
715
941
  /**
716
942
  * Retention policy for the change log.
@@ -855,7 +1081,41 @@ interface Filter {
855
1081
  * For `in`, must be an array.
856
1082
  */
857
1083
  val?: unknown;
1084
+ /**
1085
+ * Extract a value from a JSON/JSONB column before comparing. A string like
1086
+ * `'a.b'` or an array `['a', 'b']` addresses a nested key. Compiles to
1087
+ * SQLite `json_extract(col, '$.a.b')` and Postgres `col #>> '{a,b}'`.
1088
+ *
1089
+ * @example
1090
+ * ```ts
1091
+ * { col: 'metadata_json', jsonPath: 'priority', op: 'gte', val: 3 }
1092
+ * { col: 'data', jsonPath: ['address', 'city'], op: 'eq', val: 'NYC' }
1093
+ * ```
1094
+ */
1095
+ jsonPath?: string | string[];
1096
+ }
1097
+ /** An OR group of filter expressions (any may match). */
1098
+ interface FilterOr {
1099
+ or: FilterExpr[];
1100
+ }
1101
+ /** An AND group of filter expressions (all must match). */
1102
+ interface FilterAnd {
1103
+ and: FilterExpr[];
858
1104
  }
1105
+ /**
1106
+ * A filter expression: a single {@link Filter} clause, or a recursive `or` / `and`
1107
+ * group of expressions. A bare `Filter` (the pre-4.1 shape) is still a valid
1108
+ * `FilterExpr`, so existing `filters: Filter[]` usage is unchanged.
1109
+ *
1110
+ * @example
1111
+ * ```ts
1112
+ * filters: [
1113
+ * { col: 'status', op: 'eq', val: 'open' },
1114
+ * { or: [ { col: 'priority', op: 'gte', val: 3 }, { col: 'pinned', op: 'eq', val: true } ] },
1115
+ * ]
1116
+ * ```
1117
+ */
1118
+ type FilterExpr = Filter | FilterOr | FilterAnd;
859
1119
  /**
860
1120
  * Names of the four built-in render templates.
861
1121
  *
@@ -1128,6 +1388,36 @@ interface TableDefinition {
1128
1388
  encrypted?: boolean | {
1129
1389
  columns: string[];
1130
1390
  };
1391
+ /**
1392
+ * Record immutable provenance for each row (4.1+). `true` adds three columns —
1393
+ * `ingested_via`, `source_uri`, `ingested_at` — or pass a {@link ProvenanceConfig}
1394
+ * to choose a subset. `ingested_at` is auto-stamped on insert; an `update()`
1395
+ * that tries to change any provenance column throws `ProvenanceImmutableError`,
1396
+ * so lineage can't be silently rewritten. Tables without this config are
1397
+ * unaffected.
1398
+ */
1399
+ provenance?: boolean | ProvenanceConfig;
1400
+ /**
1401
+ * Gate untrusted ingest with a per-row trust state (4.1+). `true` (or a
1402
+ * {@link TrustConfig}) adds `_trust_state` (default `'unverified'`) plus
1403
+ * `_verified_by` / `_verified_at` / `_review_reason`, and enables the
1404
+ * verification workflow (`markRowForReview` / `verifyRow` / `rowsNeedingReview`
1405
+ * / `verifiedRows`). Tables without this config are unaffected.
1406
+ */
1407
+ trust?: boolean | TrustConfig;
1408
+ /**
1409
+ * Declarative computed columns (4.1+) — stored columns derived from other
1410
+ * columns on the same row by a pure function, recomputed on every write (and
1411
+ * via `refreshComputedColumns`). Lets you index / filter / sort on a derived
1412
+ * value. A dependency cycle is rejected at init. See {@link ComputedColumnSpec}.
1413
+ */
1414
+ computed?: Record<string, ComputedColumnSpec>;
1415
+ /**
1416
+ * Materialized rollups (4.1+) — stored aggregates over a child table (e.g.
1417
+ * `comment_count`), recomputed when the child changes and via
1418
+ * `refreshMaterializedRollups`. See {@link MaterializedRollupSpec}.
1419
+ */
1420
+ materializedRollups?: Record<string, MaterializedRollupSpec>;
1131
1421
  }
1132
1422
  interface MultiTableDefinition {
1133
1423
  /** Returns the "anchor" entities — one output file is produced per anchor */
@@ -1157,6 +1447,27 @@ interface EmbeddingsConfig {
1157
1447
  * Bring your own model — Lattice does not bundle an embedding provider.
1158
1448
  */
1159
1449
  embed: (text: string) => Promise<number[]>;
1450
+ /**
1451
+ * Optional text splitter. When set, each row's concatenated text is split
1452
+ * into chunks and every chunk is embedded separately, so semantic search
1453
+ * matches the most relevant *part* of a row rather than the blurred average
1454
+ * of the whole. Omit for the historical whole-row behavior (one vector/row).
1455
+ * See `semanticChunker` for a dependency-free boundary-aware default.
1456
+ */
1457
+ chunker?: ChunkerFn;
1458
+ /**
1459
+ * Optional per-row context prefix prepended to every chunk before embedding
1460
+ * (e.g. a title or breadcrumb), so each chunk carries enough context to be
1461
+ * retrieved well on its own. Receives the full row.
1462
+ */
1463
+ contextPrefix?: (row: Row) => string;
1464
+ /**
1465
+ * Optional identifier of the embedding model, stored alongside each vector.
1466
+ * Lets `refreshEmbeddings` detect and re-embed rows produced by a different
1467
+ * model, and lets the doctor report mixed-model coverage. Purely advisory —
1468
+ * Lattice never calls a model itself.
1469
+ */
1470
+ modelId?: string;
1160
1471
  }
1161
1472
  /**
1162
1473
  * Options for `Lattice.search()`.
@@ -1169,6 +1480,20 @@ interface SearchOptions {
1169
1480
  * score are excluded. Default: 0.
1170
1481
  */
1171
1482
  minScore?: number;
1483
+ /**
1484
+ * Optional second-stage reranker applied to the retrieved candidates before
1485
+ * the top-K is returned. A cross-encoder reranker typically lifts precision
1486
+ * over raw similarity. Bring your own — Lattice never calls a model. If it
1487
+ * throws or returns nothing usable, the original similarity order is kept
1488
+ * (graceful fallback). To rerank a larger pool than `topK`, set
1489
+ * `rerankPoolSize`.
1490
+ */
1491
+ reranker?: RerankerFn;
1492
+ /**
1493
+ * Number of candidates to retrieve and hand to the `reranker` before slicing
1494
+ * to `topK`. Defaults to `max(topK * 4, 20)`. Ignored when no reranker is set.
1495
+ */
1496
+ rerankPoolSize?: number;
1172
1497
  }
1173
1498
  /**
1174
1499
  * A single search result returned by `Lattice.search()`.
@@ -1178,6 +1503,17 @@ interface SearchResult {
1178
1503
  row: Row;
1179
1504
  /** Cosine similarity score (0–1). */
1180
1505
  score: number;
1506
+ /**
1507
+ * For a chunked embedding, the index of the chunk that produced the best
1508
+ * score for this row. Absent for whole-row (unchunked) embeddings.
1509
+ */
1510
+ chunkIndex?: number;
1511
+ /**
1512
+ * For a chunked embedding, the text of the best-matching chunk — useful as a
1513
+ * precise, low-token snippet to hand to a model. Absent for whole-row
1514
+ * embeddings or when chunk content was not stored.
1515
+ */
1516
+ matchedContent?: string;
1181
1517
  }
1182
1518
  /**
1183
1519
  * Dimension scores passed to `Lattice.reward()`.
@@ -1264,6 +1600,19 @@ interface WritebackDefinition {
1264
1600
  */
1265
1601
  onReject?: (entry: unknown, result: WritebackValidationResult) => void;
1266
1602
  }
1603
+ /**
1604
+ * Column projection for a query — return only the columns you need, so wide
1605
+ * tables don't transfer (or decrypt) columns the caller will discard.
1606
+ *
1607
+ * - `string[]` — include exactly these columns.
1608
+ * - `{ include }` — include exactly these columns.
1609
+ * - `{ exclude }` — return all columns except these.
1610
+ */
1611
+ type QueryProjection = string[] | {
1612
+ include: string[];
1613
+ } | {
1614
+ exclude: string[];
1615
+ };
1267
1616
  interface QueryOptions {
1268
1617
  /**
1269
1618
  * Equality filters — shorthand for `filters: [{ col, op: 'eq', val }]`.
@@ -1271,30 +1620,123 @@ interface QueryOptions {
1271
1620
  */
1272
1621
  where?: Record<string, unknown>;
1273
1622
  /**
1274
- * Advanced filter clauses with full operator support.
1275
- * Combined with `where` using AND.
1623
+ * Advanced filter clauses with full operator support. May include recursive
1624
+ * `or` / `and` groups (4.1+) and per-clause `jsonPath` extraction. Combined
1625
+ * with `where` using AND.
1276
1626
  *
1277
1627
  * @example
1278
1628
  * ```ts
1279
1629
  * filters: [
1280
1630
  * { col: 'priority', op: 'gte', val: 3 },
1281
1631
  * { col: 'deleted_at', op: 'isNull' },
1282
- * { col: 'tag', op: 'in', val: ['bug', 'feature'] },
1632
+ * { or: [ { col: 'tag', op: 'eq', val: 'bug' }, { col: 'tag', op: 'eq', val: 'feature' } ] },
1283
1633
  * ]
1284
1634
  * ```
1285
1635
  */
1286
- filters?: Filter[];
1636
+ filters?: FilterExpr[];
1287
1637
  orderBy?: string;
1288
1638
  orderDir?: 'asc' | 'desc';
1289
1639
  limit?: number;
1290
1640
  offset?: number;
1641
+ /**
1642
+ * Return only these columns (4.1+). See {@link QueryProjection}. Omitted
1643
+ * columns are never transferred or decrypted.
1644
+ */
1645
+ projection?: QueryProjection;
1646
+ /**
1647
+ * Bounded-read cap (4.1+). When set and no explicit `limit` is given, the
1648
+ * query reads at most `maxRows` rows and **throws `BoundedReadError`** if more
1649
+ * exist — forcing the caller to paginate rather than silently loading an
1650
+ * unbounded result set. Overrides `LatticeOptions.defaultMaxRows`. An explicit
1651
+ * `limit` opts out (the caller has bounded the read themselves).
1652
+ */
1653
+ maxRows?: number;
1654
+ /**
1655
+ * Return one row per distinct value of these column(s) (4.1+). Compiles to
1656
+ * Postgres `DISTINCT ON (...)` and an emulated SQLite `ROW_NUMBER()` window.
1657
+ * Which row survives per group is determined by `orderBy`/`orderDir` (then the
1658
+ * primary key as a deterministic tiebreak).
1659
+ */
1660
+ distinctOn?: string | string[];
1661
+ /**
1662
+ * Expand declared relations on each returned row (4.1+). Each name must be a
1663
+ * key of the table's `relations`. A `belongsTo` relation attaches the single
1664
+ * related row (or null); a `hasMany` relation attaches an array. Related rows
1665
+ * are fetched in ONE batched `IN (...)` query per relation — no N+1.
1666
+ */
1667
+ include?: string[];
1668
+ }
1669
+ interface QueryPageOptions {
1670
+ /** Equality filters (same as QueryOptions.where). */
1671
+ where?: Record<string, unknown>;
1672
+ /** Advanced filters (same as QueryOptions.filters). */
1673
+ filters?: FilterExpr[];
1674
+ /** Sort column the cursor walks. Defaults to the primary key. */
1675
+ orderBy?: string;
1676
+ orderDir?: 'asc' | 'desc';
1677
+ /** Page size. Default 50. */
1678
+ limit?: number;
1679
+ /** Opaque cursor from a prior page's `nextCursor`. Omit for the first page. */
1680
+ cursor?: string;
1681
+ /** Return only these columns (see {@link QueryProjection}). */
1682
+ projection?: QueryProjection;
1683
+ }
1684
+ interface QueryPageResult {
1685
+ /** The page of rows. */
1686
+ rows: Row[];
1687
+ /** Opaque cursor for the next page, or null when this is the last page. */
1688
+ nextCursor: string | null;
1689
+ /** Whether more rows exist beyond this page. */
1690
+ hasMore: boolean;
1291
1691
  }
1292
1692
  interface CountOptions {
1293
1693
  /** Equality filters (same as QueryOptions.where) */
1294
1694
  where?: Record<string, unknown>;
1295
1695
  /** Advanced filter clauses (same as QueryOptions.filters) */
1296
- filters?: Filter[];
1696
+ filters?: FilterExpr[];
1697
+ }
1698
+ /** SQL aggregate function. */
1699
+ type AggregateFunction = 'count' | 'sum' | 'avg' | 'min' | 'max';
1700
+ /** One aggregate column in an {@link AggregateOptions}. */
1701
+ interface AggregateSpec {
1702
+ /** The aggregate function to apply. */
1703
+ fn: AggregateFunction;
1704
+ /**
1705
+ * Column to aggregate. Omit for `count` to mean `COUNT(*)`. Required for
1706
+ * `sum`/`avg`/`min`/`max`.
1707
+ */
1708
+ col?: string;
1709
+ /** Output key for this aggregate in each result row. */
1710
+ as: string;
1711
+ /** Apply `DISTINCT` inside the aggregate (e.g. `COUNT(DISTINCT col)`). */
1712
+ distinct?: boolean;
1713
+ }
1714
+ /** A HAVING clause on an aggregate output (post-grouping filter). */
1715
+ interface AggregateHaving {
1716
+ /** The `as` key of an aggregate in the same query. */
1717
+ aggregate: string;
1718
+ op: FilterOp;
1719
+ val?: unknown;
1297
1720
  }
1721
+ interface AggregateOptions {
1722
+ /** Columns to GROUP BY. Omit for a single grand-total row. */
1723
+ groupBy?: string[];
1724
+ /** The aggregate columns to compute (at least one). */
1725
+ aggregates: AggregateSpec[];
1726
+ /** Row-level equality filters applied before grouping. */
1727
+ where?: Record<string, unknown>;
1728
+ /** Row-level advanced filters applied before grouping. */
1729
+ filters?: FilterExpr[];
1730
+ /** Post-grouping filters on aggregate outputs. */
1731
+ having?: AggregateHaving[];
1732
+ /** Order the grouped rows by a groupBy column or an aggregate `as` key. */
1733
+ orderBy?: string;
1734
+ orderDir?: 'asc' | 'desc';
1735
+ /** Max grouped rows to return. */
1736
+ limit?: number;
1737
+ }
1738
+ /** One row of {@link Lattice.aggregate} output: groupBy columns + aggregate keys. */
1739
+ type AggregateResult = Record<string, unknown>;
1298
1740
  interface InitOptions {
1299
1741
  migrations?: Migration[];
1300
1742
  /**
@@ -2041,6 +2483,692 @@ declare class ProgressThrottle {
2041
2483
  force(event: RenderProgress): void;
2042
2484
  }
2043
2485
 
2486
+ /** Internal table that stores one embedding vector per (table, row, chunk). */
2487
+ declare const EMBEDDINGS_TABLE = "_lattice_embeddings";
2488
+ /**
2489
+ * Ensure the internal embeddings storage table exists with the chunk-aware
2490
+ * schema, migrating an older two-key (table_name, row_pk) layout forward.
2491
+ *
2492
+ * The embeddings table is a DERIVED cache — every vector can be recomputed from
2493
+ * its source row — so when an older schema is detected it is rebuilt rather than
2494
+ * preserved bit-for-bit. The migration is idempotent: once `chunk_index` exists
2495
+ * the function is a no-op.
2496
+ */
2497
+ declare function ensureEmbeddingsTable(adapter: StorageAdapter): Promise<void>;
2498
+ /** Concatenate the configured fields of a row into a single embeddable string. */
2499
+ declare function concatRowText(row: Row, fields: string[]): string;
2500
+ /**
2501
+ * Compute and store the embedding(s) for a row. When the config supplies a
2502
+ * `chunker`, the row text is split and each chunk is embedded + stored under its
2503
+ * own `chunk_index`; otherwise the whole text is one chunk (index 0). The row's
2504
+ * prior chunks are replaced atomically-per-row (delete then insert).
2505
+ */
2506
+ declare function storeEmbedding(adapter: StorageAdapter, table: string, pk: string, row: Row, config: EmbeddingsConfig): Promise<void>;
2507
+ /** Remove all stored embedding chunks for a row. */
2508
+ declare function removeEmbedding(adapter: StorageAdapter, table: string, pk: string): Promise<void>;
2509
+ /** Cosine similarity between two vectors. */
2510
+ declare function cosineSimilarity(a: number[], b: number[]): number;
2511
+ /**
2512
+ * Error thrown when a stored vector's dimensionality does not match the query
2513
+ * vector's — almost always a sign the embedding model changed without a
2514
+ * re-embed. Surfaced loudly rather than silently scoring mismatched vectors.
2515
+ */
2516
+ declare class EmbeddingDimensionMismatchError extends Error {
2517
+ readonly table: string;
2518
+ readonly expected: number;
2519
+ readonly found: number;
2520
+ constructor(table: string, expected: number, found: number);
2521
+ }
2522
+ /**
2523
+ * Search rows by semantic similarity. Uses a native vector index (pgvector) when
2524
+ * one exists for the table; otherwise an in-process cosine scan over the stored
2525
+ * chunk vectors. Either way results respect `deleted_at IS NULL` on the base
2526
+ * table and are de-duplicated to the best-scoring chunk per row.
2527
+ */
2528
+ declare function searchByEmbedding(adapter: StorageAdapter, table: string, queryText: string, config: EmbeddingsConfig, topK: number, minScore: number, pkColumn?: string): Promise<SearchResult[]>;
2529
+ interface RefreshEmbeddingsOptions {
2530
+ /** Only re-embed rows whose stored model differs from `config.modelId`. */
2531
+ staleModelOnly?: boolean;
2532
+ /** Embed rows that have no stored embedding. Default true. */
2533
+ backfillMissing?: boolean;
2534
+ /** Re-embed rows whose source changed since `embedded_at` (caller decides via `changedSince`). */
2535
+ changedSince?: string;
2536
+ /** Page size for the base-table scan. Default 500. */
2537
+ batchSize?: number;
2538
+ }
2539
+ interface EmbeddingRefreshResult {
2540
+ /** Rows that were (re-)embedded. */
2541
+ embedded: number;
2542
+ /** Rows skipped because they were already current. */
2543
+ skipped: number;
2544
+ /** Orphaned embeddings removed (their source row no longer exists). */
2545
+ removed: number;
2546
+ }
2547
+ /**
2548
+ * Backfill / re-embed a table's vectors incrementally — embed only what's
2549
+ * missing or stale, rather than re-embedding everything. Honors `deleted_at`
2550
+ * and sweeps embeddings whose source row is gone.
2551
+ */
2552
+ declare function refreshEmbeddings(adapter: StorageAdapter, table: string, config: EmbeddingsConfig, pkColumn?: string, opts?: RefreshEmbeddingsOptions): Promise<EmbeddingRefreshResult>;
2553
+
2554
+ /**
2555
+ * Ranking signals — lightweight, deterministic boosts applied to a retrieval
2556
+ * score from columns already on the row, no model required. Pure relevance
2557
+ * (vector/FTS/hybrid) ignores how fresh, how rewarded, or how referenced a row
2558
+ * is; these signals fold that business context back into the ranking.
2559
+ *
2560
+ * Each signal yields a value in [0, 1]; the combined boost is a weighted sum,
2561
+ * and the caller multiplies the base score by `(1 + boost)` so a strong signal
2562
+ * lifts an already-relevant row without drowning relevance entirely.
2563
+ */
2564
+
2565
+ /** Exponential recency decay: 1.0 at age 0, 0.5 at one half-life, → 0 with age. */
2566
+ interface RecencySignal {
2567
+ /** Timestamp column (ISO-8601 string or epoch ms). */
2568
+ column: string;
2569
+ /** Half-life in days — the age at which the boost halves. */
2570
+ halfLifeDays: number;
2571
+ /** Weight of this signal in the combined boost. */
2572
+ weight: number;
2573
+ }
2574
+ /** Reward signal: saturating boost from a `_reward_total`-style column. */
2575
+ interface RewardSignal {
2576
+ /** Column holding the cumulative reward. Default `_reward_total`. */
2577
+ column?: string;
2578
+ /** Weight of this signal in the combined boost. */
2579
+ weight: number;
2580
+ }
2581
+ /**
2582
+ * Backlink signal: a saturating boost from an inbound-reference-count column. A
2583
+ * row referenced by many others is more central/authoritative, so it ranks higher.
2584
+ */
2585
+ interface BacklinkSignal {
2586
+ /** Column holding the inbound reference count. Default `_backlink_count`. */
2587
+ column?: string;
2588
+ /** Weight of this signal in the combined boost. */
2589
+ weight: number;
2590
+ }
2591
+ /** A custom per-row signal returning a value in [0, 1]. */
2592
+ interface CustomSignal {
2593
+ fn: (row: Row) => number;
2594
+ weight: number;
2595
+ }
2596
+ interface RankingOptions {
2597
+ recency?: RecencySignal;
2598
+ reward?: RewardSignal;
2599
+ backlink?: BacklinkSignal;
2600
+ custom?: CustomSignal;
2601
+ /**
2602
+ * Reference time (epoch ms) for recency decay. Defaults to `Date.now()`.
2603
+ * Pass it for deterministic ranking/tests.
2604
+ */
2605
+ now?: number;
2606
+ }
2607
+ /** Recency boost in [0, 1] for a row's timestamp column. */
2608
+ declare function recencyBoost(row: Row, signal: RecencySignal, nowMs: number): number;
2609
+ /** Saturating reward boost in [0, 1): r / (1 + r) for non-negative reward. */
2610
+ declare function rewardBoost(row: Row, signal: RewardSignal): number;
2611
+ /** Saturating backlink boost in [0, 1): b / (1 + b) for a non-negative count. */
2612
+ declare function backlinkBoost(row: Row, signal: BacklinkSignal): number;
2613
+ /**
2614
+ * Combined, weighted ranking boost for a row (≥ 0). Multiply a base relevance
2615
+ * score by `(1 + rankingBoost(...))` to apply it.
2616
+ */
2617
+ declare function rankingBoost(row: Row, opts: RankingOptions): number;
2618
+
2619
+ /**
2620
+ * Hybrid search — fuse semantic (vector) retrieval with lexical (full-text)
2621
+ * retrieval so the result set has both the recall of embeddings and the
2622
+ * precision of exact-term matching. Neither arm alone is enough: vectors miss
2623
+ * rare exact tokens (names, ids, codes), keywords miss paraphrases.
2624
+ *
2625
+ * Fusion is Reciprocal Rank Fusion (RRF): a document's score is the sum over the
2626
+ * arms it appears in of `1 / (k + rank)`, with `k = 60` by default. RRF needs
2627
+ * only the per-arm *ranks*, so the two arms' incomparable score scales (cosine
2628
+ * similarity vs ts_rank/bm25) never have to be normalized against each other.
2629
+ *
2630
+ * Optional post-fusion stages: deterministic ranking signals (recency / reward /
2631
+ * custom) and a bring-your-own reranker. Results carry a full score breakdown
2632
+ * for `--explain`.
2633
+ */
2634
+
2635
+ interface HybridSearchOptions {
2636
+ /** Final number of results. Default 10. */
2637
+ topK?: number;
2638
+ /** RRF constant — larger flattens the rank contribution. Default 60. */
2639
+ rrfK?: number;
2640
+ /** Candidates pulled from each arm before fusion. Default max(topK*4, 20). */
2641
+ poolSize?: number;
2642
+ /** Minimum cosine similarity for the vector arm. Default 0. */
2643
+ minVectorScore?: number;
2644
+ /** Embeddings config — enables the vector arm. Omit for FTS-only fusion. */
2645
+ embeddingsConfig?: EmbeddingsConfig;
2646
+ /** Primary-key column of the base table. Default 'id'. */
2647
+ pkColumn?: string;
2648
+ /** Deterministic post-fusion ranking signals. */
2649
+ ranking?: RankingOptions;
2650
+ /** Optional reranker over the fused top candidates (graceful fallback). */
2651
+ reranker?: RerankerFn;
2652
+ }
2653
+ /** Per-result score breakdown (the `--explain` payload). */
2654
+ interface HybridScoreBreakdown {
2655
+ /** Final score used for ordering. */
2656
+ final: number;
2657
+ /** Reciprocal-rank-fusion score before ranking/rerank. */
2658
+ rrf: number;
2659
+ /** 1-based rank in the vector arm, or null if absent. */
2660
+ vectorRank: number | null;
2661
+ /** Cosine similarity from the vector arm, or null. */
2662
+ vectorScore: number | null;
2663
+ /** 1-based rank in the FTS arm, or null if absent. */
2664
+ ftsRank: number | null;
2665
+ /** FTS relevance score (ts_rank / -bm25), or null. */
2666
+ ftsScore: number | null;
2667
+ /** Multiplicative ranking boost applied (0 when no ranking signals). */
2668
+ rankingBoost: number;
2669
+ /** Reranker score, when a reranker actually scored this row. */
2670
+ rerankerScore?: number;
2671
+ }
2672
+ interface HybridSearchResult {
2673
+ row: Row;
2674
+ score: number;
2675
+ explain: HybridScoreBreakdown;
2676
+ /** Best-matching chunk text from the vector arm, when available. */
2677
+ matchedContent?: string;
2678
+ }
2679
+ /**
2680
+ * Run a hybrid (vector + full-text) search over one table and return fused,
2681
+ * optionally ranked + reranked results with a per-result score breakdown.
2682
+ * Soft-deleted rows are excluded (both arms honor `deleted_at`).
2683
+ */
2684
+ declare function hybridSearch(adapter: StorageAdapter, table: string, query: string, opts?: HybridSearchOptions): Promise<HybridSearchResult[]>;
2685
+
2686
+ /**
2687
+ * Graph-augmented retrieval.
2688
+ *
2689
+ * Pure similarity retrieval treats every row as an island. Real knowledge is
2690
+ * relational: a document cites another, a task blocks a task, a person belongs to
2691
+ * a team. A typed-edge graph over the rows lets retrieval be *relationship-aware*
2692
+ * — traverse from an anchor entity to its neighborhood, and boost results that
2693
+ * are graph-connected to the things you already care about.
2694
+ *
2695
+ * Edges live in one internal `__lattice_edges` table (GUI-hidden by prefix).
2696
+ * They can be added explicitly, or extracted with **zero LLM** from existing
2697
+ * foreign-key columns. Traversal is a **bounded BFS** with hard caps on depth and
2698
+ * visited-node count, so a dense or cyclic graph can never blow up memory.
2699
+ */
2700
+
2701
+ /** Absolute ceiling on traversal depth — a hard guard against runaway BFS. */
2702
+ declare const MAX_TRAVERSAL_DEPTH = 5;
2703
+ /** Default ceiling on visited nodes per traversal. */
2704
+ declare const DEFAULT_MAX_NODES = 10000;
2705
+ interface GraphNode {
2706
+ table: string;
2707
+ id: string;
2708
+ }
2709
+ interface GraphEdge {
2710
+ srcTable: string;
2711
+ srcId: string;
2712
+ dstTable: string;
2713
+ dstId: string;
2714
+ /** Edge type/label (e.g. 'cites', 'blocks', 'member_of'). */
2715
+ type: string;
2716
+ /** Edge weight (default 1). Higher = stronger relationship. */
2717
+ weight?: number;
2718
+ }
2719
+ type TraversalDirection = 'out' | 'in' | 'both';
2720
+ interface TraversalOptions {
2721
+ /** Max BFS depth (clamped to MAX_TRAVERSAL_DEPTH). Default 2. */
2722
+ maxDepth?: number;
2723
+ /** Follow out-edges, in-edges, or both. Default 'out'. */
2724
+ direction?: TraversalDirection;
2725
+ /** Restrict to these edge types. */
2726
+ edgeTypes?: string[];
2727
+ /** Stop after visiting this many nodes (cycle/blowup guard). Default 10000. */
2728
+ maxNodes?: number;
2729
+ }
2730
+ interface TraversalNode {
2731
+ node: GraphNode;
2732
+ /** BFS depth from the start node (start = 0). */
2733
+ depth: number;
2734
+ }
2735
+ interface GraphTraversalResult {
2736
+ start: GraphNode;
2737
+ nodes: TraversalNode[];
2738
+ edges: GraphEdge[];
2739
+ /** True if a cap (depth or node count) stopped the traversal early. */
2740
+ truncated: boolean;
2741
+ }
2742
+ /** Ensure the internal edges table exists (idempotent, GUI-hidden by prefix). */
2743
+ declare function ensureEdgesTable(adapter: StorageAdapter): Promise<void>;
2744
+ /** Add (upsert) one edge. */
2745
+ declare function addEdge(adapter: StorageAdapter, edge: GraphEdge): Promise<void>;
2746
+ /** Add many edges (each upserted). */
2747
+ declare function addEdges(adapter: StorageAdapter, edges: GraphEdge[]): Promise<void>;
2748
+ /** Remove one edge (all matching types when `type` omitted). */
2749
+ declare function removeEdge(adapter: StorageAdapter, edge: Omit<GraphEdge, 'weight' | 'type'> & {
2750
+ type?: string;
2751
+ }): Promise<void>;
2752
+ /** Direct neighbors of a node (one hop), in the given direction + type filter. */
2753
+ declare function neighbors(adapter: StorageAdapter, node: GraphNode, opts?: {
2754
+ direction?: TraversalDirection;
2755
+ edgeTypes?: string[];
2756
+ }): Promise<GraphEdge[]>;
2757
+ /**
2758
+ * Bounded breadth-first traversal from `start`. Hard caps: depth is clamped to
2759
+ * {@link MAX_TRAVERSAL_DEPTH}, and the visited set is capped at `maxNodes`. A
2760
+ * visited set prevents revisiting nodes in cyclic graphs.
2761
+ */
2762
+ declare function traverse(adapter: StorageAdapter, start: GraphNode, opts?: TraversalOptions): Promise<GraphTraversalResult>;
2763
+ interface ExtractEdgesSpec {
2764
+ /** Source table holding the foreign key. */
2765
+ srcTable: string;
2766
+ /** FK column on the source table. */
2767
+ fkColumn: string;
2768
+ /** Table the FK points at. */
2769
+ dstTable: string;
2770
+ /** Edge type to label the extracted edges. Default `<fkColumn>`. */
2771
+ type?: string;
2772
+ /** Source-table primary key. Default 'id'. */
2773
+ pkColumn?: string;
2774
+ }
2775
+ /**
2776
+ * Zero-LLM edge extraction: derive `srcTable[pk] --type--> dstTable[fk]` edges
2777
+ * from a foreign-key column. Deterministic; no model. Returns the edge count.
2778
+ */
2779
+ declare function extractEdgesFromColumn(adapter: StorageAdapter, spec: ExtractEdgesSpec): Promise<number>;
2780
+ /**
2781
+ * Adjacency boost — re-score retrieval results by their graph connectivity to a
2782
+ * set of anchor nodes (e.g. the entities in the user's current context). A
2783
+ * result adjacent (within `maxDepth`) to an anchor is boosted by the edge weight
2784
+ * decayed by hop distance, scaled by `weight`. This makes retrieval
2785
+ * relationship-aware: things related to what you already care about rank higher.
2786
+ *
2787
+ * Returns a new array sorted by the boosted score; pure (no DB writes).
2788
+ */
2789
+ interface GraphBoostOptions {
2790
+ /** Anchor nodes whose neighborhood is preferred. */
2791
+ anchors: GraphNode[];
2792
+ /** Table the results belong to (results are `{ id, score }`). */
2793
+ resultTable: string;
2794
+ /** Boost weight applied to the adjacency signal. Default 0.5. */
2795
+ weight?: number;
2796
+ /** Hop radius from anchors to consider. Clamped to MAX_TRAVERSAL_DEPTH. Default 1. */
2797
+ maxDepth?: number;
2798
+ /** Edge direction from the anchor's perspective. Default 'both'. */
2799
+ direction?: TraversalDirection;
2800
+ edgeTypes?: string[];
2801
+ }
2802
+ interface GraphBoostResult<T> {
2803
+ item: T;
2804
+ baseScore: number;
2805
+ boostedScore: number;
2806
+ /** Min hop distance to an anchor (Infinity if unreachable). */
2807
+ hops: number;
2808
+ }
2809
+ declare function graphAdjacencyBoost<T extends {
2810
+ id: string;
2811
+ score: number;
2812
+ }>(adapter: StorageAdapter, results: T[], opts: GraphBoostOptions): Promise<GraphBoostResult<T>[]>;
2813
+
2814
+ /**
2815
+ * Seamless cloud file-byte access — an in-database presigned-URL broker.
2816
+ *
2817
+ * After joining a cloud via invite, a scoped member connects directly to the
2818
+ * cloud's Postgres as their own least-privilege role. They can SELECT a `files`
2819
+ * row they're allowed to see, but they hold no S3 credential, so fetching the
2820
+ * bytes would otherwise fail. This installs a `SECURITY DEFINER` function that,
2821
+ * **inside Postgres** (the only place the owner's key lives, away from members),
2822
+ * gates on the member's row-visibility and computes a short-lived AWS SigV4
2823
+ * presigned URL for exactly that object — so the member fetches/uploads bytes
2824
+ * with zero config and never holds a key.
2825
+ *
2826
+ * Why sign in plpgsql: the secret must never leave the database for a member's
2827
+ * process, so a Node-side presign is out — the signature is computed in-DB via
2828
+ * `pgcrypto` HMAC-SHA256. Correctness of the SigV4 chain is verified against
2829
+ * AWS's published test vectors (no real S3 needed).
2830
+ *
2831
+ * Postgres + a cloud only. SQLite is single-user with local bytes — no-op.
2832
+ */
2833
+
2834
+ /** Owner-only table holding the least-privilege S3 key. Never member-granted. */
2835
+ declare const S3_SECRET_TABLE = "__lattice_cloud_s3_secret";
2836
+ /**
2837
+ * SQL that installs the presigner: `pgcrypto`, the owner-only secret table, the
2838
+ * SigV4 signer, and the visibility-gated `lattice_presign_file` wrapper. All
2839
+ * `SECURITY DEFINER` bodies are search_path-pinned by the caller.
2840
+ *
2841
+ * `lattice_aws_sigv4_presign(...)` is parameterized on the date/time so it can be
2842
+ * verified deterministically against AWS test vectors; `lattice_presign_file`
2843
+ * derives the date from `now()` at call time.
2844
+ */
2845
+ declare function filePresignSql(): string;
2846
+ /**
2847
+ * Install the presigner into the current Postgres schema. No-op on SQLite.
2848
+ * `schema` is used to pin the `SECURITY DEFINER` search_path (reuse
2849
+ * {@link cloudSchema} to resolve it) — required to prevent a member from
2850
+ * shadowing `files` / the visibility helpers via `pg_temp`.
2851
+ */
2852
+ declare function installFilePresigner(adapter: StorageAdapter, schema: string): Promise<void>;
2853
+ interface CloudS3Secret {
2854
+ bucket: string;
2855
+ region: string;
2856
+ accessKey: string;
2857
+ secretKey: string;
2858
+ /** Optional key prefix applied to every object. */
2859
+ prefix?: string;
2860
+ /** Optional host override for S3-compatible stores. */
2861
+ endpoint?: string;
2862
+ }
2863
+ /** Store/replace the owner's least-privilege S3 key (owner-only; never granted). */
2864
+ declare function setCloudS3Secret(adapter: StorageAdapter, secret: CloudS3Secret): Promise<void>;
2865
+ /**
2866
+ * Grant a member group EXECUTE on the presigner (so every current + future
2867
+ * member can presign their own visible files), WITHOUT granting any access to
2868
+ * the owner-only secret table. Idempotent.
2869
+ */
2870
+ declare function grantPresignerToMemberGroup(adapter: StorageAdapter, memberGroup: string): Promise<void>;
2871
+ /** Whether the presigner function is installed in the current schema. */
2872
+ declare function hasFilePresigner(adapter: StorageAdapter): Promise<boolean>;
2873
+
2874
+ /**
2875
+ * Retrieval evaluation — measure the quality of any ranked-retrieval function
2876
+ * against a labeled query set, with the standard information-retrieval metrics:
2877
+ * Precision@k, Recall@k, Mean Reciprocal Rank (MRR), normalized Discounted
2878
+ * Cumulative Gain (nDCG@k), and Mean Average Precision (MAP).
2879
+ *
2880
+ * The evaluator is deliberately decoupled from any specific search
2881
+ * implementation: you hand it a {@link Retriever} — a function that maps a query
2882
+ * string to a best-first list of row ids — plus the ground-truth relevant ids
2883
+ * per query. That makes it usable to grade semantic search, full-text search, a
2884
+ * hybrid fusion, a graph-augmented retriever, or an external service, and to
2885
+ * regression-gate any of them in CI so an upgrade can't silently lower quality.
2886
+ *
2887
+ * All metric math is computed in-process from the ranked id lists; nothing here
2888
+ * touches the database, so it is dialect-agnostic and side-effect free.
2889
+ */
2890
+ /**
2891
+ * A graded relevance label. `gain` is the graded usefulness of the row for the
2892
+ * query (used by nDCG); omit it for binary relevance (treated as gain 1).
2893
+ */
2894
+ interface RelevanceLabel {
2895
+ id: string;
2896
+ /** Graded relevance gain (default 1). Higher = more useful. */
2897
+ gain?: number;
2898
+ }
2899
+ /**
2900
+ * A single labeled evaluation query: the query text plus the ground-truth set
2901
+ * of ids that *should* be retrieved. Order of `relevant` is irrelevant — it is
2902
+ * a set; ranking quality is judged against the order the retriever returns.
2903
+ */
2904
+ interface EvalQuery {
2905
+ /** Stable identifier for per-query reporting. Defaults to the query text. */
2906
+ id?: string;
2907
+ /** Natural-language query text passed to the retriever. */
2908
+ query: string;
2909
+ /** Ground-truth relevant ids — bare ids (binary) or graded labels. */
2910
+ relevant: string[] | RelevanceLabel[];
2911
+ }
2912
+ /**
2913
+ * Maps a query to a ranked, best-first list of row ids. May be sync or async.
2914
+ * Returning more than `k` ids is fine — the evaluator applies the cutoff.
2915
+ */
2916
+ type Retriever = (query: string) => Promise<string[]> | string[];
2917
+ interface RetrievalEvalOptions {
2918
+ /** Primary cutoff for P@k / Recall@k / nDCG@k. Default 10. */
2919
+ k?: number;
2920
+ /**
2921
+ * Additional cutoffs to also report (e.g. `[1, 3, 5, 10]`). Each appears in
2922
+ * {@link RetrievalEvalSummary.byK}. The primary `k` is always reported.
2923
+ */
2924
+ ks?: number[];
2925
+ }
2926
+ /** Per-query metric breakdown. */
2927
+ interface PerQueryEval {
2928
+ id: string;
2929
+ query: string;
2930
+ /** Relevant ids found in the top-k, divided by k. */
2931
+ precisionAtK: number;
2932
+ /** Relevant ids found in the top-k, divided by total relevant. */
2933
+ recallAtK: number;
2934
+ /** 1 / (rank of the first relevant id), 0 if none were returned. */
2935
+ reciprocalRank: number;
2936
+ /** DCG@k / ideal-DCG@k, in [0, 1]. */
2937
+ ndcgAtK: number;
2938
+ /** Average precision over the full returned list (the AP that MAP averages). */
2939
+ averagePrecision: number;
2940
+ /** Number of ids the retriever returned. */
2941
+ retrieved: number;
2942
+ /** Number of ground-truth relevant ids. */
2943
+ relevantTotal: number;
2944
+ }
2945
+ /** Aggregate metrics across the whole query set, plus per-query detail. */
2946
+ interface RetrievalEvalSummary {
2947
+ /** The primary cutoff used for the top-level aggregate fields. */
2948
+ k: number;
2949
+ /** Number of queries evaluated. */
2950
+ queryCount: number;
2951
+ /** Mean Precision@k. */
2952
+ precisionAtK: number;
2953
+ /** Mean Recall@k. */
2954
+ recallAtK: number;
2955
+ /** Mean Reciprocal Rank. */
2956
+ mrr: number;
2957
+ /** Mean nDCG@k. */
2958
+ ndcgAtK: number;
2959
+ /** Mean Average Precision. */
2960
+ map: number;
2961
+ /** Per-cutoff means, present when `ks` is supplied (always includes `k`). */
2962
+ byK?: Record<number, {
2963
+ precisionAtK: number;
2964
+ recallAtK: number;
2965
+ ndcgAtK: number;
2966
+ }>;
2967
+ /** Per-query metrics, in input order. */
2968
+ perQuery: PerQueryEval[];
2969
+ }
2970
+ /**
2971
+ * Evaluate a retriever against a labeled query set.
2972
+ *
2973
+ * @throws Error if `queries` is empty — an eval over no queries would silently
2974
+ * report a meaningless "0 across the board", so it fails loudly instead.
2975
+ */
2976
+ declare function evaluateRetrieval(queries: EvalQuery[], retriever: Retriever, opts?: RetrievalEvalOptions): Promise<RetrievalEvalSummary>;
2977
+ /**
2978
+ * Compare a candidate summary against a baseline and report regressions beyond
2979
+ * a tolerance. Designed to drive a CI gate: a retrieval change that lowers any
2980
+ * headline metric by more than `tolerance` fails the build.
2981
+ */
2982
+ interface EvalRegression {
2983
+ metric: 'precisionAtK' | 'recallAtK' | 'mrr' | 'ndcgAtK' | 'map';
2984
+ baseline: number;
2985
+ candidate: number;
2986
+ delta: number;
2987
+ }
2988
+ declare function detectRetrievalRegressions(baseline: RetrievalEvalSummary, candidate: RetrievalEvalSummary, tolerance?: number): EvalRegression[];
2989
+
2990
+ /**
2991
+ * Retrieval health diagnostics — a read-only `doctor` for a Lattice database's
2992
+ * search surface. It reports, without mutating anything:
2993
+ *
2994
+ * - which retrieval extensions are available/installed (FTS5, pgvector,
2995
+ * sqlite-vec, pg_trgm),
2996
+ * - per-table full-text and embedding coverage (how many base rows are
2997
+ * actually indexed/embedded vs how many exist),
2998
+ * - staleness and gaps surfaced as severity-ranked issues.
2999
+ *
3000
+ * The point is proactive detection: index or embedding drift is otherwise
3001
+ * invisible until a user notices bad results. `diagnoseRetrieval` surfaces it
3002
+ * first, and `lattice doctor` puts it one command away. Everything here is a
3003
+ * `SELECT`/introspection — no DDL, no writes, both dialects.
3004
+ */
3005
+
3006
+ type HealthSeverity = 'info' | 'warning' | 'error';
3007
+ type HealthIssueKind = 'fts_missing' | 'fts_stale' | 'fts_empty' | 'embedding_missing' | 'embedding_stale' | 'extension_missing' | 'dimension_mismatch' | 'index_stale';
3008
+ interface RetrievalHealthIssue {
3009
+ /** Table the issue concerns, or undefined for a global/extension issue. */
3010
+ table?: string;
3011
+ kind: HealthIssueKind;
3012
+ severity: HealthSeverity;
3013
+ message: string;
3014
+ /** Optional remediation hint. */
3015
+ hint?: string;
3016
+ }
3017
+ /** Availability of the retrieval extensions on this connection. */
3018
+ interface ExtensionAvailability {
3019
+ /** SQLite compiled with FTS5. */
3020
+ fts5?: boolean;
3021
+ /** SQLite sqlite-vec extension loaded (vec_version() resolves). */
3022
+ sqliteVec?: boolean;
3023
+ /** Postgres pgvector installed (CREATE EXTENSION vector done). */
3024
+ pgvectorInstalled?: boolean;
3025
+ /** Postgres pgvector available to install. */
3026
+ pgvectorAvailable?: boolean;
3027
+ /** Postgres pg_trgm installed. */
3028
+ pgTrgmInstalled?: boolean;
3029
+ }
3030
+ interface TableHealth {
3031
+ table: string;
3032
+ /** Non-deleted base rows. */
3033
+ rowCount: number;
3034
+ /** Rows present in the FTS index, when one exists. */
3035
+ ftsIndexed?: number;
3036
+ /** ftsIndexed / rowCount, in [0, 1]. */
3037
+ ftsCoverage?: number;
3038
+ /** Embeddings stored for this table. */
3039
+ embeddingCount?: number;
3040
+ /** embeddingCount / rowCount, in [0, 1]. */
3041
+ embeddingCoverage?: number;
3042
+ issues: RetrievalHealthIssue[];
3043
+ }
3044
+ interface RetrievalHealthReport {
3045
+ dialect: 'sqlite' | 'postgres';
3046
+ extensions: ExtensionAvailability;
3047
+ tables: TableHealth[];
3048
+ /** Global (non-table) issues, e.g. a missing extension. */
3049
+ issues: RetrievalHealthIssue[];
3050
+ /** True when no `error`-severity issue exists anywhere. */
3051
+ healthy: boolean;
3052
+ }
3053
+ /** What a table is expected to support, so gaps can be flagged as errors. */
3054
+ interface RetrievalHealthSpec {
3055
+ table: string;
3056
+ /** Table opted into full-text search. */
3057
+ expectFts?: boolean;
3058
+ /** Table opted into embeddings. */
3059
+ expectEmbeddings?: boolean;
3060
+ /** Known embedding dimension (reserved for dimension checks). */
3061
+ embeddingDim?: number;
3062
+ }
3063
+ interface DiagnoseOptions {
3064
+ /**
3065
+ * Tables to diagnose with their expected capabilities. When omitted, the
3066
+ * doctor reports extension availability and embedding coverage for every
3067
+ * table that already has stored embeddings, but cannot flag "missing"
3068
+ * (it has no expectations to compare against).
3069
+ */
3070
+ tables?: RetrievalHealthSpec[];
3071
+ /**
3072
+ * Coverage below which a partially-indexed/embedded table is flagged stale.
3073
+ * Default 1 — anything short of full coverage is a `warning`.
3074
+ */
3075
+ staleThreshold?: number;
3076
+ }
3077
+ /**
3078
+ * Produce a retrieval health report for the given connection.
3079
+ *
3080
+ * Read-only and dialect-agnostic. Pass `tables` (with expectations) to get
3081
+ * missing-index / missing-embedding errors; omit it for a capability + coverage
3082
+ * snapshot only.
3083
+ */
3084
+ declare function diagnoseRetrieval(adapter: StorageAdapter, opts?: DiagnoseOptions): Promise<RetrievalHealthReport>;
3085
+ /** Render a report as a human-readable multi-line string (for `lattice doctor`). */
3086
+ declare function formatHealthReport(report: RetrievalHealthReport): string;
3087
+
3088
+ /**
3089
+ * Reproducible retrieval benchmark harness.
3090
+ *
3091
+ * Produces the speed-to-answer numbers a buyer would benchmark you on —
3092
+ * p50/p95/p99 latency for filtered query, full-text search, vector search, and
3093
+ * SQL aggregation — plus ingest throughput, all on synthetic data at a
3094
+ * configurable scale, on either dialect. It exercises the *real* code paths
3095
+ * (the same `fullTextSearch` / `searchByEmbedding` / SQL the library serves in
3096
+ * production), so the numbers are honest, and it ships in the package so the
3097
+ * same harness that gates regressions in CI can be re-run by anyone.
3098
+ *
3099
+ * Default scale is small so a CI SLO gate runs in seconds; override via the
3100
+ * `scale` option (or the `LATTICE_BENCH_ROWS` / `LATTICE_BENCH_QUERIES` /
3101
+ * `LATTICE_BENCH_DIM` env vars) to reproduce the large-n published numbers.
3102
+ *
3103
+ * The default embedder is a dependency-free deterministic token-hash vector —
3104
+ * it measures latency/throughput honestly without pulling in a model. Pass your
3105
+ * own `embed` to benchmark with real vectors.
3106
+ */
3107
+
3108
+ interface LatencyStats {
3109
+ count: number;
3110
+ min: number;
3111
+ max: number;
3112
+ mean: number;
3113
+ p50: number;
3114
+ p95: number;
3115
+ p99: number;
3116
+ }
3117
+ interface BenchmarkScale {
3118
+ /** Rows inserted into the synthetic table. */
3119
+ rows: number;
3120
+ /** Distinct queries timed for each measured operation. */
3121
+ queries: number;
3122
+ /** Embedding dimensionality. */
3123
+ dim: number;
3124
+ }
3125
+ interface BenchmarkReport {
3126
+ dialect: 'sqlite' | 'postgres';
3127
+ scale: BenchmarkScale;
3128
+ ingest: {
3129
+ rows: number;
3130
+ ms: number;
3131
+ rowsPerSec: number;
3132
+ };
3133
+ query: LatencyStats;
3134
+ fts: LatencyStats;
3135
+ vector: LatencyStats;
3136
+ aggregate: LatencyStats;
3137
+ /** Peak resident-set bytes observed during the vector-search phase. */
3138
+ peakRssBytes: number;
3139
+ /**
3140
+ * Whether the `vector` numbers reflect the NATIVE index (pgvector/sqlite-vec)
3141
+ * or the in-process O(n) scan fallback. `false` means no extension was present,
3142
+ * so `vector.p95` is the scan baseline — not the indexed number. Surfaced so a
3143
+ * published benchmark can never present the scan as the index.
3144
+ */
3145
+ vectorIndexed: boolean;
3146
+ }
3147
+ interface BenchmarkOptions {
3148
+ scale?: Partial<BenchmarkScale>;
3149
+ /** Embedder; defaults to a deterministic dependency-free token-hash vector. */
3150
+ embed?: (text: string) => Promise<number[]>;
3151
+ /** Table name for the synthetic data (dropped + recreated). Default `_lattice_bench`. */
3152
+ table?: string;
3153
+ }
3154
+ declare function percentile(sortedAsc: number[], p: number): number;
3155
+ declare function latencyStats(samples: number[]): LatencyStats;
3156
+ /**
3157
+ * Run the benchmark against an adapter. Creates a synthetic table, populates it,
3158
+ * builds an FTS index + embeddings, times each operation, and drops the table.
3159
+ */
3160
+ declare function benchmarkRetrieval(adapter: StorageAdapter, opts?: BenchmarkOptions): Promise<BenchmarkReport>;
3161
+ /** A service-level objective for a single latency metric, in milliseconds. */
3162
+ interface RetrievalSlo {
3163
+ metric: 'query.p95' | 'fts.p95' | 'vector.p95' | 'aggregate.p95';
3164
+ maxMs: number;
3165
+ }
3166
+ interface SloViolation extends RetrievalSlo {
3167
+ observedMs: number;
3168
+ }
3169
+ /** Check a report against SLOs; returns the violations (empty = all pass). */
3170
+ declare function checkSlos(report: BenchmarkReport, slos: RetrievalSlo[]): SloViolation[];
3171
+
2044
3172
  /**
2045
3173
  * Thrown by Lattice.seed when onUnresolvedLink: 'throw' is set and one or more
2046
3174
  * junction links could not be created because their target rows did not
@@ -2126,6 +3254,18 @@ declare class Lattice {
2126
3254
  private readonly _writeHooks;
2127
3255
  /** Optional cap on per-row payload bytes; see LatticeOptions.maxRowBytes. */
2128
3256
  private _maxRowBytes;
3257
+ /** Optional default bounded-read cap; see LatticeOptions.defaultMaxRows. */
3258
+ private _defaultMaxRows;
3259
+ /** table → immutable provenance column names (governance: P-PROV). */
3260
+ private readonly _provenanceCols;
3261
+ /** table → default trust state for new rows (governance: P-TRUST). */
3262
+ private readonly _trustDefault;
3263
+ /** table → computed-column specs + recompute order + dep set (P-VIEW). */
3264
+ private readonly _computed;
3265
+ /** table → materialized rollup specs (P-VIEW). */
3266
+ private readonly _rollups;
3267
+ /** source table → parents whose rollup it feeds (for incremental recompute). */
3268
+ private readonly _rollupSources;
2129
3269
  /**
2130
3270
  * Reject the row if its payload exceeds `_maxRowBytes`. Cost is dominated
2131
3271
  * by Buffer.byteLength() on string columns; we skip numbers/booleans
@@ -2350,6 +3490,12 @@ declare class Lattice {
2350
3490
  * inside a GUC-scoped transaction.
2351
3491
  */
2352
3492
  private _prepareInsert;
3493
+ /**
3494
+ * Stamp governance defaults at insert time: auto-set `ingested_at` for a
3495
+ * provenance table (when not supplied) and the default `_trust_state` for a
3496
+ * trust table. Returns a shallow copy; a no-op for tables without governance.
3497
+ */
3498
+ private _applyGovernanceDefaults;
2353
3499
  /** Post-insert side effects (changelog, audit, write hooks, embedding sync),
2354
3500
  * identical for the plain and force-visibility insert paths. */
2355
3501
  private _afterInsert;
@@ -2363,6 +3509,31 @@ declare class Lattice {
2363
3509
  upsert(table: string, row: Row): Promise<string>;
2364
3510
  upsertBy(table: string, col: string, val: unknown, row: Row): Promise<string>;
2365
3511
  update(table: string, id: PkLookup, row: Partial<Row>, provenance?: ChangeProvenance): Promise<void>;
3512
+ /** Compute a table's computed columns from a (full) row, returning the merged row. */
3513
+ private _applyComputedColumns;
3514
+ /**
3515
+ * On update, if the changed columns include any computed-column dependency,
3516
+ * fetch + decrypt the current row, merge the changes, recompute the computed
3517
+ * columns, and fold them into the update payload. No-op otherwise.
3518
+ */
3519
+ private _recomputeComputedOnUpdate;
3520
+ /** Recompute parent rollup(s) for the FK values carried on a source row. */
3521
+ private _propagateRollupsFromRow;
3522
+ /** Recompute the parent rollup(s) fed by a changed source row (fetched by id). */
3523
+ private _propagateRollups;
3524
+ /** Recompute a single rollup cell for one parent row. */
3525
+ private _recomputeRollupCell;
3526
+ /**
3527
+ * Recompute all computed columns for every row of a table (a full pass). Use
3528
+ * after a bulk import that bypassed the per-row recompute, or after changing a
3529
+ * computed definition. Requires `computed` config.
3530
+ */
3531
+ refreshComputedColumns(table: string): Promise<number>;
3532
+ /**
3533
+ * Recompute all materialized rollups for every row of a table (a full,
3534
+ * authoritative pass). Requires `materializedRollups` config.
3535
+ */
3536
+ refreshMaterializedRollups(table: string): Promise<number>;
2366
3537
  /**
2367
3538
  * Update a row and return the full updated row. Equivalent to `update()`
2368
3539
  * followed by `get()`.
@@ -2485,8 +3656,147 @@ declare class Lattice {
2485
3656
  * @returns Matching rows with similarity scores, sorted best-first.
2486
3657
  */
2487
3658
  search(table: string, query: string, opts?: SearchOptions): Promise<SearchResult[]>;
3659
+ /**
3660
+ * Hybrid search — fuse semantic (vector) and full-text retrieval with
3661
+ * Reciprocal Rank Fusion, with optional deterministic ranking signals
3662
+ * (recency / reward / custom) and an optional reranker. Returns fused results
3663
+ * with a per-result score breakdown (`explain`). The vector arm is enabled
3664
+ * when the table has `embeddings` config; otherwise it is full-text only.
3665
+ */
3666
+ hybridSearch(table: string, query: string, opts?: Omit<HybridSearchOptions, 'embeddingsConfig' | 'pkColumn'>): Promise<HybridSearchResult[]>;
3667
+ /**
3668
+ * Backfill / re-embed a table's vectors incrementally — embed only rows that
3669
+ * are missing, model-stale, or changed since a timestamp, sweeping embeddings
3670
+ * whose source row is gone. Honors `deleted_at`. Requires `embeddings` config.
3671
+ */
3672
+ refreshEmbeddings(table: string, opts?: RefreshEmbeddingsOptions): Promise<EmbeddingRefreshResult>;
3673
+ /**
3674
+ * Build (or rebuild) a native vector index (pgvector / sqlite-vec) for `table`
3675
+ * from the stored embeddings, so semantic search uses an indexed
3676
+ * approximate-nearest-neighbor lookup instead of an in-process scan. Returns
3677
+ * the number of vectors indexed; a no-op (returns 0) when no native vector
3678
+ * extension is available, unless `requireExtension` is set. Requires
3679
+ * `embeddings` config (to determine the vector dimension).
3680
+ */
3681
+ buildVectorIndex(table: string, requireExtension?: boolean): Promise<number>;
3682
+ /**
3683
+ * Evaluate a retriever against a labeled query set, returning the standard IR
3684
+ * metrics (P@k / Recall@k / MRR / nDCG@k / MAP). The retriever is any
3685
+ * `(query) => rankedRowIds` function, so this grades semantic search,
3686
+ * full-text search, a hybrid fusion, or an external service — and can gate
3687
+ * retrieval-quality regressions in CI.
3688
+ */
3689
+ evaluateRetrieval(queries: EvalQuery[], retriever: Retriever, opts?: RetrievalEvalOptions): Promise<RetrievalEvalSummary>;
3690
+ /**
3691
+ * Diagnose the database's retrieval health: extension availability plus
3692
+ * per-table full-text and embedding coverage, with gaps/staleness surfaced as
3693
+ * severity-ranked issues. Read-only. When `tables` is omitted, the expectations
3694
+ * are derived from each registered table's `fts` / `embeddings` config.
3695
+ */
3696
+ diagnoseRetrieval(opts?: {
3697
+ tables?: RetrievalHealthSpec[];
3698
+ }): Promise<RetrievalHealthReport>;
3699
+ /**
3700
+ * Run the reproducible retrieval benchmark against this connection and return
3701
+ * latency percentiles + ingest throughput. Default scale is small (CI-fast);
3702
+ * pass `scale` (or set LATTICE_BENCH_* env vars) to reproduce large-n numbers.
3703
+ */
3704
+ benchmarkRetrieval(opts?: BenchmarkOptions): Promise<BenchmarkReport>;
2488
3705
  query(table: string, opts?: QueryOptions): Promise<Row[]>;
3706
+ /**
3707
+ * Keyset (cursor) pagination — stable, index-friendly paging that stays fast
3708
+ * arbitrarily deep into a result set (unlike OFFSET, which scans-and-discards).
3709
+ * Returns a page plus an opaque `nextCursor` (null on the last page).
3710
+ */
3711
+ queryPage(table: string, opts?: QueryPageOptions): Promise<QueryPageResult>;
3712
+ /**
3713
+ * Attach declared relations to each row in `rows` (mutates in place). Each
3714
+ * relation is fetched in ONE batched `IN (...)` query — no N+1. `belongsTo`
3715
+ * attaches a single row (or null); `hasMany` attaches an array.
3716
+ */
3717
+ private _expandRelations;
2489
3718
  count(table: string, opts?: CountOptions): Promise<number>;
3719
+ /**
3720
+ * SQL-side aggregation — `COUNT`/`SUM`/`AVG`/`MIN`/`MAX` with optional
3721
+ * `GROUP BY` and `HAVING`, computed in the database so only the grouped result
3722
+ * rows transfer (never the underlying rows). Returns one object per group with
3723
+ * the groupBy columns and each aggregate under its `as` key.
3724
+ *
3725
+ * @example
3726
+ * ```ts
3727
+ * await db.aggregate('orders', {
3728
+ * groupBy: ['status'],
3729
+ * aggregates: [{ fn: 'count', as: 'n' }, { fn: 'sum', col: 'total', as: 'revenue' }],
3730
+ * having: [{ aggregate: 'n', op: 'gt', val: 10 }],
3731
+ * orderBy: 'revenue', orderDir: 'desc',
3732
+ * });
3733
+ * ```
3734
+ */
3735
+ aggregate(table: string, opts: AggregateOptions): Promise<AggregateResult[]>;
3736
+ private _assertTrust;
3737
+ /**
3738
+ * Mark a row `verified` — sets `_trust_state='verified'`, `_verified_by`, and
3739
+ * `_verified_at` (now). Requires `trust` config on the table.
3740
+ */
3741
+ verifyRow(table: string, id: PkLookup, verifiedBy?: string): Promise<void>;
3742
+ /**
3743
+ * Flag a row for human review — sets `_trust_state='needs_review'` and an
3744
+ * optional `_review_reason`. Requires `trust` config on the table.
3745
+ */
3746
+ markRowForReview(table: string, id: PkLookup, reason?: string): Promise<void>;
3747
+ /** Rows currently in `needs_review` state (non-deleted). Requires `trust` config. */
3748
+ rowsNeedingReview(table: string): Promise<Row[]>;
3749
+ /** Rows currently in `verified` state (non-deleted). Requires `trust` config. */
3750
+ verifiedRows(table: string): Promise<Row[]>;
3751
+ /** Add (upsert) a typed edge between two rows. */
3752
+ addEdge(edge: GraphEdge): Promise<void>;
3753
+ /** Add (upsert) many typed edges. */
3754
+ addEdges(edges: GraphEdge[]): Promise<void>;
3755
+ /** Remove an edge (all types between the pair when `type` omitted). */
3756
+ removeEdge(edge: Omit<GraphEdge, 'weight' | 'type'> & {
3757
+ type?: string;
3758
+ }): Promise<void>;
3759
+ /** Direct neighbors (one hop) of a node. */
3760
+ neighbors(node: GraphNode, opts?: {
3761
+ direction?: TraversalDirection;
3762
+ edgeTypes?: string[];
3763
+ }): Promise<GraphEdge[]>;
3764
+ /** Bounded BFS from a node (depth ≤ 5, node-count capped). */
3765
+ traverseGraph(start: GraphNode, opts?: TraversalOptions): Promise<GraphTraversalResult>;
3766
+ /** Zero-LLM edge extraction from a foreign-key column. Returns the edge count. */
3767
+ extractEdges(spec: ExtractEdgesSpec): Promise<number>;
3768
+ /**
3769
+ * Graph-augmented hybrid search: run {@link hybridSearch}, then boost results
3770
+ * that are graph-adjacent to the `anchors` (e.g. the user's current-context
3771
+ * entities), so relationship-relevant rows rank higher. Returns the reranked
3772
+ * hybrid results (the graph boost is folded into each score).
3773
+ */
3774
+ graphSearch(table: string, query: string, opts: Omit<HybridSearchOptions, 'embeddingsConfig' | 'pkColumn'> & {
3775
+ anchors: GraphNode[];
3776
+ graphWeight?: number;
3777
+ graphDepth?: number;
3778
+ graphDirection?: TraversalDirection;
3779
+ graphEdgeTypes?: string[];
3780
+ }): Promise<HybridSearchResult[]>;
3781
+ /**
3782
+ * Enable keyless cloud file-byte access cloud-wide (Postgres cloud only).
3783
+ * Installs the in-database SigV4 presigner + `pgcrypto`, stores the owner's
3784
+ * least-privilege S3 key in an **owner-only, member-unreadable** table, and
3785
+ * grants the cloud's member group EXECUTE on `lattice_presign_file` — so every
3786
+ * current + future member can presign GET/PUT URLs for the `files` rows they're
3787
+ * allowed to see, holding no key themselves. One owner action turns it on for
3788
+ * the whole cloud.
3789
+ */
3790
+ enableCloudFilePresigning(secret: CloudS3Secret, opts?: {
3791
+ memberGroup?: string;
3792
+ }): Promise<void>;
3793
+ /**
3794
+ * Presign a GET/PUT URL for a `files` row, computed inside Postgres and gated
3795
+ * on the caller's row-visibility (the keyless-member path). Requires the
3796
+ * presigner to be installed + an S3 secret configured
3797
+ * ({@link enableCloudFilePresigning}). TTL is capped at 60s server-side.
3798
+ */
3799
+ presignFile(fileId: string, method: 'GET' | 'PUT', ttlSeconds?: number): Promise<string>;
2490
3800
  render(outputDir: string, opts?: RenderOptions): Promise<RenderResult>;
2491
3801
  /**
2492
3802
  * Render into `outputDir` through the shared single-flight guard, intended to
@@ -2510,7 +3820,10 @@ declare class Lattice {
2510
3820
  * rendered context tree is read THROUGH the member's RLS connection + masking
2511
3821
  * views — making the on-disk tree the viewer's own scoped projection. Owner /
2512
3822
  * local SQLite leave it unset → identity → unchanged behavior. Set on the
2513
- * engine (not per-render-call) so the opts-less auto-render path masks too.
3823
+ * SchemaManager (the read layer), not per-render-call, so the opts-less
3824
+ * auto-render path masks too — AND so the reverse-sync engine, which reads the
3825
+ * same SchemaManager, writes a member's file edit back through the masked view
3826
+ * instead of the REVOKE'd base table. One resolver, every reader.
2514
3827
  */
2515
3828
  setRenderReadRelation(fn: (table: string) => string): void;
2516
3829
  /**
@@ -3008,6 +4321,17 @@ declare function parseConfigFile(configPath: string): ParsedConfig;
3008
4321
  */
3009
4322
  declare function parseConfigString(yamlContent: string, configDir: string): ParsedConfig;
3010
4323
 
4324
+ /**
4325
+ * Thrown by a bounded read (`QueryOptions.maxRows` or `defaultMaxRows`) when more
4326
+ * rows match than the cap allows and no explicit `limit` was given — forcing the
4327
+ * caller to paginate instead of silently loading an unbounded result set.
4328
+ */
4329
+ declare class BoundedReadError extends Error {
4330
+ readonly table: string;
4331
+ readonly maxRows: number;
4332
+ constructor(table: string, maxRows: number);
4333
+ }
4334
+
3011
4335
  declare function contentHash(content: string): string;
3012
4336
 
3013
4337
  /**
@@ -3552,6 +4876,123 @@ declare class PostgresAdapter implements StorageAdapter {
3552
4876
  private _registerPolyfills;
3553
4877
  }
3554
4878
 
4879
+ /**
4880
+ * Durable retry for transient database failures.
4881
+ *
4882
+ * Under contention a database returns retryable errors that a robust app should
4883
+ * simply re-attempt: SQLite `SQLITE_BUSY`, Postgres serialization failures
4884
+ * (`40001`) and deadlocks (`40P01` / `40P02`), and dropped connections. `withRetry`
4885
+ * re-runs an operation through a bounded, decorrelated-jitter backoff so these
4886
+ * blips don't surface as user-facing failures.
4887
+ *
4888
+ * CRITICAL: only wrap **idempotent** work — a whole bulk operation or a Lattice
4889
+ * API method that is safe to re-run, NOT a raw non-idempotent `adapter.run()`
4890
+ * (re-running an `INSERT` after a mid-statement connection drop could double-apply
4891
+ * it). A nested `withRetry` is detected and does NOT add a second retry layer, so
4892
+ * composing retry-wrapped helpers can't multiply the attempt count.
4893
+ */
4894
+ interface RetryOptions {
4895
+ /** Maximum attempts including the first. Default 5. */
4896
+ maxAttempts?: number;
4897
+ /** Base backoff in ms. Default 50. */
4898
+ baseDelayMs?: number;
4899
+ /** Backoff ceiling in ms. Default 2000. */
4900
+ maxDelayMs?: number;
4901
+ /** Override the retryable-error classifier. */
4902
+ isRetryable?: (err: unknown) => boolean;
4903
+ /** Called before each retry (for logging/metrics). */
4904
+ onRetry?: (err: unknown, attempt: number, delayMs: number) => void;
4905
+ /** Injectable RNG in [0,1) for deterministic tests. Default Math.random. */
4906
+ random?: () => number;
4907
+ /** Injectable sleep for deterministic tests. Default real setTimeout. */
4908
+ sleep?: (ms: number) => Promise<void>;
4909
+ }
4910
+ /** Default classifier: SQLITE_BUSY / locked, retryable PG SQLSTATEs, dropped sockets. */
4911
+ declare function isRetryableDbError(err: unknown): boolean;
4912
+ /**
4913
+ * Run `fn`, retrying transient DB failures with decorrelated-jitter backoff.
4914
+ * A nested call (already inside a `withRetry`) runs `fn` directly without a
4915
+ * second retry layer.
4916
+ *
4917
+ * @throws the last error if every attempt fails, or immediately for a
4918
+ * non-retryable error.
4919
+ */
4920
+ declare function withRetry<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
4921
+
4922
+ /**
4923
+ * Online, resumable migrations.
4924
+ *
4925
+ * A naive backfill that updates a whole table in one statement takes a long
4926
+ * table lock — a maintenance window — and, if killed partway, has to restart
4927
+ * from zero. A chunked migration instead walks the table's primary key in
4928
+ * batches, each its own short transaction, and records progress in a checkpoint
4929
+ * table after every batch. So it never holds a long lock, and a kill (deploy,
4930
+ * crash, OOM) is recoverable: `resumeMigration` picks up after the last
4931
+ * checkpointed key instead of redoing completed work.
4932
+ *
4933
+ * The per-batch `apply` callback MUST be idempotent — a batch can re-run if the
4934
+ * process dies between applying it and committing its checkpoint.
4935
+ */
4936
+
4937
+ type MigrationStatus = 'running' | 'complete' | 'reverted';
4938
+ interface MigrationCheckpoint {
4939
+ id: string;
4940
+ table: string;
4941
+ lastPk: string | null;
4942
+ processed: number;
4943
+ status: MigrationStatus;
4944
+ startedAt: string;
4945
+ updatedAt: string;
4946
+ }
4947
+ interface ChunkedMigrationOptions {
4948
+ /** Unique, stable id for this migration (the resume key). */
4949
+ id: string;
4950
+ /** Table to walk. */
4951
+ table: string;
4952
+ /** Process one batch of rows. MUST be idempotent. */
4953
+ apply: (rows: Row[], adapter: StorageAdapter) => Promise<void>;
4954
+ /** Rows per batch. Default 500. */
4955
+ batchSize?: number;
4956
+ /** Primary-key column to walk (must be sortable). Default 'id'. */
4957
+ pkColumn?: string;
4958
+ /** Optional WHERE predicate (without the leading WHERE) to scope rows. */
4959
+ where?: string;
4960
+ /** Bound params for `where`. */
4961
+ whereParams?: unknown[];
4962
+ }
4963
+ interface ChunkedMigrationResult {
4964
+ id: string;
4965
+ processed: number;
4966
+ batches: number;
4967
+ status: MigrationStatus;
4968
+ }
4969
+ /** Ensure the checkpoint table exists (idempotent). */
4970
+ declare function ensureCheckpointTable(adapter: StorageAdapter): Promise<void>;
4971
+ declare function getMigrationCheckpoint(adapter: StorageAdapter, id: string): Promise<MigrationCheckpoint | null>;
4972
+ declare function listMigrationCheckpoints(adapter: StorageAdapter): Promise<MigrationCheckpoint[]>;
4973
+ /**
4974
+ * Apply a chunked migration. Creates a checkpoint and walks the table in
4975
+ * batches, committing progress after each. If a checkpoint for `id` already
4976
+ * exists (a prior killed run), it resumes from there. Re-running a completed
4977
+ * migration is a no-op.
4978
+ */
4979
+ declare function applyChunkedMigration(adapter: StorageAdapter, opts: ChunkedMigrationOptions): Promise<ChunkedMigrationResult>;
4980
+ /**
4981
+ * Resume a previously-started (and not completed) chunked migration. Throws if
4982
+ * no checkpoint exists for `id` — use {@link applyChunkedMigration} to start one.
4983
+ */
4984
+ declare function resumeMigration(adapter: StorageAdapter, opts: ChunkedMigrationOptions): Promise<ChunkedMigrationResult>;
4985
+ /**
4986
+ * Revert a migration: walk the processed rows in batches applying `revert`, then
4987
+ * mark the checkpoint `reverted`. `revert` must be idempotent.
4988
+ */
4989
+ declare function revertMigration(adapter: StorageAdapter, id: string, table: string, revert: (rows: Row[], adapter: StorageAdapter) => Promise<void>, opts?: {
4990
+ batchSize?: number;
4991
+ pkColumn?: string;
4992
+ where?: string;
4993
+ whereParams?: unknown[];
4994
+ }): Promise<ChunkedMigrationResult>;
4995
+
3555
4996
  /**
3556
4997
  * Framework-shipped tables that every Lattice can opt into via
3557
4998
  * {@link registerNativeEntities}. These tables are intentionally generic —
@@ -4181,6 +5622,13 @@ declare function isPrivateIp(ip: string): boolean;
4181
5622
  interface FtsHit {
4182
5623
  id: string;
4183
5624
  snippet: string;
5625
+ /**
5626
+ * Relevance score, higher = better. Populated by the indexed tier
5627
+ * (`ts_rank` on Postgres, `-bm25` on SQLite FTS5). Absent / 0 for the LIKE
5628
+ * fallback tier, which has no ranking model. Used to order hits and as the
5629
+ * FTS signal in hybrid fusion.
5630
+ */
5631
+ score?: number;
4184
5632
  }
4185
5633
  interface FtsGroup {
4186
5634
  table: string;
@@ -4225,6 +5673,66 @@ declare function hasFtsIndex(adapter: StorageAdapter, table: string): Promise<bo
4225
5673
  */
4226
5674
  declare function fullTextSearch(adapter: StorageAdapter, tables: string[], opts: FtsOptions): Promise<FtsResult>;
4227
5675
 
5676
+ /**
5677
+ * Native indexed vector search.
5678
+ *
5679
+ * The in-process cosine scan in `embeddings.ts` loads and scores every stored
5680
+ * vector per query — O(n), fine at small n but a disqualifier at enterprise
5681
+ * scale. When the database provides an approximate-nearest-neighbor index this
5682
+ * module builds and queries it instead, turning vector search into an indexed
5683
+ * ~O(log n) lookup that stays flat as n grows.
5684
+ *
5685
+ * - **Postgres + pgvector:** a per-table `_lattice_vec_<table>` with a
5686
+ * `vector(dim)` column and an HNSW index on cosine distance (`<=>`).
5687
+ * - **SQLite + sqlite-vec:** a per-table `vec0` virtual table (used when the
5688
+ * extension has been loaded into the connection).
5689
+ *
5690
+ * The JSON store in `_lattice_embeddings` remains the portable source of record;
5691
+ * this index is a DERIVED accelerator built from it (mirroring how the FTS index
5692
+ * derives from the base table). When no extension is present, callers fall back
5693
+ * to the in-process scan, and `lattice doctor` reports the missing extension.
5694
+ *
5695
+ * The index is opt-in: `buildVectorIndex` populates it from the JSON store, and
5696
+ * search uses it only when `hasVectorIndex` is true — so the default behavior is
5697
+ * unchanged for users who never call it.
5698
+ */
5699
+
5700
+ /**
5701
+ * Per-table native vector index name. The table is grammar-guarded here because
5702
+ * the returned name is interpolated into DDL (`CREATE TABLE "..."`, `DROP`,
5703
+ * `INSERT`); every build/drop/search path derives the index name through this
5704
+ * one function, so a single guard at the choke point covers them all.
5705
+ */
5706
+ declare function vectorIndexName(table: string): string;
5707
+ interface VectorHit {
5708
+ pk: string;
5709
+ chunkIndex: number;
5710
+ content: string | null;
5711
+ /** Cosine similarity in [0, 1] (1 − cosine distance). */
5712
+ score: number;
5713
+ }
5714
+ /** Whether this connection has a usable native vector extension. */
5715
+ declare function vectorIndexAvailable(adapter: StorageAdapter): Promise<boolean>;
5716
+ /** Whether a native vector index table exists for `table`. */
5717
+ declare function hasVectorIndex(adapter: StorageAdapter, table: string): Promise<boolean>;
5718
+ /**
5719
+ * Build (or rebuild) the native vector index for `table` from the JSON store,
5720
+ * for vectors of dimension `dim`. No-op when no native extension is available.
5721
+ * Returns the number of vectors indexed.
5722
+ *
5723
+ * @throws when called with an unavailable extension *and* `requireExtension` is
5724
+ * true — surfacing a misconfiguration loudly rather than silently doing
5725
+ * nothing. By default it is a reported no-op (returns 0).
5726
+ */
5727
+ declare function buildVectorIndex(adapter: StorageAdapter, table: string, dim: number, requireExtension?: boolean): Promise<number>;
5728
+ /** Drop a table's native vector index. */
5729
+ declare function dropVectorIndex(adapter: StorageAdapter, table: string): Promise<void>;
5730
+ /**
5731
+ * Query the native vector index for the nearest chunks to `queryVector`.
5732
+ * Returns up to `limit` hits with cosine similarity scores ≥ `minScore`.
5733
+ */
5734
+ declare function searchVectorIndex(adapter: StorageAdapter, table: string, queryVector: number[], limit: number, minScore: number): Promise<VectorHit[]>;
5735
+
4228
5736
  /**
4229
5737
  * Reference-ingestion API — parallel to {@link attachBlob}, but records a row
4230
5738
  * that *indexes* data living elsewhere instead of copying bytes. The returned
@@ -5250,4 +6758,4 @@ declare class FileSourceKeyStore implements SourceKeyStore {
5250
6758
  private encodeFile;
5251
6759
  }
5252
6760
 
5253
- export { type AddWorkspaceOptions, type AdoptNativeOptions, type AdoptResult, type ApplyWriteResult, type AudienceRowCtx, type AuditEvent, type AutoUpdateResult, type BelongsToRelation, type BelongsToSource, type BlobMetadata, type BuiltinTemplateName, CLOUD_SETTING_SYSTEM_PROMPT, CLOUD_SETTING_WORKSPACE_LOGO, CLOUD_SETTING_WORKSPACE_LOGO_ETAG, CONFIG_SUBDIR, type CatalogEntity, type CatalogRecord, type ChangeEntry, type ChangelogOptions, type ClassifyMatch, type CleanupOptions, type CleanupResult, type CloudProbeResult, type CountOptions, type CrawlOptions, type CrawlResult, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_TYPE_ALIASES, type DiscoveredTable, type EmbeddingsConfig, type EnrichOptions, type EnrichResult, type EnrichedSource, type EnrichmentLookup, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type ExtractedObject, FileSourceKeyStore, type FileSourceKeyStoreOptions, type FilesRow, type Filter, type FilterOp, FoldCache, type FtsConfig, type FtsGroup, type FtsHit, type FtsOptions, type FtsResult, type GuiServerHandle, type HasManyRelation, type HasManySource, InMemorySourceKeyStore, InMemoryStateStore, type InitOptions, LEGACY_MEMBER_GROUP, LOCAL_DB_RELPATH, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type LlmClient, type LlmMessage, type ManyToManySource, type MarkdownTableColumn, type MigrateResult, type Migration, type MigrationOptions, type MigrationProgress, type MigrationResult, type MultiTableDefinition, NATIVE_ENTITY_DEFS, NATIVE_ENTITY_NAMES, NATIVE_REGISTRY_TABLE, type Observation, type OrderBySpec, type OrganizeOptions, type OrganizeResult, type OrganizedCreation, type OrganizedLink, type ParseError, type ParseResult, type ParsedConfig, type PdfOptions, type PdfSenderInput, type PkLookup, PostgresAdapter, type PostgresAdapterOptions, type PreparedStatement, type PrimaryKey, ProgressThrottle, type QueryOptions, READ_ONLY_HEADER, ROOT_DIRNAME, type ReadOnlyHeaderOptions, type ReconcileOptions, type ReconcileResult, type RefKind, type RefProvider, type ReferenceMetadata, ReferenceUnavailableError, type Relation, type RemoteBlobStore, type RenderHooks, type RenderOptions, type RenderProgress, type RenderProgressCallback, type RenderProgressKind, type RenderResult, type RenderSpec, type ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type ResolveOptions, type ReverseSeedDetection, type ReverseSeedResult, type ReverseSeedTableResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type RewardScores, type Row, type RowVisibilityDefault, type S3Config, type S3StoreConfig, S3UnavailableError, SQLiteAdapter, type SchemaEntity, type SearchOptions, type SearchResult, type SecurityOptions, type SeedConfig, type SeedLinkSpec, SeedReconciliationError, type SeedResult, type SelfSource, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SourceHandle, type SourceKeyStore, type SourceMetadata, type SourceQueryOptions, SourceShreddedError, type StartGuiServerOptions, type StopFn, type StorageAdapter, type SyncResult, type TableDefinition, type TablePolicy, type TemplateRenderSpec, type TurnParams, type TurnResult, type UnresolvedLink, type UpsertByNaturalKeyOptions, type UserIdentity, type UserPreferences, type Viewer, type VisionOptions, type VisionSenderInput, WORKSPACES_SUBDIR, type WatchOptions, type WorkspacePaths, type WorkspaceRecord, type WorkspaceRegistry, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, type WritebackValidationResult, activeWorkspaceLabel, addWorkspace, adoptNativeEntities, analyticsEnabled, applyTokenBudget, applyWriteEntry, archiveLocalSqlite, assertSafeUrl, attachBlob, audiencePredicate, audienceViewSql, autoFtsColumns, autoUpdate, backfillOwnership, canManageRoles, classifyLinks, cloudRlsInstalled, configDir, contentHash, crawlUrl, createReadOnlyHeader, createS3Store, createSQLiteStateStore, decrypt, defaultWorkspaceYaml, deleteDbCredential, deleteToken, deriveCanonicalContexts, deriveKey, describeImage, describePdf, discoverCloudTables, enableAudienceView, enableChangelogRls, enableRlsForTable, encrypt, enrichKnowledge, ensureFtsIndex, ensureLatticeRoot, entityFileNames, estimateTokens, extractObjects, findLatticeRoot, fixSchemaConflicts, foldEntity, frontmatter, ftsTableName, fullTextSearch, generateEntryId, generateMemberPassword, generateWriteEntryId, getActiveWorkspace, getCloudSetting, getDbCredential, getOrCreateMasterKey, getTablePolicy, getWorkspace, hasFtsIndex, hashFile, importLegacyUserConfig, installCloudRls, installCloudSettings, isEncrypted, isNativeEntity, isPostgresUrl, isPrivateIp, isRowAudience, listDbCredentials, listNativeBindings, listTokens, listWorkspaces, loadColumnPolicy, manifestPath, markdownTable, memberGroupFor, memberRoleName, migrateLatticeData, observationVisible, observationsFromChange, openTargetLatticeForMigration, openUnderSource, organizeSource, parseConfigFile, parseConfigString, parseMarkdownEntries, parseMatches, parseObjects, parseSessionMD, parseSessionWrites, probeCloud, providerForUrl, provisionMemberRole, readIdentity, readManifest, readPreferences, readRegistry, readToken, referenceLocalFile, referenceUrl, regenerateAudienceViewFromDb, registerNativeEntities, registryPath, resolveActiveS3Config, resolveLatticeRoot, resolveSource, resolveWorkspacePaths, revokeMemberRole, rootConfigDir, s3Key, saveDbCredential, saveDbCredentialForTeam, sealUnderSource, secureCloud, seedColumnPolicyFromYaml, setActiveWorkspace, setCloudSetting, setColumnAudience, setRowVisibility, setTableDefaultVisibility, setTableNeverShare, shredSource, slugify, startGuiServer, summarizeText, tableNeedsAudienceView, toSafeDirName, truncate, validateEntryId, workspaceBlobsDir, workspaceConfigPath, workspaceContextDir, workspaceDataDir, workspaceDbPath, workspaceDir, workspacesDir, writeIdentity, writeManifest, writePreferences, writeRegistry, writeToken };
6761
+ export { ALL_PROVENANCE_FIELDS, type AddWorkspaceOptions, type AdoptNativeOptions, type AdoptResult, type AggregateFunction, type AggregateHaving, type AggregateOptions, type AggregateResult, type AggregateSpec, type ApplyWriteResult, type AudienceRowCtx, type AuditEvent, type AutoUpdateResult, type BacklinkSignal, type BelongsToRelation, type BelongsToSource, type BenchmarkOptions, type BenchmarkReport, type BenchmarkScale, type BlobMetadata, BoundedReadError, type BuiltinTemplateName, CLOUD_SETTING_SYSTEM_PROMPT, CLOUD_SETTING_WORKSPACE_LOGO, CLOUD_SETTING_WORKSPACE_LOGO_ETAG, CONFIG_SUBDIR, type CatalogEntity, type CatalogRecord, type ChangeEntry, type ChangelogOptions, type ChunkedMigrationOptions, type ChunkedMigrationResult, type ChunkerFn, type ClassifyMatch, type CleanupOptions, type CleanupResult, type CloudProbeResult, type CloudS3Secret, ComputedColumnCycleError, type ComputedColumnSpec, type CountOptions, type CrawlOptions, type CrawlResult, type CustomSignal, type CustomSource, DEFAULT_ENTRY_TYPES, DEFAULT_MAX_NODES, DEFAULT_TYPE_ALIASES, type DiagnoseOptions, type DiscoveredTable, EMBEDDINGS_TABLE, EmbeddingDimensionMismatchError, type EmbeddingRefreshResult, type EmbeddingsConfig, type EnrichOptions, type EnrichResult, type EnrichedSource, type EnrichmentLookup, type EntityContextDefinition, type EntityContextManifestEntry, type EntityFileManifestInfo, type EntityFileSource, type EntityFileSpec, type EntityProfileField, type EntityProfileSection, type EntityProfileTemplate, type EntityRenderSpec, type EntityRenderTemplate, type EntitySectionPerRow, type EntitySectionsTemplate, type EntityTableColumn, type EntityTableTemplate, type EvalQuery, type EvalRegression, type ExtensionAvailability, type ExtractEdgesSpec, type ExtractedObject, FileSourceKeyStore, type FileSourceKeyStoreOptions, type FilesRow, type Filter, type FilterAnd, type FilterExpr, type FilterOp, type FilterOr, FoldCache, type FtsConfig, type FtsGroup, type FtsHit, type FtsOptions, type FtsResult, type GraphBoostOptions, type GraphBoostResult, type GraphEdge, type GraphNode, type GraphTraversalResult, type GuiServerHandle, type HasManyRelation, type HasManySource, type HealthIssueKind, type HealthSeverity, type HybridScoreBreakdown, type HybridSearchOptions, type HybridSearchResult, InMemorySourceKeyStore, InMemoryStateStore, type InitOptions, LEGACY_MEMBER_GROUP, LOCAL_DB_RELPATH, type LatencyStats, Lattice, type LatticeConfig, type LatticeConfigInput, type LatticeEntityDef, type LatticeEntityRenderSpec, type LatticeFieldDef, type LatticeFieldType, type LatticeManifest, type LatticeOptions, type LinkOptions, type LlmClient, type LlmMessage, MAX_TRAVERSAL_DEPTH, type ManyToManySource, type MarkdownTableColumn, type MaterializedRollupSpec, type MigrateResult, type Migration, type MigrationCheckpoint, type MigrationOptions, type MigrationProgress, type MigrationResult, type MigrationStatus, type MultiTableDefinition, NATIVE_ENTITY_DEFS, NATIVE_ENTITY_NAMES, NATIVE_REGISTRY_TABLE, type Observation, type OrderBySpec, type OrganizeOptions, type OrganizeResult, type OrganizedCreation, type OrganizedLink, type ParseError, type ParseResult, type ParsedConfig, type PdfOptions, type PdfSenderInput, type PerQueryEval, type PkLookup, PostgresAdapter, type PostgresAdapterOptions, type PreparedStatement, type PrimaryKey, ProgressThrottle, type ProvenanceConfig, type ProvenanceField, ProvenanceImmutableError, type QueryOptions, type QueryPageOptions, type QueryPageResult, type QueryProjection, READ_ONLY_HEADER, ROOT_DIRNAME, type RankingOptions, type ReadOnlyHeaderOptions, type RecencySignal, type ReconcileOptions, type ReconcileResult, type RefKind, type RefProvider, type ReferenceMetadata, ReferenceUnavailableError, type RefreshEmbeddingsOptions, type Relation, type RelevanceLabel, type RemoteBlobStore, type RenderHooks, type RenderOptions, type RenderProgress, type RenderProgressCallback, type RenderProgressKind, type RenderResult, type RenderSpec, type ReportConfig, type ReportResult, type ReportSection, type ReportSectionResult, type RerankCandidate, type RerankScore, type RerankerFn, type ResolveOptions, type RetrievalEvalOptions, type RetrievalEvalSummary, type RetrievalHealthIssue, type RetrievalHealthReport, type RetrievalHealthSpec, type RetrievalSlo, type Retriever, type RetryOptions, type ReverseSeedDetection, type ReverseSeedResult, type ReverseSeedTableResult, type ReverseSyncError, type ReverseSyncResult, type ReverseSyncUpdate, type RewardScores, type RewardSignal, type RollupFunction, type Row, type RowVisibilityDefault, type S3Config, type S3StoreConfig, S3UnavailableError, S3_SECRET_TABLE, SQLiteAdapter, type SchemaEntity, type SearchOptions, type SearchResult, type SecurityOptions, type SeedConfig, type SeedLinkSpec, SeedReconciliationError, type SeedResult, type SelfSource, type SemanticChunkerOptions, type SessionEntry, type SessionParseOptions, type SessionWriteEntry, type SessionWriteOp, type SessionWriteParseResult, type SloViolation, type SourceHandle, type SourceKeyStore, type SourceMetadata, type SourceQueryOptions, SourceShreddedError, type StartGuiServerOptions, type StopFn, type StorageAdapter, type SyncResult, TRUST_COLUMNS, type TableDefinition, type TableHealth, type TablePolicy, type TemplateRenderSpec, type TextChunk, type TraversalDirection, type TraversalNode, type TraversalOptions, type TrustConfig, type TrustState, type TurnParams, type TurnResult, type UnresolvedLink, type UpsertByNaturalKeyOptions, type UserIdentity, type UserPreferences, type VectorHit, type Viewer, type VisionOptions, type VisionSenderInput, WORKSPACES_SUBDIR, type WatchOptions, type WorkspacePaths, type WorkspaceRecord, type WorkspaceRegistry, type WriteHook, type WriteHookContext, type WritebackDefinition, type WritebackStateStore, type WritebackValidationResult, activeWorkspaceLabel, addEdge, addEdges, addWorkspace, adoptNativeEntities, allComputedDeps, analyticsEnabled, applyChunkedMigration, applyReranker, applyTokenBudget, applyWriteEntry, archiveLocalSqlite, assertSafeUrl, attachBlob, audiencePredicate, audienceViewSql, autoFtsColumns, autoUpdate, backfillOwnership, backlinkBoost, benchmarkRetrieval, buildVectorIndex, canManageRoles, checkSlos, chunkText, classifyLinks, cloudRlsInstalled, computeColumns, computedColumnDdl, computedColumnOrder, concatRowText, configDir, contentHash, cosineSimilarity, crawlUrl, createReadOnlyHeader, createS3Store, createSQLiteStateStore, decrypt, defaultWorkspaceYaml, deleteDbCredential, deleteToken, deriveCanonicalContexts, deriveKey, describeImage, describePdf, detectRetrievalRegressions, diagnoseRetrieval, discoverCloudTables, dropVectorIndex, enableAudienceView, enableChangelogRls, enableRlsForTable, encrypt, enrichKnowledge, ensureCheckpointTable, ensureEdgesTable, ensureEmbeddingsTable, ensureFtsIndex, ensureLatticeRoot, entityFileNames, estimateTokens, evaluateRetrieval, extractEdgesFromColumn, extractObjects, filePresignSql, findLatticeRoot, fixSchemaConflicts, foldEntity, formatHealthReport, frontmatter, ftsTableName, fullTextSearch, generateEntryId, generateMemberPassword, generateWriteEntryId, getActiveWorkspace, getCloudSetting, getDbCredential, getMigrationCheckpoint, getOrCreateMasterKey, getTablePolicy, getWorkspace, grantPresignerToMemberGroup, graphAdjacencyBoost, hasFilePresigner, hasFtsIndex, hasVectorIndex, hashFile, hybridSearch, importLegacyUserConfig, installCloudRls, installCloudSettings, installFilePresigner, isEncrypted, isNativeEntity, isPostgresUrl, isPrivateIp, isRetryableDbError, isRowAudience, latencyStats, listDbCredentials, listMigrationCheckpoints, listNativeBindings, listTokens, listWorkspaces, loadColumnPolicy, manifestPath, markdownTable, memberGroupFor, memberRoleName, migrateLatticeData, neighbors, observationVisible, observationsFromChange, openTargetLatticeForMigration, openUnderSource, organizeSource, parseConfigFile, parseConfigString, parseMarkdownEntries, parseMatches, parseObjects, parseSessionMD, parseSessionWrites, percentile, probeCloud, provenanceColumns, providerForUrl, provisionMemberRole, rankingBoost, readIdentity, readManifest, readPreferences, readRegistry, readToken, recencyBoost, referenceLocalFile, referenceUrl, refreshEmbeddings, regenerateAudienceViewFromDb, registerNativeEntities, registryPath, removeEdge, removeEmbedding, resolveActiveS3Config, resolveLatticeRoot, resolveProvenanceFields, resolveSource, resolveTrustDefault, resolveWorkspacePaths, resumeMigration, revertMigration, revokeMemberRole, rewardBoost, rollupColumnDdl, rootConfigDir, s3Key, saveDbCredential, saveDbCredentialForTeam, sealUnderSource, searchByEmbedding, searchVectorIndex, secureCloud, seedColumnPolicyFromYaml, semanticChunker, setActiveWorkspace, setCloudS3Secret, setCloudSetting, setColumnAudience, setRowVisibility, setTableDefaultVisibility, setTableNeverShare, shredSource, slugify, startGuiServer, storeEmbedding, summarizeText, tableNeedsAudienceView, toSafeDirName, traverse, truncate, validateEntryId, vectorIndexAvailable, vectorIndexName, withRetry, workspaceBlobsDir, workspaceConfigPath, workspaceContextDir, workspaceDataDir, workspaceDbPath, workspaceDir, workspacesDir, writeIdentity, writeManifest, writePreferences, writeRegistry, writeToken };