Commit Graph

107 Commits

Author SHA1 Message Date
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 c8895a85d3 Merge canonical main into bottom-panel Stage 2B-1
Integrate main through the Journey/GPU directory-target ratchet (#183).
The public managed-GPU probe additions compose with the v21 wire layer.

Resolve the volatile ledgers to the landed state: advance the canonical
anchor to 7fd646d, remove the completed ratchet lane, preserve the
approved Stage 2 revision-5 recovery facts, and mark the integrated
2B-1 tree as awaiting its from-start full gate rerun.
2026-07-28 11:38:19 -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 d88d60eba6 Merge canonical main into bottom-panel Stage 2B-1
Integrate the Journey Stage 1a merge without rewriting the already
reviewed protocol branch. Record the approved three-way Stage 2B split,
advance the canonical recovery anchor, remove the landed Journey lane,
and put 2B-1 into its full-gating state.
2026-07-27 22:16:11 -04:00
Levi Neuwirth d0817314f9 merge: fold the terminal landed-docs PR (#180) into this branch
Two open documentation PRs editing the same three ledger files
re-conflict on every merge to `main` — the treadmill #169 and #176 each
paid three resolution rounds for. #180 was docs-only and already
CONFLICTING against `main`; folding it here retires one of the two
writers instead of resolving the same file twice.

Also integrates `githubsucks/main` @ `42025e4` (Lean 4 Stage 4b #181).

Conflicts resolved, and three claims corrected rather than picked:

* **The head-of-`main` anchor.** Both sides named `74301d1`, which is no
  longer true — `#181` has landed. The anchor now reads `42025e4` and
  leads with it, in `docs/agent-handoff.md` §1 and the active-work
  canonical-base line, and **the recovery floor moved with it**: the
  `git log` check requires `42025e4` or newer, per that section's own
  rule that a floor accepting an older commit than the declared base
  passes on a tree the file does not describe.
* **The Lean 4 bullet contradicted the anchor I had just written.** Its
  header still said "stages 1, 2, 3a, 3b LANDED" and its Stage 4b
  sub-bullet still said "implemented and in review", while the anchor
  above it now records #181 as merged. Both corrected: all six stages
  landed, #181 named.
* **The COHERENCE §2 grade.** #180's side still carried "broken at step
  3" / "Broken at entry" in both the ground truth and the §0 scorecard;
  this branch's corrections win, since they are what the code change in
  this PR makes true.

The removal note at the top of `docs/active-work.md` is reattributed:
the terminal config + copy mode lanes were #180's removal, and it now
says so and says why the fold happened.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 18:36:55 -04:00
Levi Neuwirth 8e31ca4646 Merge remote-tracking branch 'githubsucks/main' into journey-stage1a-directory-open 2026-07-26 18:33:44 -04:00
Levi Neuwirth d9d1c0b423 test(journey): pin the destination commit, and land the doc updates
Completes Journey Stage 1a: the `commit_to` acceptance suite (framing
§6 N4, N6, N6b, N6c, P1, P2, P3) plus the documentation updates
COHERENCE §25 requires the PR to carry.

Bite-testing the new pins found a real gap. Deleting the
`ScopedFrontend` arm from `acting_frontend` left N4 green, because
`ScopedFrontend::enter` also swaps `core.active_frontend` and the
ambient fallback then answers correctly on its own. The arm is
load-bearing in exactly one case — a commit reached from inside an
interactive command, where the origin sits between the override and the
ambient value — and nothing pinned it. N4b is added, driven through
`dispatch_key` because that is the only thing that establishes an
interactive origin, and the mutation now bites it.

Two smaller corrections found the same way:

* `commit_to`'s forged-destination message was unreachable. Typed as
  `AnyUserData`, mlua rejected a table during argument conversion, so a
  caller got "error converting Lua table to userdata" — true, but naming
  neither the rule nor the remedy. The parameter is now `mlua::Value`
  and the pointed message fires.
* P1 and P2 also fail on full revert, since `commit_to` does not exist
  on the pre-image, so §6.0's "legitimately green on the pre-image" does
  not describe them. They stay in the P list because their
  discriminating falsifier is the named mutation — a revert-only check
  cannot distinguish "validates" from "validates in time" — and each pin
  now says so at its own site rather than being silently mislabelled.

Bite results, each run against the whole suite:

  scope stops swapping `core.active_frontend`  -> N6a, P3 fail; nothing else
  preflight moved after the callback           -> P1, P2 fail; nothing else
  drop the `ScopedFrontend` arm                -> N4b fails; nothing else

Docs: COHERENCE §2 grade + step-3 verdict row, §20 Priority 1 and the
arc list; the GPU initial-target framing's Q#GT6 and acceptance 10,
whose directory case this stage deliberately supersedes; handoff §1;
the active-work ledger; framing rev 7.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 17:25:22 -04:00
Levi Neuwirth d1bff6ac30 fix(lean4): count fan-outs where a claim cannot skip the count
Round 11 put the nesting count in the expander, which is optional. A
consumer at a lower priority can CLAIM and stop the chain before the
expander runs, while that fan-out's deferred-expansion subscriber still
runs — so the nested pass went uncounted, looked like the outermost
one, expanded early, and outer pairing resumed with a record the
replace had invalidated. `\alp(` gave `α(` again.

The count now comes from a no-op consumer registered at the minimum
priority, which runs first in every chain invocation that reaches any
consumer at all. Its guarantee is exactly the ordering contract the
chain already rests on, and it degrades safely: the only thing that can
skip it is a claim ahead of it, which skips the expander too, so
nothing is queued in that fan-out either.

The other plausible home does not work and the comment now says why: a
subscriber registered beside `run_deferred` is too late, because the
whole nested fan-out completes inside the OUTER chain's subscriber,
before either of them runs.

Acceptance 45o pins the short-circuit path — a consumer at 25 that
claims when the record is nil, so the nested pass never reaches the
expander. 45n passes against this bug, which is why both exist.
Counting in the expander fails 45o and nothing else.

Framing rev 12 also names the shape rounds 10–12 share: each fix was
correct about the failure it was shown and wrong about the boundary of
the mechanism it leaned on — the chain's copy semantics, then its
re-entrancy, then its short-circuit. A queue that outlives the thing
that filled it has to name that thing, not approximate it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 17:15:24 -04:00
Levi Neuwirth 0d7ec7e3a6 fix(lean4): tie the deferred expansion to the fan-out that queued it
`buffer.after-edit` fan-outs NEST — the typed-edit contract supports a
consumer calling `pmacs.hook.run`, and typed_edit.lua's header says so
in its second paragraph. A nested run re-enters every subscriber,
including the deferred expansion's, while the OUTER chain is still
walking its consumer list and pairing has not yet seen the terminator.

So a consumer registered at priority 75 — between the expander at 50
and pairing at 100 — that runs one nested fan-out made `\alp(` yield
`α(` again: the nested pass consumed the queued expansion and edited,
and outer pairing then resumed holding a record the replace had
invalidated. That is round 10's failure reached through the chain's
documented re-entrancy seam rather than through claiming, which is why
deferring alone did not close it.

Deferring work past a fan-out means owning WHICH fan-out it belongs to.
The chain's subscriber and this module's each run exactly once per
fan-out, in that order, so counting invocations of the first and
matching them off in the second identifies the nesting level. Only the
outermost pass expands; a nested one leaves the expansion queued. No
new seam in typed_edit.lua, which is merged Stage 4a substrate.

Both halves bite: removing the level check and never counting
invocations each fail the new acceptance 45n.

Also fixes a test comment that still described the span design round 10
discarded — it claimed the expansion replaces the span "INCLUDING the
terminator". The behaviour asserted was right; the explanation was
stale. Framing rev 11.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 17:00:58 -04:00
Levi Neuwirth f3103a6953 fix(lean4): defer the expansion past the chain, and guard its point
Three defects, all about what happens AROUND the expansion rather than
about resolving an abbreviation.

A pair character that TERMINATES an abbreviation never reached
auto-pairing: `\alp(` gave `α(`. Q#LN22 already said the terminator is
not claimed and the implementation claimed it whenever an expansion
succeeded. Merely declining is not enough either — the chain hands each
consumer a copy of the record made before any consumer ran, so
expanding inside the chain invalidates the copy pairing is holding and
the closer is silently lost. Verified by mutation rather than assumed:
expand-then-decline reproduces `α(` exactly.

The expansion therefore runs on its OWN `buffer.after-edit` subscriber,
registered after typed_edit.lua's and before lsp.lua's. A claim stops
the chain but not a separate subscriber, which is the point: pairing
claims the terminator it reacts to. The replaced span now covers only
the leader and the typed text, so pairing's closer lands outside it and
survives. One undo restores the same text either way, because the
terminator was always its own insert.

That second subscriber is a new instance of Q#AP7 — lsp.lua flushes
didChange synchronously on the signature-trigger path, and `(` is a
trigger — so acceptance 45m pins it with the sighelp fake server: no
didChange may ever carry the unexpanded text.

The relevance check is now three-part, as pairing's has been since
#110: buffer, window, AND `ed.cursor() == rec.post_cursor`. A redefined
self-insert can insert the completing character and then move the
point, and expanding over a span the user has left teleports them back
into it.

Cursor placement after the replace is context-guarded, as
`repair_cursor` is. A buffer intercept may switch buffers while
`buf:replace` runs; the unguarded `goto_byte` then translated the Lean
buffer's pre-edit point through the Lean buffer's edit and applied it
to whatever was ambient.

Q#LN22, criterion 38's span wording, and the ledger are corrected to
describe the deferred design rather than the one that shipped — the
rationale's source, not only the sites quoting it. Acceptance 45j/45k/
45l/45m added; framing rev 10.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 16:47:54 -04:00
Levi Neuwirth d2ab3761c7 docs: correct the non-adopter attribution and two stale anchors
Round 6. Documentation only; no code, no protocol change.

1. **The four-writer table mapped the wrong buffers to `ensure_slot`.**
   Verified at the call sites: `ensure_slot` has exactly two callers,
   `*compilation*` (`compile.lua:1090`) and `*shell-command*` (`:1125`).
   `*search-results*` is an **independent panel** in
   `builtin/commands/default.lua` with its own intercept (`:869`),
   round-trip mark and writes; `compile.lua` declares its name only to
   answer a predicate (`:216`), which is what made it look like a third
   slot. Round 5 fixed an undercount and introduced a misattribution in
   the same paragraph — the count was right, the mechanism was not.

   The table is now keyed by **writer**, not by buffer, so the mapping
   cannot silently drift again: four mechanisms, five buffers. It carries
   an explicit "do not read `ensure_slot` as covering the search panel"
   note, because that is the specific wrong inference.

   Corrected identically in `COHERENCE.md` §14 and the framing's
   deferred-lane text, which both carried the error.

   The scope claim is narrowed with it. "Every generated buffer outside
   copy mode" was too wide: `*workers*`, `*help*` and `*buffer-list*` are
   generated but do not use this idiom, and the REPL package's intercept
   (`packages/repl/init.lua:187`) is an op-filtering editing policy
   rather than a read-only panel. The claim is now "every remaining
   intercept-protected writer", and the two excluded groups are named so
   the next reader does not have to re-derive the boundary.

2. **The recovery floor contradicted itself.** The canonical-base line
   said the check accepts `a27f646` or anything newer while the check
   below required `74301d1`. The floor genuinely advanced; the prose now
   says so outright — a tree at `a27f646` no longer passes — and states
   why the floor must move with the base rather than trailing it.

3. **Two anchors survived the integration.** Lean 4 Stage 4a said it was
   part of "the `fe8b8ba` anchor above" when the anchor had become
   `74301d1`; it now refers to the anchor rather than restating a commit,
   which is what let it go stale. And #168's closed entry called its own
   `fe8b8ba` figure "the live figure" — it is a reading taken at
   `1b6a084`, kept as history, and now says so and points at the
   coverage lane as the single authority with an explicit "do not quote
   this one forward".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gGQC6eqHJVbZJ5Hg7aLer
2026-07-26 16:45:12 -04:00
Levi Neuwirth d14fe4c4b9 Merge githubsucks/main (#169, #176) into docs-terminal-copy-mode-landed
Two doc conflicts, both in favour of `main`, and both are this PR's own
findings arriving from the other side:

- **The dired lane.** #169 did exactly what round 5 finding 5 said it
  would: absorbed dired Stage 1 into handoff §1 and removed the ledger
  lane per rule 4. This branch carried a placeholder saying #169 owned
  that text; the placeholder is dropped and #169's version taken whole.
  This is the rule working — one PR, one authority per paragraph.
- **The canonical base.** Both sides edited it. Resolved to `74301d1`,
  now naming #169 and #176, keeping `main`'s added guidance that a
  recovery threshold must move with the base it declares canonical (a
  check that accepts an older commit passes on a tree the file does not
  describe). The threshold moved with it.

Consequences of the merge, folded in:

- **The census is re-measured on the merged tree**: 3,176 vs 3,449 —
  still **273 dark**, 185 of them in the library. #176's six new tests
  are not `crdt`-gated, so both totals moved and the gap did not. The
  per-target table is unchanged.
- **The `crdt` Clippy failure is re-measured too, and the previous count
  was wrong** — it was read off a different checkout. At `74301d1` it is
  seven errors before the build aborts: four in `src/daemon.rs`, three in
  `tests/vterm_stage3_acceptance.rs`. Recorded as a **lower bound**,
  because Clippy abandons the remaining targets once one fails, and an
  older tree showed a further error in
  `tests/auto_indent_crdt_acceptance.rs` this run never reached.
- **The PTY-terminate lane (#176) is marked MERGED and retained**, with a
  note at its head saying why it survives rule 4: no landed-doc PR owns
  moving its facts to the handoff, so removing it now would delete the
  record rather than move it. The ledger preamble's stale-on-purpose
  paragraph is rewritten around that one lane; the Lean 4 and
  GPU-terminal-input headers it used to disclaim no longer exist.
- The flake note's "`src/process.rs` last changed by the Darwin PTY
  signal-name fix" is dropped — #176 changed it. The load-bearing half
  (#178 did not touch that file at all) is what remains.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gGQC6eqHJVbZJ5Hg7aLer
2026-07-26 16:37:41 -04:00
Levi Neuwirth f8ca722d66 merge: integrate main (74301d1) into Stage 4b
Reconciles the handoff and ledger against a main that advanced past
this branch's base: the header, `main` anchor, and canonical-base
description take main's richer versions restamped to 74301d1, main's
new PTY-terminate lane is kept alongside the Lean lane, and main's
Stage 4a/rev-8 lane history is dropped in favour of the Stage 4b lane
that supersedes it — per this ledger's own rule to remove entries when
their PR merges.

Also fixes the coherence census's second count, which still said eight
settings three paragraphs below the nine it now lists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 16:37:19 -04:00
Levi Neuwirth e4c9d65231 docs: fix five review-round-5 findings in the landed-doc refresh
Documentation only; no code, no protocol change. All five findings
reproduced before fixing.

1. The CRDT-dark census was stale. Re-measured at `fe8b8ba` under CI's
   exact flags versus the same flags plus `crdt`: 3,170 vs 3,443 —
   **273 dark, 185 in the library**, not the 264/177 #168 measured at
   `1b6a084`. The per-target table is regenerated (it gains a
   `terminal_copy_mode_acceptance` row, acc16e's, from this very arc),
   the rows are stated to sum to the total, and the lane now says the
   number moves with every merge and must be re-measured rather than
   quoted. #168's figure is kept as a dated historical reading with a
   pointer to the live one.

2. The generated-buffer non-adopter inventory was short by half. It is
   **four writers, not two**: listview panels (`listview.lua:60-61`),
   `*compilation*` **and** `*search-results*` — both through
   `compile.lua`'s shared `ensure_slot`, so naming only the first
   undercounts a mechanism rather than a buffer — and dired
   (`dired.lua:371`). All four pair an erroring intercept with
   `bypass_intercept` writes over a still-writable rope, and all four are
   emptiable by `M-x buffer.undo`. Corrected in the handoff §4 (as a
   table, with each writer's shape), `COHERENCE.md` §14, and the
   framing's deferred-lane text. The adoption estimate gains a
   consequence: the two `compile.lua` slots append and need a streaming
   variant; listview and dired are whole-buffer replaces and are the
   cheap half.

3. The ledger's canonical base still named `a27f646` while the same file
   recorded #168 and #178. Now `fe8b8ba`, with the recovery check's
   accept-or-newer floor moved with it — a stale floor is what lets a
   wrong base pass verification.

4. The completed terminal lane is **removed**, not marked complete. Rule
   4 of this file's own update protocol says a lane goes when it merges,
   and its opening contract says the file records only what has not
   landed. Its durable facts moved first: a new arc bullet in the handoff
   §1 (the snapshot materializes, so the dispatch-shadow count stays at
   six; `prune` reacts to removal rather than causing it; ownership means
   the handle table, never found-by-name; profiles are a raw Lua table
   and why the escape cache lives on `TerminalSession`; what criterion
   17 must assert when it can finally be written; the `cat -v` echo probe
   and count-don't-match rule), with the `set_generated_contents`
   invariant already in §4. A compact entry remains under "Closed since
   the last snapshot". The gate-run flake the lane carried moved to the
   CI `crdt`-coverage lane, which owns its discrimination — verbatim,
   including its explicit refusal to claim a root cause.

5. The refreshed handoff was internally stale: it anchors on a `main`
   that contains #179 and #165 while still calling both "in review".
   Both now read MERGED. Dired's durable facts are deliberately **not**
   absorbed here — that is open PR #169's job, and writing it from two
   PRs would put two authorities on one text — so the dired lane stays,
   with a note saying why it survives rule 4 and who removes it.

Also recorded while verifying finding 4's new home: the `crdt` Clippy
failure on `main` is re-verified with exact sites (four in `src/daemon.rs`,
one in `tests/auto_indent_crdt_acceptance.rs`), because any CI job that
compiles the `crdt` targets is red on arrival until they are fixed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gGQC6eqHJVbZJ5Hg7aLer
2026-07-26 16:28:04 -04:00
Levi Neuwirth a53965474d feat(lean4): the Unicode input method (Arc 8 Stage 4b)
Typing `\alpha` in a Lean 4 buffer gives `α`; `\<>` gives `⟨⟩` with the
point between them. The abbreviation table is vendored from
vscode-lean4 and the expander is a typed-edit consumer registered on
the Stage 4a chain at priority 50, ahead of auto-pairing.

The ordering is load-bearing. 64 abbreviation keys contain a character
in the `lean4` pair set, so with pairing first, typing `\[` would
insert `[]` and corrupt the pending key to `\[]` before the second `[`
arrives — `\[[]]` becomes unreachable. The consumer therefore claims
every keystroke that EXTENDS a pending abbreviation, not only one that
completes an expansion; claiming only completions would hand each
intermediate `[` to pairing by a different route.

The vendored table is an ORDERED SEQUENCE, not a map. Upstream breaks
equal-length ties by source declaration order — 101 prefixes depend on
it, and `\f` resolves through `f<` rather than `f>` — which a
`pairs`-iterated Lua table cannot express. `scripts/regen-lean-abbrev`
takes a vscode-lean4 commit, emits the file with its provenance header,
and aborts on a duplicate key, invalid UTF-8, or a round-trip mismatch.

Undo is cross-peer-degraded on CRDT frontends and that is accepted and
named, not papered over (Q#LN21): `\alpha` arrives as six source-peer
optimistic inserts while the expansion is one daemon-peer replace.
`set_round_trip_input` would fix it and also makes `dispatch_idle`
report false, so RET would stop inserting a newline.

Round 9 corrects three approved acceptance criteria that the real table
contradicts, found by simulating the state machine over all 1,855
entries and re-reading upstream at the pinned commit rather than
re-reading the prose. `\to` is not eager — `top`, `to0` and `toa`
extend it. `\zzzz` expands to `ζzzz ` because `ze`, `zeta` and
`zsqrtd` exist; only `$ % , ; @ W` open no key at all. And `\alpha`'s
undo does not restore `\alpha ` because `alpha` IS eager, so the
terminator is a separate edit. Criteria 38, 41 and 42 now state both
paths, and the false halves are asserted too: they read as correct
until the table is consulted.

Three implementation traps worth the record. The generator's own
round-trip check was broken twice and failed closed both times:
`str.splitlines()` splits on U+2028, which 53 symbols contain, and
escaping through `chr(byte)` produced a latin-1-shaped string that the
UTF-8 write re-encoded. The first check compared in-memory strings and
agreed with itself; it now stages the file, re-reads the bytes from
disk, and renames into place only on a match. And the expansion SHRINKS
the buffer, so the point must be placed explicitly — pairing's
no-cursor-motion rule holds only for an insert AT the cursor, and
without this every self-insert after the first expansion is silently
rejected and the editor looks dead.

25 acceptance tests plus one `--lib` test for the optimistic CRDT
producer (45f), which is where the gate list's `--features crdt` run
reaches it; a crdt-gated integration test would be dark in CI and in
the gates both. Fifteen mutations bite, each failing its target. Three
of these tests were vacuous when first written and biting is what
found them: the abandonment test asserted text a surviving record
would also produce, the re-arm test used an example that never reaches
the re-arm branch, and both switch tests ran through
`find_or_open`'s fresh-load path rather than `buffer.after-switch`.

No protocol change (Q#LN14). Also reconciles the handoff and ledger
for Stage 4a (#179) and adds `lean.abbrev` to COHERENCE.md's
config-registry adoption census, now nine settings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 16:24:06 -04:00
Levi Neuwirth 44f5e44b9f docs: record #168 and #178 as landed, and the generated-buffer invariant
Documentation only; no code, no protocol change.

Handoff §1 anchors on `main` @ `fe8b8ba` and leads with terminal copy
mode (#178) and its landed-doc pair (#168). The active-work terminal lane
flips to BOTH STAGES MERGED, and the #166 lane records #168 landing with
what it measured: 264 tests dark workspace-wide for want of `crdt` in CI,
and the vterm audit's honest count of acceptances that drive a real
daemon (2, not 3).

The substantive addition is a new §4 substrate invariant for
`Buffer::set_generated_contents`, because it is now the one authorized
write for every generated buffer and three of its properties are
non-obvious enough that four review rounds were spent finding them:

- an intercept is not read-only — `Buffer::undo` reaches the rope through
  `ensure_writable` without consulting the intercept chain, and rebinding
  the undo chords does not help because `M-x buffer.undo` needs no
  keymap;
- a bare `set_read_only` would be worse than nothing, since it also
  refuses the owner's refresh — the pairing is the primitive, which is
  why no Lua `set_read_only` exists;
- a rope write is only half of an edit: the returned `Edit` must be
  fanned out, or a displaying window paints the new rope with stale line
  offsets and replica mirrors never import the write.

Also recorded: history clearing must clear whichever history the buffer
has (the v0.1 stacks are bypassed in CRDT mode), that `*compilation*` and
listview have NOT adopted the primitive and remain emptiable by
`M-x buffer.undo`, and that this does not replace `set_round_trip_input`
— the two guards cover different copies, and a daemon refusal arrives
after the frontend has already painted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gGQC6eqHJVbZJ5Hg7aLer
2026-07-26 15:48:03 -04:00
Levi Neuwirth f3e0b98ced Merge branch 'main' into docs-dired-stage1-landed
Re-integrated after #168 landed the ledger refresh. Five conflicts, none
resolved by taking a side wholesale:

- Both head-of-main anchors take main's a27f646 wording (written by
  #168); the ledger keeps this branch's caveat about lanes naming an
  older base.
- The dired lane section is pruned, which is this PR's purpose, but main
  had meanwhile pruned the GPU terminal input lane as landed — so the
  union drops both stale lanes rather than resurrecting either.
- "Closed since the last snapshot" keeps BOTH new entries: dired Stage 1
  #165 from this branch and GPU terminal input #166 from main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RuhVYUPHXMHG8r2z4tsDPR
2026-07-26 15:41:58 -04:00
Levi Neuwirth 42f601a7ec Merge branch 'main' into gpu-terminal-input-docs, and refresh the ledger
The handoff's "last updated" paragraph conflicted; resolved by writing
the current statement rather than taking either side, and the same pass
clears the staleness the ledger had accumulated while five PRs contended
for it:

- Both head-of-main anchors (handoff §1 and the ledger's canonical base)
  now name a27f646, and list terminal config #173, the bottom-panel
  Stage 2 framing #175, Stage 2A #177 and Lean 4 Stage 4a #179 — plus
  the CRDT undo repro #157 and the inline-math landed-doc refresh #172,
  which are merged but had dropped out of both lists.
- The bottom-panel lane records Stage 2A as MERGED (#177 @ 0a3fcd1)
  instead of IN REVIEW, and states what 2B is: approved, unstarted,
  branching from main rather than stacking, with §7.2's criteria and
  §5.3's three-boundary trap named.
- The Lean 4 lane records Stage 4a as MERGED (#179 @ a27f646); its
  "framing-only, no code, awaiting approval" bullet was false.

The dired lane is left alone deliberately: #169 is the PR that records
dired Stage 1 as landed, and owns that heading.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RuhVYUPHXMHG8r2z4tsDPR
2026-07-26 14:43:43 -04:00
Levi Neuwirth b123c0b9fe Merge branch 'main' into docs-dired-stage1-landed
Three conflicts, resolved by taking the newer statement on each side
rather than either side wholesale:

- COHERENCE.md journey row 7 keeps this branch's text (dired #165 is
  merged, not a PR); row 8 takes main's, which records terminal config
  #173.
- The ledger's canonical-base line takes main's d400f30 anchor and keeps
  this branch's caveat about lanes that name an older base.
- agent-handoff's two anchors take main's d400f30 wording, with the CRDT
  undo repro #157 and the inline-math landed-doc refresh #172 added
  back — both are merged and main's summary had dropped them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RuhVYUPHXMHG8r2z4tsDPR
2026-07-26 14:40:13 -04:00
Levi Neuwirth aef4e98c26 fix(typed-edit): close round-8 review on the consumer chain
Five defects in the chain itself, plus the stale handoff state.

Each consumer now gets its own shallow copy of the typed-edit record.
Handing everyone the same table let a DECLINING consumer rewrite
provenance for the ones behind it, and pairing decides what to close
from `rec.char` — so a forged `char` turned a typed `x` into `x)`.
Every field is a scalar or an opaque id, so a shallow copy is complete.

The fan-out iterates a snapshot of the consumer list. It was iterating
the same array `add_consumer` mutates: a consumer that registered a
lower-priority one shifted itself forward under `ipairs` and ran twice,
and re-registering made that unbounded. Registrations and removals made
during a fan-out now take effect on the next one, stated as a contract
and pinned in both directions.

`tostring` on the caught error moved inside the containment. A Lua
error may be any value, including a table whose `__tostring` throws —
rendering it outside the `pcall` reintroduced exactly the escape the
containment exists to prevent.

Priorities are validated as finite integers in i32 range, matching
`pmacs.completion.register`. NaN is a number and every ordered
comparison with it is false, so a NaN consumer landed wherever the
insertion scan gave up and silently voided the lowest-first ordering
that Q#LN22 depends on.

`add_consumer` returns a handle and `remove_consumer` unregisters it,
reporting whether it was live. Without teardown the chain inherited the
`pmacs.hook.add` callback leak COHERENCE.md §13 already records, and
spread it to every consumer.

Also corrects the rationale the containment was documented with, in the
module, the test, and the framing: an uncontained throw does NOT take
the fan-out's other subscribers down. `run_all_must_succeed`
(src/hook.rs:332) collects errors and continues, so lsp.lua still
flushes didChange. The containment is still required — the throw skips
every later consumer in the chain — but the reason is narrower than
rev 7 claimed.

Criteria 46f (record isolation), 46g (snapshot iteration), and 46h
(lifecycle and priority validation) added; 46d's rationale corrected.
Four new tests, all bite-verified by mutation, each failing only its
target: shared record table (1), live-array iteration (1), unprotected
tostring (1), bare number check (1), no-op removal (2). The suite also
runs green under `--features lua54`.

docs/agent-handoff.md said Stage 4a was awaiting approval while this
branch had it implemented and in review.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 13:39:33 -04:00
Levi Neuwirth c4fad0731c docs(lean4): rev 7 — round 6 review, five P1s, and reconcile the ledgers
The 4a/4b split held; five P1s against rev 6's own content, all real,
all reproduced. Four share a root: rev 6 verified its external facts and
under-verified its internal ones.

1. Stage 4a's declared footprint excluded the tests its own acceptance
   required. 46a-46e cannot live in tests/auto_pair_acceptance.rs,
   which criterion 46 requires byte-identical. Footprint now names
   tests/typed_edit_chain_acceptance.rs and gates on it.

2. Pending abbreviation state had the wrong owner. pmacs is
   multi-frontend: EditorCore.views is per-FrontendId with its own
   active window, take_typed_edit is already frontend-keyed, and
   buffer.after-switch fires with no arguments — so a buffer-keyed
   clear-on-switch lets any frontend discard another's pending
   abbreviation. Now keyed (frontend, buffer) with a window check,
   frontend-scoped clearing, a frontend.detached purge, and acceptance
   45i, which the buffer-keyed design passes every other criterion
   without.

3. The shortest-match rule was missing its tie-break: upstream keeps
   declaration order among equal-length shortest keys, and 101 prefixes
   have equal-shortest candidates resolving to different symbols (f
   picks f< over f>). A pairs-iterated Lua map cannot express this, so
   the vendored artifact is now an ordered sequence and resolution sorts
   by (#key, source rank). Rev 6 missed this because it declared the
   package ships no README after a 404 on the package root, with the
   directory listing showing src/README.md already in hand — a 404 on a
   guessed path is not evidence of absence, and the README states the
   rule in one sentence.

4. The generator's rejection rule rejected the current table: \ is a key
   and " begins eleven, while acceptance 45d requires \ to work.
   Replaced with canonical lossless escaping; aborts only on duplicate
   keys, invalid UTF-8, and a failed self-round-trip. 45g no longer
   claims to diff against abbreviations.json, which is not shipped.

5. Durable and volatile state were not reconciled. agent-handoff.md
   anchored main at d152120 with neither #167 nor #170 and no Lean arc
   bullet at all; active-work.md kept 407 lines of merged Stage 1/2/3a/3b
   history against its own instruction to prune merged entries, under a
   stale snapshot date. Durable facts moved to the handoff; the ledger
   keeps only the unlanded Stage 4 lane.

Also corrected: 119 multi-codepoint symbols (26 with $CURSOR), not 93;
three backslash values, not two; Q#LN22 now states the terminating-\
reprocess rule acceptance 45d depended on; acceptance 38 says the
terminator is retained, so undo restores "\alpha " with its space;
coherence cites golden-journey step 5, not step 4; and the
config-registry prior art points at Q#LN22.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
2026-07-26 10:39:01 -04:00
Levi Neuwirth 23486fd572 Merge main, and fold #173's a37 findings into the CI-coverage lane
Integrates githubsucks/main @ cf54270 (terminal config Stage 1, #173).
Both conflicts were additive appends to the same lists — the handoff
preamble and the ledger's "Closed since the last snapshot" — so both
sides are kept and the preamble now leads with #173.

Also records what gating #173 measured about a37, because it changes
this lane's proposed fix rather than merely annotating it:

a37 reports `ok` without running whenever `pmacs-gpu` is absent from
the target directory. A fresh worktree reports the Stage 3 suite 9/9 in
0.17 s having never executed the arc's only real-daemon/real-PTY/real-
wgpu path; a genuine run takes about four seconds. Only
PMACS_REQUIRE_GPU=1 promotes that skip to a failure, and the standing
gate list applies that flag to `cargo test -p pmacs-gpu`, a different
package. So fix-shape part 2 must state the flag as a requirement of
the gpu-render job: a crdt leg added to the plain `test` job would run
a37 vacuously and report green.

a37 is also load-sensitive — it passed at d152120 and failed at that
same commit twenty minutes later under machine contention — which makes
a red first CI run ambiguous by construction. The lane now says to
re-run on the merge base before believing a failure, and to prefer
serialized execution over retry-until-green.

The vterm audit's "only 3 of 9 Stage 3 tests drive a real daemon" is
corrected: without the frontend binary the honest number is 2.

Ledger: terminal config Stage 1 flipped from IN REVIEW to MERGED.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gGQC6eqHJVbZJ5Hg7aLer
2026-07-26 09:29:42 -04:00
Levi Neuwirth 5b58e9a994 Merge remote-tracking branch 'githubsucks/main' into docs-dired-stage1-landed 2026-07-25 21:05:24 -04:00
Levi Neuwirth 4fbd47f025 docs: refresh the handoff's Stage 2 status (COHERENCE §25)
`docs/agent-handoff.md` §1 still said Stage 2 "needs its own
re-framing". It is framed, so that line would be false on `main` the
moment this branch merges.

It now records the approved shape — protocol v21, two serial slices
(2A census routing + painter extraction, then 2B wire/projection/band/
capability flip), parent acceptance 37-55 still authoritative — and
carries the census classification rule itself, since that is the fact
the ledger previously got wrong and the one a future reader is most
likely to re-derive incorrectly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 19:49:19 -04:00
Levi Neuwirth 39233aa25f Merge canonical main (#172, #157) into the docs lane
Both conflicts were competing rewrites of the same anchor lines: #172
refreshed the canonical base and the handoff header while this branch
did the same for #165. Resolved by taking main's list, which is the more
accurate of the two (it names Lean 4 Stage 2 #161 properly), refreshing
it to the current tip `ccf29e3`, and keeping this branch's note that
lanes naming an older base have not been re-based.

#172 also removed the inline-math lane, so the stale-header note drops
from three back to two and now says who owes the remaining updates.
2026-07-25 19:49:18 -04:00
Levi Neuwirth 7247f647c0 Merge canonical main (#158, #156) into the docs lane
Both conflicts were docs-only and resolved as unions, with one repair
taken from main: #156 fixed a pre-existing corrupted duplicate of the
"GPU initial target LANDED — #148" bullet in the handoff, whose tail ran
into the protocol-version text. This branch still carried the broken
copy, so the resolution keeps main's repaired `- Protocol **v20**` bullet
and drops the stub, along with main's now-superseded "Stage 1 IN REVIEW
as PR #165" sub-bullet.

Refreshed the canonical base to `d152120` and widened the stale-header
note from two lanes to three: #158 merged but its lane still reads
"PR #158 OPEN".
2026-07-25 18:22:07 -04:00
Levi Neuwirth adf10cc9c3 docs: record the inline-math slice (#158) as landed
Brings the three required docs current after #158 merged, and discharges
the follow-up that framing named for itself.

COHERENCE.md section 16 audits the claim that the GPU frontend exceeds
the TUI "under real divergence pressure" without a privileged frontend
emerging. Inline math is the sharpest instance of that so far -- the GPU
typesets $...$ while the TUI shows LaTeX source, and the TUI fallback is
a named deferral. Section 25 makes that update ride the PR, so the
enumerated list gains the case along with what keeps it inside the rule:
the slice reserves no protocol version and adds no wire surface, so the
divergence is presentational and both frontends read the same model.

docs/inline-math-framing.md carried a licence error the slice framing
flagged in its own section 9 and deliberately did not fix in-branch,
since the parent is a merged document. Latin Modern Math is under the
GUST Font License, not the OFL; the row now says so and records the
~717 KiB bundled size.

docs/agent-handoff.md records the landing and re-anchors section 1 to
d152120. The bullet leads with the facts a fresh agent would otherwise
have to rediscover: the whole slice lives in pmacs-gpu because pmacs-gpu
depends only on pmacs-protocol and never on pmacs; the v0 subset is 34
Greek symbols, sub/superscript and \frac; an unsupported command fails
the WHOLE span back to source, so most inline spans in a real paper
still show LaTeX by design; and math is suppressed while the caret is
inside its span.

docs/active-work.md removes the merged lane per its own update protocol
and adds a Closed entry. Four things there are reusable beyond this arc:
a stale frontend binary is invisible from the source tree, so diagnose
with strings on the binary rather than by re-reading a checkout that is
already current; the dangerous integration was the one that did NOT
conflict, so decide from the shared-file set rather than from whether
git complained; integration is proved by predicting the other side's
test-count delta and checking it; and m4_5_basedpyright has no timeout,
hangs forever, and is intermittent, so an earlier clean sweep proves
nothing. It also corrects a claim I recorded on main: the branch's
missing CI was not an unidentified cause -- a conflicting PR builds no
merge ref, so no pull_request run is created.

Docs only; no code changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZjWMjwPXhPbt9upku9mCk
2026-07-25 18:16:31 -04:00
Levi Neuwirth a72ce72349 Merge canonical main into the bottom-panel landed-doc lane
`main` moved through #158-#166 (Lean 4 Stage 2, COHERENCE.md, find-file,
the dired framing and Stage 1, the GPU terminal input fix) while this
documentation branch waited. Both required docs conflicted; neither
conflict was a code signal.

Resolution:

- `docs/active-work.md`: main's ledger is the base — every lane it has
  gained since this branch was cut is kept verbatim. Only the
  bottom-panel lane is replaced with this branch's "Stage 1 MERGED;
  Stage 2 (GPU band) is next" section, and only the bottom-panel entry
  is added to "Closed since the last snapshot".
- `docs/agent-handoff.md`: main's version is the base. This branch's §1
  bottom-panel bullet, its §1 roadmap Arc 7 entry (which also records
  that DAP is now unblocked), and its four §5 ops lessons are inserted
  at their anchors.

One repair rides along. Main's `docs/agent-handoff.md` carried a
garbled fragment at §1: a duplicated, truncated "GPU initial target
LANDED — #148" bullet whose body was the tail of the old head-of-`main`
anchor bullet, leaving the `SUPPORTED=[6..=20]` protocol enumeration
orphaned mid-sentence. The fragment is removed and the enumeration is
restored as its own bullet.

No code changes; the merged tree's non-doc content is main's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 17:47:51 -04:00
Levi Neuwirth ea0632412e docs: record dired Stage 1 (#165) as landed
#165's own commits could not update the handoff snapshot to name the
merge that contains them, so the protocol obligation lands here.

- `docs/agent-handoff.md`: absorb the dired lane into §1, replacing the
  placeholder that promised exactly this. The bullet carries Stage 1's
  durable substrate facts — why the tolerant `read_dir` had to be Rust,
  why exposing the core normalizer beat mirroring it in Lua, the
  fixed-width `_layout` contract Stage 3 reads offsets from, the
  ambient-action buffer guard, treating a failure as the answer instead
  of probing, the per-entry error cap, the first mode-scoped keymap and
  the pre-existing test it broke, and the dedication a descent does not
  carry. Refresh the head-of-`main` anchor and the last-updated line.
- `docs/agent-handoff.md` §5: two ops lessons that cost real time. A fix
  must be committed before it is bitten, because `scripts/bite` restores
  by `git checkout --` and reverts to HEAD; a CONFLICTING PR runs no CI
  at all, because `pull_request` workflows build a merge ref GitHub does
  not create while the branch conflicts, and nothing reports the absence.
- `docs/active-work.md`: remove the merged lane per update-protocol rule
  4 and summarize it under "Closed since the last snapshot", keeping the
  two forward items Stage 2 needs (the rename rebind is first-match-only
  over a raw path, and Q#DR5's seam is the main-thread drain). Refresh
  the canonical base. Flag the two lane headers that still call a merged
  PR "IN REVIEW" — #161 and #166 — rather than editing lanes another
  thread owns.
- `COHERENCE.md`: #165 is no longer a PR. Per §25 the audited claims this
  work changed were updated when it landed; this corrects their tense in
  seven places and the two prose lines that still asserted dired was in
  flight.
- `docs/dired-framing.md`: status line to MERGED, and state plainly that
  Stages 2 and 3 each still need their own framing.

Docs only; no code, no gate-relevant change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0126d2sikA6jZpFin3rtLCSK
2026-07-25 17:39:27 -04:00
Levi Neuwirth 40709fafb9 docs: measure the CI coverage gap and record the vterm as-framed audit
The lane opened in the previous commit was scoped to the Vterm Stage 3
acceptance. Measuring it properly shows the problem is much larger and
not vterm-specific.

Comparing cargo test --list under CI's exact flags against the same
flags plus crdt: 3,024 versus 3,288. 264 tests are dark in CI, and the
single worst line is the library itself at 177 -- cargo test --lib
--features crdt is a required local gate that CI has never run. Ten
suites run zero or one test, including gpu_initial_target (#148's entire
acceptance, 1 of 14), gpu_invocation (#141's, 1 of 14), and a37, the
Stage 3 real-daemon/real-PTY/real-wgpu path that #135 built precisely
because a decoded-message fixture would prove none of the three fit
together.

The lane now carries the per-target table, the verified flag combination
for the fix, a two-part fix shape (a crdt leg on the test job, plus the
GPU-requiring suites onto the existing gpu-render job that already has
lavapipe), and an explicit instruction to sort deliberate exclusions
from accidental ones first -- some of the 264 are perf suites that are
ignored by default and belong to their own jobs, while m10_10_perf has
no ignore attribute and no job naming it.

docs/vterm-framing.md gains an as-framed audit section. The arc is
structurally complete and every test named in the Stage 2 verification
map exists, but criterion 22's "without thrash" clause was never pinned
anywhere -- the word appears nowhere in src or tests -- and that clause
describes exactly the defect #166 fixed. Of the nine Stage 3 tests, only
three drive a real daemon, so the six that construct EditorState
directly could never see a dispatcher-loop defect; a31 passes on the
broken tree for that reason. Four of the nine, including a37 and Stage 3
review round 1's own presence regression guard, do not run in CI at all.
The section also records what was not audited: section 11's blanket
claim about deferral safety covers roughly twenty items and none were
spot-checked.

docs/gpu-terminal-input-framing.md scores bet B2 true now that the
reporter has confirmed typing works, and retracts Q#GT5. The bash fixture
behind it does not reproduce in real use and was almost certainly
measuring its own timing rather than a product behaviour; it is marked
retracted rather than deleted so nobody re-derives it from an earlier
revision.

docs/agent-handoff.md section 5 gains the lesson the confirmation cost:
a daemon-side fix is not deployed until the daemon is restarted from a
tree containing it, and rebuilding a binary does nothing to a running
process.

No code changes.
2026-07-25 17:17:23 -04:00
Levi Neuwirth 1c9904e217 Merge canonical main (#166) into the dired Stage 1 lane
Main moved again while this lane was gating: the GPU terminal-input fix
merged as #166. One conflict, in COHERENCE.md's journey table, resolved
as the union -- this lane owns step 7's file half, #166 owns step 8's
GPU-terminal addendum.
2026-07-25 16:41:21 -04:00
Levi Neuwirth 8c924ebf41 docs: record #166 as landed and open the CI-coverage lane
The handoff snapshot and the active-work ledger both still described the
GPU terminal input work as in review. Per their own update protocols this
should have ridden #166; it did not, because the review that surfaced the
CI-coverage finding came after that PR was already green, and expanding
an approved PR to carry a new lane would have been the wrong trade.

docs/agent-handoff.md section 1 gains the #166 entry: the split into a
frontend-kind-neutral liveness half and a grid-only geometry half, the
extracted dispatcher loop body, the trap about the no-placement release
that reads like liveness and is not, and why the one-line guard was
rejected.

docs/active-work.md moves the lane to "Closed since the last snapshot"
and opens a new one: the Stage 3 real-path acceptance is dark in CI.
The workflow never enables the crdt feature, so every crdt-gated
acceptance test is not merely skipped but never compiled -- which covers
a37 (real daemon, real PTY, real wgpu) since #135 as well as the two
tests #166 added beside it. The fix is one step on the gpu-render job,
but it needs its own lane because it would run a37 under lavapipe for
the first time, and neither its timing budgets nor its wgpu path have
been exercised on that adapter. The lane also asks which other
crdt-gated suites are dark for the same reason.

Recorded alongside it: #166's three unit pins are not crdt-gated and do
run under CI's exact flags, including the controller-release pin whose
only job is catching the plausible wrong fix, so the regression
protection is live even though the real-daemon evidence is local-only.

No code changes.
2026-07-25 16:17:24 -04:00
Levi Neuwirth adf90e5351 docs: record the GPU terminal input fix in the three required docs
COHERENCE.md section 25 and the handoff/ledger update protocols make
these ride the PR.

COHERENCE.md:
- Section 6 named one optimistic key classifier and attributed it to the
  GPU. There are two, one per replica frontend:
  crate::optimistic::classify_key belongs to the pmacs --attach TUI
  replica, and pmacs-gpu has its own unrelated optimistic_insert_text /
  optimistic_crdt_insert. The section's "kept honest by
  dispatch_idle_for" claim is confirmed for both, which this
  investigation verified rather than assumed.
- Section 16 graded per-frontend degradation strong on the evidence of
  per-frontend fold projection. That grade stands, but the practice is
  enforced by convention rather than structure, and this defect is the
  counter-example; the note says so and points at what is now structural.
- Section 2 step 8 records that the terminal was broken outright on the
  GPU frontend, not merely undiscoverable.

docs/agent-handoff.md section 5 gains four lessons: adjacency does not
make two operations alternatives (and two individually sound idempotence
guards can be jointly useless); bite against every pre-image the fix
could have taken, since the obvious guard here fixes the storm and
introduces a controller leak; a quiet child is an instrument, because a
frame storm hides inside a chatty fixture and a geometric readout is
satisfied by an oscillating geometry; and TerminalMode::Raw makes
sh-based input fixtures useless because there is no ICRNL.

docs/active-work.md gains the lane entry with the branch, the bite
matrix, the named out-of-scope items, and the gate results.
2026-07-25 15:28:47 -04:00
Levi Neuwirth 8b685dc127 docs: record dired Stage 1 (PR #165) and what it falsified
docs/dired-framing.md rev 6: §0 gains the Stage 1 implementation notes
(S1-1..S1-9) -- the normalizer is exposed rather than mirrored (so B2 is
false by one small binding, in the direction Q#DR2 preferred); R2-3's
dedication claim is falsified by the display policy; acceptance 3c
cannot pin the descent routing and now says so; dired is the first
builtin to bind a mode-scoped key, which one pre-existing lib test
assumed impossible; `C-x d` takes no completion source on purpose;
ownership is the handle table alone; the mark column ships blank; a
symlinked directory needs a probe; and interactive origin does not
survive an await.

COHERENCE.md, per its §25 (an audited claim this PR changes updates
here, riding the PR): §1.1's interactive-file-opening fact, §2's journey
step 7, §4's beginner-level `files`, §14's tree bullet (Stage 1 landed a
flat listing and did NOT invent a tree convention), and §15's Priority 1
list. Step 3 stays **Missing at the CLI** with the mechanism spelled
out: `pmacs .` still exits 1, and this arc deliberately does not claim
the CLI path -- it supplies the buffer a directory should resolve to.

docs/active-work.md: the dired lane rewritten for Stage 1, including why
the branch is a fresh cut rather than a rebase of `dired`, the durable
substrate facts, the bite results (one VACUOUS, recorded rather than
relabelled), and the verification. Its canonical-base line was four
merges stale and now names 8c86d34.

docs/agent-handoff.md: one forward pointer only. The handoff describes
merged state, so it absorbs the substance when this merges.
2026-07-25 15:08:24 -04:00
Levi Neuwirth 7c01c93226 docs: dired arc framing (revision 5) + post-merge doc refresh
Lands the approved dired framing on main as its own docs PR, and brings
the two required docs current after find-file merged as #162.

The framing was approved after two review rounds (seven findings, then
six) and revised twice more since: revision 4 recorded what implementing
Stage 0 falsified in the approved text, and revision 5 adds the coherence
impact statement that #163 made mandatory for every framing.

The coherence statement is new work, not a restatement. COHERENCE.md
section 20 Priority 1 already names this arc -- a find-file surface and
directory-argument handling -- so the framing now states which journey
steps it touches (7, and partially 3), that it adds no interaction island
because its keys are a mode-scoped keymap through the ordinary registry
and wdired is a mode swap rather than a modal layer, that it adopts the
config registry for dired.kill-when-opening, and that it inherits the
worker-attribution gap for its read_dir jobs without worsening it. It
also draws the boundary against the adjacent Journey Stage 1 arc: CLI
directory handling belongs there, the two meet at resolve_target_buffer,
and dired supplies the buffer a directory should resolve to rather than
growing a second directory surface.

One convergence worth recording: section 2 grades the golden journey
broken at step 3 because pmacs on a directory exits 1, and the mechanism
it cites -- File::open succeeding on a directory, then read_to_end
returning EISDIR -- is the same one Stage 0 pinned in its
accepting-a-directory test, where the pcall turns it into a status
message instead.

The handoff snapshot was stale through eight merges. It now anchors on
main at 2af1ab3, records COHERENCE.md as required reading and a required
framing input, and carries the two minibuffer facts find-file
established: a custom completion source cannot descend directories, and
a selected candidate shadows typed text -- both of which apply to M-x and
switch-buffer, not just find-file.

The ledger gains the dired lane with Stage 1's scope, the reason its one
Rust change cannot be done in Lua, and the rebase note for the dired
branch, whose framing commits become redundant when this lands.
2026-07-25 14:09:49 -04:00
Levi Neuwirth 7f7ad1934c docs: record bottom-panel Stage 1 (#155) landing
Handoff §1 gains the arc entry: the window-parameter substrate, the two
production `Layout::compute` callers, the recursive minima, hiding as a
durable transition, per-window input gating, the per-frontend jump
origins, and the shared initial-target load seam. §5 gains four durable
lessons, three of them the same class:

- a guard with no production caller passes every direct-call test;
- a geometric readout (`at_bottom`) is not a state predicate;
- a PTY does not translate LF to CRLF, so text equality over clipped
  output is vacuous;
- widening an ambient resolver into a scoped one can make a total
  function partial — which is what took CI red on all four Test jobs.

The roadmap position, the arc's named deferrals, and DAP's unblocking
are recorded too.

active-work closes the lane, refreshes the canonical base to `e745068`,
and keeps Stage 2's named obligations plus the two gating facts found on
the way (the sweep needs an isolated XDG_CONFIG_HOME; compile_mode
acceptance is load-sensitive, verified pre-existing).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 20:33:32 -04:00
Levi Neuwirth dcef343702 docs: record GPU initial-target (#148) landing
Move the lane from active-work.md into its Closed section, retire the
protocol v20 / main-hash references to LANDED form in agent-handoff.md, and
record both review-round lessons (failure-socket containment, upgrade-gated
replica publication) in the ops-lessons ledger.
2026-07-24 11:21:50 -04:00
Levi Neuwirth 6c06815ee4 Merge githubsucks/main into gpu-initial-target
Integrate folding Stage 2 and its landed-state documentation with the
protocol-v20 GPU initial-target branch. Preserve per-session fold projection
selection in the target bootstrap transaction and retain v19 compatibility
coverage after the later protocol bump.
2026-07-24 10:21:37 -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 7fc7420b91 docs: record folding Stage 2 (#149) landing; open the Stage 3 lane
Post-merge housekeeping owed from #149, kept as its own docs-only PR per
the #138-#140 / #147 convention. No runtime code.

- active-work.md: base snapshot and the recovery check bump 47581f4 ->
  6ed4fe9. The Stage 2 lane is retired and replaced by a folding lane that
  records both stages as merged with nothing in flight, and states Stage 3
  (GPU) has no branch and no framing yet — carrying its named obligations
  (GPU collapse at TUI parity, caret/hit-test fold-awareness, the
  BufferSnapshot fold-mirror clear, CRDT-origin unfold, and flipping
  FrontendView.fold_projection true for semantic frontends) as that
  framing's starting point. "Closed since the last snapshot" gains #149
  and #147.
- agent-handoff.md §1: main @ 6ed4fe9, the "Last updated" line and section
  date, the Stage 2 bullet flipped from IMPLEMENTED/PR-OPEN to LANDED with
  the Stage 3 obligations attached, and the roadmap entry (remaining arcs
  now read "6 folding Stage 3").

Both stages' design points are recorded as traps Stage 3 inherits rather
than as history: the merged-hidden-component unit, per-window/per-target
map instances, per-frontend projection, position-not-row normalization,
and the post-intercept edit site.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
2026-07-24 09:58:10 -04:00
Levi Neuwirth f16d72fded docs: refresh the ledger to current main and Stage 2's real state
PR #149 review round 5 flagged this PR as stale: it still claimed `main`
@ `c49a8c7`, Stage 2 framing "rev 2, under review; no implementation, no
PR", while `main` is `47581f4` and Stage 2 is implemented and open.

- Base snapshot and the recovery check bump `c49a8c7` -> `47581f4`.
- The folding Stage 2 lane becomes IMPLEMENTED / PR #149 OPEN: framing
  rev 4 approved, the `VisibleLineMap` spine, the base-moved merge (and
  why it was merged rather than rebased), and the five review rounds'
  design-changing findings — each of which is a trap Stage 3 inherits.
- `main`'s ledger had gone unrefreshed through four merges, not one, so
  "Closed since the last snapshot" now also records web grammars HTML +
  CSS (#146) and LaTeX Stage 1 (#144) with its inline-math framing
  (#145), including their durable lessons.
- agent-handoff §1: `main` @ `47581f4`, the "Last updated" line, the
  Stage 2 substrate bullet, and the roadmap entry.

Rebased onto `47581f4` so it stays one documentation-only commit
directly off canonical main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
2026-07-23 21:58:02 -04:00
Levi Neuwirth 5f7270d26a docs: record folding Stage 1 (#142) landing; open Stage 2 lane
Post-merge housekeeping owed from #142, kept as its own docs PR (no
runtime code).

- agent-handoff.md §1: bump main to c49a8c7, add the folding Stage 1
  substrate bullet (store/View, structural source, C-c @ surface,
  command-path unfold, FoldState production; no protocol bump), refresh
  the "Last updated" line and the roadmap Arc 6 entry, and note Stage 2
  is in framing on folding-tui (the visible-line-map reframe).
- active-work.md: retire the Stage 1 folding lane (PR #142 was OPEN),
  add a "Closed since the last snapshot" entry for #142, open the
  Stage 2 (grid/daemon collapse) framing lane on folding-tui, and
  refresh the canonical base snapshot to c49a8c7.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
2026-07-23 21:58:02 -04:00
Levi Neuwirth bef1c08133 fix(gpu): preserve session isolation during target publish
Keep foreign BufferSnapshot publications out of existing semantic GPU
sessions while retaining grid-replica coherence. Treat dead peer writes as
peer-local failures, restore active-frontend cleanup, deterministic probe
readiness, GPU logging, shared tilde expansion, and accurate docs.

Add focused publication and cleanup coverage and record the two-window
Wayland/Vulkan smoke plus the complete post-review gate results.
2026-07-23 21:25:33 -04:00
Levi Neuwirth 19674a47ea Record integrated GPU target verification
Update the framing, durable handoff, and active-work ledger after integrating
current canonical main and completing the required gates and real GPU smoke.
2026-07-23 19:13:34 -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 d9669746c1 Record one-command GPU invocation landing
Advance the durable snapshot to merge 63fbc66, record the green CI rerun, and
remove the completed GPU invocation lane from the volatile active-work ledger.
2026-07-23 13:33:09 -04:00
Levi Neuwirth 78339352d4 Record second GPU invocation review closure
Advance the framing to Revision 6 and record the strengthened non-CRDT,
Ctrl-C, strict-operand, probe-throttling, and PID-cleanup contracts. Update the
durable and volatile checkpoints to implementation commit 154cb9f.
2026-07-23 12:40:03 -04:00
Levi Neuwirth 9136538df9 Record exception-safe GPU daemon ownership
Advance the active and durable checkpoints to 69825d0 and clarify that every
spawned managed daemon enters the named reaper before connection or handshake
work can fail.
2026-07-23 12:06:53 -04:00
Levi Neuwirth c0ec8f75c2 Record GPU invocation review closure
Advance the framing to Revision 5 and record the reviewed lifecycle, CLI, and
acceptance contracts. Update the durable and volatile handoffs with checkpoint
82355ca and the completed verification matrix.
2026-07-23 11:54:28 -04:00
Levi Neuwirth e5ef205977 Record GPU invocation review checkpoint
Update the durable handoff and volatile active-work ledger for open PR #141, including the implementation checkpoint, accepted architecture, verification record, visible Wayland/Vulkan smoke, and cross-machine recovery commands.
2026-07-23 11:06:20 -04:00