Commit Graph

612 Commits

Author SHA1 Message Date
Levi Neuwirth 54991c89e4 session 9.1 — Selection quad backgrounds + framing doc
Retires the first half of Phase A's deferred finding A8 (background-
bearing decoration kinds couldn't render through cosmic-text's
foreground-only `Attrs`). `DecorationKind::Selection` now paints a
translucent blue rectangle under the selected glyphs in pmacs-gpu,
reusing the wgpu `QuadRenderer` that shipped for the minimap in
session 7.

The framing doc (`docs/pmacs-gpu-quad-backgrounds-framing.md`)
commits the load-bearing decisions before code lands: stance (α)
for Q#2 — single render pass, three draws in the order backgrounds
→ text → minimap — is what this commit implements. Q#1 (CurrentLine
source location, stance α: producer-side from
`core.active_window_for(self.frontend_id).cursor`) and Q#3 (per-line
cadence, stance β) are sketched for session 9.2; Q#4 defers search
backgrounds awaiting an upstream pmacs search feature.

Three components:

1. `decoration_kind_to_bg_color` helper, sibling of the existing
   `decoration_kind_to_color`. Returns `Some([f32; 4])` RGBA for
   Selection; `None` for CurrentLine (9.2), SearchMatch /
   SearchMatchActive (deferred), and the four diagnostic kinds
   (foreground-only). New unit tests assert disjoint total cover
   between the two helpers across the eight kinds.

2. `State::decoration_background_rects` walks
   `Buffer::layout_runs()`, finds glyphs whose `[start, end)`
   overlaps each background-bearing decoration's `ByteRange`, and
   produces one `MinimapRect` per laid-out visual line that
   contributes glyphs. Multi-line selections fan out as N rects.

3. Render-order change in `State::render`: a `bg_buffer` is built
   ahead of the minimap buffer and drawn first in the render pass
   (before `text_renderer.render`), so selection fills sit under
   the glyphs with the 0.30-alpha letting source color show through.
   Minimap continues to draw last.

Gates green:
- cargo fmt --all -- --check
- cargo clippy --all-targets --workspace -- -D warnings
- cargo clippy --all-targets --workspace --features crdt -- -D warnings
- pmacs-gpu unit: 13 (+2 new bg-color helper tests)
- pmacs lib: 1325, pmacs-protocol: 11
- m4_acceptance: 88, m11_5_semantic_acceptance (--features crdt): 2

Bet exercise so far: bet #1 (multi-line vertex decomposition) is
implicitly tested by the layout-run loop but waits on visual
validation for honest scoring. Bet #2 (overlap composition) is not
exercised in 9.1 — Selection is the only background kind, so no
overlaps with CurrentLine or future kinds. Bet #3 (cadence) is a
9.2 concern.

Manual probe: launch daemon + TUI attach + pmacs-gpu attach against
any file, select text in the TUI, verify the pmacs-gpu window paints
a translucent blue rectangle over the selected glyphs that tracks
selection extension. Multi-line selection should produce per-visual-
line rectangles.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 13:49:52 -04:00
Levi Neuwirth a67cb8a6f1 Close pmacs-gpu phase A audit 2026-05-28 12:49:23 -04:00
Levi Neuwirth a706864e04 session 2: pmacs-gpu workspace + wgpu/winit/glyphon hello-world
Adds the pmacs-gpu binary crate to the workspace. wgpu 29.0 + winit
0.30 + glyphon 0.11 (cosmic-text 0.18 via re-export) + pollster +
env_logger; pmacs-protocol in the dep graph but not consumed yet
(session 3 wires the attach loop).

The binary opens an 800x200 window titled 'pmacs-gpu hello-world',
sets up wgpu against its surface, configures glyphon with the bundled
JetBrains Mono Regular, and renders 'hello, pmacs' once per redraw.
Close button or Escape exits. Resize re-configures the surface and
glyphon viewport. Surface acquisition matches wgpu 29's
CurrentSurfaceTexture enum (success/suboptimal render through; lost/
outdated re-configure; timeout/occluded skip the frame).

Bundled assets: pmacs-gpu/fonts/JetBrainsMono-Regular.ttf (268 KB)
and pmacs-gpu/fonts/OFL.txt. Font shipped as required by the SIL
Open Font License 1.1.

One finding surfaced during the move and absorbed under rule (iii)
of the framing pass (small / no structural change): the design doc
recorded JetBrains Mono as Apache 2.0; the actual license has been
OFL since the family's open-source release. Doc corrected in
docs/pmacs-gpu-design.md.

Gates: cargo fmt + cargo clippy --all-targets -D warnings clean for
the whole workspace; cargo test --lib still 1314 (pmacs main crate
untouched); m4_acceptance 83; m11_5_semantic_acceptance --features
crdt 2.

Visual confirmation pending — agent environment is headless, so
'window opens, text renders' is user-side validation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:37:26 -04:00
Levi Neuwirth 1dc36f7cd4 docs: pmacs-gpu design note (framing pass closed)
Post-v1.0 design artifact for the GPU/GUI frontend. Inherits the
contract boundary from semantic-frontend-protocol.md and applies the
M10-matured framing discipline to a multi-month effort:

- Toolkit: wgpu + custom + cosmic-text + glyphon. Unambiguous.
  Records the against-gpui case so the decision isn't relitigated.
- Scope: A (read-only viewer, ~2-3 weeks, adversarial verification of
  the producer arc) → B (TUI parity, 2-3 months after A) → C
  (beyond-TUI, 3-4 months after B). Sequential, not alternative.
  ~6 months to parity, ~9-10 to beyond-TUI; recorded honestly at
  decision time.
- Phase A's framing is adversarial verification, not "build a viewer
  that works." Six static probes + one temporal probe drive the
  corpus; the viewer is the artifact of having done so.
- Predicted findings: five categorical bets, scored as a category
  matrix not a count, methodology recorded before data lands.
- Finding feedback loop: classification rule (iii) pre-authorized —
  small absorbs into Phase A, structural deferred per the
  verification-milestone premise-check.
- Distribution: workspace + separate pmacs-gpu binary. pmacs-protocol
  crate extraction as a discrete 4-hour prerequisite PR before any
  GPU work.
- Q#1 (visual motion) committed to stance β: frontend implements
  visual motion; instance stays pixel-pure. Phase A starts with
  (β-impl) — recompute wrap on motion events — with documented
  upgrade path to (α-impl) if smooth scroll lands.
- Cursor scope at v0.1: blink, multi-cursor rendering, peer cursors.
  Multi-cursor commands out of scope.
- Font: bundle JetBrains Mono + Lua override; tofu fallback for
  missing glyphs; real fallback chain is v0.2+.
- Rhythm: cadence relaxes from hour-level to daily-PR for larger
  features; discipline anchor moves from per-PR to per-session.
- Audit artifacts: this doc is the design artifact; per-phase audit
  material lands in separate per-phase audit docs (M10.x pattern).

Session plan: 1 = pmacs-protocol extraction; 2 = pmacs-gpu workspace
+ hello-world; 3 = attach loop; 4+ = Phase A proper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 08:47:45 -04:00
Levi Neuwirth c692710321 M1+M2: FileStyleSummary (minimap producer, Q#2 resolved) + doc
New InstanceMessage::FileStyleSummary { buffer_id, generation, lines:
Vec<Style> }: a coarse whole-file styling summary for a Zed/VSCode-
style minimap, resolving the design note's Open Q#2. One dominant
Style per source line (by byte count across the producer's current
spans); the frontend maps minimap rows to one or more lines.

Producer scoped_file_summary reuses scoped_style_spans with a whole-
buffer synthetic viewport, so policy A's authority pick (tree-sitter
for grammar-backed languages, LSP semantic tokens otherwise) is
inherited automatically — no separate styling path. file_style_summary_msg
is keyed on the buffer's CRDT generation: an idle buffer at the same
generation pays nothing (the whole-file summary is the expensive bit
on large files, so re-emit only after edits). First frame for a
buffer always emits; the existing first-frame test updated to expect
3 messages (StyleSpans + Decorations + FileStyleSummary).

Per-line dominant style is the v1 representation. Future refinements
(fixed-N bands; whole-file RLE style runs) are recorded in the design
note as straightforward extensions if a real frontend prefers them.

Structural gating same as the other semantic families: the daemon
only constructs a SemanticRenderState for sessions that negotiated
semantic_render, so non-semantic sessions never receive it. Grid TUI
adds the variant to its ignore list. Round-trip fixture covers it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 19:23:20 -04:00
Levi Neuwirth 8ec3abcad5 Step 3+5: InlineAdornments producer from LSP inlay hints + doc update
scoped_inline_adornments (free fn, mirrors scoped_style_spans) reads
the inlay-hint store via for_uri and maps each InlayHint to an
InlineAdornment { at, AtOffset, Text{padded label, default style} },
clipped to the declared viewport (anchor in [vis_start, vis_end)).
Step 0 established inlay columns are already byte offsets by the time
they reach the store (inbound_converted rewrites the Position-shaped
InlayHint.position), so line_col_to_byte is exact with no per-server
encoding — unlike semantic-token styling.

inline_adornments_msg does the suppression: the InlineAdornments wire
variant has no generation/full/segments, so this is M11.2-level only
(whole-set re-send on any change, nothing when byte-identical, and
never an empty frame when there is nothing to say — no spam).

Tests: clip-to-viewport + padding + AtOffset, suppress-then-resync,
no-emit-without-hints; the old never-emitted invariant is split into
block_adornments_and_fold_state_still_never_emitted (Block/Fold are
still unwired) plus inline_adornments_not_emitted_without_hints.
assert_semantic_only now admits InlineAdornments.

Step 5 (folded): docs/semantic-frontend-protocol.md moves StyleSpans
(policy A) + InlineAdornments out of "declared, not wired", and adds
two deferred Open questions — per-byte tree-sitter/LSP blend, and
multiple-servers-one-URI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:00:44 -04:00
Levi Neuwirth baddd22878 docs: land the semantic-frontend-protocol design note
The spec the M11 arc (M11.1–M11.5) implements; all five CHANGELOG
entries reference it. Status header updated from "post-v1.0 design
draft, no code" to an implementation map against the arc, so the
landed doc is not self-contradictory. Design body unchanged; the
"Open questions" remain open by design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:26:21 -04:00
Levi Neuwirth c50db222d3 V0.2-prerequisite pull-forward + M10.11 clean audit round
Pulls a set of planned V0.2 prerequisites forward to ship in v1.0,
plus the clean audit-review round over that work.

V0.2-prereq implementations (documented promotions, not M11
surprises; operator raised the v1.0 public-API ceiling to absorb
them — see V0.2-PREREQUISITES.md "v1.0 pull-forward"):

- CC-1: `bypass_intercept` opts on buffer insert/delete/replace —
  skips the Lua intercept chain only; preserves the same-buffer
  re-entry guard, undo/dirty bookkeeping, view notifications, and
  CRDT broadcast queueing.
- CC-2: `pmacs.buffer.on_removed(buf, cb)` + idempotent `:remove()`
  handle; buffer-local keymaps pruned on removal. Fires for both
  `pmacs.buffer.remove` and `.kill` (incl. interactive C-x k);
  callback errors logged to *errors* without failing the removal.
- SP-4: `pmacs.buffer.from_file`.
- SP-5: `pmacs.fs.watch` (polling; `:cancel()`/`:is_cancelled()`).
- SP-7: `pmacs.async.yield_to_next_tick` (worker-free next-tick
  yield); outline-aggregate repaint now uses it instead of
  workers.sleep(0):await(), pinning propagation to one async tick.
- SP-1: `pmacs.editor.move_to_line` (0-based, clamps out-of-range).
- SP-6: `pmacs.outline.query` published by pmacs-outline.
- SP-3: audit rule 15 `reach-around-require-field` (Info).
- CC-3: runtime API-availability documented (docs-only).

Clean audit-review round (M10.11 framing stop-condition pass):

- Finding 1 (fixed): clippy needless_raw_string_hashes blocked
  `clippy -D warnings` on both lanes; raw-string delimiter fixed.
- Finding 2 (fixed): fs_watch acceptance test was racy — the
  `pending == 1` gate could not distinguish the in-flight baseline
  stat from the steady-state poll sleep, so under load the mutation
  raced the baseline (~1/3 fail in the default lane). Rewritten to
  re-emit a distinct change each pump iteration; 6/6 on the
  previously-failing invocation.
- Finding 3 (fixed): documented fs.watch's async-baseline startup
  window and size+mtime-granularity detection limit.
- Finding 4 / SP-8 (logged, non-blocking, out of diff): a
  pre-existing PTY-lifecycle test timing flake under severe CPU
  oversubscription; src/process.rs untouched here.

CC-1's opts-extension-counts question resolved explicitly
(consistent treatment: counted; ceiling raised to fit).

Gate at normal load, both lanes: fmt clean; clippy --all-targets
-D warnings clean; non-crdt lib 1223/0; crdt lib 1377/0;
m8_1/m8_9/m8_10 green.

Not in scope here: v1.0 CHANGELOG body, version bump, the M10.11
Finding-4 (reattach undo) user-facing artifact, and the recorded
two-laptop manual acceptance — tracked as the remaining v1.0 steps.

.gitignore: M*-FRAMING.md added to the internal-only block for
consistency with the M*-AUDIT.md / M*-SHIP-GATE.md siblings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 10:31:31 -04:00
Levi Neuwirth 587a2a15de M9 ship gate
Land the Model Context Protocol (MCP) integration as a transport binding,
not a built-in feature. Six Lua functions plus userdata methods expose
the substance of three MCP feature areas (resources, tools, prompts), a
notification dispatcher, and a non-trivial AI-assistance example package
that meets the architectural ship gate (spec/pmacs-spec.tex:1572): zero
direct calls into the Rust core, zero special-cased MCP handling outside
the public API, source under 2000 lines of Lua.

The M9.5 -> M9.6 -> M9.7 -> M9.8 layered composition validates the claim
"AI is a transport binding, not a feature" -- pmacs-mcp-ai composes with
pmacs-mcp-prompts.render and inherits notification handling transitively
through M9.7's package, demonstrating that the AI domain is a layer
above MCP, not a thread woven through the core.

Subtask shape:
  M9.1 stdio transport + initialize handshake + restart policy
  M9.2 resources with in-flight + settled cache and per-uri invalidation
  M9.3 tools with isError-vs-JSON-RPC-error semantics + cancellation
  M9.4 prompts with required-argument validation
  M9.5 notification dispatcher (on_notification, off_notification)
  M9.6 tools-as-commands fixture package + 12 audit findings disposed
  M9.7 prompts-as-result-buffers fixture package + tree-sitter-md grammar
  M9.8 AI-assistance fixture package (363+ LoC; 17/17 acceptance tests)
  M9.9 formal package audit -- PASS on all three criteria
  M9.10 release: TRANSITION-M9.md + MCP-for-package-authors guide

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 15:04:23 -04:00
Levi Neuwirth 0b715de505 M7 tail: package system, audit lint, lockfile, resolver 2026-05-07 16:50:37 -04:00
Levi Neuwirth 291eb0fd8d Fix CI and Documentation issues 2026-05-04 10:19:19 -04:00
Levi Neuwirth c8d0d67615 Fix PTY final-output drain race 2026-05-04 09:44:30 -04:00