208 lines
9.5 KiB
Markdown
208 lines
9.5 KiB
Markdown
# CI red signatures — the triage registry
|
|
|
|
**This file is the single authority for judging a red CI run.** It is an
|
|
occurrence ledger, not a flake list: a row records what was seen, what is
|
|
known about why, and what would retire it. **A row is not a claim that
|
|
the failure is harmless.**
|
|
|
|
Deliberately not named "flakes". One of its rows is a possible product
|
|
defect, and a filename that called it a flake would confer immunity the
|
|
evidence does not support.
|
|
|
|
Read this before attributing any red run to the environment. Landed
|
|
framing documents keep their own historical evidence and reasoning —
|
|
that is not duplication, and it is not superseded by this file. What
|
|
lives here is **live triage policy**.
|
|
|
|
---
|
|
|
|
## How a row matches
|
|
|
|
**A test-name match is never sufficient.** A red run matches a row only
|
|
when *all three* hold:
|
|
|
|
1. the **exact test selector** matches;
|
|
2. the **job / flavor** matches;
|
|
3. **every required fragment** is present in the failure output.
|
|
|
|
Where a fragment lists alternatives (`ESRCH` / `No such process`), any
|
|
one satisfies that requirement — those are the same condition rendered
|
|
differently by platform or libc.
|
|
|
|
Fragments are **normalized**, never pasted verbatim. PIDs, elapsed
|
|
times, thread ids and rendered OS-error suffixes vary between runs; a
|
|
verbatim key would match nothing. The evidence link preserves the exact
|
|
occurrence.
|
|
|
|
**A failure in a listed test that does not carry that row's fragments is
|
|
a NEW incident**, judged on its own. The process test below is why this
|
|
rule exists: it produced two signatures with different mechanisms and
|
|
different causal status, and only one of them is a test bug.
|
|
|
|
---
|
|
|
|
## The rerun rule
|
|
|
|
This replaces "rerun before concluding", which conflated three different
|
|
outcomes.
|
|
|
|
- **A green rerun after a red establishes INTERMITTENCE ONLY.** It does
|
|
not establish environmental cause, harmlessness, or retirement.
|
|
- **The same signature on the rerun is a SECOND OCCURRENCE.** It remains
|
|
blocking pending investigation or a merge-base control.
|
|
- **A different signature is a NEW INCIDENT**, judged independently.
|
|
|
|
A merge-base control — running the same command on the merge base — is
|
|
what distinguishes "this branch caused it" from "this tree has it". It
|
|
is cheaper than argument and is the correct response to a second
|
|
occurrence.
|
|
|
|
---
|
|
|
|
## What retires a row
|
|
|
|
**Retirement is causal, never a count of green runs.** A row is retired
|
|
by removing or explaining its mechanism:
|
|
|
|
| causal status | retirement condition |
|
|
|---|---|
|
|
| **test race** | hardening that removes the named mechanism, plus a discriminating witness for the stronger predicate |
|
|
| **measurement design** | the owning lane replaces or justifies the measurement and pins the resulting claim |
|
|
| **unresolved** | diagnosis and an explicit disposition |
|
|
| **mechanism named, no occurrence** | a linked occurrence promotes it to one of the above; sustained absence is not retirement, because nothing was ever measured |
|
|
|
|
Main-branch greens are **occurrence evidence** and accumulate toward a
|
|
rate. They retire nothing by themselves. Retired rows stay in this file
|
|
with their disposition, so a recurrence is recognisable.
|
|
|
|
---
|
|
|
|
## Live rows
|
|
|
|
### R1 — supersede cancellation budget
|
|
|
|
| field | value |
|
|
|---|---|
|
|
| **selector** | `--lib async_runtime::tests::supersede_cancels_in_flight_job_within_50ms` |
|
|
| **job / flavor** | macOS / luajit |
|
|
| **required fragments** | `supersede did not cancel within 50ms` |
|
|
| **causal status** | **measurement design** |
|
|
| **evidence** | [#213 run 30826884642](https://github.com/levineuwirth/pmacs/actions/runs/30826884642) |
|
|
| **retirement** | the async-runtime lane replaces or justifies the measurement (Q#MCI3) |
|
|
|
|
The test's premise is `thread::sleep(15ms)`, asserted by comment to mean
|
|
"the worker picked the job up"; under load it may not have, in which case
|
|
the test measures the *queued* path while claiming the running one. And
|
|
its 50ms clock starts before the second dispatch and is consumed by the
|
|
test's own `tick()` + `sleep(1ms)` pump, so the interval is dominated by
|
|
when *the test* was scheduled. **Widening the budget would make it pass
|
|
and measure nothing more.**
|
|
|
|
### R2 — USR1 delivered before the trap is installed
|
|
|
|
| field | value |
|
|
|---|---|
|
|
| **selector** | `--lib process::tests::a_successful_signal_disposition_depends_on_whether_it_is_fatal` |
|
|
| **job / flavor** | macOS / lua54 |
|
|
| **required fragments** | `leader=exited(` + `SIGUSR1` |
|
|
| **causal status** | **test race** |
|
|
| **evidence** | [#213 run 30927084982 attempt 1](https://github.com/levineuwirth/pmacs/actions/runs/30927084982/attempts/1) |
|
|
| **retirement** | the fixture proves the trap is installed, with a witness that fails without it |
|
|
|
|
Readiness is `ProcessEventKind::Started`, emitted at **spawn** — not when
|
|
`/bin/sh` has parsed `trap '' USR1`. SIGUSR1's default disposition is
|
|
terminate, so a signal inside that window kills the child. The fixture's
|
|
own comment states the requirement it does not enforce.
|
|
|
|
### R3 — live-leader EPERM with an unobservable group
|
|
|
|
| field | value |
|
|
|---|---|
|
|
| **selector** | `--lib process::tests::a_successful_signal_disposition_depends_on_whether_it_is_fatal` |
|
|
| **job / flavor** | macOS / lua54 |
|
|
| **required fragments** | `EPERM` **and** `measured_group=unobservable(` **and** (`ESRCH` / `No such process`) **and** `leader=live` |
|
|
| **causal status** | **UNRESOLVED — possible product defect** |
|
|
| **evidence** | [#214 run 30932558752 attempt 1](https://github.com/levineuwirth/pmacs/actions/runs/30932558752/attempts/1) |
|
|
| **retirement** | **diagnosis and disposition by the process-signal / reap-ledger lanes. Never a green rerun.** |
|
|
|
|
**Same test as R2, different mechanism, different status.** This is the
|
|
group-target behaviour #176 and #200 circled and the reap-ledger lane
|
|
parked every disposition change pending: a group-directed `kill` returned
|
|
EPERM while the leader was observed live, and `measured_group` — the one
|
|
field able to disagree — could not be read at all.
|
|
|
|
**Do not treat a red matching this row as environmental.** A green rerun
|
|
changes nothing about it.
|
|
|
|
### R4 — readiness predicate satisfied by an empty file
|
|
|
|
| field | value |
|
|
|---|---|
|
|
| **selector** | `--test vterm_stage2_acceptance terminal_escape_gates_local_bindings_and_double_escape_sends_interrupt` |
|
|
| **job / flavor** | macOS / luajit |
|
|
| **required fragments** | `left: []` **and** `right: [49]` |
|
|
| **causal status** | **test race** |
|
|
| **evidence** | [#214 run 30932558752 attempt 1](https://github.com/levineuwirth/pmacs/actions/runs/30932558752/attempts/1) |
|
|
| **retirement** | `wait_for_file` requires the expected content, with a witness that fails against a zero-byte file |
|
|
|
|
`wait_for_file` returns as soon as `fs::read` succeeds — which succeeds
|
|
on a **zero-byte file**. The probe writes readiness with
|
|
`open(path,'wb').write(b'1')`, and `open()` creates the file before
|
|
`write()` fills it. The predicate is "readable"; the assertion is
|
|
"contains `1`" (`49` is ASCII `'1'`).
|
|
|
|
---
|
|
|
|
## Audited incumbents — mechanism named, no occurrence recorded
|
|
|
|
These were carried in the handoff's hazards list **without evidence**.
|
|
The audit found the tests real and the mechanisms plausible, so they are
|
|
neither confirmed nor deleted: they are recorded honestly as unmeasured.
|
|
|
|
**Nothing here confers "known flaky".** A red matching one of these is a
|
|
first recorded occurrence and should be investigated, not reruns-to-green.
|
|
|
|
### R5 — GPU terminal cell background did not paint
|
|
|
|
| field | value |
|
|
|---|---|
|
|
| **selector** | `-p pmacs-gpu a33_headless_terminal_frame_paints_cells_without_document_layers` |
|
|
| **job / flavor** | GPU Render (headless), under parallel load |
|
|
| **required fragments** | `the terminal cell background did not paint` + `blue pixels` |
|
|
| **causal status** | **mechanism named, no occurrence recorded** |
|
|
| **evidence** | **none linked.** The assertion string is real (`pmacs-gpu/src/main.rs:17973`); no run was ever cited |
|
|
| **retirement** | a linked occurrence promotes this row; absence retires nothing, because nothing was measured |
|
|
|
|
### R6 — supervisor reap across cycles
|
|
|
|
| field | value |
|
|
|---|---|
|
|
| **selector** | `--test m6_8_multi_repl_acceptance m6_8_supervisor_reaps_all_children_across_cycles` |
|
|
| **job / flavor** | not recorded |
|
|
| **required fragments** | **not recorded** — no signature was ever captured |
|
|
| **causal status** | **mechanism named, no occurrence recorded** ("timing-based", 10 cycles) |
|
|
| **evidence** | **none linked** |
|
|
| **retirement** | a linked occurrence with a signature promotes this row |
|
|
|
|
**R6 cannot currently be matched.** Without required fragments there is
|
|
no rule to apply, so a red in this test is a new incident by default.
|
|
That is the correct outcome for an entry that never carried evidence.
|
|
|
|
---
|
|
|
|
## Occurrence log
|
|
|
|
| date | run | row | outcome |
|
|
|---|---|---|---|
|
|
| 2026-08-04 | [30826884642](https://github.com/levineuwirth/pmacs/actions/runs/30826884642) | R1 | rerun green — intermittence only |
|
|
| 2026-08-04 | [30927084982 att.1](https://github.com/levineuwirth/pmacs/actions/runs/30927084982/attempts/1) | R2 | rerun green — intermittence only |
|
|
| 2026-08-04 | [30932558752 att.1](https://github.com/levineuwirth/pmacs/actions/runs/30932558752/attempts/1) | R3, R4 | rerun green — intermittence only; **R3 remains unresolved** |
|
|
|
|
Four incidents, three tests, **four signatures**. Count signatures: the
|
|
process test contributed two, and only one of them is a test bug.
|
|
|
|
The #214 occurrence is the strongest available evidence that these are
|
|
not caused by the PRs they appeared on — that PR is **docs-only and its
|
|
tree is byte-identical to a green `main`**. It is not evidence that any
|
|
of them is harmless.
|