Completes Arc 8 Stage 1: the Lua-side tables that turn a recognized
grammar into a usable mode, plus the acceptance suite for all twelve
framing criteria.
comment.lua -- `lean4 = "--"` (Q#LN5). Line comments only; Lean's block
comment `/- -/` and docstring `/-- -/` belong to the comment arc's own
named deferral and this lane does not front-run it.
pair.lua -- `⟨⟩`, `⦃⦄`, `⟮⟯` alongside the ASCII brackets (Q#LN6). The
anonymous constructor is among the most-typed constructs in Lean;
omitting it would make the pair set feel broken. The other two ride along
because the Stage 4 input method can produce them, and a bracket the pair
set does not understand is worse than one it does. All three sit outside
the nine built-in pair chars, so per Q#AP1 their undo is
cross-peer-degraded -- the documented, pre-existing limitation of
user-extended pairs. No `''`: Lean uses the prime as an identifier suffix
(`h'`, `foo'`), the same reason Rust excludes it.
syntax.lua -- the `lean` -> `lean4` modeline alias (Q#LN2), so an Emacs
`-*- mode: lean -*-` or a Vim `ft=lean` line is not stranded by the entry
being named `lean4`.
syntax.rs -- the `lean` -> `lean4` injection alias (Q#LN17), so both
```lean and ```lean4 fences highlight. The Lean 3 spelling is mapped
forward deliberately: a ```lean fence is overwhelmingly Lean 4 in
practice.
highlight.rs -- `warning` moves from bold red to bold BRIGHT red. Writing
the test found the collision: `number` is plain `fg(1)`, so `sorry` and
the literal `42` beside it were the same colour, differing only in the
bold flag. `sorry` means "admitted, not proved" and is the one token in a
proof file a reader must never skim past, so it now gets the loudest
entry in the table and the test asserts the full style rather than the
colour.
Twelve criteria, seventeen tests. Notes on the ones that could have been
vacuous:
* acc4 uses a `.txt` fixture, not `.lean` -- on a `.lean` path the
extension alone yields `lean4` and the assertion would pass with the
alias table empty. acc4b removes the alias and pins that the raw name
survives, so acc4 cannot silently stop testing anything.
* acc11 goes through the real `_parse_now` injection path and asserts a
`lean4` CHILD LAYER appears. `pmacs.parse.injection_aliases` is a
documented write-only proxy, so an alias-table read would have proven
nothing about the parser; acc11b pins that a misspelled fence still
resolves to nothing.
* acc12 asserts through the process supervisor and the server list that
opening a Lean buffer spawns nothing. This is not decorative: the
machine this arc was scouted on has elan installed with no default
toolchain, where `lake --version` itself fails, and Stage 1 must be
unaffected by that.
Gates: fmt and strict workspace clippy clean; 1,826 default + 2,003 CRDT
library tests; lean4 Stage 1 9, comment toggle 14, auto-pair 45,
injection 4; M4 121; required GPU 152; isolated-config workspace sweep
3,150 across 90 suites; `git diff --check` clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
New builtin/runtime/comment.lua: `edit.toggle-comment` comments or
uncomments the current line — or every line the region touches — using
the language's line prefix from the public, user-extensible
`pmacs.comment.strings` table (Q#CT3; block comments deferred).
Language detection reuses lsp.lua's grammar+filetypes chain, now
exported as `pmacs.lsp.active_buffer_language()` (the only lsp.lua
touch — one assignment).
Semantics (Q#CT4): uncomment iff every non-blank line already starts
(after its indentation) with the prefix, stripping the prefix plus one
padding space; otherwise comment, inserting `prefix .. " "` at the
minimum indentation of the span's non-blank lines (Emacs comment-region
alignment). Blank lines are skipped in both directions and don't feed
the min-indent; an all-blank span is a status no-op. Mixed spans
comment — the double prefix round-trips, preserving inner
commented-out code.
The whole toggle is ONE buf:replace (Q#CT5): one undo step (no undo
grouping exists — N per-line edits would need N undos), one CRDT op,
and one effective-edit verification with the killring intercept
discipline (pcall'd; a rejection reports rather than throws; any
post-intercept deviation reports and skips the cursor fix-up).
No-region M-; is Emacs `comment-line`, not `comment-dwim`: toggle,
then move to the next line so repeated M-; walks a block (named
deviation; DWIM's append-at-EOL can come later under its own name).
Region toggles clear the selection and land at the span start. The
command boundary substrate provides chain-break and after-edit for
free (Q#CT6) — asserted anyway.
Tests (comment_toggle_acceptance, 14): rust/lua/python prefixes and
exact round-trips; cursor-next-line incl. the no-trailing-newline
clamp; region min-indent alignment + blank-line skip + selection
clear; mixed-span round-trip; region ending at column 0 excludes that
line; unknown-language and pathless-scratch no-ops; ONE undo restores
a multi-line toggle; rejecting/transforming intercepts (cursor fix-up
skipped); after-edit exactly once on both keybound and M-x paths;
C-k, M-;, C-k breaks the kill chain. Fixture editors empty
pmacs.lsp.config so .rs/.py files never spawn real servers.
Gates: fmt; workspace clippy -D warnings; lib 1500; crdt 1672;
comment 14; killring 30; cua 5; completion 9; autosave 29; m4 100
(--skip basedpyright); GPU 58 (PMACS_REQUIRE_GPU=1); full workspace
sweep clean; git diff --check clean.
Framing: docs/comment-toggle-framing.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtRqijWecEzTjPt1B4Nrt5