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:
parent
49a42ec9dc
commit
8f64c3b2a1
|
|
@ -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
|
||||
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
|
||||
|
||||
**This file requires a lane for every open PR** (see the #171/#174 note
|
||||
|
|
|
|||
|
|
@ -315,6 +315,23 @@ someone forgot.
|
|||
`gpu_invocation_acceptance` tests fail on a missing `pmacs-gpu`
|
||||
binary. `cargo build --workspace --no-default-features --features
|
||||
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
|
||||
not build.** Stage 3's census and every verification sweep ran
|
||||
`--features luajit` WITHOUT `crdt`, so no crdt-gated suite was
|
||||
|
|
|
|||
|
|
@ -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 3–4 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
|
||||
|
||||
Q#TR1 is decided, so the listview-extension shape applies:
|
||||
|
|
|
|||
|
|
@ -8025,6 +8025,99 @@ fn open_against_fake(path: &std::path::Path) -> pmacs::editor::EditorState {
|
|||
/// hierarchical documentSymbol response ("Outer" class > "inner"
|
||||
/// method): open, depth-indented rows, RET jump-ring visit to the
|
||||
/// 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]
|
||||
#[allow(
|
||||
clippy::too_many_lines,
|
||||
|
|
|
|||
Loading…
Reference in New Issue