Merge pull request #169 from levineuwirth/docs-dired-stage1-landed
docs: record dired Stage 1 (#165) as landed
This commit is contained in:
commit
74301d1670
21
COHERENCE.md
21
COHERENCE.md
|
|
@ -120,7 +120,7 @@ asymmetry**, and **per-arc coherence debt**.
|
||||||
|
|
||||||
Coherence-shaped work already in flight at audit time: find-file /
|
Coherence-shaped work already in flight at audit time: find-file /
|
||||||
dired Stage 0 (`C-x C-f`, merged #162, `docs/dired-framing.md`) and its
|
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),
|
Stage 1 directory view (merged #165), bottom panel Stage 1 (merged #155),
|
||||||
multi-root LSP affinity (merged #161), the config registry foundation
|
multi-root LSP affinity (merged #161), the config registry foundation
|
||||||
(merged #127).
|
(merged #127).
|
||||||
|
|
||||||
|
|
@ -195,7 +195,7 @@ working, unreachable capability:
|
||||||
time; a complete 1,384-line dired existed only as a frozen test
|
time; a complete 1,384-line dired existed only as a frozen test
|
||||||
fixture (`tests/fixtures/pmacs-dired/init.lua`). **Fixed:** dired
|
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
|
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
|
browsing view as a builtin (`C-x d` / `C-x C-j`, merged #165). The fixture
|
||||||
stays frozen — its `install_local` + `require` routing *is* the M8
|
stays frozen — its `install_local` + `require` routing *is* the M8
|
||||||
package-universality proof (Q#DR1) — and shrinking it is scheduled
|
package-universality proof (Q#DR1) — and shrinking it is scheduled
|
||||||
after Stage 3.
|
after Stage 3.
|
||||||
|
|
@ -363,11 +363,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 |
|
| 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 |
|
| 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 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 |
|
| 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 (merged #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) |
|
| 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 |
|
| 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 |
|
| 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: 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 |
|
| 7 | Find symbol / file | **File: fixed (open by path merged #162; browsing #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** | Full PTY with scrollback + modeline segment, bound to `C-c t` and configurable through three registered settings (`terminal.default-profile`, `terminal.scrollback-rows`, `terminal.escape-key`) plus named `pmacs.terminal.profiles` (PR #173), and searchable through `M-x terminal.copy-mode` / `C-c C-t`, which materializes the retained scrollback into an ordinary read-only buffer (Stage 2). Named limitations: `C-c t` is unreachable from *inside* a terminal window, where `C-c` is consumed as the escape — `M-x terminal` still works there; and there is still **no close/kill command**, which is the remaining half of this step's discoverability gap. *Was broken outright on the GPU frontend until the double terminal-layout sync was fixed: the child took a `SIGWINCH` storm at tick cadence, so typing into it was impossible while output still flowed.* |
|
| 8 | Open terminal | **Works** | Full PTY with scrollback + modeline segment, bound to `C-c t` and configurable through three registered settings (`terminal.default-profile`, `terminal.scrollback-rows`, `terminal.escape-key`) plus named `pmacs.terminal.profiles` (PR #173), and searchable through `M-x terminal.copy-mode` / `C-c C-t`, which materializes the retained scrollback into an ordinary read-only buffer (Stage 2). Named limitations: `C-c t` is unreachable from *inside* a terminal window, where `C-c` is consumed as the escape — `M-x terminal` still works there; and there is still **no close/kill command**, which is the remaining half of this step's discoverability gap. *Was broken outright on the GPU frontend until the double terminal-layout sync was fixed: the child took a `SIGWINCH` storm at tick cadence, so typing into it was impossible while output still flowed.* |
|
||||||
| 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`) |
|
| 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 |
|
| 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 |
|
||||||
|
|
@ -467,7 +467,7 @@ level is the one missing. Audited level-by-level:
|
||||||
**Beginner** (should see: files, buffers, search, diagnostics, terminal,
|
**Beginner** (should see: files, buffers, search, diagnostics, terminal,
|
||||||
build actions, menus, missing-tool guidance):
|
build actions, menus, missing-tool guidance):
|
||||||
|
|
||||||
- files ✓ since #162 / PR #165 (`C-x C-f` opens a path, `C-x d` browses;
|
- files ✓ since #162 / #165 (`C-x C-f` opens a path, `C-x d` browses;
|
||||||
neither is advertised anywhere but the keymap) · buffers ✓ (`C-x
|
neither is advertised anywhere but the keymap) · buffers ✓ (`C-x
|
||||||
b`, `*buffer-list*`) · search ✓ (`C-s`/`C-r`/`C-M-s`; project.search
|
b`, `*buffer-list*`) · search ✓ (`C-s`/`C-r`/`C-M-s`; project.search
|
||||||
is M-x-only) · diagnostics ✓ once a server runs · terminal ✓ but
|
is M-x-only) · diagnostics ✓ once a server runs · terminal ✓ but
|
||||||
|
|
@ -1248,7 +1248,7 @@ Primitive-by-primitive against the list above:
|
||||||
hierarchy, package dependency graph, worker trees, git status) will
|
hierarchy, package dependency graph, worker trees, git status) will
|
||||||
each need it; building it once *before* dired's directory view and
|
each need it; building it once *before* dired's directory view and
|
||||||
the workers tree harden their own conventions is exactly this
|
the workers tree harden their own conventions is exactly this
|
||||||
section's point. Dired Stage 1 (PR #165) landed **without** inventing
|
section's point. Dired Stage 1 (merged #165) landed **without** inventing
|
||||||
one: its listing is flat (Emacs parity), and the recursive
|
one: its listing is flat (Emacs parity), and the recursive
|
||||||
in-buffer case — `i` insert-subdirectory — is a named deferral in
|
in-buffer case — `i` insert-subdirectory — is a named deferral in
|
||||||
`docs/dired-framing.md` §13, which is where a shared tree primitive
|
`docs/dired-framing.md` §13, which is where a shared tree primitive
|
||||||
|
|
@ -1412,7 +1412,8 @@ greets a new user says nothing (`EditorCore::new` sets an empty
|
||||||
status).
|
status).
|
||||||
|
|
||||||
Note the dependency: five of the ten onboarding steps above currently
|
Note the dependency: five of the ten onboarding steps above currently
|
||||||
lead somewhere broken or invisible (find a file — in flight; inspect a
|
lead somewhere broken or invisible (find a file — the mechanism is fixed
|
||||||
|
since #162/#165 but is advertised nowhere except the keymap; inspect a
|
||||||
diagnostic — silent-failure risk; view workers — undiscoverable;
|
diagnostic — silent-failure risk; view workers — undiscoverable;
|
||||||
setting provenance — unanswerable). Onboarding is correctly sequenced
|
setting provenance — unanswerable). Onboarding is correctly sequenced
|
||||||
*after* the P1/P4 fixes, but the cheap floor — a welcome buffer in
|
*after* the P1/P4 fixes, but the cheap floor — a welcome buffer in
|
||||||
|
|
@ -1476,7 +1477,7 @@ Establish the end-to-end workflow; treat regressions as release
|
||||||
blockers. **State: broken at step 3 (§2). Mostly wiring, and unusually
|
blockers. **State: broken at step 3 (§2). Mostly wiring, and unusually
|
||||||
cheap:** directory-argument handling (the remaining half of step 3 —
|
cheap:** directory-argument handling (the remaining half of step 3 —
|
||||||
dired Stage 1 landed the buffer it should resolve to); a find-file
|
dired Stage 1 landed the buffer it should resolve to); a find-file
|
||||||
surface (**done**: #162 open-by-path, PR #165 browsing); surfacing the
|
surface (**done**: #162 open-by-path, #165 browsing); surfacing the
|
||||||
LSP spawn failure with guidance (§1.2); a
|
LSP spawn failure with guidance (§1.2); a
|
||||||
compile keybinding + `cargo build`/`test` default from the existing
|
compile keybinding + `cargo build`/`test` default from the existing
|
||||||
`ProjectKind::Cargo`; a terminal keybinding; a welcome buffer. The
|
`ProjectKind::Cargo`; a terminal keybinding; a welcome buffer. The
|
||||||
|
|
@ -1546,7 +1547,9 @@ implementation — this list is direction, not commitment):
|
||||||
|
|
||||||
1. **Journey Stage 1** (P1): directory open + compile defaults +
|
1. **Journey Stage 1** (P1): directory open + compile defaults +
|
||||||
LSP-failure surfacing + bindings + welcome buffer + the first
|
LSP-failure surfacing + bindings + welcome buffer + the first
|
||||||
journey acceptance suite. Rides alongside the in-flight dired arc.
|
journey acceptance suite. Dired Stage 1 has landed (#165), so the
|
||||||
|
buffer a directory resolves *to* already exists; this arc routes
|
||||||
|
`pmacs .` into it rather than growing a second directory surface.
|
||||||
2. **Discovery surface** (P4): the describe/list/where-is command
|
2. **Discovery surface** (P4): the describe/list/where-is command
|
||||||
family, M-x rich rows, help unification, help prefix.
|
family, M-x rich rows, help unification, help prefix.
|
||||||
3. **Transient keymap layer** (§6): the overlay scope + lifetime
|
3. **Transient keymap layer** (§6): the overlay scope + lifetime
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,15 @@ 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
|
entries when their PR merges; do not let this become a second permanent
|
||||||
backlog.
|
backlog.
|
||||||
|
|
||||||
|
**Two lane headers below are stale on purpose**, pending the docs updates
|
||||||
|
their own lanes owe: multi-root LSP affinity **#161 has merged** (the
|
||||||
|
Lean 4 lane still says IN REVIEW; its continuation is PR #167) and GPU
|
||||||
|
terminal input **#166 has merged** (its lane still says IN REVIEW; PR
|
||||||
|
#168 records it). Trust the canonical-base line below over a lane header:
|
||||||
|
if a PR number appears in `git log --first-parent githubsucks/main`, it
|
||||||
|
has landed regardless of what its lane says. (The inline-math lane was
|
||||||
|
here too until #172 removed it — that is the update those two owe.)
|
||||||
|
|
||||||
## Repository authority
|
## Repository authority
|
||||||
|
|
||||||
- Canonical development URL:
|
- Canonical development URL:
|
||||||
|
|
@ -24,6 +33,8 @@ backlog.
|
||||||
Stage 1 #160, and the minimap blank-slab fix #159; protocol v20). The
|
Stage 1 #160, and the minimap blank-slab fix #159; protocol v20). The
|
||||||
previous snapshot named `d152120`; the recovery check below accepts it
|
previous snapshot named `d152120`; the recovery check below accepts it
|
||||||
or anything newer.
|
or anything newer.
|
||||||
|
**Lanes below that name an older base have not been re-based; derive
|
||||||
|
their integration surface from `git diff <their base>..main`.**
|
||||||
- On the transfer source, `origin/main` named a release mirror at
|
- On the transfer source, `origin/main` named a release mirror at
|
||||||
`d3fa632` and lagged badly. On the current destination, `origin` names
|
`d3fa632` and lagged badly. On the current destination, `origin` names
|
||||||
the canonical URL. This difference is why all recovery begins by
|
the canonical URL. This difference is why all recovery begins by
|
||||||
|
|
@ -57,7 +68,11 @@ git worktree list
|
||||||
git status --short --branch
|
git status --short --branch
|
||||||
```
|
```
|
||||||
|
|
||||||
The `git log` command must expose `d152120` or a newer intentional main.
|
The `git log` command must expose `c93f9ee` — the base named above — or a
|
||||||
|
newer intentional main. Keep this threshold and the canonical-base line in
|
||||||
|
step: a recovery check that accepts an older commit than the base it
|
||||||
|
declares canonical will pass on a tree the rest of this file does not
|
||||||
|
describe.
|
||||||
If it does not, stop and repair the remote/fetch configuration.
|
If it does not, stop and repair the remote/fetch configuration.
|
||||||
|
|
||||||
## PTY terminate diagnostic lane — IN REVIEW (PR #176)
|
## PTY terminate diagnostic lane — IN REVIEW (PR #176)
|
||||||
|
|
@ -316,154 +331,6 @@ If it does not, stop and repair the remote/fetch configuration.
|
||||||
--check` clean.
|
--check` clean.
|
||||||
- Stage 4b (the input method) is NOT in this PR and not started.
|
- Stage 4b (the input method) is NOT in this PR and not started.
|
||||||
|
|
||||||
## Dired lane — Stage 0 MERGED; Stage 1 IN REVIEW (PR #165)
|
|
||||||
|
|
||||||
- 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 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:<canonical path>*` 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.
|
|
||||||
- **Review round 1 addressed** (framing rev 7, S1-10…S1-12). Three
|
|
||||||
behavioral fixes, each bite-verified: `dired.revert`'s re-seat is
|
|
||||||
guarded on the active buffer (an ambient `move_to_line` after an await
|
|
||||||
moved an unrelated buffer's cursor — the buffer-level instance of
|
|
||||||
S1-9); `fmt_size` keeps the column width past ten digits, because
|
|
||||||
`_layout` is a contract Stage 3 is planned against; and the symlink
|
|
||||||
descent dropped its probe, since `open_directory`'s
|
|
||||||
changed-nothing-on-failure invariant *is* the probe (it was listing the
|
|
||||||
target directory twice). Plus a consecutive-`readdir`-error cap, because
|
|
||||||
**nothing cancels a dired listing** — it carries no supersede key, so
|
|
||||||
cancellation was never the backstop the tolerant loop implicitly relied
|
|
||||||
on. Naming/comment findings taken as-is.
|
|
||||||
- Durable process lesson, hit twice now: a mutation-bite helper restores
|
|
||||||
with `git checkout --`, which reverts to **HEAD** — so a fix must be
|
|
||||||
committed *before* it is bitten. Round 1's fixes were briefly wiped by
|
|
||||||
exactly that.
|
|
||||||
- **Canonical main integrated twice** — at `46a1b8f` (multi-root LSP
|
|
||||||
affinity #161) and again at `b889873` (GPU terminal input #166), both
|
|
||||||
merged rather than rebased per the #135/#137 precedent so the review
|
|
||||||
anchors stay addressable. Each conflict was a single doc hunk resolved
|
|
||||||
as the union: this lane owns COHERENCE's journey step 7 file half, #161
|
|
||||||
owns the in-flight list, #166 owns step 8's GPU-terminal addendum.
|
|
||||||
Three things worth carrying:
|
|
||||||
- **A conflicting PR silently stops running CI.** GitHub builds
|
|
||||||
`pull_request` runs against the merge ref, which does not exist while
|
|
||||||
the PR conflicts, so no run is created and nothing reports a
|
|
||||||
failure — the checks list simply stays as it was. Three pushes to
|
|
||||||
this branch produced no CI at all before the cause was found. Watch
|
|
||||||
`mergeable` on a long-lived lane, not just the check list.
|
|
||||||
- #161's own COHERENCE finding **falsified a claim in this lane's
|
|
||||||
module doc**: `pmacs.error` is never defined in production, so an
|
|
||||||
uncaught raise inside a `pmacs.async` coroutine does not reach
|
|
||||||
`*errors*` as the comment said. It reaches a bare `error()` inside
|
|
||||||
`pmacs._async.tick()`, whose result `tick_async` discards with
|
|
||||||
`let _ =` — i.e. nowhere. That makes dired's per-coroutine `pcall` +
|
|
||||||
`set_status` load-bearing rather than tidy, and the comment now says
|
|
||||||
so.
|
|
||||||
- **A lane in review against a fast-moving `main` needs its gates rerun
|
|
||||||
per integration, not per push.** Main advanced twice inside this
|
|
||||||
review round, and the second time landed while the first
|
|
||||||
integration's sweep was still running. The numbers below describe the
|
|
||||||
twice-merged tree.
|
|
||||||
- Verification on the twice-merged tree (`main` @ `b889873`):
|
|
||||||
`cargo fmt --check` clean; strict workspace Clippy clean; **1,832
|
|
||||||
default + 2,009 CRDT** library tests; dired acceptance **25 default +
|
|
||||||
25 CRDT**; m8_1 10 / m8_2 15 / m8_3 32 unchanged; multi-root 13 and
|
|
||||||
vterm Stage 3 5 (both suites main added, green under this lane's
|
|
||||||
`mod.rs` and `editor.rs` changes); M4 121; required GPU 155;
|
|
||||||
**isolated-`XDG_CONFIG_HOME` workspace sweep 3,205 passed across 93
|
|
||||||
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 — 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.
|
|
||||||
|
|
||||||
## The CRDT half of the test corpus is dark in CI — NEEDS A LANE
|
## The CRDT half of the test corpus is dark in CI — NEEDS A LANE
|
||||||
|
|
||||||
- **No branch, no framing yet.** Found while gating #166, then measured
|
- **No branch, no framing yet.** Found while gating #166, then measured
|
||||||
|
|
@ -1016,6 +883,38 @@ git worktree add --track \
|
||||||
|
|
||||||
## Closed since the last snapshot
|
## Closed since the last snapshot
|
||||||
|
|
||||||
|
- **Dired Stage 1 (the directory view) — MERGED as #165** (`main` @
|
||||||
|
`c8ec8f3`, 2026-07-25, after one review round). pmacs has a directory
|
||||||
|
surface: `C-x d` / `C-x C-j`, one read-only buffer per directory named
|
||||||
|
`*dired:<canonical path>*`, a `dired` major mode carrying
|
||||||
|
`RET`/`f`, `^`, `n`/`p`, `g`, `q`, `s`. No wire change (v20). The Rust is
|
||||||
|
two things — a per-entry-tolerant `read_dir` (Q#DR6), which had to be
|
||||||
|
Rust because `read_dir_blocking` fails a whole listing on any of five
|
||||||
|
per-entry conditions and a tolerant wrapper cannot be written in Lua at
|
||||||
|
all, and `normalize_buffer_path` going `pub` as
|
||||||
|
`pmacs.path.canonicalize` (Q#DR2's preferred end state, so no Lua mirror
|
||||||
|
exists and Stage 2 owes no mirror removal). The frozen m8_1/m8_2/m8_3
|
||||||
|
counts are unchanged, which is the additivity gate. 15 claims
|
||||||
|
bite-verified; one came back VACUOUS (acceptance 3c cannot pin descent
|
||||||
|
routing — dired holds focus in its own panel, so dedication is the only
|
||||||
|
discriminator) and is documented at the assertion rather than
|
||||||
|
relabelled. Its branch (`dired-stage1`) and worktree
|
||||||
|
(`../pmacs-dired-stage1`) are done; the abandoned `dired` branch
|
||||||
|
(`ffdd642`, `../pmacs-dired-arc`) was superseded by a fresh cut and
|
||||||
|
carries nothing unmerged. **Stage 2 (marks and operations) and Stage 3
|
||||||
|
(wdired) each still need their own framing**, and the frozen fixture
|
||||||
|
shrinks after Stage 3. Durable substrate facts and both new ops lessons
|
||||||
|
live in `docs/agent-handoff.md` §§1/5; the implementation notes are
|
||||||
|
`docs/dired-framing.md` §0, S1-1…S1-12. Two named forward items for
|
||||||
|
Stage 2: `apply_resource_op`'s rename rebind is exact-PathBuf-equality,
|
||||||
|
first-match-only, looked up with the raw path while stored paths are
|
||||||
|
normalized — so a directory rename strands every buffer under it, and
|
||||||
|
`pmacs.fs.rename` has zero production callers, so it can be fixed at
|
||||||
|
the primitive; and Q#DR5's seam is the main-thread drain
|
||||||
|
`AsyncRuntime::tick`, not `_take_result`, where rename settles as an
|
||||||
|
undifferentiated `ReplyKind::FsUnit` and so must be keyed on
|
||||||
|
`JobKind::FsRename`.
|
||||||
|
|
||||||
- **GPU terminal input (the double terminal-layout sync) — MERGED as #166**
|
- **GPU terminal input (the double terminal-layout sync) — MERGED as #166**
|
||||||
(`main` @ `b889873`, 2026-07-25, one review round, all twelve checks green
|
(`main` @ `b889873`, 2026-07-25, one review round, all twelve checks green
|
||||||
after a macOS PTY-timing rerun). The dispatcher applied **both**
|
after a macOS PTY-timing rerun). The dispatcher applied **both**
|
||||||
|
|
|
||||||
|
|
@ -179,11 +179,78 @@ commands, read `docs/active-work.md` immediately after this file.
|
||||||
against an open buffer yet fails to load one that is not open —
|
against an open buffer yet fails to load one that is not open —
|
||||||
find-file expands the tilde Lua-side. Loading through the normalized
|
find-file expands the tilde Lua-side. Loading through the normalized
|
||||||
path is a named deferral.
|
path is a named deferral.
|
||||||
- **Stage 1 (the directory view) is IN REVIEW as PR #165** — the
|
- **dired Stage 1 — the directory view — LANDED — #165**
|
||||||
builtin `dired.lua`, the per-entry-tolerant `read_dir` opt, and
|
(`docs/dired-framing.md` §0, S1-1…S1-12; merge `c8ec8f3`; one review
|
||||||
`pmacs.path.canonicalize`. Its branch state, substrate facts, and
|
round). pmacs now has a directory surface: `C-x d` / `C-x C-j` open a
|
||||||
verification live in `docs/active-work.md`; this section absorbs them
|
read-only listing, one buffer per directory named
|
||||||
when it merges.
|
`*dired:<canonical path>*`, with a `dired` major mode whose
|
||||||
|
mode-scoped keymap carries `RET`/`f`, `^`, `n`/`p`, `g`, `q`, `s`.
|
||||||
|
Protocol unchanged at **v20**. **Stage 2 (marks and operations) and
|
||||||
|
Stage 3 (wdired) each still need their own framing**; the frozen
|
||||||
|
fixture shrinks after Stage 3.
|
||||||
|
- **The Rust is confined to two things**: a per-entry-tolerant
|
||||||
|
`read_dir` (`ReadDirTolerance {Fatal, PerEntry}` →
|
||||||
|
`FsDirListing {entries, errors}`), because `read_dir_blocking` fails
|
||||||
|
a whole 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** (one error value, no partial vec); and
|
||||||
|
`editor_core::normalize_buffer_path` becoming `pub`, exposed as
|
||||||
|
`pmacs.path.canonicalize`. Only non-UTF-8 **names** stay fatal —
|
||||||
|
byte-preserving paths would be needed. The Lua result **shape** keys
|
||||||
|
on `errors.is_some()`, so the bare array the frozen M8.2 fixture
|
||||||
|
consumes with `ipairs` is untouched.
|
||||||
|
- **Exposing a core normalizer beat mirroring it in Lua.** A Lua mirror
|
||||||
|
would have been a second canonical form — the same class of bug as
|
||||||
|
the five tab-width constants (#137). Applies to any future Lua-side
|
||||||
|
path reckoning.
|
||||||
|
- **A fixed-width column must be fixed-width for every input.** The
|
||||||
|
exported `pmacs.dired._layout` (MARK 0, KIND 2, PERMS 3–12, SIZE 13,
|
||||||
|
MTIME 24, NAME 41) is the contract Stage 3 reads offsets from, and
|
||||||
|
`%10d` overflows at ≥10 GB, silently shifting every column right of
|
||||||
|
it. Sizes now fall back to a width-clamped magnitude (K/M/G/T/P/E).
|
||||||
|
- **An ambient action must be gated on the buffer it assumes.** A
|
||||||
|
revert's cursor re-seat settles a tick or more later, by which time
|
||||||
|
the user may have switched buffers; the paint names its buffer and is
|
||||||
|
safe, but seating is ambient. This is the buffer-level instance of
|
||||||
|
the rule below that interactive origin does not survive an await.
|
||||||
|
- **A failure IS an answer — don't probe first.** Kinds are lstat-based
|
||||||
|
in both `read_dir` and `stat`, so nothing in an entry says whether a
|
||||||
|
symlink points at a directory. `RET` tries to list it and treats the
|
||||||
|
failure as the answer; an explicit probe was a second full
|
||||||
|
`read_dir`, so a descent listed twice.
|
||||||
|
- **Unbounded per-entry error collection needs a cap when nothing
|
||||||
|
cancels the work.** A dired listing carries no supersede key, so
|
||||||
|
cancellation was never the backstop the tolerant loop implicitly
|
||||||
|
relied on (`READDIR_MAX_CONSECUTIVE_ENTRY_ERRORS = 1024`).
|
||||||
|
- **This is the first builtin with mode-scoped keys** (#129's first
|
||||||
|
non-detection consumer), which broke the pre-existing
|
||||||
|
`describe_key_identifies_every_default_binding`: it asserted every
|
||||||
|
binding 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`), plus a floor
|
||||||
|
assertion that at least one mode-scoped binding exists.
|
||||||
|
- **A dedicated panel does not carry its dedication across a descent**
|
||||||
|
— the framing expected it to. `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.
|
||||||
|
- Smaller facts worth knowing before touching this code: a path-backed
|
||||||
|
buffer's **name is its full path**, not its basename, which matters
|
||||||
|
for any name assertion; `pmacs.buffer.kill` (not `remove`) redirects
|
||||||
|
windows off a doomed buffer first, so `dired.kill-when-opening` kills
|
||||||
|
**after** the replacement is displayed; ownership is checked against
|
||||||
|
the handle table only, never the buffer name; and `C-x d` takes **no**
|
||||||
|
completion source on purpose (with one, `RET` on an empty field opens
|
||||||
|
whatever sorts first, and RET-where-you-are is the gesture the binding
|
||||||
|
exists for — the field is prefilled instead).
|
||||||
|
- Verification at merge: 1,832 default + 2,009 CRDT library tests;
|
||||||
|
dired acceptance 25 + 25 CRDT; the frozen m8_1 10 / m8_2 15 / m8_3 32
|
||||||
|
unchanged, which is the additivity gate for the `read_dir` change; M4
|
||||||
|
121; required GPU 155; isolated-`XDG_CONFIG_HOME` workspace sweep
|
||||||
|
3,205 across 93 suites. 15 claims bite-verified.
|
||||||
- Protocol **v20** (`SUPPORTED=[6..=20]`; v16 = `ThemeFacts`, v17 =
|
- Protocol **v20** (`SUPPORTED=[6..=20]`; v16 = `ThemeFacts`, v17 =
|
||||||
`FontFacts`, v18 = `StatuslineSegments`, v19 = terminal frames/events, v20 =
|
`FontFacts`, v18 = `StatuslineSegments`, v19 = terminal frames/events, v20 =
|
||||||
the GPU initial-target semantic bootstrap family).
|
the GPU initial-target semantic bootstrap family).
|
||||||
|
|
@ -1014,6 +1081,24 @@ final variant — its own round-trip cannot detect a discriminant shift.
|
||||||
trap-guarded one-file swap over read-only `git show`, with an
|
trap-guarded one-file swap over read-only `git show`, with an
|
||||||
inverted verdict (exit 0 iff the tests FAIL against the old
|
inverted verdict (exit 0 iff the tests FAIL against the old
|
||||||
version), making bite-verification machine-checkable.
|
version), making bite-verification machine-checkable.
|
||||||
|
- **A fix must be COMMITTED before it is bitten.** `scripts/bite`
|
||||||
|
restores by `git checkout --`, which reverts the file to **HEAD**, not
|
||||||
|
to the state it found — so any uncommitted work in a bitten file is
|
||||||
|
destroyed. A whole review round's fixes were wiped this way during
|
||||||
|
#165. Corollary for a NEW file: the swap-over-`git show` mode does not
|
||||||
|
apply at all, so its claims must be bitten by hand-editing, which makes
|
||||||
|
the commit-first rule load-bearing rather than hygienic.
|
||||||
|
- **A CONFLICTING PR silently runs no CI at all.** GitHub builds
|
||||||
|
`pull_request` workflow runs against the PR's **merge ref**, which it
|
||||||
|
does not create while the branch conflicts with its base. So pushes
|
||||||
|
land, the branch updates, no run is ever queued, and **nothing reports
|
||||||
|
the absence** — the checks list simply keeps showing the last
|
||||||
|
successful run, which reads as current. Three pushes to #165 produced
|
||||||
|
zero CI before the cause was found, and `gh pr checks` returns nothing
|
||||||
|
usable here. On any lane that lives through a moving `main`, check
|
||||||
|
`gh pr view <N> --json mergeable,mergeStateStatus,headRefOid` and
|
||||||
|
confirm a run exists **for the current head sha**, not merely that a
|
||||||
|
recent run was green.
|
||||||
- **Stacked PRs**: retarget the child to main BEFORE merging the
|
- **Stacked PRs**: retarget the child to main BEFORE merging the
|
||||||
parent — GitHub auto-closes a PR whose base branch is deleted and
|
parent — GitHub auto-closes a PR whose base branch is deleted and
|
||||||
cannot reopen it (#104 → re-opened as #105).
|
cannot reopen it (#104 → re-opened as #105).
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
# Dired — framing
|
# Dired — framing
|
||||||
|
|
||||||
**Revision 7 — 2026-07-25. Status: APPROVED; Stage 0 MERGED as #162;
|
**Revision 7 — 2026-07-25. Status: APPROVED; Stage 0 MERGED as #162;
|
||||||
Stage 1 IN REVIEW as PR #165, review round 1 addressed.**
|
Stage 1 MERGED as #165 (`main` @ `c8ec8f3`, one review round). Stage 2
|
||||||
|
(marks and operations) and Stage 3 (wdired) each still need their own
|
||||||
|
framing before implementation; the frozen fixture shrinks after Stage 3.**
|
||||||
Rev 1 passed a ground-truth review; rev 2 fixed round 1's seven findings;
|
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
|
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
|
implementation falsified in the approved text (§0); rev 5 adds the
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue