docs(coherence): §5 substrate-without-surface -> Partial

Per §25 the audited claim this stage falsifies is updated on the
landing PR. §5's scorecard row and ground truth both said the
registration metadata was best-in-class with almost no way for a user
to reach it; eleven `help.*` commands now reach it.

The row names what is still missing rather than implying the concern is
closed: packages and workers have no discovery surface, `Command` still
has no title/category/aliases/flags, M-x rows are still bare name
strings, the predicate is still never evaluated, settings value
provenance is still absent, and there is still no help prefix key. The
original audit grade is kept inline for reference.

`docs/keybindings.md` gains the family table and records that the
commands are reachable by name and bound to nothing — the help-prefix
decision belongs to a later stage, for the reason #205 recorded.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
This commit is contained in:
Levi Neuwirth 2026-07-31 19:17:22 -04:00
parent 44bd2201e7
commit c0407dc6a7
4 changed files with 92 additions and 7 deletions

View File

@ -98,7 +98,7 @@ remain open to them.
| 2 | Golden product journey | **Runs to step 10** | `pmacs .` opens the directory (1a); the interface introduces itself (1b-3); a missing language server says so (1b-2, #204); a build is bound and prefilled (1b-1, #203). Steps 1, 11 and 12 remain the thin end | | 2 | Golden product journey | **Runs to step 10** | `pmacs .` opens the directory (1a); the interface introduces itself (1b-3); a missing language server says so (1b-2, #204); a build is bound and prefilled (1b-1, #203). Steps 1, 11 and 12 remain the thin end |
| 3 | Zero-configuration state | **Partial** | Defaults genuinely strong; missing-tool failure is silent, not graceful | | 3 | Zero-configuration state | **Partial** | Defaults genuinely strong; missing-tool failure is silent, not graceful |
| 4 | Progressive disclosure | **Inverted** | The advanced level is real; the beginner level is the missing one | | 4 | Progressive disclosure | **Inverted** | The advanced level is real; the beginner level is the missing one |
| 5 | Unified discoverability | **Substrate without surface** | Best-in-class registration metadata; almost no way for a user to reach it | | 5 | Unified discoverability | **Partial** | Discovery Stage 1: eleven `help.*` commands (describe key/mode/hook/buffer/command/setting, where-is, list commands/keybindings/settings, apropos) over the existing registries, indexed by `M-x help`. Commands, keys, modes, hooks and settings are now reachable; **packages and workers are not** (§13, §9), `Command` still has no title/category/flags, M-x rows are still bare names, and the Rust help layer is still orphaned |
| 6 | Interaction islands | **Weak, and growing** | Six hardcoded key-interception shadows; no transient-keymap mechanism exists | | 6 | Interaction islands | **Weak, and growing** | Six hardcoded key-interception shadows; no transient-keymap mechanism exists |
| 7 | First-class workspaces | **Missing (conventions only)** | Marker walk + four independent consumers; no workspace object | | 7 | First-class workspaces | **Missing (conventions only)** | Marker walk + four independent consumers; no workspace object |
| 8 | Execution locations | **Missing (architecture ready)** | SSH attach works; "location" is not a value anywhere | | 8 | Execution locations | **Missing (architecture ready)** | SSH attach works; "location" is not a value anywhere |
@ -557,7 +557,25 @@ This suggests a general pmacs principle:
### Ground truth ### Ground truth
**Grade: substrate without surface — the sharpest instance of §1.1.** **Grade: partial — Discovery Stage 1 built the first surface.**
Eleven `help.*` commands now render the registries that were already
there: describe-key/mode/hook/buffer/command/setting, where-is, list
commands/keybindings/settings, and a substring apropos over names and
descriptions, indexed by `M-x help`. It needed **no Rust** — the data
was all reachable from Lua, and even the settings completion source is a
Lua function through `CompletionSource::Custom`.
**What is still missing** is itemized below and unchanged by that stage:
`Command` has no title/category/aliases/flags/arg-schema; the predicate
is still never evaluated; M-x rows are still bare name strings; the Rust
help layer is still orphaned (Stage 1 funnels every command through one
Lua seam so the eventual migration is enumerated per subject rather than
per call site); packages and workers have no discovery surface; settings
value provenance is still absent; and there is still no help prefix key.
*The original audit grade, for reference:* **substrate without surface —
the sharpest instance of §1.1.**
**What the substrate already has (genuinely strong):** **What the substrate already has (genuinely strong):**

View File

@ -380,11 +380,11 @@ which would have re-conflicted on every merge.
githubsucks/journey-stage1b3-welcome githubsucks/journey-stage1b3-welcome
``` ```
## Discovery Stage 1 (P4) — FRAMING APPROVED (rev 6); implementation next ## Discovery Stage 1 (P4) — IMPLEMENTED, PR OPEN
- **Branch `discovery-stage1-commands`**, worktree `../pmacs-p4-discovery`, - **Branch `discovery-stage1-commands`**, worktree `../pmacs-p4-discovery`,
based on `githubsucks/main` @ `54a092e`. **Framing only; no code, no based on `githubsucks/main` @ `54a092e`. **Implemented; PR open.**
PR yet.** `docs/discovery-stage1-command-family-framing.md` revision 6, `docs/discovery-stage1-command-family-framing.md` revision 6,
three review rounds closed (round 1: two blocking, two major; round 2: three review rounds closed (round 1: two blocking, two major; round 2:
two blocking, two major; round 3: two factual corrections; all two blocking, two major; round 3: two factual corrections; all
accepted), Q#D2 / Q#D3 decided by the user, and the final review's accepted), Q#D2 / Q#D3 decided by the user, and the final review's
@ -453,6 +453,24 @@ which would have re-conflicted on every merge.
a behaviour change); help-layer unification; closed-set acceptance; a behaviour change); help-layer unification; closed-set acceptance;
and the **help prefix key**, which this stage does not touch because and the **help prefix key**, which this stage does not touch because
#205 recorded why `C-h` is not free. #205 recorded why `C-h` is not free.
- **Implementation notes.** `runtime/help.lua` is new and owns the
family plus the `help` index, which **moved out of `welcome.lua`** so
the greeting file keeps only the greeting; it loads after welcome.lua
so the index can read `pmacs.welcome.entries`.
- **The seam-counting pin caught a real bypass immediately.** The two
renamed commands were still calling the file-local `show_help_text`,
so the funnel the framing promised was fiction for exactly the two
commands that predate the seam. They now call
`pmacs.editor._show_help`, with a comment saying why the in-scope
local is deliberately not used.
- **Bites, all directed** — six mutations, each failing exactly one pin:
fuzzy apropos, name-only apropos, static where-is, a dropped
forwarder, an unindexed family command, and one command writing
`*help*` itself (seam count 10 vs 11).
- **§5 moves substrate-without-surface → Partial ON THIS PR** per §25,
with the remaining gaps named in the row: packages and workers have no
surface, `Command` still lacks title/category/flags, M-x rows are bare
names, and the Rust help layer is still orphaned.
- Recovery: - Recovery:
```sh ```sh

View File

@ -300,6 +300,37 @@ commands, read `docs/active-work.md` immediately after this file.
disagree — and it still establishes no identity, because it is read disagree — and it still establishes no identity, because it is read
inside the same read-then-act window and no portable mechanism closes inside the same read-then-act window and no portable mechanism closes
that for a *group* (`pidfd` covers a process; macOS has neither). that for a *group* (`pidfd` covers a process; macOS has neither).
- **Discovery arc (P4) — Stage 1 IMPLEMENTED, PR open**
(`docs/discovery-stage1-command-family-framing.md`, rev 6, three
review rounds). Eleven `help.*` commands over the existing registries,
indexed by `M-x help`. **§5 moves substrate-without-surface →
Partial.** No Rust: the data was all reachable from Lua, and the
settings completion source is a Lua function through
`CompletionSource::Custom` — correcting a `default.lua` comment that
claimed `source` was a fixed Rust-side vocabulary.
- **Completion is assistance, not validation.**
`resolve_accepted_value` returns the literal typed text whenever no
candidate is selected, so a typo still reaches `on_accept`; and a
fuzzy near-miss would silently select a *different* value. Refusing
a non-candidate is Rust work, deferred.
- **`apropos` is substring, not fuzzy.** `fuzzy_score` is
subsequence-based and descriptions are long sentences, so fuzzy
matches nearly everything. Pinned by a fixture whose description
contains the needle only as a non-contiguous subsequence.
- **One owner for `*help*` writes is what the seam buys — not a
one-site migration.** `src/help.rs` has renderers for
command/key/buffer/mode/hook/view and **none** for settings, lists
or apropos, and `_show_help` takes already-flattened text. Rendering
is therefore a named per-subject function, so the future Rust work
is enumerated per subject (three new renderers) rather than
discovered per call site.
- **The seam-counting pin caught a real bypass**: the two renamed
commands were still calling the file-local `show_help_text`, so the
funnel was fiction for exactly the two that predate it.
- **`Command.predicate` is still never evaluated** — read only at
`src/help.rs:76` and one test. A preservation pin registers a
*raising* predicate and asserts the command still runs, so a stage
that starts evaluating must change that pin knowingly.
- **Journey arc (P1) — Stage 1b-3 IMPLEMENTED, PR open** - **Journey arc (P1) — Stage 1b-3 IMPLEMENTED, PR open**
(`docs/journey-stage1b3-welcome-framing.md`, rev 4, three review (`docs/journey-stage1b3-welcome-framing.md`, rev 4, three review
rounds). The last of the 1b split. An unconfigured launch greets in rounds). The last of the 1b split. An unconfigured launch greets in

View File

@ -189,8 +189,26 @@ Source: `builtin/runtime/compile.lua`.
| `M-!` | `shell.command` — asynchronous output in `*shell-command*` | | `M-!` | `shell.command` — asynchronous output in `*shell-command*` |
| `C-c c` | `compile.run` — prompts, prefilled from the detected project kind | | `C-c c` | `compile.run` — prompts, prefilled from the detected project kind |
`M-x help` renders this file's essentials as a `*help*` buffer inside `M-x help` is the **index of the discovery family**, rendered as a
the editor, and is what the startup welcome points at. It is the root of `*help*` buffer inside the editor, and is what the startup welcome
points at. The family — all reachable by name, none bound to a key:
| Command | Shows |
|---|---|
| `help.describe-command` | a command's description and bindings |
| `help.describe-setting` | a setting's type, default, effective value |
| `help.describe-key` | what a chord runs in **this** buffer |
| `help.describe-mode` | the active buffer's major mode |
| `help.describe-buffer` | the active buffer |
| `help.describe-hook` | a hook and its listeners |
| `help.where-is` | which keys run a command |
| `help.list-commands` | every command with its description |
| `help.list-keybindings` | every binding, grouped by scope |
| `help.list-settings` | every registered setting |
| `help.apropos` | substring search over names **and** descriptions |
`editor.describe-command` and `editor.describe-setting` still work as
deprecated aliases of their `help.*` counterparts. It is the root of
the eventual help family (`help.keys` and friends arrive with the the eventual help family (`help.keys` and friends arrive with the
discovery arc), so it takes no keybinding yet — `C-h` is **not** free: discovery arc), so it takes no keybinding yet — `C-h` is **not** free:
it deletes a word because non-kitty terminals cannot tell Ctrl+Backspace it deletes a word because non-kitty terminals cannot tell Ctrl+Backspace