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

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 (165) hide show
  1. package/SKILL.md +4 -5
  2. package/dist/engine-wasm/wasm/lix_engine.js +1 -1
  3. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  4. package/dist/generated/builtin-schemas.d.ts +87 -162
  5. package/dist/generated/builtin-schemas.js +139 -236
  6. package/dist/open-lix.d.ts +1 -1
  7. package/dist-engine-src/src/binary_cas/types.rs +0 -6
  8. package/dist-engine-src/src/catalog/context.rs +412 -0
  9. package/dist-engine-src/src/catalog/mod.rs +10 -0
  10. package/dist-engine-src/src/catalog/schema.rs +4 -0
  11. package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
  12. package/dist-engine-src/src/cel/mod.rs +1 -1
  13. package/dist-engine-src/src/cel/provider.rs +1 -1
  14. package/dist-engine-src/src/commit_graph/context.rs +328 -1015
  15. package/dist-engine-src/src/commit_graph/mod.rs +2 -3
  16. package/dist-engine-src/src/commit_graph/types.rs +7 -43
  17. package/dist-engine-src/src/commit_graph/walker.rs +57 -81
  18. package/dist-engine-src/src/commit_store/codec.rs +887 -0
  19. package/dist-engine-src/src/commit_store/context.rs +944 -0
  20. package/dist-engine-src/src/commit_store/materialization.rs +84 -0
  21. package/dist-engine-src/src/commit_store/mod.rs +16 -0
  22. package/dist-engine-src/src/commit_store/storage.rs +600 -0
  23. package/dist-engine-src/src/commit_store/types.rs +215 -0
  24. package/dist-engine-src/src/common/identity.rs +15 -5
  25. package/dist-engine-src/src/common/json_pointer.rs +67 -0
  26. package/dist-engine-src/src/common/metadata.rs +17 -12
  27. package/dist-engine-src/src/common/mod.rs +5 -5
  28. package/dist-engine-src/src/domain.rs +324 -0
  29. package/dist-engine-src/src/engine.rs +29 -43
  30. package/dist-engine-src/src/entity_identity.rs +238 -118
  31. package/dist-engine-src/src/functions/context.rs +17 -52
  32. package/dist-engine-src/src/functions/deterministic.rs +1 -1
  33. package/dist-engine-src/src/functions/mod.rs +1 -1
  34. package/dist-engine-src/src/functions/provider.rs +4 -4
  35. package/dist-engine-src/src/functions/state.rs +39 -66
  36. package/dist-engine-src/src/functions/types.rs +1 -1
  37. package/dist-engine-src/src/init.rs +204 -151
  38. package/dist-engine-src/src/json_store/context.rs +354 -60
  39. package/dist-engine-src/src/json_store/encoded.rs +6 -6
  40. package/dist-engine-src/src/json_store/mod.rs +4 -1
  41. package/dist-engine-src/src/json_store/store.rs +884 -11
  42. package/dist-engine-src/src/json_store/types.rs +166 -1
  43. package/dist-engine-src/src/lib.rs +10 -9
  44. package/dist-engine-src/src/live_state/context.rs +608 -830
  45. package/dist-engine-src/src/live_state/mod.rs +3 -3
  46. package/dist-engine-src/src/live_state/overlay.rs +7 -7
  47. package/dist-engine-src/src/live_state/reader.rs +5 -5
  48. package/dist-engine-src/src/live_state/types.rs +19 -36
  49. package/dist-engine-src/src/live_state/visibility.rs +19 -14
  50. package/dist-engine-src/src/plugin/archive.rs +3 -6
  51. package/dist-engine-src/src/plugin/install.rs +0 -18
  52. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
  53. package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
  54. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
  55. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
  56. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
  57. package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
  58. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
  59. package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
  60. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
  61. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
  62. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
  63. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
  64. package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
  65. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
  66. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
  67. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
  68. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
  69. package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
  70. package/dist-engine-src/src/schema/compatibility.rs +787 -0
  71. package/dist-engine-src/src/schema/definition.json +47 -17
  72. package/dist-engine-src/src/schema/definition.rs +202 -96
  73. package/dist-engine-src/src/schema/key.rs +9 -77
  74. package/dist-engine-src/src/schema/mod.rs +4 -4
  75. package/dist-engine-src/src/schema/tests.rs +133 -92
  76. package/dist-engine-src/src/session/context.rs +40 -42
  77. package/dist-engine-src/src/session/create_version.rs +22 -14
  78. package/dist-engine-src/src/session/execute.rs +45 -14
  79. package/dist-engine-src/src/session/merge/apply.rs +4 -4
  80. package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
  81. package/dist-engine-src/src/session/merge/stats.rs +1 -1
  82. package/dist-engine-src/src/session/merge/version.rs +35 -45
  83. package/dist-engine-src/src/session/mod.rs +4 -2
  84. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
  85. package/dist-engine-src/src/session/switch_version.rs +16 -28
  86. package/dist-engine-src/src/sql2/change_provider.rs +14 -20
  87. package/dist-engine-src/src/sql2/classify.rs +61 -26
  88. package/dist-engine-src/src/sql2/context.rs +22 -18
  89. package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
  90. package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
  91. package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
  92. package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
  93. package/dist-engine-src/src/sql2/error.rs +21 -1
  94. package/dist-engine-src/src/sql2/execute.rs +325 -264
  95. package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
  96. package/dist-engine-src/src/sql2/file_provider.rs +533 -108
  97. package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
  98. package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
  99. package/dist-engine-src/src/sql2/history_projection.rs +3 -27
  100. package/dist-engine-src/src/sql2/history_provider.rs +11 -17
  101. package/dist-engine-src/src/sql2/history_route.rs +22 -8
  102. package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
  103. package/dist-engine-src/src/sql2/mod.rs +6 -3
  104. package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
  105. package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
  106. package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
  107. package/dist-engine-src/src/sql2/public_bind/dml.rs +166 -0
  108. package/dist-engine-src/src/sql2/public_bind/mod.rs +25 -0
  109. package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
  110. package/dist-engine-src/src/sql2/read_only.rs +10 -12
  111. package/dist-engine-src/src/sql2/session.rs +7 -10
  112. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
  113. package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
  114. package/dist-engine-src/src/sql2/udfs/public_call.rs +211 -0
  115. package/dist-engine-src/src/sql2/version_provider.rs +46 -31
  116. package/dist-engine-src/src/sql2/version_scope.rs +4 -4
  117. package/dist-engine-src/src/storage_bench.rs +1782 -325
  118. package/dist-engine-src/src/test_support.rs +183 -36
  119. package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
  120. package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
  121. package/dist-engine-src/src/tracked_state/context.rs +1155 -271
  122. package/dist-engine-src/src/tracked_state/diff.rs +249 -57
  123. package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
  124. package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
  125. package/dist-engine-src/src/tracked_state/merge.rs +37 -19
  126. package/dist-engine-src/src/tracked_state/mod.rs +8 -7
  127. package/dist-engine-src/src/tracked_state/storage.rs +138 -6
  128. package/dist-engine-src/src/tracked_state/tree.rs +695 -252
  129. package/dist-engine-src/src/tracked_state/types.rs +176 -6
  130. package/dist-engine-src/src/transaction/commit.rs +695 -435
  131. package/dist-engine-src/src/transaction/context.rs +551 -310
  132. package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
  133. package/dist-engine-src/src/transaction/mod.rs +2 -0
  134. package/dist-engine-src/src/transaction/normalization.rs +311 -447
  135. package/dist-engine-src/src/transaction/prep.rs +37 -0
  136. package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
  137. package/dist-engine-src/src/transaction/staging.rs +701 -406
  138. package/dist-engine-src/src/transaction/types.rs +231 -122
  139. package/dist-engine-src/src/transaction/validation.rs +2717 -1698
  140. package/dist-engine-src/src/untracked_state/codec.rs +40 -96
  141. package/dist-engine-src/src/untracked_state/context.rs +21 -5
  142. package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
  143. package/dist-engine-src/src/untracked_state/mod.rs +3 -5
  144. package/dist-engine-src/src/untracked_state/storage.rs +105 -57
  145. package/dist-engine-src/src/untracked_state/types.rs +63 -13
  146. package/dist-engine-src/src/version/context.rs +1 -13
  147. package/dist-engine-src/src/version/lifecycle.rs +221 -0
  148. package/dist-engine-src/src/version/mod.rs +3 -2
  149. package/dist-engine-src/src/version/refs.rs +12 -103
  150. package/dist-engine-src/src/version/stage_rows.rs +15 -19
  151. package/package.json +1 -1
  152. package/dist-engine-src/src/changelog/codec.rs +0 -321
  153. package/dist-engine-src/src/changelog/context.rs +0 -92
  154. package/dist-engine-src/src/changelog/materialization.rs +0 -121
  155. package/dist-engine-src/src/changelog/mod.rs +0 -13
  156. package/dist-engine-src/src/changelog/reader.rs +0 -20
  157. package/dist-engine-src/src/changelog/storage.rs +0 -220
  158. package/dist-engine-src/src/changelog/types.rs +0 -38
  159. package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
  160. package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
  161. package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
  162. package/dist-engine-src/src/schema_registry.rs +0 -294
  163. package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
  164. package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
  165. package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
@@ -0,0 +1,324 @@
1
+ use crate::entity_identity::EntityIdentity;
2
+ use crate::live_state::MaterializedLiveStateRow;
3
+ use crate::{NullableKeyFilter, GLOBAL_VERSION_ID};
4
+
5
+ /// Validation/storage coordinate for repository facts.
6
+ ///
7
+ /// A domain is the complete scope in which a row identity is meaningful:
8
+ /// version, durability, and file scope. Projection methods on this type are
9
+ /// deliberately named so callers cannot silently erase part of the coordinate.
10
+ #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11
+ pub(crate) struct Domain {
12
+ version_id: String,
13
+ untracked: bool,
14
+ file_scope: DomainFileScope,
15
+ }
16
+
17
+ impl Domain {
18
+ pub(crate) fn exact_file(
19
+ version_id: impl Into<String>,
20
+ untracked: bool,
21
+ file_id: Option<String>,
22
+ ) -> Self {
23
+ Self {
24
+ version_id: version_id.into(),
25
+ untracked,
26
+ file_scope: DomainFileScope::Exact(file_id),
27
+ }
28
+ }
29
+
30
+ pub(crate) fn any_file(version_id: impl Into<String>, untracked: bool) -> Self {
31
+ Self {
32
+ version_id: version_id.into(),
33
+ untracked,
34
+ file_scope: DomainFileScope::Any,
35
+ }
36
+ }
37
+
38
+ pub(crate) fn schema_catalog(version_id: impl Into<String>, untracked: bool) -> Self {
39
+ Self::any_file(version_id, untracked)
40
+ }
41
+
42
+ pub(crate) fn for_live_row(row: &MaterializedLiveStateRow) -> Self {
43
+ Self::exact_file(row.version_id.clone(), row.untracked, row.file_id.clone())
44
+ }
45
+
46
+ pub(crate) fn schema_catalog_domain(&self) -> Self {
47
+ // Schema definitions are version + durability scoped. They are not
48
+ // owned by a data file, so schema catalog lookup deliberately erases
49
+ // row file scope into `Any`.
50
+ Self::schema_catalog(self.version_id.clone(), self.untracked)
51
+ }
52
+
53
+ pub(crate) fn version_id(&self) -> &str {
54
+ &self.version_id
55
+ }
56
+
57
+ pub(crate) fn untracked(&self) -> bool {
58
+ self.untracked
59
+ }
60
+
61
+ pub(crate) fn fingerprint_component(&self) -> String {
62
+ let file_scope = match &self.file_scope {
63
+ DomainFileScope::Any => "*".to_string(),
64
+ DomainFileScope::Exact(Some(file_id)) => format!("={file_id}"),
65
+ DomainFileScope::Exact(None) => "=".to_string(),
66
+ };
67
+ format!("{}|{}|{}", self.version_id, self.untracked, file_scope)
68
+ }
69
+
70
+ #[cfg(test)]
71
+ pub(crate) fn file_scope(&self) -> &DomainFileScope {
72
+ &self.file_scope
73
+ }
74
+
75
+ pub(crate) fn is_exact_file(&self, file_id: &Option<String>) -> bool {
76
+ matches!(&self.file_scope, DomainFileScope::Exact(exact) if exact == file_id)
77
+ }
78
+
79
+ pub(crate) fn with_untracked(&self, untracked: bool) -> Self {
80
+ Self {
81
+ version_id: self.version_id.clone(),
82
+ untracked,
83
+ file_scope: self.file_scope.clone(),
84
+ }
85
+ }
86
+
87
+ pub(crate) fn with_file_scope(&self, file_scope: DomainFileScope) -> Self {
88
+ Self {
89
+ version_id: self.version_id.clone(),
90
+ untracked: self.untracked,
91
+ file_scope,
92
+ }
93
+ }
94
+
95
+ pub(crate) fn with_exact_file_scope(&self, file_id: Option<String>) -> Self {
96
+ self.with_file_scope(DomainFileScope::Exact(file_id))
97
+ }
98
+
99
+ pub(crate) fn file_filters(&self) -> Vec<NullableKeyFilter<String>> {
100
+ match &self.file_scope {
101
+ DomainFileScope::Any => Vec::new(),
102
+ DomainFileScope::Exact(file_id) => vec![nullable_filter_from_option(file_id)],
103
+ }
104
+ }
105
+
106
+ pub(crate) fn contains(&self, row: &MaterializedLiveStateRow) -> bool {
107
+ row.version_id == self.version_id
108
+ && row.untracked == self.untracked
109
+ && committed_row_is_exact_version_scoped(row, &self.version_id)
110
+ && match &self.file_scope {
111
+ DomainFileScope::Any => true,
112
+ DomainFileScope::Exact(file_id) => row.file_id == *file_id,
113
+ }
114
+ }
115
+
116
+ fn reachable_target_domains(&self) -> Vec<Self> {
117
+ if self.untracked {
118
+ vec![self.with_untracked(false), self.clone()]
119
+ } else {
120
+ vec![self.clone()]
121
+ }
122
+ }
123
+
124
+ fn source_domains_that_can_reach(&self) -> Vec<Self> {
125
+ if self.untracked {
126
+ vec![self.clone()]
127
+ } else {
128
+ vec![self.clone(), self.with_untracked(true)]
129
+ }
130
+ }
131
+
132
+ fn can_reach(&self, target: &Self) -> bool {
133
+ self.version_id == target.version_id
134
+ && self.file_scope == target.file_scope
135
+ && (self.untracked || !target.untracked)
136
+ }
137
+
138
+ pub(crate) fn schema_catalog_domains(&self) -> Vec<Self> {
139
+ self.schema_catalog_domain().reachable_target_domains()
140
+ }
141
+
142
+ pub(crate) fn fk_target_domains(&self) -> Vec<Self> {
143
+ self.reachable_target_domains()
144
+ }
145
+
146
+ pub(crate) fn fk_source_domains_for_target(&self) -> Vec<Self> {
147
+ self.source_domains_that_can_reach()
148
+ }
149
+
150
+ pub(crate) fn file_owner_domains(&self) -> Vec<Self> {
151
+ self.reachable_target_domains()
152
+ }
153
+
154
+ pub(crate) fn directory_parent_domains(&self) -> Vec<Self> {
155
+ self.reachable_target_domains()
156
+ }
157
+
158
+ pub(crate) fn version_descriptor_domains_for_ref_delete(&self) -> Vec<Self> {
159
+ self.source_domains_that_can_reach()
160
+ }
161
+
162
+ pub(crate) fn file_scoped_row_domains_for_file_descriptor_delete(&self) -> Vec<Self> {
163
+ self.source_domains_that_can_reach()
164
+ }
165
+
166
+ pub(crate) fn validation_scope_contains_constraint_domain(&self, target: &Self) -> bool {
167
+ self.can_reach(target)
168
+ }
169
+
170
+ pub(crate) fn tombstone_domain_affects_validation_scope(
171
+ &self,
172
+ validation_scope: &Self,
173
+ ) -> bool {
174
+ self.can_reach(validation_scope)
175
+ }
176
+ }
177
+
178
+ #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
179
+ pub(crate) enum DomainFileScope {
180
+ Any,
181
+ Exact(Option<String>),
182
+ }
183
+
184
+ #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
185
+ pub(crate) struct DomainRowIdentity {
186
+ domain: Domain,
187
+ schema_key: String,
188
+ entity_id: EntityIdentity,
189
+ }
190
+
191
+ impl DomainRowIdentity {
192
+ pub(crate) fn new(
193
+ domain: Domain,
194
+ schema_key: impl Into<String>,
195
+ entity_id: EntityIdentity,
196
+ ) -> Self {
197
+ Self {
198
+ domain,
199
+ schema_key: schema_key.into(),
200
+ entity_id,
201
+ }
202
+ }
203
+
204
+ pub(crate) fn from_live_row(row: &MaterializedLiveStateRow) -> Self {
205
+ Self::new(
206
+ Domain::for_live_row(row),
207
+ row.schema_key.clone(),
208
+ row.entity_id.clone(),
209
+ )
210
+ }
211
+
212
+ pub(crate) fn in_domain(
213
+ domain: Domain,
214
+ schema_key: impl Into<String>,
215
+ entity_id: EntityIdentity,
216
+ ) -> Self {
217
+ Self::new(domain, schema_key, entity_id)
218
+ }
219
+
220
+ #[cfg(test)]
221
+ pub(crate) fn exact(
222
+ version_id: impl Into<String>,
223
+ untracked: bool,
224
+ file_id: Option<String>,
225
+ schema_key: impl Into<String>,
226
+ entity_id: EntityIdentity,
227
+ ) -> Self {
228
+ Self::new(
229
+ Domain::exact_file(version_id, untracked, file_id),
230
+ schema_key,
231
+ entity_id,
232
+ )
233
+ }
234
+
235
+ pub(crate) fn with_domain(&self, domain: Domain) -> Self {
236
+ Self {
237
+ domain,
238
+ schema_key: self.schema_key.clone(),
239
+ entity_id: self.entity_id.clone(),
240
+ }
241
+ }
242
+
243
+ pub(crate) fn domain(&self) -> &Domain {
244
+ &self.domain
245
+ }
246
+
247
+ pub(crate) fn schema_key(&self) -> &str {
248
+ &self.schema_key
249
+ }
250
+
251
+ pub(crate) fn schema_key_owned(&self) -> String {
252
+ self.schema_key.clone()
253
+ }
254
+
255
+ pub(crate) fn entity_id(&self) -> &EntityIdentity {
256
+ &self.entity_id
257
+ }
258
+
259
+ pub(crate) fn entity_id_owned(&self) -> EntityIdentity {
260
+ self.entity_id.clone()
261
+ }
262
+
263
+ pub(crate) fn matches_parts(
264
+ &self,
265
+ domain: &Domain,
266
+ schema_key: &str,
267
+ entity_id: &EntityIdentity,
268
+ ) -> bool {
269
+ &self.domain == domain && self.schema_key == schema_key && &self.entity_id == entity_id
270
+ }
271
+
272
+ pub(crate) fn reachable_target_identities(&self) -> Vec<Self> {
273
+ self.domain
274
+ .fk_target_domains()
275
+ .into_iter()
276
+ .map(|domain| self.with_domain(domain))
277
+ .collect()
278
+ }
279
+
280
+ pub(crate) fn source_identities_that_can_reach(&self) -> Vec<Self> {
281
+ self.domain
282
+ .fk_source_domains_for_target()
283
+ .into_iter()
284
+ .map(|domain| self.with_domain(domain))
285
+ .collect()
286
+ }
287
+ }
288
+
289
+ #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
290
+ pub(crate) struct DomainSchemaIdentity {
291
+ domain: Domain,
292
+ schema_key: String,
293
+ }
294
+
295
+ impl DomainSchemaIdentity {
296
+ pub(crate) fn new(domain: Domain, schema_key: impl Into<String>) -> Self {
297
+ Self {
298
+ domain: domain.schema_catalog_domain(),
299
+ schema_key: schema_key.into(),
300
+ }
301
+ }
302
+
303
+ pub(crate) fn fingerprint_component(&self) -> String {
304
+ format!(
305
+ "{}|{}",
306
+ self.domain.fingerprint_component(),
307
+ self.schema_key
308
+ )
309
+ }
310
+ }
311
+
312
+ pub(crate) fn committed_row_is_exact_version_scoped(
313
+ row: &MaterializedLiveStateRow,
314
+ version_id: &str,
315
+ ) -> bool {
316
+ row.version_id == version_id && row.global == (row.version_id == GLOBAL_VERSION_ID)
317
+ }
318
+
319
+ fn nullable_filter_from_option(value: &Option<String>) -> NullableKeyFilter<String> {
320
+ match value {
321
+ Some(value) => NullableKeyFilter::Value(value.clone()),
322
+ None => NullableKeyFilter::Null,
323
+ }
324
+ }
@@ -1,14 +1,13 @@
1
1
  use std::sync::Arc;
2
2
 
3
3
  use crate::binary_cas::BinaryCasContext;
4
- use crate::changelog::ChangelogContext;
4
+ use crate::catalog::CatalogContext;
5
5
  use crate::commit_graph::CommitGraphContext;
6
+ use crate::commit_store::CommitStoreContext;
6
7
  use crate::entity_identity::EntityIdentity;
7
8
  use crate::init::InitReceipt;
8
- use crate::json_store::JsonStoreContext;
9
9
  use crate::live_state::LiveStateContext;
10
10
  use crate::live_state::LiveStateRowRequest;
11
- use crate::schema_registry::SchemaRegistry;
12
11
  use crate::session::SessionContext;
13
12
  use crate::storage::{StorageContext, StorageWriteSet};
14
13
  use crate::tracked_state::TrackedStateContext;
@@ -24,12 +23,12 @@ pub struct Engine {
24
23
  live_state: Arc<LiveStateContext>,
25
24
  version_ctx: Arc<VersionContext>,
26
25
  binary_cas: Arc<BinaryCasContext>,
27
- changelog: Arc<ChangelogContext>,
28
- schema_registry: Arc<SchemaRegistry>,
26
+ commit_store: Arc<CommitStoreContext>,
27
+ catalog_context: Arc<CatalogContext>,
29
28
  }
30
29
 
31
30
  impl Engine {
32
- /// Seeds an empty backend with the engine2 repository bootstrap facts.
31
+ /// Seeds an empty backend with the engine repository bootstrap facts.
33
32
  ///
34
33
  /// Initialization is a storage lifecycle operation, separate from runtime
35
34
  /// construction. Call this before `Engine::new(...)` for a brand-new
@@ -39,13 +38,15 @@ impl Engine {
39
38
  ) -> Result<InitReceipt, LixError> {
40
39
  let backend: Arc<dyn Backend + Send + Sync> = Arc::from(backend);
41
40
  let storage = StorageContext::new(backend);
42
- let changelog = ChangelogContext::new();
43
- let commit_graph = CommitGraphContext::new(changelog);
44
- let tracked_state = TrackedStateContext::new();
45
- let untracked_state = UntrackedStateContext::new();
46
- let live_state = LiveStateContext::new(tracked_state, untracked_state, commit_graph);
41
+ let commit_store = CommitStoreContext::new();
47
42
 
48
- crate::init::initialize(storage, &changelog, &live_state).await
43
+ crate::init::initialize(
44
+ storage,
45
+ &commit_store,
46
+ &TrackedStateContext::new(),
47
+ &UntrackedStateContext::new(),
48
+ )
49
+ .await
49
50
  }
50
51
 
51
52
  /// Creates a clean DataFusion-first engine over an initialized backend.
@@ -58,8 +59,8 @@ impl Engine {
58
59
 
59
60
  let tracked_state = Arc::new(TrackedStateContext::new());
60
61
  let untracked_state = Arc::new(UntrackedStateContext::new());
61
- let changelog = Arc::new(ChangelogContext::new());
62
- let commit_graph = CommitGraphContext::new(changelog.as_ref().clone());
62
+ let commit_store = Arc::new(CommitStoreContext::new());
63
+ let commit_graph = CommitGraphContext::new();
63
64
  let live_state = Arc::new(LiveStateContext::new(
64
65
  tracked_state.as_ref().clone(),
65
66
  *untracked_state,
@@ -74,12 +75,12 @@ impl Engine {
74
75
 
75
76
  Ok(Self {
76
77
  binary_cas: Arc::new(BinaryCasContext::new()),
77
- changelog,
78
+ commit_store,
78
79
  storage,
79
80
  tracked_state,
80
81
  live_state,
81
82
  version_ctx,
82
- schema_registry: Arc::new(SchemaRegistry::new()),
83
+ catalog_context: Arc::new(CatalogContext::new()),
83
84
  })
84
85
  }
85
86
 
@@ -87,11 +88,6 @@ impl Engine {
87
88
  self.storage.clone()
88
89
  }
89
90
 
90
- #[cfg(test)]
91
- pub(crate) fn tracked_state(&self) -> Arc<TrackedStateContext> {
92
- Arc::clone(&self.tracked_state)
93
- }
94
-
95
91
  /// Loads the current commit head for a version.
96
92
  ///
97
93
  /// This is the public engine-level form of the typed `version_ref` context:
@@ -129,9 +125,9 @@ impl Engine {
129
125
  Arc::clone(&self.live_state),
130
126
  Arc::clone(&self.tracked_state),
131
127
  Arc::clone(&self.binary_cas),
132
- Arc::clone(&self.changelog),
128
+ Arc::clone(&self.commit_store),
133
129
  Arc::clone(&self.version_ctx),
134
- Arc::clone(&self.schema_registry),
130
+ Arc::clone(&self.catalog_context),
135
131
  )
136
132
  .await
137
133
  }
@@ -142,19 +138,19 @@ impl Engine {
142
138
  Arc::clone(&self.live_state),
143
139
  Arc::clone(&self.tracked_state),
144
140
  Arc::clone(&self.binary_cas),
145
- Arc::clone(&self.changelog),
141
+ Arc::clone(&self.commit_store),
146
142
  Arc::clone(&self.version_ctx),
147
- Arc::clone(&self.schema_registry),
143
+ Arc::clone(&self.catalog_context),
148
144
  )
149
145
  .await
150
146
  }
151
147
 
152
- /// Rebuilds the tracked serving projection for one version from changelog.
148
+ /// Materializes the tracked serving projection root for one version from commit_store.
153
149
  ///
154
150
  /// This is intentionally an engine-level operation: callers should not need
155
151
  /// to know which KV namespaces back changelog, commit graph, or tracked
156
152
  /// state. The current version head is read from the live-state facade so
157
- /// rebuild uses the same moving-ref visibility as normal execution.
153
+ /// materialization uses the same moving-ref visibility as normal execution.
158
154
  pub async fn rebuild_tracked_state_for_version(
159
155
  &self,
160
156
  version_id: &str,
@@ -169,29 +165,19 @@ impl Engine {
169
165
  "target",
170
166
  )
171
167
  })?;
172
- let commit_graph = CommitGraphContext::new(ChangelogContext::new());
173
168
  let storage = self.storage();
174
- let mut read_transaction = storage.begin_read_transaction().await?;
175
169
  let mut transaction = storage.begin_write_transaction().await?;
176
170
  let mut writes = StorageWriteSet::new();
177
- let mut json_writer = JsonStoreContext::new().writer();
178
- let rebuild_result = self
171
+ let materialize_result = self
179
172
  .tracked_state
180
- .rebuild_state_at_commit(
181
- &commit_graph,
182
- read_transaction.as_mut(),
173
+ .materializer(
183
174
  transaction.as_mut(),
184
175
  &mut writes,
185
- &mut json_writer,
186
- &head_commit_id,
176
+ self.commit_store.as_ref(),
187
177
  )
178
+ .materialize_root_at(&head_commit_id)
188
179
  .await;
189
- if let Err(error) = rebuild_result {
190
- let _ = read_transaction.rollback().await;
191
- let _ = transaction.rollback().await;
192
- return Err(error);
193
- }
194
- if let Err(error) = read_transaction.rollback().await {
180
+ if let Err(error) = materialize_result {
195
181
  let _ = transaction.rollback().await;
196
182
  return Err(error);
197
183
  }
@@ -234,6 +220,6 @@ async fn assert_initialized(
234
220
 
235
221
  Err(LixError::new(
236
222
  "LIX_ERROR_NOT_INITIALIZED",
237
- "engine2 backend is not initialized; call Engine::initialize(...) before Engine::new(...)",
223
+ "engine backend is not initialized; call Engine::initialize(...) before Engine::new(...)",
238
224
  ))
239
225
  }