remove Category from the type system

Category was a manually-assigned label with no remaining functional
purpose (decay was the only behavior it drove, and that's gone).
Remove the enum, its methods, category_counts, the --category search
filter, and all category display. The field remains in the capnp
schema for backwards compatibility but is no longer read or written.

Status and health reports now show NodeType breakdown (semantic,
episodic, daily, weekly, monthly) instead of categories.

Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-03-08 20:33:03 -04:00
parent ba30f5b3e4
commit 488fd5a0aa
7 changed files with 45 additions and 120 deletions

View file

@ -135,7 +135,7 @@ fn usage() {
eprintln!("poc-memory v0.4.0 — graph-structured memory store
Commands:
search QUERY [--expand] [--category CAT] Search memory (AND logic)
search QUERY [--expand] Search memory (AND logic)
init Scan markdown files, index all memory units
migrate Migrate from old weights.json system
health Report graph metrics (CC, communities, small-world)
@ -224,55 +224,24 @@ Search memory using spreading activation (AND logic across terms).
Options:
--expand Show 15 results instead of 5, plus spectral neighbors
--category CAT Filter results to category: core, tech, gen, obs, task
--help, -h Show this help
Examples:
poc-memory search irc connection
poc-memory search bcachefs transaction --expand
poc-memory search rust --category tech");
poc-memory search bcachefs transaction --expand");
return Ok(());
}
let expand = args.iter().any(|a| a == "--expand");
let category_filter: Option<String> = {
let mut cat = None;
let mut iter = args.iter();
while let Some(a) = iter.next() {
if a == "--category" {
cat = iter.next().cloned();
break;
}
}
cat
};
let query: String = args.iter()
.filter(|a| *a != "--expand" && *a != "--category")
.scan(false, |skip_next, a| {
if *skip_next { *skip_next = false; return Some(None); }
if a == "--category" { *skip_next = true; return Some(None); }
Some(Some(a.as_str()))
})
.flatten()
.filter(|a| *a != "--expand")
.map(|a| a.as_str())
.collect::<Vec<_>>()
.join(" ");
let view = store::AnyView::load()?;
let mut results = search::search(&query, &view);
// Filter by category if requested
if let Some(ref cat_str) = category_filter {
let cat = store::Category::from_str(cat_str)
.ok_or_else(|| format!("Unknown category '{}' (use: core, tech, gen, obs, task)", cat_str))?;
let store = store::Store::load()?;
results.retain(|r| {
store.nodes.get(&r.key)
.map(|n| n.category.label() == cat.label())
.unwrap_or(false)
});
}
let results = search::search(&query, &view);
if results.is_empty() {
eprintln!("No results for '{}'", query);
@ -459,16 +428,19 @@ fn cmd_status() -> Result<(), String> {
let store = store::Store::load()?;
let node_count = store.nodes.len();
let rel_count = store.relations.len();
let categories = store.category_counts();
let mut episodic = 0usize;
let mut semantic = 0usize;
for n in store.nodes.values() {
if matches!(n.node_type, store::NodeType::Semantic) {
semantic += 1;
} else {
episodic += 1;
}
}
println!("Nodes: {} Relations: {}", node_count, rel_count);
println!("Categories: core={} tech={} gen={} obs={} task={}",
categories.get("core").unwrap_or(&0),
categories.get("tech").unwrap_or(&0),
categories.get("gen").unwrap_or(&0),
categories.get("obs").unwrap_or(&0),
categories.get("task").unwrap_or(&0),
);
println!("Types: semantic={} episodic={}", semantic, episodic);
let g = store.build_graph();
println!("Graph edges: {} Communities: {}",
@ -1058,8 +1030,8 @@ fn cmd_trace(args: &[String]) -> Result<(), String> {
// Display the node itself
println!("=== {} ===", resolved);
println!("Type: {:?} Category: {} Weight: {:.2}",
node.node_type, node.category.label(), node.weight);
println!("Type: {:?} Weight: {:.2}",
node.node_type, node.weight);
if !node.source_ref.is_empty() {
println!("Source: {}", node.source_ref);
}