diff --git a/docs/active-work.md b/docs/active-work.md index e0816fd..62f6afb 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -265,10 +265,61 @@ also removed: this branch's "R8 NEEDS A LANE" investigation block, and durable facts are in the retired registry row and the handoff §6 census. -## `scripts/gate --protocol` build step — IMPLEMENTED at `49bc141`, RE-OPENED by review, witness CLOSED at `677fd25`. No PR yet +## LSP LaTeX coverage — BRANCHED, framing in review -**PR #229 OPEN** — https://github.com/levineuwirth/pmacs/pull/229, -opened at `93d557a`. **Held, not merged.** Its first CI run went red on +**Written with the lane's first commit**, per the standing correction +from #171 and #215. + +**Branch `lsp-latex-coverage`**, base `githubsucks/main` @ `4bc55e8` +(the #225 merge). **`githubsucks/lsp-latex-coverage` is the +authoritative tip** — the ref, not a SHA. Recover with +`git fetch githubsucks && git checkout lsp-latex-coverage`. + +- **Framing `docs/lsp-language-coverage-framing.md`, revision 2**, in + review. **Revision 1 was UNTRACKED on `main` in one checkout** and + therefore did not travel; committing it here is the fix. +- **Scope: one `pmacs.lsp.config.latex` entry plus its root resolver.** + `texlab` 5.25.1 is installed and unused; a `.tex` buffer highlights + correctly and offers no completion, diagnostics, or go-to-definition. +- **Revision 2 found Slice 1 is SMALLER than revision 1 framed.** The + proposed `.tex`/`.latex`/`.sty`/`.cls` filetype mappings are + redundant: the grammar already carries exactly those extensions + (`src/syntax.rs:1111`), grammar-extension detection sits **ahead** of + the LSP filetype map in the precedence chain + (`docs/latex-grammar-math-substrate-framing.md:166-171`), and + `lsp.lua:267-270` calls that map "mainly the LSP-only fallback". The + two systems cannot disagree, because the grammar's extension list is + what drives detection. +- **Two other corrections.** `haskell-language-server` **is** installed + on this machine — revision 1 said it was not, which was the whole + basis of its Slice 1 / Slice 2 split. And Q#LX3's deferral argument + read `COHERENCE.md:1669` ("first slice in flight") when `:124` and + `:867` both record multi-root affinity as **merged (#161)**; that + line contradicts the same document twice and wants a separate fix. +- **Q#LX2 (the LaTeX root) is answered, with a caveat that must be + discharged first.** An upward marker walk — `.texlabroot`, + `latexmkrc`/`.latexmkrc`, `Tectonic.toml`, then the file's own + directory — through `config.latex.root`, which already accepts a + resolver function (`lsp.lua:543`). **`.git` is deliberately excluded**: + a repo root is the wrong answer for LaTeX, and it is the one place + copying the other fourteen entries' instinct is actively wrong. + **Whether texlab honours `.texlabroot` is UNVERIFIED** — only its + version and CLI were checked, and the CLI exposes no such surface. + Confirm against a live session before implementing; if it is not a + real marker, the walk starts at `latexmkrc`. +- **Gates:** `scripts/gate --acceptance `. No + `--protocol` — a config entry, no wire. + +## `scripts/gate --protocol` build step — **MERGED as #229** (`7cf4653`) + +**MERGED as PR #229** — https://github.com/levineuwirth/pmacs/pull/229, +at `3b10f9d`, 14/14 CI green including both macOS legs. `main` is now +`7cf4653`. *(This lane still awaits Rule 4 retirement — its durable +facts belong in the handoff before the entry is removed. Corrected here +only because the previous text said "Held, not merged", which the merge +falsified; the retirement itself is not this lane's work.)* + +**History, retained:** opened at `93d557a`. Its first CI run went red on `Test (macos-latest / lua54)`; the rerun turned that selector green and went red on a **different** one. Both are recorded as **U4** and **U5** in `docs/ci-red-signatures.md`, as separate incidents per the matching @@ -466,6 +517,7 @@ authoritative tip** — the ref, not a SHA. Recover with emission, an aborting runner, the build folded into `sweep-crdt`, and — added in the second round — a **rename of either** the build or the sweep step each fail the suite. +||||||| parent of 72bbb96 (docs: LSP LaTeX coverage framing revision 2, on a branch at last) ## QoL arc retirement — PR #224 OPEN (docs only) diff --git a/docs/lsp-language-coverage-framing.md b/docs/lsp-language-coverage-framing.md new file mode 100644 index 0000000..67bf343 --- /dev/null +++ b/docs/lsp-language-coverage-framing.md @@ -0,0 +1,238 @@ +# LSP language coverage: LaTeX (and the Haskell/OCaml question) + +**Status: framing pass, revision 2. Pre-implementation. Awaiting +approval.** + +**Revision 2 corrects three facts revision 1 got wrong or stale, and +answers the question revision 1 named as most likely to make the entry +wrong in practice.** Haskell's server *is* installed; Slice 1 is +**smaller** than framed because the extension wiring already exists; +Q#LX3's deferral argument rests on a `COHERENCE.md` line the same +document contradicts twice; and Q#LX2 (the LaTeX root) now has a +proposal rather than a shrug. + +**Revision 1 was untracked, on `main`, in one checkout.** Per the +handoff's own rule — work is portable only after it is committed and +pushed — it did not travel. That is fixed by this branch. + +--- + +## 0. What prompted this + +An audit of the host machine against `builtin/runtime/lsp.lua`. pmacs +configures LSP for fourteen languages — verified exactly, by extracting +the `pmacs.lsp.config.*` keys: + + bash c cmake cpp cuda dockerfile go json lua + python rust toml yaml zig + +**Lean is NOT among the gaps, and revision 1's first draft wrongly said +it was.** Lean 4 has `builtin/runtime/lean.lua`, `lean_abbrev.lua` and +`lean_input.lua` (all three present), an `arborium-lean` grammar, and +comment/typed-edit integration — Arc 8 Stages 1–4b, merged. The error +came from grepping `lsp.lua` alone, which is the wrong place to look +for a language that earned its own module. + +## 1. The gap, re-measured + +| Language | tree-sitter | LSP config | Server on this machine | +|---|---|---|---| +| LaTeX | ✅ grammar + `builtin/queries/latex/highlights.scm` | ❌ | **`texlab` 5.25.1 — installed** | +| Haskell | ❌ | ❌ | **`haskell-language-server` — INSTALLED** | +| OCaml | ❌ | ❌ | `ocaml`/`opam`/`dune` yes, `ocaml-lsp-server` **absent** | + +**Correction: revision 1 said Haskell's server was missing.** Both +`haskell-language-server` and `haskell-language-server-wrapper` are on +this machine. That collapses revision 1's Slice 1 / Slice 2 split, +which rested on "Slice 2 needs servers installed first" — only OCaml +does now. + +LaTeX remains the sharp case: the grammar work landed, so a `.tex` +buffer highlights correctly **and** offers no completion, no +diagnostics, no go-to-definition, while `texlab` sits on disk unused. + +## 2. Ground truth — Slice 1 is smaller than revision 1 claimed + +Revision 1 proposed "one `pmacs.lsp.config.latex` entry, **plus** +filetype mappings for `.tex`/`.latex`/`.sty`/`.cls`, matching the +grammar's existing extension set so highlighting and LSP agree on what +a LaTeX file is." + +**The filetype mappings are redundant, and the rationale describes a +problem that cannot occur.** Three facts, read rather than assumed: + +- **The grammar already carries exactly those extensions.** + `src/syntax.rs:1110-1112` — `name: "latex"`, + `extensions: &["tex", "latex", "sty", "cls"]`. +- **Grammar-extension detection sits AHEAD of the LSP filetype map.** + The merged `docs/latex-grammar-math-substrate-framing.md:166-171` + states the chain — *modeline → grammar extension → LSP filetype map → + filename map → shebang* — and concludes that adding those extensions + "**wires the whole chain with no Lua edit**". +- **The filetype map is explicitly a fallback.** `lsp.lua:267-270`: + "Every language with an LSP config now also ships a grammar, so this + is mainly the **LSP-only fallback** that keeps a language id stable if + a grammar is ever dropped, plus the seam for user-added mappings." + +So a `.tex` buffer **already** resolves to language `latex`. They +cannot disagree, because the grammar's extension list *is* what drives +detection. + +**Slice 1 is therefore one thing: the `pmacs.lsp.config.latex` entry** +(plus its root resolver, §3). Filetype-map entries may still be added +as the documented drop-a-grammar fallback, but that is belt-and-braces +and should be labelled as such rather than sold as making two systems +agree. + +## 3. Q#LX2 — the LaTeX project root **(answered in rev 2)** + +Revision 1 called this "the question most likely to make the entry +wrong in practice" and left it open. It is the difference between +texlab serving a multi-file thesis and serving isolated files, so it is +the whole value of the lane for the stated use case. + +**The mechanism exists.** `pmacs.lsp.config..root` accepts a +string **or a resolver function**, resolved through `resolve_root_fn` +(`lsp.lua:543`) with per-resolver memoization, and on the *reuse* path +as well as the spawn path (`:535`). A configured root "MUST be a +canonical absolute path" (`:525`). So this is a config entry, not new +machinery. + +*My vote: **an upward marker walk with an explicit precedence, falling +back to the file's own directory.*** In order: + +1. **`.texlabroot`** — if texlab honours it (see the verification + caveat below), an explicit user-placed marker should win over + everything inferred. +2. **`latexmkrc` / `.latexmkrc`** — a build config is a strong, + deliberate signal of a document root. +3. **`Tectonic.toml`** — the same for tectonic projects. +4. **The file's own directory**, as the fallback. + +**Deliberately NOT in the walk: `.git`.** A repository root is the +wrong answer for LaTeX — texlab wants the *document* root, and a thesis +inside a monorepo would otherwise get the monorepo. This is the one +place where copying the other fourteen entries' instinct would be +actively wrong. + +**Deliberately NOT proposed: scanning for `\documentclass`.** That is +the semantically correct notion of a root document, and it is a +directory scan on every resolve, with its own caching and invalidation +questions. If the marker walk proves insufficient in use, that is the +next increment — with evidence. + +**VERIFICATION CAVEAT, stated rather than buried.** `texlab 5.25.1` is +installed and its version and CLI surface were checked directly. Its +**LSP-level** behaviour — whether it honours `.texlabroot`, and how it +resolves multi-file projects from a root URI — was **not** verified +here; the CLI exposes only `run` / `inverse-search`, so this needs a +live session. **Marker 1 is provisional and must be confirmed against a +running texlab before implementation**, exactly as the sibling +`gate-protocol-build` lane requires its precondition to be observed +rather than reasoned about. If `.texlabroot` is not a real marker, it +drops and the walk starts at `latexmkrc`. + +## 4. Open questions + +### Q#LX1 — does `texlab` need `settings` or `init_options`? + +It pulls configuration via `workspace/configuration` under a `texlab` +section, which pmacs answers (#13). An empty section takes defaults, as +the Go entry does for gopls. + +*My vote: **ship nothing.*** Build-on-save and forward-search are the +two candidates and both are opinionated; forward-search additionally +needs a configured viewer, so a default would be wrong for most +machines. Users override through the same `init.lua` seam as the other +fourteen. + +### Q#LX4 — do Haskell and OCaml belong in this lane at all? *(renumbered — see below)* + +With HLS installed, Haskell is now the same shape as LaTeX: one entry, +no new dependency. **But the argument against it never rested on the +dependency.** The `.hs` files here are `levineuwirth.org`'s Hakyll +generator, edited rarely; HLS is version-coupled to GHC and is a large +resident process for a language touched a few times a year. + +*My vote: **LaTeX only in this lane.*** Add Haskell when there is use +evidence, which is a one-line change at that point. OCaml needs +`ocaml-lsp-server` via opam (not packaged for Arch) and is not close. + +**Renumbered from Q#HS1 deliberately.** The merged +`docs/latex-grammar-math-substrate-framing.md` already uses **Q#LX2** +for a different question — its grammar vendoring source (`:83`) — so +revision 1's Q#LX2 collided with a live ID in the same language area. +This document's LaTeX questions are Q#LX1 and the root question in §3; +the language-scope question takes Q#LX4 to avoid a second collision. + +### Q#LX3 — does this touch multi-root LSP affinity? — **RESOLVED, and revision 1 read a stale line** + +Revision 1 called this "the one item that could argue for deferring +Slice 1", on the basis that multi-root affinity was in flight. + +**It merged as PR #161.** `COHERENCE.md:124` lists it among landed +coherence work, and `:867` says "First slice landed (PR #161)". Only +`:1669` still says "first slice in flight" — and that line contradicts +the other two **within the same document**. + +So the deferral argument dissolves: a LaTeX entry keyed like the +existing servers rides the convention that already landed. **The +`COHERENCE.md:1669` inconsistency is real and should be fixed**, but by +whoever next touches §20 — not smuggled into this lane. + +## 5. Coherence impact (§20) + +- **Journey steps touched: none.** This adds a row to an existing + registry; no new surface, keybinding, or panel. +- **Interaction islands: none added.** +- **Config registry adoption: yes, and only that.** One entry in the + existing `pmacs.lsp.config` table, overridable from `init.lua` by the + same mechanism as the fourteen already there. +- **Background-work attribution (§9): unchanged, and NOT improved.** + texlab spawns under the existing LSP supervision path with no new + lifecycle — but it is another process that appears in `*lsp*` and + whose requests appear in `*workers*` with nothing joining them. The + worker-identity lane owns that; this lane neither helps nor worsens + it. +- **§20 classification: WIRING, not model.** It surfaces machinery that + already exists rather than adding a runtime entity — and §2 shows it + is *more* purely wiring than revision 1 thought. + +## 6. Verification + +- **A `.tex` buffer attaches texlab**, witnessed end to end rather than + by asserting the config table's contents. +- **Detection is unchanged**: `.tex`/`.latex`/`.sty`/`.cls` still + resolve to `latex` via the grammar path (§2), asserted so that a + later "helpful" filetype-map addition cannot be mistaken for the + thing that made it work. +- **The root resolver returns the marker directory**, witnessed on a + fixture with a `latexmkrc` above a `chapters/` subdirectory — the + thesis shape, which is the case a file-directory root gets wrong. +- **It falls back to the file's own directory** with no marker present. +- **`.git` does NOT become the root** (§3) — a fixture with a + repository above a document directory, asserting the document + directory wins. This is the case where copying the other entries' + instinct is wrong, so it is pinned. +- **A missing `texlab` surfaces guidance**, through the existing + spawn-failure path (#204) — asserted, not assumed, since that path is + what makes the failure honest. +- **Fixtures bound project detection** with + `pmacs.project.set_search_boundary`. R8 was a fixture letting + detection escape into the developer's environment; a LaTeX root + fixture is exactly that hazard's shape. + +**What this will NOT prove:** that texlab resolves multi-file `\input` +graphs correctly (that is texlab's job, not pmacs's), or that Haskell +and OCaml work (Q#LX4). + +## 7. Not in scope + +New tree-sitter grammars — Haskell and OCaml would have LSP without +highlighting, a real asymmetry that must be stated in the PR rather +than discovered by a user. Any change to Lean, which needs none. +Math/typesetting work (`#172` owns it). Any change to the LSP +spawn-failure surface (#204). Scanning for `\documentclass` to find a +root document (§3). Fixing `COHERENCE.md:1669`'s stale multi-root line +(Q#LX3) — real, but another lane's edit. Haskell and OCaml entries +(Q#LX4).