Skip to content

fix(GATE-WINDOWS-WARNING-POLICY): /WX- is not /WX, and OBJCXX is not the C++ compile (#774) - #795

Merged
localai-bot merged 5 commits into
mainfrom
row/FIX-WX-TOKEN-BOUNDARY-774
Aug 14, 2026
Merged

fix(GATE-WINDOWS-WARNING-POLICY): /WX- is not /WX, and OBJCXX is not the C++ compile (#774)#795
localai-bot merged 5 commits into
mainfrom
row/FIX-WX-TOKEN-BOUNDARY-774

Conversation

@localai-bot

@localai-bot localai-bot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Closes #774.

Spec: .agents/specs/windows-msvc-warning-policy-tokens.md
Roadmap issue table: .agents/roadmap_v1.md, #774 / ENG-RELEASE-WINDOWS.

Root cause

scripts/check-windows-portability.py:1710 asserted the MSVC warning policy
with a substring test:

if not all(token in warnings for token in ("/W4", "/WX")):

"/WX" in "/WX-" is True, and /WX- is MSVC's spelling for disable
warnings-as-errors. Two more blindnesses fall out of the same in, both
confirmed against this tree:

  • "/W4" in "/W44996" is True/W44996 sets warning C4996 to level 4, it
    does not raise the warning level.
  • CMakeLists.txt:30 contains the literal /W4 /WX inside a # comment, so
    the prose alone satisfied the whole policy. Deleting every real flag in
    cmake/CompilerWarnings.cmake would still have passed.

And the assertion never asked which language the flag reaches. The measured
demonstration is PR #640 commit 74ba3823f (reverted in 15aa963a6 after
review), where the only bare /WX left was on $<COMPILE_LANGUAGE:OBJCXX>
Objective-C++, the Metal backend, which never compiles under MSVC — while the
arm that matters got /WX-.

RED before

Same harness both sides: the HEAD test file run against the BASE checker
(af026e524) and against the HEAD checker, differing in nothing else.

===== BASE checker af026e524 + HEAD tests =====
FAILED ...::test_real_tree_msvc_warning_policy_reaches_the_cxx_compile
FAILED ...::test_rejects_policy_declared_only_in_a_comment
FAILED ...::test_rejects_policy_satisfied_only_on_objcxx
FAILED ...::test_rejects_prefix_lookalike_warning_flags
FAILED ...::test_rejects_warning_level_disabled_alongside_the_policy
FAILED ...::test_rejects_warnings_as_errors_disabled_by_wx_minus
6 failed, 1 passed, 71 deselected, 4 subtests passed

E   AssertionError: 0 == 0 : Windows portability contract OK

===== HEAD checker + HEAD tests =====
7 passed, 71 deselected, 9 subtests passed

The base failure message is the point: the checker reports Windows portability contract OK on a tree whose C++ arm says /WX-.

The one base test that passes is the inverse pin — an honest tree still passes
both before and after, so this is not "stricter about everything".

The fix

msvc_cxx_flag_text() reduces the CMake text to what can reach an MSVC C/C++
translation unit: # comments removed, and every generator expression whose
COMPILE_LANGUAGE names only non-C/C++ languages blanked (spans from a
$< / > stack scan, blanked in place so offsets survive, matching
without_set_source_properties). A genex naming no language is kept, because
it does reach C/C++, so the failure direction is never "silently excluded".

has_msvc_flag() matches with (?<![A-Za-z0-9_-]) / (?![A-Za-z0-9_-])
boundaries, case-sensitively — cl treats /w and /W4 as different flags.

The assertion then requires /W4 and /WX as tokens on that text, and refuses
the disable spellings of the same two flags — /WX-, /W0, /w — as a
separate error, because "absent" and "present and cancelled" are different
repairs.

cmake/CompilerWarnings.cmake is deliberately not edited: the tree already
satisfies the repaired policy, and a checker repair that also moved the thing it
checks could not show that.

The sibling evasions #640 also used — decided, not silently widened

  • COMPILE_WARNING_AS_ERROR OFF: out of scope. CMake uses that property
    only to decide whether it adds a warnings-as-errors flag; nothing about it
    removes a literal flag from target_compile_options. Under the VS generator
    it lowers to MSBuild TreatWarningAsError=false, whose /WX- precedes
    AdditionalOptions, and MSVC takes the last of the pair — our explicit /WX
    still wins. The converse already fails closed: a tree that dropped the literal
    /WX in favour of the property would go RED on the missing token. Asserting a
    property value is a new policy about spelling, which check-windows-portability's /WX assertion is satisfied by /WX-, so the gate is blind to its own inversion #774 does not describe.
  • Blanket /wd####: out of scope, and pinned as a deliberate non-goal by
    test_accepts_the_policy_on_every_shape_that_reaches_cxx. A per-warning
    suppression narrows what /W4 reports; it does not invert /W4 or /WX.
    Refusing it wholesale would forbid the legitimate targeted suppression (the
    tree has none today, so nothing is grandfathered in) and "how many is too
    many" is an undecided threshold. Any future /wd is a review judgement on its
    own PR.
  • /W0 and /w: in scope, unlike the two above, because they are the
    disable spellings of /W4 itself. Closing /WX- while leaving its exact twin
    one character away would be the same defect check-windows-portability's /WX assertion is satisfied by /WX-, so the gate is blind to its own inversion #774 reports.

One pre-existing red had to be cleared to land this

check-pr-size.py's executable-evidence contract runs the whole recognized
module and requires it green at HEAD. tests/scripts/test_check_windows_portability.py
has been RED on main since e8a9e74e1 — verified on a pristine base worktree
at af026e524: 71 tests, 1 failure. That is the "one fake-runner case" of #680,
so no change to scripts/check-windows-portability.py could satisfy the gate.

It is a stale mutation anchor, not a checker gap. The checker reads
$calls.Add( in exactly one place — good_runner, the $good scriptblock of
Invoke-UnsupportedTierContractTests (check-windows-portability.py:1372) —
and script.replace("$calls.Add(", ..., 1) takes the first occurrence in the
file, which since #512/#583 added Invoke-CheckedContractTests above it lives
in a function the checker never looks at. The mutation left the governed text
intact, the checker correctly stayed green, and the assertion read that as a
defect.

The third commit anchors the mutation to the governed occurrence and asserts
that occurrence is unique. No assertion is deleted or widened, and the mutation
is now rejected by the base checker and this one — a fixture repair, not a
semantics change. #680 stays open for its other half: no workflow invokes
this suite at all.

Gates

  • scripts/agent-preflight.sh — green (70 ok, 0 failed).
  • python3 scripts/check-pr-size.py --base af026e524 --head HEADOK. That
    is the gate's own re-execution of the red-before/green-after evidence in an
    isolated worktree, so base_failed and head_passed are proven by the gate,
    not asserted by me.
  • python3 scripts/check-commit-trailers.py --range af026e524..HEAD — OK.
  • python3 -m unittest tests.scripts.test_check_windows_portability under
    check-pr-size's exact sanitized environment — 78 tests, OK.
  • python3 -m pytest tests/scripts/ --ignore=tests/scripts/test_cpu_kernel_bench.py
    8 failed, 1368 passed, 3 skipped, 1541 subtests passed (18:51). All 8
    are pre-existing; the same 8 reproduce on a pristine origin/main worktree
    under the same names.

Baseline to subtract

Run on a /dev/shm worktree detached at origin/main, no diff applied:

SUBFAILED(shader='vt_attn_qk_norm_rope_gate.comp') test_gen_vulkan_spirv.py::CommittedArtifact::test_other_shaders_declare_none_yet
SUBFAILED(shader='vt_gdn_decode.comp')             (same test)
SUBFAILED(shader='vt_gdn_post_conv.comp')          (same test)
SUBFAILED(shader='vt_gdn_prefill.comp')            (same test)
SUBFAILED(shader='vt_matmul_vec.comp')             (same test)
SUBFAILED(shader='vt_sigmoid_gate_bf16.comp')      (same test)
FAILED test_mlx_system_headers.py::...::test_mlx_includes_have_source_scoped_clang_warning_suppression
FAILED test_now_render.py::DerivedFromPerRowRecords::test_a_spec_now_line_is_picked_up
8 failed, 20 passed, 2 skipped

test_now_render reads .agents/specs/now-derived.md, not the spec added here.

Separately, tests/scripts/test_cpu_x86_llamacpp_floor.py failed on an earlier
run of this branch and on the pristine base tree (af026e524: 2 failures,
including test_a_contended_leg_is_discarded_and_never_summarised, at loadavg
~29 with many agents on the box) and passed on the run above. It is
contention-sensitive, not attributable to this change. windows-msvc-* are
PR-only and red on every PR (#584).

CPU-only; no GPU, no benchmark.

mudler added 5 commits August 14, 2026 17:25
…n the C/C++ compile (#774)

`check-windows-portability.py:1710` asserts the policy with `token in
warnings`. `"/WX" in "/WX-"` is True, and `/WX-` is MSVC's spelling for
DISABLE warnings-as-errors, so the gate is blind to its own inversion.

Measured on PR #640 commit `74ba3823f` (reverted in `15aa963a6` after
review): it shipped `/WX-` on the CXX arm while the only bare `/WX` left was
on `$<COMPILE_LANGUAGE:OBJCXX>` -- Objective-C++, the Metal backend, which
never compiles under MSVC. Two more blindnesses fall out of the same `in`:
`/W44996` answers for `/W4`, and `CMakeLists.txt:30`'s `#` comment satisfies
the whole policy on its own.

The spec fixes the shape of the repair before the code exists: token
boundaries, language scoping, comment stripping, and the negating spellings
of the two flags the policy names. It also decides the two sibling evasions
#640 used and argues both rather than widening silently --
`COMPILE_WARNING_AS_ERROR OFF` cannot cancel a literal `/WX` and stays out;
`/wd####` narrows what `/W4` reports rather than inverting it and stays out;
`/W0` and `/w` are the disable spellings of `/W4` itself and come in.

Spec before code, per AGENTS.md. No checker or test changes here.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]
…the C++ compile (#774)

`check-windows-portability.py:1710` asserted the MSVC warning policy with
`token in warnings`. `"/WX" in "/WX-"` is True, and `/WX-` is MSVC's spelling
for DISABLE warnings-as-errors: the gate could not see its own inversion.
Nor did it ask which language the flag reaches, so a `/WX` confined to
`$<COMPILE_LANGUAGE:OBJCXX>` -- the Metal backend, never compiled by MSVC --
satisfied it. And `CMakeLists.txt:30` says `/W4 /WX` in a `#` comment, which
satisfied the whole policy by itself.

`msvc_cxx_flag_text()` reduces the CMake text to what can reach an MSVC C/C++
translation unit: comments removed, and every generator expression whose
COMPILE_LANGUAGE names only non-C/C++ languages blanked in place (spans from
a `$<`/`>` stack scan, blanked rather than cut so offsets survive, as
`without_set_source_properties` does). A genex naming no language at all is
KEPT -- it does reach C/C++ -- so the failure direction is never "silently
excluded".

`has_msvc_flag()` matches with boundaries on both sides, case-sensitively
because `cl` is. The assertion then requires /W4 and /WX as tokens on that
text and refuses the disable spellings of the same two flags -- /WX-, /W0,
/w -- as a separate error, because absent and present-and-cancelled are
different repairs. `/wd####` and COMPILE_WARNING_AS_ERROR are argued OUT in
the spec and pinned as accepted shapes by the inverse test.

RED before, same harness both sides: the six new cases fail against the base
checker `af026e524` with "AssertionError: 0 == 0 : Windows portability
contract OK" -- the gate reporting OK on a tree whose C++ arm says `/WX-` --
and pass against this one. The seventh, the inverse pin, passes on both.

`cmake/CompilerWarnings.cmake` is deliberately untouched: the tree already
satisfies the repaired policy, and a checker repair that also moved the thing
it checks could not show that.

Spec: .agents/specs/windows-msvc-warning-policy-tokens.md

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]
…nction since #583 (#680)

`test_real_unsupported_tier_helper_is_structurally_scoped` mutates the real
`build-windows-release.ps1` and asserts the checker rejects each mutation.
The "fake runner call recording" case did `script.replace("$calls.Add(",
"$calls.Append(", 1)`.

The checker reads `$calls.Add(` in exactly one place: `good_runner`, the
`$good` scriptblock inside `Invoke-UnsupportedTierContractTests`
(`check-windows-portability.py:1372`). `replace(..., 1)` takes the FIRST
occurrence in the file, and since `e8a9e74e1` (#512/#583) added
`Invoke-CheckedContractTests` above it, that first occurrence is in a
different function the checker never looks at. So the mutation left the
governed text intact, the checker correctly stayed green, and the assertion
read that as a defect. This is the "one fake-runner case" of #680, RED on
`main` at `af026e524` -- verified on a pristine base worktree, 71 tests, 1
failure, message `AssertionError: 0 == 0 : Windows portability contract OK`.

Anchor the mutation to the governed occurrence and assert that occurrence is
unique rather than assuming it, which is the property that silently changed
underneath this test. No assertion is deleted or widened: the same rejection
is still required, and it now actually exercises the rule it names -- the
mutation is rejected by BOTH the base and the current checker, so this is a
fixture repair, not a semantics change.

It has to land here because `check-pr-size.py`'s executable-evidence contract
runs the WHOLE recognized module and requires it green at HEAD, so this stale
anchor blocks every change to `scripts/check-windows-portability.py`.

The second half of #680 -- that no workflow invokes this suite -- is NOT
addressed here and the issue stays open for it.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]
Five commits landed on main after this branch's base `af026e524`. None touch
`scripts/check-windows-portability.py`, its test module, or the MSVC warning
flags in `cmake/CompilerWarnings.cmake`; the only shared surface is the
`.agents/roadmap_v1.md` issue table, where #777 was inserted mid-table and
#774 appended, so both keys survive and no unrelated key moved.

Merged so the gates run against the tree this branch will actually land on.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]
Picks up #782 (GATE-FORK-ANCESTRY), which repairs the range computation in
check-pr-size.py and check-commit-trailers.py. Both of this PR's red non-baseline
checks -- pr-size and agent-record -- failed on "base must be an ancestor of
head", which is exactly that defect and predates its fix.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]

# Conflicts:
#	.agents/roadmap_v1.md
@localai-bot
localai-bot merged commit be4a3ed into main Aug 14, 2026
0 of 16 checks passed
localai-bot pushed a commit that referenced this pull request Aug 14, 2026
Picks up #795 (GATE-WINDOWS-WARNING-POLICY) and #802 (GATE-AUDIT-BRANCH-
EVIDENCE), which landed while this PR was in CI.

FOLLOWING_AGENTS_PROTOCOL

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: Claude:claude-opus-5 [Claude Code]

# Conflicts:
#	.agents/roadmap_v1.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check-windows-portability's /WX assertion is satisfied by /WX-, so the gate is blind to its own inversion

2 participants