From 6096da09ad46b78f90d599c7517acaec693bebd4 Mon Sep 17 00:00:00 2001 From: Stella Test Date: Thu, 6 Aug 2026 04:07:45 -0700 Subject: [PATCH] fix(stella-cli): resolve the current self-driving root through stella-home too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1810 factored the LEGACY roots into `stella-home` so the writer and the read-only reader could not drift, and moved `stella-observatory` onto `stella_home::self_driving_root` for the current one — but left `LoopState::open` building `home.join("self-driving")` itself. Half the job: the current root, the one every live loop actually uses, was still two literals in two crates. That is the exact shape #1755 was filed for. Renaming the directory in one of them would point the dashboard at nothing, and the failure is silent — an empty Self-Driving tab reads as "no runs", never as "the reader is looking in the wrong place". Witness: `the_current_root_comes_from_the_shared_resolver` pins that the shared resolver still yields the directory this crate writes and the observatory reads. The test helper keeps its own literal deliberately — a test that re-derives the expected path from the code under test cannot catch a change to it. Refs #1755 --- .../stella-cli/src/self_driving_cmd/state.rs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/stella-cli/src/self_driving_cmd/state.rs b/crates/stella-cli/src/self_driving_cmd/state.rs index 1f81f9803..9a411ea20 100644 --- a/crates/stella-cli/src/self_driving_cmd/state.rs +++ b/crates/stella-cli/src/self_driving_cmd/state.rs @@ -141,7 +141,13 @@ impl LoopState { let home = stella_home::stella_home() .ok_or_else(|| "cannot resolve the stella home directory".to_string())?; let slug = repo_slug(&repo_root); - let dir = home.join("self-driving").join(&slug); + // Through `stella-home`, never `home.join("self-driving")` — the + // observatory resolves this same root read-only, and #1755 + // moved the spelling there precisely so the writer and the + // reader cannot drift. A second literal here is the drift. + let dir = stella_home::resolve_self_driving_root(Some(home.clone())) + .ok_or_else(|| "cannot resolve the self-driving state root".to_string())? + .join(&slug); migrate_legacy_state(&dir, &slug, &home); dir } @@ -679,6 +685,23 @@ mod tests { ); } + /// The CURRENT root has the same two-readers problem as the legacy ones, + /// and #1810 factored out only half of it: the observatory moved to + /// `stella_home::self_driving_root`, while `LoopState::open` kept its own + /// `home.join("self-driving")`. Two literals for one path is exactly the + /// drift the shared resolver exists to prevent — a rename of the directory + /// in one of them would point the dashboard at nothing, silently. + #[test] + fn the_current_root_comes_from_the_shared_resolver() { + let home = PathBuf::from("/home/dev/.stella"); + assert_eq!( + stella_home::resolve_self_driving_root(Some(home.clone())), + Some(home.join("self-driving")), + "the shared resolver must still produce the directory this crate \ + writes and stella-observatory reads" + ); + } + /// The reader (`stella-observatory`) scans exactly the roots this migrates /// out of. Two hand-maintained copies drift: the dashboard would keep /// showing a loop the CLI had already moved, or miss one it had not.