Advance the volatile ledger to the current canonical base and record the
portable Revision 1 framing checkpoint, scope, recovery command, and approval
boundary.
Round 2 correctly found the Finding-2/3 fixes were unpinned (reverting
them left the suite green). Both are now bite-verified:
- **Kill-path purge (Finding 2).** Replaced the direct
`forget_buffer(id)` unit test with
`killing_a_buffer_through_the_real_path_purges_its_fold_store`, which
drives `pmacs.buffer.remove` — the production route through
`after_buffer_removed` — and asserts the store is gone via the dead id
(BufferIds never recycle). Mirrors config_registry's real-kill-path
test. Bite-verified: reverting the `after_buffer_removed` fold branch
turns it red.
- **close-all point move (Finding 3).** Added
`close_all_command_moves_point_to_enclosing_head`, which invokes the
`fold.close-all` command with the point inside the second of two
top-level fns and asserts the cursor landed on that fn's head-line
content end (and both folds exist). Bite-verified: reverting close_all's
`maybe_move_point` loop turns it red.
- Ledger: `docs/active-work.md` folding lane now records PR #142 OPEN +
the two landed review rounds (was "opens once the gate suite is green").
Correction to the round-1 gate report: the acceptance suite is **21**
tests (round 1 was 20, not 24 — a tally slip), green under default and
`--features crdt`. Full gate suite otherwise green (fmt, clippy
--workspace --all-targets, git diff --check).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
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.
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.
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.
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.
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.
Q#FD4 settled: the user chose Emacs hideshow parity, so Stage 1 ships the
`C-c @` prefix set (`C-c <letter>` is fully taken by the LSP surface; the
hs-minor-mode prefix collides with nothing). §6/§9 now list the five
bindings; §0 records the rev 4 -> rev 5 approval note; §14 records the
rebase onto canonical `main` @ 96d0bae at implementation start. Bet B1
accepted as framed. active-work.md folding lane flipped to APPROVED /
Stage 1 implementing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5BkezMppbpCgGAYk2ftxV
One major, three minors, and a nit from the third review, all fixed:
R3-1 (major, derived head line): rev 3's head-selection ascend was not a
no-op for brace languages — rustfmt wraps long signatures
(fn foo( / a: u32, / ) -> bool {) and puts { on its own line under where
clauses, so block.start_line > parent.start_line, the ascend fired, and
the fold hid the wrapped signature: the R2-5 defect class one level up.
Replaced by a derived head line — the interior comes from the body node
alone (closer-aware tail unchanged) and the head is the line immediately
above the first hidden line (B.start_line - 1 for an introduced
delimiter-less body, B.start_line otherwise). Emacs hideshow / LSP
foldingRange parity: the fold hides the body, nothing else. The
introducer<->body association survives for matching and close-all only.
Acceptance 1 gains wrapped-signature cases in both grammar shapes.
R3-2: "innermost-first" on a shared head line made the outer fold
unreachable via fold.toggle (close inner, reopen inner, forever) and
allowed zero-visible-change presses. Replaced by state-aware ordering:
close acts on the innermost open fold, open on the outermost closed
fold, toggle cycles org-TAB-style (close inward-out, then open all).
Acceptance 9 updated.
R3-3: Stage 1's "command path" is dispatch_key self-insert/delete only;
interactive Lua commands (yank, query-replace, comment-toggle) mutate
through the Lua mutator path and classify programmatic, so their edits
land inside a fold without unfolding. Stated as the intended Stage 1
line; widening the classifier to interactive Lua command contexts is a
named Stage 2 obligation beside Stage 3's CRDT-origin unfold.
R3-4: the data API's normalization of an arbitrary range is now defined
(head = line containing start; hidden = full lines strictly after it
through the line containing end, exclusive of an end at a line start).
Nit: stored-range containment pinned start-exclusive/end-inclusive with
the matching View boundary bias, so typing at the end of a head line
neither unfolds nor lands hidden; acceptance 6 asserts it.
Also: Sec 14 records that canonical main has advanced past the cac4961
base (docs + tab-width #137, no Stage 1 overlap; rebase at
implementation start), and the active-work folding lane is brought
current (head was stale at rev 1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ledger inherited from #135's merge still listed Vterm Stage 3 as an
open 'never merge without authorization' implementation lane; it is merged
(main @ cac4961), so per the update protocol it moves to Closed and Arc 5's
terminal stage is marked complete. Adds the folding framing lane (branch
folding, off cac4961, framing-only) and points the canonical base at
cac4961 / protocol v19.
Advance canonical state to protocol v19, close the Vterm lane and roadmap arc, preserve the cross-PR integration lesson, mark PR #91 landed, and point machine-local housekeeping at the durable policy.
vterm-stage3-framing (superseded; content carried on vterm-gpu) and
tab-width-parity (merged via #137) were deleted with authorization —
worktree + local ref + githubsucks ref, origin tracking pruned. The
-framing branches for each are kept. Retires the now-dangling
superseded-lane recovery entry.
Integrates canonical `main` @ 2625ec7 after PR #137 (tab-width parity)
merged. The agreed order was #137 first, this lane second: #137 was
approved and FROZEN at 5b23e11, and "frozen" is incompatible with
"rebase onto the resulting main" — landing it second would have broken
its freeze and voided its approval.
Integrated by MERGING main into the branch rather than rebasing, matching
repo precedent (Merge canonical main into vterm-tui, ... into modeline
detection). A rebase would have force-pushed away the review anchors on
the two completed review rounds of #135.
Main had also moved past this lane's base by #133/#134/#136, so the
integration surface was wider than the #135/#137 overlap: src/
semantic_render.rs was a fourth overlapping code file. It auto-merged, as
did pmacs-protocol/src/lib.rs. The single code conflict was the
pmacs_protocol import list in pmacs-gpu/src/main.rs — TAB_STOP_COLUMNS
against the terminal types — resolved as a union.
The feared semantic collision did not occur, and this is verified rather
than assumed: terminal cell geometry still uses the monospace advance and
never TAB_STOP_COLUMNS. pmacs-gpu/src/terminal.rs references neither the
constant nor display_width, and terminal_cell_viewport / terminal_run_rect
/ hit_test_cell derive from mono_advance() and code_line_height() alone.
That separation is correct by construction: a terminal's columns come
from the child, while tab expansion is a document projection concern.
Doc conflicts resolved toward landed state: the tab-width lane moves to
"Closed since the last snapshot", the #135/#137 coordination section is
kept as a resolved worked example, and the Arc 5 lines in the roadmap and
handoff now read "implemented and in review". While resolving, restored a
clause main had dropped from the handoff's injection-follow-ups list
("literals, doc-comment code);"), keeping main's strikethrough-and-SHIPPED
convention for the modeline entry.
Post-integration gates, from a clean tree: cargo fmt --check; strict
workspace clippy; pmacs-protocol 17; cargo test --lib 1,768; --features
crdt 1,944 (3 ignored each); vterm Stage 1 9/10, Stage 2 4/4, Stage 3
5/7, statusline 7/8, tab-width 2/2 (default/CRDT); M4 121 passed (3
ignored, 1 filtered); required GPU 139; workspace sweep 2,946 passed
across 84 suites (19 ignored), one invocation; git diff --check clean.
PR #137 (tab-width-parity) is approved and frozen at 5b23e11. Neither
lane copies from or merges the other; whichever lands second rebases
onto the canonical resulting main and reruns the complete gate suite.
The overlap is pmacs-gpu/src/main.rs, pmacs-protocol/src/lib.rs,
Cargo.lock, and the two ledger docs. The lock and docs are mechanical;
the two source files are not — both PRs edit the GPU renderer's
measurement path and widen the protocol crate's export surface in the
same region, so a conflict-free apply is not evidence of a correct
merge.
One real defect, three cleanups, and a named deferral.
A daemon disconnect in terminal mode hid the disconnect notice. The
Disconnected arm set the placeholder text but never left terminal mode,
where the document code layer is not prepared at all and the terminal glyph
layer keeps painting its last frame — so the user was left looking at a
frozen, live-looking terminal that silently ignored input. GPU auto-reconnect
is a named deferral, so that state persisted until relaunch. State::
on_daemon_disconnected now leaves terminal mode, forces a repaint even when
the notice text is byte-identical, and requests a redraw.
The fix and its test share a file, so scripts/bite's file granularity cannot
bite it; the equivalent was done by hand. Neutralizing only the
exit_terminal_mode() call makes the test fail on the "must leave terminal
mode" assertion; restoring it makes it pass.
sync_semantic_terminal_layout no longer clones the whole visible cell grid to
read one size. It ran every dispatcher tick for any semantic frontend with a
declared terminal; TerminalManager::screen_size reads the value from the
borrowed projection instead.
Inbound terminal events now require a negotiated v19 session. The outbound
TerminalFrame was gated twice while TerminalResize/TerminalPointer relied on
the frontend's send gate alone. A pre-v19 peer cannot construct those
variants, so this only refuses a hand-rolled client — and the a32 forgery
tests already prove such an event reaches nothing but the sender's own
authenticated active view — but the asymmetry was not deliberate.
A terminal-mode press that misses the grid no longer arms a drag, so a later
in-grid motion cannot send a Drag with no preceding Down. Daemon-side impact
was nil; the state is now honest. A release still always ends the drag.
The roadmap and handoff Arc 5 lines still said Stage 3 was framed and
awaiting approval, contradicting this PR's own ledger. Both corrected.
Named deferral: terminal wheel gestures discard scroll magnitude. One winit
wheel event becomes one gesture regardless of the lines it accumulated, while
the document path scrolls by lines. Closing it means either N gestures
(chattier) or a magnitude field on the pointer event — a protocol change.
Neither belongs in this stage.
Gates: fmt; strict workspace clippy; 1,758 default + 1,934 CRDT library
tests; Stage 1 9/10, Stage 2 4/4, Stage 3 5/7, statusline 7/8
(default/CRDT); M4 120; required GPU 129; workspace sweep 2,923 across 83
suites; diff check clean.
Five findings, all addressed. One was a real defect; one prediction did not
reproduce and is documented as such rather than papered over.
Hover no longer claims durable terminal control (finding 2, the real one).
apply_terminal_gesture claimed the controller before dispatching, including
for Move, which does nothing. A semantic frontend reports motion at pixel
rate, so sweeping the mouse across a passive split's terminal took durable
control, and the next layout sync resized the shared PTY to that background
view's geometry — precisely the theft the controller rule exists to prevent.
Bare motion no longer claims; every deliberate gesture still does.
scripts/bite HEAD src/editor.rs on the new test is a clean behavioral bite.
The terminal-mode presence-sweep skip is removed (finding 1), but the
predicted failure did NOT reproduce. The review reasoned that skipping the
sweep freezes last_broadcast at the abandoned document position. It does
not: the buffer-follow clears the terminal declaration when it ships the
snapshot, so terminal_active is false on the tick a window first shows a
terminal, and the declaration cannot arrive until a later tick — the
frontend learns the buffer id from that very snapshot. One truthful sweep
always lands first. The real-daemon two-frontend test written to catch the
freeze passes against the pre-fix tree; the bite is vacuous and the test is
labelled a regression guard, not fix evidence. The skip goes anyway: it was
load-bearing on tick ordering and bought nothing, and removing it makes
"presence follows the frontend" structural.
Terminal motion is deduplicated by cell (finding 3). Sub-cell motion
resolved to the same coordinate and still crossed the wire, where every
event is a daemon-side gesture. Press and release re-arm the memo so the
first drag after a press still reports. Its unit test cannot bite — the
seam did not exist pre-fix — and says so.
Declarations record only once sent (finding 4).
terminal_declaration_if_changed is now a pure query;
note_terminal_declaration_sent records. A failed write is retried instead of
suppressed as already-declared. The existing a35 test caught the contract
change and now pins both halves.
Unchanged frames skip revalidation (finding 5). The complete-payload
comparison runs before validate; only validated frames are ever stored, so a
frame equal to the baseline has already passed. The chrome tail is factored
into terminal_chrome so both exits emit it identically.
Gates: fmt; strict workspace clippy; 1,757 default + 1,933 CRDT library
tests; Stage 1 9/10, Stage 2 4/4, Stage 3 5/7, statusline 7/8
(default/CRDT); M4 120; required GPU 128; workspace sweep 2,921 across 83
suites; diff check clean.
Mark PR #134 as shipped in the durable handoff, framing, and side-quest
backlog. Remove the completed volatile lane and advance the canonical recovery
anchor to the merge commit.
Vterm Stage 3 — the final vterm stage. A semantic frontend can now host a
terminal: the daemon ships complete validated cell grids, and pmacs-gpu
renders them with fixed-cell geometry, its own input path, and no document
projection at all.
Protocol v19 appends three variants after their enums' final v18 members:
InstanceMessage::TerminalFrame (daemon-gated), and FrontendEvent::
TerminalResize / TerminalPointer (frontend-gated). It is the first bump to
gate in both directions, so criterion 28 pins each filter independently and
byte pins on StatuslineSegments and MenuPointer guard the placements.
pmacs-protocol gains src/terminal.rs: the shared row/column/visible-cell/
grapheme/metadata bounds, TerminalProcessState, TerminalSelectionSpan, and
TerminalFrame::validate — the ONE structural policy the daemon runs before
emission and the frontend runs after decode. src/terminal/* re-exports them
so no duplicate type exists, and unicode-width becomes a workspace dependency
so the screen and the validator measure glyph columns with one table. A new
8 MiB aggregate glyph bound keeps the largest legal frame (measured:
13,437,863 bytes) under the unchanged 16 MiB transport cap rather than
widening every connection's allocation ceiling.
The semantic producer suppresses the whole document family for a terminal
buffer while keeping the status band, theme, font, statusline, menu, and
minibuffer, and compares the complete ordered payload rather than
screen_generation — scroll, selection, and process state all change without
advancing it.
Two things the framing did not spell out, both found by the real-daemon
acceptance:
The Viewport gate keys on the authenticated source's ACTIVE buffer, not the
buffer the message names. Viewport also aligns the window to what it
declares, so a stale document viewport in flight when a command opened a
terminal dragged the frontend straight back off it: the window oscillated,
every terminal declaration was refused, and no frame ever arrived, with
nothing logged anywhere.
The producer clears terminal mode on every exit path. The daemon uses that
flag to suppress CursorByte and the presence sweep, so an early return that
left it set kept both suppressed after the frontend returned to a document.
pmacs-gpu/src/terminal.rs is a pure cell-space paint planner, unit-testable
without a GPU. The renderer builds one shaped buffer per text run, so a wide
or cluster glyph's advance can never choose the next column's origin.
Criterion 37 needed a seam rather than a fixture: pmacs-gpu depends only on
pmacs-protocol, so attach::connect's reader sink was generalized and a
--headless-probe mode added. The acceptance drives a real daemon, a real
/bin/sh child, the real attach client, and real composited pixels in one
path — which is how both defects above were found.
Gates: fmt; strict workspace clippy; 1,757 default + 1,933 CRDT library
tests; vterm Stage 1 9/10, Stage 2 4/4, Stage 3 4/5 acceptance
(default/CRDT); statusline 7/8; M4 120; required GPU 127; workspace sweep
2,919 across 83 suites; diff check clean.
Replace the obsolete fail-closed locals note with the settled lexical-facts
contract and record the feature branch, verification, and recovery commands in
the active-work ledger.
Revision 8 of docs/vterm-framing.md was reviewed and approved on the
documentation branch vterm-stage3-framing. Stage 3 is implemented on this
branch, cut from canonical main, rather than stacked on that branch.
The framing locks additive protocol v19 (TerminalFrame, TerminalResize,
TerminalPointer), an 8 MiB aggregate glyph-byte bound under the unchanged
16 MiB transport cap, dual viewport declaration after every semantic
snapshot, authenticated per-view routing, and a fixed-cell native GPU
renderer. Criteria 28-37 are the scope of this branch.
Advance the durable baseline to PR #132, remove the completed volatile lane,
and record the shared language pin, bounded modeline contract, Vterm Stage 2
landing, remaining deferrals, and current roadmap state.
Integrate landed Vterm Stage 2 before the approved modeline merge. Preserve the
active modeline lane in the volatile ledger and record the full integrated gate
results.
Update the durable handoff and active-work ledger with the second-review
fix checkpoint and exact final gate evidence.
Co-authored-by: OpenAI Codex <codex@openai.com>
Advance the canonical base after the mode-system handoff merge and preserve
the draft modeline framing branch, checkpoint, scope, and recovery command.
Move mode-system wiring from the active ledger into the durable handoff,
refresh the side-quest priorities, and preserve the macOS acceptance lessons
from the final CI review round.
Align the durable handoff with the approved escape-prefix contract, record the performance and lifecycle hardening, update the Stage 2 verification map, and publish exact final gate evidence in the active-work ledger.
Merges canonical main up to 2e37c04 and records the second of the two
arcs that landed while this lane was open. Vterm Stage 1 (#126) was
already recorded; this adds the config registry and reconciles every
claim the two merges falsified.
Handoff §1: main pointer moved to 2e37c04, and a config-registry entry
covering the parts a future agent cannot re-derive from the code --- the
always-store rule and why the "equal-value set is a no-op" reading
silently voids a buffer-local pin; the two-scope model and the
no-ambient-buffer contract on get(name); explicit-dispose-only listener
lifetime and the absence of any MetaMethod::Gc; the InitCompleteFlag
freeze that kept editor.rs untouched; and the strict-registry /
lenient-wrapper split that preserves trim_on_save("yes") and
interval_ms(1500.7).
Handoff §5 gains two lessons. Tab width is a rendering-parity bug, not
a config gap: five sites across two crates with two different values,
and no tab expansion at all on the GPU main text path, so
editor.tab-width is the obvious-looking first adopter and is not one.
And "a test that never runs passes" --- pmacs.editor.save() is the raw
save while buffer.before-save fires inside the buffer.save COMMAND, and
save() no-ops on an unmodified buffer, which made two review-round tests
vacuous until the buffer was dirtied and the command invoked.
Handoff §6: the three config-registry-blocked deferrals are resolved
(the per-buffer auto-pair toggle shipped as editing.auto-pair), replaced
by the registry's own named deferrals --- persistence, list-settings, a
settings completion source, table-valued settings, the unmigrated scalar
setters, and a scope = "global" flag, since set_local is currently
accepted for autosave.interval-ms where a per-buffer value is
meaningless.
active-work.md: base pointer and recovery assertion moved to 2e37c04;
the Vterm Stage 2 lane is told to cut from current main rather than
643d1e1; a closed-since-last-snapshot section records the merged lane
and the parallel-lane result --- two arcs in sibling worktrees with the
shared files assigned one lane each in advance rebased with zero
conflicts, which is worth repeating and states its precondition.
side-quest-backlog.md: both original north-star items have now shipped,
so the board is re-ranked to locals-query processing, mode-system wiring
(promoted --- every editor resolve still passes &[], making it the
largest remaining scoping gap), and tab-width parity. The config-registry
entry is struck and tab width is split out of it, since listing tab
width as a config consequence is what made it look like a cheap adopter.
Documentation only: the diff against main touches no runtime code.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the portable Revision 7 branch, exact approved checkpoint, current state,
next implementation lane, and cross-machine recovery command. Preserve the
separate documentation-lane ownership boundary.
Co-Authored-By: Claude <noreply@anthropic.com>
Advance canonical main to the #126 merge, retire the completed active lane, and
record the landed headless terminal core plus the remaining TUI/GPU stages.
Record the addressed Stage 1 review, final branch head, full gate counts, and
clean behavioral bite while preserving the unmerged three-stage boundary.
Record the published Stage 1 implementation and documentation heads, open PR
#126, final verification, and the sequencing boundary for the later TUI and
protocol/GPU stages.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Advance canonical main and protocol state after PR #125, remove the
completed statusline lane from the active-work ledger, and mark the
first four roadmap arcs complete. Record Arc 5 stage 2 as the next
formal roadmap stage.
Co-Authored-By: Claude <noreply@anthropic.com>
Record the manually folded hardening changes, current feature head,
second review resolution, and final sequential verification counts.
Co-Authored-By: Claude <noreply@anthropic.com>
Update the volatile ledger with the rebased feature head, real TUI PTY
smoke evidence, post-rebase gates, review comment, and recovery state.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Record the exact feature head, PR #125, complete sequential gate results,
and clean recovery state for the statusline-segments review lane.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Mark CI run 29778967156 successful across all 12 jobs for exact PR head
5c202c5. Leave user review as the only remaining action and retain the
standing prohibition on unprompted merge.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Record the green logged workspace sweep, final diff audit, and matching
public/checkpoint head 5c202c5. Pin PR #123's full head OID and fresh CI
run so any machine can resume at CI or review without reconstructing
local state.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Record the green formatting, standalone Clippy, default and CRDT library,
M4 acceptance, live JSON/YAML provider, and required-GPU results for
checkpoint 5c202c5. Leave only the logged workspace sweep, final diff
check, and public PR-branch update outstanding.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Record checkpoint 5c202c5 after the one-line doc-markdown correction was
amended into the live YAML test commit. Preserve the first Clippy result
and its rerun state for cross-machine continuation.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Advance the portable JSON/YAML head to 3ef5e2e and record its clean rebase
onto canonical main f8096ff. Leave the full gates and public PR-branch
update as the only remaining work.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Define the canonical repository by URL and bootstrap a stable local
`githubsucks` alias instead of assigning authority to machine-specific
remote names. Record JSON/YAML checkpoint f99870e and the completed live
YAML provider plus bite evidence, leaving only rebase and full gates.
Keep AGENTS.md and CLAUDE.md synchronized so a fresh agent receives the
same recovery rule on any machine.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
Record the pushed JSON/YAML checkpoint and framing heads so a clean
machine can verify it recovered the intended state, and document the
existing-local-branch worktree variant.
Add synchronized agent bootstraps and a volatile active-work ledger so
another machine can distinguish durable project state from open
branches, local checkpoints, machine-only providers, and incomplete
verification. Record githubsucks/main as the canonical development
line, refresh the #124/protocol-v17 handoff, correct the current
keybinding reference for compile mode, and mark the July roadmap as a
historical snapshot.