feat(maestro): uncapped spawn-history recents for project enrichment (#54)

This commit is contained in:
Miguel Palhas
2026-08-23 20:44:15 +01:00
parent 33fb50be6e
commit 1809f5d581
2 changed files with 48 additions and 2 deletions
+10
View File
@@ -169,6 +169,16 @@ impl SessionManager {
.unwrap_or_default()
}
/// Every deduped recent dir, newest-first, without the picker's result
/// cap (#54): project enrichment folds the whole history.
pub fn all_recent_dirs(&self) -> Vec<RecentDir> {
self.inner
.spawn_history
.as_ref()
.map(|h| h.all_recent_dirs())
.unwrap_or_default()
}
/// Subscribe to session deltas. Each subscriber gets its own lag domain —
/// a slow client makes only itself resync.
pub fn events(&self) -> broadcast::Receiver<CatalogEvent> {
+38 -2
View File
@@ -143,11 +143,23 @@ impl SpawnHistory {
/// Recent working dirs, newest use first, deduped by `cwd`, within the
/// recency cap, capped at `max_results`. Empty when disabled or unreadable.
pub fn recent_dirs(&self) -> Vec<RecentDir> {
self.recent_dirs_as_of(Utc::now())
self.recent_dirs_capped(Utc::now(), self.max_results)
}
/// Every deduped recent dir, newest-first, without the picker's result
/// cap (#54): project enrichment folds the whole history, not its first
/// page, so a project spawned in long ago still reads as fresh.
pub fn all_recent_dirs(&self) -> Vec<RecentDir> {
self.recent_dirs_capped(Utc::now(), usize::MAX)
}
/// [`recent_dirs`](Self::recent_dirs) with an explicit clock for testing.
#[cfg(test)]
fn recent_dirs_as_of(&self, now: DateTime<Utc>) -> Vec<RecentDir> {
self.recent_dirs_capped(now, self.max_results)
}
fn recent_dirs_capped(&self, now: DateTime<Utc>, max_results: usize) -> Vec<RecentDir> {
if !self.is_enabled() {
return Vec::new();
}
@@ -168,7 +180,7 @@ impl SpawnHistory {
last_command: rec.command,
last_used: rec.at,
});
if out.len() >= self.max_results {
if out.len() >= max_results {
break;
}
}
@@ -362,4 +374,28 @@ mod tests {
assert_eq!(recents[0].cwd, PathBuf::from("/d4"));
assert_eq!(recents[1].cwd, PathBuf::from("/d3"));
}
/// Project enrichment (#54) folds the whole log, not just the picker's
/// first page.
#[test]
fn all_recent_dirs_skips_the_result_cap() {
let tmp = tempfile::tempdir().unwrap();
let mut h = SpawnHistory::new(tmp.path().join("h.jsonl"), 30);
h.max_results = 2;
// Recent enough to survive the 30-day cap against the real clock.
let base = Utc::now() - Duration::hours(1);
for i in 0..5 {
h.append(&rec(
&format!("/d{i}"),
"claude",
base + Duration::minutes(i),
))
.unwrap();
}
assert_eq!(h.recent_dirs().len(), 2);
let all = h.all_recent_dirs();
assert_eq!(all.len(), 5);
assert_eq!(all[0].cwd, PathBuf::from("/d4"));
assert_eq!(all[4].cwd, PathBuf::from("/d0"));
}
}