Commit Graph
3669 Commits
Author SHA1 Message Date
swung0x48 eaef83b32a [MG_Remote, MG_Test] (P7): the server binds its deferred stream link through the Transport factory 2026-09-23 13:23:09 -04:00
swung0x48 14e1c8b9b1 docs: close p7w6 controls and F2 hardening status 2026-09-23 08:40:33 -04:00
swung0x48 e036b4e017 docs: record B4 landing and p7w6 matrix results 2026-09-23 06:07:36 -04:00
swung0x48 b19297d5e5 [MG_Backend, MG_Test] (P7): prove aggregate waits with a single-fence control 2026-09-23 03:53:37 -04:00
swung0x48 a4c1bc8b1e [MG_Backend, MG_Remote] (P7): draft B4 aggregate waits and staged extent reset 2026-09-23 03:53:37 -04:00
swung0x48 7ea7ce89cb [trace_replay] (P7): persist cancelled TCP attempts in results JSON 2026-09-23 02:12:40 -04:00
swung0x48 3ce5b9913e [docs, MG_Backend] (P7): record W6 device evidence and land M3 on review 2026-09-23 01:59:32 -04:00
swung0x48 9fd768d493 [MG_Backend, MG_IntegrationTest] (P7): bound wire descriptor sets within long frames 2026-09-23 01:35:20 -04:00
swung0x48 254bfb013e [docs] (P7): preserve the interrupted p7w5 matrix and p7w6 bsl evidence 2026-09-23 01:35:07 -04:00
swung0x48 f749d4c340 [trace_replay] (P7): pin the signed APK path used by a preinstalled device run 2026-09-23 01:08:18 -04:00
swung0x48 0e16ca272e [docs] (P7): HANDOFF-2026-09-22.md rewritten to the session's end state - nothing left to land, one matrix still running, the queue starts at p7w6 2026-09-22 23:15:28 -04:00
swung0x48 3374becde1 [docs] (P7): ID-P7-47/48 - V1 fix round 2 lands on the integrator's own review; the window-1b mid-run reading and the screen-off hypothesis are recorded for the next integrator 2026-09-22 23:11:14 -04:00
swung0x48 336174e36f [docs] (P7): the A-prime paragraph carries its where=entry counts
- the two counts were left as placeholders in the previous commit; they are 1 / 1 (DirectGLES / DirectVulkan), and the client summary of 4 / 3 is that one entry report plus the server read arm's 3 / 2, the divergence counter being process-wide
2026-09-22 23:05:20 -04:00
swung0x48 9814bc7426 [MG_IntegrationTest, MG_Remote] (P7): two citations stop misquoting - the old floor's unnamed count and a CMake line number
- split_log_paths.py's verify_split_arming docstring said the old count-only floor left ~117 entries unnamed; 117 is the lane's skip count, and the entries the floor left unnamed are the ones that did not arm - 155 on the last host run (1064 per-entry client logs, 909 armed), of which the 117 skips are a part
- CONTRACT-P7 §6 cited the monolith verify block by a CMakeLists line number ("约 :1715 起", with a note about an earlier wrong range); the guard `if (MOBILEGL_PIPE_VERIFY)` is the durable citation and now stands alone
2026-09-22 23:05:20 -04:00
swung0x48 07f4e3acef [MobileGL, MG_Backend, MG_Impl, docs] (P7): the FATAL=0 verify summary is written before Debug::Close, so the client half keeps its lines
- the summary line ("N divergence(s) survived MOBILEGL_PIPE_VERIFY_FATAL=0") came from a namespace-scope static's destructor, which runs from __run_exit_handlers AFTER MobileGL::Destroy has called MG_Util::Debug::Close(); Close nulls the role's sink, Log.cpp's WriteToFile re-runs InitFile() for the next line, and InitFile opens the role's file with "w" - so that one line was the only line the client half of every FATAL=0 run kept (121 B: the entry compare's reports, the arming line and the config dump all gone, on the split corrupt / read-corrupt entries and on the monolith arm's VerifyCorrupted. log alike)
- fixed in verify-only code, since Log.cpp is in the pull build and G1 admits no byte there: VerifyState gains FlushSummary(), which reports the count once (idempotent - a second call with nothing new, the destructor's own included, writes nothing); MGPipeVerifyFlushSummary() exports it from PipeFill.cpp, declared in PipeInputs.h beside the other verify-only entry points, and DestroyImpl calls it right before Close under #if MOBILEGL_PIPE_VERIFY
- the note's A' paragraph no longer says the entry compare is silent on the pack field - it reports it (the client summaries read 4 divergence(s) on DirectGLES / 3 on DirectVulkan); the red line can only come from the read arm because of where=read and the server-role file, and the paragraph now names the truncation and carries the numbers
- measured on the same entry, pipe-verify-split-read-corrupt-DirectGLES.client.log: 121 B / 1 line before, 7461 B / 85 lines after (DirectVulkan 121 B / 1 line -> 7386 B / 85 lines), with the where=entry report (1 each; the summary's 4 / 3 is that one plus the server's 3 / 2 read reports, the counter being process-wide) and the arming line present and the summary as the last line
2026-09-22 23:02:08 -04:00
swung0x48 ffc4fb7d77 [MG_Impl, MG_IntegrationTest, ci] (P7): the first perturbation block's falsifier is the DirectVulkan entry
- measured with one block removed at a time: without the re-applied block both server halves drop to 1 (DirectGLES 1 / DirectVulkan 1, both entries red); without the first block DirectVulkan drops to 1 (red) while DirectGLES stays at 2 (green), because the GLES backend reads the pack field twice after the neutral pack is installed (3 = the saved-pack read + 2 post-install) and DirectVulkan once (2 = 1 + 1)
- so the >= 2 requirement falsifies the re-applied block on both backends and the first block on DirectVulkan; the CI step runs both backends and needs both, which it already does
- the scenario, hook and CI comments now say exactly that, instead of "removing either block drops it to 1"
2026-09-22 23:02:08 -04:00
swung0x48 403b566949 [MG_Impl, MG_IntegrationTest, ci] (P7): the read-side control counts to two, one per perturbation block
- the server reads GetPixelStoreParameters twice inside the ReadPixels window - PipeApplier::read_pixels saves the application's pack through the accessor before it installs the neutral one, and the backend's ReadPixels reads the field after - and both reads sit inside ServerReadsInsideTheNeutralPackWindow; the hook's first perturbation is what turns the saved-pack read red (past the first compare the application's pack differs from the neutral oracle on its own), and only the perturbation re-applied after the window's overwrite can turn the post-install read red, because there the stored value is the neutral pack
- so a control that accepted ONE `where=read` line was satisfied by either block alone and falsified neither: the second block, which protects the lane's post-install backend reads, had no falsifier
- CorruptedFieldIsReportedOnTheServerRead now counts the `where=read` reports for the field in the server half since its mark and requires at least two; the CI read-side step does the same with grep -c; both block comments in the hook say which read each turns red
- measured on the host: both entries green, server half DirectGLES 3 / DirectVulkan 2; removing only the second block rebuilds green and turns both entries red with exactly one report per server half (1 / 1, ctest rc 8); the file was restored byte-identical and rebuilt
2026-09-22 23:02:08 -04:00
swung0x48 be764a56d7 [docs] (P7): ID-P7-46 - M2 round 2 lands on the integrator's own review, the memo handle-reuse ABA is closed 2026-09-22 23:02:07 -04:00
swung0x48 1ab62ece4c [ci] (P7): the parity exception list names M2 round 2's fourth Reclaim case
- 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
2026-09-22 22:56:43 -04:00
swung0x48 f62703e933 [MG_Backend] (P7): a respecified wire store starts with no submission stamp
- M2 round 2 left this to the integrator: lastUseSubmitIndex is B3's field and exists only on
  the integration tree; without the reset the fresh store answers busy-by-submission until the
  old index retires (a needless staged copy, conservative not unsafe)
2026-09-22 22:51:20 -04:00
swung0x48 5ba34fcf42 [docs] (P7): magma-m2.md round 2 - the memo epoch fix and its red-once, the pipe tree's SHAs, the floor decision on its first reason alone, and the round's gates
- Section 0 cites the six commits by their pipe-tree SHAs (b81a8827 c569c916 0acee60a 9328bdc7 f0356dbe 5d8a2b99), with the branch SHAs alongside; every in-text cite follows.
- Section 2.1 keeps "the frame-serial floor is not a proof" on its first reason and drops the second, a stale citation of B3's fix; 6.3 is reworded to match.
- New section 9 records the review's must-fix (ID-P7-43): the handle-reuse ABA against UniformManager's memos, the destroy-epoch fix, the deterministic scenario and its red-once on both arms (the dead store's colour read back at base), the finding that the integration binary links the backend statically so a red-once variant has to be built into it as well (round 1's reds re-verified that way, unchanged), the three more knobs the spawn scrub keeps, the review's smaller items, the gates, and what is left for the integrator (the pipe-tree-only lastUseSubmitIndex reset in RespecifyWireBuffer).
2026-09-22 22:51:20 -04:00
swung0x48 6e18acaa5d [MG_Remote] (P7): the spawn launcher also passes MOBILEGL_IPC_SPIN_US, MOBILEGL_IPC_SERVER_AFFINITY and MOBILEGL_IPC_AUDIT through to the server child
- The environment scrub kept exactly one MOBILEGL_IPC_* knob (WIRE_DEFERRED_MB, M2); these three are also read by the server and were silently defaulting in the spawned child for the same reason: SPIN_US is the doorbell spin budget both roles read, SERVER_AFFINITY the apply thread's CPU mask, AUDIT the 0xDD fill of retired stage bytes. Each is a tuning or audit value; none names an endpoint, a role, a path or a segment size, and ServerMain's catch (b) keeps verifying the four it verifies (TRANSPORT, SERVER_PATH, RING_MB, STAGE_MB).
- Everything else under the prefix still goes (the fable review of M2, item on ServerSpawn.cpp).
2026-09-22 22:51:20 -04:00
swung0x48 959ebc9e76 [MG_IntegrationTest] (P7): MagmaWireReclaimScenario draws through a handle the early reclaim freed and re-minted, and reds on the dead store's bytes; the count-ceiling case refuses an absent gauge
- ADrawAfterTheEarlyReclaimFollowsTheNewStoreNotTheMemoizedHandle is the round-2 red-once for ID-P7-43, deterministic at every step: a draw from a 256-byte UBO store memoizes its handle; glBufferData(0) orphans it without minting; glClientWaitSync with the flush bit and a zero timeout submits the batch without waiting (the review's flush-without-wait); a glBufferSubData into the busy vertex store records a staged copy so the blocking glClientWaitSync that follows cannot take the frame-boundary drain that clears the memos; the vertex store's own glBufferData(0) is the park whose sweep destroys the dead store; a 64 KiB glBufferData through the same GL buffer mints through the freed handle value (glibc tcache, LIFO) into memory that cannot alias the 256-byte hole a 1 MiB pin store bounds; the second draw resolves the same (handle, range). The pixel must be the new store's colour; at base it is the dead store's.
- Red-once (rule J), the epoch guards removed from UniformManager.cpp and the variant built into MobileGL, MobileGLServer AND MobileGLIntegrationTest: Split and Spawn both read rgba(200,60,30,255) - the dead store's colour - against the wanted rgba(60,200,90,255); green with the guards. The integration binary links the backend statically (MobileGL_s), so a variant built into the two shared targets alone never reaches the inproc arm - the first run of this red-once read Split green for that reason, and a re-run of round 1's base variant into all three targets reproduces round 1's reds on both arms unchanged (1025 vs 4; 49,287,168 vs 9,437,184 and 49 vs 11; 3001 vs 1027).
- ManySmallRespecifyAndDrawRoundsStayUnderTheStoreCountCeiling asserts the wlivepk gauge is a reading before bounding it, as the other two cases already did: an absent gauge read -1 and passed the one-sided bound as a leak that never happened.
- Registered on the Split and Spawn Reclaim entries beside the three; spawn_lane_parity.py's MAGMA_NOT_ON_TCP names the fixture by prefix, so nothing there moves.
2026-09-22 22:51:20 -04:00
swung0x48 4d20746831 [MG_Backend] (P7): the descriptor memos fold in a wire-store destroy epoch, so a VkBuffer handle the mid-frame reclaim freed and the next mint handed back cannot revive a set baked to the dead store
- M2's defer path destroys a wire store MID-FRAME (the serial-0 park, the sweep's prefix walk, the watermark); before it a wire store only died at the boundary that also clears UniformManager's memos (BeginFrame from Present or a drain). Those memos are keyed on the VkBuffer HANDLE - m_descriptorReuseMemo hashes the VkDescriptorBufferInfo words, FastRebindMemo compares uboBuffer - and on the wire arm the direct-bind UBO and the SSBO descriptor name the store's own handle. A store destroyed at a park, its handle value re-minted by the next Create (a heap pointer under lavapipe, LIFO out of glibc's tcache), and a draw resolving the same (handle, range) reused a set whose descriptor still pointed at the dead store's memory: silent wrong bytes, no Fatal (ID-P7-43, the fable review's must-fix).
- VkBufferManager gains m_wireStoreDestroyEpoch, bumped on every path that destroys a wire store's VkBuffer (DeferWireRelease's immediate destroy, SweepDeferredWireReleases once per sweep that freed anything, DestroyAllDeferredWireReleases, Shutdown's record teardown) and never reset, with GetWireStoreDestroyEpoch(). UniformManager mixes it into the descriptor-reuse signature and records it in FastRebindMemo, refusing the fast rebind when it moved; all under MOBILEGL_BUILD_DISAGGREGATED. Deliberately not m_sliceEpochCounter, which every WriteWireBuffer bumps and would defeat the memo on every glBufferSubData. On the wire arm only the signature is reached (SetupWireDraw passes no sampler hint), the FastRebindMemo field is the defensive half.
- Two comments from the same review: SweepDeferredWireReleases no longer claims GetSyncPointSubmitIndex() never decreases - it steps back by one across an abandoned recording (RecreateSwapchain, the minimized Present), and the prefix walk is conservative across that, not wrong; and the header's "floor is not a proof" keeps its decision on its first reason alone, the second was a stale citation of a fix that is on the integration tree.
- Section 9 partition exception for UniformManager.{h,cpp} granted by the integrator for this fix.
2026-09-22 22:51:20 -04:00
swung0x48 efa19cb16f [docs] (P7): ID-P7-45 - X2 lands: the InitialCapsStartup flake was the fixture pairing loopback sockets by accept order 2026-09-22 22:20:50 -04:00
swung0x48 9a4752adba [docs] (P7): X2 - note for the InitialCapsStartup flake: TCP accept order, not the caps bring-up
- docs/Disaggregated/notes/p7/x2-caps-flake.md: the failure text (Fatal{ProtocolCorruption,
  "StreamLink"} invalid data frame header, SIGABRT), the mechanism (ConnectTo/AcceptPair pairs
  two loopback TCP connections by accept order and the kernel reorders them under load: 5 of
  3000 in a raw-socket probe), the TEST verdict against the product's DataBind rendezvous, the
  before/after loop counts (2/500, 5/500, 3/500 -> 0/500 x3 under the same load) and the gate
  numbers (unit 2435/2435, census 79, ratchet 173, G1 .text 0xa52203 and +0/-0 symbols)
- open: AcceptPair/ConnectTo over tcp:// are still callable and still pair by order; refusing
  them by name is a product change with its own red-once
2026-09-22 22:20:24 -04:00
swung0x48 e730a91206 [MG_Test] (P7): X2 - SocketTransportTest's TCP case uses the DataBind rendezvous too
- TcpCarriesControlAndIndependentDataWithKeepalive had the same assumption as the
  InitialCapsStartup fixture: ConnectTo/AcceptPair over loopback TCP, paired by accept order;
  when the kernel reordered the two connects the bytes sent on the client's data socket arrived
  on the server's control socket and recv(serverData, MSG_WAITALL) hung until the 60 s kill -
  3 of 500 runs under the same load, 0 of 500 afterwards
- the case now opens the control connection, accepts it, then opens the data connection with a
  DataBind nonce and decodes it on the accepted side, exactly the shape the product uses on TCP;
  it keeps its NODELAY, keepalive and ShareFd-unsupported checks on both control transports and
  its independent-data check on the bound data sockets, and asserts that a control-only TCP
  transport owns no data descriptor (TakeDataFd == -1)
2026-09-22 22:20:24 -04:00
swung0x48 f91d0f2c4b [MG_Test] (P7): X2 - InitialCapsStartup pairs its TCP sockets by DataBind nonce, not by accept order
- the fixture rendezvoused with ConnectTo/AcceptPair over loopback TCP, which pairs the two
  connections by the order the listener accepts them; under host load the kernel delivers two
  back-to-back loopback connects to the accept queue out of connect order (measured 5 of 3000
  with 20 CPU hogs), the peer's control socket became the client's data socket, the first control
  frame hit the StreamLink reader and the process died of Fatal{ProtocolCorruption, "StreamLink"}
  invalid data frame header - 2 of 200 and 2 of 500 runs of ANullInitialSnapshot..., 5 of 500 of
  DelayedTcpSnapshot..., every one in 3 of the last 4 integration gates on the loaded host
- the flake is in the TEST: PH-7 (4) already took by-order pairing out of the product on TCP
  ("never paired by arrival order"); the fixture now does what ServerMain's ListenerSource does -
  ConnectControl is accepted before ConnectDataConnection is opened, and the data connection
  names itself with a DataBind nonce that the peer decodes and matches in constant time
- 0 of 500 for both cases under the same load afterwards; AHealthyPeer... shares the fixture and
  is covered by the same change; no product bytes touched
2026-09-22 22:20:24 -04:00
swung0x48 bf8e605fd0 [docs] (P7): ID-P7-44 - the integrator's own reviews land the F fix round and the B3 r3 / B2 r4 rounds, with two small debts recorded 2026-09-22 22:16:07 -04:00
swung0x48 137c911a94 [docs] (P7): ID-P7-43 - M2 lands with a must-fix routed to M2 round 2, and HANDOFF-2026-09-22.md lists every mechanical step left for the next integrator 2026-09-22 22:08:23 -04:00
swung0x48 63347c1682 [docs] (P7): ID-P7-42 - M2 and the F fix round pass their gates, B3 round 3 and B2 round 4 join the tree, and the verify counts are the integration tree's 2026-09-22 22:05:21 -04:00
swung0x48 4b96f55d32 [docs, MG_IntegrationTest] (P7): magma-b2.md carries review round 4 - the transport gate loses a conjunct nothing reaches, and the debt lines cite by symbol
- review round 4 nit: the second gate of the flipped multisample resolve case read `!SplitLane::IsSplitLane() && !PeekSplitRuntime().transportResolved`; the marker term is dead - with the marker set and no transport resolved, the fixture's SetUp already skipped through SplitLane::SkipReasonForSplitOnlyAssertions() -> SplitRuntimeSkipReason(), so Ready() is false and the gate is never reached; in every reachable state it equals `!PeekSplitRuntime().transportResolved`, which is what it now says (the SplitLane.h include goes with it), and the comment no longer describes an unreachable branch; behaviour unchanged - monolith entries still Skipped with the same text, the Full entries still Passed
- review round 4 nit: magma-b2.md §6 items 1, 2, 3 cited WireFramebuffer.inc by line numbers that round 3 had already moved; they now name the arm inside BlitWireFramebuffers's `blit` lambda and the MGLOG_E_ONCE / RecordTextureCopyError text, and the monolith cross-reference names VulkanRenderer::BlitFramebuffer's vkCmdResolveImage + vkCmdBlitImage instead of pipe line numbers
- §2.11 records the round: the should-fix (window primed magenta/0.625, the one-shot wrong-surface demonstration and its readings), the two nits, and a round 4 line under §7 with this tree's readings
- test and docs only; no backend source touched (G1 unaffected)
2026-09-22 22:03:23 -04:00
swung0x48 e385ea96c8 [MG_IntegrationTest] (P7): the window leg of the flipped multisample resolve case primes the default framebuffer with values no other surface in the test holds
- review round 4 should-fix: round 3 primed the window blue at depth 0.5, the same colour and depth the user framebuffer `resolved.fbo` was primed with and still held after its own declined blit, so a glBindFramebuffer(GL_FRAMEBUFFER, 0) that landed on the user framebuffer, or a default-framebuffer readback that resolved the wrong surface, read the priming it was meant to reject and the leg passed vacuously
- the window is now primed magenta at depth 0.625 - the user framebuffer is blue at 0.5, the source red/green at 0.25/0.75 - and the three probes expect exactly that
- shown once and restored: with the probes pointed at `resolved.fbo` instead of 0, all three arms (`DirectVulkan.{Split,Spawn,Tcp}.MsFlip.`) fail on both aspects at (1, 1): colour reads {0,0,255,255} against {255,0,255,255} ("must not have written its colour at (1, 1)"), depth reads 0.5 against 0.625 ("must have left its depth alone at (1, 1)"); under round 3's priming the same probes on that surface were green
- test only; no backend source touched (G1 unaffected)
2026-09-22 22:03:23 -04:00
swung0x48 c8fc4fb712 [docs] (P7): magma-b3 - fix round 3: the audit's guard-aware walk, the tcp-naming server-log fatal, the EVIDENCE guard, and the round's gate
- §0: rows 28-31 for this round
- §1.5: the two walk holes the third review found (a log under `#if 0` accepted, an indented
  `#else` walked through), the fail-open-for-one-guard rule, and the two new fixtures' readings
  on the round-2 audit and on this one; 16/16, tree 53 / 53 / 0; the probe shapes that are not
  fixtures
- §4.1: the merged server-log fatal names MOBILEGL_IPC_CONTROL; demo 1 re-run on the new runner
- §4.5: the EVIDENCE empty-pattern guard; the stub's executable bit restored
- §7.2: the B4 sentence gives both numberings (package tree :13404 / :13471, landed tree
  :13533 / :13600); two debts recorded - the tcp pid-arm-proof check still runs before the
  marker check, and LOG_WINDOW counts the blank and `#if` lines it skips
- §5: the round's gate on the code head; no product file, so G1 is unaffected; lanes not re-run
2026-09-22 22:03:23 -04:00
swung0x48 3b8bf9ec25 [scripts] (P7): the pull-library control refuses an empty grep -F pattern in EVIDENCE, and the stub ctest is executable again
- 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
2026-09-22 22:03:23 -04:00
swung0x48 10220b564e [tools] (P7): the merged server-log fatal names MOBILEGL_IPC_CONTROL, so the tcp arm's red still says tcp
- the round-2 merge folded "TCP session has no forwarded server log" into the one server-log
  check for every transport, and its message named only MOBILEGL_TRANSPORT - which is `spawn`
  for the tcp arm too (tcp = spawn + MOBILEGL_IPC_CONTROL=tcp://), so the tcp arm's missing
  forwarded log read as a plain spawn red
- the message carries MOBILEGL_IPC_CONTROL='...' after the transport (empty for inproc and
  plain spawn); message only, no check moved
2026-09-22 22:03:23 -04:00
swung0x48 bd849b2821 [tools] (P7): the audit's block walk is fail-open only for the disaggregated guard, and an indented #else stops it
- 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
2026-09-22 22:03:23 -04:00
swung0x48 9cea514010 [docs] (P7): ph-f.md §6/§7 record the F fix round - the fingerprint refusal is one-directional and an un-redeployed phone shows as "no Welcome", the unix pairing window and the two pre-auth exposures are §12 debts, the token minimum is TCP-only, and the token examples are 16+ bytes
- ph-f.md: §0 rows F-a..F-d with package-tree SHAs; §2.2 states the asymmetry (new server + old client -> Refuse{WireFingerprint}; old server + new client -> the old AcceptPair closes both after 2000 ms and the client sees `no Welcome ... (rc=6)`, no Refuse frame); §6 the four fix commits with their red-once lines; §6.4 the unix arrival-order pairing (250 ms / 2000 ms) as a local-peer debt with the SELinux assumption named, and the two pre-auth exposures; §7 the gates on 2b2a0ae0
- CONTRACT-P7 §12: the two pre-auth exposures (fork before Hello with a 10 s wait; ValidatePeerHandshake before AuthenticatePeerToken sends the fingerprint and build stamp to an unauthenticated peer), the unix pairing debt, and the fingerprint asymmetry, for PH-7 (5)
- PLAN-PH-P34B-P7: PH-7 (3) says the minimum is checked at the TCP listen; PH-8 says "ignored, server-sized" rather than "clamped"; the no-token listen row's remaining-work cell no longer claims the smoke is unreferenced
- device-window-1-runbook §2 step 3: the un-redeployed-phone symptom, and where to look first
- ROADMAP §6 and peer-loss-probe: `MOBILEGL_IPC_TOKEN=devtoken` (8 bytes, which now exits 72) becomes a 25-byte token in every example
2026-09-22 21:55:39 -04:00
swung0x48 8c8fc31952 [MG_Remote, MG_Test, ci] (P7): the token compare runs a fixed 64-byte width, an ignored window ask is logged once, a nonce that could not be minted is refused by name, and a garbage first frame while busy is MalformedHello rather than Busy
- 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)
2026-09-22 21:54:46 -04:00
swung0x48 c69d8dfdc8 [MG_Remote, MG_Test, ci] (P7): sha256(protocol.fbs) is pinned to MOBILEGL_PROTOCOL_CONTROL_REVISION, so a control-schema edit without a bump is red in the unit lane and in flatc-check instead of a silently absent field
- 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
2026-09-22 21:54:46 -04:00
swung0x48 0293aebb17 [MG_Remote, ci] (P7): a bound session closes its data-connection source, so a later DataBind is refused by name instead of queued into a child that stopped reading, and the single-session listener closes with it
- 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
2026-09-22 21:54:46 -04:00
swung0x48 9ae1e6c04e [docs] (P7): ID-P7-41 - M2 is on the integration tree with its second leak named, three reviews land with fixes, and window 1b's instant failures are the pairing window over the LAN 2026-09-22 21:48:27 -04:00
swung0x48 7d1315271a [docs] (P7): magma-m2.md names the one server-side-knob parity list its three entries joined at merge 2026-09-22 21:46:08 -04:00
swung0x48 5d8a2b99fd [docs] (P7): magma-m2.md records M2 - the wire arm's orphaned VkBuffers are bounded (25,935 -> ~1,050 peak, bsl spawn server 825 -> 546 MiB), and the host maps M1 attributed to them are lavapipe descriptor sets
Before/after on host with M1's sampler and probe for bsl-esc-menu-854 and iris-bsl-in-world on
monolith / inproc / spawn (pixels identical on every arm), the mechanism with citations, the
knob's semantics, the red-once table, the gates, and what remains: the wire arm's descriptor-set
growth between BeginFrame rewinds (27,377 live sets == 28,134 maps; now bounded only because
M2's forced syncs let the drain rewind the cursors), CollectGarbage/pruneWire never reached on
the wire arm (B4), the frame-serial proof deferred until B3's floor fix, the tcp arm's gauge
reach, the ServerSpawn.cpp touch and the knob for the integrator to ratify, and the Redmi
acceptance run.
2026-09-22 21:46:08 -04:00
swung0x48 f0356dbe61 [MG_Backend, MG_IntegrationTest] (P7): the wire watermark's sync point also fires above 1024 parked stores, so small orphans that never reach the byte budget are bounded by count
Measured on bsl-esc-menu-854 (spawn, lavapipe) with the byte watermark alone: the dead VkBuffers
at the end fell from 25,935 to 32, but one stretch with no submission still parked 12,498 stores
in 39.5 MB - under 64 MiB, so nothing forced a sync. A fixed ceiling
(VkBufferManager::kWireDeferredCountCeiling = 1024, not a knob) now rides the same
WaitForSubmitIndex call; MOBILEGL_IPC_WIRE_DEFERRED_MB=0 still turns both triggers off.
MagmaWireReclaimScenario gains the case: 3000 respecify-and-draw rounds of a 256-byte store in one
frame (750 KB, far below the lane's 8 MiB). Red before this commit on inproc and spawn (live peak
3001 vs a bound of 1027), green after (1025, two forced syncs).
2026-09-22 21:46:08 -04:00
swung0x48 9328bdc735 [MG_Backend, MG_Util, MG_Test, MG_IntegrationTest, scripts] (P7): integration-magma-split and -spawn carry MagmaWireReclaimScenario, which reads the server's wbuf[] gauges and reds on a wire arm that keeps orphaned buffer stores until the frame ends
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.
2026-09-22 21:46:08 -04:00
swung0x48 0acee60a3b [MG_Remote] (P7): the spawn launcher passes MOBILEGL_IPC_WIRE_DEFERRED_MB through to the server child, the one MOBILEGL_IPC_* knob its environment scrub keeps
BuildChildEnv drops every MOBILEGL_IPC_* entry, so the server-owned watermark meant something
under inproc and silently nothing under spawn - measured: the spawn server parked 47 MiB against
a lane budget of 8 with zero forced syncs, because it had parsed the default out of an
environment that no longer carried the variable. The knob names no endpoint, role or segment
size, so neither anti-recursion catch (Dial=No, ServerMain's scrub check of TRANSPORT /
SERVER_PATH / RING_MB / STAGE_MB) is weakened; it is listed by name, not by widening the prefix.
2026-09-22 21:44:06 -04:00
swung0x48 c569c916c0 [MG_Backend] (P7): when the orphaned wire buffer stores still parked exceed MOBILEGL_IPC_WIRE_DEFERRED_MB (64 by default), the server takes the host-access sync point mid-frame and reclaims them all
The defer-path sweep frees an orphan once its last submission has retired, but inside one long
frame a store that was drawn from is named by recorded, unsubmitted work, and nothing submits it
until the frame ends. The knob is read once through MG_Config::Ipc like its siblings; above it
the park calls WaitForSubmitIndex(GetSyncPointSubmitIndex(), flush) - the call
WaitForWireBufferHostAccess makes - and sweeps again, which empties the list because no entry can
be tagged past the sync point just waited out. A sync point that cannot complete dies through
the existing Fatal{ResourceUnavailable, "buffer-write-sync"} site, now one helper shared with the
host write (fatal_census: 79 abort sites, unchanged). 0 is the negative control.
2026-09-22 21:44:06 -04:00
swung0x48 b81a8827b5 [MG_Backend] (P7): a wire buffer store that glBufferData orphans is destroyed on the defer path as soon as no GPU command can still name it, instead of waiting for a frame boundary
RespecifyWireBuffer (every wire glBufferData) and DestroyWireBuffer parked the old VkBuffer in
the per-frame-slot buckets, which only BeginFrame and the idle drain empty. A snapshot-exiting
pbuffer replay delivers one present per run (ID-P7-32), so on bsl-esc-menu-854 the split server
held 25,923 dead stores. The wire arm now keeps its own flat list: a store whose last-use serial
is 0 (never named by a GPU command) is destroyed at the park; any other is tagged with the
renderer's sync-point submit index and destroyed by the sweep every park runs, once that index
has completed or the renderer is idle. The frame-serial floor is deliberately not a proof here
(it cannot move mid-frame, and on this base it is the floor B3 found unsound). The transient
arena's releases and the monolith OnRespecify path are unchanged.
2026-09-22 21:44:06 -04:00
swung0x48 41b392298b [docs] (P7): ID-P7-40 - window 1b's TCP matrix runs on the user's route, and the B3, V1 and B2 fix rounds are on the integration tree 2026-09-22 21:38:13 -04:00