From 8b685dc127af1198b01722d1768b0302fa5400b1 Mon Sep 17 00:00:00 2001 From: Levi Neuwirth Date: Sat, 25 Jul 2026 15:08:24 -0400 Subject: [PATCH] docs: record dired Stage 1 (PR #165) and what it falsified MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/dired-framing.md rev 6: §0 gains the Stage 1 implementation notes (S1-1..S1-9) -- the normalizer is exposed rather than mirrored (so B2 is false by one small binding, in the direction Q#DR2 preferred); R2-3's dedication claim is falsified by the display policy; acceptance 3c cannot pin the descent routing and now says so; dired is the first builtin to bind a mode-scoped key, which one pre-existing lib test assumed impossible; `C-x d` takes no completion source on purpose; ownership is the handle table alone; the mark column ships blank; a symlinked directory needs a probe; and interactive origin does not survive an await. COHERENCE.md, per its §25 (an audited claim this PR changes updates here, riding the PR): §1.1's interactive-file-opening fact, §2's journey step 7, §4's beginner-level `files`, §14's tree bullet (Stage 1 landed a flat listing and did NOT invent a tree convention), and §15's Priority 1 list. Step 3 stays **Missing at the CLI** with the mechanism spelled out: `pmacs .` still exits 1, and this arc deliberately does not claim the CLI path -- it supplies the buffer a directory should resolve to. docs/active-work.md: the dired lane rewritten for Stage 1, including why the branch is a fresh cut rather than a rebase of `dired`, the durable substrate facts, the bite results (one VACUOUS, recorded rather than relabelled), and the verification. Its canonical-base line was four merges stale and now names 8c86d34. docs/agent-handoff.md: one forward pointer only. The handoff describes merged state, so it absorbs the substance when this merges. --- COHERENCE.md | 37 +++++++---- docs/active-work.md | 139 +++++++++++++++++++++++++++++++----------- docs/agent-handoff.md | 5 ++ docs/dired-framing.md | 94 +++++++++++++++++++++++++++- 4 files changed, 223 insertions(+), 52 deletions(-) diff --git a/COHERENCE.md b/COHERENCE.md index 1594b69..b1557e7 100644 --- a/COHERENCE.md +++ b/COHERENCE.md @@ -119,10 +119,10 @@ detailed in §1.1–§1.3: **substrate without surface**, **the silence asymmetry**, and **per-arc coherence debt**. Coherence-shaped work already in flight at audit time: find-file / -dired Stage 0 (`C-x C-f`, PR #162, `docs/dired-framing.md`), bottom -panel Stage 1 (merged #155), multi-root LSP affinity (branch -`lsp-multi-root-affinity`), the config registry foundation (merged -#127). +dired Stage 0 (`C-x C-f`, merged #162, `docs/dired-framing.md`) and its +Stage 1 directory view (PR #165), bottom panel Stage 1 (merged #155), +multi-root LSP affinity (branch `lsp-multi-root-affinity`), the config +registry foundation (merged #127). --- @@ -192,9 +192,13 @@ working, unreachable capability: is Lua-bound; no builtin command opens `*lsp*` (§2, §9). - **Interactive file opening.** `pmacs.buffer.find_or_open` (`src/lua_bindings/mod.rs:3103`) had no interactive caller at audit - time; a complete 1,384-line dired exists as a frozen test fixture - (`tests/fixtures/pmacs-dired/init.lua`). Being fixed now: dired Stage - 0 (PR #162). + time; a complete 1,384-line dired existed only as a frozen test + fixture (`tests/fixtures/pmacs-dired/init.lua`). **Fixed:** dired + Stage 0 opens a path (`C-x C-f`, merged #162) and Stage 1 ships the + browsing view as a builtin (`C-x d` / `C-x C-j`, PR #165). The fixture + stays frozen — its `install_local` + `require` routing *is* the M8 + package-universality proof (Q#DR1) — and shrinking it is scheduled + after Stage 3. The strategic consequence: **most coherence gaps in pmacs are doors, not engines** — deliberately deferred surface, not design error. That is @@ -331,11 +335,11 @@ Full verdict table: |---|---|---|---| | 1 | Install | **Partial** | Source build only: `cargo build --release --workspace --features pmacs/crdt` (`README.md`). No binaries, no packaging. Runtime deps (`/bin/sh`, git, tar, coreutils) documented, never checked at runtime | | 2 | Launch unconfigured | **Works** | `EditorState::new()` → empty `*scratch*`; missing config is not an error (`src/config.rs:7-9`); recentf/saveplace/autosave default-on | -| 3 | Open real project | **Missing** | `pmacs .` exits 1 (above). No directory handling anywhere | +| 3 | Open real project | **Missing at the CLI** | `pmacs .` still exits 1 (above): `load_file` does `File::open` (which succeeds on a directory) then `read_to_end` → EISDIR, which is not `NotFound`, so `resolve_target_buffer`'s create-a-`[new file]` arm never fires. Dired Stage 1 (PR #165) supplies the buffer a directory should resolve *to*; routing `pmacs .` into it is Journey Stage 1's work, which must not invent a second directory surface | | 4 | Understand interface | **Partial** | Mode line gives name/modified/L:C/scroll + mode/LSP/terminal segments; but no welcome text (`EditorCore::new` sets `status: String::new()`), no cheat sheet, and `C-h` deletes a word (§18) | | 5 | Edit | **Works** | Full CUA + Emacs keymap in 161 lines (`builtin/keymaps/default.lua`); isearch, query-replace, kill ring, undo/redo, auto-indent/pair/comment, atomic save. Genuinely excellent zero-config | | 6 | Language intelligence | **Partial** | Rust grammar bundled and auto-attaches; rust-analyzer preconfigured (`builtin/runtime/lsp.lua:44-52`) — but a missing binary fails silently (§1.2) and highlighting masks it. No LSP status command exists to diagnose | -| 7 | Find symbol / file | **File: missing → in flight (PR #162). Symbol: works but undiscoverable** | No find-file/dired/picker existed at audit; `M-.`/`M-?`/`C-c o` bound but advertised nowhere and server-gated; no workspace-symbol command; `pmacs.index.*` has no UI | +| 7 | Find symbol / file | **File: fixed (open by path merged #162; browsing PR #165). Symbol: works but undiscoverable** | No find-file/dired/picker existed at audit. Now `C-x C-f` opens a known path and `C-x d` / `C-x C-j` browse (flat listing, `dired` mode keymap); `M-.`/`M-?`/`C-c o` still bound but advertised nowhere and server-gated; no workspace-symbol command; `pmacs.index.*` has no UI | | 8 | Open terminal | **Works but undiscoverable** | Full PTY with scrollback + modeline segment — reachable only as `M-x terminal`, no keybinding | | 9 | Build / test | **Partial** | `M-x compile.run` works, defaults cwd to detected project root, parses Rust `-->` errors — but no keybinding, an **empty first prompt** (`initial = last and last.cmdline or ""`, `builtin/runtime/compile.lua:1134-1138`), and no `cargo build`/`cargo test` suggestion despite `ProjectKind::Cargo` existing (`src/project.rs:77`) | | 10 | Inspect error | **Partial (good once reached)** | `E:n W:n` modeline counts, underlines, `M-g n/p` + ``C-x ` `` walking a unified compile/grep/diag source, message echo, `RET` visits. Gated entirely on step 6 or 9 succeeding first | @@ -428,7 +432,8 @@ level is the one missing. Audited level-by-level: **Beginner** (should see: files, buffers, search, diagnostics, terminal, build actions, menus, missing-tool guidance): -- files ✗ (no find-file at audit; PR #162 in flight) · buffers ✓ (`C-x +- files ✓ since #162 / PR #165 (`C-x C-f` opens a path, `C-x d` browses; + neither is advertised anywhere but the keymap) · buffers ✓ (`C-x b`, `*buffer-list*`) · search ✓ (`C-s`/`C-r`/`C-M-s`; project.search is M-x-only) · diagnostics ✓ once a server runs · terminal ✓ but M-x-only · build ✓ but M-x-only with empty prompt · menus △ @@ -1139,7 +1144,11 @@ Primitive-by-primitive against the list above: hierarchy, package dependency graph, worker trees, git status) will each need it; building it once *before* dired's directory view and the workers tree harden their own conventions is exactly this - section's point. + section's point. Dired Stage 1 (PR #165) landed **without** inventing + one: its listing is flat (Emacs parity), and the recursive + in-buffer case — `i` insert-subdirectory — is a named deferral in + `docs/dired-framing.md` §13, which is where a shared tree primitive + would land. - **Structured table / inspector / diff view** ✗ — none. (`describe.*` tables are the inspector's data model without a view; the wire-declared `ResourceOffer` family was reserved for diff/blame @@ -1346,8 +1355,10 @@ missing runtime entity — a real arc). Establish the end-to-end workflow; treat regressions as release blockers. **State: broken at step 3 (§2). Mostly wiring, and unusually -cheap:** directory-argument handling; a find-file surface (in flight, -PR #162); surfacing the LSP spawn failure with guidance (§1.2); a +cheap:** directory-argument handling (the remaining half of step 3 — +dired Stage 1 landed the buffer it should resolve to); a find-file +surface (**done**: #162 open-by-path, PR #165 browsing); surfacing the +LSP spawn failure with guidance (§1.2); a compile keybinding + `cargo build`/`test` default from the existing `ProjectKind::Cargo`; a terminal keybinding; a welcome buffer. The journey acceptance suite (§19) is the ratchet that keeps it fixed. diff --git a/docs/active-work.md b/docs/active-work.md index 6dc235f..b83a1bc 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -14,10 +14,11 @@ 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` @ `0dd16a5` (GPU initial-target #148 atop folding Stage 2 - landed-doc refresh #150, folding Stage 2 #149, the ledger refresh #147, web - grammars HTML+CSS #146, and the LaTeX Stage 1 #144 / inline-math framing - #145 pair; protocol v20). + `githubsucks/main` @ `8c86d34` (the dired framing #164 atop find-file + #162, COHERENCE.md #163, Lean 4 Stage 1 #160, the minimap blank-slab fix + #159, bottom-panel Stage 1 #155, the inline-math re-scout #154, the vterm + PTY-flake fix #153, and the GPU initial-target doc refresh #152; protocol + v20). - 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 @@ -51,7 +52,7 @@ git worktree list git status --short --branch ``` -The `git log` command must expose `0dd16a5` or a newer intentional main. +The `git log` command must expose `8c86d34` or a newer intentional main. If it does not, stop and repair the remote/fetch configuration. ## Lean 4 lane (Arc 8) — Stage 1 IN REVIEW (PR #160) @@ -124,44 +125,108 @@ If it does not, stop and repair the remote/fetch configuration. or markerless scratch files fragment into one server per directory for every language. -## Dired lane — framing APPROVED; Stage 0 MERGED, Stage 1 next +## Dired lane — Stage 0 MERGED; Stage 1 IN REVIEW (PR #165) -- Approved framing: `docs/dired-framing.md` (revision 5), landing as its - own docs PR off `githubsucks/main` @ `2af1ab3`, branch - `githubsucks/dired-framing`, worktree `../pmacs-dired-framing`. The - repo's `-framing`-branch convention (`vterm-framing`, - `gpu-initial-target-framing`, `tab-width-parity-framing`). +- Approved framing: `docs/dired-framing.md` **revision 6** — rev 5 is the + approved text (merged as its own docs PR #164), rev 6 adds §0's Stage 1 + implementation notes (S1-1…S1-9). Stages 2 (marks and operations) and 3 + (wdired) each get their own detailed framing after the prior stage lands. - **Stage 0 (`C-x C-f` find-file) MERGED as #162** (`main` @ `2af1ab3`, 2026-07-25, one review round, 12/12 CI green). Durable facts moved to `docs/agent-handoff.md` §1 per rule 3 below. -- **Stage 1 (the dired view) is next and unstarted.** Branch `dired` - (worktree `../pmacs-dired-arc`) carries the framing commits only and is - based on the now-superseded `0827dd1`; **rebase it onto the `main` - resulting from the framing PR before implementing**, or cut a fresh - branch — its framing commits become redundant once the docs PR lands. -- Stage 1's scope, from the framing §10: `builtin/runtime/dired.lua`; the - `dired` major mode + mode keymap; buffer-per-directory with lexical - canonicalization and the ownership check; read-only intercept + - `set_round_trip_input`; visit routing through `window.display_file`; - parent/sort/revert/quit; `C-x d` (with the `display` opt) / `C-x C-j`; - cursor preservation by basename; the `dired.kill-when-opening` config - key; **and the tolerant `read_dir` opt** — the only Rust in the stage. -- The one Rust change is load-bearing and is why Stage 1 is not - pure-Lua: `read_dir_blocking` (`src/fs.rs:201`) fails the **entire - listing** on any of five per-entry conditions, and the tolerant wrapper - its own module doc delegates to package authors **cannot be written in - Lua** — the primitive returns one error and no partial vec. -- Coherence (framing §0.5, required since #163): serves `COHERENCE.md` - §20 Priority 1, which names this work explicitly; journey steps 7 and - (partially) 3; **adds no interaction island** — keys are a mode-scoped - keymap, and wdired is a mode swap; adopts `pmacs.config` for - `dired.kill-when-opening`; inherits §9's worker-attribution gap for its - `read_dir` jobs without worsening it. +- **Stage 1 branch: `githubsucks/dired-stage1`**, worktree + `../pmacs-dired-stage1`, based on `githubsucks/main` @ `8c86d34` (the + framing merge #164). **A fresh cut, not a rebase:** the older `dired` + branch (`ffdd642`, worktree `../pmacs-dired-arc`) was based on the + superseded `0827dd1` and carried only the framing content #164 already + put on `main`, so merging it would have reconciled two histories of one + document. It is left untouched and carries nothing unmerged. +- **Stage 1 implemented; no wire change (protocol stays v20).** What + landed on the branch: + - `builtin/runtime/dired.lua`: one buffer per directory named + `*dired:*` with the handle-table ownership check; + read-only intercept + `set_round_trip_input`; the `dired` major mode + and its mode-scoped keymap (`RET`/`f`, `^`, `n`/`p`, `g`, `q`, `s`); + basename cursor re-seating across every wholesale repaint; + `display_file` for file visits and same-window reuse for directory + descent; `C-x d` / `C-x C-j`; the `dired.kill-when-opening` setting. + Loaded after `window.lua`. + - `src/fs.rs`: `ReadDirTolerance`, `FsDirEntryError`, `FsDirListing`, + and one walk that either fails on a per-entry condition or records it + (Q#DR6). `src/async_runtime.rs` carries the listing in + `ReplyKind::ReadDir` / `JobResult::ReadDir`; `src/lua_bindings/mod.rs` + keys the Lua result **shape** on `errors.is_some()`, so the bare array + the frozen M8.2 fixture consumes with `ipairs` is untouched; + `builtin/runtime/fs.lua` validates read-op opts and **rejects unknown + keys** (a typo'd `tolerant` used to degrade silently to fatal). + - `src/editor_core.rs` + `src/lua_bindings/mod.rs`: + `normalize_buffer_path` is `pub` and exposed as + `pmacs.path.canonicalize` — Q#DR2's preferred end state, so no Lua + mirror exists and Stage 2 owes no mirror removal. This makes B2 + ("tolerant `read_dir` is the only Rust change") false by one small + binding, deliberately. + - `tests/dired_acceptance.rs`: 22 tests over framing items 1–16, + dispatch-driven; item 17 is the m8_1/m8_2/m8_3 additivity gate. +- **The framing claim the substrate falsified (S1-2):** R2-3 expected a + dedicated dired panel to carry its dedication across a descent. + `display_buffer` never replaces the buffer in a slot dedicated to + another one — it discards every side-specific parameter and falls back + to the document window (Q#BP3 2.iii), and the exact-window arm errors. + Dired does not unpin the user's panel; both arms are pinned. +- **The vacuity the bites found (S1-3):** acceptance 3c cannot pin the + descent *routing*. Dired holds focus in its own panel, so a raw + `switch_buffer` lands in the same window and every 3c assertion holds + either way. Dedication is the only discriminator, so the + dedicated-panel test is the real pin — and the vacuity is documented at + the assertion rather than relabelled. +- **The pre-existing test dired's first mode-scoped binding broke + (S1-4):** `describe_key_identifies_every_default_binding` asserted every + binding in the stack resolves through `describe.key` context-free, which + held only while the modes table was empty. It now sets the effective + context per binding and explicitly *clears* the mode for global ones, + because a leaked mode legitimately shadows a global chord of the same + name (dired's `RET` shadows `edit.newline-and-indent`). +- Durable substrate facts, independent of this arc: + - `pmacs.buffer.kill` (not `remove`) redirects windows off a doomed + buffer before removal, so `kill-when-opening` kills **after** the + replacement is displayed. + - Interactive origin does **not** survive an await: work resumed in + `tick_async` sees no `InteractiveCommandOrigin`, so `pmacs.window.*` + acts for the *ambient* active frontend (S1-9). + - Kinds are lstat-based in both `read_dir` and `stat`, so nothing in an + entry says whether a symlink points at a directory; `RET` probes by + trying to list it (S1-8). + - A path-backed buffer's *name* is its full path, not its basename — + worth knowing before writing any name assertion. + - `C-x d` takes **no** completion source on purpose (S1-5): with one, + RET on an empty field opens whatever sorts first, and + RET-on-where-you-are is the gesture the binding exists for. The field + is prefilled instead. +- **Bite verification:** 15 claims, each mutated in place and required to + fail the test that names it. `dired.lua` is new, so `scripts/bite`'s + file swap does not apply; every mutation was applied and reverted with + `git checkout --`. One came back VACUOUS and is recorded above. +- Verification on this branch: `cargo fmt --check` clean; strict workspace + Clippy clean; 1,829 default + 2,006 CRDT library tests; dired acceptance + 22 default + 22 CRDT; m8_1 10 / m8_2 15 / m8_3 32 unchanged; M4 121; + required GPU 155; **isolated-`XDG_CONFIG_HOME` workspace sweep 3,186 + passed across 92 suites, zero failures**; `git diff --check` clean. The + sweep needs the isolated config for the reason recorded in the + bottom-panel lane below. +- Coherence (framing §0.5, required since #163): serves `COHERENCE.md` §20 + Priority 1, which names this work explicitly; journey step 7's file half + goes from no surface to a surface; **adds no interaction island** — keys + are a mode-scoped keymap, and wdired will be a mode swap; adopts + `pmacs.config` for `dired.kill-when-opening`; inherits §9's + worker-attribution gap for its `read_dir` jobs without worsening it. The + audited claims this changes are updated in `COHERENCE.md` itself, per its + §25. - **Boundary with the Journey Stage 1 arc** (`COHERENCE.md` §20 arc-cut 1): CLI directory-argument handling (`pmacs .` exits 1) belongs there, - not here. The two meet at `resolve_target_buffer`; dired supplies the - buffer a directory should resolve *to*, and `pmacs .` should route into - it rather than growing a second directory surface. + not here — Stage 1 does **not** fix it. The two meet at + `resolve_target_buffer`; dired supplies the buffer a directory should + resolve *to*, and `pmacs .` should route into it rather than growing a + second directory surface. ## Bottom-panel lane (window placement + side windows) — Stage 1 IN REVIEW diff --git a/docs/agent-handoff.md b/docs/agent-handoff.md index a844230..fe51463 100644 --- a/docs/agent-handoff.md +++ b/docs/agent-handoff.md @@ -70,6 +70,11 @@ commands, read `docs/active-work.md` immediately after this file. against an open buffer yet fails to load one that is not open — find-file expands the tilde Lua-side. Loading through the normalized path is a named deferral. + - **Stage 1 (the directory view) is IN REVIEW as PR #165** — the + builtin `dired.lua`, the per-entry-tolerant `read_dir` opt, and + `pmacs.path.canonicalize`. Its branch state, substrate facts, and + verification live in `docs/active-work.md`; this section absorbs them + when it merges. - **GPU initial target LANDED — #148** (`docs/gpu-initial-target-framing.md` rev 3; merge `0dd16a5`; two review rounds). `pmacs --gpu [--socket NAME|PATH] FILE` transports exact Unix path diff --git a/docs/dired-framing.md b/docs/dired-framing.md index 87b4573..3f6b8a5 100644 --- a/docs/dired-framing.md +++ b/docs/dired-framing.md @@ -1,11 +1,13 @@ # Dired — framing -**Revision 5 — 2026-07-25. Status: APPROVED; Stage 0 MERGED as #162.** +**Revision 6 — 2026-07-25. Status: APPROVED; Stage 0 MERGED as #162; +Stage 1 IN REVIEW as PR #165.** Rev 1 passed a ground-truth review; rev 2 fixed round 1's seven findings; rev 3 fixed round 2's six and was approved; rev 4 recorded what Stage 0's implementation falsified in the approved text (§0); rev 5 adds the **coherence impact** statement now required of every framing -(`CLAUDE.md`, `COHERENCE.md` §20) — see §0.5. Deliberately +(`CLAUDE.md`, `COHERENCE.md` §20) — see §0.5; rev 6 records what Stage +1's implementation falsified (§0, S1-1…S1-9). Deliberately unnumbered: the roadmap's Arc 8 is GPU structural parity but `docs/lean4-mode-framing.md` also claims Arc 8, so the arc space is already forked in uncommitted work. (Rev 2 also cited @@ -203,6 +205,94 @@ the correction belongs here rather than only in the code. same normalize-before-lookup family as Q#DR5's `apply_resource_op` correction. +### Stage 1 implementation notes (rev 5 → rev 6) + +Implementing Stage 1 (PR #165) falsified four things the approved text +asserted and settled five it left open. Recorded here rather than only +in the code, per the rev-4 precedent. + +- **S1-1. The normalizer is EXPOSED, not mirrored — so B2 is partly + false, in the direction Q#DR2 preferred.** Q#DR2 made the mirror + conditional (`Stage 1 may still mirror if exposure turns out to drag + in EditorCore borrow plumbing it does not otherwise need`). + `normalize_buffer_path` is a **free function** (`editor_core.rs`), so + exposure drags in nothing: it is now `pub` and reachable as + `pmacs.path.canonicalize`. Consequences, all deliberate: B2 ("tolerant + `read_dir` is the only Rust change Stage 1 needs") is false by one + small binding; acceptance 3b degenerates to the round-trip form the + framing described; and the Stage 2 mirror-removal follow-up **is not + owed** — there is no second canonical form to remove. The parity + acceptance is still carried, now as "the Lua binding and the Rust + function agree over one shared edge list", which is exactly the claim + a future re-mirroring would break. +- **S1-2. R2-3's dedication claim is falsified by the substrate.** It + read "a dedicated dired panel stays dedicated across descent and the + new dired buffer inherits it". `display_buffer` never replaces the + buffer in a slot dedicated to another one: it discards every + side-specific parameter and falls back to the document window (Q#BP3 + 2.iii), and the exact-window arm errors outright. Dired therefore does + **not** try to unpin the user's panel — which is also what Emacs's + `display-buffer` does with a dedicated window. Acceptance 3c is split: + a non-dedicated panel keeps the descent, and a dedicated one keeps its + buffer *and* its pin while the new directory appears in the document + window. +- **S1-3. Acceptance 3c cannot pin the descent ROUTING, and the test now + says so.** Dired holds the focus in its own panel, so a raw + `switch_buffer` lands in that same window and every 3c assertion holds + either way — the mutation is *vacuous* against it. Dedication is the + only thing that distinguishes `display { side = … }` from the raw + switch, so the dedicated-panel test is the discriminating pin. Found + by running the bite rather than by reading the test; the vacuity is + documented at the assertion instead of being left to be believed. +- **S1-4. Dired is the first builtin to bind a mode-scoped key, and one + pre-existing lib test assumed none existed.** + `describe_key_identifies_every_default_binding` iterated *every* + binding in the stack and asserted `pmacs.describe.key` resolves it + context-free, which held only while the modes table was empty. It now + sets the effective context per binding — and explicitly *clears* the + mode for a global one, because a mode left over from a previous + iteration legitimately shadows a global chord of the same name + (dired's `RET` shadows `edit.newline-and-indent`, which is the point + of the mode). +- **S1-5. `C-x d` deliberately takes NO completion source.** It is the + direct consequence of S0-1/S0-4: with a `files` source, RET on an + empty field opens whatever sorts first (the minibuffer selects + candidate 0 whenever the list is non-empty, and a selected candidate + shadows typed text), and RET-on-the-directory-you-are-in is exactly + the gesture `C-x d` exists for. The field is **prefilled** with the + current directory instead — Emacs's own shape here — and free text + always reaches `on_accept` because `CompletionSource::None` bypasses + candidate resolution entirely. Directory-name completion is what dired + itself replaces. +- **S1-6. Ownership is the handle table ALONE**, narrower than Q#DR2's + "present in dired's handle table, or `major_mode(buf) == "dired"`". A + foreign buffer that carries the mode *is* the case the check exists to + refuse, and a builtin's handle table cannot be lost the way a + reloadable package's can. Acceptance 4 sets the mode on the foreign + buffer to pin the stronger reading. +- **S1-7. The mark column ships in Stage 1, rendered blank.** Q#DR4 is a + Stage 2 decision, but reserving the two columns now means Stage 2 does + not move every offset and Stage 3's column-classifying intercept can + be written against constants that did not shift under it. The + constants are computed from the widths (the fixture hardcoded + `NAME_START = 39` and paid for it in every wdired test) and exported + as `pmacs.dired._layout` so acceptance cannot drift from them. +- **S1-8. A symlinked directory needs a probe, because kinds are + lstat-based.** Both `read_dir` and `stat` report a link as + `"symlink"`, so nothing in the entry says whether it points at a + directory. `RET` on a symlink therefore *tries* to list the target + (one extra syscall, on symlink lines only) and descends if that + succeeds, else visits it as a file. Q#DR10 specified only the + dir/file arms; this is the third. +- **S1-9. Interactive origin does not survive the await.** Every listing + is worker-dispatched, so the work after the first `:await()` resumes + inside `tick_async`, where `InteractiveCommandOrigin` is empty and + `pmacs.window.*` falls back to the **ambient** active frontend. Single + frontend: correct. Multi-frontend: a dired opened from peer B while A + is ambient would display for A. Not fixable from Lua (the display + surface takes no frontend argument) and named here rather than + discovered later. + ## 0.5. Coherence impact (`COHERENCE.md` §20) Required of every framing since #163. This arc was scouted and approved