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

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 (169) hide show
  1. package/SKILL.md +46 -8
  2. package/dist/engine-wasm/wasm/lix_engine.d.ts +25 -1
  3. package/dist/engine-wasm/wasm/lix_engine.js +60 -2
  4. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  5. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +5 -0
  6. package/dist/generated/builtin-schemas.d.ts +87 -162
  7. package/dist/generated/builtin-schemas.js +139 -236
  8. package/dist/open-lix.d.ts +10 -3
  9. package/dist/open-lix.js +39 -0
  10. package/dist-engine-src/src/binary_cas/types.rs +0 -6
  11. package/dist-engine-src/src/catalog/context.rs +412 -0
  12. package/dist-engine-src/src/catalog/mod.rs +10 -0
  13. package/dist-engine-src/src/catalog/schema.rs +4 -0
  14. package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
  15. package/dist-engine-src/src/cel/mod.rs +1 -1
  16. package/dist-engine-src/src/cel/provider.rs +1 -1
  17. package/dist-engine-src/src/commit_graph/context.rs +328 -1015
  18. package/dist-engine-src/src/commit_graph/mod.rs +2 -3
  19. package/dist-engine-src/src/commit_graph/types.rs +7 -43
  20. package/dist-engine-src/src/commit_graph/walker.rs +57 -81
  21. package/dist-engine-src/src/commit_store/codec.rs +887 -0
  22. package/dist-engine-src/src/commit_store/context.rs +944 -0
  23. package/dist-engine-src/src/commit_store/materialization.rs +84 -0
  24. package/dist-engine-src/src/commit_store/mod.rs +16 -0
  25. package/dist-engine-src/src/commit_store/storage.rs +600 -0
  26. package/dist-engine-src/src/commit_store/types.rs +215 -0
  27. package/dist-engine-src/src/common/identity.rs +15 -5
  28. package/dist-engine-src/src/common/json_pointer.rs +67 -0
  29. package/dist-engine-src/src/common/metadata.rs +17 -12
  30. package/dist-engine-src/src/common/mod.rs +5 -5
  31. package/dist-engine-src/src/domain.rs +324 -0
  32. package/dist-engine-src/src/engine.rs +29 -43
  33. package/dist-engine-src/src/entity_identity.rs +238 -118
  34. package/dist-engine-src/src/functions/context.rs +17 -52
  35. package/dist-engine-src/src/functions/deterministic.rs +1 -1
  36. package/dist-engine-src/src/functions/mod.rs +1 -1
  37. package/dist-engine-src/src/functions/provider.rs +4 -4
  38. package/dist-engine-src/src/functions/state.rs +39 -66
  39. package/dist-engine-src/src/functions/types.rs +1 -1
  40. package/dist-engine-src/src/init.rs +204 -151
  41. package/dist-engine-src/src/json_store/context.rs +354 -60
  42. package/dist-engine-src/src/json_store/encoded.rs +6 -6
  43. package/dist-engine-src/src/json_store/mod.rs +4 -1
  44. package/dist-engine-src/src/json_store/store.rs +884 -11
  45. package/dist-engine-src/src/json_store/types.rs +166 -1
  46. package/dist-engine-src/src/lib.rs +11 -10
  47. package/dist-engine-src/src/live_state/context.rs +608 -830
  48. package/dist-engine-src/src/live_state/mod.rs +3 -3
  49. package/dist-engine-src/src/live_state/overlay.rs +7 -7
  50. package/dist-engine-src/src/live_state/reader.rs +5 -5
  51. package/dist-engine-src/src/live_state/types.rs +19 -36
  52. package/dist-engine-src/src/live_state/visibility.rs +19 -14
  53. package/dist-engine-src/src/plugin/archive.rs +3 -6
  54. package/dist-engine-src/src/plugin/install.rs +0 -18
  55. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
  56. package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
  57. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
  58. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
  59. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
  60. package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
  61. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
  62. package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
  63. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
  64. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
  65. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
  66. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
  67. package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
  68. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
  69. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
  70. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
  71. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
  72. package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
  73. package/dist-engine-src/src/schema/compatibility.rs +787 -0
  74. package/dist-engine-src/src/schema/definition.json +47 -17
  75. package/dist-engine-src/src/schema/definition.rs +202 -96
  76. package/dist-engine-src/src/schema/key.rs +9 -77
  77. package/dist-engine-src/src/schema/mod.rs +4 -4
  78. package/dist-engine-src/src/schema/tests.rs +133 -92
  79. package/dist-engine-src/src/session/context.rs +86 -48
  80. package/dist-engine-src/src/session/create_version.rs +22 -14
  81. package/dist-engine-src/src/session/execute.rs +117 -23
  82. package/dist-engine-src/src/session/merge/apply.rs +4 -4
  83. package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
  84. package/dist-engine-src/src/session/merge/stats.rs +1 -1
  85. package/dist-engine-src/src/session/merge/version.rs +35 -45
  86. package/dist-engine-src/src/session/mod.rs +9 -7
  87. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
  88. package/dist-engine-src/src/session/switch_version.rs +17 -28
  89. package/dist-engine-src/src/session/transaction.rs +76 -0
  90. package/dist-engine-src/src/sql2/change_provider.rs +14 -20
  91. package/dist-engine-src/src/sql2/classify.rs +75 -48
  92. package/dist-engine-src/src/sql2/context.rs +22 -18
  93. package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
  94. package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
  95. package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
  96. package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
  97. package/dist-engine-src/src/sql2/error.rs +24 -5
  98. package/dist-engine-src/src/sql2/execute.rs +426 -272
  99. package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
  100. package/dist-engine-src/src/sql2/file_provider.rs +533 -108
  101. package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
  102. package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
  103. package/dist-engine-src/src/sql2/history_projection.rs +3 -27
  104. package/dist-engine-src/src/sql2/history_provider.rs +11 -17
  105. package/dist-engine-src/src/sql2/history_route.rs +22 -8
  106. package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
  107. package/dist-engine-src/src/sql2/mod.rs +8 -4
  108. package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
  109. package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
  110. package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
  111. package/dist-engine-src/src/sql2/public_bind/dml.rs +172 -0
  112. package/dist-engine-src/src/sql2/public_bind/mod.rs +26 -0
  113. package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
  114. package/dist-engine-src/src/sql2/read_only.rs +10 -12
  115. package/dist-engine-src/src/sql2/session.rs +7 -10
  116. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
  117. package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
  118. package/dist-engine-src/src/sql2/udfs/public_call.rs +238 -0
  119. package/dist-engine-src/src/sql2/version_provider.rs +46 -31
  120. package/dist-engine-src/src/sql2/version_scope.rs +4 -4
  121. package/dist-engine-src/src/storage_bench.rs +1782 -325
  122. package/dist-engine-src/src/test_support.rs +183 -36
  123. package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
  124. package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
  125. package/dist-engine-src/src/tracked_state/context.rs +1155 -271
  126. package/dist-engine-src/src/tracked_state/diff.rs +249 -57
  127. package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
  128. package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
  129. package/dist-engine-src/src/tracked_state/merge.rs +37 -19
  130. package/dist-engine-src/src/tracked_state/mod.rs +8 -7
  131. package/dist-engine-src/src/tracked_state/storage.rs +138 -6
  132. package/dist-engine-src/src/tracked_state/tree.rs +695 -252
  133. package/dist-engine-src/src/tracked_state/types.rs +176 -6
  134. package/dist-engine-src/src/transaction/commit.rs +695 -435
  135. package/dist-engine-src/src/transaction/context.rs +551 -310
  136. package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
  137. package/dist-engine-src/src/transaction/mod.rs +2 -0
  138. package/dist-engine-src/src/transaction/normalization.rs +311 -447
  139. package/dist-engine-src/src/transaction/prep.rs +37 -0
  140. package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
  141. package/dist-engine-src/src/transaction/staging.rs +701 -406
  142. package/dist-engine-src/src/transaction/types.rs +231 -122
  143. package/dist-engine-src/src/transaction/validation.rs +2717 -1698
  144. package/dist-engine-src/src/untracked_state/codec.rs +40 -96
  145. package/dist-engine-src/src/untracked_state/context.rs +21 -5
  146. package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
  147. package/dist-engine-src/src/untracked_state/mod.rs +3 -5
  148. package/dist-engine-src/src/untracked_state/storage.rs +105 -57
  149. package/dist-engine-src/src/untracked_state/types.rs +63 -13
  150. package/dist-engine-src/src/version/context.rs +1 -13
  151. package/dist-engine-src/src/version/lifecycle.rs +221 -0
  152. package/dist-engine-src/src/version/mod.rs +3 -2
  153. package/dist-engine-src/src/version/refs.rs +12 -103
  154. package/dist-engine-src/src/version/stage_rows.rs +15 -19
  155. package/package.json +1 -1
  156. package/dist-engine-src/src/changelog/codec.rs +0 -321
  157. package/dist-engine-src/src/changelog/context.rs +0 -92
  158. package/dist-engine-src/src/changelog/materialization.rs +0 -121
  159. package/dist-engine-src/src/changelog/mod.rs +0 -13
  160. package/dist-engine-src/src/changelog/reader.rs +0 -20
  161. package/dist-engine-src/src/changelog/storage.rs +0 -220
  162. package/dist-engine-src/src/changelog/types.rs +0 -38
  163. package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
  164. package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
  165. package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
  166. package/dist-engine-src/src/schema_registry.rs +0 -294
  167. package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
  168. package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
  169. package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
@@ -5,11 +5,11 @@ mod types;
5
5
  mod visibility;
6
6
 
7
7
  #[allow(unused_imports)]
8
- pub(crate) use context::{LiveStateContext, LiveStateStoreReader, LiveStateWriter};
8
+ pub(crate) use context::{LiveStateContext, LiveStateStoreReader};
9
9
  #[allow(unused_imports)]
10
10
  pub(crate) use reader::LiveStateReader;
11
11
  #[allow(unused_imports)]
12
12
  pub(crate) use types::{
13
- Bound, LiveStateFilter, LiveStateProjection, LiveStateRow, LiveStateRowIdentity,
14
- LiveStateRowRequest, LiveStateScanRequest, ScanConstraint, ScanField, ScanOperator,
13
+ Bound, LiveStateFilter, LiveStateProjection, LiveStateRowIdentity, LiveStateRowRequest,
14
+ LiveStateScanRequest, MaterializedLiveStateRow, ScanConstraint, ScanField, ScanOperator,
15
15
  };
@@ -1,6 +1,6 @@
1
1
  use std::collections::BTreeMap;
2
2
 
3
- use crate::live_state::{LiveStateRow, LiveStateRowIdentity};
3
+ use crate::live_state::{LiveStateRowIdentity, MaterializedLiveStateRow};
4
4
 
5
5
  /// Applies the local untracked overlay to tracked live-state rows.
6
6
  ///
@@ -9,9 +9,9 @@ use crate::live_state::{LiveStateRow, LiveStateRowIdentity};
9
9
  /// knowing whether a visible row came from tracked changelog projection or from
10
10
  /// local untracked state.
11
11
  pub(crate) fn overlay_untracked_rows(
12
- tracked_rows: Vec<LiveStateRow>,
13
- untracked_rows: Vec<LiveStateRow>,
14
- ) -> Vec<LiveStateRow> {
12
+ tracked_rows: Vec<MaterializedLiveStateRow>,
13
+ untracked_rows: Vec<MaterializedLiveStateRow>,
14
+ ) -> Vec<MaterializedLiveStateRow> {
15
15
  let mut rows_by_identity = BTreeMap::new();
16
16
 
17
17
  for row in tracked_rows {
@@ -55,14 +55,14 @@ mod tests {
55
55
  assert_eq!(rows.len(), 2);
56
56
  }
57
57
 
58
- fn live_row(value: &str, untracked: bool, change_id: Option<&str>) -> LiveStateRow {
59
- LiveStateRow {
58
+ fn live_row(value: &str, untracked: bool, change_id: Option<&str>) -> MaterializedLiveStateRow {
59
+ MaterializedLiveStateRow {
60
60
  entity_id: crate::entity_identity::EntityIdentity::single("entity"),
61
61
  schema_key: "schema".to_string(),
62
62
  file_id: None,
63
63
  snapshot_content: Some(format!("{{\"value\":\"{value}\"}}")),
64
64
  metadata: None,
65
- schema_version: "1".to_string(),
65
+ deleted: false,
66
66
  created_at: "2026-01-01T00:00:00Z".to_string(),
67
67
  updated_at: "2026-01-01T00:00:00Z".to_string(),
68
68
  global: true,
@@ -1,12 +1,12 @@
1
1
  use async_trait::async_trait;
2
2
 
3
- use crate::live_state::LiveStateRow;
3
+ use crate::live_state::MaterializedLiveStateRow;
4
4
  use crate::live_state::{LiveStateRowRequest, LiveStateScanRequest};
5
5
  use crate::LixError;
6
6
 
7
- /// Minimal engine2 read model for transaction planning and SQL providers.
7
+ /// Minimal engine read model for transaction planning and SQL providers.
8
8
  ///
9
- /// Engine2 only needs visible state-row reads here. Changelog freshness/catch-up
9
+ /// Engine only needs visible state-row reads here. Changelog freshness/catch-up
10
10
  /// should be added at this boundary later instead of leaking projection internals
11
11
  /// into sessions or SQL providers.
12
12
  #[async_trait]
@@ -14,10 +14,10 @@ pub(crate) trait LiveStateReader: Send + Sync {
14
14
  async fn scan_rows(
15
15
  &self,
16
16
  request: &LiveStateScanRequest,
17
- ) -> Result<Vec<LiveStateRow>, LixError>;
17
+ ) -> Result<Vec<MaterializedLiveStateRow>, LixError>;
18
18
 
19
19
  async fn load_row(
20
20
  &self,
21
21
  request: &LiveStateRowRequest,
22
- ) -> Result<Option<LiveStateRow>, LixError>;
22
+ ) -> Result<Option<MaterializedLiveStateRow>, LixError>;
23
23
  }
@@ -1,23 +1,22 @@
1
- use crate::changelog::MaterializedCanonicalChange;
2
1
  use crate::entity_identity::EntityIdentity;
3
- use crate::tracked_state::TrackedStateRow;
2
+ use crate::tracked_state::MaterializedTrackedStateRow;
4
3
  use crate::untracked_state::{
5
4
  MaterializedUntrackedStateRow, UntrackedStateFilter, UntrackedStateRowRequest,
6
5
  };
7
- use crate::{NullableKeyFilter, RowMetadata, Value};
6
+ use crate::{NullableKeyFilter, Value};
8
7
 
9
8
  /// Durable row visible through live_state reads.
10
9
  ///
11
10
  /// Unlike provider write rows, live-state rows are fully hydrated facts. Missing
12
11
  /// generated fields should be caught before this type is constructed.
13
12
  #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14
- pub(crate) struct LiveStateRow {
13
+ pub(crate) struct MaterializedLiveStateRow {
15
14
  pub(crate) entity_id: EntityIdentity,
16
15
  pub(crate) schema_key: String,
17
16
  pub(crate) file_id: Option<String>,
18
17
  pub(crate) snapshot_content: Option<String>,
19
- pub(crate) metadata: Option<RowMetadata>,
20
- pub(crate) schema_version: String,
18
+ pub(crate) metadata: Option<String>,
19
+ pub(crate) deleted: bool,
21
20
  pub(crate) created_at: String,
22
21
  pub(crate) updated_at: String,
23
22
  pub(crate) global: bool,
@@ -27,32 +26,15 @@ pub(crate) struct LiveStateRow {
27
26
  pub(crate) version_id: String,
28
27
  }
29
28
 
30
- impl From<LiveStateRow> for MaterializedCanonicalChange {
31
- fn from(row: LiveStateRow) -> Self {
32
- MaterializedCanonicalChange {
33
- id: row
34
- .change_id
35
- .expect("tracked live-state rows must carry change_id"),
36
- entity_id: row.entity_id,
37
- schema_key: row.schema_key,
38
- schema_version: row.schema_version,
39
- file_id: row.file_id,
40
- snapshot_content: row.snapshot_content,
41
- metadata: row.metadata,
42
- created_at: row.created_at,
43
- }
44
- }
45
- }
46
-
47
- impl From<MaterializedUntrackedStateRow> for LiveStateRow {
29
+ impl From<MaterializedUntrackedStateRow> for MaterializedLiveStateRow {
48
30
  fn from(row: MaterializedUntrackedStateRow) -> Self {
49
- LiveStateRow {
31
+ MaterializedLiveStateRow {
50
32
  entity_id: row.entity_id,
51
33
  schema_key: row.schema_key,
52
34
  file_id: row.file_id,
53
35
  snapshot_content: row.snapshot_content,
54
36
  metadata: row.metadata,
55
- schema_version: row.schema_version,
37
+ deleted: row.deleted,
56
38
  created_at: row.created_at,
57
39
  updated_at: row.updated_at,
58
40
  global: row.global,
@@ -64,10 +46,10 @@ impl From<MaterializedUntrackedStateRow> for LiveStateRow {
64
46
  }
65
47
  }
66
48
 
67
- impl TryFrom<&LiveStateRow> for TrackedStateRow {
49
+ impl TryFrom<&MaterializedLiveStateRow> for MaterializedTrackedStateRow {
68
50
  type Error = crate::LixError;
69
51
 
70
- fn try_from(row: &LiveStateRow) -> Result<Self, Self::Error> {
52
+ fn try_from(row: &MaterializedLiveStateRow) -> Result<Self, Self::Error> {
71
53
  if row.untracked {
72
54
  return Err(crate::LixError::new(
73
55
  "LIX_ERROR_UNKNOWN",
@@ -87,13 +69,13 @@ impl TryFrom<&LiveStateRow> for TrackedStateRow {
87
69
  ));
88
70
  };
89
71
 
90
- Ok(TrackedStateRow {
72
+ Ok(MaterializedTrackedStateRow {
91
73
  entity_id: row.entity_id.clone(),
92
74
  schema_key: row.schema_key.clone(),
93
75
  file_id: row.file_id.clone(),
94
76
  snapshot_content: row.snapshot_content.clone(),
95
77
  metadata: row.metadata.clone(),
96
- schema_version: row.schema_version.clone(),
78
+ deleted: row.deleted,
97
79
  created_at: row.created_at.clone(),
98
80
  updated_at: row.updated_at.clone(),
99
81
  change_id,
@@ -102,15 +84,15 @@ impl TryFrom<&LiveStateRow> for TrackedStateRow {
102
84
  }
103
85
  }
104
86
 
105
- impl From<&LiveStateRow> for MaterializedUntrackedStateRow {
106
- fn from(row: &LiveStateRow) -> Self {
87
+ impl From<&MaterializedLiveStateRow> for MaterializedUntrackedStateRow {
88
+ fn from(row: &MaterializedLiveStateRow) -> Self {
107
89
  MaterializedUntrackedStateRow {
108
90
  entity_id: row.entity_id.clone(),
109
91
  schema_key: row.schema_key.clone(),
110
92
  file_id: row.file_id.clone(),
111
93
  snapshot_content: row.snapshot_content.clone(),
112
94
  metadata: row.metadata.clone(),
113
- schema_version: row.schema_version.clone(),
95
+ deleted: row.deleted,
114
96
  created_at: row.created_at.clone(),
115
97
  updated_at: row.updated_at.clone(),
116
98
  global: row.global,
@@ -124,7 +106,6 @@ impl From<&LiveStateRow> for MaterializedUntrackedStateRow {
124
106
  pub(crate) enum ScanField {
125
107
  EntityId,
126
108
  FileId,
127
- SchemaVersion,
128
109
  }
129
110
 
130
111
  /// Inclusive or exclusive range bound.
@@ -164,6 +145,8 @@ pub(crate) struct LiveStateFilter {
164
145
  #[serde(default)]
165
146
  pub(crate) file_ids: Vec<NullableKeyFilter<String>>,
166
147
  #[serde(default)]
148
+ pub(crate) untracked: Option<bool>,
149
+ #[serde(default)]
167
150
  pub(crate) constraints: Vec<ScanConstraint>,
168
151
  #[serde(default)]
169
152
  pub(crate) include_tombstones: bool,
@@ -187,7 +170,7 @@ pub(crate) struct LiveStateProjection {
187
170
  pub(crate) columns: Vec<String>,
188
171
  }
189
172
 
190
- /// First-principles scan request for engine2-owned reads.
173
+ /// First-principles scan request for engine-owned reads.
191
174
  #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
192
175
  pub(crate) struct LiveStateScanRequest {
193
176
  #[serde(default)]
@@ -228,7 +211,7 @@ pub(crate) struct LiveStateRowIdentity {
228
211
  }
229
212
 
230
213
  impl LiveStateRowIdentity {
231
- pub(crate) fn from_row(row: &LiveStateRow) -> Self {
214
+ pub(crate) fn from_row(row: &MaterializedLiveStateRow) -> Self {
232
215
  Self {
233
216
  version_id: row.version_id.clone(),
234
217
  schema_key: row.schema_key.clone(),
@@ -1,6 +1,6 @@
1
1
  use std::collections::BTreeMap;
2
2
 
3
- use crate::live_state::{LiveStateRow, LiveStateRowIdentity};
3
+ use crate::live_state::{LiveStateRowIdentity, MaterializedLiveStateRow};
4
4
  use crate::GLOBAL_VERSION_ID;
5
5
 
6
6
  /// Expands a version-scoped storage read so global candidates are available for
@@ -32,13 +32,13 @@ pub(crate) fn expanded_version_ids(version_ids: &[String]) -> Vec<String> {
32
32
  /// validation remains exact storage-scope local unless a validator explicitly
33
33
  /// opts into overlay semantics.
34
34
  pub(crate) fn resolve_scan_rows(
35
- rows: Vec<LiveStateRow>,
35
+ rows: Vec<MaterializedLiveStateRow>,
36
36
  requested_version_ids: &[String],
37
37
  include_tombstones: bool,
38
- ) -> Vec<LiveStateRow> {
38
+ ) -> Vec<MaterializedLiveStateRow> {
39
39
  let mut rows = project_global_rows_into_requested_versions(rows, requested_version_ids);
40
40
  if !include_tombstones {
41
- rows.retain(|row| row.snapshot_content.is_some());
41
+ rows.retain(|row| !row.deleted);
42
42
  }
43
43
  rows
44
44
  }
@@ -46,10 +46,10 @@ pub(crate) fn resolve_scan_rows(
46
46
  /// Resolves a row loaded through a concrete storage version into the row visible
47
47
  /// to the requested version scope.
48
48
  pub(crate) fn project_loaded_row(
49
- mut row: LiveStateRow,
49
+ mut row: MaterializedLiveStateRow,
50
50
  requested_version_id: &str,
51
51
  matched_version_id: &str,
52
- ) -> LiveStateRow {
52
+ ) -> MaterializedLiveStateRow {
53
53
  if row.global && requested_version_id != GLOBAL_VERSION_ID {
54
54
  row.version_id = requested_version_id.to_string();
55
55
  } else if matched_version_id == GLOBAL_VERSION_ID && requested_version_id != GLOBAL_VERSION_ID {
@@ -59,14 +59,14 @@ pub(crate) fn project_loaded_row(
59
59
  }
60
60
 
61
61
  fn project_global_rows_into_requested_versions(
62
- rows: Vec<LiveStateRow>,
62
+ rows: Vec<MaterializedLiveStateRow>,
63
63
  requested_version_ids: &[String],
64
- ) -> Vec<LiveStateRow> {
64
+ ) -> Vec<MaterializedLiveStateRow> {
65
65
  if requested_version_ids.is_empty() {
66
66
  return rows;
67
67
  }
68
68
 
69
- let mut rows_by_identity = BTreeMap::<LiveStateRowIdentity, LiveStateRow>::new();
69
+ let mut rows_by_identity = BTreeMap::<LiveStateRowIdentity, MaterializedLiveStateRow>::new();
70
70
  for requested_version_id in requested_version_ids {
71
71
  for row in &rows {
72
72
  if row.version_id == GLOBAL_VERSION_ID {
@@ -191,14 +191,14 @@ mod tests {
191
191
  value: &str,
192
192
  global: bool,
193
193
  change_id: Option<&str>,
194
- ) -> LiveStateRow {
195
- LiveStateRow {
194
+ ) -> MaterializedLiveStateRow {
195
+ MaterializedLiveStateRow {
196
196
  entity_id: crate::entity_identity::EntityIdentity::single("entity"),
197
197
  schema_key: "schema".to_string(),
198
198
  file_id: None,
199
199
  snapshot_content: Some(format!("{{\"value\":\"{value}\"}}")),
200
200
  metadata: None,
201
- schema_version: "1".to_string(),
201
+ deleted: false,
202
202
  created_at: "2026-01-01T00:00:00Z".to_string(),
203
203
  updated_at: "2026-01-01T00:00:00Z".to_string(),
204
204
  global,
@@ -209,9 +209,14 @@ mod tests {
209
209
  }
210
210
  }
211
211
 
212
- fn tombstone_at(version_id: &str, global: bool, change_id: Option<&str>) -> LiveStateRow {
213
- LiveStateRow {
212
+ fn tombstone_at(
213
+ version_id: &str,
214
+ global: bool,
215
+ change_id: Option<&str>,
216
+ ) -> MaterializedLiveStateRow {
217
+ MaterializedLiveStateRow {
214
218
  snapshot_content: None,
219
+ deleted: true,
215
220
  ..row_at(version_id, "ignored", global, change_id)
216
221
  }
217
222
  }
@@ -71,15 +71,12 @@ pub(crate) fn parse_plugin_archive_for_install(
71
71
  })?;
72
72
  validate_lix_schema_definition(&schema_json)?;
73
73
  let schema_key = schema_key_from_definition(&schema_json)?;
74
- if !seen_schema_keys.insert((
75
- schema_key.schema_key.clone(),
76
- schema_key.schema_version.clone(),
77
- )) {
74
+ if !seen_schema_keys.insert(schema_key.schema_key.clone()) {
78
75
  return Err(LixError {
79
76
  code: "LIX_ERROR_UNKNOWN".to_string(),
80
77
  message: format!(
81
- "Plugin archive declares duplicate schema '{}~{}'",
82
- schema_key.schema_key, schema_key.schema_version
78
+ "Plugin archive declares duplicate schema '{}'",
79
+ schema_key.schema_key
83
80
  ),
84
81
  hint: None,
85
82
  details: None,
@@ -37,11 +37,8 @@ use crate::{LixError, Value};
37
37
 
38
38
  use crate::transaction::WriteCommand;
39
39
  const REGISTERED_SCHEMA_STORAGE_SCHEMA_KEY: &str = "lix_registered_schema";
40
- const REGISTERED_SCHEMA_STORAGE_SCHEMA_VERSION: &str = "1";
41
40
  const FILESYSTEM_DESCRIPTOR_SCHEMA_KEY: &str = "lix_file_descriptor";
42
- const FILESYSTEM_DESCRIPTOR_SCHEMA_VERSION: &str = "1";
43
41
  const FILESYSTEM_BINARY_BLOB_REF_SCHEMA_KEY: &str = "lix_binary_blob_ref";
44
- const FILESYSTEM_BINARY_BLOB_REF_SCHEMA_VERSION: &str = "1";
45
42
 
46
43
  #[derive(Clone)]
47
44
  pub(crate) struct PluginInstallWriteContext {
@@ -170,7 +167,6 @@ fn prepare_registered_schema_write_statement_from_schemas(
170
167
  .map(|row| PublicChange {
171
168
  entity_id: row.entity_id.clone(),
172
169
  schema_key: REGISTERED_SCHEMA_STORAGE_SCHEMA_KEY.to_string(),
173
- schema_version: Some(REGISTERED_SCHEMA_STORAGE_SCHEMA_VERSION.to_string()),
174
170
  file_id: None,
175
171
  plugin_key: None,
176
172
  snapshot_content: Some(row.snapshot.to_string()),
@@ -289,10 +285,6 @@ fn registered_schema_planned_row(
289
285
  );
290
286
  values.insert("file_id".to_string(), Value::Null);
291
287
  values.insert("plugin_key".to_string(), Value::Null);
292
- values.insert(
293
- "schema_version".to_string(),
294
- Value::Text(REGISTERED_SCHEMA_STORAGE_SCHEMA_VERSION.to_string()),
295
- );
296
288
  values.insert(
297
289
  "snapshot_content".to_string(),
298
290
  Value::Json(row.snapshot.clone()),
@@ -331,10 +323,6 @@ fn plugin_archive_file_descriptor_row(
331
323
  );
332
324
  values.insert("file_id".to_string(), Value::Null);
333
325
  values.insert("plugin_key".to_string(), Value::Null);
334
- values.insert(
335
- "schema_version".to_string(),
336
- Value::Text(FILESYSTEM_DESCRIPTOR_SCHEMA_VERSION.to_string()),
337
- );
338
326
  values.insert(
339
327
  "snapshot_content".to_string(),
340
328
  Value::Text(snapshot_content),
@@ -381,10 +369,6 @@ fn plugin_archive_binary_blob_ref_row(
381
369
  );
382
370
  values.insert("file_id".to_string(), Value::Text(archive_id.to_string()));
383
371
  values.insert("plugin_key".to_string(), Value::Null);
384
- values.insert(
385
- "schema_version".to_string(),
386
- Value::Text(FILESYSTEM_BINARY_BLOB_REF_SCHEMA_VERSION.to_string()),
387
- );
388
372
  values.insert(
389
373
  "snapshot_content".to_string(),
390
374
  Value::Text(snapshot_content),
@@ -506,7 +490,6 @@ fn planned_row_to_public_change(row: &PlannedStateRow) -> Result<PublicChange, L
506
490
  Ok(PublicChange {
507
491
  entity_id: row.entity_id.clone(),
508
492
  schema_key: row.schema_key.clone(),
509
- schema_version: planned_row_text_value(row, "schema_version"),
510
493
  file_id: planned_row_text_value(row, "file_id"),
511
494
  plugin_key: planned_row_text_value(row, "plugin_key"),
512
495
  snapshot_content: if row.tombstone {
@@ -569,7 +552,6 @@ fn summarize_change(change: &PublicChange) -> JsonValue {
569
552
  json!({
570
553
  "entity_id": change.entity_id,
571
554
  "schema_key": change.schema_key,
572
- "schema_version": change.schema_version,
573
555
  "file_id": change.file_id,
574
556
  "plugin_key": change.plugin_key,
575
557
  "version_id": change.version_id,
@@ -62,7 +62,6 @@
62
62
  "enum": [
63
63
  "entity_id",
64
64
  "schema_key",
65
- "schema_version",
66
65
  "snapshot_content",
67
66
  "file_id",
68
67
  "plugin_key",
@@ -9,7 +9,6 @@ pub(crate) fn apply_schema_defaults<P>(
9
9
  evaluator: &CelEvaluator,
10
10
  functions: P,
11
11
  schema_key: &str,
12
- schema_version: &str,
13
12
  ) -> Result<bool, LixError>
14
13
  where
15
14
  P: CelFunctionProvider,
@@ -21,7 +20,6 @@ where
21
20
  evaluator,
22
21
  functions,
23
22
  schema_key,
24
- schema_version,
25
23
  )
26
24
  }
27
25
 
@@ -30,7 +28,6 @@ pub(crate) fn apply_schema_defaults_with_shared_runtime<P>(
30
28
  schema: &JsonValue,
31
29
  functions: P,
32
30
  schema_key: &str,
33
- schema_version: &str,
34
31
  ) -> Result<bool, LixError>
35
32
  where
36
33
  P: CelFunctionProvider,
@@ -41,7 +38,6 @@ where
41
38
  crate::cel::shared_runtime(),
42
39
  functions,
43
40
  schema_key,
44
- schema_version,
45
41
  )
46
42
  }
47
43
 
@@ -52,7 +48,6 @@ pub(crate) fn apply_schema_defaults_with_context<P>(
52
48
  evaluator: &CelEvaluator,
53
49
  functions: P,
54
50
  schema_key: &str,
55
- schema_version: &str,
56
51
  ) -> Result<bool, LixError>
57
52
  where
58
53
  P: CelFunctionProvider,
@@ -78,8 +73,8 @@ where
78
73
  .map_err(|err| LixError {
79
74
  code: "LIX_ERROR_UNKNOWN".to_string(),
80
75
  message: format!(
81
- "failed to evaluate x-lix-default for '{}.{}' ({}): {}",
82
- schema_key, field_name, schema_version, err.message
76
+ "failed to evaluate x-lix-default for '{}.{}': {}",
77
+ schema_key, field_name, err.message
83
78
  ),
84
79
  hint: None,
85
80
  details: None,
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "x-lix-key": "lix_account",
3
- "x-lix-version": "1",
4
3
  "x-lix-primary-key": [
5
4
  "/id"
6
5
  ],
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "x-lix-key": "lix_active_account",
3
- "x-lix-version": "1",
4
3
  "x-lix-primary-key": [
5
4
  "/account_id"
6
5
  ],
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "x-lix-key": "lix_binary_blob_ref",
3
- "x-lix-version": "1",
4
3
  "description": "Metadata pointer from a file version to its binary payload in internal CAS storage.",
5
4
  "x-lix-primary-key": [
6
5
  "/id"
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "x-lix-key": "lix_change",
3
- "x-lix-version": "1",
4
- "description": "Canonical immutable change fact. This surface represents the authoritative stream of journaled change facts. Commit lineage and non-commit scope are modeled separately around these facts.",
3
+ "description": "A change records one edit to a Lix entity, including what changed, when it changed, and which entity was affected.",
5
4
  "x-lix-primary-key": [
6
5
  "/id"
7
6
  ],
@@ -10,20 +9,20 @@
10
9
  "id": {
11
10
  "type": "string",
12
11
  "x-lix-default": "lix_uuid_v7()",
13
- "description": "Stable change identifier (UUIDv7). Referenced from `lix_commit.change_ids` and `lix_change_set_element.change_id`."
12
+ "description": "Stable identifier for this change."
14
13
  },
15
14
  "entity_id": {
16
- "type": "string",
17
- "description": "The entity this change applies to, scoped by (`schema_key`, `file_id`)."
15
+ "type": "array",
16
+ "description": "Canonical JSON primary-key tuple for the entity this change applies to, scoped by (`schema_key`, `file_id`). Values are ordered according to the target schema's `x-lix-primary-key`.",
17
+ "items": {
18
+ "type": "string"
19
+ },
20
+ "minItems": 1
18
21
  },
19
22
  "schema_key": {
20
23
  "type": "string",
21
24
  "description": "Schema identifier of the entity (e.g. `lix_file_descriptor`, `lix_commit`, or a user-registered key)."
22
25
  },
23
- "schema_version": {
24
- "type": "string",
25
- "description": "Schema version the snapshot_content was written against (matches `x-lix-version` on the schema at write time)."
26
- },
27
26
  "file_id": {
28
27
  "type": [
29
28
  "string",
@@ -40,6 +39,9 @@
40
39
  },
41
40
  "created_at": {
42
41
  "type": "string",
42
+ "examples": [
43
+ "2026-05-08T17:42:31.123Z"
44
+ ],
43
45
  "description": "ISO-8601 timestamp at which the change was recorded (set via `lix_timestamp()` at write time)."
44
46
  },
45
47
  "snapshot_content": {
@@ -54,7 +56,6 @@
54
56
  "id",
55
57
  "entity_id",
56
58
  "schema_key",
57
- "schema_version",
58
59
  "file_id",
59
60
  "created_at"
60
61
  ],
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "x-lix-key": "lix_change_author",
3
- "x-lix-version": "1",
4
3
  "x-lix-primary-key": [
5
4
  "/change_id",
6
5
  "/account_id"
@@ -1,62 +1,24 @@
1
1
  {
2
2
  "x-lix-key": "lix_commit",
3
- "x-lix-version": "1",
4
- "description": "Commit header change. Canonical commit membership is stored in change_ids as the ordered list of canonical changes whose effects this commit introduces relative to its first parent. A merge commit may reference canonical changes originally authored in another parent instead of copying them. Derived projections such as lix_change_set_element must be rebuildable from this header plus the referenced change rows. Version head pointers such as lix_version_ref are maintained separately and are not commit members.",
5
- "x-lix-primary-key": [
6
- "/id"
7
- ],
8
- "x-lix-foreign-keys": [
3
+ "description": "A commit is a stable point in project history. Versions point to commits. Use lix_commit_edge to inspect parent commits.",
4
+ "examples": [
9
5
  {
10
- "properties": [
11
- "/change_set_id"
12
- ],
13
- "references": {
14
- "schemaKey": "lix_change_set",
15
- "properties": [
16
- "/id"
17
- ]
18
- }
6
+ "id": "commit_01jexample"
19
7
  }
20
8
  ],
9
+ "x-lix-primary-key": [
10
+ "/id"
11
+ ],
21
12
  "type": "object",
22
13
  "properties": {
23
14
  "id": {
24
15
  "type": "string",
25
16
  "x-lix-default": "lix_uuid_v7()",
26
- "description": "Stable commit identifier."
27
- },
28
- "change_set_id": {
29
- "type": "string",
30
- "description": "Commit-local grouping identifier used by derived relational indexes and projections such as lix_change_set_element."
31
- },
32
- "change_ids": {
33
- "type": "array",
34
- "default": [],
35
- "items": {
36
- "type": "string"
37
- },
38
- "description": "Canonical ordered membership list of non-header change IDs whose effects this commit introduces relative to its first parent. Merge commits may reference existing changes from another parent instead of minting equivalent copies. Derived indexes such as lix_change_set_element must be rebuildable from this list. This does not include lix_version_ref pointer rows."
39
- },
40
- "author_account_ids": {
41
- "type": "array",
42
- "default": [],
43
- "items": {
44
- "type": "string"
45
- },
46
- "description": "Ordered set of author account IDs associated with this commit."
47
- },
48
- "parent_commit_ids": {
49
- "type": "array",
50
- "default": [],
51
- "items": {
52
- "type": "string"
53
- },
54
- "description": "Parent commit IDs for commit graph topology."
17
+ "description": "Stable identifier of this commit."
55
18
  }
56
19
  },
57
20
  "required": [
58
- "id",
59
- "change_set_id"
21
+ "id"
60
22
  ],
61
23
  "additionalProperties": false
62
24
  }