diff --git a/docs/active-work.md b/docs/active-work.md index 147f568..625509f 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -414,13 +414,25 @@ compatible. - **DAP waits for Stage 2, not Stage 1** — that dependency is now satisfied. -## Test ambient-root isolation — FRAMING OPEN, revision 4 +## Test ambient-root isolation — IMPLEMENTATION OPEN -- **Branch `test-ambient-config-isolation`**, worktree - `../pmacs-test-isolation`, based on `githubsucks/main` @ `4cd4a7b`. - **Framing only; no code, no PR yet.** - `docs/test-ambient-config-isolation-framing.md` revision 4, three review - rounds closed (eight blocking, six major, all accepted). +- **Framing MERGED (#201)**; + `docs/test-ambient-config-isolation-framing.md` revision 4, three + review rounds closed (eight blocking, six major, all accepted). +- **Implementation branch `test-ambient-isolation-impl`**, worktree + `../pmacs-test-isolation-impl`, based on `githubsucks/main` @ + `54a092e`. The framing-only worktree `../pmacs-test-isolation` + (branch `test-ambient-config-isolation`) is spent — its doc is on + `main`. +- **What landed on the branch.** `pmacs::bootstrap::BootstrapRoots` + (config/data/state/cache, `ambient()` for production), reachable from + `EditorState::new_with_roots` **and** `open_with_roots` and consulted + again by `install_state_dirs`; all 342 in-process construction sites + in 65 files migrated; `journey_acceptance` keeps the ambient `open` + and re-execs itself per test with controlled roots instead; the shared + daemon and PTY spawners now set all five storage variables; + `tests/ambient_isolation_acceptance.rs` carries the hostile-environment + proof and the adoption ratchet. - **What it is.** Integration tests use the developer's real ambient roots. `#[cfg(not(test))]` guards config loading against the crate's own unit tests only, so the **65** files in `tests/` that construct an @@ -455,9 +467,9 @@ compatible. ```sh git fetch githubsucks - git worktree add ../pmacs-test-isolation \ - -b test-ambient-config-isolation \ - githubsucks/test-ambient-config-isolation + git worktree add ../pmacs-test-isolation-impl \ + -b test-ambient-isolation-impl \ + githubsucks/test-ambient-isolation-impl ``` ## Reap-ledger silent failures — MERGED (#202); kept for its parked follow-ons diff --git a/docs/agent-handoff.md b/docs/agent-handoff.md index d4542f4..ad61320 100644 --- a/docs/agent-handoff.md +++ b/docs/agent-handoff.md @@ -1639,6 +1639,35 @@ git diff --check Machine-specific caveats — re-verify on a machine you haven't used before trusting them: +- **Ambient storage roots: control all FIVE, not four.** Until the + ambient-root isolation lane lands + (`docs/test-ambient-config-isolation-framing.md`), the ~96 integration + suites read the developer's real `~/.config/pmacs/init.lua` and + **write** bundled packages into the real data root: + `#[cfg(not(test))]` guards the crate's own unit tests only, and + `EditorState::new` materializes packages outside every `cfg` guard. + A local full-suite run therefore needs, all pointed at a fresh + directory: + + ``` + XDG_CONFIG_HOME XDG_DATA_HOME XDG_STATE_HOME XDG_CACHE_HOME + PMACS_STATE_HOME + ``` + + **The fifth is not redundant.** `PMACS_STATE_HOME` outranks + `XDG_STATE_HOME` (`src/state.rs`), so redirecting the four XDG + variables on a machine that exports it leaves the real state root + live. `HOME` is deliberately left alone: it is the fallback for the + XDG roots (already covered once they are set) and separately drives + `~`-expansion, which `find_file_acceptance` pins on purpose. + A run isolating only `XDG_CONFIG_HOME` stops the `init.lua` reads and + still writes through the real data root — every local gate run in this + repo before 2026-07-31 had that hole. + + **After the lane lands** the in-process population isolates itself + through `EditorState::new_with_roots(&crate::iso::roots())` and the + five variables are belt-and-braces rather than required. + - **basedpyright**: the desktop binary was **never broken** — this was a real code defect, diagnosed and fixed 2026-07-29 (see §5, "A `Drop` body runs before its fields"). `RuntimeHandles::drop` joined its reader