Skip to content

The #1755 console call-site gate holds only the JSON build: sliding the console block below ByStart and Sum survives 19 of 20 runs #1760

Description

@localai-bot

### 10 of .agents/specs/ltx25-phase-instrument.md repaired two things at once and gates them with one composite case: RenderText reads its own clock first (arm B), and the console block moves from the END of WriteJson to immediately after that writer's own clock read — above ByStart(Records()), above Sum(...), and above the whole nlohmann build (arm A).

Arm (A) holds only the last of those three. Slide the console block back down BELOW ByStart(Records()) and Sum(...) while keeping it ABOVE the JSON build, and the suite stays green. The intent the repair's own comment states — "it sits above the copy, the sort and the whole JSON build because those were being charged to it" — is therefore held in one third.

Call the mutation M-SITE-MID. Applied to src/vllm/multimodal/render_phase_log.cpp at the head of PR #1711 (61c3f0a75):

+  const std::vector<Record> records = ByStart(Records());
+  const Totals totals = Sum(records, wall);
+
   if (StderrEnabled()) {
     const std::string block = RenderText(family, device);
     std::fwrite(block.data(), 1, block.size(), stderr);
     std::fflush(stderr);
   }
 
-  const std::vector<Record> records = ByStart(Records());
-  const Totals totals = Sum(records, wall);
-
   nlohmann::json out;

anchor_occurrences=1, git diff --numstat 3 3 src/vllm/multimodal/render_phase_log.cpp, compile_status=0, restore_sha256_ok=True against a pristine byte copy, and git diff --numstat EMPTY after the restore. Release build, -DVLLM_CPP_BUILD_TESTS=ON, x86_64, loadavg 8.5 to 10.3. Every run printed its own doctest count lines, because a -tc filter that matches nothing prints Status: SUCCESS! at rc 0.

20 runs: 19 GREEN, 1 RED. Nineteen read test cases: 8 | 8 passed | 0 failed | 0 skipped and assertions: 120 | 120 passed | 0 failed. One — run 7 of the first batch, loadavg 9.88 — read 8 | 7 passed | 1 failed and 120 | 119 passed | 1 failed. A mutation a gate catches 1 time in 20 is a mutation the gate does not catch; it is worse than a clean survivor, because the one red is a flake a later session will reasonably discount.

The console lags the case measured under M-SITE-MID, each a minimum over 3 probes:

7.0954e-4  8.0859e-4  6.1208e-4  5.5063e-4  7.0809e-4
4.4587e-4  1.0344e-3  4.8383e-4  6.9707e-4  5.2762e-4
3.8975e-4  8.3156e-4  4.0191e-4  7.2963e-4  7.7509e-4
7.8492e-4  4.7455e-4  9.6428e-4  6.6708e-4  7.8302e-4

min 3.8975e-4 s, max 1.0344e-3 s, against a bound of one full step of %10.3f, 1e-3 s. The honest tree on the same box reads 7.94e-5, 1.206e-4, 2.876e-4, 4.492e-4 s.

Why arm (A) cannot see it, and it is structural rather than a matter of luck. Arm (A)'s table is 16 000 records, and that size was chosen to make the JSON build cross the format's last printed digit. Measured inside the same runs, that build is 6.5388e-3 to 7.2559e-3 s — 6.54 to 7.26 steps of %10.3f, comfortably over the arm's 2 * kStep precondition. The copy and the sort at the SAME table size are what M-SITE-MID moves, and the lags above measure them at 3.90e-4 to 1.03e-3 s — 0.39 to 1.03 steps, straddling the one-step bound rather than clearing it. The two quantities differ by roughly an order of magnitude at one table size, so a table sized to the larger one cannot separate the smaller one.

That is #1569's mute-switch argument met a fourth time, on the arm that was written to close its third occurrence: a discriminator large enough to be visible does not make a SMALLER co-located discriminator visible, and a composite gate reports one verdict for both.

This is NOT #1718. #1718 is about Record::instrument_seconds' five CHARGE sites being gated only in aggregate. This is the #1755 class: the console emitter's call-site ORDERING inside WriteJson, gated against a full revert and not against a partial one. M-RT-PARTIAL — the same partial-regression shape on arm (B) — is RED 10/10, so arm (B) holds its own partial. Arm (A) does not hold arm (A)'s.

What would settle it, and what would NOT. Enlarging arm (A)'s table until the copy and the sort cross the format's last digit is the obvious move and it is measured shut: WriteJson holds one nlohmann object per record while it dumps, about 3.3 KB per record, so a table big enough costs about a gigabyte of resident set through arm (A), and arm (A) already costs 141 MB and 2.2 s in CI. Inventing a new wall-clock tolerance is forbidden by #1668 and by ltx25-phase-residue.md ## Design 3.

What would work is a bound that does not go through the printed format at all: assert the ORDER rather than its timing consequence. The console block's position relative to ByStart and Sum is a static property of one function, and a gate over the emitted WALL will always be limited by %10.3f's three digits. A structural assertion — or a RenderText that is handed the wall it must print instead of reading a clock, which would make the whole ordering question disappear — is the repair. Both are production changes to a shared emitter and each owes its own red-first evidence, which is why this is filed rather than fixed in flow.

Found by the fresh review of PR #1711 and reproduced independently by the repair session that recorded it.

Owned by .agents/specs/ltx25-phase-instrument.md ## Owed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions