use std::fs;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
use supercode_harness::{DiscoveryQuery, HarnessCatalog, HarnessHomes, HarnessId};
fn temp_dir(label: &str) -> PathBuf {
let nonce = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos();
let path = std::env::temp_dir().join(format!(
"supercode-uni7-{label}-{}-{nonce}",
std::process::id()
));
fs::create_dir_all(&path).unwrap();
path
}
fn make_main_repo(root: &Path, origin: &str) {
let git = root.join(".git");
fs::create_dir_all(git.join("worktrees")).unwrap();
fs::write(
git.join("config"),
format!("[core]\n\trepositoryformatversion = 0\n[remote \"origin\"]\n\turl = {origin}\n\tfetch = +refs/heads/*:refs/remotes/origin/*\n"),
)
.unwrap();
}
fn make_worktree(root: &Path, main: &Path, name: &str) {
fs::create_dir_all(root).unwrap();
let slot = main.join(".git/worktrees").join(name);
fs::create_dir_all(&slot).unwrap();
fs::write(root.join(".git"), format!("gitdir: {}\n", slot.display())).unwrap();
}
fn write_session(home: &Path, id: &str, cwd: &Path, at_ms: u64) {
let project = home.join("projects/p");
fs::create_dir_all(&project).unwrap();
let line = serde_json::json!({
"type": "user",
"sessionId": id,
"cwd": cwd.to_string_lossy(),
"timestamp": format!("2026-08-30T00:00:{:02}.000Z", at_ms / 1000 % 60),
"message": {"role": "user", "content": [{"type": "text", "text": format!("hello from {id}")}]}
});
fs::write(project.join(format!("{id}.jsonl")), format!("{line}\n")).unwrap();
let stamp = SystemTime::UNIX_EPOCH + std::time::Duration::from_millis(at_ms);
let file = fs::File::options()
.append(true)
.open(project.join(format!("{id}.jsonl")))
.unwrap();
file.set_modified(stamp).unwrap();
}
struct World {
home: PathBuf,
main: PathBuf,
worktree_a: PathBuf,
worktree_b: PathBuf,
clone: PathBuf,
unrelated: PathBuf,
}
fn build_world() -> World {
let base = temp_dir("family");
let main = base.join("repo-main");
let worktree_a = base.join("repo-wt-a");
let worktree_b = base.join("repo-wt-b");
let clone = base.join("repo-clone");
let unrelated = base.join("other-repo");
fs::create_dir_all(&main).unwrap();
make_main_repo(&main, "git@example.com:volter/product.git");
make_worktree(&worktree_a, &main, "wt-a");
make_worktree(&worktree_b, &main, "wt-b");
fs::create_dir_all(&clone).unwrap();
make_main_repo(&clone, "git@example.com:volter/product.git");
fs::create_dir_all(&unrelated).unwrap();
make_main_repo(&unrelated, "git@example.com:volter/other.git");
let home = base.join("claude-home");
write_session(&home, "s-main", &main, 5_000);
write_session(&home, "s-wt-a", &worktree_a, 4_000);
write_session(&home, "s-wt-b", &worktree_b, 3_000);
write_session(&home, "s-clone", &clone, 2_000);
write_session(&home, "s-unrelated", &unrelated, 1_000);
World {
home,
main,
worktree_a,
worktree_b,
clone,
unrelated,
}
}
fn family_query(world: &World, scope: &Path) -> DiscoveryQuery {
DiscoveryQuery {
harnesses: vec![HarnessId::new(HarnessId::CLAUDE_CODE)],
homes: HarnessHomes {
claude_code: world.home.clone(),
..HarnessHomes::default()
},
workspace_family: Some(scope.to_path_buf()),
..DiscoveryQuery::default()
}
}
#[test]
fn family_scope_joins_main_and_worktrees_without_admitting_unrelated_repos() {
let world = build_world();
let page = HarnessCatalog::new()
.discover_page(&family_query(&world, &world.worktree_a))
.unwrap();
let ids: Vec<&str> = page
.sessions
.iter()
.map(|s| s.locator.session_id.as_str())
.collect();
assert_eq!(ids, ["s-main", "s-wt-a", "s-wt-b", "s-clone"], "{ids:?}");
let page = HarnessCatalog::new()
.discover_page(&family_query(&world, &world.unrelated))
.unwrap();
let ids: Vec<&str> = page
.sessions
.iter()
.map(|s| s.locator.session_id.as_str())
.collect();
assert_eq!(ids, ["s-unrelated"]);
let mut exact = family_query(&world, &world.main);
exact.workspace_family = None;
exact.workspace = Some(world.worktree_b.clone());
let page = HarnessCatalog::new().discover_page(&exact).unwrap();
let ids: Vec<&str> = page
.sessions
.iter()
.map(|s| s.locator.session_id.as_str())
.collect();
assert_eq!(ids, ["s-wt-b"]);
}
#[test]
fn receipt_reports_window_bounds_counts_and_truncation() {
let world = build_world();
let mut query = family_query(&world, &world.main);
query.updated_after_ms = Some(2_500);
query.limit = Some(2);
let page = HarnessCatalog::new().discover_page(&query).unwrap();
assert_eq!(page.sessions.len(), 2);
let receipt = &page.receipt;
assert_eq!(receipt.requested_after_ms, Some(2_500));
assert_eq!(receipt.requested_before_ms, None);
assert_eq!(receipt.requested_limit, Some(2));
assert_eq!(receipt.returned, 2);
assert_eq!(receipt.total_matched, 3);
assert!(receipt.truncated);
assert!(page.next_cursor.is_some());
assert_eq!(receipt.newest_returned_ms, Some(5_000));
assert_eq!(receipt.oldest_returned_ms, Some(4_000));
query.cursor = page.next_cursor.clone();
let rest = HarnessCatalog::new().discover_page(&query).unwrap();
assert_eq!(rest.receipt.returned, 1);
assert!(!rest.receipt.truncated);
assert!(rest.next_cursor.is_none());
assert_eq!(rest.receipt.oldest_returned_ms, Some(3_000));
}