Commit Graph

565 Commits

Author SHA1 Message Date
Levi Neuwirth 85cb905e97 docs(folding): frame Arc 6 folding (draft rev 1)
Draft framing for the folding arc, committed to the `folding` branch for
review before any implementation. Branch is cut from canonical main @
cac4961 (post Vterm Stage 3 #135).

The load-bearing finding: the bundled tree-sitter grammars ship no fold
query and no folds.scm — they export HIGHLIGHTS/INJECTIONS/LOCALS/TAGS
only. The roadmap's "tree-sitter fold ranges" premise is therefore not
free, so the fold source is a real decision (Q#FD1). The draft recommends
structural node folding (fold the nearest enclosing block-like node
spanning >= 2 rows), which reuses the existing parse trees for every
grammar and injection layer with zero per-language authoring; indentation
folding (grammarless fallback) and curated per-language queries (quality
pass) are deferred.

FoldState already exists in the protocol, declared but unproduced, with a
test pinning that it is never emitted; no frontend consumes it; gutter
markers are frontend-derived like the diagnostic sign bars, so no new wire
type is needed. Staged like vterm: Stage 1 engine (instance-side fold
model + structural source + Lua commands + FoldState production, headless),
Stage 2 TUI collapse+gutter, Stage 3 GPU at parity.

Numbered decisions Q#FD1-9, three falsifiable bets, named deferrals, and a
Stage 1 acceptance list. Awaiting review rounds; bindings (Q#FD4) and the
block-kind heuristic (Bet B1) are the two calls flagged for the user.
2026-07-23 09:51:38 -04:00
Levi Neuwirth 96d0baebb7
Merge pull request #140 from levineuwirth/docs-readme-refresh
docs(readme): refresh current capabilities
2026-07-23 00:25:23 +00:00
Levi Neuwirth 4eafaafde7
Merge pull request #139 from levineuwirth/docs-roadmap-housekeeping
docs: refresh roadmap and Vterm landed state
2026-07-23 00:25:06 +00:00
Levi Neuwirth 498f571941
Merge pull request #138 from levineuwirth/docs-v02-reference
docs(changelog): remove dangling prerequisite links
2026-07-23 00:24:47 +00:00
Levi Neuwirth a9af998e0b docs(readme): refresh current capabilities
Update the Status and Highlights sections through protocol v19, covering the terminal, themes, statusline, mode, config, modeline, syntax, and tab-width work shipped since the previous snapshot.
2026-07-22 19:54:22 -04:00
Levi Neuwirth e316ba3a27 docs: record Vterm Stage 3 landing
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.
2026-07-22 19:54:14 -04:00
Levi Neuwirth 1c3a50f785 docs(changelog): remove dangling prerequisite links
Keep the shipped API and remaining undo limitation descriptions self-contained after the untracked V0.2 prerequisite document disappeared.
2026-07-22 19:54:07 -04:00
Levi Neuwirth cac4961c73
Merge pull request #135 from levineuwirth/vterm-gpu
feat(vterm): protocol v19 terminal frames and a native GPU terminal (Stage 3)
2026-07-22 23:41:25 +00:00
Levi Neuwirth 27120e7540 docs(vterm): record the deleted framing/tab-width branches
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.
2026-07-22 19:13:02 -04:00
Levi Neuwirth 3c4d969aba Merge canonical main into vterm stage 3
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.
2026-07-22 17:39:58 -04:00
Levi Neuwirth 2625ec7486
Merge pull request #137 from levineuwirth/tab-width-parity
feat(render): unify tab-width projection
2026-07-22 21:05:07 +00:00
Levi Neuwirth 3618289633 docs(vterm): record the #135/#137 rebase-and-regate constraint
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.
2026-07-22 15:36:51 -04:00
Levi Neuwirth 9ff6a62623 fix(vterm): address stage 3 review round 2
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.
2026-07-22 15:33:26 -04:00
Levi Neuwirth 5b23e11f71 docs: link tab-width parity PR
Record PR #137 in the framing, durable handoff, active-work recovery ledger, and side-quest backlog.
2026-07-22 15:06:10 -04:00
Levi Neuwirth 3d28a31573 docs: record tab-width implementation lane
Record the proven implementation head, full local gate results, recovery commands, concurrent vterm overlap, and the advanced side-quest backlog.
2026-07-22 15:04:52 -04:00
Levi Neuwirth 9f7bc77f44 feat(render): unify tab-width projection
Share one fixed eight-column tab-stop contract across core and GPU renderers. Consolidate byte-to-display-column accounting, expand GPU code tabs with source provenance, align caret/hit/decoration geometry, and refresh minimap projection on edits.
2026-07-22 15:03:30 -04:00
Levi Neuwirth 50fd9a08e4 fix(vterm): address stage 3 review round 1
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.
2026-07-22 14:49:23 -04:00
Levi Neuwirth 9f2f0d5ccd docs: incorporate tab-width framing review
Make protocol-version constraints merge-order independent, require wrapped-tab decoration coverage, and explicitly exclude hover panel sizing.
2026-07-22 14:36:30 -04:00
Levi Neuwirth a8f1283581 docs: frame tab-width rendering parity
Define the fixed cross-frontend tab-stop contract, GPU source projection and mapping rules, core display-width consolidation, minimap behavior, and acceptance gates.
2026-07-22 14:25:19 -04:00
Levi Neuwirth 40111dc2b0
Merge pull request #136 from levineuwirth/locals-query-handoff
Record landed locals-query processing
2026-07-22 17:49:41 +00:00
Levi Neuwirth 6ad3b88854 docs: record landed locals-query processing
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.
2026-07-22 13:30:07 -04:00
Levi Neuwirth 1d0b46f023 docs(vterm): record the stage 3 pull request 2026-07-22 13:29:29 -04:00
Levi Neuwirth bdf2b6e4b4 feat(vterm): protocol v19 terminal frames and a native GPU terminal
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.
2026-07-22 13:28:35 -04:00
Levi Neuwirth 8cbb9f4377
Merge pull request #134 from levineuwirth/locals-query-processing
Process Tree-sitter locals queries
2026-07-22 17:24:49 +00:00
Levi Neuwirth e5db4a98f8 test: enforce locals-query coverage
Assert that every bundled local-sensitive highlight query has a non-empty,
compilable locals query. Clarify the upstream-parity worst-case complexity of
lexical reference resolution in the framing document.
2026-07-22 13:05:33 -04:00
Levi Neuwirth 08ea6a3e12 docs: record locals-query pull request
Link PR #134 from the durable handoff and active-work lane now that the
implementation is published for review.
2026-07-22 12:31:18 -04:00
Levi Neuwirth cdeb5fb7cd docs: record locals-query implementation lane
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.
2026-07-22 12:29:39 -04:00
Levi Neuwirth 47ffe5dcff syntax: process bundled locals queries
Compile grammar locals metadata, resolve lexical definitions and references
once per settled layer, and apply local property predicates in both highlight
producers. Restore non-shadowed JavaScript builtins while suppressing local
shadows, with lexical, viewport, render, and edit-freshness regressions.
2026-07-22 12:28:31 -04:00
Levi Neuwirth 42a28b90c7 docs: frame locals-query processing
Define grammar locals metadata, lexical resolution semantics, shared local
predicate filtering, settle-time caching, producer coverage, and acceptance
criteria for shadowed versus non-shadowed builtins.
2026-07-22 12:03:37 -04:00
Levi Neuwirth 8bd82981f5
Merge pull request #133 from levineuwirth/modeline-handoff
Record landed modeline detection
2026-07-22 15:47:15 +00:00
Levi Neuwirth 3adac8c4cb docs(vterm): carry approved stage 3 framing onto the implementation branch
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.
2026-07-22 11:46:45 -04:00
Levi Neuwirth 9b8b312848 docs: record landed modeline detection
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.
2026-07-22 11:30:45 -04:00
Levi Neuwirth 1dd47fcad1
Merge pull request #132 from levineuwirth/modeline-detection
Detect language from modelines
2026-07-22 15:24:25 +00:00
Levi Neuwirth b45e5ee5ec Merge canonical main into modeline detection
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.
2026-07-22 10:56:35 -04:00
Levi Neuwirth 86fc1bccae
Merge pull request #130 from levineuwirth/vterm-tui
feat(vterm): compose terminal views in the TUI
2026-07-22 14:48:04 +00:00
Levi Neuwirth 506912a069 docs(vterm): record current-main integration gates
Record the resolved mode-system integration head, exact post-integration
verification, and isolated M4 timeout reruns before the authorized merge.
2026-07-22 10:29:54 -04:00
Levi Neuwirth 3f0252fb97 Merge canonical main into vterm-tui
Integrate mode-system wiring and handoff updates before PR #130 lands.
Preserve per-frontend terminal dispatch while resolving major-mode keymaps,
and expose mode, terminal, and LSP statusline providers together.
2026-07-22 10:28:56 -04:00
Levi Neuwirth 88a371efdb docs: checkpoint modeline implementation
Record the implementation head, completed acceptance contract, full gate
results, and pull-request handoff for modeline detection.
2026-07-22 10:02:54 -04:00
Levi Neuwirth f8d05d2134 feat: detect language from modelines
Parse bounded Emacs and Vim modelines, normalize common aliases, and give
explicit file metadata precedence over inferred language. Pin one fresh-load
language decision for syntax, LSP, pairing, comments, and initial major mode,
while preserving the LSP path guard and explicit mode overrides.

Cover supported forms, rejection boundaries, precedence, unknown modes,
shebang and modeline pinning, reopen behavior, and pathless buffers.
2026-07-22 10:02:20 -04:00
Levi Neuwirth d5e59a9dcf docs: approve modeline detection framing
Record user approval of Revision 2 and mark implementation active in the
isolated modeline lane.
2026-07-22 09:44:35 -04:00
Levi Neuwirth f521413bce docs: checkpoint revised modeline framing
Record the review-complete Revision 2 framing head and approval boundary in
the active-work ledger.
2026-07-22 09:41:25 -04:00
Levi Neuwirth 6b4f3c3b38 docs: correct Vim modeline framing
Match Vim's real direct and set-form tokenization, reject nonexistent colon
assignments, clarify suffix scanning and trust, extend aliases, and pin the
shebang-edit regression in acceptance.
2026-07-22 09:41:06 -04:00
Levi Neuwirth 49efa805b5 docs(vterm): record PR 130 review round 2
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>
2026-07-22 09:10:30 -04:00
Levi Neuwirth b9a7e40855 fix(vterm): harden view anchors and interactive authority
Clamp anchors into partially evicted wrapped lines, require authenticated
interactive origins, and avoid per-mouse cell snapshots. Restore dispatcher
rationale, named context errors, and focused regressions for the corrected
contracts.

Co-authored-by: OpenAI Codex <codex@openai.com>
2026-07-22 09:09:44 -04:00
Levi Neuwirth 5a39ac4a9c docs: record modeline framing lane
Advance the canonical base after the mode-system handoff merge and preserve
the draft modeline framing branch, checkpoint, scope, and recovery command.
2026-07-22 09:05:49 -04:00
Levi Neuwirth 47a7f4cefd docs: frame modeline language detection
Define bounded Emacs and Vim modeline parsing, alias normalization,
explicit precedence, one pinned language decision shared by syntax and LSP,
and the acceptance contract for load-time mode detection.
2026-07-22 09:05:02 -04:00
Levi Neuwirth d5d9b9c1ca
Merge pull request #131 from levineuwirth/mode-system-handoff
Record landed mode system
2026-07-22 12:50:12 +00:00
Levi Neuwirth aafa47514c docs: record landed mode system
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.
2026-07-22 08:40:35 -04:00
Levi Neuwirth b4b925df49
Merge pull request #129 from levineuwirth/mode-system-wiring
Wire major modes through key dispatch
2026-07-22 12:38:16 +00:00
Levi Neuwirth 2e332b579c docs(vterm): record PR 130 review round 1
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.
2026-07-22 08:29:33 -04:00