Merge pull request #238 from levineuwirth/docs-absorb-237
docs: absorb #236 and #237 — anchors to d038f71, recovery procedure re-run
This commit is contained in:
commit
4f77491bca
|
|
@ -136,7 +136,11 @@ lesson, §1 for the two framings).
|
||||||
are identical on every machine. Remote names are otherwise
|
are identical on every machine. Remote names are otherwise
|
||||||
machine-local: `origin` may name this canonical URL, a release mirror,
|
machine-local: `origin` may name this canonical URL, a release mirror,
|
||||||
or something else, and therefore has no authority by name alone.
|
or something else, and therefore has no authority by name alone.
|
||||||
- Canonical base at this snapshot: **`githubsucks/main` @ `e67ad07`** —
|
- Canonical base at this snapshot: **`githubsucks/main` @ `d038f71`** —
|
||||||
|
**GUI Stage 1-pre #237**, the input seam (`App::window_event` from 655
|
||||||
|
lines to four; no behaviour change, no wire change), atop `f8ad3e7`
|
||||||
|
**GUI arc Stage 0 #236**, the arc framing and its documentation sweep.
|
||||||
|
Beneath them `e67ad07`,
|
||||||
the file-watcher arc absorption, atop `122b8e8`
|
the file-watcher arc absorption, atop `122b8e8`
|
||||||
the file-watcher D3 **#235** (closes issue #233), atop `b867f64`
|
the file-watcher D3 **#235** (closes issue #233), atop `b867f64`
|
||||||
git integration Stage 1 **#227**, atop `ae84d58` the LSP file-watcher
|
git integration Stage 1 **#227**, atop `ae84d58` the LSP file-watcher
|
||||||
|
|
@ -173,7 +177,7 @@ lesson, §1 for the two framings).
|
||||||
where they describe a stage as it landed** — only this
|
where they describe a stage as it landed** — only this
|
||||||
current-state paragraph tracks the live range.
|
current-state paragraph tracks the live range.
|
||||||
**The recovery floor advances with the base**, so the check below
|
**The recovery floor advances with the base**, so the check below
|
||||||
now requires **`e67ad07`** or newer; a tree at `db1bbe9` no longer
|
now requires **`d038f71`** or newer; a tree at `db1bbe9` no longer
|
||||||
passes — it would lack the entire QoL arc, which this file and the
|
passes — it would lack the entire QoL arc, which this file and the
|
||||||
handoff both describe as complete. That is deliberate — a check accepting an older commit than
|
handoff both describe as complete. That is deliberate — a check accepting an older commit than
|
||||||
the declared base passes on a tree the rest of this file does not
|
the declared base passes on a tree the rest of this file does not
|
||||||
|
|
@ -213,28 +217,44 @@ git worktree list
|
||||||
git status --short --branch
|
git status --short --branch
|
||||||
```
|
```
|
||||||
|
|
||||||
The `git log` command must expose `e67ad07` — the base named above — or a
|
The `git log` command must expose `d038f71` — the base named above — or a
|
||||||
newer intentional main. Keep this threshold and the canonical-base line in
|
newer intentional main. Keep this threshold and the canonical-base line in
|
||||||
step: a recovery check that accepts an older commit than the base it
|
step: a recovery check that accepts an older commit than the base it
|
||||||
declares canonical will pass on a tree the rest of this file does not
|
declares canonical will pass on a tree the rest of this file does not
|
||||||
describe.
|
describe.
|
||||||
If it does not, stop and repair the remote/fetch configuration.
|
If it does not, stop and repair the remote/fetch configuration.
|
||||||
|
|
||||||
**LAST EXERCISED AT `9a26ac8`, 2026-08-08** — re-run from an empty
|
**LAST EXERCISED AT `d038f71`, 2026-08-12**, from an empty directory
|
||||||
directory rather than having its SHA swapped. **The advance to
|
rather than by having its SHA swapped — **which also discharges the
|
||||||
`e67ad07` (2026-08-11) has NOT been re-exercised**, and by this
|
outstanding obligation this paragraph carried at `e67ad07`**, where the
|
||||||
paragraph's own argument that is exactly when the exercise matters, so
|
base advanced without the procedure being re-run. That debt is settled,
|
||||||
it is recorded as an outstanding obligation rather than left to read as
|
not inherited: the advance recorded here was exercised as part of making
|
||||||
though it had been done. The floor above and the check below are in
|
it.
|
||||||
step at `e67ad07`; what is unverified is the *procedure* against that
|
|
||||||
base, not the SHA. That distinction is the
|
Every documented step ran, in order, on git **2.55.0**:
|
||||||
whole point of this paragraph: advancing the base is exactly when the
|
|
||||||
recovery commands are most likely to have rotted, and a swapped SHA
|
1. `git clone` the canonical URL into an empty directory. The clone
|
||||||
reads identically to a verified one. `git clone` the canonical URL, add
|
names it `origin`; **`git remote get-url githubsucks` errors with
|
||||||
the `githubsucks` alias, `git fetch githubsucks --prune`, confirm
|
`No such remote`**, exactly as the section above anticipates.
|
||||||
`9a26ac8` is an ancestor of `githubsucks/main`, and recover with the
|
2. Add the alias, confirm the URL, `git fetch githubsucks --prune`.
|
||||||
three-argument `git worktree add <path> -b <local> githubsucks/<branch>`
|
3. `git log -1 --oneline githubsucks/main` → `d038f71`.
|
||||||
form. All four steps ran clean.
|
4. **The floor check, run against the OLD DECLARED FLOOR and the new
|
||||||
|
one**: `e67ad07` and `d038f71` are each an ancestor of the tip, so
|
||||||
|
advancing the floor is valid rather than merely plausible.
|
||||||
|
*(`9a26ac8` is the previous last-EXERCISED anchor, which is a
|
||||||
|
different thing from the previous declared floor — the two had
|
||||||
|
drifted apart, and checking the exercised anchor in the floor's place
|
||||||
|
would have verified the wrong claim.)*
|
||||||
|
5. The three-argument `git worktree add <path> -b <local>
|
||||||
|
githubsucks/<branch>` form → a real branch with its upstream set
|
||||||
|
(`## recovered-local...githubsucks/gui-stage1-pre`).
|
||||||
|
6. **The documented trap, reproduced rather than assumed**: the
|
||||||
|
two-argument form on a remote-only branch **succeeds** and leaves
|
||||||
|
`## HEAD (no branch)`. The correction below still holds on 2.55.0.
|
||||||
|
|
||||||
|
That distinction is the whole point of this paragraph: advancing the
|
||||||
|
base is exactly when the recovery commands are most likely to have
|
||||||
|
rotted, and a swapped SHA reads identically to a verified one.
|
||||||
|
|
||||||
**Correction, found by re-running it.** This file claimed the
|
**Correction, found by re-running it.** This file claimed the
|
||||||
two-argument form fails for a remote-only branch with `fatal: invalid
|
two-argument form fails for a remote-only branch with `fatal: invalid
|
||||||
|
|
@ -250,186 +270,91 @@ hazard in a shape that looks committed. **A documented error message
|
||||||
that never appears is worse than no documentation**, because the reader
|
that never appears is worse than no documentation**, because the reader
|
||||||
waits for a signal that is not coming.
|
waits for a signal that is not coming.
|
||||||
|
|
||||||
## GUI arc Stage 1 — 1-pre OPEN as PR #237
|
## GUI arc Stage 1 — 1-pre MERGED as #237 (`d038f71`); 1a is next, NOT STARTED
|
||||||
|
|
||||||
**Written at the branch's first commit**, with the framing, as the arc's
|
**The lane is rewritten, not removed.** Rule 4 removes a lane when its
|
||||||
§5 requires of every PR in it.
|
ARC is done, and the arc is Stage 1 as a whole: **five slices remain**.
|
||||||
|
|
||||||
- **PR #237** — https://github.com/levineuwirth/pmacs/pull/237.
|
|
||||||
- **Branch `gui-stage1-pre`**, base `githubsucks/main` @ `f8ad3e7` (the
|
|
||||||
Stage 0 merge, #236). **`githubsucks/gui-stage1-pre` is the
|
|
||||||
authoritative tip** — the ref, not a SHA. Recover with
|
|
||||||
`git fetch githubsucks && git checkout gui-stage1-pre`.
|
|
||||||
- **Framing `docs/gui-stage1-input-framing.md`, revision 11, APPROVED**
|
- **Framing `docs/gui-stage1-input-framing.md`, revision 11, APPROVED**
|
||||||
after **eight rejected revisions**. Revision 9 is the approved design;
|
after eight rejected revisions. It is Stage 1's framing for **all**
|
||||||
revision 10 recorded a scope correction found against this
|
slices and governs every later branch; only Stage 0 was framed by the
|
||||||
implementation and **also argued P2 was satisfied by classification
|
arc document itself. Revision 9 is the approved design; 10 recorded a
|
||||||
alone, which review overturned — revision 11 retracts it**. It is
|
scope correction found against the 1-pre implementation; **11 retracts
|
||||||
Stage 1's framing for **all** slices and governs the later branches;
|
10's claim that P2 was satisfied by route classification alone**, and
|
||||||
only Stage 0 was framed by the arc document itself.
|
corrects the Stage 1a consequence 10 got wrong.
|
||||||
- **Scope of THIS branch: 1-pre only — the input seam. No behaviour
|
- **Slice order, each its own branch and PR:** ~~`1-pre`~~ → **`1a`**\* →
|
||||||
change.** `App::window_event` was **655 lines** and is now **four** —
|
`1b` → `1c` → `1d` → `1e`\*. **`1a` and `1e` are the two
|
||||||
call `dispatch_window_event`, exit if it asks. The dispatch it calls
|
protocol-bearing slices — v24 `TextInput` and v25
|
||||||
is one `route_event` call and one arm per route. Nothing below it
|
`OpenTarget`/`OpenTargetResult` — and they are SERIALIZED** against
|
||||||
could be witnessed without a display, which is why the seam precedes
|
each other and against every other wire change in the project. 1c is
|
||||||
every other slice.
|
**not** protocol-bearing, under Q#S1-8.
|
||||||
- **IMPLEMENTED in four commits, one per event family**, so each lands
|
- **NEXT: 1a, and nothing of it exists yet** — no branch, no code. It
|
||||||
with its own witnesses and mutations rather than as one 600-line
|
carries the **v24** `TextInput` variant, so it must run alone.
|
||||||
diff: `014110f` lifecycle (close / modifiers / resize), `7f0f9db`
|
`PROTOCOL_VERSION` is **23** at this base, and
|
||||||
redraw, `0705564` keyboard, `e955645` the four pointer arms. Review
|
`ADVERTISED_PROTOCOL_VERSION` stays pinned at 20 and must not be
|
||||||
round 1 added `f976dc1`, the P2 effect harness.
|
edited to chase it. Its nine contracts (A1–A9) and the Q#S1-9
|
||||||
- **P2 HAS TWO HARNESSES, and the second was review round 1's blocker.**
|
precedence rules are in the framing; **A4 deletes the idle-Escape
|
||||||
The routing harness answers *where did this event go*; `EffectHarness`
|
local quit**, which is **pre-existing behaviour, not something 1-pre
|
||||||
answers *what did it do*. Classification alone could not satisfy P2 —
|
introduced** — 1-pre preserved it and moved it behind an
|
||||||
**a wheel route carries a delta, and whether that becomes a viewport
|
`EventOutcome` return, and 1a removes it. `EventOutcome` survives that
|
||||||
update, a panel event, a terminal event or nothing depends on
|
removal: the native close still returns `Exit`.
|
||||||
`State`.** The effect harness drives a real `AttachClient` over a
|
|
||||||
`socketpair` (real handshake, outbox, writer thread and encoder, so
|
|
||||||
the transcript is the wire), a real windowless `State`, and
|
|
||||||
`App::dispatch_window_event`.
|
|
||||||
- **`App::dispatch_window_event` is what made P2 reachable.** Left inside
|
|
||||||
`window_event`, the dispatch would force the harness to re-implement
|
|
||||||
it, and a harness that re-implements what it tests witnesses its own
|
|
||||||
copy. `window_event` is now **four lines**, so **P3 shrinks from a
|
|
||||||
33-line match to a single `if`**.
|
|
||||||
- **Steps are delimited by a non-coalesceable sentinel key, not a
|
|
||||||
sleep** — otherwise "this step sent nothing" is undecidable without
|
|
||||||
waiting, and a fixed-duration wait against a writer thread is exactly
|
|
||||||
the core-count assumption behind PR #235's CI red.
|
|
||||||
- **The effect rows never skip**: a missing wgpu adapter is an assertion
|
|
||||||
failure. M21 confirms all **nine** effect rows fail loudly while the
|
|
||||||
**thirteen** GPU-free routing rows stay green. The assert is
|
|
||||||
**unconditional**, not `PMACS_REQUIRE_GPU`-gated, so no invocation
|
|
||||||
anywhere can turn a missing adapter into a quiet `ok`.
|
|
||||||
- **They execute in exactly ONE CI job, and that is checked rather than
|
|
||||||
assumed.** `cargo metadata` reports `workspace_default_members` as the
|
|
||||||
root `pmacs` package alone, so the `test` matrix and `crdt-test` —
|
|
||||||
both bare `cargo test --all-targets` — never compile `pmacs-gpu`'s
|
|
||||||
unit tests at all. Only **`gpu-render`** runs them, and it installs
|
|
||||||
lavapipe, proves the adapter with `vulkaninfo`, and sets
|
|
||||||
`PMACS_REQUIRE_GPU=1`. This is the handoff's "`gpu-render` runs a
|
|
||||||
DIFFERENT PACKAGE" fact showing up as a dependency: these rows live or
|
|
||||||
die with that one job.
|
|
||||||
- **Three manufactured absences, all found by running the rows**, and
|
|
||||||
each the same shape: the harness withheld something production
|
|
||||||
supplies, then witnessed its own omission. `resumed` sets the frontend
|
|
||||||
id and session version before any geometry flush (the resize row);
|
|
||||||
the fixture document was two lines and could not scroll; a headless
|
|
||||||
`State` has no attached buffer, so `scroll_by_lines` returned `None`.
|
|
||||||
A fourth was a vacuous assertion — `.all(|e| matches!(..))` over an
|
|
||||||
empty transcript is true — caught by the outbound-blind mutation.
|
|
||||||
- **The shape.** Deciding is `route_event(&WindowEvent) -> Route`, a
|
|
||||||
free function composing one decision function per family
|
|
||||||
(`route_lifecycle`, `route_keyboard` + `route_key_action`,
|
|
||||||
`route_pointer`). Performing stays on `App` in seven `apply_*`
|
|
||||||
methods. A route carries the **decision**, not the effect: a wheel
|
|
||||||
route holds a delta, and whether that becomes a viewport update, a
|
|
||||||
panel event, a terminal event or nothing depends on `State`. Effects
|
|
||||||
are witnessed separately — see the P2 bullet below.
|
|
||||||
- **Every moved body verified as the original, mechanically.** The
|
|
||||||
keyboard body is byte-identical modulo two named conversions; the four
|
|
||||||
pointer bodies were checked by re-running rustfmt on the pre-move text
|
|
||||||
at the new indent level and diffing, since de-indenting by 8 columns
|
|
||||||
lets rustfmt rejoin lines. **22 witnesses — 13 routing, 9 effect — and
|
|
||||||
24 mutations, M1–M24.** Twenty-three fail their own rows; **M6 is the
|
|
||||||
P3 exception check and must stay green**.
|
|
||||||
- **P3 IS NOW MEASURED, NOT ASSUMED — and re-measured after the effect
|
|
||||||
harness landed.** Replacing `window_event`'s whole body with `let _ =
|
|
||||||
(event_loop, event);` — a GUI that responds to no input at all —
|
|
||||||
leaves **all 265 `pmacs-gpu` tests green** under `PMACS_REQUIRE_GPU=1`
|
|
||||||
at the current shape (it was 256 before the effect rows; the number is
|
|
||||||
re-run, not carried forward). That is the exception's true extent:
|
|
||||||
`ActiveEventLoop` cannot exist outside a live event loop, so **no**
|
|
||||||
headless test in the crate observes the delegation. What it covers is
|
|
||||||
now **one `if`**, not a 33-line match.
|
|
||||||
- **A SECOND ACCEPTED STRUCTURAL EXCEPTION, found here and winit's
|
|
||||||
rather than ours.** `KeyEvent` carries a `pub(crate)
|
|
||||||
platform_specific` field, so **no `WindowEvent::KeyboardInput` can be
|
|
||||||
constructed outside winit** and the keyboard family's routing arm
|
|
||||||
cannot be fed by a test. Bounded three ways: it does **not** extend to
|
|
||||||
the pointer families (`DeviceId::dummy()` exists for exactly this, and
|
|
||||||
all three pointer events are constructible — checked before writing
|
|
||||||
the exception down); the family's only real decision is factored into
|
|
||||||
`route_key_action(ElementState)` and witnessed directly; and what
|
|
||||||
stays unwitnessed is one pattern arm containing a match and a call.
|
|
||||||
- **The crate now has exactly ONE executable `event_loop.exit()`**, in
|
|
||||||
`window_event`. Bodies return an `EventOutcome` rather than taking an
|
|
||||||
`&ActiveEventLoop`, which is what keeps them reachable in principle.
|
|
||||||
**`EventOutcome` has TWO producers and they differ in kind**: a native
|
|
||||||
close (`LifecycleRoute::Exit`), which must always exit, and
|
|
||||||
`apply_keyboard`'s idle Escape, which is a local quit. **Stage 1a's A4
|
|
||||||
removes the keyboard producer only**, leaving **one** `Exit`
|
|
||||||
producer — the native close. **One producer is not one variant**:
|
|
||||||
`EventOutcome` survives because `dispatch_window_event` must still
|
|
||||||
distinguish `Continue` from `Exit` on every event, and only the close
|
|
||||||
exits. A4 changes `apply_keyboard`'s signature, not the type. An
|
|
||||||
earlier revision of this bullet claimed the type would collapse and
|
|
||||||
should go with the Escape branch; that was wrong.
|
|
||||||
- **Slice order (each its own branch and PR):** `1-pre` → `1a`\* → `1b`
|
|
||||||
→ `1c` → `1d` → `1e`\*. **`1a` and `1e` are protocol-bearing (v24
|
|
||||||
`TextInput`, v25 `OpenTarget`/`OpenTargetResult`) and are
|
|
||||||
SERIALIZED.** 1c is **not** protocol-bearing under Q#S1-8.
|
|
||||||
- **Q#S1-7 obligation carried by THIS PR:** Meta/Super policy moves to
|
|
||||||
Stage 2, so the arc framing's §2.5 and the standing backlog are
|
|
||||||
amended here. Stage 1 keeps the deliberate OS reservation and adds no
|
|
||||||
island.
|
|
||||||
- **Gates:** `./scripts/gate --acceptance gpu_invocation_acceptance`.
|
|
||||||
That one invocation already runs `PMACS_REQUIRE_GPU=1 cargo test -p
|
|
||||||
pmacs-gpu` (step `gpu`) and the full `--workspace --no-fail-fast`
|
|
||||||
sweep in both feature configurations, so the framing §11 phrase "plus
|
|
||||||
touched input suites" is satisfied by the sweep rather than by a
|
|
||||||
hand-picked list. **No `--protocol`** — 1-pre changes no wire.
|
|
||||||
- **THE FIRST GATE RUN WENT RED ON A STRAY `/tmp/.git`, NOT ON THIS
|
|
||||||
BRANCH.** `m4` and the sweep failed
|
|
||||||
`m4_24_bare_string_glob_stays_relative` and
|
|
||||||
`m4_24_d3_fallback_base_is_the_smallest_attachment_dir` — two LSP
|
|
||||||
file-watcher tests — with every other target green. Established as
|
|
||||||
environmental three ways, in increasing strength:
|
|
||||||
- **Structurally impossible for this branch to cause.** The branch
|
|
||||||
changes seven files, five of them under `docs/`; **the whole
|
|
||||||
executable diff is inside the `pmacs-gpu` crate**
|
|
||||||
(`src/main.rs` and `src/attach.rs`), and `pmacs-gpu` is a workspace
|
|
||||||
**member but not a dependency** of the root package, so the
|
|
||||||
`m4_acceptance` binary never links it.
|
|
||||||
- **The marker is older than the session.** `/tmp/.git` is empty and
|
|
||||||
was created at 20:14 CEST, **3.5 h before** the gate run at 23:45;
|
|
||||||
`/tmp` held 8,920 entries. That is handoff §1's recorded hazard
|
|
||||||
exactly.
|
|
||||||
- **A discriminating pair compared on SIGNATURE, not test name**, same
|
|
||||||
binary and commit, one variable — run as **four literal `--exact`
|
|
||||||
invocations, one test each**, since `m4_24_` is a prefix matching
|
|
||||||
**18** tests. Contaminated: `0 passed; 1 failed` each, panicking at
|
|
||||||
`m4_acceptance.rs:5668:5` and `:6615:5` with `.received = ""`,
|
|
||||||
**matching the gate red's own signature**. Clean: `1 passed; 0
|
|
||||||
failed` each, **zero panics**. The exact commands are in handoff
|
|
||||||
§1's hazard bullet. A rerun would have established only
|
|
||||||
intermittence; the pair establishes the cause.
|
|
||||||
|
|
||||||
**`scripts/gate` isolates the target dir and five ambient roots but
|
### What 1-pre landed, and the facts worth not re-deriving
|
||||||
NOT `TMPDIR`** — recorded in handoff §1, where the standing fix is
|
|
||||||
assigned to the gate lane rather than to this PR.
|
- **`App::window_event` went from 655 lines to four**: call
|
||||||
|
`dispatch_window_event`, exit if it asks. Deciding is
|
||||||
|
`route_event(&WindowEvent) -> Route`, composing one decision function
|
||||||
|
per family; performing is seven `apply_*` methods. **No behaviour
|
||||||
|
change, no wire change.**
|
||||||
|
- **A route carries the DECISION, not the effect.** A wheel route holds
|
||||||
|
a delta; whether that becomes a viewport update, a panel event, a
|
||||||
|
terminal event or nothing depends on `State`. This is why P2 needs a
|
||||||
|
second harness, and why revision 10's contrary argument was retracted.
|
||||||
|
- **Two harnesses.** `RoutingHarness` answers *where did this event go*
|
||||||
|
(13 rows, no GPU). `EffectHarness` answers *what did it do* (9 rows) —
|
||||||
|
a real `AttachClient` over a `socketpair` through the real handshake,
|
||||||
|
outbox, writer thread and encoder, a real windowless `State`, and the
|
||||||
|
production dispatch. **22 witnesses, 24 mutations M1–M24**;
|
||||||
|
twenty-three fail their own rows and **M6 is the P3 exception check,
|
||||||
|
which must stay green**.
|
||||||
|
- **`dispatch_window_event` is why P2 was reachable at all.** Left inside
|
||||||
|
`window_event`, the dispatch would force a harness to re-implement it,
|
||||||
|
and a harness that re-implements what it tests witnesses its own copy.
|
||||||
|
- **The sentinel is the success condition; the 30 s read ceiling is only
|
||||||
|
an error ceiling.** Steps are delimited by a non-coalesceable sentinel
|
||||||
|
key rather than a sleep, so absence is never inferred from duration —
|
||||||
|
but an unbounded blocking read would wedge the gate instead of
|
||||||
|
reddening it, and a hang looks like slowness until the job is killed.
|
||||||
|
- **TWO ACCEPTED STRUCTURAL EXCEPTIONS, both measured rather than
|
||||||
|
asserted.** **P3**: deleting `window_event`'s whole body leaves all
|
||||||
|
**265** `pmacs-gpu` tests green, so no headless test in the crate
|
||||||
|
observes the delegation — what it covers is now one `if`. **P1,
|
||||||
|
keyboard only, and winit's rather than ours**: `KeyEvent` carries a
|
||||||
|
`pub(crate) platform_specific` field, so **no
|
||||||
|
`WindowEvent::KeyboardInput` can be constructed outside winit**. It
|
||||||
|
does **not** reach the pointer families — `DeviceId::dummy()` exists
|
||||||
|
for exactly this and all three pointer events are constructible,
|
||||||
|
checked before the exception was written down.
|
||||||
|
- **`EventOutcome` survives A4, and one producer is not one variant.**
|
||||||
|
The crate has **exactly one** executable `event_loop.exit()`, in
|
||||||
|
`window_event`. A4 removes the keyboard `Exit` producer, leaving the
|
||||||
|
native close; the type stays because `dispatch_window_event` must
|
||||||
|
still distinguish `Continue` from `Exit` on every event. What A4
|
||||||
|
changes is `apply_keyboard`'s signature.
|
||||||
|
- **The effect rows execute in exactly ONE CI job**, checked with `cargo
|
||||||
|
metadata`: `workspace_default_members` is the root `pmacs` package
|
||||||
|
alone, so the `test` matrix and `crdt-test` — both bare `cargo test
|
||||||
|
--all-targets` — never compile `pmacs-gpu`'s unit tests. Only
|
||||||
|
**`gpu-render`** runs them, with lavapipe, `vulkaninfo` and
|
||||||
|
`PMACS_REQUIRE_GPU=1`. The harness's adapter assert is
|
||||||
|
**unconditional**, so a missing adapter can never become a quiet `ok`.
|
||||||
|
- **A stray `/tmp/.git` reddened the first gate run and had nothing to do
|
||||||
|
with this branch.** Established on signature, not test name, by four
|
||||||
|
literal `--exact` invocations; the marker was left in place and an
|
||||||
|
isolated `TMPDIR` used instead. **`scripts/gate` does not isolate
|
||||||
|
`TMPDIR`** — recorded in `docs/agent-handoff.md` §1, where the
|
||||||
|
standing fix is assigned to the gate lane.
|
||||||
|
|
||||||
**The marker was left in place**: it is foreign, deleting it is
|
|
||||||
unnecessary, and the isolated `TMPDIR` is the correct remedy. It must
|
|
||||||
be **outside `/tmp` and outside every git worktree** — a child of
|
|
||||||
`/tmp` is not isolated, because `/tmp/.git` remains its ancestor.
|
|
||||||
- **GREEN under an isolated `TMPDIR`: all nine gates pass on the final
|
|
||||||
EXECUTABLE tree** (log `20260812T090034Z-2989598`, review round 2) —
|
|
||||||
executable, not final, because prose and doc comments changed after
|
|
||||||
it, as the sentence below records. fmt, clippy,
|
|
||||||
lib, lib-crdt, `gpu_invocation_acceptance`, **m4 168/0/3**,
|
|
||||||
`PMACS_REQUIRE_GPU=1 -p pmacs-gpu` (**265 tests, none filtered and
|
|
||||||
none skipped**, all nine effect rows included), the **117-target
|
|
||||||
`--workspace --no-fail-fast` sweep with zero failures anywhere**
|
|
||||||
(`m4_acceptance` running all 171 in it), and `diff-check`. Earlier
|
|
||||||
full-green runs at `20260811T215605Z-2664352` (round 1) and
|
|
||||||
`20260812T083735Z-2869707` (the P2 harness) are superseded by this
|
|
||||||
one. **What changed after it is doc comments and prose only** — the
|
|
||||||
`EventOutcome` correction below and this paragraph; `cargo fmt
|
|
||||||
--check`, `clippy -D warnings` and the 22 routing/effect rows were
|
|
||||||
re-run on the result. Stated rather than glossed, because "the gate
|
|
||||||
was green" and "the gate was green on exactly this tree" are
|
|
||||||
different claims.
|
|
||||||
|
|
||||||
## The GUI arc — Stage 0 MERGED as #236 (`f8ad3e7`)
|
## The GUI arc — Stage 0 MERGED as #236 (`f8ad3e7`)
|
||||||
|
|
||||||
|
|
@ -450,24 +375,21 @@ absorption" was too generous. Five stale lanes remain below, and two
|
||||||
`COHERENCE.md` corrections had not been made at all. What is done here
|
`COHERENCE.md` corrections had not been made at all. What is done here
|
||||||
is listed at the commit that does it, not promised here.
|
is listed at the commit that does it, not promised here.
|
||||||
|
|
||||||
- **Branch `gui-arc-stage0`**, base `githubsucks/main` @ `e67ad07` (the
|
- **MERGED as #236 (`f8ad3e7`).** The branch was `gui-arc-stage0`, based
|
||||||
file-watcher arc absorption) after the 2026-08-11 rebase; it was
|
on `e67ad07` after the 2026-08-11 rebase and branched at `0e4c58d`.
|
||||||
branched at `0e4c58d`. **`githubsucks/gui-arc-stage0` is the
|
**Recovery instructions are removed deliberately**: a merged lane that
|
||||||
authoritative tip** — the ref, not a SHA. Recover with
|
still says "checkout the branch" sends a reader to a tip that no
|
||||||
`git fetch githubsucks && git checkout gui-arc-stage0`.
|
longer moves. Its content is on `main`.
|
||||||
- **Framing `docs/gui-arc-framing.md`, revision 3, APPROVED
|
- **Framing `docs/gui-arc-framing.md`, revision 3, APPROVED
|
||||||
2026-08-10** after two review rounds (two blocking findings each
|
2026-08-10** after two review rounds (two blocking findings each
|
||||||
round, closed). It is **also the framing for Stage 0 itself**, which
|
round, closed). It is **also the framing for Stage 0 itself**, which
|
||||||
is docs-only; Stages 1–10 each require their own framing before their
|
is docs-only; Stages 1–10 each require their own framing before their
|
||||||
branch.
|
branch.
|
||||||
- **The park is over and the work is DONE.** The branch was parked at
|
- **The park is over and the work is MERGED.** The branch was parked at
|
||||||
its first commit until #227 merged, because #227 was 72 `main` commits
|
its first commit until #227 merged, because #227 was 72 `main` commits
|
||||||
behind and touched the three files Stage 0's absorption rewrites.
|
behind and touched the three files Stage 0's absorption rewrites.
|
||||||
#227 merged (`b867f64`), #233's arc closed (#234, #235), this branch
|
#227 merged (`b867f64`), #233's arc closed (#234, #235), this branch
|
||||||
rebased onto `e67ad07`, and the absorption ran. **Sixteen commits
|
rebased onto `e67ad07`, the absorption ran, and it landed as **#236**.
|
||||||
above the base as of `30e2209`; ready for its PR.** *(Anchored to a
|
|
||||||
SHA deliberately: a bare running count goes stale on the next commit,
|
|
||||||
which is the staleness class this lane exists to retire.)*
|
|
||||||
- **What landed (docs only, no `src/`):** the absorption pass
|
- **What landed (docs only, no `src/`):** the absorption pass
|
||||||
enumerated in the framing's §5 — five stale lanes, the
|
enumerated in the framing's §5 — five stale lanes, the
|
||||||
authority/recovery anchor, `COHERENCE.md`'s `v6..=v21` → `v6..=v23`,
|
authority/recovery anchor, `COHERENCE.md`'s `v6..=v21` → `v6..=v23`,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,15 @@
|
||||||
# Agent handoff — cross-machine continuity
|
# Agent handoff — cross-machine continuity
|
||||||
|
|
||||||
**Last updated: 2026-08-11 (second pass, same day).** `main` is
|
**Last updated: 2026-08-12.** `main` is **`d038f71`** — **#237**, GUI
|
||||||
|
arc **Stage 1-pre**, the input seam: `App::window_event` goes from 655
|
||||||
|
lines to four, deciding moves to a pure `route_event` and performing to
|
||||||
|
seven `apply_*` methods. **No behaviour change and no wire change** —
|
||||||
|
it is the seam the five behavioural slices land on, and **1a is next
|
||||||
|
and not started**. Beneath it `f8ad3e7` — **#236**, GUI arc **Stage
|
||||||
|
0**, the arc framing and its documentation sweep. **Both are absorbed
|
||||||
|
into §1 at this anchor.**
|
||||||
|
|
||||||
|
Previously **2026-08-11 (second pass)**: `main` was
|
||||||
**`122b8e8`** — **#235**, D3 of the LSP file watcher, which **closes
|
**`122b8e8`** — **#235**, D3 of the LSP file watcher, which **closes
|
||||||
issue #233 and completes that arc**: the watcher stops sleeping and
|
issue #233 and completes that arc**: the watcher stops sleeping and
|
||||||
walks once per scan, zero jobs at idle. Beneath it `b867f64` — git
|
walks once per scan, zero jobs at idle. Beneath it `b867f64` — git
|
||||||
|
|
@ -102,8 +111,68 @@ reads it the way you just did.
|
||||||
For volatile branches, checkpoints, verification, and recovery
|
For volatile branches, checkpoints, verification, and recovery
|
||||||
commands, read `docs/active-work.md` immediately after this file.
|
commands, read `docs/active-work.md` immediately after this file.
|
||||||
|
|
||||||
## 1. Where the project stands (2026-08-11)
|
## 1. Where the project stands (2026-08-12)
|
||||||
|
|
||||||
|
- **GUI arc — Stage 0 MERGED as #236, Stage 1-pre MERGED as #237
|
||||||
|
(2026-08-12). The arc is OPEN: five Stage 1 slices remain and 1a has
|
||||||
|
not started.** Stage 0 framed the arc
|
||||||
|
(`docs/gui-arc-framing.md`); Stage 1 is framed for **all** its slices
|
||||||
|
by `docs/gui-stage1-input-framing.md` (revision 11). 1-pre is the
|
||||||
|
input seam and changes **no behaviour and no wire**:
|
||||||
|
`App::window_event` went from 655 lines to four. Durable facts:
|
||||||
|
- **A route carries the DECISION; only running the body gives the
|
||||||
|
EFFECT.** A wheel route holds a delta, and whether that becomes a
|
||||||
|
viewport update, a panel event, a terminal event or nothing at all
|
||||||
|
depends on `State`. An approved evidence contract asked for
|
||||||
|
"outbound events **and** local effects", and a first implementation
|
||||||
|
argued route-classification covered both. It does not, and framing
|
||||||
|
revision 11 retracts the argument. **When a contract names two
|
||||||
|
things, satisfying one and arguing it implies the other is a
|
||||||
|
narrowing wearing the costume of a mechanism.**
|
||||||
|
- **A harness that re-implements the thing it tests witnesses its own
|
||||||
|
copy.** The dispatch had to leave `window_event` — which cannot be
|
||||||
|
driven, since `ActiveEventLoop` does not exist outside a live event
|
||||||
|
loop — and become `App::dispatch_window_event` before any effect
|
||||||
|
could be observed. That single extraction is what made the evidence
|
||||||
|
possible, and it shrank the untestable residue to one `if`.
|
||||||
|
- **Winit's `KeyEvent` cannot be constructed outside winit** — a
|
||||||
|
`pub(crate) platform_specific` field — so **no
|
||||||
|
`WindowEvent::KeyboardInput` can be built by a test**. This will
|
||||||
|
bind every future GUI input slice. It does **not** extend to the
|
||||||
|
pointer families: `DeviceId::dummy()` exists for exactly this
|
||||||
|
purpose and `CursorMoved` / `MouseInput` / `MouseWheel` are
|
||||||
|
constructible. Bound an exception by checking its edges before
|
||||||
|
writing it down.
|
||||||
|
- **The sentinel is the success condition; the timeout is only an
|
||||||
|
error ceiling**, and conflating them undoes the design. Absence is
|
||||||
|
decided by a non-coalesceable sentinel rather than a duration, so
|
||||||
|
the harness is insensitive to core count — but an unbounded blocking
|
||||||
|
read turns a downstream regression into a **wedged gate** instead of
|
||||||
|
a red one, and a hang reads as slowness until the job is killed.
|
||||||
|
- **Four defects in the tests themselves, all one shape: witnessing an
|
||||||
|
absence the harness had manufactured.** It skipped the post-connect
|
||||||
|
wiring `resumed` performs, so geometry was silently withheld; the
|
||||||
|
fixture was too short to scroll; a windowless `State` has no
|
||||||
|
attached buffer, so viewport sends were withheld; and
|
||||||
|
`.all(|e| matches!(..))` over an **empty** transcript is vacuously
|
||||||
|
true. **Before believing a green row, ask what the harness withheld
|
||||||
|
that production supplies.**
|
||||||
|
- **`cargo metadata` decides which CI job runs a member's unit
|
||||||
|
tests, not intuition.** `workspace_default_members` is the root
|
||||||
|
package alone, so every bare `cargo test --all-targets` skips
|
||||||
|
`pmacs-gpu` entirely; only `gpu-render` runs it. A GPU-dependent
|
||||||
|
assert is therefore **unconditional** rather than
|
||||||
|
`PMACS_REQUIRE_GPU`-gated, so a missing adapter can never become a
|
||||||
|
quiet `ok`.
|
||||||
|
- **Deliberately unbuilt here**: every behavioural change. 1a
|
||||||
|
(`TextInput`, **v24**, protocol-bearing) is next and serialized
|
||||||
|
against 1e (`OpenTarget`, **v25**); **A4 deletes the idle-Escape
|
||||||
|
local quit**, which is **pre-existing behaviour that 1-pre preserved
|
||||||
|
and isolated rather than introduced** — the seam moved it behind an
|
||||||
|
`EventOutcome` return, and 1a is what removes it. `EventOutcome`
|
||||||
|
nevertheless **survives** A4:
|
||||||
|
the native close still returns `Exit`, and **one producer is not one
|
||||||
|
variant**.
|
||||||
- **Git integration Stage 1 — MERGED as #227 (2026-08-11).**
|
- **Git integration Stage 1 — MERGED as #227 (2026-08-11).**
|
||||||
`*git-status*` (a `listview` panel over `git --no-optional-locks -C
|
`*git-status*` (a `listview` panel over `git --no-optional-locks -C
|
||||||
<dir> status --porcelain=v2 --branch -z`) and `*git-diff*`
|
<dir> status --porcelain=v2 --branch -z`) and `*git-diff*`
|
||||||
|
|
@ -620,18 +689,27 @@ commands, read `docs/active-work.md` immediately after this file.
|
||||||
|
|
||||||
**Read this before picking anything up.** It is the only place the
|
**Read this before picking anything up.** It is the only place the
|
||||||
remaining work is enumerated in one view; the per-arc bullets below give
|
remaining work is enumerated in one view; the per-arc bullets below give
|
||||||
the detail. Nothing here is in flight: **zero PRs are open** at this
|
the detail.
|
||||||
anchor, so every item is startable.
|
|
||||||
|
**THIS TABLE IS MIXED-ANCHOR AND IS NOT CURRENT AS A WHOLE.** The GUI
|
||||||
|
row is written at `d038f71` (2026-08-12); **every other row dates from
|
||||||
|
2026-08-01** and has not been re-audited since, including the original
|
||||||
|
claim that zero PRs were open. Rows are known to have drifted — P5
|
||||||
|
called the tree primitive "PR held" when **#217 had already merged** —
|
||||||
|
so **check `git log --first-parent githubsucks/main` before believing
|
||||||
|
any row is still startable**. Refreshing the rest of the board is a
|
||||||
|
separate pass, deliberately not folded into a GUI absorption.
|
||||||
|
|
||||||
#### Arc state, against `COHERENCE.md` §20's priority order
|
#### Arc state, against `COHERENCE.md` §20's priority order
|
||||||
|
|
||||||
| P | Arc | State | What is next |
|
| P | Arc | State | What is next |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| 1 | **Journey** | **Stage 1 COMPLETE** (1a #182/#183; 1b-1 #203, 1b-2 #204, 1b-3 #205) | Journey runs to step 10. The thin end is now steps **1** (install — that is P8), **11** (background work: visible but no ownership model, §9) and **12** (session restore: desktop-save is opt-in *and* a documented no-op under a daemon) |
|
| 1 | **Journey** | **Stage 1 COMPLETE** (1a #182/#183; 1b-1 #203, 1b-2 #204, 1b-3 #205) | Journey runs to step 10. The thin end is now steps **1** (install — that is P8), **11** (background work: visible but no ownership model, §9) and **12** (session restore: desktop-save is opt-in *and* a documented no-op under a daemon) |
|
||||||
| 2 | Workspace + location | Missing; model gap | The long-lead arc. Start before a fifth subsystem grows its own root convention — four have already diverged (§7) |
|
| 1.5 | **GUI arc (half A)** | **Stage 0 MERGED (#236); Stage 1-pre MERGED (#237)** | **`COHERENCE.md` §20 Q#GA5 slots half A immediately after Priority 1** and it runs alongside P2–P5, interacting only at Q#GA5's start gate — **reaching Stage 4b obliges P2 to have STARTED, and no later GUI stage begins until it has an approved framing and an opened lane. The constraint binds THIS arc, not P2**, which is free to start at any time. It is the product half of §16 and what that section's product subgrade is graded against. **Next: Stage 1a**, not started, protocol-bearing at **v24** and serialized against 1e's v25 |
|
||||||
|
| 2 | Workspace + location | Missing; model gap | The long-lead arc. Start before a fifth subsystem grows its own root convention — four have already diverged (§7). **P2 is blocked by nothing and may start now.** Q#GA5 runs the other way: when the GUI arc reaches Stage 4b, **P2 must already have started**, and no later GUI stage begins until it has an approved framing and an opened lane. **The gate is on STARTING P2, not on finishing it** |
|
||||||
| 3 | Extension ownership | Missing; prerequisite-shaped | **`pmacs.hook.remove` does not exist.** That one bug-sized gap blocks §13's disable/uninstall, §10's trust classes, and package-scoped cancellation |
|
| 3 | Extension ownership | Missing; prerequisite-shaped | **`pmacs.hook.remove` does not exist.** That one bug-sized gap blocks §13's disable/uninstall, §10's trust classes, and package-scoped cancellation |
|
||||||
| 4 | **Discovery** | **Stage 1 MERGED (#207)** | Stage 2 candidates, in rough dependency order: richer M-x rows (**protocol change** — `MinibufferPrompt.candidates` is `Vec<String>`; `CompletionPopupRow` already proves the pattern), `Command` gaining title/category/aliases/flags/arg-schema (~147 definition sites), predicate evaluation, help-layer unification, and the help-prefix decision |
|
| 4 | **Discovery** | **Stage 1 MERGED (#207)** | Stage 2 candidates, in rough dependency order: richer M-x rows (**protocol change** — `MinibufferPrompt.candidates` is `Vec<String>`; `CompletionPopupRow` already proves the pattern), `Command` gaining title/category/aliases/flags/arg-schema (~147 definition sites), predicate evaluation, help-layer unification, and the help-prefix decision |
|
||||||
| 5 | Workbench convergence | Partial; **Arc 7 COMPLETE** (#213) and **the tree primitive is implemented** (PR held) | The bottom panel is finished on both frontends and the adopter default is flipped. The tree primitive has landed on a held PR: §14's Tree moves ✗ → ◐ with the LSP outline as its one adopter. **Next: adoption** — dired's `i`, then DAP's variables view, which is why it was built first |
|
| 5 | Workbench convergence | Partial; **Arc 7 COMPLETE** (#213) and **the tree primitive MERGED as #217** | The bottom panel is finished on both frontends and the adopter default is flipped. §14's Tree moves ✗ → ◐ with the LSP outline as its one adopter. *(This row said "PR held" until 2026-08-12; #217 is in the canonical base chain.)* **Next: adoption** — dired's `i`, then DAP's variables view, which is why it was built first |
|
||||||
| 6 | Config productization | Foundation only | Value provenance, then layering, then adoption migration (**table-valued settings are the hard prerequisite** — `ConfigValue` is four scalars) |
|
| 6 | Config productization | Foundation only | Value provenance, then layering, then adoption migration (**table-valued settings are the hard prerequisite** — `ConfigValue` is four scalars) |
|
||||||
| 7 | Package lifecycle | Not started | Correctly sequenced after P3 |
|
| 7 | Package lifecycle | Not started | Correctly sequenced after P3 |
|
||||||
| 8 | **Distribution** | **Stage 1 SHIPPED (v1.1.0, #211)** | Binaries on tag, checksums, machine-checked glibc floor. **Journey step 1 now works and the "invisible until this exists" blocker is lifted.** Next is a *decision* about channels / update / signing, not a queued plan |
|
| 8 | **Distribution** | **Stage 1 SHIPPED (v1.1.0, #211)** | Binaries on tag, checksums, machine-checked glibc floor. **Journey step 1 now works and the "invisible until this exists" blocker is lifted.** Next is a *decision* about channels / update / signing, not a queued plan |
|
||||||
|
|
@ -3257,7 +3335,9 @@ servers.
|
||||||
|
|
||||||
## 6. Named deferrals (the standing backlog, consolidated)
|
## 6. Named deferrals (the standing backlog, consolidated)
|
||||||
|
|
||||||
**The GUI arc — OPEN, framing approved 2026-08-10, Stage 0 READY FOR PR (not yet opened).**
|
**The GUI arc — OPEN. Stage 0 MERGED as #236 and Stage 1-pre MERGED as
|
||||||
|
#237 (2026-08-12); Stage 1a is next and not started.** See §1's arc
|
||||||
|
bullet for what landed.
|
||||||
`docs/gui-arc-framing.md` is the arc-level frame and is also Stage 0's
|
`docs/gui-arc-framing.md` is the arc-level frame and is also Stage 0's
|
||||||
own framing; Stages 1–10 each need their own before their branch. It
|
own framing; Stages 1–10 each need their own before their branch. It
|
||||||
opened from a daily-driver report: the TUI is daily-drivable, the GUI is
|
opened from a daily-driver report: the TUI is daily-drivable, the GUI is
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue