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

@ -145,15 +145,13 @@ fn gather(level: &DigestLevel, store: &Store, arg: &str) -> Result<(String, Vec<
.collect();
load_child_digests(store, child_name, &child_labels)
} else {
// Leaf level: scan store for journal entries matching label
let date_re = Regex::new(&format!(
r"^journal#j-{}", regex::escape(&label)
)).unwrap();
// Leaf level: scan store for episodic entries matching date
let mut entries: Vec<_> = store.nodes.values()
.filter(|n| date_re.is_match(&n.key))
.filter(|n| n.node_type == store::NodeType::EpisodicSession
&& n.timestamp > 0
&& store::format_date(n.timestamp) == label)
.map(|n| {
let ts = n.key.strip_prefix("journal#j-").unwrap_or(&n.key);
(ts.to_string(), n.content.clone())
(store::format_datetime(n.timestamp), n.content.clone())
})
.collect();
entries.sort_by(|a, b| a.0.cmp(&b.0));
@ -252,14 +250,10 @@ pub fn generate(store: &mut Store, level_name: &str, arg: &str) -> Result<(), St
pub fn digest_auto(store: &mut Store) -> Result<(), String> {
let today = Local::now().format("%Y-%m-%d").to_string();
// Collect all dates with journal entries
let date_re = Regex::new(r"^\d{4}-\d{2}-\d{2}").unwrap();
let dates: Vec<String> = store.nodes.keys()
.filter_map(|key| {
key.strip_prefix("journal#j-")
.filter(|rest| rest.len() >= 10 && date_re.is_match(rest))
.map(|rest| rest[..10].to_string())
})
// Collect all dates with episodic entries
let dates: Vec<String> = store.nodes.values()
.filter(|n| n.node_type == store::NodeType::EpisodicSession && n.timestamp > 0)
.map(|n| store::format_date(n.timestamp))
.collect::<BTreeSet<_>>()
.into_iter()
.collect();
@ -408,10 +402,12 @@ fn parse_digest_node_links(key: &str, content: &str) -> Vec<DigestLink> {
pub fn parse_all_digest_links(store: &Store) -> Vec<DigestLink> {
let mut all_links = Vec::new();
let mut digest_keys: Vec<&String> = store.nodes.keys()
.filter(|k| k.starts_with("daily-")
|| k.starts_with("weekly-")
|| k.starts_with("monthly-"))
let mut digest_keys: Vec<&String> = store.nodes.iter()
.filter(|(_, n)| matches!(n.node_type,
store::NodeType::EpisodicDaily
| store::NodeType::EpisodicWeekly
| store::NodeType::EpisodicMonthly))
.map(|(k, _)| k)
.collect();
digest_keys.sort();