Skip to main content

MemoryStore

Struct MemoryStore 

Source
pub struct MemoryStore { /* private fields */ }

Implementations§

Source§

impl MemoryStore

Source

pub fn calibration(&self, family: Option<&str>) -> CalibrationReport

Calibration of every family, or of one family.

Source

pub fn calibration_report(&self, filter: FamilyFilter<'_>) -> CalibrationReport

Calibration of the families filter selects; a prefix filter adds pooled rows.

Source§

impl MemoryStore

Source

pub fn active_conflicts(&self) -> Vec<ActiveConflict>

Every claim key whose active traces carry more than one normalized value. Conflicts are derived from current state on every call, so a supersession or purge resolves them without any extra event. Sensitive traces are left out unless the policy allows them.

Source§

impl MemoryStore

Source

pub fn consolidation_proposals(&self) -> Vec<ConsolidationProposal>

Quiet Replay: generate evidence-preserving consolidation proposals. This never writes a new belief automatically.

Source§

impl MemoryStore

Source

pub fn focus(&self, query: &RecallQuery) -> FocusCapsule

Start a working set from one recall, bounded by the policy’s working_set_limit.

Source§

impl MemoryStore

Source

pub fn open(path: impl AsRef<Path>, policy: KernelPolicy) -> Result<Self>

Open a store, creating the file (and parent directories) when it does not exist. Use this for commands that write. Read-only commands should use Self::open_existing.

Examples found in repository?
examples/retrieval_bench.rs (line 154)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
239
240fn corrections(dir: &Path, cases: usize) -> Result<()> {
241    if !(1..=10000).contains(&cases) {
242        return Err("cases must be 1..10000".into());
243    }
244    let path = fresh(dir)?;
245    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
246    let mut stale_hits = 0;
247    let mut latest_hits = 0;
248    let mut model_rejections = 0;
249    let mut link_hits = 0;
250    let mut expected = Vec::new();
251    for i in 0..cases {
252        let subject = format!("service{i}topic");
253        let key = format!("{subject}.region");
254        let mut predecessor = None;
255        for (version, value) in ["oldregion", "middlezone", "newlocation"]
256            .iter()
257            .enumerate()
258        {
259            let id = format!("{i}-v{version}");
260            let mut trace = make_trace(
261                &id,
262                &format!("{subject} {value}"),
263                "synthetic:correction",
264                if version == 0 {
265                    TraceKind::Belief
266                } else {
267                    TraceKind::Correction
268                },
269            );
270            trace.claim_key = Some(key.clone());
271            trace.claim_value = Some((*value).into());
272            trace.supersedes = predecessor;
273            store.remember(trace)?;
274            predecessor = Some(id);
275        }
276        let mut malicious = make_trace(
277            &format!("{i}-model"),
278            "invented overwrite",
279            "model:fixture",
280            TraceKind::Correction,
281        );
282        malicious.supersedes = predecessor;
283        model_rejections += usize::from(store.remember(malicious).is_err());
284        let results = store.recall(&RecallQuery::new(&subject));
285        stale_hits += results
286            .iter()
287            .filter(|r| r.trace.id == format!("{i}-v0") || r.trace.id == format!("{i}-v1"))
288            .count();
289        latest_hits += usize::from(results.iter().any(|r| r.trace.id == format!("{i}-v2")));
290        link_hits +=
291            usize::from(results.iter().any(|r| {
292                r.trace.id == format!("{i}-v2") && r.supersedes == Some(format!("{i}-v1"))
293            }));
294        expected.push((subject, format!("{i}-v2")));
295    }
296    let old_only_results = store
297        .recall(&RecallQuery::new("oldregion middlezone"))
298        .len();
299    drop(store);
300    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
301    store.verify()?;
302    let restart_hits = expected
303        .iter()
304        .filter(|(q, id)| {
305            store
306                .recall(&RecallQuery::new(q))
307                .iter()
308                .any(|r| &r.trace.id == id)
309        })
310        .count();
311    let provenance = store
312        .all()
313        .filter(|e| {
314            e.trace.provenance.source == "synthetic:correction" && !e.trace.provenance.verified
315        })
316        .count();
317    let ok = stale_hits == 0
318        && latest_hits == cases
319        && model_rejections == cases
320        && link_hits == cases
321        && old_only_results == 0
322        && restart_hits == cases
323        && provenance == 3 * cases;
324    emit(
325        json!({"kind": "synthetic_corrections", "cases": cases, "ok": ok,
326        "stale_hits": stale_hits, "latest_hits": latest_hits, "supersession_link_hits": link_hits,
327        "model_overwrite_rejections": model_rejections, "old_only_query_results": old_only_results,
328        "latest_hits_after_restart": restart_hits, "provenance_retained": provenance,
329        "limits": ["Generated structured histories; not extracted real incident corrections.",
330          "Subject variants of one generated template, not independent real incidents or a proof across all histories.",
331          "A query matching only retired terms abstains; no semantic alias expansion is implied."]}),
332    )?;
333    if !ok {
334        return Err("correction invariant failure".into());
335    }
336    Ok(())
337}
More examples
Hide additional examples
examples/bench_kernel.rs (line 119)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
214
215// Specified, platform-independent SplitMix64; never a cryptographic RNG.
216struct Rng(u64);
217impl Rng {
218    fn next(&mut self) -> u64 {
219        self.0 = self.0.wrapping_add(0x9e3779b97f4a7c15);
220        let mut x = self.0;
221        x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
222        x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
223        x ^ (x >> 31)
224    }
225    fn unit(&mut self) -> f64 {
226        (self.next() % 10001) as f64 / 10000.0
227    }
228}
229
230fn option(name: &str, a: f64, b: f64) -> DecisionOption {
231    DecisionOption {
232        name: name.into(),
233        description: None,
234        scores: BTreeMap::from([("a".into(), a), ("b".into(), b)]),
235        model_scores: BTreeMap::new(),
236        evidence_confidence: 1.0,
237        hard_blocks: vec![],
238        reversible: false,
239    }
240}
241
242fn decisions(cases: usize, seed: u64) -> Result<Value> {
243    if cases < 6 {
244        return Err("at least 6 cases required to exercise every family".into());
245    }
246    let mut rng = Rng(seed);
247    let mut counts: BTreeMap<&str, usize> = BTreeMap::new();
248    let mut failures = Vec::new();
249    let mut violations = 0;
250    let start = Instant::now();
251    for i in 0..cases {
252        let mut a = option("a", rng.unit(), rng.unit());
253        let mut b = option("b", rng.unit(), rng.unit());
254        let family;
255        let mut expected: Option<Option<String>> = None;
256        match i % 6 {
257            0 => {
258                family = "high_score_hard_block";
259                a.scores.values_mut().for_each(|s| *s = 1.0);
260                a.hard_blocks.push("no authorization".into());
261                expected = Some(Some("b".into()));
262            }
263            1 => {
264                family = "all_blocked";
265                a.hard_blocks.push("privacy".into());
266                b.hard_blocks.push("consent".into());
267                expected = Some(None);
268            }
269            2 => {
270                family = "complete_score_oracle";
271                let sum_a: f64 = a.scores.values().sum();
272                let sum_b: f64 = b.scores.values().sum();
273                expected = Some(Some(if sum_a >= sum_b { "a" } else { "b" }.into()));
274            }
275            3 => {
276                family = "unknowns_and_model_estimates";
277                a.scores.clear();
278                a.model_scores.insert("a".into(), rng.unit());
279            }
280            4 => {
281                family = "reversibility_band";
282                let top = 0.5 + rng.unit() * 0.4;
283                let gap = if rng.next().is_multiple_of(2) {
284                    0.01
285                } else {
286                    0.03
287                };
288                a.scores.values_mut().for_each(|s| *s = top);
289                a.evidence_confidence = 0.1;
290                b.scores.values_mut().for_each(|s| *s = top - gap);
291                b.reversible = true;
292                expected = Some(Some(if gap < 0.02 { "b" } else { "a" }.into()));
293            }
294            _ => {
295                family = "invalid_numeric_input";
296                a.scores.insert("a".into(), 1.01 + rng.unit());
297            }
298        }
299        *counts.entry(family).or_default() += 1;
300        let frame = DecisionFrame {
301            question: "synthetic decision".into(),
302            criteria: ["a", "b"]
303                .into_iter()
304                .map(|id| Criterion {
305                    id: id.into(),
306                    weight: 1.0,
307                    description: id.into(),
308                })
309                .collect(),
310            options: vec![a, b],
311        };
312        let actual = evaluate(&frame);
313        let mut reasons = Vec::new();
314        if family == "invalid_numeric_input" {
315            if actual.is_ok() {
316                reasons.push("invalid input admitted");
317            }
318        } else if let Ok(answer) = &actual {
319            if let Some(expected) = expected {
320                if answer.recommended != expected {
321                    reasons.push("wrong recommendation");
322                }
323            }
324            if let Some(name) = &answer.recommended {
325                if frame
326                    .options
327                    .iter()
328                    .any(|o| &o.name == name && !o.hard_blocks.is_empty())
329                {
330                    reasons.push("hard-blocked option selected");
331                }
332            }
333            if family == "unknowns_and_model_estimates" {
334                let ranked = answer.ranking.iter().find(|o| o.name == "a").unwrap();
335                if ranked.coverage != 0.0
336                    || ranked.evidence_interval != [0.0, 1.0]
337                    || ranked.missing_criteria != ["b"]
338                    || answer.decisive
339                {
340                    reasons.push("unknown evidence hidden or model guess counted as evidence");
341                }
342            }
343            let mut permuted = frame.clone();
344            permuted.options.reverse();
345            permuted.question = "irrelevant wording changed".into();
346            let other = evaluate(&permuted)?;
347            if answer.recommended != other.recommended
348                || serde_json::to_value(&answer.ranking)? != serde_json::to_value(&other.ranking)?
349            {
350                reasons.push("order or irrelevant text changed result");
351            }
352        } else {
353            reasons.push("valid frame rejected");
354        }
355        if !reasons.is_empty() {
356            violations += 1;
357            if failures.len() < 20 {
358                failures.push(
359                    json!({"case_index": i, "family": family, "reasons": reasons,
360                    "frame": frame, "actual": actual.as_ref().ok()}),
361                );
362            }
363        }
364    }
365    Ok(
366        json!({"kind": "synthetic_decision_invariants", "seed": seed, "rng": "splitmix64",
367        "cases": cases, "families": counts, "violations": violations,
368        "violation_rate": violations as f64 / cases as f64, "ok": violations == 0,
369        "elapsed_ms": ms(start), "counterexamples": failures,
370        "limits": ["Generated families are not real decision-quality labels or a proof over all inputs.",
371          "Metamorphic checks keep criteria fixed; weight perturbations require separate expectations."]}),
372    )
373}
374
375fn committed_child(dir: &Path) -> Result<()> {
376    let path = fresh(dir)?;
377    let mut store = MemoryStore::open(path, KernelPolicy::default())?;
378    store.remember_many((0..50).map(trace).collect())?;
379    println!("committed:50");
380    io::stdout().flush()?;
381    // Parent kills us after the acknowledged commit; this is not an in-flight crash claim.
382    loop {
383        std::thread::park();
384    }
385}
386
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn open_existing( path: impl AsRef<Path>, policy: KernelPolicy, ) -> Result<Self>

Open a store that must already exist. A mistyped path is an error, not an empty store.

Examples found in repository?
examples/retrieval_bench.rs (line 187)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
239
240fn corrections(dir: &Path, cases: usize) -> Result<()> {
241    if !(1..=10000).contains(&cases) {
242        return Err("cases must be 1..10000".into());
243    }
244    let path = fresh(dir)?;
245    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
246    let mut stale_hits = 0;
247    let mut latest_hits = 0;
248    let mut model_rejections = 0;
249    let mut link_hits = 0;
250    let mut expected = Vec::new();
251    for i in 0..cases {
252        let subject = format!("service{i}topic");
253        let key = format!("{subject}.region");
254        let mut predecessor = None;
255        for (version, value) in ["oldregion", "middlezone", "newlocation"]
256            .iter()
257            .enumerate()
258        {
259            let id = format!("{i}-v{version}");
260            let mut trace = make_trace(
261                &id,
262                &format!("{subject} {value}"),
263                "synthetic:correction",
264                if version == 0 {
265                    TraceKind::Belief
266                } else {
267                    TraceKind::Correction
268                },
269            );
270            trace.claim_key = Some(key.clone());
271            trace.claim_value = Some((*value).into());
272            trace.supersedes = predecessor;
273            store.remember(trace)?;
274            predecessor = Some(id);
275        }
276        let mut malicious = make_trace(
277            &format!("{i}-model"),
278            "invented overwrite",
279            "model:fixture",
280            TraceKind::Correction,
281        );
282        malicious.supersedes = predecessor;
283        model_rejections += usize::from(store.remember(malicious).is_err());
284        let results = store.recall(&RecallQuery::new(&subject));
285        stale_hits += results
286            .iter()
287            .filter(|r| r.trace.id == format!("{i}-v0") || r.trace.id == format!("{i}-v1"))
288            .count();
289        latest_hits += usize::from(results.iter().any(|r| r.trace.id == format!("{i}-v2")));
290        link_hits +=
291            usize::from(results.iter().any(|r| {
292                r.trace.id == format!("{i}-v2") && r.supersedes == Some(format!("{i}-v1"))
293            }));
294        expected.push((subject, format!("{i}-v2")));
295    }
296    let old_only_results = store
297        .recall(&RecallQuery::new("oldregion middlezone"))
298        .len();
299    drop(store);
300    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
301    store.verify()?;
302    let restart_hits = expected
303        .iter()
304        .filter(|(q, id)| {
305            store
306                .recall(&RecallQuery::new(q))
307                .iter()
308                .any(|r| &r.trace.id == id)
309        })
310        .count();
311    let provenance = store
312        .all()
313        .filter(|e| {
314            e.trace.provenance.source == "synthetic:correction" && !e.trace.provenance.verified
315        })
316        .count();
317    let ok = stale_hits == 0
318        && latest_hits == cases
319        && model_rejections == cases
320        && link_hits == cases
321        && old_only_results == 0
322        && restart_hits == cases
323        && provenance == 3 * cases;
324    emit(
325        json!({"kind": "synthetic_corrections", "cases": cases, "ok": ok,
326        "stale_hits": stale_hits, "latest_hits": latest_hits, "supersession_link_hits": link_hits,
327        "model_overwrite_rejections": model_rejections, "old_only_query_results": old_only_results,
328        "latest_hits_after_restart": restart_hits, "provenance_retained": provenance,
329        "limits": ["Generated structured histories; not extracted real incident corrections.",
330          "Subject variants of one generated template, not independent real incidents or a proof across all histories.",
331          "A query matching only retired terms abstains; no semantic alias expansion is implied."]}),
332    )?;
333    if !ok {
334        return Err("correction invariant failure".into());
335    }
336    Ok(())
337}
More examples
Hide additional examples
examples/bench_kernel.rs (line 167)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
214
215// Specified, platform-independent SplitMix64; never a cryptographic RNG.
216struct Rng(u64);
217impl Rng {
218    fn next(&mut self) -> u64 {
219        self.0 = self.0.wrapping_add(0x9e3779b97f4a7c15);
220        let mut x = self.0;
221        x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
222        x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
223        x ^ (x >> 31)
224    }
225    fn unit(&mut self) -> f64 {
226        (self.next() % 10001) as f64 / 10000.0
227    }
228}
229
230fn option(name: &str, a: f64, b: f64) -> DecisionOption {
231    DecisionOption {
232        name: name.into(),
233        description: None,
234        scores: BTreeMap::from([("a".into(), a), ("b".into(), b)]),
235        model_scores: BTreeMap::new(),
236        evidence_confidence: 1.0,
237        hard_blocks: vec![],
238        reversible: false,
239    }
240}
241
242fn decisions(cases: usize, seed: u64) -> Result<Value> {
243    if cases < 6 {
244        return Err("at least 6 cases required to exercise every family".into());
245    }
246    let mut rng = Rng(seed);
247    let mut counts: BTreeMap<&str, usize> = BTreeMap::new();
248    let mut failures = Vec::new();
249    let mut violations = 0;
250    let start = Instant::now();
251    for i in 0..cases {
252        let mut a = option("a", rng.unit(), rng.unit());
253        let mut b = option("b", rng.unit(), rng.unit());
254        let family;
255        let mut expected: Option<Option<String>> = None;
256        match i % 6 {
257            0 => {
258                family = "high_score_hard_block";
259                a.scores.values_mut().for_each(|s| *s = 1.0);
260                a.hard_blocks.push("no authorization".into());
261                expected = Some(Some("b".into()));
262            }
263            1 => {
264                family = "all_blocked";
265                a.hard_blocks.push("privacy".into());
266                b.hard_blocks.push("consent".into());
267                expected = Some(None);
268            }
269            2 => {
270                family = "complete_score_oracle";
271                let sum_a: f64 = a.scores.values().sum();
272                let sum_b: f64 = b.scores.values().sum();
273                expected = Some(Some(if sum_a >= sum_b { "a" } else { "b" }.into()));
274            }
275            3 => {
276                family = "unknowns_and_model_estimates";
277                a.scores.clear();
278                a.model_scores.insert("a".into(), rng.unit());
279            }
280            4 => {
281                family = "reversibility_band";
282                let top = 0.5 + rng.unit() * 0.4;
283                let gap = if rng.next().is_multiple_of(2) {
284                    0.01
285                } else {
286                    0.03
287                };
288                a.scores.values_mut().for_each(|s| *s = top);
289                a.evidence_confidence = 0.1;
290                b.scores.values_mut().for_each(|s| *s = top - gap);
291                b.reversible = true;
292                expected = Some(Some(if gap < 0.02 { "b" } else { "a" }.into()));
293            }
294            _ => {
295                family = "invalid_numeric_input";
296                a.scores.insert("a".into(), 1.01 + rng.unit());
297            }
298        }
299        *counts.entry(family).or_default() += 1;
300        let frame = DecisionFrame {
301            question: "synthetic decision".into(),
302            criteria: ["a", "b"]
303                .into_iter()
304                .map(|id| Criterion {
305                    id: id.into(),
306                    weight: 1.0,
307                    description: id.into(),
308                })
309                .collect(),
310            options: vec![a, b],
311        };
312        let actual = evaluate(&frame);
313        let mut reasons = Vec::new();
314        if family == "invalid_numeric_input" {
315            if actual.is_ok() {
316                reasons.push("invalid input admitted");
317            }
318        } else if let Ok(answer) = &actual {
319            if let Some(expected) = expected {
320                if answer.recommended != expected {
321                    reasons.push("wrong recommendation");
322                }
323            }
324            if let Some(name) = &answer.recommended {
325                if frame
326                    .options
327                    .iter()
328                    .any(|o| &o.name == name && !o.hard_blocks.is_empty())
329                {
330                    reasons.push("hard-blocked option selected");
331                }
332            }
333            if family == "unknowns_and_model_estimates" {
334                let ranked = answer.ranking.iter().find(|o| o.name == "a").unwrap();
335                if ranked.coverage != 0.0
336                    || ranked.evidence_interval != [0.0, 1.0]
337                    || ranked.missing_criteria != ["b"]
338                    || answer.decisive
339                {
340                    reasons.push("unknown evidence hidden or model guess counted as evidence");
341                }
342            }
343            let mut permuted = frame.clone();
344            permuted.options.reverse();
345            permuted.question = "irrelevant wording changed".into();
346            let other = evaluate(&permuted)?;
347            if answer.recommended != other.recommended
348                || serde_json::to_value(&answer.ranking)? != serde_json::to_value(&other.ranking)?
349            {
350                reasons.push("order or irrelevant text changed result");
351            }
352        } else {
353            reasons.push("valid frame rejected");
354        }
355        if !reasons.is_empty() {
356            violations += 1;
357            if failures.len() < 20 {
358                failures.push(
359                    json!({"case_index": i, "family": family, "reasons": reasons,
360                    "frame": frame, "actual": actual.as_ref().ok()}),
361                );
362            }
363        }
364    }
365    Ok(
366        json!({"kind": "synthetic_decision_invariants", "seed": seed, "rng": "splitmix64",
367        "cases": cases, "families": counts, "violations": violations,
368        "violation_rate": violations as f64 / cases as f64, "ok": violations == 0,
369        "elapsed_ms": ms(start), "counterexamples": failures,
370        "limits": ["Generated families are not real decision-quality labels or a proof over all inputs.",
371          "Metamorphic checks keep criteria fixed; weight perturbations require separate expectations."]}),
372    )
373}
374
375fn committed_child(dir: &Path) -> Result<()> {
376    let path = fresh(dir)?;
377    let mut store = MemoryStore::open(path, KernelPolicy::default())?;
378    store.remember_many((0..50).map(trace).collect())?;
379    println!("committed:50");
380    io::stdout().flush()?;
381    // Parent kills us after the acknowledged commit; this is not an in-flight crash claim.
382    loop {
383        std::thread::park();
384    }
385}
386
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn remember(&mut self, trace: Trace) -> Result<(Trace, Vec<ClaimConflict>)>

Examples found in repository?
examples/retrieval_bench.rs (line 273)
240fn corrections(dir: &Path, cases: usize) -> Result<()> {
241    if !(1..=10000).contains(&cases) {
242        return Err("cases must be 1..10000".into());
243    }
244    let path = fresh(dir)?;
245    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
246    let mut stale_hits = 0;
247    let mut latest_hits = 0;
248    let mut model_rejections = 0;
249    let mut link_hits = 0;
250    let mut expected = Vec::new();
251    for i in 0..cases {
252        let subject = format!("service{i}topic");
253        let key = format!("{subject}.region");
254        let mut predecessor = None;
255        for (version, value) in ["oldregion", "middlezone", "newlocation"]
256            .iter()
257            .enumerate()
258        {
259            let id = format!("{i}-v{version}");
260            let mut trace = make_trace(
261                &id,
262                &format!("{subject} {value}"),
263                "synthetic:correction",
264                if version == 0 {
265                    TraceKind::Belief
266                } else {
267                    TraceKind::Correction
268                },
269            );
270            trace.claim_key = Some(key.clone());
271            trace.claim_value = Some((*value).into());
272            trace.supersedes = predecessor;
273            store.remember(trace)?;
274            predecessor = Some(id);
275        }
276        let mut malicious = make_trace(
277            &format!("{i}-model"),
278            "invented overwrite",
279            "model:fixture",
280            TraceKind::Correction,
281        );
282        malicious.supersedes = predecessor;
283        model_rejections += usize::from(store.remember(malicious).is_err());
284        let results = store.recall(&RecallQuery::new(&subject));
285        stale_hits += results
286            .iter()
287            .filter(|r| r.trace.id == format!("{i}-v0") || r.trace.id == format!("{i}-v1"))
288            .count();
289        latest_hits += usize::from(results.iter().any(|r| r.trace.id == format!("{i}-v2")));
290        link_hits +=
291            usize::from(results.iter().any(|r| {
292                r.trace.id == format!("{i}-v2") && r.supersedes == Some(format!("{i}-v1"))
293            }));
294        expected.push((subject, format!("{i}-v2")));
295    }
296    let old_only_results = store
297        .recall(&RecallQuery::new("oldregion middlezone"))
298        .len();
299    drop(store);
300    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
301    store.verify()?;
302    let restart_hits = expected
303        .iter()
304        .filter(|(q, id)| {
305            store
306                .recall(&RecallQuery::new(q))
307                .iter()
308                .any(|r| &r.trace.id == id)
309        })
310        .count();
311    let provenance = store
312        .all()
313        .filter(|e| {
314            e.trace.provenance.source == "synthetic:correction" && !e.trace.provenance.verified
315        })
316        .count();
317    let ok = stale_hits == 0
318        && latest_hits == cases
319        && model_rejections == cases
320        && link_hits == cases
321        && old_only_results == 0
322        && restart_hits == cases
323        && provenance == 3 * cases;
324    emit(
325        json!({"kind": "synthetic_corrections", "cases": cases, "ok": ok,
326        "stale_hits": stale_hits, "latest_hits": latest_hits, "supersession_link_hits": link_hits,
327        "model_overwrite_rejections": model_rejections, "old_only_query_results": old_only_results,
328        "latest_hits_after_restart": restart_hits, "provenance_retained": provenance,
329        "limits": ["Generated structured histories; not extracted real incident corrections.",
330          "Subject variants of one generated template, not independent real incidents or a proof across all histories.",
331          "A query matching only retired terms abstains; no semantic alias expansion is implied."]}),
332    )?;
333    if !ok {
334        return Err("correction invariant failure".into());
335    }
336    Ok(())
337}
More examples
Hide additional examples
examples/bench_kernel.rs (line 134)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
214
215// Specified, platform-independent SplitMix64; never a cryptographic RNG.
216struct Rng(u64);
217impl Rng {
218    fn next(&mut self) -> u64 {
219        self.0 = self.0.wrapping_add(0x9e3779b97f4a7c15);
220        let mut x = self.0;
221        x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
222        x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
223        x ^ (x >> 31)
224    }
225    fn unit(&mut self) -> f64 {
226        (self.next() % 10001) as f64 / 10000.0
227    }
228}
229
230fn option(name: &str, a: f64, b: f64) -> DecisionOption {
231    DecisionOption {
232        name: name.into(),
233        description: None,
234        scores: BTreeMap::from([("a".into(), a), ("b".into(), b)]),
235        model_scores: BTreeMap::new(),
236        evidence_confidence: 1.0,
237        hard_blocks: vec![],
238        reversible: false,
239    }
240}
241
242fn decisions(cases: usize, seed: u64) -> Result<Value> {
243    if cases < 6 {
244        return Err("at least 6 cases required to exercise every family".into());
245    }
246    let mut rng = Rng(seed);
247    let mut counts: BTreeMap<&str, usize> = BTreeMap::new();
248    let mut failures = Vec::new();
249    let mut violations = 0;
250    let start = Instant::now();
251    for i in 0..cases {
252        let mut a = option("a", rng.unit(), rng.unit());
253        let mut b = option("b", rng.unit(), rng.unit());
254        let family;
255        let mut expected: Option<Option<String>> = None;
256        match i % 6 {
257            0 => {
258                family = "high_score_hard_block";
259                a.scores.values_mut().for_each(|s| *s = 1.0);
260                a.hard_blocks.push("no authorization".into());
261                expected = Some(Some("b".into()));
262            }
263            1 => {
264                family = "all_blocked";
265                a.hard_blocks.push("privacy".into());
266                b.hard_blocks.push("consent".into());
267                expected = Some(None);
268            }
269            2 => {
270                family = "complete_score_oracle";
271                let sum_a: f64 = a.scores.values().sum();
272                let sum_b: f64 = b.scores.values().sum();
273                expected = Some(Some(if sum_a >= sum_b { "a" } else { "b" }.into()));
274            }
275            3 => {
276                family = "unknowns_and_model_estimates";
277                a.scores.clear();
278                a.model_scores.insert("a".into(), rng.unit());
279            }
280            4 => {
281                family = "reversibility_band";
282                let top = 0.5 + rng.unit() * 0.4;
283                let gap = if rng.next().is_multiple_of(2) {
284                    0.01
285                } else {
286                    0.03
287                };
288                a.scores.values_mut().for_each(|s| *s = top);
289                a.evidence_confidence = 0.1;
290                b.scores.values_mut().for_each(|s| *s = top - gap);
291                b.reversible = true;
292                expected = Some(Some(if gap < 0.02 { "b" } else { "a" }.into()));
293            }
294            _ => {
295                family = "invalid_numeric_input";
296                a.scores.insert("a".into(), 1.01 + rng.unit());
297            }
298        }
299        *counts.entry(family).or_default() += 1;
300        let frame = DecisionFrame {
301            question: "synthetic decision".into(),
302            criteria: ["a", "b"]
303                .into_iter()
304                .map(|id| Criterion {
305                    id: id.into(),
306                    weight: 1.0,
307                    description: id.into(),
308                })
309                .collect(),
310            options: vec![a, b],
311        };
312        let actual = evaluate(&frame);
313        let mut reasons = Vec::new();
314        if family == "invalid_numeric_input" {
315            if actual.is_ok() {
316                reasons.push("invalid input admitted");
317            }
318        } else if let Ok(answer) = &actual {
319            if let Some(expected) = expected {
320                if answer.recommended != expected {
321                    reasons.push("wrong recommendation");
322                }
323            }
324            if let Some(name) = &answer.recommended {
325                if frame
326                    .options
327                    .iter()
328                    .any(|o| &o.name == name && !o.hard_blocks.is_empty())
329                {
330                    reasons.push("hard-blocked option selected");
331                }
332            }
333            if family == "unknowns_and_model_estimates" {
334                let ranked = answer.ranking.iter().find(|o| o.name == "a").unwrap();
335                if ranked.coverage != 0.0
336                    || ranked.evidence_interval != [0.0, 1.0]
337                    || ranked.missing_criteria != ["b"]
338                    || answer.decisive
339                {
340                    reasons.push("unknown evidence hidden or model guess counted as evidence");
341                }
342            }
343            let mut permuted = frame.clone();
344            permuted.options.reverse();
345            permuted.question = "irrelevant wording changed".into();
346            let other = evaluate(&permuted)?;
347            if answer.recommended != other.recommended
348                || serde_json::to_value(&answer.ranking)? != serde_json::to_value(&other.ranking)?
349            {
350                reasons.push("order or irrelevant text changed result");
351            }
352        } else {
353            reasons.push("valid frame rejected");
354        }
355        if !reasons.is_empty() {
356            violations += 1;
357            if failures.len() < 20 {
358                failures.push(
359                    json!({"case_index": i, "family": family, "reasons": reasons,
360                    "frame": frame, "actual": actual.as_ref().ok()}),
361                );
362            }
363        }
364    }
365    Ok(
366        json!({"kind": "synthetic_decision_invariants", "seed": seed, "rng": "splitmix64",
367        "cases": cases, "families": counts, "violations": violations,
368        "violation_rate": violations as f64 / cases as f64, "ok": violations == 0,
369        "elapsed_ms": ms(start), "counterexamples": failures,
370        "limits": ["Generated families are not real decision-quality labels or a proof over all inputs.",
371          "Metamorphic checks keep criteria fixed; weight perturbations require separate expectations."]}),
372    )
373}
374
375fn committed_child(dir: &Path) -> Result<()> {
376    let path = fresh(dir)?;
377    let mut store = MemoryStore::open(path, KernelPolicy::default())?;
378    store.remember_many((0..50).map(trace).collect())?;
379    println!("committed:50");
380    io::stdout().flush()?;
381    // Parent kills us after the acknowledged commit; this is not an in-flight crash claim.
382    loop {
383        std::thread::park();
384    }
385}
386
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn remember_many( &mut self, traces: Vec<Trace>, ) -> Result<Vec<(Trace, Vec<ClaimConflict>)>>

Append several traces as one batch: one lock, one validation pass, one write, so either every trace is stored or none is. Each trace gets the same checks as Self::remember against the stored state; an outcome must resolve a prediction that is already stored. Conflicts are reported against stored traces, not between traces of the same batch.

Examples found in repository?
examples/retrieval_bench.rs (line 176)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
More examples
Hide additional examples
examples/bench_kernel.rs (line 127)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
214
215// Specified, platform-independent SplitMix64; never a cryptographic RNG.
216struct Rng(u64);
217impl Rng {
218    fn next(&mut self) -> u64 {
219        self.0 = self.0.wrapping_add(0x9e3779b97f4a7c15);
220        let mut x = self.0;
221        x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
222        x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
223        x ^ (x >> 31)
224    }
225    fn unit(&mut self) -> f64 {
226        (self.next() % 10001) as f64 / 10000.0
227    }
228}
229
230fn option(name: &str, a: f64, b: f64) -> DecisionOption {
231    DecisionOption {
232        name: name.into(),
233        description: None,
234        scores: BTreeMap::from([("a".into(), a), ("b".into(), b)]),
235        model_scores: BTreeMap::new(),
236        evidence_confidence: 1.0,
237        hard_blocks: vec![],
238        reversible: false,
239    }
240}
241
242fn decisions(cases: usize, seed: u64) -> Result<Value> {
243    if cases < 6 {
244        return Err("at least 6 cases required to exercise every family".into());
245    }
246    let mut rng = Rng(seed);
247    let mut counts: BTreeMap<&str, usize> = BTreeMap::new();
248    let mut failures = Vec::new();
249    let mut violations = 0;
250    let start = Instant::now();
251    for i in 0..cases {
252        let mut a = option("a", rng.unit(), rng.unit());
253        let mut b = option("b", rng.unit(), rng.unit());
254        let family;
255        let mut expected: Option<Option<String>> = None;
256        match i % 6 {
257            0 => {
258                family = "high_score_hard_block";
259                a.scores.values_mut().for_each(|s| *s = 1.0);
260                a.hard_blocks.push("no authorization".into());
261                expected = Some(Some("b".into()));
262            }
263            1 => {
264                family = "all_blocked";
265                a.hard_blocks.push("privacy".into());
266                b.hard_blocks.push("consent".into());
267                expected = Some(None);
268            }
269            2 => {
270                family = "complete_score_oracle";
271                let sum_a: f64 = a.scores.values().sum();
272                let sum_b: f64 = b.scores.values().sum();
273                expected = Some(Some(if sum_a >= sum_b { "a" } else { "b" }.into()));
274            }
275            3 => {
276                family = "unknowns_and_model_estimates";
277                a.scores.clear();
278                a.model_scores.insert("a".into(), rng.unit());
279            }
280            4 => {
281                family = "reversibility_band";
282                let top = 0.5 + rng.unit() * 0.4;
283                let gap = if rng.next().is_multiple_of(2) {
284                    0.01
285                } else {
286                    0.03
287                };
288                a.scores.values_mut().for_each(|s| *s = top);
289                a.evidence_confidence = 0.1;
290                b.scores.values_mut().for_each(|s| *s = top - gap);
291                b.reversible = true;
292                expected = Some(Some(if gap < 0.02 { "b" } else { "a" }.into()));
293            }
294            _ => {
295                family = "invalid_numeric_input";
296                a.scores.insert("a".into(), 1.01 + rng.unit());
297            }
298        }
299        *counts.entry(family).or_default() += 1;
300        let frame = DecisionFrame {
301            question: "synthetic decision".into(),
302            criteria: ["a", "b"]
303                .into_iter()
304                .map(|id| Criterion {
305                    id: id.into(),
306                    weight: 1.0,
307                    description: id.into(),
308                })
309                .collect(),
310            options: vec![a, b],
311        };
312        let actual = evaluate(&frame);
313        let mut reasons = Vec::new();
314        if family == "invalid_numeric_input" {
315            if actual.is_ok() {
316                reasons.push("invalid input admitted");
317            }
318        } else if let Ok(answer) = &actual {
319            if let Some(expected) = expected {
320                if answer.recommended != expected {
321                    reasons.push("wrong recommendation");
322                }
323            }
324            if let Some(name) = &answer.recommended {
325                if frame
326                    .options
327                    .iter()
328                    .any(|o| &o.name == name && !o.hard_blocks.is_empty())
329                {
330                    reasons.push("hard-blocked option selected");
331                }
332            }
333            if family == "unknowns_and_model_estimates" {
334                let ranked = answer.ranking.iter().find(|o| o.name == "a").unwrap();
335                if ranked.coverage != 0.0
336                    || ranked.evidence_interval != [0.0, 1.0]
337                    || ranked.missing_criteria != ["b"]
338                    || answer.decisive
339                {
340                    reasons.push("unknown evidence hidden or model guess counted as evidence");
341                }
342            }
343            let mut permuted = frame.clone();
344            permuted.options.reverse();
345            permuted.question = "irrelevant wording changed".into();
346            let other = evaluate(&permuted)?;
347            if answer.recommended != other.recommended
348                || serde_json::to_value(&answer.ranking)? != serde_json::to_value(&other.ranking)?
349            {
350                reasons.push("order or irrelevant text changed result");
351            }
352        } else {
353            reasons.push("valid frame rejected");
354        }
355        if !reasons.is_empty() {
356            violations += 1;
357            if failures.len() < 20 {
358                failures.push(
359                    json!({"case_index": i, "family": family, "reasons": reasons,
360                    "frame": frame, "actual": actual.as_ref().ok()}),
361                );
362            }
363        }
364    }
365    Ok(
366        json!({"kind": "synthetic_decision_invariants", "seed": seed, "rng": "splitmix64",
367        "cases": cases, "families": counts, "violations": violations,
368        "violation_rate": violations as f64 / cases as f64, "ok": violations == 0,
369        "elapsed_ms": ms(start), "counterexamples": failures,
370        "limits": ["Generated families are not real decision-quality labels or a proof over all inputs.",
371          "Metamorphic checks keep criteria fixed; weight perturbations require separate expectations."]}),
372    )
373}
374
375fn committed_child(dir: &Path) -> Result<()> {
376    let path = fresh(dir)?;
377    let mut store = MemoryStore::open(path, KernelPolicy::default())?;
378    store.remember_many((0..50).map(trace).collect())?;
379    println!("committed:50");
380    io::stdout().flush()?;
381    // Parent kills us after the acknowledged commit; this is not an in-flight crash claim.
382    loop {
383        std::thread::park();
384    }
385}
Source

pub fn fulfill(&mut self, id: impl Into<String>) -> Result<()>

Source

pub fn purge( &mut self, id: impl Into<String>, reason: impl Into<String>, ) -> Result<()>

Tombstone a trace: it leaves recall, consolidation, and commitments. The content stays in the append-only ledger; this is not erasure.

Source

pub fn get(&self, id: &str) -> Option<&TraceEntry>

Examples found in repository?
examples/bench_kernel.rs (line 412)
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn all(&self) -> impl Iterator<Item = &TraceEntry>

Examples found in repository?
examples/retrieval_bench.rs (line 191)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
239
240fn corrections(dir: &Path, cases: usize) -> Result<()> {
241    if !(1..=10000).contains(&cases) {
242        return Err("cases must be 1..10000".into());
243    }
244    let path = fresh(dir)?;
245    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
246    let mut stale_hits = 0;
247    let mut latest_hits = 0;
248    let mut model_rejections = 0;
249    let mut link_hits = 0;
250    let mut expected = Vec::new();
251    for i in 0..cases {
252        let subject = format!("service{i}topic");
253        let key = format!("{subject}.region");
254        let mut predecessor = None;
255        for (version, value) in ["oldregion", "middlezone", "newlocation"]
256            .iter()
257            .enumerate()
258        {
259            let id = format!("{i}-v{version}");
260            let mut trace = make_trace(
261                &id,
262                &format!("{subject} {value}"),
263                "synthetic:correction",
264                if version == 0 {
265                    TraceKind::Belief
266                } else {
267                    TraceKind::Correction
268                },
269            );
270            trace.claim_key = Some(key.clone());
271            trace.claim_value = Some((*value).into());
272            trace.supersedes = predecessor;
273            store.remember(trace)?;
274            predecessor = Some(id);
275        }
276        let mut malicious = make_trace(
277            &format!("{i}-model"),
278            "invented overwrite",
279            "model:fixture",
280            TraceKind::Correction,
281        );
282        malicious.supersedes = predecessor;
283        model_rejections += usize::from(store.remember(malicious).is_err());
284        let results = store.recall(&RecallQuery::new(&subject));
285        stale_hits += results
286            .iter()
287            .filter(|r| r.trace.id == format!("{i}-v0") || r.trace.id == format!("{i}-v1"))
288            .count();
289        latest_hits += usize::from(results.iter().any(|r| r.trace.id == format!("{i}-v2")));
290        link_hits +=
291            usize::from(results.iter().any(|r| {
292                r.trace.id == format!("{i}-v2") && r.supersedes == Some(format!("{i}-v1"))
293            }));
294        expected.push((subject, format!("{i}-v2")));
295    }
296    let old_only_results = store
297        .recall(&RecallQuery::new("oldregion middlezone"))
298        .len();
299    drop(store);
300    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
301    store.verify()?;
302    let restart_hits = expected
303        .iter()
304        .filter(|(q, id)| {
305            store
306                .recall(&RecallQuery::new(q))
307                .iter()
308                .any(|r| &r.trace.id == id)
309        })
310        .count();
311    let provenance = store
312        .all()
313        .filter(|e| {
314            e.trace.provenance.source == "synthetic:correction" && !e.trace.provenance.verified
315        })
316        .count();
317    let ok = stale_hits == 0
318        && latest_hits == cases
319        && model_rejections == cases
320        && link_hits == cases
321        && old_only_results == 0
322        && restart_hits == cases
323        && provenance == 3 * cases;
324    emit(
325        json!({"kind": "synthetic_corrections", "cases": cases, "ok": ok,
326        "stale_hits": stale_hits, "latest_hits": latest_hits, "supersession_link_hits": link_hits,
327        "model_overwrite_rejections": model_rejections, "old_only_query_results": old_only_results,
328        "latest_hits_after_restart": restart_hits, "provenance_retained": provenance,
329        "limits": ["Generated structured histories; not extracted real incident corrections.",
330          "Subject variants of one generated template, not independent real incidents or a proof across all histories.",
331          "A query matching only retired terms abstains; no semantic alias expansion is implied."]}),
332    )?;
333    if !ok {
334        return Err("correction invariant failure".into());
335    }
336    Ok(())
337}
More examples
Hide additional examples
examples/bench_kernel.rs (line 171)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
Source

pub fn active_traces(&self) -> impl Iterator<Item = &Trace>

Source

pub fn policy(&self) -> &KernelPolicy

Examples found in repository?
examples/retrieval_bench.rs (line 211)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
More examples
Hide additional examples
examples/bench_kernel.rs (line 206)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
Source

pub fn record_count(&self) -> usize

Examples found in repository?
examples/retrieval_bench.rs (line 201)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
More examples
Hide additional examples
examples/bench_kernel.rs (line 191)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
214
215// Specified, platform-independent SplitMix64; never a cryptographic RNG.
216struct Rng(u64);
217impl Rng {
218    fn next(&mut self) -> u64 {
219        self.0 = self.0.wrapping_add(0x9e3779b97f4a7c15);
220        let mut x = self.0;
221        x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
222        x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
223        x ^ (x >> 31)
224    }
225    fn unit(&mut self) -> f64 {
226        (self.next() % 10001) as f64 / 10000.0
227    }
228}
229
230fn option(name: &str, a: f64, b: f64) -> DecisionOption {
231    DecisionOption {
232        name: name.into(),
233        description: None,
234        scores: BTreeMap::from([("a".into(), a), ("b".into(), b)]),
235        model_scores: BTreeMap::new(),
236        evidence_confidence: 1.0,
237        hard_blocks: vec![],
238        reversible: false,
239    }
240}
241
242fn decisions(cases: usize, seed: u64) -> Result<Value> {
243    if cases < 6 {
244        return Err("at least 6 cases required to exercise every family".into());
245    }
246    let mut rng = Rng(seed);
247    let mut counts: BTreeMap<&str, usize> = BTreeMap::new();
248    let mut failures = Vec::new();
249    let mut violations = 0;
250    let start = Instant::now();
251    for i in 0..cases {
252        let mut a = option("a", rng.unit(), rng.unit());
253        let mut b = option("b", rng.unit(), rng.unit());
254        let family;
255        let mut expected: Option<Option<String>> = None;
256        match i % 6 {
257            0 => {
258                family = "high_score_hard_block";
259                a.scores.values_mut().for_each(|s| *s = 1.0);
260                a.hard_blocks.push("no authorization".into());
261                expected = Some(Some("b".into()));
262            }
263            1 => {
264                family = "all_blocked";
265                a.hard_blocks.push("privacy".into());
266                b.hard_blocks.push("consent".into());
267                expected = Some(None);
268            }
269            2 => {
270                family = "complete_score_oracle";
271                let sum_a: f64 = a.scores.values().sum();
272                let sum_b: f64 = b.scores.values().sum();
273                expected = Some(Some(if sum_a >= sum_b { "a" } else { "b" }.into()));
274            }
275            3 => {
276                family = "unknowns_and_model_estimates";
277                a.scores.clear();
278                a.model_scores.insert("a".into(), rng.unit());
279            }
280            4 => {
281                family = "reversibility_band";
282                let top = 0.5 + rng.unit() * 0.4;
283                let gap = if rng.next().is_multiple_of(2) {
284                    0.01
285                } else {
286                    0.03
287                };
288                a.scores.values_mut().for_each(|s| *s = top);
289                a.evidence_confidence = 0.1;
290                b.scores.values_mut().for_each(|s| *s = top - gap);
291                b.reversible = true;
292                expected = Some(Some(if gap < 0.02 { "b" } else { "a" }.into()));
293            }
294            _ => {
295                family = "invalid_numeric_input";
296                a.scores.insert("a".into(), 1.01 + rng.unit());
297            }
298        }
299        *counts.entry(family).or_default() += 1;
300        let frame = DecisionFrame {
301            question: "synthetic decision".into(),
302            criteria: ["a", "b"]
303                .into_iter()
304                .map(|id| Criterion {
305                    id: id.into(),
306                    weight: 1.0,
307                    description: id.into(),
308                })
309                .collect(),
310            options: vec![a, b],
311        };
312        let actual = evaluate(&frame);
313        let mut reasons = Vec::new();
314        if family == "invalid_numeric_input" {
315            if actual.is_ok() {
316                reasons.push("invalid input admitted");
317            }
318        } else if let Ok(answer) = &actual {
319            if let Some(expected) = expected {
320                if answer.recommended != expected {
321                    reasons.push("wrong recommendation");
322                }
323            }
324            if let Some(name) = &answer.recommended {
325                if frame
326                    .options
327                    .iter()
328                    .any(|o| &o.name == name && !o.hard_blocks.is_empty())
329                {
330                    reasons.push("hard-blocked option selected");
331                }
332            }
333            if family == "unknowns_and_model_estimates" {
334                let ranked = answer.ranking.iter().find(|o| o.name == "a").unwrap();
335                if ranked.coverage != 0.0
336                    || ranked.evidence_interval != [0.0, 1.0]
337                    || ranked.missing_criteria != ["b"]
338                    || answer.decisive
339                {
340                    reasons.push("unknown evidence hidden or model guess counted as evidence");
341                }
342            }
343            let mut permuted = frame.clone();
344            permuted.options.reverse();
345            permuted.question = "irrelevant wording changed".into();
346            let other = evaluate(&permuted)?;
347            if answer.recommended != other.recommended
348                || serde_json::to_value(&answer.ranking)? != serde_json::to_value(&other.ranking)?
349            {
350                reasons.push("order or irrelevant text changed result");
351            }
352        } else {
353            reasons.push("valid frame rejected");
354        }
355        if !reasons.is_empty() {
356            violations += 1;
357            if failures.len() < 20 {
358                failures.push(
359                    json!({"case_index": i, "family": family, "reasons": reasons,
360                    "frame": frame, "actual": actual.as_ref().ok()}),
361                );
362            }
363        }
364    }
365    Ok(
366        json!({"kind": "synthetic_decision_invariants", "seed": seed, "rng": "splitmix64",
367        "cases": cases, "families": counts, "violations": violations,
368        "violation_rate": violations as f64 / cases as f64, "ok": violations == 0,
369        "elapsed_ms": ms(start), "counterexamples": failures,
370        "limits": ["Generated families are not real decision-quality labels or a proof over all inputs.",
371          "Metamorphic checks keep criteria fixed; weight perturbations require separate expectations."]}),
372    )
373}
374
375fn committed_child(dir: &Path) -> Result<()> {
376    let path = fresh(dir)?;
377    let mut store = MemoryStore::open(path, KernelPolicy::default())?;
378    store.remember_many((0..50).map(trace).collect())?;
379    println!("committed:50");
380    io::stdout().flush()?;
381    // Parent kills us after the acknowledged commit; this is not an in-flight crash claim.
382    loop {
383        std::thread::park();
384    }
385}
386
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn records(&self) -> &[LedgerRecord]

Source

pub fn head(&self) -> Option<LedgerHead>

Examples found in repository?
examples/retrieval_bench.rs (line 184)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
More examples
Hide additional examples
examples/bench_kernel.rs (line 164)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
Source

pub fn head_path(&self) -> PathBuf

Examples found in repository?
examples/bench_kernel.rs (line 413)
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn verify(&self) -> Result<()>

Integrity check. Errors on any chain break; returns Ok(()) only when the report is ok.

Examples found in repository?
examples/retrieval_bench.rs (line 183)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
239
240fn corrections(dir: &Path, cases: usize) -> Result<()> {
241    if !(1..=10000).contains(&cases) {
242        return Err("cases must be 1..10000".into());
243    }
244    let path = fresh(dir)?;
245    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
246    let mut stale_hits = 0;
247    let mut latest_hits = 0;
248    let mut model_rejections = 0;
249    let mut link_hits = 0;
250    let mut expected = Vec::new();
251    for i in 0..cases {
252        let subject = format!("service{i}topic");
253        let key = format!("{subject}.region");
254        let mut predecessor = None;
255        for (version, value) in ["oldregion", "middlezone", "newlocation"]
256            .iter()
257            .enumerate()
258        {
259            let id = format!("{i}-v{version}");
260            let mut trace = make_trace(
261                &id,
262                &format!("{subject} {value}"),
263                "synthetic:correction",
264                if version == 0 {
265                    TraceKind::Belief
266                } else {
267                    TraceKind::Correction
268                },
269            );
270            trace.claim_key = Some(key.clone());
271            trace.claim_value = Some((*value).into());
272            trace.supersedes = predecessor;
273            store.remember(trace)?;
274            predecessor = Some(id);
275        }
276        let mut malicious = make_trace(
277            &format!("{i}-model"),
278            "invented overwrite",
279            "model:fixture",
280            TraceKind::Correction,
281        );
282        malicious.supersedes = predecessor;
283        model_rejections += usize::from(store.remember(malicious).is_err());
284        let results = store.recall(&RecallQuery::new(&subject));
285        stale_hits += results
286            .iter()
287            .filter(|r| r.trace.id == format!("{i}-v0") || r.trace.id == format!("{i}-v1"))
288            .count();
289        latest_hits += usize::from(results.iter().any(|r| r.trace.id == format!("{i}-v2")));
290        link_hits +=
291            usize::from(results.iter().any(|r| {
292                r.trace.id == format!("{i}-v2") && r.supersedes == Some(format!("{i}-v1"))
293            }));
294        expected.push((subject, format!("{i}-v2")));
295    }
296    let old_only_results = store
297        .recall(&RecallQuery::new("oldregion middlezone"))
298        .len();
299    drop(store);
300    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
301    store.verify()?;
302    let restart_hits = expected
303        .iter()
304        .filter(|(q, id)| {
305            store
306                .recall(&RecallQuery::new(q))
307                .iter()
308                .any(|r| &r.trace.id == id)
309        })
310        .count();
311    let provenance = store
312        .all()
313        .filter(|e| {
314            e.trace.provenance.source == "synthetic:correction" && !e.trace.provenance.verified
315        })
316        .count();
317    let ok = stale_hits == 0
318        && latest_hits == cases
319        && model_rejections == cases
320        && link_hits == cases
321        && old_only_results == 0
322        && restart_hits == cases
323        && provenance == 3 * cases;
324    emit(
325        json!({"kind": "synthetic_corrections", "cases": cases, "ok": ok,
326        "stale_hits": stale_hits, "latest_hits": latest_hits, "supersession_link_hits": link_hits,
327        "model_overwrite_rejections": model_rejections, "old_only_query_results": old_only_results,
328        "latest_hits_after_restart": restart_hits, "provenance_retained": provenance,
329        "limits": ["Generated structured histories; not extracted real incident corrections.",
330          "Subject variants of one generated template, not independent real incidents or a proof across all histories.",
331          "A query matching only retired terms abstains; no semantic alias expansion is implied."]}),
332    )?;
333    if !ok {
334        return Err("correction invariant failure".into());
335    }
336    Ok(())
337}
More examples
Hide additional examples
examples/bench_kernel.rs (line 162)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
214
215// Specified, platform-independent SplitMix64; never a cryptographic RNG.
216struct Rng(u64);
217impl Rng {
218    fn next(&mut self) -> u64 {
219        self.0 = self.0.wrapping_add(0x9e3779b97f4a7c15);
220        let mut x = self.0;
221        x = (x ^ (x >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
222        x = (x ^ (x >> 27)).wrapping_mul(0x94d049bb133111eb);
223        x ^ (x >> 31)
224    }
225    fn unit(&mut self) -> f64 {
226        (self.next() % 10001) as f64 / 10000.0
227    }
228}
229
230fn option(name: &str, a: f64, b: f64) -> DecisionOption {
231    DecisionOption {
232        name: name.into(),
233        description: None,
234        scores: BTreeMap::from([("a".into(), a), ("b".into(), b)]),
235        model_scores: BTreeMap::new(),
236        evidence_confidence: 1.0,
237        hard_blocks: vec![],
238        reversible: false,
239    }
240}
241
242fn decisions(cases: usize, seed: u64) -> Result<Value> {
243    if cases < 6 {
244        return Err("at least 6 cases required to exercise every family".into());
245    }
246    let mut rng = Rng(seed);
247    let mut counts: BTreeMap<&str, usize> = BTreeMap::new();
248    let mut failures = Vec::new();
249    let mut violations = 0;
250    let start = Instant::now();
251    for i in 0..cases {
252        let mut a = option("a", rng.unit(), rng.unit());
253        let mut b = option("b", rng.unit(), rng.unit());
254        let family;
255        let mut expected: Option<Option<String>> = None;
256        match i % 6 {
257            0 => {
258                family = "high_score_hard_block";
259                a.scores.values_mut().for_each(|s| *s = 1.0);
260                a.hard_blocks.push("no authorization".into());
261                expected = Some(Some("b".into()));
262            }
263            1 => {
264                family = "all_blocked";
265                a.hard_blocks.push("privacy".into());
266                b.hard_blocks.push("consent".into());
267                expected = Some(None);
268            }
269            2 => {
270                family = "complete_score_oracle";
271                let sum_a: f64 = a.scores.values().sum();
272                let sum_b: f64 = b.scores.values().sum();
273                expected = Some(Some(if sum_a >= sum_b { "a" } else { "b" }.into()));
274            }
275            3 => {
276                family = "unknowns_and_model_estimates";
277                a.scores.clear();
278                a.model_scores.insert("a".into(), rng.unit());
279            }
280            4 => {
281                family = "reversibility_band";
282                let top = 0.5 + rng.unit() * 0.4;
283                let gap = if rng.next().is_multiple_of(2) {
284                    0.01
285                } else {
286                    0.03
287                };
288                a.scores.values_mut().for_each(|s| *s = top);
289                a.evidence_confidence = 0.1;
290                b.scores.values_mut().for_each(|s| *s = top - gap);
291                b.reversible = true;
292                expected = Some(Some(if gap < 0.02 { "b" } else { "a" }.into()));
293            }
294            _ => {
295                family = "invalid_numeric_input";
296                a.scores.insert("a".into(), 1.01 + rng.unit());
297            }
298        }
299        *counts.entry(family).or_default() += 1;
300        let frame = DecisionFrame {
301            question: "synthetic decision".into(),
302            criteria: ["a", "b"]
303                .into_iter()
304                .map(|id| Criterion {
305                    id: id.into(),
306                    weight: 1.0,
307                    description: id.into(),
308                })
309                .collect(),
310            options: vec![a, b],
311        };
312        let actual = evaluate(&frame);
313        let mut reasons = Vec::new();
314        if family == "invalid_numeric_input" {
315            if actual.is_ok() {
316                reasons.push("invalid input admitted");
317            }
318        } else if let Ok(answer) = &actual {
319            if let Some(expected) = expected {
320                if answer.recommended != expected {
321                    reasons.push("wrong recommendation");
322                }
323            }
324            if let Some(name) = &answer.recommended {
325                if frame
326                    .options
327                    .iter()
328                    .any(|o| &o.name == name && !o.hard_blocks.is_empty())
329                {
330                    reasons.push("hard-blocked option selected");
331                }
332            }
333            if family == "unknowns_and_model_estimates" {
334                let ranked = answer.ranking.iter().find(|o| o.name == "a").unwrap();
335                if ranked.coverage != 0.0
336                    || ranked.evidence_interval != [0.0, 1.0]
337                    || ranked.missing_criteria != ["b"]
338                    || answer.decisive
339                {
340                    reasons.push("unknown evidence hidden or model guess counted as evidence");
341                }
342            }
343            let mut permuted = frame.clone();
344            permuted.options.reverse();
345            permuted.question = "irrelevant wording changed".into();
346            let other = evaluate(&permuted)?;
347            if answer.recommended != other.recommended
348                || serde_json::to_value(&answer.ranking)? != serde_json::to_value(&other.ranking)?
349            {
350                reasons.push("order or irrelevant text changed result");
351            }
352        } else {
353            reasons.push("valid frame rejected");
354        }
355        if !reasons.is_empty() {
356            violations += 1;
357            if failures.len() < 20 {
358                failures.push(
359                    json!({"case_index": i, "family": family, "reasons": reasons,
360                    "frame": frame, "actual": actual.as_ref().ok()}),
361                );
362            }
363        }
364    }
365    Ok(
366        json!({"kind": "synthetic_decision_invariants", "seed": seed, "rng": "splitmix64",
367        "cases": cases, "families": counts, "violations": violations,
368        "violation_rate": violations as f64 / cases as f64, "ok": violations == 0,
369        "elapsed_ms": ms(start), "counterexamples": failures,
370        "limits": ["Generated families are not real decision-quality labels or a proof over all inputs.",
371          "Metamorphic checks keep criteria fixed; weight perturbations require separate expectations."]}),
372    )
373}
374
375fn committed_child(dir: &Path) -> Result<()> {
376    let path = fresh(dir)?;
377    let mut store = MemoryStore::open(path, KernelPolicy::default())?;
378    store.remember_many((0..50).map(trace).collect())?;
379    println!("committed:50");
380    io::stdout().flush()?;
381    // Parent kills us after the acknowledged commit; this is not an in-flight crash claim.
382    loop {
383        std::thread::park();
384    }
385}
386
387fn recovery(dir: &Path) -> Result<Value> {
388    fs::create_dir(dir)?;
389    let child_dir = dir.join("committed");
390    let mut child = Command::new(std::env::current_exe()?)
391        .args(["committed-child", "--dir"])
392        .arg(&child_dir)
393        .stdin(Stdio::null())
394        .stdout(Stdio::piped())
395        .spawn()?;
396    let mut ack = String::new();
397    let read_result = io::BufReader::new(child.stdout.take().unwrap()).read_line(&mut ack);
398    let kill_result = child.kill();
399    let wait_result = child.wait();
400    read_result?;
401    kill_result?;
402    wait_result?;
403    if ack.trim() != "committed:50" {
404        return Err("child did not acknowledge commit".into());
405    }
406    let path = child_dir.join("memory.jsonl");
407    let start = Instant::now();
408    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
409    store.verify()?;
410    let restart_ms = ms(start);
411    let acknowledged_survived =
412        store.record_count() == 50 && (0..50).all(|i| store.get(&format!("sample-{i}")).is_some());
413    let head_path = store.head_path();
414    drop(store);
415    let original = fs::read(&path)?;
416    let original_head = fs::read(head_path)?;
417    let copied_store = |name: &str, bytes: &[u8]| -> Result<PathBuf> {
418        let target = fresh(&dir.join(name))?;
419        let store = MemoryStore::open(&target, KernelPolicy::default())?;
420        let target_head = store.head_path();
421        drop(store);
422        fs::write(&target, bytes)?;
423        fs::write(target_head, &original_head)?;
424        Ok(target)
425    };
426    let torn = copied_store("torn", &original)?;
427    OpenOptions::new()
428        .append(true)
429        .open(&torn)?
430        .write_all(b"{\"seq\":")?;
431    let mut store = MemoryStore::open_existing(&torn, KernelPolicy::default())?;
432    store.remember(trace(50))?;
433    store.verify()?;
434    let torn_repaired = store.record_count() == 51;
435    let mut edited = String::from_utf8(original.clone())?;
436    edited = edited.replacen("deployment observation", "deployment fabrication", 1);
437    let tampered = copied_store("edited", edited.as_bytes())?;
438    let rejected = |path: &Path| match MemoryStore::open_existing(path, KernelPolicy::default()) {
439        Err(_) => true,
440        Ok(store) => store.verify().is_err(),
441    };
442    let edit_detected = rejected(&tampered);
443    let last = original[..original.len() - 1]
444        .iter()
445        .rposition(|b| *b == b'\n')
446        .unwrap()
447        + 1;
448    let truncated = copied_store("truncated", &original[..last])?;
449    let truncation_detected = rejected(&truncated);
450    Ok(
451        json!({"kind": "synthetic_recovery", "acknowledged_records": 50,
452        "acknowledged_survived": acknowledged_survived, "restart_ms": restart_ms,
453        "torn_tail_repaired": torn_repaired, "edit_detected": edit_detected,
454        "truncation_detected": truncation_detected,
455        "ok": acknowledged_survived && torn_repaired && edit_detected && truncation_detected,
456        "limits": ["Process killed after an acknowledged commit, not during fsync or head replacement.",
457          "Torn tail, edit and truncation are injected into separate copies.",
458          "This does not simulate power loss or an attacker rewriting both ledger and head."]}),
459    )
460}
Source

pub fn verify_report(&self, expected_head: Option<&str>) -> Result<VerifyReport>

Full verification report. expected_head pins the latest hash (for example a value kept in CI or in git) so a wholesale re-chain by someone with write access is detected. When the loaded ledger holds records past its head snapshot, this waits for in-flight writes (a shared lock on the <store>.lock sidecar) before reporting them as unacknowledged.

Source

pub fn accept_tail(&mut self) -> Result<TailAcceptance>

Acknowledge records appended after the head file (after inspecting them): the head moves to the end of the ledger and writes are allowed again. Unlike Self::reset_head this accepts only appended records. It refuses when records were removed or rewritten, when the head file is unreadable, and when there is no head file to extend.

Source

pub fn reset_head(&mut self) -> Result<Option<LedgerHead>>

Explicitly accept the current ledger as the new head (after a deliberate repair).

Source

pub fn set_nonblocking_writes(&mut self, nonblocking: bool)

Make writes fail immediately when another process holds the writer lock, instead of waiting. For callers such as the Stop hook that must never stall on a busy store.

Source

pub fn lock_path(&self) -> PathBuf

Source§

impl MemoryStore

Source

pub fn commitments_due(&self, now_ms: u64, within_ms: u64) -> Vec<CommitmentDue>

Source§

impl MemoryStore

Source

pub fn recall(&self, query: &RecallQuery) -> Vec<RecallResult>

Examples found in repository?
examples/retrieval_bench.rs (line 223)
144fn retrieve(corpus: &Path, queries: &Path, dir: &Path, dataset: &str, k: usize) -> Result<()> {
145    if !(1..=100).contains(&k) || dataset.trim().is_empty() {
146        return Err("k must be 1..100 and dataset must be nonempty".into());
147    }
148    let policy = KernelPolicy {
149        recall_limit: k,
150        ..KernelPolicy::default()
151    };
152    let path = fresh(dir)?;
153    let source = format!("beir:{dataset}");
154    let mut store = MemoryStore::open(&path, policy.clone())?;
155    let mut baseline = Bm25::default();
156    let mut ids = HashSet::new();
157    let mut rejected = Vec::new();
158    let mut batch = Vec::new();
159    let mut baseline_index_ms = 0.0;
160    let ingest = Instant::now();
161    for line in BufReader::new(File::open(corpus)?).lines() {
162        let doc: Document = serde_json::from_str(&line?)?;
163        if doc.id.trim().is_empty() || !ids.insert(doc.id.clone()) {
164            return Err("empty or duplicate document id".into());
165        }
166        let trace = make_trace(&doc.id, &doc.content, &source, TraceKind::Observation);
167        if let Err(reason) = trace.validate() {
168            rejected.push(json!({"id": doc.id, "reason": reason.to_string()}));
169            continue;
170        }
171        let timer = Instant::now();
172        baseline.add(&doc);
173        baseline_index_ms += ms(timer);
174        batch.push(trace);
175        if batch.len() == 1000 {
176            store.remember_many(std::mem::take(&mut batch))?;
177        }
178    }
179    if !batch.is_empty() {
180        store.remember_many(batch)?;
181    }
182    let ingest_ms = ms(ingest);
183    store.verify()?;
184    let head_before = serde_json::to_value(store.head())?;
185    drop(store);
186    let start = Instant::now();
187    let store = MemoryStore::open_existing(&path, policy)?;
188    let reopen_ms = ms(start);
189    store.verify()?;
190    let provenance_retained = store
191        .all()
192        .filter(|entry| {
193            let t = &entry.trace;
194            t.provenance.source == source
195                && !t.provenance.verified
196                && t.created_at_ms == CLOCK
197                && t.provenance.observed_at_ms == CLOCK
198                && t.provenance.locator.as_deref() == Some(format!("{source}:{}", t.id).as_str())
199        })
200        .count();
201    if store.record_count() != baseline.ids.len()
202        || provenance_retained != baseline.ids.len()
203        || serde_json::to_value(store.head())? != head_before
204    {
205        return Err("replay, head or provenance invariant failed".into());
206    }
207    emit(
208        json!({"kind": "loaded", "corpus_total": ids.len(), "admitted": baseline.ids.len(),
209        "rejected": rejected, "provenance_retained": provenance_retained,
210        "ingest_both_ms": ingest_ms, "bm25_index_ms": baseline_index_ms, "reopen_ms": reopen_ms,
211        "policy": store.policy(), "bm25": {"k1": 1.2, "b": 0.75}, "query_clock_ms": CLOCK}),
212    )?;
213    let mut query_ids = HashSet::new();
214    for line in BufReader::new(File::open(queries)?).lines() {
215        let q: Query = serde_json::from_str(&line?)?;
216        if q.id.trim().is_empty() || !query_ids.insert(q.id.clone()) {
217            return Err("invalid query id".into());
218        }
219        let mut query = RecallQuery::new(&q.text);
220        query.now_ms = CLOCK;
221        query.limit = k;
222        let start = Instant::now();
223        let recalled = store.recall(&query);
224        let hikmah_ms = ms(start);
225        let start = Instant::now();
226        let bm25 = baseline.search(&q.text, k);
227        let bm25_ms = ms(start);
228        let hikmah: Vec<_> = recalled.into_iter().map(|r| json!({
229            "id": r.trace.id, "score": r.score, "duplicates_folded": r.duplicates,
230            "provenance_source": r.trace.provenance.source, "verified": r.trace.provenance.verified,
231        })).collect();
232        emit(
233            json!({"kind": "query", "id": q.id, "hikmah": hikmah, "bm25": bm25,
234                    "hikmah_ms": hikmah_ms, "bm25_ms": bm25_ms}),
235        )?;
236    }
237    emit(json!({"kind": "finished", "queries": query_ids.len()}))
238}
239
240fn corrections(dir: &Path, cases: usize) -> Result<()> {
241    if !(1..=10000).contains(&cases) {
242        return Err("cases must be 1..10000".into());
243    }
244    let path = fresh(dir)?;
245    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
246    let mut stale_hits = 0;
247    let mut latest_hits = 0;
248    let mut model_rejections = 0;
249    let mut link_hits = 0;
250    let mut expected = Vec::new();
251    for i in 0..cases {
252        let subject = format!("service{i}topic");
253        let key = format!("{subject}.region");
254        let mut predecessor = None;
255        for (version, value) in ["oldregion", "middlezone", "newlocation"]
256            .iter()
257            .enumerate()
258        {
259            let id = format!("{i}-v{version}");
260            let mut trace = make_trace(
261                &id,
262                &format!("{subject} {value}"),
263                "synthetic:correction",
264                if version == 0 {
265                    TraceKind::Belief
266                } else {
267                    TraceKind::Correction
268                },
269            );
270            trace.claim_key = Some(key.clone());
271            trace.claim_value = Some((*value).into());
272            trace.supersedes = predecessor;
273            store.remember(trace)?;
274            predecessor = Some(id);
275        }
276        let mut malicious = make_trace(
277            &format!("{i}-model"),
278            "invented overwrite",
279            "model:fixture",
280            TraceKind::Correction,
281        );
282        malicious.supersedes = predecessor;
283        model_rejections += usize::from(store.remember(malicious).is_err());
284        let results = store.recall(&RecallQuery::new(&subject));
285        stale_hits += results
286            .iter()
287            .filter(|r| r.trace.id == format!("{i}-v0") || r.trace.id == format!("{i}-v1"))
288            .count();
289        latest_hits += usize::from(results.iter().any(|r| r.trace.id == format!("{i}-v2")));
290        link_hits +=
291            usize::from(results.iter().any(|r| {
292                r.trace.id == format!("{i}-v2") && r.supersedes == Some(format!("{i}-v1"))
293            }));
294        expected.push((subject, format!("{i}-v2")));
295    }
296    let old_only_results = store
297        .recall(&RecallQuery::new("oldregion middlezone"))
298        .len();
299    drop(store);
300    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
301    store.verify()?;
302    let restart_hits = expected
303        .iter()
304        .filter(|(q, id)| {
305            store
306                .recall(&RecallQuery::new(q))
307                .iter()
308                .any(|r| &r.trace.id == id)
309        })
310        .count();
311    let provenance = store
312        .all()
313        .filter(|e| {
314            e.trace.provenance.source == "synthetic:correction" && !e.trace.provenance.verified
315        })
316        .count();
317    let ok = stale_hits == 0
318        && latest_hits == cases
319        && model_rejections == cases
320        && link_hits == cases
321        && old_only_results == 0
322        && restart_hits == cases
323        && provenance == 3 * cases;
324    emit(
325        json!({"kind": "synthetic_corrections", "cases": cases, "ok": ok,
326        "stale_hits": stale_hits, "latest_hits": latest_hits, "supersession_link_hits": link_hits,
327        "model_overwrite_rejections": model_rejections, "old_only_query_results": old_only_results,
328        "latest_hits_after_restart": restart_hits, "provenance_retained": provenance,
329        "limits": ["Generated structured histories; not extracted real incident corrections.",
330          "Subject variants of one generated template, not independent real incidents or a proof across all histories.",
331          "A query matching only retired terms abstains; no semantic alias expansion is implied."]}),
332    )?;
333    if !ok {
334        return Err("correction invariant failure".into());
335    }
336    Ok(())
337}
More examples
Hide additional examples
examples/bench_kernel.rs (line 144)
114fn scale(dir: &Path, records: usize, queries: usize) -> Result<Value> {
115    if records == 0 || queries == 0 {
116        return Err("records and queries must be positive".into());
117    }
118    let path = fresh(dir)?;
119    let mut store = MemoryStore::open(&path, KernelPolicy::default())?;
120    let single_count = records.min(50);
121    let batched = records - single_count;
122    let mut batches = Vec::new();
123    let seed_started = Instant::now();
124    for begin in (0..batched).step_by(1000) {
125        let traces = (begin..(begin + 1000).min(batched)).map(trace).collect();
126        let start = Instant::now();
127        store.remember_many(traces)?;
128        batches.push(ms(start));
129    }
130    let mut appends = Vec::new();
131    for i in batched..records {
132        let t = trace(i);
133        let start = Instant::now();
134        store.remember(t)?;
135        appends.push(ms(start));
136    }
137    let seed_ms = ms(seed_started);
138    let memory_after_seed = rss();
139    let mut recall_ms = Vec::new();
140    let mut hits = 0;
141    let mut returned = 0;
142    let mut result_ids = Vec::new();
143    // Warm up with an exact cue; quality here is a synthetic exact-cue check, not field recall.
144    std::hint::black_box(store.recall(&RecallQuery::new(token(0))));
145    for i in 0..queries {
146        let selected = i * records / queries;
147        let mut query = RecallQuery::new(token(selected));
148        query.now_ms = CLOCK;
149        query.limit = 1;
150        let start = Instant::now();
151        let found = store.recall(&query);
152        recall_ms.push(ms(start));
153        returned += found.len();
154        hits += usize::from(
155            found
156                .first()
157                .is_some_and(|r| r.trace.id == format!("sample-{selected}")),
158        );
159        result_ids.push(found.iter().map(|r| r.trace.id.clone()).collect::<Vec<_>>());
160    }
161    let start = Instant::now();
162    store.verify()?;
163    let verify_ms = ms(start);
164    let before = store.head();
165    drop(store);
166    let start = Instant::now();
167    let store = MemoryStore::open_existing(&path, KernelPolicy::default())?;
168    let replay_ms = ms(start);
169    store.verify()?;
170    let retained = store
171        .all()
172        .filter(|e| {
173            e.trace.provenance.source == "synthetic-kernel-benchmark"
174                && e.trace.provenance.observed_at_ms == CLOCK
175                && !e.trace.provenance.verified
176        })
177        .count();
178    let mut replay_matches = 0;
179    for (i, expected) in result_ids.iter().enumerate() {
180        let mut query = RecallQuery::new(token(i * records / queries));
181        query.now_ms = CLOCK;
182        query.limit = 1;
183        let ids: Vec<_> = store
184            .recall(&query)
185            .into_iter()
186            .map(|r| r.trace.id)
187            .collect();
188        replay_matches += usize::from(ids == *expected);
189    }
190    let head_same = serde_json::to_value(before)? == serde_json::to_value(store.head())?;
191    let ok = store.record_count() == records
192        && retained == records
193        && hits == queries
194        && replay_matches == queries
195        && head_same;
196    Ok(json!({
197        "kind": "synthetic_scale", "ok": ok, "records": records, "queries": queries,
198        "workload": "unclaimed observation traces, unique exact lexical cues, fixed clock",
199        "seed_ms": seed_ms, "batch_size": 1000, "batched_records": batched,
200        "batch_append_ms": quantiles(batches), "single_append_ms": quantiles(appends),
201        "recall_ms": quantiles(recall_ms), "verify_ms": verify_ms, "replay_ms": replay_ms,
202        "exact_cue_hits": hits, "returned": returned, "recall_at_1": hits as f64 / queries as f64,
203        "provenance_retained": retained, "replayed_records": store.record_count(),
204        "recall_replay_matches": replay_matches, "head_unchanged": head_same,
205        "ledger_bytes": fs::metadata(path)?.len(), "memory_after_seed": memory_after_seed,
206        "memory_after_replay": rss(), "policy": store.policy(),
207        "limits": ["Batched seeding does not measure per-record durable append latency.",
208          "Warm filesystem cache; reopening in the same process is not a cold-start measurement.",
209          "No structured claims in this workload; conflict-heavy stores need a separate workload.",
210          "Synthetic exact-cue quality is not semantic or real-world retrieval accuracy.",
211          "RSS is process-wide Linux /proc data; unavailable platforms report null."]
212    }))
213}
Source§

impl MemoryStore

Source

pub fn gate_threshold( &self, max_false_block: f64, ) -> Result<GateThresholdReport>

Pair recorded Truth Gate engine predictions (model: sources only) with their outcomes and choose the engine threshold. Refuses with fewer than MIN_OUTCOMES resolved predictions, or without both classes.

Source§

impl MemoryStore

Source

pub fn provenance_chain(&self, id: &str) -> Option<TraceLineage>

The full provenance chain of one trace: itself, its supersession lineage, and its unresolved conflicts. None when no trace carries id.

Trait Implementations§

Source§

impl Debug for MemoryStore

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.