Commit Graph

671 Commits

Author SHA1 Message Date
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
Levi Neuwirth 3a7fe0cae9 feat(font): GPU derived metric fields + single-source family (Q#F6)
The 13 compile-time metric consts become BASE_* values behind a
FontMetrics { scale, advance_ratio } carried on State: every
surface derives from one knob (size/16.0), menu_char_w and the
empty-gutter advance fallback additionally multiply the measured
selected/default advance ratio, and the Default (1.0, 1.0)
reproduces today's constants bit-for-bit -- all 69 GPU tests pass
unchanged. The compiler enumerated every use site via the BASE_*
rename; fm threads as a parameter through the free helpers
(text_area_bottom, estimated_visible_lines, minimap_height/
band_contains/y_to_line/rects, edge_scroll_direction,
mb_dropdown_window, menu_width_px). The stray Metrics::new(16.0,
22.0) literal in assemble() now derives from the same fields, and
all seven Family::Name("JetBrains Mono") literals route through
State.resolved_family (seeded from the sanitized default; the
borrow checker forced hoisted clones at set-text sites, so the
field itself is the single source rather than an accessor).

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
Levi Neuwirth e9bafdacd6 feat(font): GPU sanitized font-database assembly (Q#F6)
assemble() replaces FontSystem::new() + post-hoc load_font_data
with an explicit fontdb::Database built in today's order -- system
fonts first, the bundled JetBrains Mono second (its fontdb::ID
retained) -- then the parameterized same-family collision filter
(sanitize_font_database removes every NON-monospace face
advertising the default family; the bundled face survives by
construction), cosmic-text's generic-family defaults, and only
then FontSystem::new_with_locale_and_db (sys-locale with the
"en-US" fallback, the same resolution cosmic-text's own
constructor performs; new pmacs-gpu dependency) -- so the internal
monospace-ID set is computed over the final database, bundle
included. FontDefaults { default_family, bundled_id } lands on
State as the total-fallback anchor for the resolution work in the
next commit; query_normal_face is the shared normal-style query
(the same fontdb::Query the base Attrs imply). Debug assertions
pin both anchors present and monospaced at assembly. All 69 GPU
tests pass unchanged -- assembly preserves today's pixels.

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
Levi Neuwirth 661b4968d9 feat(font): FontFacts wire + daemon half (v17, FontPref, producer)
Protocol v16->17: InstanceMessage::FontFacts { family,
size_centi_px } appended after ThemeFacts (integer hundredths of a
logical pixel -- the enum derives Eq, f32 cannot; range 600..=7200
documented on the wire). Pins updated: version 17, ladder accepts
6..=17 rejects 18, FontFacts round-trip (populated + all-None), and
a ThemeFacts byte pin ([23, 0]) guarding the appended placement.

Daemon half: FontPref { family, size_centi_px, epoch } behind a
shared handle on EditorState, installed with the new pmacs.gpu Lua
module BEFORE load_user_config so init.lua set_font lands in the
state the first attachment reads. set_font is strict plain data
(raw_get, unknown raw keys rejected by name, metatables never
consulted, parse/validate/quantize fully before locking -- range-
check the ORIGINAL value so 5.999 errors, then nearest-hundredth
round); pmacs.gpu.font() returns a fresh quantized table.

Producer: font_facts_msg (the theme_facts_msg discipline --
Option-seeded epoch + payload baselines, advance on computation,
one authoritative send per attachment incl (None, None),
bufferless so on_buffer_snapshot_sent never touches it); for_peer
gains peer_knows_font_facts (>= 17); daemon write-loop skip arm;
TUI silent-drop arm + regression test; first-frame count test now
expects 6 messages. GPU application follows in the next commit.

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
Levi Neuwirth 2521169350 docs: gpu-set-font framing (Arc 4 stage 2) at revision 4
pmacs.gpu.set_font { family?, size? }: one global daemon-side font
preference relayed to GPU peers as the bufferless FontFacts fact at
protocol v17 (size in integer hundredths of a logical pixel -- the
InstanceMessage Eq derive forbids f32), applied mid-session as one
fail-closed GPU transaction: sanitized current-order fontdb
assembly with four-style monospace queries, derived metric fields
scaled from one knob (band height included), atomic
set_metrics_and_size on all seven buffers with real drawable
dimensions, Wrap::None on row-oriented popups, a measured
advance-ratio probe, and visual-run-aware caret preservation (a
normalized code-buffer Scroll residual + shape_until_cursor,
shared with the CursorByte and optimistic-edit paths, gutter
continuation blanks keeping line numbers aligned). Revisions 2-3
fold framing rounds 1-2 (Eq-safe wire size, wire validation
failing closed, caret repair ordered before the final reshape,
vertical-containment acceptance, sanitized default query,
quantization pins); revision 4 is the user's round 3 (visual runs,
horizontal-scroll deferral, atomicity, popup row invariance,
strict Lua raw-data contract). Acceptance items 1-19.

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
Levi Neuwirth 56eb67e216
Merge pull request #121 from levineuwirth/side-quest-backlog
docs: side-quest-backlog — non-themes deferral inventory
2026-07-15 15:32:36 +00:00
Levi Neuwirth afe2690158 docs: sync handoff for injections (#122); prune backlog
Post-merge handoff sync for multi-language injections (#122), folded
into the side-quest-backlog PR (rebased onto current main, which now
carries #120 themes stage 1 and #122 injections).

agent-handoff.md:
- §1: main head → 5e73966; add the #122 injection-engine entry (layered
  ParseTreeBundle, worker-side layer building off the static grammar
  table, settle-time query resolution, the new substrate — injections_query,
  the alias snapshot, injection_capped, compute_highlight_spans_for, the
  flatten event-sweep, the GPU fold — and the two hard-won findings).
- §6: the "multi-language injections" deferral is retired; replaced with
  the real follow-ups (injection.combined, child-tree incrementality,
  injectable Lua-registered languages, HTML/CSS/GraphQL/SQL consumer
  grammars). Jupyter is now gated on JSON only.

side-quest-backlog.md: injections marked SHIPPED with its remaining
follow-ups; Jupyter gate and north star revised (JSON grammar and
locals-query processing rise to the top now that injections landed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJ9FQ832QwftJXCD9LeFan
2026-07-15 16:21:43 +01:00
Levi Neuwirth c51c88cac0 docs: side-quest-backlog — non-themes deferral inventory
Consolidate the non-themes backlog into docs/side-quest-backlog.md: an
exhaustive, deduplicated index compiled from every framing doc's
"Deferred (named)" section, the handoff §6 list, the roadmap arcs, and a
code-level marker sweep. Organized as side quests (one-shot-ish, led by
the highlighting/detection/LSP/editing families that continue the
#114–#118 stack), raid bosses (vterm, folding, DAP, GPU splits, Jupyter),
cross-cutting substrate blockers, and a prioritization north star.
Themes/faces/color items are excluded (they're the Arc 4 main quest) and
listed once so they're visibly accounted for. Handoff §6 gains a pointer
to it.

Docs only. git diff --check clean.
2026-07-15 16:10:19 +01:00
Levi Neuwirth 5e73966316
Merge pull request #122 from levineuwirth/multi-language-injections
feat(injections): multi-language injection layers
2026-07-15 14:57:44 +00:00
Levi Neuwirth bc0922bea2 test(m4): keep injection work outside root parse gate 2026-07-15 14:50:45 +01:00
Levi Neuwirth c3a57be3fa fix(injections): pin sibling priority regression 2026-07-15 13:24:37 +01:00
Levi Neuwirth a231257894 chore(injections): rebase onto main (#120 themes stage 1 / v16)
Rebase the injection branch onto main after #120 (themes stage 1,
protocol v16) merged. Conflicts were confined to appended test blocks
in pmacs-gpu/src/main.rs (kept both #120's GPU face tests and the
injection source_color test); highlight.rs, lua_bindings/mod.rs, and
semantic_render.rs auto-merged (my injection code and #120's theme
epochs / resolve_faces summary path / ThemeFacts occupy disjoint
regions). The one API adaptation: #120 gave scoped_file_summary a
`resolve_faces: bool` parameter, so the full-buffer flatten perf gate
passes `false` (it exercises the syntax flatten path).

Gates re-run on the rebased base: fmt, clippy -D warnings, lib (1582),
lib crdt (1756), m4 (110), theme_faces (22, #120's suite unbroken),
PMACS_REQUIRE_GPU gpu (70), full workspace sweep (0 failures),
git diff --check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJ9FQ832QwftJXCD9LeFan
2026-07-15 12:17:27 +01:00
Levi Neuwirth 325dcd553f fix(injections): PR #122 round 2 — sibling precedence, observable cap, docs
Two follow-ups + doc cleanup.

[P2] Same-depth sibling precedence was reversed. The wire priority was
(depth, capture_order), omitting the layer ordinal, so two overlapping
spans from different sibling layers tied — and the active-set insert
then applied the later one first, making the earlier sibling win, the
opposite of the grid's layer-by-layer paint. Priority is now
(layer_index, capture_order): layer_index is the depth-ascending
position in bundle.layers, so a deeper layer AND a later same-depth
sibling both override, matching the grid exactly. New
flatten_same_depth_sibling_later_layer_wins pins it.

[P2] Cap surfacing had no end-to-end test. Added
injection_cap_surfaced_once_and_rearms_via_lua, which drives the real
Lua settle path (syntax.lua tick -> _injection_capped -> pmacs.error)
and asserts surfaced-once, suppressed-on-unchanged-reparse, and
re-armed-after-dropping-below-then-exceeding-the-cap.

Docs:
- Q#IJ6 now states the accurate bound O(n log n + Sum active) for the
  event sweep, not O(boundaries).
- The full-buffer perf test is renamed/narrowed to guard the FLATTENER
  regression; the summary's per-line dominant-style tally is a separate
  pre-existing O(lines x spans) loop, not claimed linear.
- Framing #9 now matches the test: it drives spans_from_segments (the
  extracted replace_style_spans transform) + source_color_at, not a live
  State render.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJ9FQ832QwftJXCD9LeFan
2026-07-15 12:07:21 +01:00