Docs only. No `src/`, no `pmacs-gpu/`, no 1a implementation. **The recovery procedure was RE-RUN, not SHA-swapped, and that is what licenses the rest of this commit.** Every documented step, from an empty directory, on git 2.55.0: clone the canonical URL (which names it `origin`, and `git remote get-url githubsucks` errors with `No such remote`, exactly as the section anticipates); add the alias; fetch; `git log -1 --oneline githubsucks/main` -> `d038f71`; confirm BOTH the old floor `9a26ac8` and the new `d038f71` are ancestors, so advancing the floor is valid rather than merely plausible; recover with the three-argument `git worktree add <path> -b <local> githubsucks/<branch>` form and confirm the upstream is actually set. The documented TRAP was reproduced too: the two-argument form succeeds and leaves `## HEAD (no branch)`, so that correction still holds on 2.55.0. **This discharges a debt rather than inheriting one.** The previous absorption advanced the base to `e67ad07` WITHOUT re-running the procedure and recorded that as an outstanding obligation. It is settled here, by the run above. Canonical base, recovery floor, the `git log` threshold and the last-exercised record all move to `d038f71` together --- a floor that accepts an older commit than the base it declares passes on a tree the rest of the file does not describe. **The GUI lane is REWRITTEN, not removed.** Rule 4 removes a lane when its ARC is done; the arc is Stage 1 as a whole and **five slices remain**. The lane now records 1-pre as merged, names 1a as next and NOT STARTED, and keeps the fact that 1a (v24 `TextInput`) and 1e (v25 `OpenTarget`) are the two protocol-bearing slices and are serialized. Open-PR and branch-recovery wording for 1-pre is gone --- a lane that still says "recover with `git checkout`" for a merged branch is how a reader ends up on a stale tip. The handoff anchor absorbs both merges, and §1 gains the arc bullet the anchor promises. Its durable facts are the ones that will bind future slices rather than the diff: a route carries the DECISION and only the body gives the EFFECT; a harness that re-implements what it tests witnesses its own copy; winit's `KeyEvent` is non-constructible outside winit and this will bind every GUI input slice; the sentinel is the success condition and the timeout only an error ceiling; four test defects that were all one shape --- witnessing an absence the harness had manufactured; and `cargo metadata`, not intuition, decides which CI job runs a member's unit tests. **One judgement beyond the stated scope, flagged rather than slipped in.** §1a's board had no GUI-arc row at all, which would have contradicted the anchor two sections above it. A row is added at the position `COHERENCE.md` §20 Q#GA5 gives it --- after Priority 1, running alongside P2-P5, interacting only at the P2 start gate --- and the P2 row now names that gate. The section's own dateline is corrected in the same breath: the table was written 2026-08-01 and claimed zero open PRs, so it now says which row is current and which are as-of that date. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
This commit is contained in:
parent
d038f7144e
commit
502308d8e4
|
|
@ -136,7 +136,11 @@ lesson, §1 for the two framings).
|
|||
are identical on every machine. Remote names are otherwise
|
||||
machine-local: `origin` may name this canonical URL, a release mirror,
|
||||
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 D3 **#235** (closes issue #233), atop `b867f64`
|
||||
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
|
||||
current-state paragraph tracks the live range.
|
||||
**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
|
||||
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
|
||||
|
|
@ -213,28 +217,40 @@ git worktree list
|
|||
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
|
||||
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
|
||||
describe.
|
||||
If it does not, stop and repair the remote/fetch configuration.
|
||||
|
||||
**LAST EXERCISED AT `9a26ac8`, 2026-08-08** — re-run from an empty
|
||||
directory rather than having its SHA swapped. **The advance to
|
||||
`e67ad07` (2026-08-11) has NOT been re-exercised**, and by this
|
||||
paragraph's own argument that is exactly when the exercise matters, so
|
||||
it is recorded as an outstanding obligation rather than left to read as
|
||||
though it had been done. The floor above and the check below are in
|
||||
step at `e67ad07`; what is unverified is the *procedure* against that
|
||||
base, not the SHA. 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. `git clone` the canonical URL, add
|
||||
the `githubsucks` alias, `git fetch githubsucks --prune`, confirm
|
||||
`9a26ac8` is an ancestor of `githubsucks/main`, and recover with the
|
||||
three-argument `git worktree add <path> -b <local> githubsucks/<branch>`
|
||||
form. All four steps ran clean.
|
||||
**LAST EXERCISED AT `d038f71`, 2026-08-12**, from an empty directory
|
||||
rather than by having its SHA swapped — **which also discharges the
|
||||
outstanding obligation this paragraph carried at `e67ad07`**, where the
|
||||
base advanced without the procedure being re-run. That debt is settled,
|
||||
not inherited: the advance recorded here was exercised as part of making
|
||||
it.
|
||||
|
||||
Every documented step ran, in order, on git **2.55.0**:
|
||||
|
||||
1. `git clone` the canonical URL into an empty directory. The clone
|
||||
names it `origin`; **`git remote get-url githubsucks` errors with
|
||||
`No such remote`**, exactly as the section above anticipates.
|
||||
2. Add the alias, confirm the URL, `git fetch githubsucks --prune`.
|
||||
3. `git log -1 --oneline githubsucks/main` → `d038f71`.
|
||||
4. **The floor check, run against both floors**: `9a26ac8` (the old one)
|
||||
and `d038f71` are each an ancestor of the tip, so advancing the floor
|
||||
is valid rather than merely plausible.
|
||||
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
|
||||
two-argument form fails for a remote-only branch with `fatal: invalid
|
||||
|
|
@ -250,186 +266,88 @@ hazard in a shape that looks committed. **A documented error message
|
|||
that never appears is worse than no documentation**, because the reader
|
||||
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
|
||||
§5 requires of every PR in it.
|
||||
**The lane is rewritten, not removed.** Rule 4 removes a lane when its
|
||||
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**
|
||||
after **eight rejected revisions**. Revision 9 is the approved design;
|
||||
revision 10 recorded a scope correction found against this
|
||||
implementation and **also argued P2 was satisfied by classification
|
||||
alone, which review overturned — revision 11 retracts it**. It is
|
||||
Stage 1's framing for **all** slices and governs the later branches;
|
||||
only Stage 0 was framed by the arc document itself.
|
||||
- **Scope of THIS branch: 1-pre only — the input seam. No behaviour
|
||||
change.** `App::window_event` was **655 lines** and is now **four** —
|
||||
call `dispatch_window_event`, exit if it asks. The dispatch it calls
|
||||
is one `route_event` call and one arm per route. Nothing below it
|
||||
could be witnessed without a display, which is why the seam precedes
|
||||
every other slice.
|
||||
- **IMPLEMENTED in four commits, one per event family**, so each lands
|
||||
with its own witnesses and mutations rather than as one 600-line
|
||||
diff: `014110f` lifecycle (close / modifiers / resize), `7f0f9db`
|
||||
redraw, `0705564` keyboard, `e955645` the four pointer arms. Review
|
||||
round 1 added `f976dc1`, the P2 effect harness.
|
||||
- **P2 HAS TWO HARNESSES, and the second was review round 1's blocker.**
|
||||
The routing harness answers *where did this event go*; `EffectHarness`
|
||||
answers *what did it do*. Classification alone could not satisfy P2 —
|
||||
**a wheel route carries a delta, and whether that becomes a viewport
|
||||
update, a panel event, a terminal event or nothing depends on
|
||||
`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.
|
||||
after eight rejected revisions. It is Stage 1's framing for **all**
|
||||
slices and governs every later branch; only Stage 0 was framed by the
|
||||
arc document itself. Revision 9 is the approved design; 10 recorded a
|
||||
scope correction found against the 1-pre implementation; **11 retracts
|
||||
10's claim that P2 was satisfied by route classification alone**, and
|
||||
corrects the Stage 1a consequence 10 got wrong.
|
||||
- **Slice order, each its own branch and PR:** ~~`1-pre`~~ → **`1a`**\* →
|
||||
`1b` → `1c` → `1d` → `1e`\*. **`1a` and `1e` are the two
|
||||
protocol-bearing slices — v24 `TextInput` and v25
|
||||
`OpenTarget`/`OpenTargetResult` — and they are SERIALIZED** against
|
||||
each other and against every other wire change in the project. 1c is
|
||||
**not** protocol-bearing, under Q#S1-8.
|
||||
- **NEXT: 1a, and nothing of it exists yet** — no branch, no code. It
|
||||
carries the **v24** `TextInput` variant, so it must run alone.
|
||||
`PROTOCOL_VERSION` is **23** at this base, and
|
||||
`ADVERTISED_PROTOCOL_VERSION` stays pinned at 20 and must not be
|
||||
edited to chase it. Its nine contracts (A1–A9) and the Q#S1-9
|
||||
precedence rules are in the framing; **A4 deletes the idle-Escape
|
||||
local quit**, which is the one 1-pre change 1a is expected to undo.
|
||||
|
||||
**`scripts/gate` isolates the target dir and five ambient roots but
|
||||
NOT `TMPDIR`** — recorded in handoff §1, where the standing fix is
|
||||
assigned to the gate lane rather than to this PR.
|
||||
### What 1-pre landed, and the facts worth not re-deriving
|
||||
|
||||
- **`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`)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
# 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
|
||||
issue #233 and completes that arc**: the watcher stops sleeping and
|
||||
walks once per scan, zero jobs at idle. Beneath it `b867f64` — git
|
||||
|
|
@ -102,8 +111,66 @@ reads it the way you just did.
|
|||
For volatile branches, checkpoints, verification, and recovery
|
||||
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 1-pre's
|
||||
idle-Escape local quit**, which is the one thing 1-pre added that a
|
||||
later slice removes. `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-status*` (a `listview` panel over `git --no-optional-locks -C
|
||||
<dir> status --porcelain=v2 --branch -z`) and `*git-diff*`
|
||||
|
|
@ -620,15 +687,20 @@ commands, read `docs/active-work.md` immediately after this file.
|
|||
|
||||
**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
|
||||
the detail. Nothing here is in flight: **zero PRs are open** at this
|
||||
anchor, so every item is startable.
|
||||
the detail. **The table is current at `d038f71` (2026-08-12); the rows
|
||||
beneath it that carry no GUI-arc mention date from 2026-08-01** and
|
||||
were written before that arc existed. Zero PRs were open when this
|
||||
section was first written; the GUI row is the only one refreshed since,
|
||||
so treat the others as of that date and check `git log` before believing
|
||||
any of them is still startable.
|
||||
|
||||
#### Arc state, against `COHERENCE.md` §20's priority order
|
||||
|
||||
| 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) |
|
||||
| 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 P2 — *reaching Stage 4b is a P2 START GATE*. 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). **Gated by the GUI arc reaching Stage 4b** (Q#GA5) |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
|
|
|||
Loading…
Reference in New Issue