diff --git a/docs/active-work.md b/docs/active-work.md index d9e3484..56454dd 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -57,17 +57,25 @@ If it does not, stop and repair the remote/fetch configuration. - Portable branch: `githubsucks/gpu-invocation` - Pull request: **#141 OPEN — do not merge without explicit user approval.** - Base: `githubsucks/main` @ `96d0bae`; protocol remains v19. -- Implementation checkpoint: `6fd5834` (approved Revision-4 framing is the - preceding `821835b`). -- State: implementation and all 18 acceptance criteria complete; awaiting user - review. Public path is additive `pmacs --gpu [--socket NAME|PATH]`; bare - `pmacs [FILE]` remains TUI and `pmacs --gpu FILE` remains rejected. -- Verification: strict workspace Clippy; 1,768 default + 1,944 CRDT library - tests; root CLI 33; GPU 145 required; GPU invocation acceptance 1 default + - 9 CRDT; Vterm Stage 3 7; M4 121 with 3 ignored and the requested - `basedpyright` skip; formatting and diff check clean. Unified release build - passed. Two real Wayland/Vulkan launches attached at protocol v19; the - second reused the daemon retained after the first GPU process exited. +- Implementation checkpoints: `82355ca` (first implementation-review fixes) + atop `6fd5834`; approved framing began at `821835b` and is now Revision 5. +- State: all six implementation-review findings are resolved, all 18 + acceptance criteria complete, and the PR awaits another user review. Public + path is additive `pmacs --gpu [--socket NAME|PATH]`; bare `pmacs [FILE]` + remains TUI and `pmacs --gpu FILE` remains rejected. +- Review fixes: pre-state GPU events are buffered until winit state exists; + daemon stderr is detached; spawned-child ownership is handed off without a + leak window; direct CLI guidance, help operands, and sibling-file discovery + are strict; transient retry, timeout reporting, hermetic socket paths, and + deterministic concurrent-loser reaping have behavioral coverage. +- Verification: strict workspace and CRDT acceptance Clippy; 1,768 default + + 1,944 CRDT library tests; root CLI 33; GPU 149 required; GPU invocation + acceptance 1 default + 9 CRDT; Vterm Stage 3 7; M4 121 with 3 ignored and + the requested `basedpyright` skip; full workspace 2,961 across 85 suites + with 19 ignored and 1 requested skip; formatting and diff check clean. + Unified release build passed. Two real Wayland/Vulkan launches attached at + protocol v19; the second reused the daemon retained after the first GPU + process exited. - Distribution remains source-checkout/workspace oriented: `pmacs-gpu` is still unpublished. No install/service packaging claim was added. diff --git a/docs/agent-handoff.md b/docs/agent-handoff.md index bc8c52d..305cf6c 100644 --- a/docs/agent-handoff.md +++ b/docs/agent-handoff.md @@ -24,14 +24,16 @@ commands, read `docs/active-work.md` immediately after this file. `ThemeFacts`, v17 = `FontFacts`, v18 = `StatuslineSegments`, v19 = terminal frames/events). - **One-command GPU invocation is implemented on OPEN PR #141, not yet on - `main`** (`gpu-invocation`, implementation checkpoint `6fd5834`, framing - Revision 4). The additive public path is `pmacs --gpu [--socket NAME|PATH]`; - bare `pmacs [FILE]` remains the TUI. Root owns the CRDT gate, socket - resolution, sibling-first GPU discovery/PATH fallback, and GPU outcome. - The separate `pmacs-gpu` binary owns connect-or-start, a five-second / - 50-ms retry window, daemon process-group isolation, and named child - reaping. Direct `pmacs-gpu --attach RAW_PATH` remains strict and never - auto-starts. No protocol change. + `main`** (`gpu-invocation`, implementation-review checkpoint `82355ca`, + framing Revision 5). The additive public path is + `pmacs --gpu [--socket NAME|PATH]`; bare `pmacs [FILE]` remains the TUI. + Root owns the CRDT gate, socket resolution, sibling-regular-file GPU + discovery/PATH fallback, and GPU outcome. The separate `pmacs-gpu` binary + owns connect-or-start, a five-second / 50-ms retry window, pre-winit event + buffering, daemon process-group/stdin/stdout/stderr isolation, and named + child reaping with explicit ownership handoff. Direct + `pmacs-gpu --attach RAW_PATH` remains strict, is documented as advanced, + and never auto-starts. No protocol change. - **Config registry LANDED — #127** (`docs/config-registry-framing.md` rev 3; merge `2e37c04`; two review rounds). `pmacs.config` is the typed, introspectable options registry the backlog ranked first, and diff --git a/docs/gpu-invocation-framing.md b/docs/gpu-invocation-framing.md index 799ad09..9946fd2 100644 --- a/docs/gpu-invocation-framing.md +++ b/docs/gpu-invocation-framing.md @@ -1,7 +1,7 @@ # GPU invocation — one-command broker framing -**Revision 4 — implemented on `gpu-invocation`. Ground truth: canonical -`main` @ `96d0bae`, protocol v19, 2026-07-23.** +**Revision 5 — implementation review complete on `gpu-invocation`. Ground +truth: canonical `main` @ `96d0bae`, protocol v19, 2026-07-23.** The GPU editor works, but reaching it is still a development-session ritual: build two packages with different feature requirements, keep a foreground @@ -35,6 +35,13 @@ managed connector, process-group isolation, named child reaper, deterministic managed probe, acceptance suite, coherent workspace build, and one-command visible smoke are implemented and verified. +Revision 5 closes the first implementation review. Managed attach now buffers +messages that arrive before winit creates application state, spawned-daemon +ownership remains local until the named reaper accepts it, and the daemon +inherits no launcher stdio. Direct GPU help points normal users to the root +broker and labels raw socket attach as advanced. The retry, timeout, socket +type, and concurrent-loser contracts now have deterministic behavioral tests. + ## Ground truth ### Current user path @@ -547,8 +554,10 @@ Vterm probe continues to cover offscreen wgpu. does not weaken the gate, and fake GPU/daemon executables record zero invocations. The default socket remains unowned. 3. **Sibling discovery wins:** with executable fixtures at the current-exe - sibling and on PATH, the sibling receives the managed arguments. Removing - it uses PATH. With neither, the error names both lookup attempts. + sibling and on PATH, the sibling regular file receives the managed + arguments. A directory at the sibling pathname is ignored in favor of + PATH. With neither executable available, the error names both lookup + attempts. 4. **Existing daemon fast path:** start a real CRDT daemon on a private socket, run `--headless-managed-probe`, and assert a v19 session establishes and a real `BufferSnapshot` arrives without invoking the supplied daemon spawner. @@ -563,10 +572,11 @@ Vterm probe continues to cover offscreen wgpu. session remain usable. This does not require a controlling terminal or a foreground-process-group claim in CI. Direct foreground `pmacs --daemon` still exits cleanly on SIGINT. -7. **Concurrent launchers converge:** start two managed probes together on an - absent named socket. Exactly one daemon owns the lock; both clients - establish sessions; the losing daemon child is reaped rather than becoming - a zombie or aborting its frontend. +7. **Concurrent launchers converge:** hold two daemon wrappers behind a shared + barrier so both managed probes authorize and spawn before either daemon + binds the absent named socket. Exactly one daemon owns the lock; both + clients establish sessions; exactly one probe reports its losing daemon + child reaped rather than leaving a zombie or aborting its frontend. 8. **Stale socket recovery stays daemon-owned:** leave a stale Unix socket with no lock owner, launch managed GPU, and assert the daemon replaces it and the frontend attaches. The launcher itself performs no unlink. @@ -574,9 +584,11 @@ Vterm probe continues to cover offscreen wgpu. permission-denied initial socket path invokes no daemon spawner and reports the path/error immediately. A regular file at the socket path survives unchanged, invokes no daemon, and reports that managed startup refuses to - replace a non-socket entry. An injected post-spawn sequence of - `Interrupted`, `WouldBlock`, then a successful real connection stays - within the deadline and establishes the session. + replace a non-socket entry. A unit connector injects post-spawn + `Interrupted`, `WouldBlock`, then a successful real `UnixStream::connect` + inside a private temporary directory; it stays within the deadline, + establishes the protocol session, and hands the spawned child to the + reaper. 10. **Live capability mismatch is not replaced:** against a non-CRDT daemon, managed launch reports the existing capability mismatch, invokes no second daemon, and leaves the live daemon untouched. @@ -585,9 +597,10 @@ Vterm probe continues to cover offscreen wgpu. invokes no daemon spawner, and leaves the listener/path untouched. 12. **Bounded startup failure:** substitute a daemon executable that exits nonzero without binding. Managed GPU exits after five seconds (50 ms - polls) and reports socket + child status. A concurrent-winner fixture - proves an early losing-child exit does not abort while another process - binds before the deadline. + polls) and reports socket + child status. Unit tests with a one-millisecond + deadline assert the configured duration appears in `StartupTimeout`. + A concurrent-winner fixture proves an early losing-child exit does not + abort while another process binds before the deadline. 13. **Post-attach daemon exit is reaped:** let the spawned daemon establish a managed session, wait for the probe's `phase=ready`, then terminate the daemon while keeping the probe's stdin open. Poll the atomically replaced @@ -598,11 +611,13 @@ Vterm probe continues to cover offscreen wgpu. succeed; fake nonzero and spawn failure make it fail with the executable named. 15. **GPU argv is strict without breaking probes:** bare invocation points to - `pmacs --gpu`; direct `--attach PATH`, existing - `--headless-probe SOCKET REPORT`, and hidden - `--headless-managed-probe SOCKET REPORT DAEMON_EXE` accept exactly their - operands. Missing/trailing/unknown/incomplete args exit 2. `--version` - prints package and protocol versions without initializing winit/wgpu. + `pmacs --gpu`; `--help` leads with normal root-broker usage and labels + direct `--attach PATH` as advanced. Existing `--headless-probe SOCKET + REPORT` and hidden `--headless-managed-probe SOCKET REPORT DAEMON_EXE` + accept exactly their operands. Missing/trailing/unknown/incomplete args + exit 2; trailing help/version operands say those flags accept no operands. + `--version` prints package and protocol versions without initializing + winit/wgpu. 16. **Existing direct and Vterm paths remain intact:** rebuilt `pmacs-gpu --attach RAW_PATH` still renders an existing CRDT daemon, and `tests/vterm_stage3_acceptance.rs` still invokes its unchanged @@ -625,29 +640,36 @@ Vterm probe continues to cover offscreen wgpu. socket resolution, test override, sibling-first GPU discovery with PATH fallback, child argv, and exit-status propagation. - `pmacs-gpu/src/main.rs` accepts only explicit direct, managed, and headless - modes. Managed windowed attach completes before winit creates a window. - Bare invocation is an exit-2 usage error pointing users to `pmacs --gpu`. + modes. Managed windowed attach completes before winit creates a window; + decoded messages arriving first are buffered and drained in order once + application state exists. Bare invocation is an exit-2 usage error pointing + users to `pmacs --gpu`; help labels raw-socket attach as advanced. - `pmacs-gpu/src/attach.rs` owns connect-or-start policy, the five-second / 50-ms retry window, socket-type protection, daemon process-group isolation, - and the named child-reaper thread. The first successful protocol connection - wins; protocol/capability failures never authorize replacement. + and the named child-reaper thread. A spawned child stays owned by the + connector until it is handed to that reaper, and daemon stdio is null. The + first successful protocol connection wins; protocol/capability failures + never authorize replacement. - `--headless-managed-probe SOCKET REPORT DAEMON_EXE` drives the production managed connector, writes atomic `phase=ready` / `phase=complete` reports, holds on stdin, and exposes disconnect plus daemon-reaper observations. - `tests/gpu_invocation_acceptance.rs` covers the root broker, non-CRDT gate, existing/missing/stale/racing daemon paths, process-group SIGINT isolation, - capability and protocol mismatches, bounded startup failure, child reaping, - outcome propagation, and strict headless CLI behavior. + capability and protocol mismatches, bounded startup failure, deterministic + losing-child reaping, outcome propagation, and strict headless CLI behavior. -Verification on 2026-07-23: +Verification on 2026-07-23 after the implementation review: - root CLI unit suite: 33 passed; -- required GPU suite: 145 passed; +- required GPU suite: 149 passed; - managed invocation acceptance: 1 default + 9 CRDT passed; - Vterm Stage 3: 7 passed with `PMACS_REQUIRE_GPU=1`; - default / CRDT libraries: 1,768 / 1,944 passed; - M4 acceptance: 121 passed, 3 ignored, 1 requested skip; -- strict workspace Clippy and formatting passed; +- full workspace sweep: 2,961 passed across 85 suites, 19 ignored, 1 requested + skip; +- strict workspace Clippy, CRDT invocation-acceptance Clippy, formatting, and + `git diff --check` passed; - the documented release workspace build and `cargo run --release -- --version` passed; - two real `target/release/pmacs --gpu` launches on Wayland/Vulkan attached at