Commit Graph

4 Commits

Author SHA1 Message Date
Levi Neuwirth e1df0cff4d docs(tests): framing revision 4 — close review round 3
One blocking and two major findings, all accepted.

- The isolated gate still inherited `PMACS_STATE_HOME`, which wins over
  `XDG_STATE_HOME` in `user_state_dir` (`src/state.rs:47-68`), so
  controlling the four XDG storage variables did not isolate state on a
  machine that exports it. The contract now names the exact five
  variables rather than counting roots.
- Q#TI5 still called self-spawn the durable regression guard after
  revision 3 had accepted that it proves behaviour, not continued
  adoption. It now names both guards and their different jobs: self-spawn
  is the behavioural proof, the checked source inventory is the adoption
  proof.
- The active-work lane still said revision 2 and still prescribed an
  isolated `XDG_CONFIG_HOME` alone; both are synchronized, and the stale
  config-only gating note elsewhere in the ledger is corrected to say it
  isolates the observed symptom rather than the gate.

Framing only. No code.
2026-07-30 13:57:02 -04:00
Levi Neuwirth e9613c7d94 docs(tests): framing revision 3 — close review round 2
Three blocking and two major findings, all accepted. Two were verified
by running the thing rather than reading it.

- **Journey isolation had no executable mechanism.** Cargo launches each
  integration-test binary with the caller's environment, and a binary
  cannot re-point its own roots before its tests run — the `set_var`
  prohibition applies to itself. Revision 2's "isolated by its launched
  environment" therefore assumed the external wrapper this lane exists
  to delete. Now named and pinned: each journey test re-execs
  `current_exe()` with `--exact`, a marker, and controlled roots; the
  child runs the real body against the ambient `EditorState::open`, so
  the production-entry-point ratchet is untouched while the roots are
  contained. The same helper serves the hostile-environment check.
- **One self-spawning test is not a ratchet.** It proves the seam works
  and cannot notice a raw `EditorState::new()` added to another binary
  later. A checked source inventory, falsifiable by adding an ambient
  constructor, is now acceptance 12.
- **The root list and the gates disagreed with the audit.** The scope is
  now explicit — bootstrap STORAGE roots only (config, data, state,
  cache). `HOME`'s non-storage semantics are excluded by decision, not
  omission: `expand_tilde` resolves user-entered `~` and
  `find_file_acceptance` pins it deliberately, so redirecting `HOME`
  would retarget a user-facing feature. `XDG_RUNTIME_DIR` addresses
  sockets, not stored data.
- **The gate instruction itself was insufficient**, and this is the
  finding with immediate consequences: isolating only `XDG_CONFIG_HOME`
  stops the reads and leaves the write path open. Every local gate run
  in this repository today had that hole.
- **The count was one high and the ledger overstated it further.** 65
  files call the constructor; 66 mention it. The 66th, `m5_6_acceptance`,
  mentions it only to say it deliberately does not use it — making it
  the third place in the suite documenting the `cfg(test)` gap. The
  ledger's "all 96 test files load the real config" was false.
- **The recovery command did not work**, verified by running it:
  `git worktree add <path> <remote-only-branch>` fails with `fatal:
  invalid reference` after a bare fetch. Replaced with the explicit
  tracking-branch form.

Framing only. No code.
2026-07-30 13:45:15 -04:00
Levi Neuwirth f2071ea022 docs(tests): framing revision 2 — close review round 1
Four blocking and two major findings, all accepted, all verified in the
code before acceptance. The lane's scope changes: it is about ambient
roots, not about init.lua.

- The read-only assumption was already false. `EditorState::new`
  materializes bundled packages unconditionally and before config
  loading, into `XDG_DATA_HOME` or `$HOME/.local/share`, and
  `materialize_all` creates directories. Confirmed on the development
  machine: `~/.local/share/pmacs/builtin-packages/` exists with v0.1.0
  and v1.0.0. This upgrades the lane from "local gates lie" to "tests
  write into real user data".
- The population count was wrong and its stated method did not match the
  command that produced it: 18 from a grep for `Editor::new`, which does
  not match the real constructor `EditorState::new`. 66 of 96 files
  construct an editor directly.
- File-level classification cannot work: 5 files are both in-process and
  spawned. Classification moves to construction sites.
- The seam must cover `EditorState::open`, which calls `Self::new()`
  directly, while `journey_acceptance` requires that exact public entry
  point to avoid a dead-production-path test. Resolved by isolating
  journey through its launched environment rather than a different call.
- Isolated construction must still return `is_init_complete() == true`.
  Config loading and `set_init_complete()` share one block, and
  `m8_2_acceptance.rs:75` documents its dependence on integration-test
  construction being init-complete — the `cfg(test)` gap is load-bearing
  in that one respect.
- Revision 1 both proposed and parked a hostile-config CI leg. Resolved
  in favour of a test-binary self-spawn, which travels with the test
  rather than the workflow file, and which now also asserts the hostile
  root is unmodified afterwards.
- The lane is recorded in `docs/active-work.md`, which revision 1 omitted
  despite the volatile-work protocol requiring it.

Also documents six ambient roots where the shared daemon harness sets
two, and why setting HOME only isolates a root whose XDG variable is
unset — the harness's apparent adequacy is a property of one developer's
environment.

Framing only. No code.
2026-07-30 13:36:23 -04:00
Levi Neuwirth 89ee2f9985 docs(tests): frame the ambient-config isolation defect
Integration tests read the developer's real `~/.config/pmacs/init.lua`.
The suite is green in CI and deterministically red on any machine with a
real config, attributed to whatever branch is checked out — 11 of 67 in
`compile_mode_acceptance` on 2026-07-30, 67/67 with an isolated
`XDG_CONFIG_HOME`.

The mechanism is that `src/editor.rs:770` guards config loading with
`#[cfg(not(test))]`, which is set only when compiling the crate's own
unit tests. An integration test links pmacs as an ordinary dependency, so
the guard is inactive for all 96 of them. The hazard was identified and a
mitigation was written; its scope does not match the threat.

The obvious fix is unavailable: `std::env::set_var` is unsafe and the
crate forbids unsafe, which the repo already knows —
`Installer::root_override` exists for exactly this reason.

Framing only, awaiting review round 1. No code changes.
2026-07-30 13:14:58 -04:00