huskies: merge 1199 story Orphaned build-dir GC: reclaim dead worktree targets without touching warm caches

This commit is contained in:
Huskies Agent
2026-07-17 20:57:21 +00:00
parent 2bd41d980c
commit 5b340e7b20
18 changed files with 565 additions and 5 deletions
@@ -157,6 +157,12 @@ pub(crate) async fn on_coding_transition(project_root: &Path, port: u16, story_i
}
/// Remove the worktree and feature branch for `story_id` after it reaches a terminal stage.
///
/// Story 1199: bytes-reclaimed accounting for the worktree's `target/` dir
/// happens one layer down, in `remove_worktree` — the single choke point
/// shared by this subscriber, the `remove_worktree` MCP tool, and
/// `worktree::cleanup`/`sweep`. Logging it there (once) avoids a duplicate
/// log line here.
pub(crate) async fn on_terminal_transition(project_root: &Path, story_id: &str) {
let config = match crate::config::ProjectConfig::load(project_root) {
Ok(c) => c,
@@ -270,6 +276,30 @@ mod tests {
);
}
/// Story 1199 AC4: on_terminal_transition reclaims the worktree's target/
/// dir (and everything else in the worktree) when removing it.
#[tokio::test]
async fn terminal_transition_reclaims_target_dir() {
let tmp = TempDir::new().unwrap();
let root = setup_project(&tmp);
let story_id = "1006_test_reclaim_target";
on_coding_transition(&root, 3001, story_id).await;
let wt_path = crate::worktree::worktree_path(&root, story_id);
let target_dir = wt_path.join("target");
fs::create_dir_all(&target_dir).unwrap();
fs::write(target_dir.join("build_artifact.bin"), vec![0u8; 512]).unwrap();
assert!(target_dir.exists(), "target/ must exist before cleanup");
on_terminal_transition(&root, story_id).await;
assert!(
!target_dir.exists(),
"target/ dir must be reclaimed when the worktree is removed"
);
assert!(!wt_path.exists());
}
/// AC2: on_terminal_transition is a no-op (non-fatal) when no worktree exists.
#[tokio::test]
async fn terminal_transition_noop_when_no_worktree() {