docs: record the ambient-isolation lane and its five-variable rule

`docs/active-work.md`: the lane moves from FRAMING OPEN to
IMPLEMENTATION OPEN, with the implementation branch and worktree and a
recovery command that names them. The framing-only worktree is spent —
its doc is on `main` (#201).

`docs/agent-handoff.md` §3: a local full-suite run needs all FIVE
storage variables controlled, not four. `PMACS_STATE_HOME` outranks
`XDG_STATE_HOME`, so naming only the XDG four leaves a
higher-precedence state override live; and a run isolating only
`XDG_CONFIG_HOME` stops the `init.lua` reads while still writing through
the real data root — every local gate run in this repo before today had
that hole. `HOME` is deliberately excluded: it is the fallback the XDG
roots already cover once set, and it separately drives `~`-expansion,
which `find_file_acceptance` pins on purpose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
This commit is contained in:
Levi Neuwirth 2026-07-31 18:49:00 -04:00
parent fb14dc9ec3
commit 22925964d9
2 changed files with 50 additions and 9 deletions

View File

@ -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

View File

@ -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