store: strip .md suffix from all keys
Keys were a vestige of the file-based era. resolve_key() added .md to lookups while upsert() used bare keys, creating phantom duplicate nodes (the instructions bug: writes went to "instructions", reads found "instructions.md"). - Remove .md normalization from resolve_key, strip instead - Update all hardcoded key patterns (journal.md# → journal#, etc) - Add strip_md_keys() migration to fsck: renames nodes and relations - Add broken link detection to health report - Delete redirect table (no longer needed) - Update config defaults and config.jsonl Migration: run `poc-memory fsck` to rename existing keys. Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
This commit is contained in:
parent
77fc533631
commit
46f8fe662e
12 changed files with 289 additions and 132 deletions
38
src/graph.rs
38
src/graph.rs
|
|
@ -606,6 +606,25 @@ pub fn health_report(graph: &Graph, store: &Store) -> String {
|
|||
.filter(|k| graph.clustering_coefficient(k) < 0.1)
|
||||
.count();
|
||||
|
||||
// Orphan edges: relations referencing non-existent nodes
|
||||
let mut orphan_edges = 0usize;
|
||||
let mut orphan_sources: Vec<String> = Vec::new();
|
||||
let mut orphan_targets: Vec<String> = Vec::new();
|
||||
for rel in &store.relations {
|
||||
if rel.deleted { continue; }
|
||||
let s_missing = !store.nodes.contains_key(&rel.source_key);
|
||||
let t_missing = !store.nodes.contains_key(&rel.target_key);
|
||||
if s_missing || t_missing {
|
||||
orphan_edges += 1;
|
||||
if s_missing && !orphan_sources.contains(&rel.source_key) {
|
||||
orphan_sources.push(rel.source_key.clone());
|
||||
}
|
||||
if t_missing && !orphan_targets.contains(&rel.target_key) {
|
||||
orphan_targets.push(rel.target_key.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Category breakdown
|
||||
let cats = store.category_counts();
|
||||
|
||||
|
|
@ -658,6 +677,25 @@ Categories: core={core} tech={tech} gen={gen} obs={obs} task={task}",
|
|||
task = cats.get("task").unwrap_or(&0),
|
||||
);
|
||||
|
||||
// Orphan edges
|
||||
if orphan_edges == 0 {
|
||||
report.push_str("\n\nBroken links: 0");
|
||||
} else {
|
||||
let mut all_missing: Vec<String> = orphan_sources;
|
||||
all_missing.extend(orphan_targets);
|
||||
all_missing.sort();
|
||||
all_missing.dedup();
|
||||
report.push_str(&format!(
|
||||
"\n\nBroken links: {} edges reference {} missing nodes",
|
||||
orphan_edges, all_missing.len()));
|
||||
for key in all_missing.iter().take(10) {
|
||||
report.push_str(&format!("\n - {}", key));
|
||||
}
|
||||
if all_missing.len() > 10 {
|
||||
report.push_str(&format!("\n ... and {} more", all_missing.len() - 10));
|
||||
}
|
||||
}
|
||||
|
||||
// Show history trend if we have enough data points
|
||||
if history.len() >= 3 {
|
||||
report.push_str("\n\nMetrics history (last 5):\n");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue