diff --git a/COHERENCE.md b/COHERENCE.md index 3bfcff4..7b58b47 100644 --- a/COHERENCE.md +++ b/COHERENCE.md @@ -107,7 +107,7 @@ remain open to them. | 11 | Config layering + provenance | **Partial (foundation only)** | Typed registry is right; 5 settings live in it; no value provenance | | 12 | Profiles | **Missing** | One hardcoded default keymap; not a named concept | | 13 | Package lifecycle UX | **Resolution without lifecycle** | Mature resolver/lockfile; init-only install; no uninstall/disable/search | -| 14 | Workbench primitives | **Partial (best trajectory)** | Listview is a real primitive but only **4** call sites, all LSP panels (`*lsp*` added post-audit by #204); buffer-list and search re-implement it; **the bottom panel is COMPLETE — both frontends, and Stage 3 flipped the adopter default so omission means the panel**. **Tree is still ✗ and is now the arc's successor** | +| 14 | Workbench primitives | **Partial (best trajectory)** | Listview is a real primitive but only **4** call sites, all LSP panels (`*lsp*` added post-audit by #204); buffer-list and search re-implement it; **the bottom panel is COMPLETE — both frontends, and Stage 3 flipped the adopter default so omission means the panel**. **Tree is implemented (◐) with the LSP outline as its one adopter; the remaining consumers, including dired's `i`, have not adopted** | | 15 | Contextual affordances | **Weak** | Right-click menu only; code actions apply first-blindly; no git integration at all | | 16 | Semantic frontend | **Strong** | v6..=v21 schema support; production attach remains v20 during the dark panel slice; degradation practiced | | 17 | Distribution | **Partial** | **v1.1.0 ships prebuilt Linux/macOS binaries on tag** (#211) with checksums and a stated glibc floor. No channels, in-place update, rollback, signing, or package-manager distribution | @@ -1367,15 +1367,27 @@ Primitive-by-primitive against the list above: (§9). - **Help view** △ — exists twice (§5); needs unification, not invention. -- **Tree** ✗ — none. The named future consumers (project files, symbol - 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. Dired Stage 1 (merged #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. +- **Tree** ◐ — **implemented, one consumer.** `listview` carries + optional `depth` and `id` on rows, primitive-owned collapse state, and + selection re-seated by id rather than by line; `TAB` toggles. Absent + `depth`/`id`, a row behaves exactly as before, which is what leaves + the flat consumers untouched (pinned by byte-identity coverage). + **The LSP outline is the only adopter**: it previously flattened a + genuine `DocumentSymbol` tree into indented strings, and now supplies + structure while keeping its rendered text. + + The organising fact, worth carrying: **folding is local projection + state, not a refresh protocol.** Collapse only hides rows and never + changes a surviving row's depth, so the primitive re-renders from its + own array without calling the consumer — which is why the outline + works at all, having no `on_refresh`. + + **Still one consumer, hence ◐ not ✓.** The named future consumers + (project files, package dependency graph, worker trees, git status) + have not adopted, and dired's recursive `i` insert-subdirectory — the + second real constraint source — remains the deferral in + `docs/dired-framing.md` §13. Dired Stage 1 (merged #165) landed + **without** inventing its own, which is what kept this possible. - **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 diff --git a/docs/active-work.md b/docs/active-work.md index f3346b2..575490e 100644 --- a/docs/active-work.md +++ b/docs/active-work.md @@ -161,6 +161,76 @@ form. All four steps ran clean. **The two-argument form still does not work** for a remote-only branch (`fatal: invalid reference`), which is why every lane below spells out the `-b` form. +## Tree primitive (P5) — IMPLEMENTED and GATED, PR HELD + +**Held deliberately, not stalled.** The work is complete and green; the +PR is not open pending review of the documentation this lane records. + +- **Branch `tree-primitive-framing`**, base `githubsucks/main` @ + `12f2970`. **Unpushed** while held. Framing + `docs/tree-primitive-framing.md` **revision 5** — approved after four + review rounds, with Q#TR1–TR4 decided. +- **Commits:** `61b1062` framing, `cf4ac1c` rev 2, `932b3ab` rev 3, + `5186bfd` rev 4 (carrying the `COHERENCE.md` §14 call-site + correction), `49a42ec` the primitive, `8f64c3b` byte-identity coverage + plus the verification record. + +### What it ships + +`listview` gains **optional** `depth` and `id` on rows; absent, a row +behaves exactly as before, which is what leaves the flat consumers +untouched. Collapse state is **primitive-owned**, keyed by +consumer-supplied id. Selection is re-seated **by id, not by line**. +`TAB` toggles; a leaf reports rather than silently doing nothing. + +**The observation that made it cheap:** collapse only ever *hides* rows +and never changes a surviving row's depth, and consumers emit parents +before children, so descendants are a **contiguous run**. Folding is +therefore **local projection state, not a refresh protocol** — the +primitive re-renders from its own array without calling the consumer, +which is why the anchor consumer works at all: **the outline has no +`on_refresh`**. + +The LSP outline adopts, supplying `depth` and `id = line:col`; its +`text` stays consumer-rendered per Q#TR4. + +### Verification + +| gate | result | +|---|---| +| luajit sweep | **3453 / 0** (= `main` 3450 + 3 listview tests) | +| crdt sweep, isolated ×2 | **3722 / 0** (= `main` 3718 + 4 tests) | +| `listview_acceptance` | 21 / 21 | +| `m4_acceptance` | 150 / 150 (basedpyright skipped) | +| `--lib` | 1896 / 0 | +| fmt · diff-check · clippy ±crdt | pass | + +Both behavioural claims are **bite-verified**: disabling the ancestor +filter fails the fold test; an unconditional gutter fails the +byte-identity test. + +**One unclassified occurrence** — the first crdt sweep reported 7 +failures whose signatures were destroyed before being read. It is +recorded in the framing's §6a, **not** as a row in +`docs/ci-red-signatures.md`, because it has no normalized signature to +match. Two non-causal hypotheses are recorded there; neither is testable +now. + +### Recovery, once pushed + +```sh +git fetch githubsucks +git worktree add ../pmacs-tree \ + -b tree-primitive-framing \ + githubsucks/tree-primitive-framing +``` + +### Not in scope + +dired's `i` insert-subdirectory (the second consumer, its own stage); +the other four §14 consumers; DAP's variables view; giving the outline a +refresh, which is LSP request-lifecycle work. + ## Leaked daemons from `gpu_invocation_acceptance` — NEEDS A LANE **Found 2026-08-05 while cleaning up after the tree-primitive work. No @@ -187,7 +257,8 @@ so **nothing in the existing ledger covers them**. **Why it matters beyond tidiness.** Dozens of resident daemons were present during every local sweep run this week, including the one that -produced the unclassified failure recorded in the tree lane below. That +produced the unclassified failure recorded in the **tree-primitive lane +above** (and, in full, in that lane's framing §6a). That makes them a **rival explanation** to the shared-target-dir mechanism for that occurrence, and neither can be tested against it now — the signatures were not captured. A leak that quietly changes the diff --git a/docs/agent-handoff.md b/docs/agent-handoff.md index 17938ca..a093c2c 100644 --- a/docs/agent-handoff.md +++ b/docs/agent-handoff.md @@ -122,6 +122,36 @@ commands, read `docs/active-work.md` immediately after this file. - **A capability fallback must strip the QUIT ACTION too**, not just the side parameters — a quit action stranded on a document window makes a later `q` try to restore a presentation that never happened. +- **The tree primitive ships — `listview` gained depth, collapse and + identity** (P5, §14's last missing workbench primitive; implemented, + PR held). Rows carry **optional** `depth` and `id`; absent, a row + behaves exactly as before, which is what leaves the flat consumers + untouched. The LSP outline is the one adopter. Durable facts: + - **Folding is local projection state, not a refresh protocol.** + Collapse only *hides* rows and never changes a surviving row's + depth, and consumers emit parents before children, so descendants + are a **contiguous run**. The primitive therefore re-renders from + its own array **without calling the consumer** — which is the only + reason the anchor consumer works, because **the outline has no + `on_refresh` at all**. A design requiring the consumer to re-supply + rows on every fold would have fitted no existing consumer. + - **Identity is consumer-supplied and compared by equality; the + primitive never derives one.** `item` is opaque by design. The + outline uses `line:col`, because the `::` parent chain collides on + overloads and same-named siblings — exactly where a stale expansion + would reattach to the wrong node. **Selection is re-seated by id, + not by line**, since a fold inserts or removes rows above the + cursor. + - **`has_children` must read the FULL row array, not the rendered + subset.** A collapsed node's children are absent from the rendered + map by construction, so asking the view would answer "no" for every + collapsed node and make expanding impossible — a self-sealing bug + that looks like fold working and unfold silently not. + - **A bite that passes validates the pair, not the test.** The first + byte-identity injection used `row.depth or 0`; flat rows have no + depth, so it changed nothing and the test "passed" against a + regression the flat path is immune to. Ask which defect you + injected before believing a green bite. - **pmacs is installable without cloning — Distribution Stage 1, #211, released as v1.1.0.** A `v*` tag builds `pmacs` and `pmacs-gpu` on pinned `ubuntu-22.04` / `macos-15` and publishes a GitHub Release with @@ -226,7 +256,7 @@ anchor, so every item is startable. | 2 | Workspace + location | Missing; model gap | The long-lead arc. Start before a fifth subsystem grows its own root convention — four have already diverged (§7) | | 3 | Extension ownership | Missing; prerequisite-shaped | **`pmacs.hook.remove` does not exist.** That one bug-sized gap blocks §13's disable/uninstall, §10's trust classes, and package-scoped cancellation | | 4 | **Discovery** | **Stage 1 MERGED (#207)** | Stage 2 candidates, in rough dependency order: richer M-x rows (**protocol change** — `MinibufferPrompt.candidates` is `Vec`; `CompletionPopupRow` already proves the pattern), `Command` gaining title/category/aliases/flags/arg-schema (~147 definition sites), predicate evaluation, help-layer unification, and the help-prefix decision | -| 5 | Workbench convergence | Partial; **Arc 7 COMPLETE** (Stage 3 merged, #213) | The bottom panel is finished on both frontends and the adopter default is flipped. **The tree primitive is now the arc's successor** — `COHERENCE.md` §14 grades Tree ✗, and DAP's variables view is its next would-be inventor. Build it *before* dired's `i` and the worker tree invent two | +| 5 | Workbench convergence | Partial; **Arc 7 COMPLETE** (#213) and **the tree primitive is implemented** (PR held) | The bottom panel is finished on both frontends and the adopter default is flipped. The tree primitive has landed on a held PR: §14's Tree moves ✗ → ◐ with the LSP outline as its one adopter. **Next: adoption** — dired's `i`, then DAP's variables view, which is why it was built first | | 6 | Config productization | Foundation only | Value provenance, then layering, then adoption migration (**table-valued settings are the hard prerequisite** — `ConfigValue` is four scalars) | | 7 | Package lifecycle | Not started | Correctly sequenced after P3 | | 8 | **Distribution** | **Stage 1 SHIPPED (v1.1.0, #211)** | Binaries on tag, checksums, machine-checked glibc floor. **Journey step 1 now works and the "invisible until this exists" blocker is lifted.** Next is a *decision* about channels / update / signing, not a queued plan | diff --git a/docs/tree-primitive-framing.md b/docs/tree-primitive-framing.md index d243a05..8343166 100644 --- a/docs/tree-primitive-framing.md +++ b/docs/tree-primitive-framing.md @@ -1,6 +1,8 @@ # Framing — the tree primitive -**Revision 5.** Status: **APPROVED; Q#TR1–TR4 decided.** Scouted against +**Revision 5.** Status: **IMPLEMENTED and GATED; PR HELD for review.** +Q#TR1–TR4 decided at approval. Both sweeps green and both behavioural +claims bite-verified — see §6a. Scouted against `githubsucks/main` @ `12f2970`. Carries a correction to `COHERENCE.md` §14 (revision 4, below).