Commit Graph

12 Commits

Author SHA1 Message Date
Levi Neuwirth fb14dc9ec3 test(isolation): migrate the corpus off the ambient roots
The mechanical half, riding on the census in the previous commit.

* 342 in-process construction sites in 65 files now take
  `new_with_roots` / `open_with_roots` with `iso::roots()`. The isolated
  base is a pure function of `CARGO_TARGET_TMPDIR` — no counter, no
  `OnceLock` — so two copies of the module in one binary agree instead of
  racing, and the tree lives somewhere `cargo clean` owns rather than
  leaking into `/tmp` once per run. It is shared deliberately:
  materialization is content-gated and idempotent, so a per-test
  directory would repeat it ~330 times per run for a byte-identical
  result.

* `journey_acceptance` keeps the ambient `EditorState::open`, because
  proving the production entry point has a caller is the whole of what
  that ratchet is for. Rev 2's "isolated by the environment its binary is
  launched with" was not a mechanism — cargo launches each test binary
  with the caller's environment, and a binary cannot re-point its own
  roots before its tests run. Each test is now a thin parent that
  re-execs this binary for its own name with controlled roots, and the
  child runs the body against production's call. Two pins guard it: the
  child asserts all four roots resolve inside the controlled base, and
  the suite asserts against its own source that it has not quietly taken
  the seam. The parent also asserts the child ran `1 passed` — a stale
  `--exact` filter would otherwise hollow the whole thing out silently.

* The shared spawners take all five storage variables.
  `spawn_daemon_process_with_env` set `HOME` and `XDG_CONFIG_HOME` only;
  `HOME` is a FALLBACK, so it isolates a root only while the matching
  `XDG_*` is unset — the harness's apparent adequacy was a property of
  one developer's environment. The PTY spawner backfills whichever of the
  five its caller did not pin. The 10 direct `Command::new` daemon and
  attach spawns get the same treatment.

Three suites had `mod common;` behind `#[cfg(feature = "crdt")]`;
`common::iso` is needed in every build, so those are ungated. Files that
already pull in `common` reach `iso` through a `use` rather than a second
`#[path]` declaration — loading one file as two modules is
`clippy::duplicate_mod`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
2026-07-31 18:48:45 -04:00
Levi Neuwirth d03845e826 feat(bottom-panel): activate protocol v21 by frontend counter-offer
Bottom-panel Stage 2B-3, part 1 of 3: the compatibility-preserving v21
activation mechanism and the negotiated `panel_capable` flip.

2B-1 reserved the v21 wire and 2B-2 built the daemon projection behind
it, both dark, because the handshake is server-first: the daemon writes
`Hello` before the frontend has said anything, and a frontend rejects a
`protocol_version` outside its supported range *before* it can send
`AttachRequest`. Advertising 21 there is therefore an incompatible act on
its own, independent of whether one new message is ever exchanged.

So the advertised version does not move. `ADVERTISED_PROTOCOL_VERSION`
becomes a permanent compatibility BASELINE, and the session's real
version is settled one message later, by the frontend:

  1. the daemon advertises the baseline (20, unchanged);
  2. the frontend answers `requested_protocol_version(baseline)` — its
     own `PROTOCOL_VERSION` when the baseline is the current one, and a
     verbatim echo of anything older;
  3. the daemon records `negotiated_session_version(offer)`.

A shipped v20 frontend echoes 20 and gets a v20 session, byte-for-byte
as before — the real-daemon acceptance that emulates its rejection point
still passes untouched. A current frontend offers up and gets v21. The
`Hello` encoding and value are unchanged, which is why the old frontend
never sees a version it must reject.

`peer_declared_panel_support` gains the arm 2B-2 deliberately left off:
a semantic session is panel-capable exactly when it negotiated
`PANEL_MIN_VERSION` or later. The gate is on placement, not only
transport, so a v6-v20 semantic session keeps the Stage 1 fallback.

The GPU client's `server_protocol_version` splits into
`session_protocol_version` (what the session speaks — every wire gate
keys on this) and `baseline_protocol_version` (what `Hello` advertised).
They now differ in the normal case, and that difference IS the
compatibility property, so both headless probe reports emit both keys and
the two ratchets that read them assert both directions: session 21 AND
baseline 20. Asserting only the session version would pass if the
baseline had been bumped too — the exact incompatible change this
mechanism avoids.

Also fixes a pre-existing `unused_mut` in a `crdt`-gated daemon test,
dark to the standard clippy gate because that gate runs without the
feature.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
2026-07-29 17:42:08 -04:00
Levi Neuwirth ab7c207904 Keep the v21 panel wire dark for v20 clients
Reserve the additive v21 panel schema without advertising it in the
server-first production handshake. Pin a real shipped-v20 client attach,
make the two aggregate-budget ratchets exactly one byte over, and update
the framing, coherence audit, handoff, and volatile lane record.
2026-07-28 14:08:17 -04:00
Levi Neuwirth dc2dc42627 test(journey): retain daemon cleanup while awaiting dired
Capture the managed daemon's lifecycle facts from the ready report before
waiting for the post-quiescence directory snapshot. If that regression
assertion times out, the acceptance harness can now terminate the daemon
instead of leaving it orphaned.
2026-07-28 11:02:48 -04:00
Levi Neuwirth 34b8f28cf2 test(journey): ratchet the public GPU directory path
Drive pmacs --gpu . through the root broker and real managed GPU
connector, keep the session alive through the asynchronous dired
replacement, and assert its canonical listing before daemon reuse.

Expose snapshot count and materialized text through the private
display-less acceptance probe so the public path is observable.
2026-07-28 10:27:22 -04:00
Levi Neuwirth ec4191fd8e test(journey): pin post-quiescence GPU dired surface
Consume the directory session's later replacement snapshot and assert
the canonical dired header plus a known listing entry before checking
daemon reuse.

Correct the bottom-panel revision-5 recovery branch and advance the
durable handoff to the Journey Stage 1a main anchor.
2026-07-28 09:48:48 -04:00
Levi Neuwirth 486ce16748 test(journey): ratchet directory GPU bootstrap success
Replace the stale directory-negative in the GPU initial-target suite
with an explicit snapshot-first readiness path, while retaining all
genuinely malformed and unloadable failure cases. Record the portable
side-quest and bottom-panel dependency state.
2026-07-27 22:53:36 -04:00
Levi Neuwirth be8c67c30c fix(daemon): contain failed target sessions
Shut down bootstrap sockets on every dispatcher-side failure and reject
frontend events whose session state was never installed. This prevents a
lingering failed client from reaching absent render/size state.

Track target-side CRDT upgrades independently from load/create status so a
deduplicated hidden buffer is published to every existing grid replica. Add
real-daemon regressions for both failure containment and replica publication.
2026-07-24 10:10:31 -04:00
Levi Neuwirth 2dd30ec730 Implement session-scoped GPU initial targets
Add protocol-v20 semantic bootstrap and readiness result framing so
`pmacs --gpu FILE` opens the requested path before the GPU window becomes
ready. Keep target identity scoped to the authenticated frontend, preserve
legacy/no-target attach behavior, and publish fresh buffers coherently to
existing replicas.

Carry Unix path bytes and launcher cwd through the root broker, resolve paths
lexically in the daemon, reuse or create buffers without ambient-view state,
and preserve the managed daemon lifecycle from #141. Add focused parser,
wire, lifecycle, hook, isolation, and real-connector acceptance coverage.
2026-07-23 19:03:25 -04:00
Levi Neuwirth 154cb9f08d Close remaining GPU invocation review nits
Throttle the managed probe after its event channel closes, reject option-like
path operands, and document the connector test seam. Strengthen non-CRDT and
Ctrl-C acceptance so socket side effects and a pre-signal surviving frontend
are exercised, while avoiding cleanup signals to already-reaped daemon PIDs.
2026-07-23 12:38:11 -04:00
Levi Neuwirth 82355ca529 Address GPU invocation review findings
Buffer attach events until winit state exists, keep spawned daemon ownership
until the reaper handoff, and detach daemon stderr from the launcher terminal.
Tighten direct GPU CLI guidance and sibling discovery. Strengthen managed
connector unit and process acceptance coverage for transient retries, timeout
reporting, hermetic paths, and deterministic loser reaping.
2026-07-23 11:50:33 -04:00
Levi Neuwirth 6fd583417b Add one-command managed GPU invocation
Add the root --gpu broker, strict GPU entry points, daemon connect-or-start orchestration, process-group isolation, bounded retry, named child reaping, and a deterministic headless lifecycle probe. Cover the complete launch matrix with real subprocess acceptance, make root Cargo runs unambiguous, and document the coherent build and one-command workflow.
2026-07-23 11:02:09 -04:00