docs: record landed mode system

Move mode-system wiring from the active ledger into the durable handoff,
refresh the side-quest priorities, and preserve the macOS acceptance lessons
from the final CI review round.
This commit is contained in:
Levi Neuwirth 2026-07-22 08:40:35 -04:00
parent b4b925df49
commit aafa47514c
3 changed files with 53 additions and 50 deletions

View File

@ -1,6 +1,6 @@
# Active work — cross-machine resume ledger
**Snapshot: 2026-07-21.** This file records volatile work that has not
**Snapshot: 2026-07-22.** This file records volatile work that has not
landed on `main`. Read it after `docs/agent-handoff.md`. Remove completed
entries when their PR merges; do not let this become a second permanent
backlog.
@ -14,8 +14,8 @@ backlog.
machine-local: `origin` may name this canonical URL, a release mirror,
or something else, and therefore has no authority by name alone.
- Canonical base at this snapshot:
`githubsucks/main` @ `f1a2f75` (#128 documentation merge; runtime remains
config registry #127 at protocol v18).
`githubsucks/main` @ `b4b925d` (mode system wiring #129 merged;
protocol v18).
- On the transfer source, `origin/main` named a release mirror at
`d3fa632` and lagged badly. On the current destination, `origin` names
the canonical URL. This difference is why all recovery begins by
@ -49,44 +49,19 @@ git worktree list
git status --short --branch
```
The first command must expose `f1a2f75` or a newer intentional main.
The first command must expose `b4b925d` or a newer intentional main.
If it does not, stop and repair the remote/fetch configuration.
## Mode system wiring lane
- Portable branch: `githubsucks/mode-system-wiring`
- PR: #129, <https://github.com/levineuwirth/pmacs/pull/129>
- Base: canonical `main` @ `f1a2f75` (protocol v18).
- Approved framing commit: `424f82b`
- Implementation checkpoint: `99cd7ec`
- State: implementation complete and awaiting user review. One detected major
mode is stored per buffer; dispatch, describe-key, show-key, and encoded
help links resolve it; after-load initializes it once; explicit overrides
and clears survive switches; the existing statusline provider path renders
it per window. No protocol change.
- Verification at `99cd7ec`: formatting and Clippy clean; 1,742 default +
1,918 CRDT library tests; 8 default + 9 CRDT touched acceptance tests; 114
M4 tests; 109 required-GPU tests; workspace sweep 2,867 passed across 81
suites (19 ignored, 1 filtered); diff check clean.
Recovery worktree on a machine that does not already own the branch:
```sh
git worktree add --track \
-b mode-system-wiring \
../pmacs-mode-system \
githubsucks/mode-system-wiring
```
## Vterm Stage 2 framing lane
- Portable branch: `githubsucks/vterm-framing`
- Approved framing head: `fb4f8f0`
- Base: canonical `main` @ `643d1e1` (Vterm Stage 1 / PR #126 merged).
`main` has since advanced to `f1a2f75` (config registry #127 plus the #128
documentation merge, with no runtime overlap with vterm); cut the Stage 2
lane from current `main`, not from `643d1e1`.
`main` has since advanced to `b4b925d` (config registry #127, the #128
documentation merge, and mode system wiring #129); cut the Stage 2 lane
from current `main`, not from `643d1e1`.
- State: `docs/vterm-framing.md` Revision 7 is framing-only, reviewed, and
approved for implementation. It closes the final `at_bottom`, terminal
`C-c` binding-reachability, and context-implicit Lua failure-mode findings.

View File

@ -1,9 +1,9 @@
# Agent handoff — cross-machine continuity
**Last updated: 2026-07-21, after the config registry (#127) and Vterm
Stage 1 terminal core (#126) both landed on `main`, atop completed
Themes Arc 4 (#120/#124/#125). Vterm Stages 2 and 3 are not
implemented.**
**Last updated: 2026-07-22, after mode system wiring (#129) landed on
`main`, atop the config registry (#127), Vterm Stage 1 terminal core
(#126), and completed Themes Arc 4 (#120/#124/#125). Vterm Stages 2 and 3
are not implemented.**
This file is the
bridge between development machines. If you are an agent reading
this on a fresh clone: this document plus the `docs/*-framing.md`
@ -15,9 +15,9 @@ reads it the way you just did.
For volatile branches, checkpoints, verification, and recovery
commands, read `docs/active-work.md` immediately after this file.
## 1. Where the project stands (2026-07-21)
## 1. Where the project stands (2026-07-22)
- `main` @ `2e37c04` (config registry #127), protocol **v18**
- `main` @ `b4b925d` (mode system wiring #129), protocol **v18**
(`SUPPORTED=[6..18]`; v16 = `ThemeFacts`, v17 = `FontFacts`, v18 =
`StatuslineSegments`).
- **Config registry LANDED — #127** (`docs/config-registry-framing.md`
@ -40,8 +40,8 @@ commands, read `docs/active-work.md` immediately after this file.
local → global → default; **`get(name)` resolves the GLOBAL CHAIN
ONLY** and never consults an ambient buffer. Per-language and
per-project are *patterns* (a hook calling `set_local`), not scopes
the registry knows about. Mode scope is impossible until the mode
system is wired — every editor `KeymapStack::resolve` passes `&[]`.
the registry knows about. Mode keymaps now resolve through #129, but
`pmacs.config` deliberately remains global + buffer-local.
- Buffer-locals live in a registry side table purged at
`after_buffer_removed`, beside the keymap purge.
- Listeners: commit → snapshot → **drop the borrow** → re-enter Lua;
@ -61,6 +61,25 @@ commands, read `docs/active-work.md` immediately after this file.
their legacy coercion** — the registry is strict, the legacy setters
stay lenient (`trim_on_save("yes")`, `interval_ms(1500.7)`).
- `M-x describe-setting` renders into `*help*`.
- **Mode system wiring LANDED — #129** (`docs/mode-system-wiring-framing.md`;
merge `b4b925d`; one review round). The existing mode-keymap substrate is
now live without a protocol change.
- `Buffer.major_mode: Option<String>` owns the single major mode. The
detected language name initializes it once on `buffer.after-load`, before
grammar gating, so server-only languages work; switches never rewrite it.
Explicit overrides and clears survive switches. A future reload that fires
after-load re-detects, and explicit mode state is not session-persisted.
- Dispatch borrows the zero-or-one mode through `Option<&str>::as_slice()`
and `&[&str]`: no hot-path mode allocation. Resolution remains
buffer-local → mode → global, and registry/keymap borrows end before Lua
command invocation.
- Lua surfaces: `pmacs.buffer.major_mode` / `set_major_mode` and
`pmacs.editor.active_modes`. `pmacs.describe.key`, `pmacs.help.show_key`,
and followed percent-encoded `@mode:` links use the same effective context;
`pmacs.keymap.lookup` remains raw-global.
- The built-in `mode` statusline provider reads `ctx.buffer`, so passive
splits render their own mode. Real-daemon acceptance covers all ten framing
criteria across both Lua backends and Linux/macOS CI.
- **Syntax-highlight / language-detection side-quest (#114#118)
LANDED** — a one-shot arc built in sibling worktrees off main while
the user's themes lane (`theme-faces`) ran concurrently in the shared
@ -253,6 +272,8 @@ commands, read `docs/active-work.md` immediately after this file.
cross-cutting substrate ranked first on
`docs/side-quest-backlog.md`'s north star, and it unblocks the
editing/indent/comment items that were config-blocked.
- **Mode system wiring COMPLETE (#129)** — major-mode keymaps,
introspection, lifecycle initialization, and statusline display shipped.
- Remaining ranked arcs: 6 folding, 7 DAP, 8 GPU splits, plus the
`.ipynb` arc (its JSON-grammar prerequisite shipped in #123).
@ -433,6 +454,14 @@ acceptance.
and go through `pmacs.command.invoke("buffer.save")`. Caught only
because the *other* case failed and the cause was chased instead of
the assertion adjusted.
- **Real-grid acceptance must budget for macOS startup and path width.**
A 100 ms first-Hello timeout failed under loaded macOS CI; use the normal
five-second handshake window, then short polling reads. An 80-column split
also clipped a custom statusline segment after macOS's long
`/var/folders/...` temp path while passing on Linux; size the grid for the
longest supported fixture path (the mode-system test uses 160 columns per
split).
## 6. Named deferrals (the standing backlog, consolidated)
@ -475,6 +504,9 @@ setters (`async_config` ×2, `killring.max`, the `enable` booleans) and
currently accepted for `autosave.interval-ms`, where a per-buffer
value is meaningless.
**Tab width is NOT a config gap** — see §5.
Mode system (SHIPPED #129): minor modes, `buffer.after-mode-change`,
mode-scoped settings, modeline detection, `describe-mode`, and persistence of
explicit major-mode overrides/clears across sessions.
Highlight/detection (from the #114#118 side-quest + injections #122):
locals-query processing (run each grammar's LOCALS_QUERY so
`#is?`/`#is-not? local` is honored instead of the current fail-closed

View File

@ -130,8 +130,8 @@ The direct continuation of the #114#118 grammar/detection stack.
decision. Deferred from #127 on those grounds.
- **Real `read_only` buffer flag** on both edit paths — true immutability
for panels / REPL / generated buffers.
- **Mode system wiring** — dispatch passes an empty mode list (`&[]`);
mode-scoped keybindings unresolved everywhere.
- ~~**Mode system wiring**~~**SHIPPED as #129.** Per-buffer major modes
now drive key dispatch, effective-key introspection, and statusline display.
- **Buffer-aware edit epoch + origin-pinned `after-edit` fan-out** — a
command that edits buffer A then switches to B currently evades
`didChange` / reparse / autosave observers.
@ -237,17 +237,13 @@ guides (visual, not color).
## North star (highest-leverage first)
**Both original north-star items have now shipped** — multi-language
injections (#122) and the config registry (#127) — and JSON + YAML
(#123) merged too. The remaining board:
**The original north-star items and mode-system wiring have now shipped** —
multi-language injections (#122), the config registry (#127), JSON + YAML
(#123), and mode-system wiring (#129). The remaining board:
1. **Locals-query processing** — restores `.builtin` styling for
non-shadowed builtins, the last rough edge of the highlight stack.
2. **Mode-system wiring** — every editor `KeymapStack::resolve` still
passes `&[]`, so mode-scoped keybindings and any mode-scoped setting
remain unreachable. Promoted here because #127 made it the largest
remaining scoping gap.
3. **Tab-width rendering parity** — five constants across two crates
2. **Tab-width rendering parity** — five constants across two crates
with two different values, and no tab expansion at all on the GPU
main text path. Explicitly NOT a config-registry task; see the entry
under "Cross-cutting substrate".