Commit Graph

683 Commits

Author SHA1 Message Date
Levi Neuwirth fc4e0ce77d docs(vterm): record Stage 1 review round 2
Record the control-free cell and SGR mouse hardening, accepted cleanup changes,
remaining DECSTBM/allocation/limit deferrals, behavioral bite, and final gate
counts in framing Revision 5 and project continuity docs.
2026-07-21 16:31:10 -04:00
Levi Neuwirth 9797adaa0b fix(vterm): harden terminal cell and input invariants
Reject C0/C1 controls before terminal text reaches screen cells, and preserve
the released button code in SGR mouse reports.

Remove dead screen branches, keep logical-line allocation saturating, and clear
round-trip input state when pruning externally removed terminal buffers.
2026-07-21 16:27:43 -04:00
Levi Neuwirth 2e97d60023 docs(active-work): record green Vterm review CI
Record the fully green Linux/macOS, Lua, GPU, format, lint, and acceptance
matrix for PR #126 after review round 1.
2026-07-21 15:48:03 -04:00
Levi Neuwirth 8dfb918082 docs(active-work): record Vterm review round 1
Record the addressed Stage 1 review, final branch head, full gate counts, and
clean behavioral bite while preserving the unmerged three-stage boundary.
2026-07-21 15:37:45 -04:00
Levi Neuwirth 5d5055871f docs(vterm): record Stage 1 review round 1
Record the IND, NEL, RI, TERM, portable-liveness, and tab-stop fixes; make the
line-oriented EOF contract explicit; and list the accepted fidelity,
performance, and lifecycle deferrals.

Update final from-start gates and the clean behavioral bite proof.
2026-07-21 15:37:11 -04:00
Levi Neuwirth bf972a76fa fix(vterm): share line-feed screen dispatch
Merge the identical LF and IND match arms so the post-review workspace Clippy
gate remains warning-free without changing terminal behavior.
2026-07-21 15:35:25 -04:00
Levi Neuwirth 28f2e6ce66 fix(vterm): parse VT index operations
Dispatch ESC D, ESC E, and ESC M as typed full-screen IND, NEL, and RI
operations while preserving the line-oriented parser contract.

Extend both the every-split parser matrix and parser-to-screen integration test
so missing dispatch fails behaviorally rather than only at compile time.
2026-07-21 15:31:15 -04:00
Levi Neuwirth f0a235f635 fix(vterm): harden Stage 1 terminal contracts
Add typed IND, NEL, and RI operations with exact screen semantics, preserve
application tab stops across resize, and default terminal children to the
supported xterm-256color capability set.

Make shutdown liveness acceptance portable with kill(pid, 0), and document the
public TerminalScreen methods consumed by later stages.
2026-07-21 15:30:06 -04:00
Levi Neuwirth 2a037dc14c docs(active-work): record Vterm CI portability fix
Update the Vterm Stage 1 lane with the Darwin PTY signal normalization,
post-fix branch head, and final from-start verification counts.
2026-07-21 14:39:19 -04:00
Levi Neuwirth 4d74d64b6f docs(vterm): record macOS portability fix
Record the Darwin PTY signal-name mismatch found by PR CI, the normalization
commit, and the final from-start green gate sequence with updated test counts.
2026-07-21 14:38:52 -04:00
Levi Neuwirth 962944b744 fix(vterm): normalize Darwin PTY signal names
portable-pty forwards libc strsignal text, which includes a numeric suffix on
Darwin. Strip a verified numeric suffix before mapping known descriptions so
terminal snapshots and exit annotations retain the protocol's symbolic
SIGFOO form across platforms.

Add focused coverage for glibc, Darwin, and unknown descriptions.
2026-07-21 14:37:54 -04:00
Levi Neuwirth b3220b165e docs(active-work): record Vterm Stage 1 delivery
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>
2026-07-21 14:26:04 -04:00
Levi Neuwirth 5d7f0078f1 docs(vterm): refresh merged statusline baseline
Record canonical protocol v18 main after #125, mark Arc 4 complete, and pin
the Vterm Stage 1 feature commit and open PR #126 in the delivery records.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-21 14:24:46 -04:00
Levi Neuwirth bbc1f33a7c feat(vterm): add Stage 1 terminal core
Add compatibility-preserving full-screen ANSI operations, the bounded terminal
screen and input encoders, and a transactional TerminalManager owning one
read-only identity buffer, PTY process, and screen per session.

Drain terminal-owned process events before process.after-tick, retain exact
final output and PID/outcome annotations, reap killed buffers and shutdown
children safely, and enforce buffer-owned read-only checks across ordinary,
host, undo/redo, and CRDT mutation paths.

Cover split parser and grapheme boundaries, screen/reflow/history invariants,
device responses, lifecycle cleanup, and a real adversarial alternate-screen
PTY. Record the fully gated Stage 1 delivery and downstream TUI/GPU contracts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-21 14:20:28 -04:00
Levi Neuwirth f26aa0b38b docs(vterm): fold architecture decisions
Record the chosen C-c escape, resize and exit behavior, additive v19
compatibility, complete-frame wire, unchanged Style, and shared-session
ownership. Specify the Emacs-style PID/outcome line retained after exit.
2026-07-21 13:26:36 -04:00
Levi Neuwirth 2ff67e7236 docs(vterm): frame staged terminal implementation
Define the terminal screen ownership boundary, three-PR delivery,
protocol v19 surface, fixed four-agent roster, and 33 acceptance cases.

No implementation is included; the framing remains pending user review.
2026-07-21 13:21:21 -04:00
Levi Neuwirth b65c927ac4 docs: record Themes Arc 4 completion
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>
2026-07-21 12:56:17 -04:00
Levi Neuwirth 7bc0c61339
Merge pull request #125 from levineuwirth/statusline-segments
feat(statusline): composable modeline segments at protocol v18
2026-07-21 16:53:41 +00:00
Levi Neuwirth 4ae888dda3 docs(active-work): record statusline review round two
Record the manually folded hardening changes, current feature head,
second review resolution, and final sequential verification counts.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-21 12:44:35 -04:00
Levi Neuwirth 1be7a30468 fix(statusline): harden narrow-band review edges
Document and pin the GPU built-in-only narrow-band clipping policy,
including the intentional ability of a wide right group to hide the
left identity. Guard the fixed UI face ordering used by binary search,
preserve flattened provider tracebacks in *errors*, and rename the
phase-one unavailable reason to cover missing layout contexts.

Refresh the implementation verification record after the full gate
suite.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-21 12:43:22 -04:00
Levi Neuwirth dd92c241b2 docs(handoff): record statusline first-review resolution
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>
2026-07-21 12:17:48 -04:00
Levi Neuwirth 66765b3cbc docs(statusline): record rebased review baseline
Update the feature handoff and framing to current main bb17ec9 and the
post-rebase full-gate counts.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-21 12:15:19 -04:00
Levi Neuwirth 4b65b9e1e5 feat(statusline): add composable modeline segments at protocol v18
Add the strict pmacs.statusline provider registry, deterministic
borrow-released per-window evaluation, context-scoped failure latches,
and a pure built-in LSP provider.

Preserve the legacy TUI modeline while composing faced custom runs,
and append authoritative complete StatuslineSegments replacements for
semantic frontends. Expand dynamic ThemeFacts, reset producer/frontend
baselines symmetrically, and gate all provider work off protocol v18.

Teach the GPU to atomically validate, resolve, shape, clip, and cache
custom modeline runs without displacing the protected status suffix.
Document the public Lua lifecycle, wire ownership, snapshot semantics,
and the fully gated Arc 4 stage-3 delivery state.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-21 12:01:25 -04:00
Levi Neuwirth ac7f776c3a docs(statusline): close revision 3 review findings
Retain authoritative-empty payloads as emission baselines and pin the
legacy TUI behavior when the protected suffix itself cannot fit.
2026-07-21 12:01:25 -04:00
Levi Neuwirth fe1dc7ad94 docs(statusline): close review contracts in revision 2
Specify authoritative invalidation, safe grapheme runs, separator faces,
detach-aware latches, and the unknown LSP label.
2026-07-21 12:01:25 -04:00
Levi Neuwirth f16c98b56b docs(statusline): preserve stage-3 framing for review
Checkpoint revision 1 of the Arc 4 stage-3 statusline-segments framing
on its own portable branch. The framing remains awaiting user review;
there is no implementation or PR.
2026-07-21 12:01:25 -04:00
Levi Neuwirth 738506b06b docs(handoff): record statusline stage-3 delivery
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>
2026-07-21 11:26:41 -04:00
Levi Neuwirth a9732d9fb1 docs(handoff): record statusline framing revision 3
Advance the active lane and durable handoff to the framing-only Revision
3 checkpoint without changing its awaiting-review status.
2026-07-21 10:25:56 -04:00
Levi Neuwirth c488cbb9d4 docs(handoff): record statusline framing revision 2
Advance the active review lane after its contract-tightening revision.
2026-07-21 10:04:05 -04:00
Levi Neuwirth 753689955d docs(handoff): record JSON and YAML merge
Mark PR #123 landed at bb17ec9 and remove its completed recovery lane.
2026-07-21 09:48:46 -04:00
Levi Neuwirth bb17ec955e
Merge pull request #123 from levineuwirth/json-yaml-grammar
feat(json-yaml): JSON + YAML grammars and language servers
2026-07-21 13:47:06 +00:00
Levi Neuwirth 5ba9c526b4 docs(handoff): record JSON/YAML review cleanup
Advance the PR #123 recovery heads and verification record after its
documentation-only pre-merge cleanup.
2026-07-21 09:35:29 -04:00
Levi Neuwirth ffcb903fc1 docs(json-yaml): refresh final review state
Remove stale transfer-task wording and record the rebased, fully gated
JSON/YAML provider validation in the framing and handoff.
2026-07-21 09:34:54 -04:00
Levi Neuwirth 03ef1801d2 docs: record green JSON/YAML CI
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>
2026-07-20 17:23:36 -04:00
Levi Neuwirth f870bc4ca9 docs: mark JSON/YAML locally gated and public
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>
2026-07-20 17:22:51 -04:00
Levi Neuwirth b489780781 docs: checkpoint JSON/YAML gate progress
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>
2026-07-20 17:05:14 -04:00
Levi Neuwirth 6db8a4b166 docs: advance amended JSON/YAML checkpoint
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>
2026-07-20 17:01:50 -04:00
Levi Neuwirth 5c202c54c1 test(json-yaml): verify real YAML provider through pmacs
Drive Red Hat yaml-language-server 1.24.0 through the default YAML
auto-attach path. Disable SchemaStore and the Kubernetes CRD catalog for
network-free determinism, require language-specific initialization and a
real syntax diagnostic, and prove the server remains alive afterward.

Update the framing and runtime commentary with the completed live-provider
evidence. The test passes against the pinned provider and fails against the
pre-JSON/YAML runtime under scripts/bite.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-07-20 17:00:20 -04:00
Levi Neuwirth af7e010381 docs: record rebased JSON/YAML checkpoint
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>
2026-07-20 16:56:11 -04:00
Levi Neuwirth 19ad5cc8ac fix(json-yaml): checkpoint reviewed LSP configuration fixes
Preserve PR #123's unpushed review fixes on a transfer branch: initial
didChangeConfiguration delivery, explicit JSON validation, the pinned
JSON server provider, corrected YAML configuration sections, and
deterministic plus real-provider acceptance coverage. Record the
observed yaml-language-server 1.24.0 standalone smoke and leave the
real YAML-through-pmacs test, rebase, and full gates explicitly pending
for the destination machine.
2026-07-20 16:49:37 -04:00
Levi Neuwirth 9ce6f1abf3 feat(json-yaml): JSON + YAML grammars and language servers
Add tree-sitter-json (0.24) and tree-sitter-yaml (0.7) to
BUILTIN_LANGUAGES (both ABI-current via tree-sitter-language, verified
compiling under tree-sitter 0.26), each self-contained highlights, no
injections of their own. Extensions json=.json, yaml=.yaml/.yml; root
kinds json `document`, yaml `stream`.

The payoff from the #122 injection engine is free: the markdown block
injection query already sets injection.language "yaml" for `---`
frontmatter (minus_metadata) and "toml" for `+++` (plus_metadata), so
registering yaml lights up YAML frontmatter highlighting with no extra
wiring, and ```json / ```yaml / ```yml fences resolve through the engine
(yml->yaml alias already present). Two acceptance tests pin this synergy.

LSP (builtin/runtime/lsp.lua): pmacs.lsp.config.json uses the maintained
extracted-bundle binary `vscode-json-language-server --stdio` (NOT the
stale standalone vscode-json-languageserver); MIT, no telemetry, remote
$schema fetch left enabled (no handledSchemaProtocols). pmacs.lsp.config
.yaml uses `yaml-language-server --stdio` with Red Hat telemetry
disabled by default. Both ship the exact workspace/configuration sections
each server pulls (json+http; yaml+http+redhat.telemetry) present-not-null
so the servers get defaults rather than erroring — the CMake #117 lesson.
Sections derived from server source/docs (neither binary installed on
this build machine to observe live; verify where present). Filetype
fallback entries added. JSON is the standing prerequisite for the Jupyter
.ipynb arc; handoff §6 updated.

Nine acceptance tests (grammar ABI, highlights compile, detection,
grammar<->LSP-key alignment, the two frontmatter/fence synergy proofs,
and the pinned LSP-config sections).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJ9FQ832QwftJXCD9LeFan
2026-07-20 16:49:37 -04:00
Levi Neuwirth f233765f74 docs(json-yaml): framing for JSON + YAML grammars
Frame the JSON/YAML grammar-gap addition (tree-sitter-json 0.24 +
tree-sitter-yaml 0.7, both ABI-current) plus their language servers, and
the free frontmatter/fence highlighting that falls out of the #122
injection engine (the markdown block query already injects yaml for `---`
frontmatter and toml for `+++`). Four decisions (Q#JY1-JY4), nine
acceptance tests. JSON is also the standing prerequisite for the Jupyter
.ipynb arc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJ9FQ832QwftJXCD9LeFan
2026-07-20 16:49:37 -04:00
Levi Neuwirth eb779cfcd1 docs: make active recovery machine-agnostic
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>
2026-07-20 16:47:02 -04:00
Levi Neuwirth ad05498545 docs: pin portable branch heads in active-work ledger
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.
2026-07-20 10:57:48 -04:00
Levi Neuwirth 968e01ae6a docs: add cross-machine active-work handoff
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.
2026-07-20 10:51:34 -04:00
Levi Neuwirth f8096ff826
Merge pull request #124 from levineuwirth/gpu-set-font
feat(font): pmacs.gpu.set_font — global font preference at protocol v17 (Arc 4 stage 2)
2026-07-18 16:00:13 +00:00
Levi Neuwirth b3d326d937 fix(font): close stage-2 GPU behavioral findings
Normalize source bytes to representable shaped-cluster cursors and
reflow the code buffer whenever gutter or minimap geometry changes.

Measure alternate monospace advances across complete shaped runs and
load hermetic fixture faces before FontSystem construction. Complete
the rendered geometry, popup, caret, snapshot, and fixture acceptance
coverage, and record the review fixes in framing revision 5.
2026-07-18 15:29:25 +01:00
Levi Neuwirth 6cd78f0870 test(font): wire acceptance suite + protocol/design docs (items 2-8, 15)
tests/gpu_font_acceptance.rs (items 2-7; the header manifest routes
item 1 to src/protocol.rs pins, item 8 to the src/frontend.rs TUI
drop unit, items 9-14/16-19 to pmacs-gpu's headless suite, and item
15 to the docs):

- 2: a fresh attachment's first frame carries the REAL (None, None)
     default; unchanged ticks are silent; a late joiner receives the
     current preference without post-attach mutation
- 3: a mid-session set_font emits exactly one FontFacts on the next
     frame; an identical re-set advances the epoch without emitting
- 4 (producer half): on_buffer_snapshot_sent re-ships buffer facts
     but never the bufferless FontFacts
- 5: real-daemon probe -- a v17 semantic session receives FontFacts,
     a v16 peer never does (crdt feature)
- 6: the strict Lua contract -- 5.999/72.01/0/-16/NaN/inf/non-number
     sizes error naming `size`; empty/non-string family errors
     naming `family`; unknown keys rejected by name; hostile
     __index/__pairs metatables never invoked and never inject
     values; quantization pins 15.994->1599 / 15.996->1600 and both
     boundaries; set_font {} resets both axes; the getter returns a
     fresh quantized plain table; every rejected shape leaves the
     preference and the wire untouched
- 7: a load_user_config_at fixture's init.lua set_font lands in the
     handle installed before user config, and a pre-attach
     preference ships on the first frame

Bites (mutate, observe the acceptance test fail, restore): the
Option-seeded first-frame send, the payload compare, the snapshot
survival of the font baselines, the v17 gate (BOTH halves widened --
producer for_peer alone leaks nothing because the daemon skip arm
still filters; the wire test only fails when belt AND braces are
cut), the unknown-key rejection, the range-check-original ordering,
and the raw_get metatable isolation.

Docs (item 15): docs/semantic-frontend-protocol.md gains the
FontFacts variant entry (v17 gate, authoritative default, no-pixels
preference relay, fail-closed receiver) and folds FontFacts into the
BufferSnapshot reset-contract paragraph (bufferless facts survive;
the frontend's caret-follow scroll residual is the buffer-scoped
part). docs/pmacs-gpu-design.md's "future customization needs no
wire-protocol changes" claim is corrected in place and points at the
framing as design of record; the Lua-override bullet now names the
landed set_font shape. The framing status bumps to implemented.

Also re-homes the ProcessSupervisor doc comment that the make_font_pref
insertion had orphaned onto the wrong function.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VoiEyuPjoBhvwACf8HAnLB
2026-07-18 11:46:44 +01:00
Levi Neuwirth fe65fddae5 test(font): GPU acceptance for apply_font_facts + caret substrate
Twenty-one new headless tests covering the GPU-side acceptance items of
docs/gpu-set-font-framing.md (9-14, 16-19):

-  9: size route re-derives metrics; (None, None) reset reproduces
      the never-set frame byte-for-byte
- 10: 600/7200 bounds render; minibuffer dropdown windows its rows
      above the band at the derived row height; context menu keeps
      the clipped route with coherent hit geometry
- 11: wrapped caret survives 16->72->6 px; an optimistic insertion
      that wraps a new bottom row follows immediately and its
      confirming CursorByte needs no second repair; overscan caret
      never snaps the viewport; narrowing resize re-follows via the
      coarse + visual-run + fold pipeline; adornment projection
      shifts the caret past injected text with left gravity at the
      anchor; the CursorByte arm follows into a wrapped run as a
      normalized sub-line residual; explicit scrolls clear the
      residual (including wheel-up at the clamp edge); the
      minibuffer suspends the follow decision
-  4 (GPU half): BufferSnapshot resets the residual while the font
      preference/metrics survive -- the replacement buffer wraps
      too, so the EOF clamp cannot mask a leaked residual
- 12: unknown + proportional families fall back; the four-style
      gate rejects a proportional BOLD sibling the normal-only
      query would accept; a valid second monospace family resolves,
      changes the ink, and resets cleanly; the parameterized
      sanitizer removes exactly the same-family proportional
      collision
- 13: the "\0" sentinel defeats the status string-equality gates
- 14: a shrinking visible slice re-declares the scoped viewport
- 16: 0/599/7201/u32::MAX reject the whole message, state untouched
- 17: metrics + drawable dimensions atomic on all seven buffers,
      resize symmetric via Buffer::size()
- 18: popup rows never wrap (Wrap::None + unique line_i per run)
- 19: with line numbers and a context menu open over an EMPTY
      buffer, the measured probe advance drives gutter reservation
      and menu hit width (fixture ratio exactly 1.2 vs the bundled
      default); reset restores the exact geometry and frame

Family routing is hermetic: four generated fixture faces under
pmacs-gpu/fonts/test/ (second monospace at 720/1000, a proportional,
and a "Pmacs Test Family" whose NORMAL face is monospaced but whose
BOLD face is proportional), built by the committed generate.py --
provenance and license in LICENSE.txt beside them. fontdb requires a
PostScript name (nameID 6), which the generator sets explicitly.

assemble() now routes construction through sync_buffer_dimensions
too: shape_until_cursor and wrapping must use the painter's clip
from the first frame -- a v16 daemon never sends the FontFacts that
would sync them later (found by the CursorByte-follow test: the
caret parked in the status band at surface-height dims).

Every protection was bitten (temporarily reverted, its test observed
failing, then restored): wire validation, CursorByte visual-run
follow, painted-before gate, projection inversion, Wrap::None,
four-style gate, sanitizer, status sentinel, normalize fold,
scroll_by_lines residual clear, BufferSnapshot residual reset, the
all-seven dimension helper, and the optimistic-completion follow.
The snapshot-reset test was strengthened after its first bite did
NOT fail (a short replacement buffer let cosmic's EOF clamp zero the
residual anyway).

PMACS_REQUIRE_GPU suite 90/90; clippy -D warnings and fmt clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VoiEyuPjoBhvwACf8HAnLB
2026-07-18 11:46:44 +01:00
Levi Neuwirth 06a4b2e359 feat(font): GPU apply_font_facts + visual-run caret substrate (Q#F6)
The stage-2 GPU application half, framing revision 4:

- apply_font_facts transaction: fail-closed wire validation
  (600..=7200 centi-px; deserialized protocol input, not the Lua
  courtesy check), painted-before decision from the ACTUAL caret rect
  intersected with the drawable code clip, four-style monospace
  resolution with total fallback to the sanitized default, derived
  metrics + measured advance, atomic re-metric/re-size, status
  shaping-cache drop, reshape at the retained scroll, drawable-width
  settle pass, conditional caret re-follow, minimap cache drop.
- Advance probe: fixed ASCII digits shaped in the resolved family at
  the new code metrics; the NORMAL-face advance is authoritative for
  gutter geometry (mono_advance no longer trusts an arbitrary code
  glyph once measured), and the selected/default ratio scales the
  const-based fallbacks -- the default family is ratio 1 by
  construction, so never-set/reset stays byte-identical.
- sync_buffer_dimensions: metrics + REAL drawable dimensions change
  atomically on all seven buffers via set_metrics_and_size; the code
  buffer wraps at the painter's clip width; resize() routes through
  the helper (closes the old four-of-seven skew) and applies the same
  painted-before follow policy.
- Rows stay rows: Wrap::None on the menu/minibuffer/completion
  buffers at assembly and (idempotently) in the transaction.
- Normalized code-buffer Scroll residual: slice-local line == 0
  invariant with a vertical pixel residual; horizontal always
  discarded (glyphon 0.11 never applies it). normalize_code_scroll
  folds line advances into whole-file scroll_top (strictly advancing
  origin, EOF clamp) after EVERY final code shape. BufferSnapshot
  resets the residual (buffer-scoped view state); explicit
  wheel/minimap jumps clear it -- including a wheel-up whose only
  remaining motion IS the residual.
- Byte-to-layout projection: code_byte_to_projected inverts the
  line_chunk_cache chunk projection (earliest projected boundary for
  adornment anchors, the left-gravity caret), then code_byte_px uses
  cosmic-text's layout_cursor so wrap boundaries select the same
  visual run shape_until_cursor scrolls to. caret_rect and
  completion_anchor_px are now visual-run aware instead of scanning
  the source line's first run.
- ensure_caret_painted (coarse source-line follow, then
  shape_until_cursor, discard Scroll.horizontal, normalize) shared by
  the CursorByte arm (under its existing moved gate -- fixes the
  pre-existing wrapped-line follow hole), the optimistic edit
  completion, the font transaction, and resize.
- Gutter mirrors the code layout's visual runs: continuation blanks
  for wrapped runs plus the same normalized vertical scroll, so line
  numbers stay row-aligned when wrapping appears.
- assemble() shapes the initial text through reshape() so the
  buffer.lines <-> line_chunk_cache invariant holds from
  construction (the projection inversion depends on it).

PMACS_REQUIRE_GPU suite 69/69; clippy -D warnings and fmt clean.
Acceptance tests for items 9-11/13-14/16-19 land in the next commit
with the embedded test faces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VoiEyuPjoBhvwACf8HAnLB
2026-07-18 11:45:51 +01:00