- ADrawAfterTheEarlyReclaimFollowsTheNewStoreNotTheMemoizedHandle rides the same split/spawn
fixture as the three gauge cases and the tcp arm does not carry it (magma-m2.md §9.3); the
integration tree keys this list by exact tail, so the fourth name goes in beside the three
- every line of EVIDENCE is a grep -F pattern and an empty line matches everything: a trailing
newline or a blank line between the two sentences would turn hole 2 into "any red will do".
The smoke's "red without the transport-resolution message" case catches that (22/23), but
only when somebody runs it; a `case` after the assignment now refuses a blank line or a
leading/trailing newline with ::error:: and rc 1, before the selection is counted or the
library is swapped. The red-check's perturbation line is untouched; smoke 23/23
- scripts/ci/testdata/stub_ctest.sh went 100755 -> 100644 in the round-2 commit that added
its retrace-evidence-nolog mode (a Windows-mount artefact); restored with
`git update-index --chmod=+x`. The smoke copies it and chmods the copy, so nothing ran
differently
- stepping over `#endif` accepted a log that is compiled out: `#if 0` / `MGLOG_W(...)` /
`#endif` / `Count(...)` read as logged, and so did a log under `#ifdef
MOBILEGL_VERBOSE_DECLINES` - a Count that counts every time and logs in no shipped build
- the walk now counts the `#endif`s it crosses; a same-indent log met with one outstanding
counts only if every opener enclosing it, reached by continuing upward, is the whole-line
`#if MOBILEGL_BUILD_DISAGGREGATED` (`&& X` is not it). `#if`/`#ifdef`/`#ifndef` with no
`#endif` outstanding is the Count's own guard and is still stepped over, so the column-0
`#if/#endif` fixture stays green; the comment says the walk is fail-open for that one
guard and nothing else
- `#else`/`#elif` stopped the walk only at column 0, as a line of lesser indentation; one at
the Count's own indentation walked straight through to the log above it. PP_STOP now
returns False at any indentation, before the indent test
- two red fixtures, both green on the round-2 audit: "log only under a #if 0 above the
Count" and "log only on the other side of an INDENTED #else at the Count's indentation";
16/16, the tree stays 53 / 53 / 0
- AuthToken.h: ConstantTimeTokenMatch loops kAuthTokenCompareBytes (64) iterations with both operands read as zero past their ends - its trip count no longer tells a peer the configured token's length; a token longer than 64 is still compared to its last byte (SocketTransportTest pins the 70-byte case)
- ServerSession.cpp: an ask in Hello.linkTerms above the granted terms logs one MGLOG_W naming both sides ("the ask is ignored and the session is server-sized"); the production client asks for nothing, so a session that was never mis-configured never logs it; SessionHandshakeTest's 64 GiB case requires the line (red before: absent)
- ServerSession.cpp: a MintNonce failure sends Refuse{LinkTerms} "stream data plane unavailable: the server could not mint a data nonce" before returning the fault it is (still exit 67, still counted) instead of a bare close
- ServerMain.cpp: a first frame with the wrong magic or over 1 MiB while a session is live is Refuse{MalformedHello} "first frame is not a control frame", drained before the close so the refusal is not RST away; Busy stays the answer for a well-formed frame that is not a DataBind
- tcp_supervisor_smoke.py: garbage_first_frame_while_busy (magic XXXX on a live session -> code 8; red before: code 7)
- fatal census unchanged: 79 abort sites, 3 refusal words (the new refusals go through the enum, not a literal)
- the revision is a hand-bumped integer mixed into wireFingerprint and nothing tied it to protocol.fbs's content; scripts/ci/protocol_revision_pin.py holds {revision -> sha256(protocol.fbs)} in protocol_revision_pins.json and refuses a schema whose digest is not the current revision's, or a revision with no row
- registered as ProtocolSchema.RevisionPinsDigest (label unit, MG_Test/Wire/CMakeLists.txt, --self-test proves both perturbations red before it says green) and as a step of CI's flatc-check job, the one that regenerates the header on every schema edit
- --write records a bump's row and refuses to re-pin an existing revision to a different digest, which is what a schema edit without a bump looks like
- mg_protocol_base.h says where the pin lives beside the revision it pins
- red-once: protocol.fbs touched with one trailing comment, revision left at 1 -> "protocol.fbs has sha256 a7b5c7fb... but MOBILEGL_PROTOCOL_CONTROL_REVISION is still 1, which is pinned to 7fc859f7..." rc=1; restored, green
- ServerMain.cpp: RunSession takes the descriptor its data-connection source reads from (the child's hand-off end under --serve, the listener itself without it) and closes it the moment Accept returns; the source object goes with it
- the supervisor's hand-off send is MSG_DONTWAIT (FdPassing::SendFd dontWait), so a peer that stopped reading answers at once; "peer gone" on a datagram pair (ECONNREFUSED, ENOTCONN) is an answer the caller names, not a logged fault
- before: every DataBind after the bind sat in the child's receive queue with no reply, its TCP connection held open until the session ended, and past the queue limit (net.unix.max_dgram_qlen 10 on the phone; ~288 datagrams of sender buffer on this host) the supervisor blocked in sendmsg for the rest of the session - no accepts, no Busy, no reaping
- before, without --serve: the listener stayed open after the data connection bound, so a second client or a retry completed a TCP handshake nobody would accept and waited out its 20 s connect budget instead of the ECONNREFUSED it got before PH-7 (4)
- tcp_supervisor_smoke.py: data_bind_after_bound (12 extra DataBinds on a bound session each get Refuse{Authentication} "data connection could not be handed to the live session", and a fresh control connection is still Busy) and single_session_listener (a connect after `ready` is ECONNREFUSED); connect_control retries ECONNREFUSED at startup for pair() and held_session() alike
- red-once at da313010: smoke TimeoutError on the first extra's receive; probe with qlen+2 fire-and-forget DataBinds: 288 queued silently, then the supervisor stopped accepting (fresh control: connect timed out) while still alive; single-session connect after ready succeeded
Rule J's red-once for M2. The server role's VkBufferManager publishes four PipeStats gauges
(push builds only, so the pull image is untouched): wire buffer records alive, and the run
maxima of live wire VkBuffers and of parked bytes, plus the watermark's forced-sync count -
maxima because the defect lived inside one frame and a swap-time sample reads after the frame
boundary's own sweep. Two cases, each inside a single frame: 1024 undrawn respecifies of one
4 KiB buffer (live peak <= 4 x wire buffers), and 48 respecify-and-draw rounds of a 1 MiB store
under the lane's MOBILEGL_IPC_WIRE_DEFERRED_MB=8 (parked peak <= budget + one store, every strip
its own colour). Red at base (ec46a550's defer path, counted): 1025 vs 4 live, 49,287,168 vs
9,437,184 bytes and 49 vs 11 live, on both arms; green after: 1 live, 9,437,184 bytes / 9 live
with 5 forced syncs. The knob's negative control (=0) reds the second case with the same
49,287,168 bytes. Inproc and spawn only: the tcp server is the lane-wide fixture supervisor,
whose environment and log the entry cannot reach - named in spawn_lane_parity.py as
MAGMA_NOT_ON_TCP (the ID-P7-14 shape), and PipeStatsTest pins the four short names.
- retrace_pull_library_control.sh required run_trace_case.cmake's "never reported resolving
it", the marker-search sentence. Since P6's one-log-per-role rename a pull library never
reaches that search: it has one role and writes MOBILEGL_LOG_FILE_PATH unchanged
(output/mobilegl.log, Log.h's pull arm of RoleLogPath), the runner reads
output/mobilegl.client.log and stops one check earlier with "the run wrote no <client log>,
so there is no evidence the transport ever resolved" - so the control's hole-2 check
refused its own red and the step exited 1 on every pull-library run
- measured on this tree with the real ctest, build-linux's pull library over build-split's
frozen split library, SPLIT_TRANSPORT=inproc: control rc 1, "::error::the split retrace
went red (ctest exit 8) ... never says the library did not resolve the transport", the
runner's fatal at the no-client-log check. With this change the same run passes for its
own reason on both inproc and spawn
- EVIDENCE carries both sentences as grep -F's newline-separated patterns, so the evidence
line the red-check perturbs is unchanged; both are the transport-identity assertion
refusing the same library for the same reason, and neither is a loader failure, a missing
fixture, a timeout or an SSIM drop
- stub_ctest.sh gains retrace-evidence-nolog, the no-client-log fatal CMake-wrapped across
lines the way the real one arrives; control_smoke_test.sh expects it to PASS (23/23); the
red-check still reds "red without the transport-resolution message"
- a same-indent `case`/`default:`/`break;`/`return`/`continue;`/`goto`/`throw` line between a
log and a bare Count ends the walk: control cannot flow from that log to the Count, so it
is not the Count's log. A `case 1: MGLOG_W; break; case 2: Count` switch with its labels at
statement indentation, and a log above a `return` with the Count under a same-indent label,
both read as logged before
- `#if`/`#ifdef`/`#ifndef`/`#endif` lines are passed over: a log and its Count that straddle a
`#if MOBILEGL_BUILD_DISAGGREGATED` are one block on both sides of the preprocessor, and the
column-0 line ended the walk for no defect. `#else`/`#elif` still end it - a log on the other
side of one is in a different build, not this one
- four fixtures: same-indent return (red), same-indent switch (red), log across a #else (red,
and red on the previous audit too - it pins that #else still stops), Count under its log
across #if/#endif (green; a false red before). 14/14 fixtures; the tree stays 53 / 53 / 0
- L'"', u'"', U'"' and u8'"': the `'` after an identifier character was taken for a C++14
digit separator, the `"` inside it opened a phantom string, and the rest of the line was
blanked - a site on that line vanished and its row read as NO SITE (fail-closed: a false red)
- CHAR_PREFIX accepts a u8/u/U/L prefix before `'` the way RAW_PREFIX does before `"`, with
a non-identifier character (or the start of the text) in front of it, so a real separator
(0xAB'CD, 1'000) is untouched
- self-test fixture with L'"' and u8'"' ahead of two AT sites on their own lines: rc 0; it
was rc 1 on the previous audit. The tree has no prefixed character literal today (53 / 53 / 0)
- the wire declines audit's LOGGED pattern was unanchored, so a guarded one-liner at the
Count's indentation (`if (g) MGLOG_W("x");`, `g ? MGLOG_W("x") : (void)0;`) counted as
the site's own log and the site read as logged - a decline counted every time but logged
only sometimes, which is the unlogged site the check exists to refuse
- anchored to the statement start; the block walk matches the line, not searches it
- self-test fixture "guarded one-liner log at the Count's indentation" (both shapes) reds
with the NO_LOG sentence; it was green on the previous audit. The tree stays 53 / 53 / 0
Fable review of the B3 rework, should-fix: the audit had no negative
control, so a green run could not say it would have been red. It now takes
--self-test, which writes each inline fixture as a one-file renderer tree in
a temp dir, runs the audit on it and checks both the rc and the line the
audit must print (so a red is red for the fixture's reason):
comment-only site (//) -> rc 1, "has NO SITE"
comment-only site (/* */) -> rc 1, "has NO SITE"
string-literal site -> rc 1, "has NO SITE"
other-branch log -> rc 1, "with no MGLOG_W/E in its own block"
nested-branch log -> rc 1, same
log only in a /* */ comment above -> rc 1, same
nearest log is MGLOG_D -> rc 1, same
good sites (AT form, bare Count under
its own MGLOG_E_ONCE, def row with a
trailing comment) -> rc 0, "0 unlogged, 0 unknown"
8/8, rc 0. Mutants: with the strip disabled 5 of 8 fail (the four
comment/string reds go green and the good fixture's commented row is
lost); with the old 8-line window in place of the block walk 2 of 8 fail
(other-branch, nested-branch). Against the audit as it stood at aab01275,
six of the seven red fixtures passed and the good one failed.
.github/workflows/test.yml: the "Wire declines audit (B3)" step runs
--self-test and then the tree audit, the way the next step runs
trace_cases.py --self-test-transport-matrices before it computes matrices.
Fable review of the B3 rework, should-fix: the 8-lines-above MGLOG_W/E window
was branch-blind - a Count() in `if (x == 2) { ... }` whose only log sat in a
preceding `if (x == 1) { ... }` passed, as did a log in a nested branch just
above. All 12 bare sites in the tree are under their own line today, so this
was a gate hole, not a present defect.
has_own_log() walks upwards from the Count line (still capped at 8 lines):
blank and deeper-indented lines (a log's continuation lines, a nested block)
are passed over, only a line at the Count's own indentation can be its log,
and the first line indented less than the Count - the block's opening, a
sibling's `} else {` - ends the walk.
WireDeclines.def is now read through the same comment/string strip, and ROW
tolerates spaces inside the parentheses: `MGL_WIRE_DECLINE(Name) // note`
used to fail `\)\s*$`, dropping the row, and its real site was then
reported as naming no row.
Tree: 53 rows, 53 with sites, 53 sites, 0 unlogged, rc 0 (unchanged).
Fixtures the previous commit passed and this one reds: other-branch log,
nested-branch log (rc 0 -> 1); a def row with a trailing comment plus its
site (rc 1 -> 0).
Fable review of the B3 rework, must-fix: a row was "sited" by any line the
AT_SITE / COUNT_SITE regex matched, including a // comment, a /* */ block or
a string literal - `// MGL_WIRE_DECLINE_AT(GhostRow, "...");` satisfied the
audit for a row nothing counts, and an MGLOG_W inside a comment above a bare
Count() satisfied the log rule.
wire_declines_audit.py now blanks //...$ (with backslash-newline
continuation), /* ... */, "..." and '...' (raw strings R"d(...)d" and
C++14 digit separators handled) out of each source before any match. Every
character but the newline becomes a space, so the text keeps its length and
line count and each report still cites the real line.
Tree: 53 rows, 53 with sites, 53 sites, 0 unlogged, rc 0 (unchanged).
Fixtures that the previous audit passed and this one reds (rc 1): a
comment-only site (//), a comment-only site (/* */), a string-literal site,
a log only in a /* */ comment above a bare Count. The branch-blind window
and the .def trailing-comment row are the next commit.