rename agent: LLM-powered semantic key generation for memory nodes

New consolidation agent that reads node content and generates semantic
3-5 word kebab-case keys, replacing auto-generated slugs (5K+ journal
entries with truncated first-line slugs, 2.5K mined transcripts with
opaque UUIDs).

Implementation:
- prompts/rename.md: agent prompt template with naming conventions
- prompts.rs: format_rename_candidates() selects nodes with long
  auto-generated keys, newest first
- daemon.rs: job_rename_agent() parses RENAME actions from LLM
  output and applies them directly via store.rename_node()
- Wired into RPC handler (run-agent rename) and TUI agent types
- Fix epoch_to_local panic on invalid timestamps (fallback to UTC)

Rename dramatically improves search: key-component matching on
"journal#2026-02-28-violin-dream-room" makes the node findable by
"violin", "dream", or "room" — the auto-slug was unsearchable.
This commit is contained in:
ProofOfConcept 2026-03-10 00:55:26 -04:00
parent ef760f0053
commit 4c973183c4
5 changed files with 219 additions and 5 deletions

View file

@ -133,10 +133,15 @@ pub fn epoch_to_local(epoch: i64) -> (i32, u32, u32, u32, u32, u32) {
chrono::LocalResult::Single(dt) => dt,
chrono::LocalResult::Ambiguous(dt, _) => dt,
chrono::LocalResult::None => {
// DST gap — add an hour to land in valid local time
// DST gap or invalid — try shifting, then fall back to UTC
Local.timestamp_opt(epoch + 3600, 0)
.earliest()
.unwrap_or_else(|| chrono::Utc.timestamp_opt(epoch, 0).unwrap().with_timezone(&Local))
.or_else(|| chrono::Utc.timestamp_opt(epoch, 0).earliest()
.map(|dt| dt.with_timezone(&Local)))
.unwrap_or_else(|| {
// Completely invalid timestamp — use epoch 0
chrono::Utc.timestamp_opt(0, 0).unwrap().with_timezone(&Local)
})
}
};
(