§14 said references, outline, buffer-list and project-search all use
listview. Measured at ad41cf1, there are exactly three
`pmacs.listview.open` call sites and all three are in
builtin/runtime/lsp.lua: *references* (:2056), *outline* (:2102) and
*lsp-help* (:2513). buffer-list and project-search are not consumers.
The document already knew this and contradicted itself. Twenty lines
below the claim it says "(*workers*, *help* and *buffer-list* are
generated but do not use this idiom.)" The second statement was right.
The other three `listview` mentions under builtin/ are comments in
compile.lua and dired.lua citing "the listview idiom" — a pattern being
copied, not the primitive being used. Counting imitators as adopters is
what produced the wrong number, and it has a concrete cost: the
erroring-intercept pattern those comments copy is exactly the one the
Output-channel bullet directly below records as NOT read-only. The
copies inherited the defect without inheriting the primitive.
Why this matters beyond the count: it changes the remediation. A
primitive with three sibling call sites in one file is a good primitive
with an adoption problem, not a missing one — the work is migrating
buffer-list and search onto it rather than building anything. The grade
moves from ✓ to ◐ for that reason, and the scorecard row now carries the
narrower claim.
Two consistency fixes ride along: the §6 picker/panel parenthetical
listed two of the three listview panels and now lists all three, and
line 503's "listview is Lua-usable" is left alone because it is about
extensibility and is accurate.
No runtime code. No other open PR touches this file — verified across
all four branches — so this does not enter the active-work contention.
Revision 5 was reviewed and not approved. Round 5 has one theme, not
six: rev 5 changed the slice split and the ownership of a decision, and
the prose did not follow. Four of the six findings are that same defect
in different places. All six verified against the tree before acting;
two are understated by the review.
R1 (P1) — rev 5 was superseded by its own ledger entry and by a PR body
older still. active-work.md:507 records Q#DR25 as moved out of this lane
(dired's paint is one instance of a CLASS bug — the same
erroring-intercept-over-writable-rope idiom is in listview, compile and
search/grep, and no Lua caller anywhere sets read_only because there is
no Lua set_read_only), while the framing still called it mandatory and
assigned it to 2b, and the PR body still described revision 1's
two-slice plan. All three reconciled: Q#DR25 is withdrawn, §3.1 becomes
a handoff to the generated-buffer-immutability lane, and the PR body is
rewritten. Also corrected in the other direction: rev 5's claim that
Q#DR25 "closes dired's quarter" of the §14 gap was itself wrong — dired
was never a quarter of anything.
R2 (P1) — acceptance allocation contradicted the code split, and the
review undercounts by one. Items 23-24 test apply_resource_op and the
drain harvest (2a substrate) but sat under a 2b header; item 33 needs a
dired.lua subscriber while 2a is defined as containing no dired code.
23-24 moved to 2a; 33 moved to 2b, because 2a's whole review rationale
is that its diff contains no dired code. The cost is stated: between 2a
and 2b a directory rename leaves dired handles stale, which is the
status quo and not a regression. The undercount: that leaves 2a shipping
resource.renamed with no acceptance, so item 50 pins the hook contract.
R3 (P1) — TickOutcome could not carry deletions. Replaced the two ad-hoc
vectors with one ordered Vec<ResourceOp>, and PendingJob carries a
single Option<ResourceOp>. Ordered because a directory rename and a
delete beneath it can settle in one tick; one enum rather than two
Options because two admit a both-Some state that cannot occur, the
argument ResolvedTarget's own doc makes at editor_core.rs:100-102.
R4 (P1) — reconcile_delete stopped short, and the substrate is worse
than the review says. Right that removal is two phases; what it does not
say is that NO existing Rust path composes them. pmacs.buffer.kill
(mod.rs:5476-5491) does, and its doc says it is late-bound precisely to
redirect windows — but apply_resource_op uses remove_buffer_and_fire,
which is phase 2 without phase 1, and BufferRegistry::remove touches
only buffers and order. So an LSP-authored delete leaves a displaying
window pointing at a removed id: a third defect on that arm. §6 now
specifies both phases, the last-buffer and ConcurrentEdit refusals, and
items 51-53.
R5 (P2) — the "every consumer" claim was false for Lean. The deferral
was right and the summary was wrong; fixed the summary. Stage 2 supplies
the hook, Lean's state stays stale until its owner adopts it.
R6 (P2) — pre-three-slice file inventory. minibuffer.lua joins
src/editor.rs's include_str! sequence, so 2b touches a Rust file; "2b is
dired.lua plus one killring binding" was false. + and C retagged 2c.
The sweep the review asked for caught four more stale labels it had not
cited: §4's "C (copy, 2b)", §7's "(in 2b) a recursive delete", §8's op
sections, and §8's d/x line — which was wrong in BOTH halves, saying 2a
where it meant 2b and 2b where it meant 2c, a pure two-slice-era
leftover. Historical round sections keep their original labels, flagged
rather than retconned.
The ledger lane rides this PR and is updated to match.
Status unchanged: PROPOSED, needs explicit user approval. Do not merge.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
PROPOSED. Framing only; no runtime code.
Buffer::undo gates on ensure_writable() and never consults the intercept
chain, so the add_intercept "read-only" idiom leaves the rope writable
and the owner's own bypass_intercept paint on the undo stack. Four writer
mechanisms across five buffer families are affected; every one was
reproduced by execution at ad41cf1, not inferred.
The document carries the measured reproductions, the full classified
census with its arithmetic shown, the primitive decision with numbered
alternatives, per-criterion bite obligations, and the staging proposal.
Recommended primitive: Buffer::apply_generated_edit(op), exposed as a
{ generated = true } option on the existing Lua mutators, with
set_generated_contents reimplemented as its whole-buffer wrapper. It is
the only candidate in which the buffer is never observably unlocked.
Docs-only and one m4 test fix; no overlap with the daemon projection.
Integrating now so CI builds a real merge ref for the head SHA.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
The lane described the pre-re-scout state: head ab42a79, 1,570 lines,
"re-scout under way", and a five-owner rename census. All four are now
wrong. It rides this PR rather than a standalone refresh, because a
separate ledger PR with several others open re-conflicts on every merge.
What the lane now records:
- Head e7f811b, 2,304 lines, integrated to main @ ad41cf1, status
PROPOSED and never formally approved — four revisions and three review
rounds are not approval and must not be read as one.
- Seven of rev 4's own claims about pmacs were wrong. The load-bearing
one is kept in full because it is a trap anyone can repeat:
drain_external_cancelled (:1561) and drain_cancelled_externals (:1596)
are two different functions 35 lines apart, and rev 4 named one while
citing the other's line. Following the citation gives the per-tick
token sweep instead of the unconditional server-scoped drain, so the
drain half becomes a silent no-op and the awaiting coroutine hangs.
- The path-owner census is six, not five. The sixth is lean.lua's
M.file_progress, a URI-keyed Lua table in no Rust store, which is the
first evidence outside dired that the hook rather than the Rust method
is what scales.
- The journey ratchet is split across journey_acceptance.rs and
gpu_invocation_acceptance.rs; both are gates, and a scout checking only
the first concludes #183 added nothing.
- open_directory now commits under pmacs.window.commit_to, whose scope
refuses an await, which constrains the proposed batch contract.
Scope moved OUT of this lane: Q#DR25's adoption of
set_generated_contents turned out to address a class bug shared with
listview, compile and search/grep, so it is owned by the
generated-buffer immutability lane now. This PR needs a rev 6 deferring
Q#DR25 there once that framing is approved.
Also records two live bugs this lane confirmed but does not fix, both
owned elsewhere: apply_resource_op's delete arm destroying unsaved work,
and View still lacking rename_resource.
`clippy::format_collect` rejected the generated body; the replacement
was shorter than the hard-coded caret offset, so the caret landed past
the end and the focused half stopped exercising the clamp. Derive the
offset from the body instead of restating it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
Q#BP16 step 3 compares an inbound event's geometry epoch against BOTH
the declaration the frontend was looking at and the daemon's latest
accepted one, and mutation testing showed the second half unpinned: no
fixture made the two diverge, so deleting it changed nothing. They
diverge exactly once — between a declaration being accepted and the
next frame answering it — which is the font/scale/resize race the epoch
exists for.
Also pins the attach/resize gate change at the seam it would break: a
semantic frontend's `Resize` must mint no frame geometry even when its
view is panel-capable, while a grid frontend's real frame size still IS
its declaration.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
Bottom-panel Stage 2B-2, second half: the producer, the presentation
epoch, and the three inbound event gates.
The producer lives beside the terminal pass in `semantic_render.rs` and
follows its shape: compare the complete payload first, validate only a
payload that differs, and store only what was actually shipped. The
presentation epoch is allocated from the side window and its buffer, so
a new side window, a replaced buffer, and every `Absent` -> `Present`
transition each take a fresh identity; `Absent` clears the identity,
which is what makes close/hide/reopen of the SAME persistent buffer
unaddressable by a stale `PanelPointer`. Allocation is checked and
exhaustion fails closed to `Absent` rather than wrapping into a live
identity. The `Absent` baseline is seeded rather than left empty: a
fresh session has no band, so the opening state is a fact the peer
already holds.
The band rides both render paths and does not wait for a declared byte
viewport: it is a separate surface, and gating it on the document
declaration would leave the first panel unpaintable. Its mode line takes
the side window's segments from the SAME provider invocation that serves
the document's wire segments.
Inbound, `peer_may_send_panel_events` checks four facts together — an
installed semantic projection, the negotiated version, the daemon's own
capability bit, and (via the transport source) that the payload's
claimed id is never consulted. `panel_event_epochs_are_current` then
runs Q#BP16 steps 2-4 as one predicate so no caller can check the
geometry epoch and forget the presentation epoch.
Two daemon gates moved from `panel_capable` to `!semantic_render`. Stage
1 could conflate them because panel capability implied grid; now that a
semantic view can be panel-capable, a capability-keyed gate would feed it
the permanent 24x80 attach placeholder that Q#BP15a forbids, and parent
acceptance 40 would fail through the attach line rather than through the
projection. Not a live defect — no production semantic session is
panel-capable yet — but it is the landmine Stage 2B-3 would have stepped
on.
`panel_capable` is unchanged for production negotiation and the
unsolicited `Hello` still advertises v20. Nothing here is reachable by a
user.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
PR #185 merged during the re-scout, so `docs/active-work.md`,
`docs/agent-handoff.md` and `COHERENCE.md` are no longer held by an open
PR. #185 changed docs only — no source — so nothing in rev 5's census
moves, and the two facts rev 5 cites from the durable records survive
intact: the handoff §4 inventory still names `builtin/runtime/dired.lua:371`
as a non-adopter of `set_generated_contents`, and COHERENCE §14 still
names dired and still classifies it as the cheap half.
This branch continues to touch only `docs/dired-stage2-framing.md`. A
standalone docs-refresh PR is exactly the ledger contention treadmill
the ops lessons warn about, and the ledger's own protocol puts a lane
refresh with the work rather than ahead of it.
What §16 now records instead: the landed `docs/active-work.md` lane
still has this branch at head `ab42a79`, calls the document 1,570 lines,
says the re-scout is under way, and states the rename census as FIVE
path owners. Rev 5 makes all four stale — and the census is SIX (§5,
W5). Same lesson in the other direction: a census is a reading, not a
constant. The refresh should lift §5's table rather than re-derive it,
and should note that Q#DR25 added scope the lane does not mention.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
`main` moved mid-re-scout: #174 (fix-m4-sink-races) merged. It touches
`tests/m4_acceptance.rs` only and changes no source, so nothing in the
rev 5 census moves — but it intersects this document at one point, and
in the direction that strengthens it.
#174 fixed the CONFIG sink by waiting for a complete JSONL record
(`ends_with('\n')` instead of `contains("probe")`) and deliberately left
the ROOTURI predicate alone, adding a comment at
`m4_acceptance.rs:5486-5496` giving the same three reasons §11's
deferral gives: it is the same weak-predicate class, it has never been
observed failing, and waiting for the expected value would trade a
precise regression diff for a vague five-second timeout. Closing it
needs a record terminator in the fake server first.
So that deferral is no longer a claim of this framing; it is a claim of
the tree. Item updated with the current line (`:5499`, shifted by
#174's own comment) and the in-tree backing.
The header now records both anchors: the census was read at `6bee09d`,
and it holds unchanged at `0442d78`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
Rev 4 was scouted at c8ec8f3, which is dired Stage 1's own merge commit.
Canonical main has moved 153 commits since. This is that re-scout. Every
claim below was read on the tree at 6bee09d, not inferred.
Four dependencies arrived that rev 4 could not have known about:
- #178 landed `Buffer::set_generated_contents`, and dired has NOT
adopted it — the handoff §4 and COHERENCE §14 both name
`dired.lua:371` in the non-adopter inventory. Dired pairs an erroring
intercept with a bypass_intercept write over a still-writable rope, so
`M-x buffer.undo` empties a listing today, with no keybinding needed.
Stage 2 writes that buffer on every mark. New decision Q#DR25 adopts
the primitive at the head of 2b, with acceptance items 48-49.
- #182 (Journey Stage 1a) demoted dired to a replaceable slot
(`pmacs.path.directory_handler`, deliberately not a hook subscriber)
and rewrote `open_directory` around `pmacs.window.commit_to`, whose
scope REFUSES an await. That constrains §9's serialize-and-await batch.
- `tests/journey_acceptance.rs` is a declared ratchet (24 tests, "stages
add rows, none removes them"), seven rows assert on dired, and #183
put the GPU row in `gpu_invocation_acceptance.rs` instead — so the
ratchet is split across two files and both are gates now.
- #179/#181's typed-edit chain: dired participates in neither it nor
`buffer.after-edit`, and `set_generated_contents` fires no hook, so
Q#DR25 does not drag dired onto the chain. The chain's lessons still
bind §5's two NEW hooks.
Seven of rev 4's own claims about pmacs were wrong:
- W1 (load-bearing): §5 named `drain_external_cancelled` and cited
`lsp.rs:1596`. Those are two different functions.
`drain_external_cancelled` (:1561) is the unconditional server-scoped
drain and is the right precedent; `drain_cancelled_externals` (:1596)
is a per-tick token/timeout sweep. A rename flips no token, so
following the line number yields a `forget_uri` whose drain half is a
silent no-op and the awaiting coroutine hangs forever — the exact
failure step 2 exists to prevent.
- W2: there is no `fn restart`. The teardown is `start_generation`
(:1307-1345), and there is a second precedent rev 4 never named,
`LspManager::forget` (:3015-3042). Neither clears the 14 result
stores, so rev 4's "surprising" note now holds twice.
- W3: `ResponseRoute` has 15 variants, 14 URI-bearing; there are 16
insert sites, 15 URI-bearing. Rev 4's fifteen was a correct count of
URI-bearing inserts and an incorrect count of sites. The purge
predicate must retain `WorkspaceSymbol { query }` explicitly.
- W4: `rec.uri` is read at 57 lines in lsp.lua, not "~20".
- W5: the path-owner census has grown to SIX. `lean.lua`'s
`M.file_progress` is a URI-keyed Lua module table in no Rust store, so
`forget_uri` cannot reach it — independent evidence that the hook, not
the Rust method, is the mechanism that scales.
- W6: the ledger note named PR #169, which merged. #185 holds the
durable records now.
- W7: the C1 seam is at mod.rs:7104-7115, and mod.rs defines three
`_tick` bindings in different classes.
The 2a/2b/2c/Stage-3 cut was re-examined and holds unchanged; §16 adds
the ownership warning that 2a overlaps editor_core.rs, lsp.lua and the
URI-keyed LSP state with Journey Stage 1b and must not run concurrently
with it. §0.5 now cites COHERENCE §20 Priority 1 and §14 by number, and
records that #182 put dired on journey step 3 — a claim rev 4 could not
make.
Status is stated honestly: PROPOSED, never formally approved, and
needing explicit framing approval before any implementation branch.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
Bottom-panel Stage 2B-2, first half: the daemon-side primitives the
panel producer needs.
`GeometryUpdate` is three-valued rather than a boolean because the
caller must act differently on each arm. `declare_frame_geometry` stays
the grid/LOCAL allocator, keeps value dedup, and moves from
`saturating_add` to checked allocation with a fail-closed exhaustion
arm: it clears the declaration back to unknown, which is already
non-presentable, so reconciliation hides the panel rather than painting
one sized to a frame that no longer exists.
`accept_frame_geometry` is the separate semantic path. No value dedup —
a font or scale change can invalidate a panel frame while `CellSize` is
identical, which is exactly what daemon-side dedup cannot see (Q#BP2S1)
— and a lower epoch is rejected even when it carries identical data.
`panel_grid_size` derives Q#BP15a's third geometry: full declared
width, `fixed_rows` clamped by the recursive document minimum and then
by the shared wire area budget, with the stored request left alone.
`prepare_panel_projection` paints the side window through the Stage 2A
extracted painter, gating folds on the OWNING frontend rather than
`fold_map_for_window`'s active-frontend gate (Q#BP17), and takes the
side window's statusline segments as a parameter so one provider
invocation serves both surfaces. `window_cursor_cell` is `paint_frame`'s
caret derivation lifted out so the band does not become a second,
drifting copy of it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
#174 merged while this PR was open, so the lane it had just been given
is already a merged lane. Rule 4 removes those rather than relabelling
them — but only once the durable facts are in the handoff, so do both
here in that order.
docs/agent-handoff.md
- §5 gains the lesson: a wait predicate WEAKER than the assertion it
guards is a race on whichever platform loses it, and "wait until the
file mentions X, then assert Y" races whenever Y is stricter than X.
- Two things that generalize past the fix ride with it: a race you
cannot reproduce can still be bitten at one remove (an unsatisfiable
predicate proves the wait is load-bearing; the old predicate still
passing proves a local run cannot tell them apart), and the obvious
fix is sometimes worse — the sibling m4_26 is deliberately left alone
because closing it the easy way trades a precise assertion diff for a
vague five-second hang.
- Header and §1 anchor advance to 0442d78, noting #174 is test-only and
#184 remains the substantive change at that head.
docs/active-work.md
- Remove the #174 lane; the header paragraph now says where it went.
- Canonical base and recovery floor advance to 0442d78. The floor
explicitly rejects 6bee09d as well as 7fd646d, per its own rule that a
check accepting an older commit than the declared base passes on a
tree the file does not describe.
- Bottom-panel lane: 2B-2 is IN FLIGHT, not merely "next" — branch,
worktree, and the fact it is branched fresh rather than stacked. Its
boundaries are restated because they are easy to overrun: production
Hello stays v20, panel_capable stays false, and 2B-3 may not simply
bump the unsolicited Hello.
- dired lane: the re-scout is under way on the existing branch, so #171
keeps its three-round history and the product is a rev 5.
- Both lanes note that main advancing to 0442d78 changes nothing for
them, since #174 is test-only.
The bottom-panel framing doc keeps its 6bee09d ground-truth line: that
is a scouting statement about what was actually read, and re-anchoring
it to a commit nobody re-scouted against would be a false claim.
Neither #174 nor #171 had any entry in this ledger. An open PR is
exactly the volatile work the file exists to record, so its absence is a
defect rather than a tidy omission — #171 drifted 153 commits while
invisible here, and its still-green old CI run describes a tree nobody
has looked at since.
#174 — M4 config-sink race, revived and regated. Records the predicate
fix, the gate numbers on the integrated head 302c21c, and two things
verified rather than inherited: the "one writeln! is the only writer"
argument re-checked against a fake_lsp that DID change upstream, and the
wait bitten two ways (unsatisfiable predicate fails on the pump deadline;
the old predicate still passes locally, confirming a green local run
cannot tell them apart).
#171 — dired Stage 2 framing, stale, do not merge as-is. Measured 4
ahead / 153 behind with merge base c8ec8f3, which is itself #165's merge
— so dired Stage 1 and find-file are its base, not new arrivals. Names
the three landed changes that move ground under it: #178's
generated-buffer write invariant (dired is a non-adopting writer),
#182's demotion of dired to a replaceable directory-handler slot, and
#179/#181's typed-edit consumer chain. Restates the five-path-owner
rename transaction the framing still has to answer.
Also records that three review rounds in a commit history is not the
same as approval, and that dired 2a's file overlap with Journey 1b needs
assigning before either runs.
PR #184 (bottom-panel Stage 2B-1) merged, but the four documents that
new work is supposed to start from still described it as open. Advance
every canonical anchor and close the one obligation that was blocking a
lane removal.
docs/agent-handoff.md
- §1's head-of-main anchor moves 7fd646d -> 6bee09d.
- State schema support and production advertisement as two separate
facts: SUPPORTED is now v6..=v21, the server-first Hello still says
v20, and #184 landed only the first.
- New §1 bullet for Stage 2B-1 carrying its durable substrate: the
server-first incompatibility argument, the shared wire_grid boundary
and why per-axis caps are a parameter, authoritative Absent, and the
panel_epoch / geometry_epoch split.
- New §1 bullet for the PTY terminate diagnostic (#176), plus two §5
ops lessons: a drain that ticks is not an observation, and how to
prove a child exited without waitid or unsafe.
docs/active-work.md
- Canonical base and the recovery floor both advance to 6bee09d.
- Remove the #176 lane. It was retained only because rule 4 requires
its facts to reach the handoff first; that move is in this commit, so
the lane goes.
- Rewrite the bottom-panel lane as 2B-1 MERGED with 2B-2 next, branching
fresh from landed main rather than stacking.
- Annotate the documentation lane with measured staleness (1 ahead, 320
behind) without deleting it, since nothing has decided its fate.
docs/bottom-panel-stage2-framing.md
- Status header records 2A and 2B-1 as merged and 2B-2 as next. No
revision bump: the header is landed state, and no design decision in
the document changed.
COHERENCE.md
- §16 names #184 as the PR that landed the reserved v21 family.
No runtime code, no protocol change, no gate suite implicated.
Capture the follow-up review finding, the evidence-driven completion
contract, the exact corrected CAT duration, and the proportional green
gate matrix at 9c79ce1.
Let producer probes name the frame text they require while input probes
finish on their latched echo observation. Report and assert whether the
probe reached that evidence so the 20-second safety deadline cannot
masquerade as successful completion.
The CAT acceptance now finishes in 0.32 seconds instead of waiting out
the full deadline, while the VTERMROW producer still waits for its own
PTY breadcrumb.
Capture the exact review-fix and GPU probe checkpoints, the full green
gate evidence, and the classified sandbox-only socket failure in the
cross-machine active-work ledger.
Keep the real GPU/PTY acceptance probe running until the child output
that its report asserts has actually reached the terminal frame. This
closes the blank-last-frame race exposed by the v20-compatible handshake.
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.
Record the complete post-#183 gate matrix for bottom-panel Stage 2B-1
at c8895a8 and mark the lane ready to open for review.
Retain the required-GPU first-pass classification: one unrelated math
render assertion failed, passed immediately in isolated single-threaded
execution, and the mandatory complete 202-test rerun passed.
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.
Capture the managed daemon's lifecycle facts from the ready report before
waiting for the post-quiescence directory snapshot. If that regression
assertion times out, the acceptance harness can now terminate the daemon
instead of leaving it orphaned.
Drive pmacs --gpu . through the root broker and real managed GPU
connector, keep the session alive through the asynchronous dired
replacement, and assert its canonical listing before daemon reuse.
Expose snapshot count and materialized text through the private
display-less acceptance probe so the public path is observable.
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.
Capture the complete green gate matrix and retain the diagnosed setup
and transient full-sweep failures so the lane remains recoverable and
the evidence is not flattened into an unexplained rerun.
Replace the stale directory-negative in the GPU initial-target suite
with an explicit snapshot-first readiness path, while retaining all
genuinely malformed and unloadable failure cases. Record the portable
side-quest and bottom-panel dependency state.
Make the statusline and Vterm Stage 3 acceptance suites track the
bottom-panel v21 bump, including the real daemon and headless GPU probe.
Record the full gate result and the unrelated stale directory-target
assertion reproduced on canonical main.
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.
The ledger preamble already says Lean 4's merged lane was removed, and
the durable Stage 4b facts already live in the handoff. Remove the stale
section that still called Stage 4b in review so PR #182's post-merge
state is internally consistent.
Rev 4 §9 scoped Stage 2B as a single PR: v21 protocol, daemon panel
projection, GPU band, and the negotiated `panel_capable` flip.
Implementation showed that to be roughly four thousand lines across
three crates with three different failure modes. Rev 5 splits it into
2B-1 (the wire layer), 2B-2 (the daemon projection and epoch machine),
and 2B-3 (the GPU band and the flip), on the rule that a slice ends
where the next thing to build has a different authority.
No decision changes. What changes is the allocation:
- §7.2 becomes three subsections, and criteria that span a boundary are
named in every slice they touch with their half stated, rather than
assigned wholesale to one. Parent 39 is the clearest case: its
shared-validation and transport-budget halves are wire properties
provable in 2B-1, while "the previous valid frame is retained" and "a
duplicate does no work" need the epoch machine and are 2B-2. A2B-1
splits the same way — grid exhaustion in 2B-2, the frontend latch in
2B-3.
- §9 lists four serial PRs instead of two, each cut from `main`, and
states that every slice runs the full gate set rather than the subset
its own crate suggests.
- §6 records which slice pays the coherence debt. The journey claim
belongs to 2B-3 alone: with `panel_capable = false`, a GPU user still
gets the Stage 1 non-side fallback after 2A, 2B-1 and 2B-2 have all
landed. Three quarters of this stage is preparation.
Two things recorded because they are easy to inherit silently:
- This revision is retroactive for slice 1. `bottom-panel-stage2b`
already carried the v21 protocol layer, written before the revision
existed, which inverts framing -> approval -> branch -> implement. The
slicing was sound; taking it in code rather than in the document is
how a stage's scope drifts without anyone deciding that it should.
- 2B-1 and 2B-2 ship dark. The bump advertises a capability whose only
distinguishing feature is unreachable until 2B-3, so the arc must not
stall between them. Safe for compatibility — appended variants,
extended ladder, a v20 peer still negotiates 20 — but a stall should
be visible as a decision, not inherited as a default.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LFvC4FQtux4y32KuevZ7B
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>
A count is a reading, not a constant. Recorded as of rev 8 with an
explicit instruction to re-read rather than quote the line.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>