use rto_graph::{
AnchorState, DEFAULT_MEMORY_SCOPE, Edge, EdgeKind, FactSet, GraphArtifact, MemoryFilter,
MemoryKind, MemoryWrite, Node, NodeKind, Provenance, RecallOptions, SearchOptions, Store,
anchor_penalty, search, search_channels,
};
const LESSON: &str = "The pelican migration failed because the retry loop double-counted \
partial batches; do not reintroduce the batch cursor without a dedup key.";
fn seed_graph(store: &mut Store) {
let mut facts = FactSet::new();
let mut adr =
Node::new("adr:0013", NodeKind::Adr, "Agent memory").with_provenance(Provenance::Authored);
adr.path = Some("docs/adr/0013.md".into());
adr.meta = serde_json::json!({
"content": "Durable agent-learned knowledge lives in its own artifact store and \
never borrows the graph's trust.",
});
let mut migrate = Node::new("sym:rust:src/migrate.rs#run", NodeKind::Fn, "run");
migrate.path = Some("src/migrate.rs".into());
migrate.blob_hash = Some("blob-migrate-v1".into());
facts.nodes = vec![
adr,
migrate,
Node::new("sym:rust:src/lib.rs#main", NodeKind::Fn, "main"),
];
facts.edges = vec![Edge::authored(
"adr:0013",
"sym:rust:src/lib.rs#main",
EdgeKind::References,
)];
store.rebuild(&facts, Some("treeabc")).expect("rebuild");
}
fn seed_graph_with_changed_blob(store: &mut Store) {
let mut facts = store.export_factset().expect("export");
for node in &mut facts.nodes {
if node.key == "sym:rust:src/migrate.rs#run" {
node.blob_hash = Some("blob-migrate-v2".into());
}
}
store.rebuild(&facts, Some("treedef")).expect("rebuild");
}
fn lesson(body: &str) -> MemoryWrite<'_> {
MemoryWrite {
scope: DEFAULT_MEMORY_SCOPE,
kind: MemoryKind::Lesson,
anchor: None,
body,
confidence: None,
supersedes: None,
}
}
fn state(store: &Store, id: i64) -> AnchorState {
store
.memory_record(id)
.expect("get")
.expect("present")
.anchor_state
}
fn live(store: &Store) -> Vec<rto_graph::MemoryRecord> {
store
.memory_records(&MemoryFilter::default())
.expect("records")
}
#[test]
fn memory_writes_leave_the_exported_artifact_byte_identical() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let before_bytes =
serde_json::to_vec(&store.export_factset().expect("export")).expect("serialize");
let before_artifact =
serde_json::to_vec(&GraphArtifact::from_store(&store).expect("artifact")).expect("bytes");
let (before_nodes, before_edges) = (
store.node_count().expect("nodes"),
store.edge_count().expect("edges"),
);
let anchored = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
kind: MemoryKind::Attempt,
confidence: Some(0.9),
..lesson(LESSON)
})
.expect("anchored write");
store
.record_memory(&MemoryWrite {
supersedes: Some(anchored),
..lesson("Superseded: the dedup key alone was not enough.")
})
.expect("superseding write");
let doomed = store
.record_memory(&lesson("A record that will be forgotten."))
.expect("write");
store.forget_memory(doomed).expect("forget");
assert_eq!(
store.memory_counts().expect("counts"),
(1, 1),
"the writes must actually have done work",
);
assert_eq!(
serde_json::to_vec(&store.export_factset().expect("export")).expect("serialize"),
before_bytes,
"export_factset must be byte-identical across memory writes",
);
assert_eq!(
serde_json::to_vec(&GraphArtifact::from_store(&store).expect("artifact")).expect("bytes"),
before_artifact,
"the published GraphArtifact must be byte-identical across memory writes",
);
assert_eq!(store.node_count().expect("nodes"), before_nodes);
assert_eq!(store.edge_count().expect("edges"), before_edges);
for node in store.all_nodes().expect("nodes") {
assert!(
!node.meta.to_string().contains("pelican migration"),
"{}: a memory body leaked into a node's meta",
node.key,
);
}
}
#[test]
fn a_memory_record_is_not_a_node_under_any_provenance() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let before: Vec<(Provenance, usize)> = [
Provenance::Derived,
Provenance::Authored,
Provenance::Inferred,
]
.into_iter()
.map(|p| (p, store.nodes_by_provenance(p).expect("nodes").len()))
.collect();
store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson(LESSON)
})
.expect("write");
for (provenance, count) in before {
assert_eq!(
store.nodes_by_provenance(provenance).expect("nodes").len(),
count,
"a memory write must not add a {provenance:?} node",
);
}
assert!(
store
.all_keys()
.expect("keys")
.iter()
.all(|k| !k.contains("memory") && !k.contains("mem:")),
"no node key may be minted for a memory record",
);
assert!(
store
.all_edges()
.expect("edges")
.iter()
.all(|e| e.kind != EdgeKind::Supersedes),
"supersession stays inside the artifact store and never becomes an edge",
);
}
#[test]
fn memory_reaches_search_only_through_its_own_channel() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson(LESSON)
})
.expect("write");
for query in [
"pelican migration",
"retry loop double-counted",
"dedup key",
] {
assert!(
search(&store, query, 10).expect("search").is_empty(),
"a memory body reached the graph channel via {query:?}",
);
let default = search_channels(&store, query, SearchOptions::default()).expect("search");
assert!(
default.hits.is_empty() && default.generated.is_empty() && default.memory.is_empty(),
"{query:?} reached a default search, which asks for none of this",
);
let generated_only = search_channels(
&store,
query,
SearchOptions {
limit: 10,
include_generated: true,
..SearchOptions::default()
},
)
.expect("search");
assert!(
generated_only.hits.is_empty(),
"{query:?} reached the graph channel",
);
assert!(
generated_only.generated.is_empty(),
"{query:?} reached the generated-content channel",
);
assert!(
generated_only.memory.is_empty(),
"one opt-in must not imply another",
);
let opted = search_channels(
&store,
query,
SearchOptions {
limit: 10,
include_memory: true,
..SearchOptions::default()
},
)
.expect("search");
assert_eq!(
opted.memory.len(),
1,
"{query:?} must find the record in the memory channel",
);
assert!(opted.memory[0].memory, "and it is marked as memory");
assert!(
opted.hits.is_empty(),
"{query:?} still must not be a graph hit",
);
}
assert!(
!search(&store, "agent memory", 10)
.expect("search")
.is_empty(),
"the authored ADR must still be findable",
);
}
#[test]
fn the_memory_channel_scores_without_the_authored_boost() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let shared = "durable agent-learned knowledge";
store
.record_memory(&MemoryWrite {
confidence: Some(1.0),
..lesson(
"Durable agent-learned knowledge lives in its own artifact store and never \
borrows the graph's trust.",
)
})
.expect("write");
let results = search_channels(
&store,
shared,
SearchOptions {
limit: 10,
include_memory: true,
..SearchOptions::default()
},
)
.expect("search");
let authored = results
.hits
.iter()
.find(|h| h.node.key == "adr:0013")
.expect("the authored ADR is a graph hit");
let remembered = results
.memory
.first()
.expect("and the memory record is a memory hit");
assert!(
authored.score > remembered.score,
"the same words scored {} as memory against {} as authored intent — the +40 \
boost has leaked",
remembered.score,
authored.score,
);
let tokens = shared.split_whitespace().count();
let ceiling = u32::try_from(25 + 8 * tokens).expect("small");
assert!(
remembered.score <= ceiling,
"a memory hit scored {} against a lexical ceiling of {ceiling} — the score \
carries a term that is not its own, and the only such term is the +40 \
`authored` boost",
remembered.score,
);
assert!(
!results.hits.iter().any(|h| h.node.key.contains("memory:")),
"nothing memory-shaped is in the graph channel",
);
}
#[test]
fn memory_survives_a_graph_rebuild_and_a_reconcile() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let id = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson(LESSON)
})
.expect("write");
let mut facts = FactSet::new();
facts.nodes = vec![Node::new(
"sym:rust:src/other.rs#helper",
NodeKind::Fn,
"helper",
)];
store.rebuild(&facts, Some("treexyz")).expect("rebuild");
let record = store
.memory_record(id)
.expect("get")
.expect("the record must survive a rebuild");
assert_eq!(record.body, LESSON);
assert_eq!(
record.anchor.as_ref().map(|a| a.key.as_str()),
Some("sym:rust:src/migrate.rs#run"),
"the anchor is preserved verbatim, even though its node is gone",
);
store.reconcile(&facts, Some("treexyz")).expect("reconcile");
assert_eq!(store.memory_counts().expect("counts"), (1, 0));
}
#[test]
fn anchor_state_distinguishes_valid_drifted_and_vanished() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let anchored = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson(LESSON)
})
.expect("write");
let ghost = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/gone.rs#removed"),
..lesson("This function was deleted for a reason; do not resurrect it.")
})
.expect("write");
let free = store
.record_memory(&lesson("A general lesson"))
.expect("write");
assert_eq!(state(&store, anchored), AnchorState::Valid);
assert_eq!(
state(&store, ghost),
AnchorState::Vanished,
"an anchor key naming no node is recorded and reads as vanished",
);
assert_eq!(state(&store, free), AnchorState::Unanchored);
assert!(!state(&store, anchored).is_stale() && state(&store, ghost).is_stale());
seed_graph_with_changed_blob(&mut store);
assert_eq!(
state(&store, anchored),
AnchorState::Drifted,
"a differing blob means the code changed underneath the record",
);
assert!(state(&store, anchored).is_stale());
let record = store
.memory_record(anchored)
.expect("get")
.expect("present");
assert_eq!(
record.anchor.expect("anchored").blob.as_deref(),
Some("blob-migrate-v1"),
);
}
#[test]
fn a_record_whose_anchor_vanished_is_kept_and_marked_not_pruned() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let id = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
kind: MemoryKind::Attempt,
..lesson(LESSON)
})
.expect("write");
assert_eq!(
store
.memory_record(id)
.expect("get")
.expect("present")
.anchor_state,
AnchorState::Valid,
);
let mut facts = store.export_factset().expect("export");
facts
.nodes
.retain(|n| n.key != "sym:rust:src/migrate.rs#run");
store.rebuild(&facts, Some("treedel")).expect("rebuild");
rto_graph::refresh_contexts(&store).expect("refresh");
let record = store
.memory_record(id)
.expect("get")
.expect("a record about deleted code is the point, not the problem");
assert_eq!(record.anchor_state, AnchorState::Vanished);
assert_eq!(record.body, LESSON);
assert_eq!(
live(&store).len(),
1,
"and it is still returned by a live listing, marked rather than hidden",
);
assert_eq!(store.memory_counts().expect("counts"), (1, 0));
}
#[test]
fn applicability_is_decided_by_the_anchor_and_by_nothing_about_the_record() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let id = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson(LESSON)
})
.expect("write");
let in_tree_a = store.memory_record(id).expect("get").expect("present");
assert!(
in_tree_a.applies,
"the anchor resolves here with the same blob"
);
assert_eq!(in_tree_a.anchor_state, AnchorState::Valid);
seed_graph_with_changed_blob(&mut store);
let in_tree_b = store.memory_record(id).expect("get").expect("present");
assert!(
!in_tree_b.applies,
"the association is not in this tree in the same format",
);
assert_eq!(in_tree_b.anchor_state, AnchorState::Drifted);
assert_eq!(in_tree_a.id, in_tree_b.id);
assert_eq!(in_tree_a.body, in_tree_b.body);
assert_eq!(in_tree_a.scope, in_tree_b.scope);
assert_eq!(in_tree_a.created_at, in_tree_b.created_at);
assert_eq!(
in_tree_a.anchor, in_tree_b.anchor,
"the captured evidence is untouched"
);
assert_eq!(in_tree_a.superseded_by, in_tree_b.superseded_by);
assert_eq!(store.memory_counts().expect("counts"), (1, 0));
assert_eq!(live(&store).len(), 1);
seed_graph(&mut store);
assert!(
store
.memory_record(id)
.expect("get")
.expect("present")
.applies,
"the record applies again as soon as the association is back in this form",
);
}
#[test]
fn no_anchor_applies_everywhere_and_is_never_confused_with_a_failed_one() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let general = store
.record_memory(&lesson("CI is Ubuntu-only; do not assume a macOS runner."))
.expect("write");
let ghost = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/gone.rs#removed"),
..lesson("This function was deleted on purpose.")
})
.expect("write");
let general_record = store.memory_record(general).expect("get").expect("present");
let ghost_record = store.memory_record(ghost).expect("get").expect("present");
assert_eq!(general_record.anchor_state, AnchorState::Unanchored);
assert!(
general_record.applies,
"a general lesson never claimed to be about particular code, so no tree \
can disagree with it",
);
assert!(general_record.anchor.is_none());
assert_eq!(ghost_record.anchor_state, AnchorState::Vanished);
assert!(
!ghost_record.applies,
"an anchor that failed to resolve is the opposite case and must not be \
rounded up to repo-wide",
);
assert!(
ghost_record.anchor.is_some(),
"the failed anchor is still on record"
);
let json = serde_json::to_value(&general_record).expect("json");
assert_eq!(json["anchor_state"], "unanchored");
assert_eq!(json["applies"], true);
assert!(json.get("anchor").is_none(), "no anchor key at all");
let json = serde_json::to_value(&ghost_record).expect("json");
assert_eq!(json["anchor_state"], "vanished");
assert_eq!(json["applies"], false);
assert_eq!(json["anchor"]["key"], "sym:rust:src/gone.rs#removed");
store
.rebuild(&FactSet::new(), Some("treeempty"))
.expect("rebuild");
assert!(
store
.memory_record(general)
.expect("get")
.expect("present")
.applies,
"a repo-wide lesson applies even to an empty tree",
);
}
#[test]
fn the_applicability_rule_is_exactly_unanchored_or_valid() {
for state in [AnchorState::Unanchored, AnchorState::Valid] {
assert!(state.applies(), "{state} must apply");
}
for state in [
AnchorState::Drifted,
AnchorState::Vanished,
AnchorState::Unverifiable,
] {
assert!(!state.applies(), "{state} must not apply");
}
assert!(!AnchorState::Unverifiable.is_stale());
assert!(AnchorState::Drifted.is_stale() && AnchorState::Vanished.is_stale());
}
#[test]
fn an_anchor_with_no_blob_is_unverifiable_rather_than_valid() {
let mut store = Store::open_in_memory().expect("store");
let mut facts = FactSet::new();
facts.nodes = vec![Node::new("sym:rust:src/lib.rs#main", NodeKind::Fn, "main")];
store.rebuild(&facts, Some("tree0")).expect("rebuild");
let id = store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/lib.rs#main"),
..lesson(LESSON)
})
.expect("write");
let record = store.memory_record(id).expect("get").expect("present");
assert_eq!(record.anchor_state, AnchorState::Unverifiable);
assert!(
!record.anchor_state.is_stale(),
"unverifiable is not drift: nothing was measured either way",
);
assert!(
!record.applies,
"an unmeasurable anchor cannot establish that the association is here",
);
assert!(record.anchor.is_some());
}
#[test]
fn a_superseded_record_leaves_live_listing_but_stays_on_record() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let old = store
.record_memory(&lesson("Batch size 500 is safe."))
.expect("write");
let new = store
.record_memory(&MemoryWrite {
supersedes: Some(old),
..lesson("Batch size 500 deadlocks under contention; 100 is safe.")
})
.expect("write");
let live_ids: Vec<i64> = live(&store).iter().map(|r| r.id).collect();
assert_eq!(live_ids, vec![new], "only the successor is live");
assert_eq!(store.memory_counts().expect("counts"), (1, 1));
let audited = store
.memory_records(&MemoryFilter {
include_superseded: true,
..MemoryFilter::default()
})
.expect("records");
assert_eq!(
audited.iter().map(|r| r.id).collect::<Vec<_>>(),
vec![new, old],
"newest generation first, by id and not by clock",
);
let overruled = audited.iter().find(|r| r.id == old).expect("still stored");
assert_eq!(overruled.superseded_by, Some(new));
assert!(
overruled.superseded_at.is_some(),
"the moment is recorded too"
);
assert!(!overruled.is_live());
assert_eq!(overruled.body, "Batch size 500 is safe.");
let err = store
.record_memory(&MemoryWrite {
supersedes: Some(old),
..lesson("A third opinion.")
})
.expect_err("already superseded");
assert!(
matches!(err, rto_graph::MemoryError::AlreadySuperseded { id, by } if id == old && by == new),
"{err}",
);
let before = store.memory_counts().expect("counts");
assert!(matches!(
store
.record_memory(&MemoryWrite {
supersedes: Some(9999),
..lesson("Overruling a record that is not there.")
})
.expect_err("no such record"),
rto_graph::MemoryError::NotFound(9999),
));
assert_eq!(store.memory_counts().expect("counts"), before);
}
#[test]
fn forgetting_a_successor_restores_what_it_superseded() {
let mut store = Store::open_in_memory().expect("store");
let old = store.record_memory(&lesson("The original")).expect("write");
let new = store
.record_memory(&MemoryWrite {
supersedes: Some(old),
..lesson("The correction")
})
.expect("write");
let forgotten = store
.forget_memory(new)
.expect("forget")
.expect("the record was there");
assert_eq!(forgotten.id, new);
assert_eq!(forgotten.restored, vec![old]);
assert_eq!(
live(&store).iter().map(|r| r.id).collect::<Vec<_>>(),
vec![old],
"the predecessor is live again",
);
let record = store.memory_record(old).expect("get").expect("present");
assert_eq!(record.superseded_by, None);
assert_eq!(record.superseded_at, None, "both columns clear together");
assert!(store.forget_memory(new).expect("forget").is_none());
}
#[test]
fn ordering_is_a_monotonic_generation_that_never_reuses_an_id() {
let mut store = Store::open_in_memory().expect("store");
let first = store.record_memory(&lesson("first")).expect("write");
let second = store.record_memory(&lesson("second")).expect("write");
assert!(second > first, "ids are monotonic");
store.forget_memory(second).expect("forget");
let third = store.record_memory(&lesson("third")).expect("write");
assert!(
third > second,
"a forgotten id must never be handed out again: {third} <= {second}",
);
assert_eq!(
live(&store)
.iter()
.map(|r| r.body.clone())
.collect::<Vec<_>>(),
vec!["third".to_owned(), "first".to_owned()],
"listing is newest generation first",
);
let stamps: Vec<String> = live(&store).iter().map(|r| r.created_at.clone()).collect();
assert!(
stamps.iter().all(|s| !s.is_empty()),
"created_at is written for humans",
);
}
#[test]
fn scope_is_a_namespace_and_never_decides_applicability() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
store
.record_memory(&lesson("a repo-wide lesson"))
.expect("write");
let branchy = store
.record_memory(&MemoryWrite {
scope: "feat/some-other-branch",
kind: MemoryKind::Decision,
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson("a decision taken on a branch, about code that is here")
})
.expect("write");
assert!(
store
.memory_record(branchy)
.expect("get")
.expect("present")
.applies,
"a branch-shaped scope must not stop a resolving anchor from applying",
);
let scoped = store
.memory_records(&MemoryFilter {
scope: Some("feat/some-other-branch"),
..MemoryFilter::default()
})
.expect("records");
assert_eq!(scoped.len(), 1);
assert_eq!(scoped[0].scope, "feat/some-other-branch");
assert_eq!(scoped[0].kind, MemoryKind::Decision);
assert_eq!(live(&store).len(), 2);
assert_eq!(
store
.memory_records(&MemoryFilter {
kind: Some(MemoryKind::Lesson),
..MemoryFilter::default()
})
.expect("records")
.len(),
1,
);
assert!(
store
.memory_records(&MemoryFilter {
scope: Some("nope"),
..MemoryFilter::default()
})
.expect("records")
.is_empty(),
);
}
#[test]
fn a_listing_reports_the_counts_that_make_an_empty_result_legible() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let old = store.record_memory(&lesson("old")).expect("write");
store
.record_memory(&MemoryWrite {
supersedes: Some(old),
..lesson("new")
})
.expect("write");
store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/migrate.rs#run"),
..lesson(LESSON)
})
.expect("write");
let listing = store
.memory_listing(&MemoryFilter {
scope: Some("nothing-here"),
..MemoryFilter::default()
})
.expect("listing");
assert!(listing.records.is_empty());
assert_eq!((listing.live, listing.superseded), (2, 1));
assert_eq!(listing.schema, rto_graph::MEMORY_SCHEMA);
let listing = store
.memory_listing(&MemoryFilter::default())
.expect("listing");
let json = serde_json::to_value(&listing).expect("json");
assert_eq!(json["schema"], "roteiro.memory/v1");
assert_eq!(json["live"], 2);
assert_eq!(json["superseded"], 1);
let newest = &json["records"][0];
assert_eq!(newest["kind"], "lesson");
assert_eq!(newest["anchor_state"], "valid");
assert_eq!(
newest["applies"], true,
"the scope rule is in the JSON, so a consumer need not re-derive it",
);
assert_eq!(newest["anchor"]["key"], "sym:rust:src/migrate.rs#run");
assert_eq!(newest["anchor"]["blob"], "blob-migrate-v1");
assert_eq!(newest["superseded_by"], serde_json::Value::Null);
assert_eq!(
newest["tree"], "treeabc",
"the repo-state witness is recorded"
);
}
#[test]
fn a_limit_returns_the_newest_generations() {
let mut store = Store::open_in_memory().expect("store");
for i in 0..5 {
store
.record_memory(&lesson(&format!("lesson {i}")))
.expect("write");
}
let limited = store
.memory_records(&MemoryFilter {
limit: Some(2),
..MemoryFilter::default()
})
.expect("records");
assert_eq!(
limited.iter().map(|r| r.body.as_str()).collect::<Vec<_>>(),
vec!["lesson 4", "lesson 3"],
);
}
#[test]
fn a_record_round_trips_every_field() {
let mut store = Store::open_in_memory().expect("store");
seed_graph(&mut store);
let id = store
.record_memory(&MemoryWrite {
scope: "feat/stage23",
kind: MemoryKind::Pattern,
anchor: Some("sym:rust:src/migrate.rs#run"),
body: LESSON,
confidence: Some(0.75),
supersedes: None,
})
.expect("write");
let record = store.memory_record(id).expect("get").expect("present");
assert_eq!(record.id, id);
assert_eq!(record.scope, "feat/stage23");
assert_eq!(record.kind, MemoryKind::Pattern);
assert_eq!(record.body, LESSON);
assert_eq!(record.confidence, Some(0.75));
assert_eq!(record.tree.as_deref(), Some("treeabc"));
assert!(!record.created_at.is_empty());
let anchor = record.anchor.expect("anchored");
assert_eq!(anchor.key, "sym:rust:src/migrate.rs#run");
assert_eq!(anchor.blob.as_deref(), Some("blob-migrate-v1"));
assert_eq!(anchor.path.as_deref(), Some("src/migrate.rs"));
}
#[test]
fn a_memory_can_be_recorded_before_the_first_sync() {
let mut store = Store::open_in_memory().expect("store");
let id = store.record_memory(&lesson(LESSON)).expect("write");
let record = store.memory_record(id).expect("get").expect("present");
assert_eq!(record.tree, None);
assert_eq!(record.anchor_state, AnchorState::Unanchored);
}
#[test]
fn an_invalid_write_stores_nothing() {
let mut store = Store::open_in_memory().expect("store");
for bad in [
MemoryWrite { ..lesson("") },
MemoryWrite {
scope: "",
..lesson("body")
},
MemoryWrite {
confidence: Some(1.5),
..lesson("body")
},
] {
assert!(store.record_memory(&bad).is_err());
}
assert_eq!(store.memory_counts().expect("counts"), (0, 0));
}
fn two_anchored_nodes(store: &mut Store, moving_blob: &str) {
let mut facts = FactSet::new();
let mut stable = Node::new("sym:rust:src/stable.rs#keep", NodeKind::Fn, "keep");
stable.blob_hash = Some("blob-stable-v1".into());
let mut moving = Node::new("sym:rust:src/moving.rs#shift", NodeKind::Fn, "shift");
moving.blob_hash = Some(moving_blob.into());
facts.nodes = vec![stable, moving];
store.rebuild(&facts, Some("tree-two")).expect("rebuild");
}
#[test]
fn a_zero_confidence_memory_is_ranked_last_and_still_returned() {
let mut store = Store::open_in_memory().expect("store");
two_anchored_nodes(&mut store, "blob-moving-v1");
store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/stable.rs#keep"),
confidence: Some(0.0),
..lesson("A batch cursor dedup note its writer gave no credence.")
})
.expect("write");
store
.record_memory(&MemoryWrite {
anchor: Some("sym:rust:src/moving.rs#shift"),
..lesson("A batch cursor dedup note whose code moved underneath it.")
})
.expect("write");
two_anchored_nodes(&mut store, "blob-moving-v2");
let recall = store
.recall_memory(&RecallOptions::default())
.expect("recall");
assert_eq!(recall.results.len(), 2, "both records are recalled");
let zero = recall
.results
.iter()
.find(|r| r.record.body.contains("no credence"))
.expect("a zero-confidence record is still recalled, not dropped");
let drifted = recall
.results
.iter()
.find(|r| r.record.body.contains("moved underneath"))
.expect("present");
assert!(zero.score.abs() < f64::EPSILON, "the score is exactly zero");
assert!(zero.base_confidence.abs() < f64::EPSILON);
assert_eq!(zero.record.anchor_state, AnchorState::Valid);
assert!(
(zero.anchor_penalty - 1.0).abs() < f64::EPSILON,
"its anchor is perfect: only the stated confidence zeroed it",
);
assert!(zero.record.applies, "and it still applies to this tree");
assert_eq!(drifted.record.anchor_state, AnchorState::Drifted);
assert!((drifted.anchor_penalty - anchor_penalty(AnchorState::Drifted)).abs() < f64::EPSILON,);
assert!(
drifted.score > 0.0,
"the worst anchor state must not silence a record: {}",
drifted.score,
);
assert_eq!(
recall.results.last().expect("non-empty").record.id,
zero.record.id,
"a zero-evidence record sorts last",
);
let results = search_channels(
&store,
"batch cursor dedup",
SearchOptions {
limit: 10,
include_memory: true,
..SearchOptions::default()
},
)
.expect("search");
assert_eq!(results.memory.len(), 2, "both reach the memory channel");
let hit = results
.memory
.iter()
.find(|h| {
h.snippet
.as_deref()
.is_some_and(|s| s.contains("no credence"))
})
.expect("a zero-confidence memory is still a search hit");
assert_eq!(hit.score, 0, "scored zero…");
assert!(hit.evidence.abs() < f64::EPSILON);
assert_eq!(hit.anchor_state, "valid");
assert!(hit.applies);
assert!(hit.snippet.is_some(), "with its prose readable");
assert_eq!(
results.memory.last().expect("non-empty").score,
0,
"and ranked last",
);
assert!(
results.memory.iter().any(|h| h.score > 0),
"the drifted record still scores, so zero is not simply what this query gives",
);
}