@lix-js/sdk 0.6.0-preview.3 → 0.6.0-preview.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +105 -65
  3. package/dist/engine-wasm/index.js +4 -4
  4. package/dist/engine-wasm/wasm/lix_engine.d.ts +30 -6
  5. package/dist/engine-wasm/wasm/lix_engine.js +187 -117
  6. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  7. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +14 -8
  8. package/dist/generated/builtin-schemas.d.ts +69 -69
  9. package/dist/generated/builtin-schemas.js +94 -94
  10. package/dist/open-lix.d.ts +42 -28
  11. package/dist/open-lix.js +49 -10
  12. package/dist/sqlite/index.js +86 -30
  13. package/dist-engine-src/README.md +3 -3
  14. package/dist-engine-src/src/backend/capabilities.rs +67 -0
  15. package/dist-engine-src/src/backend/conformance/baseline.rs +1127 -0
  16. package/dist-engine-src/src/backend/conformance/factory.rs +93 -0
  17. package/dist-engine-src/src/backend/conformance/failure_tests.rs +608 -0
  18. package/dist-engine-src/src/backend/conformance/fixtures.rs +26 -0
  19. package/dist-engine-src/src/backend/conformance/mod.rs +75 -0
  20. package/dist-engine-src/src/backend/conformance/model.rs +28 -0
  21. package/dist-engine-src/src/backend/conformance/model_based.rs +257 -0
  22. package/dist-engine-src/src/backend/conformance/persistence.rs +204 -0
  23. package/dist-engine-src/src/backend/conformance/projection.rs +21 -0
  24. package/dist-engine-src/src/backend/conformance/pushdown.rs +24 -0
  25. package/dist-engine-src/src/backend/conformance/runner.rs +90 -0
  26. package/dist-engine-src/src/backend/conformance/scan.rs +24 -0
  27. package/dist-engine-src/src/backend/conformance/write.rs +16 -0
  28. package/dist-engine-src/src/backend/error.rs +94 -0
  29. package/dist-engine-src/src/backend/in_memory.rs +670 -0
  30. package/dist-engine-src/src/backend/mod.rs +36 -9
  31. package/dist-engine-src/src/backend/predicate.rs +80 -0
  32. package/dist-engine-src/src/backend/traits.rs +260 -0
  33. package/dist-engine-src/src/backend/types.rs +224 -81
  34. package/dist-engine-src/src/binary_cas/context.rs +8 -8
  35. package/dist-engine-src/src/binary_cas/kv.rs +234 -259
  36. package/dist-engine-src/src/{version → branch}/context.rs +12 -12
  37. package/dist-engine-src/src/branch/lifecycle.rs +221 -0
  38. package/dist-engine-src/src/branch/mod.rs +13 -0
  39. package/dist-engine-src/src/branch/refs.rs +321 -0
  40. package/dist-engine-src/src/branch/stage_rows.rs +67 -0
  41. package/dist-engine-src/src/branch/types.rs +21 -0
  42. package/dist-engine-src/src/catalog/context.rs +18 -18
  43. package/dist-engine-src/src/catalog/snapshot.rs +8 -8
  44. package/dist-engine-src/src/changelog/bench_support.rs +785 -0
  45. package/dist-engine-src/src/changelog/change.rs +1 -0
  46. package/dist-engine-src/src/changelog/codec.rs +497 -0
  47. package/dist-engine-src/src/changelog/commit.rs +1 -0
  48. package/dist-engine-src/src/changelog/context.rs +1614 -0
  49. package/dist-engine-src/src/changelog/mod.rs +29 -0
  50. package/dist-engine-src/src/changelog/store.rs +163 -0
  51. package/dist-engine-src/src/changelog/test_support.rs +54 -0
  52. package/dist-engine-src/src/changelog/types.rs +213 -0
  53. package/dist-engine-src/src/commit_graph/context.rs +317 -274
  54. package/dist-engine-src/src/commit_graph/mod.rs +2 -4
  55. package/dist-engine-src/src/commit_graph/types.rs +22 -42
  56. package/dist-engine-src/src/commit_graph/walker.rs +133 -103
  57. package/dist-engine-src/src/common/error.rs +52 -18
  58. package/dist-engine-src/src/common/identity.rs +2 -2
  59. package/dist-engine-src/src/common/mod.rs +1 -1
  60. package/dist-engine-src/src/domain.rs +42 -46
  61. package/dist-engine-src/src/engine.rs +74 -96
  62. package/dist-engine-src/src/{entity_identity.rs → entity_pk.rs} +89 -92
  63. package/dist-engine-src/src/functions/context.rs +56 -52
  64. package/dist-engine-src/src/functions/state.rs +51 -52
  65. package/dist-engine-src/src/init.rs +288 -154
  66. package/dist-engine-src/src/json_store/context.rs +15 -266
  67. package/dist-engine-src/src/json_store/mod.rs +26 -0
  68. package/dist-engine-src/src/json_store/store.rs +103 -718
  69. package/dist-engine-src/src/json_store/types.rs +4 -9
  70. package/dist-engine-src/src/lib.rs +49 -19
  71. package/dist-engine-src/src/live_state/context.rs +654 -790
  72. package/dist-engine-src/src/live_state/mod.rs +9 -3
  73. package/dist-engine-src/src/live_state/overlay.rs +4 -4
  74. package/dist-engine-src/src/live_state/types.rs +30 -21
  75. package/dist-engine-src/src/live_state/visibility.rs +514 -71
  76. package/dist-engine-src/src/plugin/install.rs +48 -48
  77. package/dist-engine-src/src/plugin/manifest.rs +7 -7
  78. package/dist-engine-src/src/plugin/materializer.rs +0 -275
  79. package/dist-engine-src/src/plugin/plugin_manifest.json +4 -3
  80. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +2 -2
  81. package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +34 -0
  82. package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +48 -0
  83. package/dist-engine-src/src/schema/builtin/lix_change.json +3 -3
  84. package/dist-engine-src/src/schema/builtin/lix_commit.json +1 -1
  85. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +6 -6
  86. package/dist-engine-src/src/schema/builtin/mod.rs +18 -20
  87. package/dist-engine-src/src/schema/compatibility.rs +11 -11
  88. package/dist-engine-src/src/schema/definition.json +2 -2
  89. package/dist-engine-src/src/schema/definition.rs +5 -5
  90. package/dist-engine-src/src/schema/key.rs +3 -3
  91. package/dist-engine-src/src/schema/mod.rs +1 -1
  92. package/dist-engine-src/src/schema/tests.rs +18 -18
  93. package/dist-engine-src/src/session/context.rs +819 -124
  94. package/dist-engine-src/src/session/create_branch.rs +94 -0
  95. package/dist-engine-src/src/session/execute.rs +260 -57
  96. package/dist-engine-src/src/session/merge/analysis.rs +9 -3
  97. package/dist-engine-src/src/session/merge/{version.rs → branch.rs} +119 -129
  98. package/dist-engine-src/src/session/merge/conflicts.rs +2 -2
  99. package/dist-engine-src/src/session/merge/mod.rs +5 -6
  100. package/dist-engine-src/src/session/merge/stats.rs +7 -11
  101. package/dist-engine-src/src/session/mod.rs +19 -16
  102. package/dist-engine-src/src/session/switch_branch.rs +113 -0
  103. package/dist-engine-src/src/session/transaction.rs +557 -0
  104. package/dist-engine-src/src/sql2/bind/classify.rs +102 -0
  105. package/dist-engine-src/src/sql2/bind/error.rs +5 -0
  106. package/dist-engine-src/src/sql2/bind/expr.rs +29 -0
  107. package/dist-engine-src/src/sql2/bind/mod.rs +12 -0
  108. package/dist-engine-src/src/sql2/{udfs/public_call.rs → bind/public_udf.rs} +98 -3
  109. package/dist-engine-src/src/sql2/bind/read.rs +65 -0
  110. package/dist-engine-src/src/sql2/bind/statement.rs +2236 -0
  111. package/dist-engine-src/src/sql2/bind/table.rs +273 -0
  112. package/dist-engine-src/src/sql2/bind/write.rs +86 -0
  113. package/dist-engine-src/src/sql2/branch_scope.rs +436 -0
  114. package/dist-engine-src/src/sql2/catalog/capability.rs +20 -0
  115. package/dist-engine-src/src/sql2/catalog/entity_surface.rs +296 -0
  116. package/dist-engine-src/src/sql2/catalog/mod.rs +15 -0
  117. package/dist-engine-src/src/sql2/catalog/registry.rs +556 -0
  118. package/dist-engine-src/src/sql2/catalog/schema.rs +88 -0
  119. package/dist-engine-src/src/sql2/catalog/surface.rs +41 -0
  120. package/dist-engine-src/src/sql2/change_materialization.rs +122 -0
  121. package/dist-engine-src/src/sql2/context.rs +36 -30
  122. package/dist-engine-src/src/sql2/error.rs +4 -5
  123. package/dist-engine-src/src/sql2/exec/bound_public_write.rs +1593 -0
  124. package/dist-engine-src/src/sql2/exec/datafusion.rs +5266 -0
  125. package/dist-engine-src/src/sql2/exec/fast_write.rs +82 -0
  126. package/dist-engine-src/src/sql2/exec/mod.rs +24 -0
  127. package/dist-engine-src/src/sql2/exec/write.rs +661 -0
  128. package/dist-engine-src/src/sql2/filesystem_planner.rs +72 -77
  129. package/dist-engine-src/src/sql2/filesystem_visibility.rs +21 -21
  130. package/dist-engine-src/src/sql2/history_projection.rs +8 -8
  131. package/dist-engine-src/src/sql2/history_route.rs +35 -31
  132. package/dist-engine-src/src/sql2/mod.rs +30 -24
  133. package/dist-engine-src/src/sql2/optimize/datafusion.rs +1 -0
  134. package/dist-engine-src/src/sql2/optimize/mod.rs +2 -0
  135. package/dist-engine-src/src/sql2/optimize/simple_write.rs +116 -0
  136. package/dist-engine-src/src/sql2/parse/mod.rs +69 -0
  137. package/dist-engine-src/src/sql2/parse/normalize.rs +1 -0
  138. package/dist-engine-src/src/sql2/plan/branch_scope.rs +24 -0
  139. package/dist-engine-src/src/sql2/plan/mod.rs +5 -0
  140. package/dist-engine-src/src/sql2/plan/predicate.rs +22 -0
  141. package/dist-engine-src/src/sql2/plan/write.rs +147 -0
  142. package/dist-engine-src/src/sql2/predicate_typecheck.rs +258 -0
  143. package/dist-engine-src/src/sql2/{version_provider.rs → providers/branch.rs} +218 -214
  144. package/dist-engine-src/src/sql2/{change_provider.rs → providers/change.rs} +156 -42
  145. package/dist-engine-src/src/sql2/{directory_provider.rs → providers/directory.rs} +291 -322
  146. package/dist-engine-src/src/sql2/{directory_history_provider.rs → providers/directory_history.rs} +56 -42
  147. package/dist-engine-src/src/sql2/providers/entity.rs +1484 -0
  148. package/dist-engine-src/src/sql2/{entity_history_provider.rs → providers/entity_history.rs} +43 -31
  149. package/dist-engine-src/src/sql2/{file_provider.rs → providers/file.rs} +323 -316
  150. package/dist-engine-src/src/sql2/{file_history_provider.rs → providers/file_history.rs} +60 -46
  151. package/dist-engine-src/src/sql2/{history_provider.rs → providers/history.rs} +46 -32
  152. package/dist-engine-src/src/sql2/{lix_state_provider.rs → providers/lix_state.rs} +359 -329
  153. package/dist-engine-src/src/sql2/providers/mod.rs +508 -0
  154. package/dist-engine-src/src/sql2/read_only.rs +2 -2
  155. package/dist-engine-src/src/sql2/session.rs +47 -96
  156. package/dist-engine-src/src/sql2/storage/constraints.rs +1 -0
  157. package/dist-engine-src/src/sql2/storage/mod.rs +1 -0
  158. package/dist-engine-src/src/sql2/test_support/differential.rs +712 -0
  159. package/dist-engine-src/src/sql2/test_support/generators.rs +354 -0
  160. package/dist-engine-src/src/sql2/test_support/mod.rs +2 -0
  161. package/dist-engine-src/src/sql2/udfs/{lix_active_version_commit_id.rs → lix_active_branch_commit_id.rs} +7 -7
  162. package/dist-engine-src/src/sql2/udfs/mod.rs +3 -6
  163. package/dist-engine-src/src/sql2/write_normalization.rs +45 -22
  164. package/dist-engine-src/src/storage/conformance.rs +399 -0
  165. package/dist-engine-src/src/storage/context.rs +552 -288
  166. package/dist-engine-src/src/storage/mod.rs +48 -10
  167. package/dist-engine-src/src/storage/point.rs +440 -0
  168. package/dist-engine-src/src/storage/read_scope.rs +43 -64
  169. package/dist-engine-src/src/storage/reader.rs +867 -0
  170. package/dist-engine-src/src/storage/scan.rs +784 -0
  171. package/dist-engine-src/src/storage/spaces.rs +236 -0
  172. package/dist-engine-src/src/storage/stats.rs +80 -0
  173. package/dist-engine-src/src/storage/write_set.rs +962 -0
  174. package/dist-engine-src/src/storage_bench.rs +136 -4828
  175. package/dist-engine-src/src/test_support.rs +360 -138
  176. package/dist-engine-src/src/tracked_state/bench_support.rs +394 -0
  177. package/dist-engine-src/src/tracked_state/codec.rs +155 -1057
  178. package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +358 -0
  179. package/dist-engine-src/src/tracked_state/context.rs +1927 -993
  180. package/dist-engine-src/src/tracked_state/diff.rs +1715 -261
  181. package/dist-engine-src/src/tracked_state/merge.rs +74 -88
  182. package/dist-engine-src/src/tracked_state/mod.rs +19 -16
  183. package/dist-engine-src/src/tracked_state/{materialization.rs → row_materialization.rs} +50 -178
  184. package/dist-engine-src/src/tracked_state/storage.rs +243 -191
  185. package/dist-engine-src/src/tracked_state/tree.rs +247 -371
  186. package/dist-engine-src/src/tracked_state/types.rs +49 -42
  187. package/dist-engine-src/src/transaction/bench_support.rs +407 -0
  188. package/dist-engine-src/src/transaction/commit.rs +821 -713
  189. package/dist-engine-src/src/transaction/context.rs +705 -600
  190. package/dist-engine-src/src/transaction/mod.rs +13 -2
  191. package/dist-engine-src/src/transaction/normalization.rs +63 -76
  192. package/dist-engine-src/src/transaction/prep.rs +13 -13
  193. package/dist-engine-src/src/transaction/schema_resolver.rs +19 -5
  194. package/dist-engine-src/src/transaction/staging.rs +228 -434
  195. package/dist-engine-src/src/transaction/types.rs +41 -98
  196. package/dist-engine-src/src/transaction/validation.rs +382 -446
  197. package/dist-engine-src/src/untracked_state/codec.rs +337 -29
  198. package/dist-engine-src/src/untracked_state/context.rs +7 -7
  199. package/dist-engine-src/src/untracked_state/materialization.rs +2 -2
  200. package/dist-engine-src/src/untracked_state/mod.rs +1 -1
  201. package/dist-engine-src/src/untracked_state/storage.rs +659 -157
  202. package/dist-engine-src/src/untracked_state/types.rs +21 -21
  203. package/package.json +71 -68
  204. package/dist-engine-src/src/backend/kv.rs +0 -358
  205. package/dist-engine-src/src/backend/testing.rs +0 -658
  206. package/dist-engine-src/src/commit_store/codec.rs +0 -887
  207. package/dist-engine-src/src/commit_store/context.rs +0 -944
  208. package/dist-engine-src/src/commit_store/materialization.rs +0 -84
  209. package/dist-engine-src/src/commit_store/mod.rs +0 -16
  210. package/dist-engine-src/src/commit_store/storage.rs +0 -600
  211. package/dist-engine-src/src/commit_store/types.rs +0 -215
  212. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
  213. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
  214. package/dist-engine-src/src/session/create_version.rs +0 -88
  215. package/dist-engine-src/src/session/merge/apply.rs +0 -23
  216. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
  217. package/dist-engine-src/src/session/switch_version.rs +0 -109
  218. package/dist-engine-src/src/sql2/classify.rs +0 -182
  219. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  220. package/dist-engine-src/src/sql2/execute.rs +0 -3440
  221. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  222. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  223. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -166
  224. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -25
  225. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  226. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  227. package/dist-engine-src/src/storage/types.rs +0 -501
  228. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  229. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  230. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  231. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  232. package/dist-engine-src/src/version/mod.rs +0 -13
  233. package/dist-engine-src/src/version/refs.rs +0 -330
  234. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  235. package/dist-engine-src/src/version/types.rs +0 -21
@@ -1,61 +1,53 @@
1
1
  use std::collections::{BTreeMap, BTreeSet};
2
2
 
3
3
  use crate::tracked_state::{
4
- MaterializedTrackedStateRow, TrackedStateDiff, TrackedStateDiffEntry, TrackedStateDiffIdentity,
4
+ TrackedStateDiff, TrackedStateDiffEntry, TrackedStateDiffIdentity, TrackedStateDiffRow,
5
5
  };
6
6
  use crate::LixError;
7
7
 
8
8
  /// Planned tracked-state merge result.
9
9
  ///
10
- /// This is intentionally a pure planner. It does not know about versions,
10
+ /// This is intentionally a pure planner. It does not know about branches,
11
11
  /// sessions, changelog writes, or live-state overlays. Callers provide two
12
12
  /// diffs from the same merge base:
13
13
  ///
14
- /// - `base -> target`: what the destination version changed.
15
- /// - `base -> source`: what the incoming version changed.
14
+ /// - `base -> target`: what the destination branch changed.
15
+ /// - `base -> source`: what the incoming branch changed.
16
16
  ///
17
- /// The planner returns source-side patches that can be applied to the target
18
- /// root plus first-class conflicts for identities changed differently on both
19
- /// sides.
17
+ /// The planner returns source-side picks plus first-class conflicts for
18
+ /// identities changed differently on both sides.
20
19
  #[derive(Debug, Clone, PartialEq, Eq, Default)]
21
20
  pub(crate) struct TrackedStateMergePlan {
22
- pub(crate) patches: Vec<TrackedStateMergePatch>,
21
+ pub(crate) picks: Vec<TrackedStateMergePick>,
23
22
  pub(crate) conflicts: Vec<TrackedStateMergeConflict>,
24
23
  }
25
24
 
26
- /// One source-side patch to apply to the target root.
25
+ /// One source-side change selected for the merge result.
27
26
  ///
28
- /// Merge patches are expressed as canonical change adoption, not as new row
29
- /// writes. The projected row carries the target-root materialization shape,
30
- /// including tombstones, while `change_id` preserves the source canonical
31
- /// change identity.
27
+ /// Merge picks describe source-side state that will be selected into
28
+ /// the target root. The selected row carries the target-root materialization
29
+ /// shape, including tombstones.
32
30
  #[derive(Debug, Clone, PartialEq, Eq)]
33
- pub(crate) enum TrackedStateMergePatch {
34
- Adopt {
35
- identity: TrackedStateDiffIdentity,
36
- change_id: String,
37
- projected_row: MaterializedTrackedStateRow,
38
- },
31
+ pub(crate) struct TrackedStateMergePick {
32
+ pub(crate) identity: TrackedStateDiffIdentity,
33
+ pub(crate) change_id: String,
34
+ pub(crate) selected_row: TrackedStateDiffRow,
39
35
  }
40
36
 
41
- impl TrackedStateMergePatch {
37
+ impl TrackedStateMergePick {
42
38
  #[cfg(test)]
43
39
  pub(crate) fn identity(&self) -> &TrackedStateDiffIdentity {
44
- match self {
45
- Self::Adopt { identity, .. } => identity,
46
- }
40
+ &self.identity
47
41
  }
48
42
 
49
- pub(crate) fn change_id(&self) -> &str {
50
- match self {
51
- Self::Adopt { change_id, .. } => change_id,
52
- }
43
+ #[cfg(test)]
44
+ pub(crate) fn source_change_id(&self) -> &str {
45
+ &self.change_id
53
46
  }
54
47
 
55
- pub(crate) fn projected_row(&self) -> &MaterializedTrackedStateRow {
56
- match self {
57
- Self::Adopt { projected_row, .. } => projected_row,
58
- }
48
+ #[cfg(test)]
49
+ pub(crate) fn source_row(&self) -> &TrackedStateDiffRow {
50
+ &self.selected_row
59
51
  }
60
52
  }
61
53
 
@@ -70,7 +62,7 @@ pub(crate) struct TrackedStateMergeConflict {
70
62
  /// Plans a three-way tracked-state merge from two base-relative diffs.
71
63
  ///
72
64
  /// This follows the same shape as prolly-tree merge systems: compare
73
- /// `base -> target` and `base -> source` by identity, emit source-only patches
65
+ /// `base -> target` and `base -> source` by identity, emit source-only picks
74
66
  /// for the target root, ignore target-only changes, collapse convergent
75
67
  /// changes, and report divergent same-identity changes as conflicts.
76
68
  pub(crate) fn plan_merge(
@@ -94,11 +86,10 @@ pub(crate) fn plan_merge(
94
86
  (None, None) => {}
95
87
  (Some(_target), None) => {
96
88
  // Target already changed this identity. Source did not, so
97
- // there is nothing to apply.
89
+ // there is nothing to pick.
98
90
  }
99
91
  (None, Some(source)) => {
100
- plan.patches
101
- .push(adopt_source_change_patch(identity, source)?);
92
+ plan.picks.push(source_change_pick(identity, source)?);
102
93
  }
103
94
  (Some(target), Some(source)) if same_final_state(target, source) => {
104
95
  // Both sides reached the same visible state. Keep target to
@@ -122,13 +113,16 @@ fn diff_by_identity(
122
113
  ) -> Result<BTreeMap<TrackedStateDiffIdentity, &TrackedStateDiffEntry>, LixError> {
123
114
  let mut entries = BTreeMap::new();
124
115
  for entry in &diff.entries {
116
+ if entry.identity.schema_key == "lix_commit" {
117
+ continue;
118
+ }
125
119
  if entries.insert(entry.identity.clone(), entry).is_some() {
126
120
  return Err(LixError::new(
127
121
  "LIX_ERROR_UNKNOWN",
128
122
  format!(
129
123
  "tracked-state merge received duplicate diff entry for schema '{}' entity '{}'",
130
124
  entry.identity.schema_key,
131
- entry.identity.entity_id.as_json_array_text()?
125
+ entry.identity.entity_pk.as_json_array_text()?
132
126
  ),
133
127
  ));
134
128
  }
@@ -136,24 +130,24 @@ fn diff_by_identity(
136
130
  Ok(entries)
137
131
  }
138
132
 
139
- fn adopt_source_change_patch(
133
+ fn source_change_pick(
140
134
  identity: TrackedStateDiffIdentity,
141
135
  entry: &TrackedStateDiffEntry,
142
- ) -> Result<TrackedStateMergePatch, LixError> {
136
+ ) -> Result<TrackedStateMergePick, LixError> {
143
137
  let Some(row) = entry.after.clone() else {
144
138
  return Err(LixError::new(
145
139
  "LIX_ERROR_UNKNOWN",
146
140
  format!(
147
- "tracked-state merge cannot apply source removal for schema '{}' entity '{}' without a tombstone row",
141
+ "tracked-state merge cannot pick source removal for schema '{}' entity '{}' without a tombstone row",
148
142
  entry.identity.schema_key,
149
- entry.identity.entity_id.as_json_array_text()?
143
+ entry.identity.entity_pk.as_json_array_text()?
150
144
  ),
151
145
  ));
152
146
  };
153
- Ok(TrackedStateMergePatch::Adopt {
147
+ Ok(TrackedStateMergePick {
154
148
  identity,
155
149
  change_id: row.change_id.clone(),
156
- projected_row: row,
150
+ selected_row: row,
157
151
  })
158
152
  }
159
153
 
@@ -168,21 +162,19 @@ fn same_final_state(target: &TrackedStateDiffEntry, source: &TrackedStateDiffEnt
168
162
  }
169
163
  }
170
164
 
171
- fn row_is_live(row: &MaterializedTrackedStateRow) -> bool {
172
- row.snapshot_content.is_some()
165
+ fn row_is_live(row: &TrackedStateDiffRow) -> bool {
166
+ !row.deleted
173
167
  }
174
168
 
175
- fn tracked_row_payload_eq(
176
- left: &MaterializedTrackedStateRow,
177
- right: &MaterializedTrackedStateRow,
178
- ) -> bool {
179
- left.snapshot_content == right.snapshot_content && left.metadata == right.metadata
169
+ fn tracked_row_payload_eq(left: &TrackedStateDiffRow, right: &TrackedStateDiffRow) -> bool {
170
+ left.snapshot_ref == right.snapshot_ref && left.metadata_ref == right.metadata_ref
180
171
  }
181
172
 
182
173
  #[cfg(test)]
183
174
  mod tests {
184
175
  use super::*;
185
- use crate::entity_identity::EntityIdentity;
176
+ use crate::entity_pk::EntityPk;
177
+ use crate::json_store::JsonRef;
186
178
  use crate::tracked_state::TrackedStateDiffKind;
187
179
 
188
180
  #[test]
@@ -198,7 +190,7 @@ mod tests {
198
190
  )
199
191
  .expect("merge should plan");
200
192
 
201
- assert_eq!(patch_ids(&plan), vec!["entity-a"]);
193
+ assert_eq!(pick_ids(&plan), vec!["entity-a"]);
202
194
  assert!(plan.conflicts.is_empty());
203
195
  }
204
196
 
@@ -215,12 +207,9 @@ mod tests {
215
207
  )
216
208
  .expect("merge should plan");
217
209
 
218
- assert_eq!(patch_ids(&plan), vec!["entity-a"]);
219
- assert_eq!(
220
- plan.patches[0].projected_row().snapshot_content.as_deref(),
221
- Some("{\"value\":\"source\"}")
222
- );
223
- assert_eq!(plan.patches[0].change_id(), "source");
210
+ assert_eq!(pick_ids(&plan), vec!["entity-a"]);
211
+ assert!(plan.picks[0].source_row().snapshot_ref.is_some());
212
+ assert_eq!(plan.picks[0].source_change_id(), "source");
224
213
  }
225
214
 
226
215
  #[test]
@@ -236,9 +225,9 @@ mod tests {
236
225
  )
237
226
  .expect("merge should plan");
238
227
 
239
- assert_eq!(patch_ids(&plan), vec!["entity-a"]);
240
- assert_eq!(plan.patches[0].projected_row().snapshot_content, None);
241
- assert_eq!(plan.patches[0].change_id(), "source-delete");
228
+ assert_eq!(pick_ids(&plan), vec!["entity-a"]);
229
+ assert!(plan.picks[0].source_row().deleted);
230
+ assert_eq!(plan.picks[0].source_change_id(), "source-delete");
242
231
  }
243
232
 
244
233
  #[test]
@@ -254,7 +243,7 @@ mod tests {
254
243
  )
255
244
  .expect("merge should plan");
256
245
 
257
- assert!(plan.patches.is_empty());
246
+ assert!(plan.picks.is_empty());
258
247
  assert!(plan.conflicts.is_empty());
259
248
  }
260
249
 
@@ -275,7 +264,7 @@ mod tests {
275
264
 
276
265
  let plan = plan_merge(&diff(vec![target]), &diff(vec![source])).expect("merge should plan");
277
266
 
278
- assert!(plan.patches.is_empty());
267
+ assert!(plan.picks.is_empty());
279
268
  assert!(plan.conflicts.is_empty());
280
269
  }
281
270
 
@@ -296,7 +285,7 @@ mod tests {
296
285
 
297
286
  let plan = plan_merge(&diff(vec![target]), &diff(vec![source])).expect("merge should plan");
298
287
 
299
- assert!(plan.patches.is_empty());
288
+ assert!(plan.picks.is_empty());
300
289
  assert!(plan.conflicts.is_empty());
301
290
  }
302
291
 
@@ -317,7 +306,7 @@ mod tests {
317
306
 
318
307
  let plan = plan_merge(&diff(vec![target]), &diff(vec![source])).expect("merge should plan");
319
308
 
320
- assert!(plan.patches.is_empty());
309
+ assert!(plan.picks.is_empty());
321
310
  assert_eq!(conflict_ids(&plan), vec!["entity-a"]);
322
311
  }
323
312
 
@@ -378,7 +367,7 @@ mod tests {
378
367
  }
379
368
 
380
369
  #[test]
381
- fn patch_and_conflict_order_is_deterministic_by_identity() {
370
+ fn pick_and_conflict_order_is_deterministic_by_identity() {
382
371
  let target = diff(vec![entry(
383
372
  "entity-b",
384
373
  TrackedStateDiffKind::Modified,
@@ -408,7 +397,7 @@ mod tests {
408
397
 
409
398
  let plan = plan_merge(&target, &source).expect("merge should plan");
410
399
 
411
- assert_eq!(patch_ids(&plan), vec!["entity-a", "entity-c"]);
400
+ assert_eq!(pick_ids(&plan), vec!["entity-a", "entity-c"]);
412
401
  assert_eq!(conflict_ids(&plan), vec!["entity-b"]);
413
402
  }
414
403
 
@@ -417,15 +406,15 @@ mod tests {
417
406
  }
418
407
 
419
408
  fn entry(
420
- entity_id: &str,
409
+ entity_pk: &str,
421
410
  kind: TrackedStateDiffKind,
422
- before: Option<MaterializedTrackedStateRow>,
423
- after: Option<MaterializedTrackedStateRow>,
411
+ before: Option<TrackedStateDiffRow>,
412
+ after: Option<TrackedStateDiffRow>,
424
413
  ) -> TrackedStateDiffEntry {
425
414
  TrackedStateDiffEntry {
426
415
  identity: TrackedStateDiffIdentity {
427
416
  schema_key: "test_schema".to_string(),
428
- entity_id: EntityIdentity::single(entity_id),
417
+ entity_pk: EntityPk::single(entity_pk),
429
418
  file_id: None,
430
419
  },
431
420
  kind,
@@ -434,13 +423,13 @@ mod tests {
434
423
  }
435
424
  }
436
425
 
437
- fn patch_ids(plan: &TrackedStateMergePlan) -> Vec<String> {
438
- plan.patches
426
+ fn pick_ids(plan: &TrackedStateMergePlan) -> Vec<String> {
427
+ plan.picks
439
428
  .iter()
440
429
  .map(|entry| {
441
430
  entry
442
431
  .identity()
443
- .entity_id
432
+ .entity_pk
444
433
  .as_single_string_owned()
445
434
  .expect("identity")
446
435
  })
@@ -453,36 +442,33 @@ mod tests {
453
442
  .map(|entry| {
454
443
  entry
455
444
  .identity
456
- .entity_id
445
+ .entity_pk
457
446
  .as_single_string_owned()
458
447
  .expect("identity")
459
448
  })
460
449
  .collect()
461
450
  }
462
451
 
463
- fn tombstone(entity_id: &str, change_id: &str) -> MaterializedTrackedStateRow {
464
- let mut row = row(entity_id, change_id);
465
- row.snapshot_content = None;
452
+ fn tombstone(entity_pk: &str, change_id: &str) -> TrackedStateDiffRow {
453
+ let mut row = row(entity_pk, change_id);
454
+ row.snapshot_ref = None;
466
455
  row.deleted = true;
467
456
  row
468
457
  }
469
458
 
470
- fn row(entity_id: &str, change_id: &str) -> MaterializedTrackedStateRow {
471
- row_with_value(entity_id, change_id, "value")
459
+ fn row(entity_pk: &str, change_id: &str) -> TrackedStateDiffRow {
460
+ row_with_value(entity_pk, change_id, "value")
472
461
  }
473
462
 
474
- fn row_with_value(
475
- entity_id: &str,
476
- change_id: &str,
477
- value: &str,
478
- ) -> MaterializedTrackedStateRow {
479
- MaterializedTrackedStateRow {
480
- entity_id: EntityIdentity::single(entity_id),
463
+ fn row_with_value(entity_pk: &str, change_id: &str, value: &str) -> TrackedStateDiffRow {
464
+ let snapshot = format!("{{\"value\":\"{value}\"}}");
465
+ TrackedStateDiffRow {
466
+ entity_pk: EntityPk::single(entity_pk),
481
467
  schema_key: "test_schema".to_string(),
482
468
  file_id: None,
483
- snapshot_content: Some(format!("{{\"value\":\"{value}\"}}")),
484
- metadata: None,
485
469
  deleted: false,
470
+ snapshot_ref: Some(JsonRef::for_content(snapshot.as_bytes())),
471
+ metadata_ref: None,
486
472
  created_at: "2026-01-01T00:00:00Z".to_string(),
487
473
  updated_at: "2026-01-01T00:00:00Z".to_string(),
488
474
  change_id: change_id.to_string(),
@@ -1,32 +1,35 @@
1
- mod by_file_index;
1
+ #[cfg(feature = "storage-benches")]
2
+ mod bench_support;
2
3
  mod codec;
4
+ mod commit_root_rebuild;
3
5
  mod context;
4
6
  mod diff;
5
- mod materialization;
6
- mod materializer;
7
7
  mod merge;
8
+ mod row_materialization;
8
9
  mod storage;
9
10
  mod tree;
10
11
  mod types;
11
12
 
12
- #[allow(unused_imports)]
13
- pub(crate) use context::{
14
- TrackedStateContext, TrackedStateMaterializer, TrackedStateStoreReader, TrackedStateWriter,
15
- };
16
- #[allow(unused_imports)]
13
+ pub(crate) use context::{TrackedStateContext, TrackedStateStoreReader};
17
14
  pub(crate) use diff::{
18
15
  TrackedStateDiff, TrackedStateDiffEntry, TrackedStateDiffIdentity, TrackedStateDiffKind,
19
- TrackedStateDiffRequest,
16
+ TrackedStateDiffRequest, TrackedStateDiffRow,
20
17
  };
21
- pub(crate) use materialization::{materialize_index_entries, TrackedMaterializationProjection};
22
- #[allow(unused_imports)]
23
18
  pub(crate) use merge::{
24
- plan_merge, TrackedStateMergeConflict, TrackedStateMergePatch, TrackedStateMergePlan,
19
+ plan_merge, TrackedStateMergeConflict, TrackedStateMergePick, TrackedStateMergePlan,
20
+ };
21
+ pub(crate) use row_materialization::{
22
+ materialize_rows_from_index_entries, TrackedRowMaterialization,
25
23
  };
26
- pub(crate) use storage::{load_delta_pack, DeltaJsonPackIndexesRef};
27
- #[allow(unused_imports)]
24
+ #[cfg(feature = "storage-benches")]
25
+ pub(crate) use storage::{TRACKED_STATE_COMMIT_ROOT_SPACE, TRACKED_STATE_TREE_CHUNK_SPACE};
26
+ #[cfg(any(test, feature = "storage-benches"))]
27
+ pub(crate) use types::TrackedStateKey;
28
28
  pub(crate) use types::{
29
- MaterializedTrackedStateRow, TrackedStateDeltaRef, TrackedStateFilter,
30
- TrackedStateIndexValueRef, TrackedStateKeyRef, TrackedStateProjection, TrackedStateRowRequest,
29
+ MaterializedTrackedStateRow, TrackedStateDeltaRef, TrackedStateFilter, TrackedStateReadColumns,
31
30
  TrackedStateScanRequest,
32
31
  };
32
+ #[cfg(feature = "storage-benches")]
33
+ pub mod bench {
34
+ pub use super::bench_support::*;
35
+ }