query by NodeType instead of key prefix

Replace key prefix matching (journal#j-, daily-, weekly-, monthly-)
with NodeType filters (EpisodicSession, EpisodicDaily, EpisodicWeekly,
EpisodicMonthly) for all queries: journal-tail, digest gathering,
digest auto-detection, experience mining dedup, and find_journal_node.

Add EpisodicMonthly to NodeType enum and capnp schema.

Key naming conventions (journal#j-TIMESTAMP-slug, daily-DATE, etc.)
are retained for key generation — the fix is about how we find nodes,
not how we name them.

Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-03-08 20:14:37 -04:00
parent fd5591653d
commit 804578b977
8 changed files with 43 additions and 47 deletions

View file

@ -1122,7 +1122,8 @@ fn cmd_trace(args: &[String]) -> Result<(), String> {
episodic_session.push(entry),
store::NodeType::EpisodicDaily =>
episodic_daily.push(entry),
store::NodeType::EpisodicWeekly =>
store::NodeType::EpisodicWeekly
| store::NodeType::EpisodicMonthly =>
episodic_weekly.push(entry),
store::NodeType::Semantic =>
semantic.push(entry),
@ -1855,12 +1856,12 @@ fn cmd_journal_tail(args: &[String]) -> Result<(), String> {
// Original journal-tail behavior
journal_tail_entries(&store, n, full)
} else {
let prefix = match level {
1 => "daily-",
2 => "weekly-",
_ => "monthly-",
let node_type = match level {
1 => store::NodeType::EpisodicDaily,
2 => store::NodeType::EpisodicWeekly,
_ => store::NodeType::EpisodicMonthly,
};
journal_tail_digests(&store, prefix, n, full)
journal_tail_digests(&store, node_type, n, full)
}
}
@ -1916,17 +1917,22 @@ fn journal_tail_entries(store: &store::Store, n: usize, full: bool) -> Result<()
Ok(())
}
fn journal_tail_digests(store: &store::Store, prefix: &str, n: usize, full: bool) -> Result<(), String> {
fn journal_tail_digests(store: &store::Store, node_type: store::NodeType, n: usize, full: bool) -> Result<(), String> {
let mut digests: Vec<_> = store.nodes.values()
.filter(|node| node.key.starts_with(prefix))
.filter(|node| node.node_type == node_type)
.collect();
// Sort by key — the date/week label sorts lexicographically
digests.sort_by(|a, b| a.key.cmp(&b.key));
// Sort by timestamp, fall back to key for lexicographic ordering
digests.sort_by(|a, b| {
if a.timestamp > 0 && b.timestamp > 0 {
a.timestamp.cmp(&b.timestamp)
} else {
a.key.cmp(&b.key)
}
});
let skip = if digests.len() > n { digests.len() - n } else { 0 };
for node in digests.iter().skip(skip) {
let label = node.key.strip_prefix(prefix)
.unwrap_or(&node.key);
let label = &node.key;
let title = extract_title(&node.content);
if full {
println!("--- [{}] {} ---\n{}\n", label, title, node.content);