P1 — THE PROTOCOL-BUMP GATE WEAKENED THE SWEEP IT MEANT TO STRENGTHEN.
Revision 1 said `--tests --no-fail-fast` REPLACES the `--workspace`
line. Measured: `--tests` selects 108 targets, `--workspace` selects
110, and the two it drops are `pmacs_protocol` and `pmacs_gpu`. On a
PROTOCOL bump, dropping the protocol crate's tests is the wrong loss —
and it also silently dropped `--skip basedpyright`.
Worse, this lane's own remediation sweep used `--tests`, so it never
ran pmacs-protocol's 25 tests, including the `scroll::classify` tests
this lane had just written. They pass (verified 25/0), but by luck. A
correction that reproduces the shape of the mistake it corrects is
worth naming, so §3 and §5 both say `--workspace`, additive, with
`-- --skip basedpyright` retained in both feature configurations.
P1 — NO COORDINATE CONTRACT FOR view_left. Revision 1 decided what
moves the viewport and never said what its offset IS — the same
omission as shipping WrapMode with no DisplayCoord. Its verification
sketch named tabs and wide characters with no oracle for either,
because nothing defined what a left edge is.
Q#HS7 is new and BLOCKING, in four coupled parts: the unit; which
columns may be a left edge; the snap rule for an invalid one; and the
invariant rendering and coordinate mapping share. Votes recorded —
display column (tab stops come free, since the walk must start at
column 0 either way and a byte offset buys nothing); a left edge may
not fall inside a wide glyph; snap toward the line start (snapping left
can only reveal a character, snapping right can hide the one the user
scrolled to reach); and snap when the value is SET, not in the painter,
so one canonical value serves both readers.
Part (d) is why it blocks: if the painter clips where the mapper does
not, clicks land on the wrong character — silently, and only on lines
wide enough to scroll.
P2 — THE CAVEAT IS NOT IN THE SETTING DESCRIPTION. Revision 1 said it
was. builtin/runtime/linewrap.lua:23 says only "truncate at the edge";
"unreachable" lives in the toggle's status message and a source
comment, neither of which a user sees who sets the mode in init.lua.
That is a real, small user-facing gap shipped in #221. Claim corrected,
and amending the description is now a Stage 4 deliverable (§6) with the
text depending on which stage has landed.
THE THREE ANSWERS, recorded with the reasoning that decided them:
HS1 — GPU is Stage 5. The distinction that matters is that Stage 3's
defect was never "the frontends differ" but "the frontends differ and
nobody chose that". Time box made concrete per the request: Stage 5
is the immediately-next QoL lane, `wrap` stays default until it
lands, release notes state the asymmetry, and the truncate
affordances name the GUI gap meanwhile.
HS2 — automatic only. No command surface; the cursor-visibility pass
gains a horizontal component.
HS6 — `wrap` stays default, and the reason given is stronger than the
one revision 1 reasoned from. I had framed it as "if scroll makes
truncate good, reconsider the default". With the GPU deferred, a
truncate default would ship a mode navigable in the TUI and a dead
end in the GUI for every user who never opened the setting. HS1 and
HS6 are coupled: the split is only safe because the default does not
move.
Q#HS4 is deferred rather than closed — not live under automatic-only,
but the snap-back hazard is real and rediscovering it costs more than
carrying the paragraph. Q#HS5 stands, with the caveat that §1.4 cites
the struct shape and not serde's behavior on a missing field.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai