test(listview): byte-identity for the flat consumers, and two findings

ACCEPTANCE 5, and it needed a real test rather than a weakened claim.
`listview_acceptance` says in its own header that the references panel
"needs a live LSP and is validated manually / via the m4 harness", so it
does not exercise `*references*` at all; the m4 hover test asserts
content PRESENCE, not exact output. Neither would notice a flat consumer
silently gaining an indent column — the regression a tree extension can
introduce. So the coverage is written against the real entry points
through the fake language server.

`*references*` is pinned EXACTLY: the row is the location string and
nothing else. `*lsp*` formats its own two-space indentation, so
"starts with a space" is not a violation there; what must hold is that
the primitive reproduces the consumer's text verbatim, matched as a
WHOLE LINE — a substring would still be found inside a further-indented
copy of itself. Volatile parts (pid, elapsed) are deliberately excluded,
the same normalization reasoning the CI registry uses.

THE FIRST BITE PASSED, AND THAT WAS THE FINDING. Injecting
`string.rep("  ", row.depth or 0)` did not fail the test — flat rows
carry no depth, so it added nothing. I had simulated a regression the
flat path is immune to and would have recorded the test as verified.
The regression this criterion actually guards is an UNCONDITIONAL
column, a fold gutter on every row; with that injected the test fails on
"the flat references row renders verbatim". A bite that passes validates
the pair, not the test — and injecting the wrong defect teaches nothing
while feeling like assurance.

A VERIFICATION RECORD, including one unclassified occurrence. The first
local crdt sweep of this branch reported 7 failures and its SIGNATURES
WERE DESTROYED before being read, piped through an aggregation that
emitted only totals. That is the failure the CI registry exists to
prevent, committed one lane after writing it, and it is why the cause
cannot now be established rather than merely being unknown.

It is recorded in this lane's own framing and deliberately NOT as a
registry row: that registry keys on a normalized signature, and an
occurrence with none would be granted a recognisability it cannot
support — the same reasoning that made the unevidenced incumbents audit
notes rather than rows.

Four re-runs are tabulated with what each supports. Two were not
isolated, including one where my own guard printed "aborting" and did
not abort. TWO GENUINELY ISOLATED RUNS ARE BOTH CLEAN, which supports
repeatability under isolation and establishes nothing about the cause.

Two mechanisms are recorded as NON-CAUSAL hypotheses, because both were
present and neither can now be tested: a shared CARGO_TARGET_DIR (whose
reciprocal case another lane observed independently, with `pgrep`
evidence and failing text that named its own cause), and ~40 resident
leaked daemons. Having two plausible mechanisms and no way to
discriminate IS the result; naming either would repeat the reasoning
this project has rejected — concluding something about an occurrence
from something that was not about that occurrence.

Both mechanisms are recorded as standing hazards in the handoff, and the
daemon leak gets its own candidate lane: 42 orphans, oldest four days,
reparented to systemd with deleted sockets, from
`gpu_invocation_acceptance`'s one-command tests, leaking 3-4 per sweep
as measured rather than estimated. It predates this work and belongs to
the reap-ledger family — a process outliving its supervisor with nothing
watching it — but the existing ledger arms only for `spec.group` and so
does not cover it.

Verified: fmt, diff-check, luajit sweep 3453/0 and crdt 3722/0, each
exactly +4 on its baseline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Levi Neuwirth 2026-08-05 16:31:31 +02:00
parent 49a42ec9dc
commit 8f64c3b2a1
No known key found for this signature in database
4 changed files with 205 additions and 0 deletions

View File

@ -161,6 +161,44 @@ form. All four steps ran clean. **The two-argument form still does not
work** for a remote-only branch (`fatal: invalid reference`), which is work** for a remote-only branch (`fatal: invalid reference`), which is
why every lane below spells out the `-b` form. why every lane below spells out the `-b` form.
## Leaked daemons from `gpu_invocation_acceptance` — NEEDS A LANE
**Found 2026-08-05 while cleaning up after the tree-primitive work. No
branch, no framing.**
- **42 orphaned `pmacs --daemon` processes** were resident on the
development machine, **the oldest 3 days 23 hours old**. All had been
**reparented to systemd** (`ppid=1`) and all had **deleted sockets**,
so nothing could ever reach or reap them.
- **Source: `tests/gpu_invocation_acceptance.rs`** — the one-command
tests, whose daemons carry `--socket <tempdir>/one-command.sock`. The
tempdir is cleaned up; the daemon is not.
- **Rate measured, not estimated: 3 per sweep.** A single isolated
`--features luajit,crdt` sweep leaked exactly three. 42 is what
several days of sweeps accumulate to.
- **This predates the tree work** — the oldest is four days old — so it
is a standing leak, not something a current lane introduced.
**Why it belongs to the reap-ledger family.** This is precisely the
shape that lane exists for: a process that outlives its supervisor with
nothing left watching it. The ledger arms only for `spec.group`, and
these are daemons spawned by a test harness rather than by compile mode,
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
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
environment of every subsequent test run is a measurement problem as
well as a resource one.
**First questions for whoever takes it:** does the test harness fail to
reap, or does the daemon fail to exit when its socket disappears? Those
have different fixes, and the second would be a product defect rather
than a test one.
## macOS CI signal integrity — STAGE 1 IN REVIEW, PR #215 ## macOS CI signal integrity — STAGE 1 IN REVIEW, PR #215
**This file requires a lane for every open PR** (see the #171/#174 note **This file requires a lane for every open PR** (see the #171/#174 note

View File

@ -315,6 +315,23 @@ someone forgot.
`gpu_invocation_acceptance` tests fail on a missing `pmacs-gpu` `gpu_invocation_acceptance` tests fail on a missing `pmacs-gpu`
binary. `cargo build --workspace --no-default-features --features binary. `cargo build --workspace --no-default-features --features
luajit,crdt` is the invocation that produces both binaries. luajit,crdt` is the invocation that produces both binaries.
- **A shared `CARGO_TARGET_DIR` makes concurrent sweeps unattributable.**
Two worktrees both defaulting to it means one lane's
`cargo test --workspace` **overwrites `target/debug/pmacs` mid-sweep**
in the other, and every real-daemon suite then spawns the wrong
binary. Observed twice on 2026-08-05, from both sides: the failing
text named its own cause ("start the daemon built with the `crdt`
feature"), and re-running the same suites with a dedicated target dir
gave 41/41. **Give a second worktree its own target dir**, and treat
any red from a sweep that overlapped another build as unattributable
rather than as evidence.
- **A local sweep leaks daemons, and they accumulate across days.**
`gpu_invocation_acceptance`'s one-command tests leave ~3 orphaned
`pmacs --daemon` processes per sweep, reparented to systemd with
deleted sockets; 42 were resident at one point, the oldest four days
old. They are a rival explanation for any load-sensitive local
failure, so **check `pgrep -f "pmacs --daemon"` before trusting a
local red**. Lane recorded in `docs/active-work.md`.
- **A local sweep is blind to whichever feature configuration it does - **A local sweep is blind to whichever feature configuration it does
not build.** Stage 3's census and every verification sweep ran not build.** Stage 3's census and every verification sweep ran
`--features luajit` WITHOUT `crdt`, so no crdt-gated suite was `--features luajit` WITHOUT `crdt`, so no crdt-gated suite was

View File

@ -515,6 +515,63 @@ reports as one suite.
--- ---
## 6a. Verification record, including one unclassified occurrence
**The luajit sweep is 3453 / 0** and the count reconciles exactly:
`main` is 3450 (Stage 3's 3449 sweep predated its own capability-fallback
pin) plus this lane's three listview tests and one m4 test.
**The crdt sweep is 3722 / 0**, likewise +4 on `main`'s 3718.
### An UNCLASSIFIED, UNCAPTURED local occurrence
The **first** local crdt sweep of this branch reported **7 failures**.
**It is recorded here as unclassified and it is deliberately NOT a row
in `docs/ci-red-signatures.md`** — that registry keys on a normalized
signature, and this occurrence has none to match, so a row would confer
recognisability it cannot support.
**The signatures were destroyed before they were read.** The sweep was
piped through an aggregation that emitted only totals. That is the exact
failure the registry exists to prevent, committed one lane after writing
it — and it is why the cause cannot now be established rather than
merely being unknown.
**Re-runs, with what each does and does not support:**
| run | isolated? | result |
|---|---|---|
| first | no — concurrent with another lane's build | **7 failed, signatures lost** |
| second | no | 3722 / 0 |
| A | **no** — the isolation guard printed "aborting" and did not abort | 3722 / 0 |
| B | **yes** — verified idle | 3722 / 0 |
| C | **yes** — verified idle | 3722 / 0 |
Two genuinely isolated runs, both clean. **That supports repeatability
under isolation. It does not establish what caused the original.**
### Two NON-CAUSAL hypotheses, neither testable now
Both are mechanisms known to have been present. Neither is offered as an
explanation, because the occurrence's signatures no longer exist to test
either against:
1. **Shared `CARGO_TARGET_DIR`.** Another lane's worktree shared
`/home/jeans/build/cargo-target`, so its `cargo test --workspace`
overwrote `target/debug/pmacs` mid-sweep. That lane observed the
reciprocal case independently, caught the concurrent build with
`pgrep`, and its failing text named its own cause ("start the daemon
built with the `crdt` feature").
2. **Resident leaked daemons.** ~40 orphaned `pmacs --daemon` processes
were present, some four days old (see the lane in
`docs/active-work.md`). Isolated sweeps leak 34 each, so the
population was growing throughout.
**Having two plausible mechanisms and no way to discriminate is the
result.** Reporting either as *the* cause would be the reasoning this
project has rejected repeatedly: concluding something about an
occurrence from something that was not about that occurrence.
## 7. Branch plan ## 7. Branch plan
Q#TR1 is decided, so the listview-extension shape applies: Q#TR1 is decided, so the listview-extension shape applies:

View File

@ -8025,6 +8025,99 @@ fn open_against_fake(path: &std::path::Path) -> pmacs::editor::EditorState {
/// hierarchical documentSymbol response ("Outer" class > "inner" /// hierarchical documentSymbol response ("Outer" class > "inner"
/// method): open, depth-indented rows, RET jump-ring visit to the /// method): open, depth-indented rows, RET jump-ring visit to the
/// symbol's selectionRange, M-, back to the outline row, q restore. /// symbol's selectionRange, M-, back to the outline row, q restore.
/// Tree primitive, acceptance 5 — the FLAT listview consumers render
/// **byte-identically** after the depth/collapse extension.
///
/// This exists because the weaker claim was not true. `listview_
/// acceptance` says in its own header that the references panel "needs
/// a live LSP and is validated manually / via the m4 harness", so it
/// does not exercise `*references*` at all; and the hover test asserts
/// content *presence*, not exact output. Neither would notice a flat
/// consumer silently gaining an indent column — which is precisely the
/// regression a tree extension can introduce.
///
/// So the assertion is on the **exact rendered bytes**, through the
/// real entry points, against the fake language server.
#[test]
fn flat_listview_consumers_render_byte_identically_after_the_tree_extension() {
let dir = tempfile::tempdir().expect("tempdir");
let a_path = dir.path().join("r.rs");
std::fs::write(&a_path, b"fn main() {}\n").expect("write r");
let mut state = open_against_fake(&a_path);
let body = |state: &pmacs::editor::EditorState| -> String {
state
.lua_host
.lua()
.load("local b = pmacs.window.buffer() return b:slice(0, b:len())")
.eval()
.expect("panel text")
};
// --- *references* (on_visit, no depth) ---
state
.lua_host
.lua()
.load("pmacs.lsp.find_references()")
.exec()
.expect("invoke find_references");
assert!(
pump_lua_flag(
&mut state,
"pmacs.describe.buffer(pmacs.window.buffer()).name == '*references*'",
5,
),
"the references panel opened"
);
let refs = body(&state);
let (header, rows) = refs.split_once('\n').expect("header then rows");
assert_eq!(
header, "1 reference RET visit n/p move q quit",
"the header is unchanged — no fold affordance is advertised on a \
flat panel"
);
// EXACT: the row is the location string and nothing else. An added
// indent column, tree gutter or fold marker would all fail here.
assert_eq!(
rows,
format!("{}:12:3", a_path.display()),
"the flat references row renders verbatim"
);
// --- *lsp* (on_refresh, no depth) ---
state
.lua_host
.lua()
.load("pmacs.command.invoke('lsp.status')")
.exec()
.expect("invoke lsp.status");
let status_body = body(&state);
let (status_header, status_rows) = status_body.split_once('\n').expect("header then rows");
assert_eq!(
status_header, "LSP status g refresh q quit",
"the one panel WITH refresh keeps its exact header"
);
// `*lsp*` formats its OWN indentation — two spaces on detail lines —
// so "starts with a space" is not a violation here. What must hold
// is that the primitive reproduces the consumer's text EXACTLY: a
// prefix added by render would shift this line and break the match.
//
// Matched as a whole line rather than a substring, because a
// substring would still be found inside a further-indented version
// of itself. Volatile parts (pid, elapsed) are deliberately not
// included.
assert!(
status_rows
.lines()
.any(|l| l == " capabilities: sync, hover, completion, definition, diagnostics"),
"the consumer's own two-space indentation survives verbatim; got:\n{status_rows}"
);
assert!(
status_rows.lines().any(|l| l == "Servers:"),
"an unindented row stays unindented; got:\n{status_rows}"
);
}
#[test] #[test]
#[allow( #[allow(
clippy::too_many_lines, clippy::too_many_lines,