@feltdb/core 0.8.4 → 0.8.6

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 (160) hide show
  1. package/dist/create/package-versions.js +1 -1
  2. package/dist/create/server-source/Cargo.lock +165 -0
  3. package/dist/create/server-source/Cargo.toml +9 -0
  4. package/dist/create/server-source/crates/feltdb/Cargo.toml +3 -0
  5. package/dist/create/server-source/crates/feltdb/benches/gate13_baseline.rs +44 -44
  6. package/dist/create/server-source/crates/feltdb/benches/gate13_phase_7_1_release_economics.rs +12 -24
  7. package/dist/create/server-source/crates/feltdb/benches/gate_13_redux.rs +7 -13
  8. package/dist/create/server-source/crates/feltdb/benches/gate_13_regression_runner.rs +13 -10
  9. package/dist/create/server-source/crates/feltdb/benches/gate_14a_concurrent_writer_scaling.rs +12 -9
  10. package/dist/create/server-source/crates/feltdb/benches/gate_14a_production_admission_revalidation.rs +78 -25
  11. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc2_admission_contract.rs +16 -13
  12. package/dist/create/server-source/crates/feltdb/benches/gate_14a_rc_root_cause.rs +13 -5
  13. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync1_queued_prototype.rs +41 -22
  14. package/dist/create/server-source/crates/feltdb/benches/gate_14a_sync_economics.rs +33 -15
  15. package/dist/create/server-source/crates/feltdb/benches/gate_14b_causal_backlog_scaling.rs +100 -33
  16. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_contract_test.rs +56 -20
  17. package/dist/create/server-source/crates/feltdb/benches/gate_14c_replication_scaling.rs +116 -41
  18. package/dist/create/server-source/crates/feltdb/benches/gate_14d_combined_dimension_scaling.rs +186 -55
  19. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_2_optimization_benchmark.rs +64 -26
  20. package/dist/create/server-source/crates/feltdb/benches/phase_7_1_3_crossover_analysis.rs +46 -15
  21. package/dist/create/server-source/crates/feltdb/src/admission.rs +8 -15
  22. package/dist/create/server-source/crates/feltdb/src/admission_contract_tests.rs +43 -13
  23. package/dist/create/server-source/crates/feltdb/src/adversarial_transport.rs +15 -42
  24. package/dist/create/server-source/crates/feltdb/src/analytics.rs +65 -19
  25. package/dist/create/server-source/crates/feltdb/src/application.rs +113 -30
  26. package/dist/create/server-source/crates/feltdb/src/authorization_security_tests.rs +475 -140
  27. package/dist/create/server-source/crates/feltdb/src/cardinality_diagnostics.rs +17 -15
  28. package/dist/create/server-source/crates/feltdb/src/cardinality_endpoint.rs +0 -1
  29. package/dist/create/server-source/crates/feltdb/src/causal_backlog_bound.rs +59 -15
  30. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier.rs +266 -114
  31. package/dist/create/server-source/crates/feltdb/src/causal_dependency_barrier_phase_7_1.rs +25 -7
  32. package/dist/create/server-source/crates/feltdb/src/concurrency_fuzzing.rs +10 -15
  33. package/dist/create/server-source/crates/feltdb/src/consistency_contract.rs +3 -11
  34. package/dist/create/server-source/crates/feltdb/src/crash_atomic_boundary.rs +14 -5
  35. package/dist/create/server-source/crates/feltdb/src/crash_injection.rs +21 -25
  36. package/dist/create/server-source/crates/feltdb/src/crash_recovery_tests.rs +14 -11
  37. package/dist/create/server-source/crates/feltdb/src/dedup_bound_investigation.rs +103 -22
  38. package/dist/create/server-source/crates/feltdb/src/distributed_indexing.rs +18 -15
  39. package/dist/create/server-source/crates/feltdb/src/durability_guarantees.rs +12 -8
  40. package/dist/create/server-source/crates/feltdb/src/durable_dedup_set.rs +1 -5
  41. package/dist/create/server-source/crates/feltdb/src/durable_operation_identity.rs +87 -23
  42. package/dist/create/server-source/crates/feltdb/src/durable_operation_log.rs +3 -7
  43. package/dist/create/server-source/crates/feltdb/src/durable_sync.rs +10 -9
  44. package/dist/create/server-source/crates/feltdb/src/in_process_transport.rs +1 -6
  45. package/dist/create/server-source/crates/feltdb/src/indexing.rs +35 -38
  46. package/dist/create/server-source/crates/feltdb/src/lib.rs +1648 -46
  47. package/dist/create/server-source/crates/feltdb/src/managed_cas_tests.rs +4 -1
  48. package/dist/create/server-source/crates/feltdb/src/metrics.rs +0 -1
  49. package/dist/create/server-source/crates/feltdb/src/multi_node_convergence.rs +1 -2
  50. package/dist/create/server-source/crates/feltdb/src/multi_operation_transaction.rs +107 -30
  51. package/dist/create/server-source/crates/feltdb/src/observability.rs +19 -6
  52. package/dist/create/server-source/crates/feltdb/src/operation.rs +39 -0
  53. package/dist/create/server-source/crates/feltdb/src/operation_algebra.rs +12 -11
  54. package/dist/create/server-source/crates/feltdb/src/operation_log.rs +9 -4
  55. package/dist/create/server-source/crates/feltdb/src/p1_application_atomicity.rs +65 -18
  56. package/dist/create/server-source/crates/feltdb/src/p1_atomicity_acceptance.rs +193 -57
  57. package/dist/create/server-source/crates/feltdb/src/partition_reconciliation.rs +37 -27
  58. package/dist/create/server-source/crates/feltdb/src/permutation_scheduler.rs +38 -10
  59. package/dist/create/server-source/crates/feltdb/src/persistence_reality.rs +20 -14
  60. package/dist/create/server-source/crates/feltdb/src/phase1b_acceptance.rs +394 -229
  61. package/dist/create/server-source/crates/feltdb/src/phase1c1_acceptance.rs +8 -6
  62. package/dist/create/server-source/crates/feltdb/src/phase1c2_acceptance.rs +11 -13
  63. package/dist/create/server-source/crates/feltdb/src/phase1c3_acceptance.rs +79 -70
  64. package/dist/create/server-source/crates/feltdb/src/phase1c_atomicity_proof.rs +3 -3
  65. package/dist/create/server-source/crates/feltdb/src/phase5_integration.rs +33 -11
  66. package/dist/create/server-source/crates/feltdb/src/phase5_scenarios.rs +6 -6
  67. package/dist/create/server-source/crates/feltdb/src/phase6_adversarial_scenarios.rs +14 -56
  68. package/dist/create/server-source/crates/feltdb/src/phase6_convergence_validator.rs +29 -27
  69. package/dist/create/server-source/crates/feltdb/src/phase6_persistence.rs +35 -17
  70. package/dist/create/server-source/crates/feltdb/src/phase_1c_real_tcp.rs +8 -2
  71. package/dist/create/server-source/crates/feltdb/src/phase_2a_failures.rs +59 -15
  72. package/dist/create/server-source/crates/feltdb/src/phase_2b_network.rs +70 -17
  73. package/dist/create/server-source/crates/feltdb/src/phase_2c_cascading.rs +23 -6
  74. package/dist/create/server-source/crates/feltdb/src/phase_3_durability.rs +12 -3
  75. package/dist/create/server-source/crates/feltdb/src/phase_4_baseline.rs +41 -11
  76. package/dist/create/server-source/crates/feltdb/src/phase_5_soak.rs +56 -25
  77. package/dist/create/server-source/crates/feltdb/src/policy_evaluation.rs +701 -245
  78. package/dist/create/server-source/crates/feltdb/src/production_api.rs +31 -13
  79. package/dist/create/server-source/crates/feltdb/src/query_performance.rs +6 -8
  80. package/dist/create/server-source/crates/feltdb/src/replay_fuzzing.rs +5 -5
  81. package/dist/create/server-source/crates/feltdb/src/replica_acknowledgements.rs +48 -18
  82. package/dist/create/server-source/crates/feltdb/src/replica_membership.rs +30 -11
  83. package/dist/create/server-source/crates/feltdb/src/replication_manager.rs +6 -3
  84. package/dist/create/server-source/crates/feltdb/src/replication_protocol.rs +4 -3
  85. package/dist/create/server-source/crates/feltdb/src/sharding.rs +36 -10
  86. package/dist/create/server-source/crates/feltdb/src/state_conflict_contract.rs +516 -0
  87. package/dist/create/server-source/crates/feltdb/src/state_contract.rs +13 -4
  88. package/dist/create/server-source/crates/feltdb/src/state_diff_contract.rs +222 -0
  89. package/dist/create/server-source/crates/feltdb/src/state_facade.rs +82 -54
  90. package/dist/create/server-source/crates/feltdb/src/state_hash.rs +2 -2
  91. package/dist/create/server-source/crates/feltdb/src/state_model.rs +1565 -536
  92. package/dist/create/server-source/crates/feltdb/src/state_transition_store.rs +6 -3
  93. package/dist/create/server-source/crates/feltdb/src/state_trigger.rs +672 -0
  94. package/dist/create/server-source/crates/feltdb/src/storage.rs +9 -3
  95. package/dist/create/server-source/crates/feltdb/src/submission.rs +5 -11
  96. package/dist/create/server-source/crates/feltdb/src/tcp_transport.rs +6 -8
  97. package/dist/create/server-source/crates/feltdb/src/transaction_api.rs +24 -35
  98. package/dist/create/server-source/crates/feltdb/src/transaction_invariants.rs +24 -8
  99. package/dist/create/server-source/crates/feltdb/src/transaction_preconditions.rs +248 -59
  100. package/dist/create/server-source/crates/feltdb/src/transactions.rs +17 -20
  101. package/dist/create/server-source/crates/feltdb/src/trigger_contract.rs +749 -0
  102. package/dist/create/server-source/crates/feltdb/src/worker_mesh.rs +1 -0
  103. package/dist/create/server-source/crates/feltdb/src/workload.rs +512 -4
  104. package/dist/create/server-source/crates/feltdb/src/workload_diagnostics.rs +3 -4
  105. package/dist/create/server-source/crates/feltdb/tests/bounded_read_contract.rs +132 -0
  106. package/dist/create/server-source/crates/feltdb/tests/branching_evidence.rs +299 -0
  107. package/dist/create/server-source/crates/feltdb/tests/compaction_stall_contract.rs +272 -0
  108. package/dist/create/server-source/crates/feltdb/tests/crash_durability_contract.rs +467 -0
  109. package/dist/create/server-source/crates/feltdb/tests/current_revision_authority_evidence.rs +309 -0
  110. package/dist/create/server-source/crates/feltdb/tests/durable_backup_contract.rs +445 -0
  111. package/dist/create/server-source/crates/feltdb/tests/durable_corruption_contract.rs +518 -0
  112. package/dist/create/server-source/crates/feltdb/tests/durable_format_compatibility.rs +392 -0
  113. package/dist/create/server-source/crates/feltdb/tests/feltdb_state_boundary_tests.rs +436 -220
  114. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_conflict_contract_corpus.json +1916 -0
  115. package/dist/create/server-source/crates/feltdb/tests/fixtures/state_diff_contract_corpus.json +1878 -0
  116. package/dist/create/server-source/crates/feltdb/tests/fixtures/trigger_contract_corpus.json +1862 -0
  117. package/dist/create/server-source/crates/feltdb/tests/operational_health_contract.rs +278 -0
  118. package/dist/create/server-source/crates/feltdb/tests/pr34_query_collection.rs +2 -1
  119. package/dist/create/server-source/crates/feltdb/tests/pr35_equality_index.rs +80 -25
  120. package/dist/create/server-source/crates/feltdb/tests/pr7_self_authorization_proof.rs +5 -8
  121. package/dist/create/server-source/crates/feltdb/tests/pr8_vocabulary_assessment.rs +52 -44
  122. package/dist/create/server-source/crates/feltdb/tests/pr9_phase2_boundary_tests.rs +33 -16
  123. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3a_path_a_tests.rs +22 -7
  124. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_authorized_mutations.rs +41 -22
  125. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_role_based_authorization.rs +25 -8
  126. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_simple_auth_delete.rs +9 -6
  127. package/dist/create/server-source/crates/feltdb/tests/pr9_phase3c_team_delete_role_authorization.rs +120 -69
  128. package/dist/create/server-source/crates/feltdb/tests/pr9_teams_role_based_access.rs +21 -10
  129. package/dist/create/server-source/crates/feltdb/tests/production_readiness_contract.rs +1365 -0
  130. package/dist/create/server-source/crates/feltdb/tests/reconciliation_application.rs +868 -0
  131. package/dist/create/server-source/crates/feltdb/tests/reconciliation_wire_format_evidence.rs +221 -0
  132. package/dist/create/server-source/crates/feltdb/tests/replicated_history_contract.rs +417 -0
  133. package/dist/create/server-source/crates/feltdb/tests/resource_scoped_revisions.rs +338 -0
  134. package/dist/create/server-source/crates/feltdb/tests/revision_identity_contract.rs +1039 -0
  135. package/dist/create/server-source/crates/feltdb/tests/revision_model_decision.rs +739 -0
  136. package/dist/create/server-source/crates/feltdb/tests/revision_retention_boundary_evidence.rs +427 -0
  137. package/dist/create/server-source/crates/feltdb/tests/saas_authorization_integration.rs +3 -3
  138. package/dist/create/server-source/crates/feltdb/tests/saas_invitation_lifecycle.rs +25 -22
  139. package/dist/create/server-source/crates/feltdb/tests/state_conflict_contract_conformance.rs +1799 -0
  140. package/dist/create/server-source/crates/feltdb/tests/state_diff_contract_conformance.rs +1316 -0
  141. package/dist/create/server-source/crates/feltdb/tests/state_model_integration.rs +53 -61
  142. package/dist/create/server-source/crates/feltdb/tests/state_persistence_integration.rs +156 -61
  143. package/dist/create/server-source/crates/feltdb/tests/state_store_boundary_evidence.rs +299 -0
  144. package/dist/create/server-source/crates/feltdb/tests/sync_divergence_evidence.rs +255 -0
  145. package/dist/create/server-source/crates/feltdb/tests/three_way_input_boundary_evidence.rs +249 -0
  146. package/dist/create/server-source/crates/feltdb/tests/trigger_contract_conformance.rs +994 -0
  147. package/dist/create/server-source/crates/feltdb/tests/workload_envelope_contract.rs +442 -0
  148. package/dist/create/server-source/crates/feltdb-server/src/app_state.rs +16 -1
  149. package/dist/create/server-source/crates/feltdb-server/src/auth.rs +164 -13
  150. package/dist/create/server-source/crates/feltdb-server/src/main.rs +695 -47
  151. package/dist/create/server-source/crates/feltdb-server/src/metrics.rs +21 -0
  152. package/dist/studio-app/assets/{feltdb_wasm-CVQWgXO-.js → feltdb_wasm-C1VhI-U5.js} +1 -1
  153. package/dist/studio-app/assets/feltdb_wasm_bg-C8HXbAXb.wasm +0 -0
  154. package/dist/studio-app/assets/{index-DwgNAIIX.js → index-Bbos1m2U.js} +1 -1
  155. package/dist/studio-app/index.html +1 -1
  156. package/dist/wasm/feltdb_wasm_bg.wasm +0 -0
  157. package/dist/workload.d.ts +2 -1
  158. package/dist/workload.d.ts.map +1 -1
  159. package/package.json +1 -1
  160. package/dist/studio-app/assets/feltdb_wasm_bg-CNVpvaZV.wasm +0 -0
@@ -8,8 +8,7 @@
8
8
  /// - Frontier advances: 1, 10, 100
9
9
  ///
10
10
  /// Output: CSV table suitable for crossover curve analysis
11
-
12
- use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
11
+ use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
13
12
  use feltdb::causal_dependency_barrier::CausalDependencyBarrier;
14
13
  use feltdb::convergence::VectorClock;
15
14
  use std::fs::File;
@@ -65,7 +64,11 @@ impl CrossoverMetrics {
65
64
  self.ix_index_entries,
66
65
  self.speedup,
67
66
  self.winner,
68
- if self.winner == 'I' { "INDEXED" } else { "FULL_SCAN" }
67
+ if self.winner == 'I' {
68
+ "INDEXED"
69
+ } else {
70
+ "FULL_SCAN"
71
+ }
69
72
  )
70
73
  }
71
74
  }
@@ -86,7 +89,8 @@ fn generate_workload(
86
89
  let mut operations = Vec::new();
87
90
  for i in 0..workload.pending_size {
88
91
  let mut required = VectorClock::new();
89
- let release_threshold = (workload.pending_size as f64 * workload.release_selectivity) as usize;
92
+ let release_threshold =
93
+ (workload.pending_size as f64 * workload.release_selectivity) as usize;
90
94
  let ts = if i < release_threshold {
91
95
  10 // Will be released when frontier advances to 10
92
96
  } else {
@@ -185,7 +189,13 @@ fn measure_indexed(
185
189
  candidates_discovered = barrier.get_dependency_index().waiters.len() as u64;
186
190
  }
187
191
 
188
- (latency_ns, candidates_discovered, candidates_examined, ops_released, candidates_discovered)
192
+ (
193
+ latency_ns,
194
+ candidates_discovered,
195
+ candidates_examined,
196
+ ops_released,
197
+ candidates_discovered,
198
+ )
189
199
  }
190
200
 
191
201
  /// Phase 7.1.3: Crossover Matrix Benchmark
@@ -201,8 +211,10 @@ fn benchmark_crossover_matrix(c: &mut Criterion) {
201
211
  let mut results = Vec::new();
202
212
 
203
213
  println!("\n=== Phase 7.1.3: Crossover Analysis ===");
204
- println!("{:>7} {:>3} {:>5} {:>10} {:>12} {:>12} {:>7}",
205
- "Pending", "Adv", "Sel%", "FS (µs)", "IX (µs)", "Speedup", "Winner");
214
+ println!(
215
+ "{:>7} {:>3} {:>5} {:>10} {:>12} {:>12} {:>7}",
216
+ "Pending", "Adv", "Sel%", "FS (µs)", "IX (µs)", "Speedup", "Winner"
217
+ );
206
218
 
207
219
  for pending in &pending_sizes {
208
220
  for advances in &advance_counts {
@@ -216,7 +228,8 @@ fn benchmark_crossover_matrix(c: &mut Criterion) {
216
228
  let (ops, advs) = generate_workload(&workload, 42);
217
229
 
218
230
  // Measure both paths
219
- let (fs_latency, fs_examined, fs_released) = measure_full_scan(&workload, &ops, &advs);
231
+ let (fs_latency, fs_examined, fs_released) =
232
+ measure_full_scan(&workload, &ops, &advs);
220
233
  let (ix_latency, ix_discovered, ix_examined, ix_released, ix_entries) =
221
234
  measure_indexed(&workload, &ops, &advs);
222
235
 
@@ -231,9 +244,20 @@ fn benchmark_crossover_matrix(c: &mut Criterion) {
231
244
  let fs_us = fs_latency as f64 / 1000.0;
232
245
  let ix_us = ix_latency as f64 / 1000.0;
233
246
 
234
- println!("{:>7} {:>3} {:>5.0} {:>10.1} {:>12.1} {:>12.2}x {}",
235
- pending, advances, selectivity * 100.0, fs_us, ix_us, speedup,
236
- if winner == 'I' { "INDEXED" } else { "FULL_SCAN" });
247
+ println!(
248
+ "{:>7} {:>3} {:>5.0} {:>10.1} {:>12.1} {:>12.2}x {}",
249
+ pending,
250
+ advances,
251
+ selectivity * 100.0,
252
+ fs_us,
253
+ ix_us,
254
+ speedup,
255
+ if winner == 'I' {
256
+ "INDEXED"
257
+ } else {
258
+ "FULL_SCAN"
259
+ }
260
+ );
237
261
 
238
262
  let metrics = CrossoverMetrics {
239
263
  pending: *pending,
@@ -254,15 +278,21 @@ fn benchmark_crossover_matrix(c: &mut Criterion) {
254
278
  results.push(metrics);
255
279
 
256
280
  // Criterion benchmarks for regression gates
257
- let bench_name = format!("pending_{}_adv_{}_sel_{:.0}pct",
258
- pending, advances, selectivity * 100.0);
281
+ let bench_name = format!(
282
+ "pending_{}_adv_{}_sel_{:.0}pct",
283
+ pending,
284
+ advances,
285
+ selectivity * 100.0
286
+ );
259
287
 
260
288
  group.bench_with_input(
261
289
  BenchmarkId::new("full_scan", &bench_name),
262
290
  &workload,
263
291
  |b, w| {
264
292
  let (ops, advs) = generate_workload(w, 42);
265
- b.iter(|| measure_full_scan(black_box(w), black_box(&ops), black_box(&advs)));
293
+ b.iter(|| {
294
+ measure_full_scan(black_box(w), black_box(&ops), black_box(&advs))
295
+ });
266
296
  },
267
297
  );
268
298
 
@@ -282,7 +312,8 @@ fn benchmark_crossover_matrix(c: &mut Criterion) {
282
312
 
283
313
  // Write results to CSV for analysis
284
314
  if let Ok(mut file) = File::create("target/phase_7_1_3_crossover.csv") {
285
- let _ = writeln!(file,
315
+ let _ =
316
+ writeln!(file,
286
317
  "pending,advances,selectivity_pct,fs_latency_ns,fs_entries_examined,fs_ops_released,\
287
318
  ix_latency_ns,ix_candidates_discovered,ix_candidates_examined,ix_ops_released,\
288
319
  ix_index_entries,speedup,winner,winner_name");
@@ -2,7 +2,6 @@
2
2
  ///
3
3
  /// Defines explicit, machine-readable submission semantics.
4
4
  /// Never silently drops operations. Rejection is explicit and retryable.
5
-
6
5
  use serde::{Deserialize, Serialize};
7
6
  use std::fmt;
8
7
 
@@ -12,9 +11,7 @@ pub enum SubmissionOutcome {
12
11
  /// Operation accepted for processing
13
12
  /// Operations are accepted in order but may not yet be committed.
14
13
  /// Caller should wait for CommitAck before assuming durability.
15
- Accepted {
16
- operation_id: u64,
17
- },
14
+ Accepted { operation_id: u64 },
18
15
 
19
16
  /// Operation rejected due to backpressure
20
17
  /// Caller should retry with backoff
@@ -103,11 +100,11 @@ impl ProductionRetryPolicy {
103
100
  ProductionRetryPolicy {
104
101
  max_attempts: 4,
105
102
  backoff_sequence: vec![
106
- 0, // Attempt 1: no backoff (immediate)
107
- 100, // Attempt 2: 100µs
108
- 200, // Attempt 3: 200µs
109
- 400, // Attempt 4: 400µs
110
- // Total: 700µs of bounded admission attempts
103
+ 0, // Attempt 1: no backoff (immediate)
104
+ 100, // Attempt 2: 100µs
105
+ 200, // Attempt 3: 200µs
106
+ 400, // Attempt 4: 400µs
107
+ // Total: 700µs of bounded admission attempts
111
108
  ],
112
109
  }
113
110
  }
@@ -117,9 +114,7 @@ impl ProductionRetryPolicy {
117
114
  pub fn stress_test() -> Self {
118
115
  ProductionRetryPolicy {
119
116
  max_attempts: 10,
120
- backoff_sequence: vec![
121
- 0, 50, 100, 150, 200, 250, 300, 350, 400, 450,
122
- ],
117
+ backoff_sequence: vec![0, 50, 100, 150, 200, 250, 300, 350, 400, 450],
123
118
  }
124
119
  }
125
120
 
@@ -168,9 +163,7 @@ mod tests {
168
163
 
169
164
  #[test]
170
165
  fn outcome_accessors_work() {
171
- let accepted = SubmissionOutcome::Accepted {
172
- operation_id: 123,
173
- };
166
+ let accepted = SubmissionOutcome::Accepted { operation_id: 123 };
174
167
  assert!(accepted.is_accepted());
175
168
  assert!(!accepted.is_rejected());
176
169
 
@@ -38,7 +38,10 @@ mod tests {
38
38
  record_id: "rec1".to_string(),
39
39
  fields: {
40
40
  let mut m = HashMap::new();
41
- m.insert("field".to_string(), serde_json::json!(format!("value_{}", seq)));
41
+ m.insert(
42
+ "field".to_string(),
43
+ serde_json::json!(format!("value_{}", seq)),
44
+ );
42
45
  m
43
46
  },
44
47
  },
@@ -62,7 +65,11 @@ mod tests {
62
65
  assert!(true, "Operation explicitly accepted");
63
66
  }
64
67
  SubmissionOutcome::Rejected(ref reason) => {
65
- assert!(true, "Operation explicitly rejected with reason: {:?}", reason);
68
+ assert!(
69
+ true,
70
+ "Operation explicitly rejected with reason: {:?}",
71
+ reason
72
+ );
66
73
  }
67
74
  }
68
75
  }
@@ -101,7 +108,10 @@ mod tests {
101
108
 
102
109
  let op1 = create_operation("node1", 1);
103
110
  let outcome1 = submitter.submit(op1.clone());
104
- assert!(outcome1.is_accepted(), "First submission should be accepted");
111
+ assert!(
112
+ outcome1.is_accepted(),
113
+ "First submission should be accepted"
114
+ );
105
115
 
106
116
  let outcome2 = submitter.submit(op1);
107
117
  assert!(outcome2.is_rejected(), "Duplicate should be rejected");
@@ -110,7 +120,10 @@ mod tests {
110
120
  SubmissionOutcome::Rejected(RejectionReason::DuplicateDetected {
111
121
  original_operation_id,
112
122
  }) => {
113
- assert_eq!(original_operation_id, 1, "Should identify original operation ID");
123
+ assert_eq!(
124
+ original_operation_id, 1,
125
+ "Should identify original operation ID"
126
+ );
114
127
  }
115
128
  _ => panic!("Expected DuplicateDetected rejection reason"),
116
129
  }
@@ -130,8 +143,14 @@ mod tests {
130
143
  retry_after_us,
131
144
  suggested_backoff_ms,
132
145
  } => {
133
- assert!(retry_after_us > 0, "retry_after_us should guide backoff strategy");
134
- assert!(suggested_backoff_ms > 0, "suggested_backoff_ms should guide backoff");
146
+ assert!(
147
+ retry_after_us > 0,
148
+ "retry_after_us should guide backoff strategy"
149
+ );
150
+ assert!(
151
+ suggested_backoff_ms > 0,
152
+ "suggested_backoff_ms should guide backoff"
153
+ );
135
154
  }
136
155
  _ => panic!("Expected AdmissionBackpressure"),
137
156
  }
@@ -159,7 +178,10 @@ mod tests {
159
178
  RejectionReason::DuplicateDetected {
160
179
  original_operation_id,
161
180
  } => {
162
- assert_eq!(original_operation_id, 42, "Should identify original operation");
181
+ assert_eq!(
182
+ original_operation_id, 42,
183
+ "Should identify original operation"
184
+ );
163
185
  }
164
186
  _ => panic!("Expected DuplicateDetected"),
165
187
  }
@@ -279,7 +301,10 @@ mod tests {
279
301
  let policy = ProductionRetryPolicy::standard();
280
302
 
281
303
  // Verify bounded policy constraints
282
- assert!(policy.max_attempts < 100, "max_attempts should be reasonable");
304
+ assert!(
305
+ policy.max_attempts < 100,
306
+ "max_attempts should be reasonable"
307
+ );
283
308
  assert!(
284
309
  policy.backoff_sequence.len() <= policy.max_attempts,
285
310
  "backoff sequence length should not exceed max_attempts"
@@ -353,7 +378,11 @@ mod tests {
353
378
 
354
379
  let elapsed = start.elapsed();
355
380
 
356
- assert_eq!(accepted + rejected, 1000, "Every operation must get an outcome");
381
+ assert_eq!(
382
+ accepted + rejected,
383
+ 1000,
384
+ "Every operation must get an outcome"
385
+ );
357
386
  assert_eq!(rejected, 0, "Under normal load, no rejections expected");
358
387
  println!(
359
388
  "Processed 1000 operations in {:.2}ms ({:.0} ops/sec)",
@@ -398,7 +427,10 @@ mod tests {
398
427
 
399
428
  // First cycle: all should be accepted
400
429
  assert_eq!(accepted_by_cycle[0], 20, "First cycle should accept all");
401
- assert_eq!(duplicates_by_cycle[0], 0, "First cycle should have no duplicates");
430
+ assert_eq!(
431
+ duplicates_by_cycle[0], 0,
432
+ "First cycle should have no duplicates"
433
+ );
402
434
 
403
435
  // Subsequent cycles: all should be duplicates
404
436
  for cycle in 1..5 {
@@ -464,9 +496,7 @@ mod tests {
464
496
 
465
497
  #[test]
466
498
  fn contract_outcome_accessors_are_correct() {
467
- let accepted = SubmissionOutcome::Accepted {
468
- operation_id: 42,
469
- };
499
+ let accepted = SubmissionOutcome::Accepted { operation_id: 42 };
470
500
  assert!(accepted.is_accepted());
471
501
  assert!(!accepted.is_rejected());
472
502
 
@@ -9,7 +9,6 @@
9
9
  /// send → maybe delay → maybe duplicate → maybe drop → eventually deliver
10
10
  ///
11
11
  /// FeltDB must converge itself. Simulator cannot help.
12
-
13
12
  use std::collections::{HashMap, VecDeque};
14
13
 
15
14
  /// Reproducible fault seed
@@ -44,32 +43,17 @@ pub enum LinkState {
44
43
  #[derive(Clone, Debug, Eq, PartialEq)]
45
44
  pub enum NetworkEvent {
46
45
  /// Delay a message by N ticks
47
- Delay {
48
- message_id: MessageId,
49
- ticks: u64,
50
- },
46
+ Delay { message_id: MessageId, ticks: u64 },
51
47
  /// Drop a message permanently
52
- Drop {
53
- message_id: MessageId,
54
- },
48
+ Drop { message_id: MessageId },
55
49
  /// Duplicate a message
56
- Duplicate {
57
- message_id: MessageId,
58
- },
50
+ Duplicate { message_id: MessageId },
59
51
  /// Partition a directional link
60
- Partition {
61
- from: NodeId,
62
- to: NodeId,
63
- },
52
+ Partition { from: NodeId, to: NodeId },
64
53
  /// Heal a directional link
65
- Heal {
66
- from: NodeId,
67
- to: NodeId,
68
- },
54
+ Heal { from: NodeId, to: NodeId },
69
55
  /// Reorder messages on a connection
70
- Reorder {
71
- connection: ConnectionId,
72
- },
56
+ Reorder { connection: ConnectionId },
73
57
  }
74
58
 
75
59
  /// Deterministic network schedule (fully reproducible from seed)
@@ -125,11 +109,13 @@ impl ConnectivityMatrix {
125
109
  }
126
110
 
127
111
  pub fn partition(&mut self, from: NodeId, to: NodeId) {
128
- self.links.insert(ConnectionId { from, to }, LinkState::Partitioned);
112
+ self.links
113
+ .insert(ConnectionId { from, to }, LinkState::Partitioned);
129
114
  }
130
115
 
131
116
  pub fn heal(&mut self, from: NodeId, to: NodeId) {
132
- self.links.insert(ConnectionId { from, to }, LinkState::Connected);
117
+ self.links
118
+ .insert(ConnectionId { from, to }, LinkState::Connected);
133
119
  }
134
120
 
135
121
  pub fn get_state(&self, from: NodeId, to: NodeId) -> LinkState {
@@ -326,10 +312,7 @@ impl ReplicationTransport for AdversarialTransport {
326
312
 
327
313
  fn apply_fault(&mut self, event: NetworkEvent) {
328
314
  match event {
329
- NetworkEvent::Delay {
330
- message_id,
331
- ticks,
332
- } => {
315
+ NetworkEvent::Delay { message_id, ticks } => {
333
316
  // Find message and delay delivery
334
317
  for msg in &mut self.in_flight {
335
318
  if msg.id == message_id {
@@ -438,10 +421,7 @@ mod tests {
438
421
  let n2 = NodeId(2);
439
422
 
440
423
  // Partition n1 → n2
441
- transport.apply_fault(NetworkEvent::Partition {
442
- from: n1,
443
- to: n2,
444
- });
424
+ transport.apply_fault(NetworkEvent::Partition { from: n1, to: n2 });
445
425
 
446
426
  // Message should be dropped
447
427
  let _msg_id = transport.send(n1, n2, vec![1, 2, 3]);
@@ -489,9 +469,7 @@ mod tests {
489
469
  let msg_id = transport.send(n1, n2, vec![1, 2, 3]);
490
470
 
491
471
  // Duplicate the message
492
- transport.apply_fault(NetworkEvent::Duplicate {
493
- message_id: msg_id,
494
- });
472
+ transport.apply_fault(NetworkEvent::Duplicate { message_id: msg_id });
495
473
 
496
474
  transport.tick();
497
475
  let messages = transport.receive(n2);
@@ -510,9 +488,7 @@ mod tests {
510
488
 
511
489
  let msg_id = transport.send(n1, n2, vec![1, 2, 3]);
512
490
 
513
- transport.apply_fault(NetworkEvent::Drop {
514
- message_id: msg_id,
515
- });
491
+ transport.apply_fault(NetworkEvent::Drop { message_id: msg_id });
516
492
 
517
493
  transport.tick();
518
494
  let messages = transport.receive(n2);
@@ -528,10 +504,7 @@ mod tests {
528
504
  let n2 = NodeId(2);
529
505
 
530
506
  // Partition n1 → n2 only (asymmetric)
531
- transport.apply_fault(NetworkEvent::Partition {
532
- from: n1,
533
- to: n2,
534
- });
507
+ transport.apply_fault(NetworkEvent::Partition { from: n1, to: n2 });
535
508
 
536
509
  // n1 → n2 blocked
537
510
  let _msg_id = transport.send(n1, n2, vec![1, 2, 3]);
@@ -85,11 +85,13 @@ impl IndexAnalytics {
85
85
  if operation == "read" {
86
86
  let old_avg = metric.avg_query_time_ms;
87
87
  metric.reads += 1;
88
- metric.avg_query_time_ms = (old_avg * (metric.reads - 1) as f64 + time_ms) / metric.reads as f64;
88
+ metric.avg_query_time_ms =
89
+ (old_avg * (metric.reads - 1) as f64 + time_ms) / metric.reads as f64;
89
90
  } else {
90
91
  let old_avg = metric.avg_write_time_ms;
91
92
  metric.writes += 1;
92
- metric.avg_write_time_ms = (old_avg * (metric.writes - 1) as f64 + time_ms) / metric.writes as f64;
93
+ metric.avg_write_time_ms =
94
+ (old_avg * (metric.writes - 1) as f64 + time_ms) / metric.writes as f64;
93
95
  }
94
96
 
95
97
  metric.last_used_at = current_time_ms();
@@ -142,13 +144,21 @@ impl IndexAnalytics {
142
144
 
143
145
  pub fn get_slowest_queries(&self, limit: usize) -> Vec<QueryTrace> {
144
146
  let mut traces = self.query_traces.clone();
145
- traces.sort_by(|a, b| b.execution_time_ms.partial_cmp(&a.execution_time_ms).unwrap_or(std::cmp::Ordering::Equal));
147
+ traces.sort_by(|a, b| {
148
+ b.execution_time_ms
149
+ .partial_cmp(&a.execution_time_ms)
150
+ .unwrap_or(std::cmp::Ordering::Equal)
151
+ });
146
152
  traces.truncate(limit);
147
153
  traces
148
154
  }
149
155
 
150
156
  pub fn get_frequent_fields(&self, limit: usize) -> Vec<(String, u64)> {
151
- let mut fields: Vec<_> = self.field_query_count.iter().map(|(k, v)| (k.clone(), *v)).collect();
157
+ let mut fields: Vec<_> = self
158
+ .field_query_count
159
+ .iter()
160
+ .map(|(k, v)| (k.clone(), *v))
161
+ .collect();
152
162
  fields.sort_by(|a, b| b.1.cmp(&a.1));
153
163
  fields.truncate(limit);
154
164
  fields
@@ -182,11 +192,7 @@ impl IndexAnalytics {
182
192
  }
183
193
  }
184
194
 
185
- pub fn generate_report(
186
- &self,
187
- collection_name: &str,
188
- period: &str,
189
- ) -> PerformanceReport {
195
+ pub fn generate_report(&self, collection_name: &str, period: &str) -> PerformanceReport {
190
196
  let now = current_time_ms();
191
197
  let cutoff = match period {
192
198
  "hourly" => now - 3_600_000,
@@ -201,20 +207,31 @@ impl IndexAnalytics {
201
207
  .cloned()
202
208
  .collect();
203
209
 
204
- let indexed_queries = recent_traces.iter().filter(|t| t.index_used.is_some()).count();
210
+ let indexed_queries = recent_traces
211
+ .iter()
212
+ .filter(|t| t.index_used.is_some())
213
+ .count();
205
214
  let full_scans = recent_traces.len() - indexed_queries;
206
215
 
207
216
  let avg_query_time = if recent_traces.is_empty() {
208
217
  0.0
209
218
  } else {
210
- recent_traces.iter().map(|t| t.execution_time_ms).sum::<f64>() / recent_traces.len() as f64
219
+ recent_traces
220
+ .iter()
221
+ .map(|t| t.execution_time_ms)
222
+ .sum::<f64>()
223
+ / recent_traces.len() as f64
211
224
  };
212
225
 
213
226
  let slowest_query = if recent_traces.is_empty() {
214
227
  None
215
228
  } else {
216
229
  let mut traces = recent_traces.clone();
217
- traces.sort_by(|a, b| b.execution_time_ms.partial_cmp(&a.execution_time_ms).unwrap_or(std::cmp::Ordering::Equal));
230
+ traces.sort_by(|a, b| {
231
+ b.execution_time_ms
232
+ .partial_cmp(&a.execution_time_ms)
233
+ .unwrap_or(std::cmp::Ordering::Equal)
234
+ });
218
235
  traces.first().cloned()
219
236
  };
220
237
 
@@ -267,7 +284,10 @@ impl IndexAnalytics {
267
284
  rec_type: "create_index".to_string(),
268
285
  priority: "high".to_string(),
269
286
  index_name: None,
270
- reason: format!("Field '{}' scanned {:.0} rows per query", field, avg_scanned_per_query),
287
+ reason: format!(
288
+ "Field '{}' scanned {:.0} rows per query",
289
+ field, avg_scanned_per_query
290
+ ),
271
291
  expected_speedup: Some(avg_scanned_per_query / 10.0),
272
292
  estimated_roi: None,
273
293
  });
@@ -283,7 +303,10 @@ impl IndexAnalytics {
283
303
  rec_type: "drop_index".to_string(),
284
304
  priority: "low".to_string(),
285
305
  index_name: Some(metric.name.clone()),
286
- reason: format!("Index has {:.1}% hit rate and unused for 24h", metric.hit_rate * 100.0),
306
+ reason: format!(
307
+ "Index has {:.1}% hit rate and unused for 24h",
308
+ metric.hit_rate * 100.0
309
+ ),
287
310
  expected_speedup: None,
288
311
  estimated_roi: Some(-0.01),
289
312
  });
@@ -307,7 +330,11 @@ impl IndexAnalytics {
307
330
  rec_type: "create_index".to_string(),
308
331
  priority: "medium".to_string(),
309
332
  index_name: None,
310
- reason: format!("Fields '{}' queried together in {} queries", fields.replace('|', ", "), count),
333
+ reason: format!(
334
+ "Fields '{}' queried together in {} queries",
335
+ fields.replace('|', ", "),
336
+ count
337
+ ),
311
338
  expected_speedup: Some(5.0),
312
339
  estimated_roi: None,
313
340
  });
@@ -326,7 +353,9 @@ impl IndexAnalytics {
326
353
  if priority_cmp == std::cmp::Ordering::Equal {
327
354
  let speedup_a = a.expected_speedup.unwrap_or(0.0);
328
355
  let speedup_b = b.expected_speedup.unwrap_or(0.0);
329
- speedup_b.partial_cmp(&speedup_a).unwrap_or(std::cmp::Ordering::Equal)
356
+ speedup_b
357
+ .partial_cmp(&speedup_a)
358
+ .unwrap_or(std::cmp::Ordering::Equal)
330
359
  } else {
331
360
  priority_cmp
332
361
  }
@@ -368,7 +397,14 @@ impl AutoTuner {
368
397
  return false;
369
398
  }
370
399
 
371
- let key = format!("{}:{}", recommendation.rec_type, recommendation.index_name.as_ref().unwrap_or(&recommendation.reason));
400
+ let key = format!(
401
+ "{}:{}",
402
+ recommendation.rec_type,
403
+ recommendation
404
+ .index_name
405
+ .as_ref()
406
+ .unwrap_or(&recommendation.reason)
407
+ );
372
408
  if self.applied_recommendations.contains(&key) {
373
409
  return false;
374
410
  }
@@ -386,13 +422,23 @@ impl AutoTuner {
386
422
  return false;
387
423
  }
388
424
 
389
- let key = format!("{}:{}", recommendation.rec_type, recommendation.index_name.as_ref().unwrap_or(&recommendation.reason));
425
+ let key = format!(
426
+ "{}:{}",
427
+ recommendation.rec_type,
428
+ recommendation
429
+ .index_name
430
+ .as_ref()
431
+ .unwrap_or(&recommendation.reason)
432
+ );
390
433
  self.applied_recommendations.insert(key);
391
434
  true
392
435
  }
393
436
 
394
437
  /// Get recommendations that are ready for auto-apply.
395
- pub fn get_auto_applicable_recommendations(&self, report: &PerformanceReport) -> Vec<TuningRecommendation> {
438
+ pub fn get_auto_applicable_recommendations(
439
+ &self,
440
+ report: &PerformanceReport,
441
+ ) -> Vec<TuningRecommendation> {
396
442
  report
397
443
  .recommendations
398
444
  .iter()