[scripts, ci] (P7): the memo purity gate asserts its own anchors and allow-list, and stops calling a policy exemption an absence

Rework round 3 of 4 after the D2 review (fable, ID-P7-8). Three defects, each of a kind
the gate could not have reported about itself.

(a) TWO STRUCTURAL SELF-CHECKS. family_spans() returned whatever matched and nothing ever
asserted that each of the five FAMILIES anchors found its declaration, so a renamed struct
would drop a whole family while every rule kept passing. And an allow-list entry no rule
can consult documents a carve-out that is not happening - a claim about the tree that
nothing verifies. main() now fails on either, naming the anchor or the entry and saying
which of the two repairs is wanted. Both are exercised: renaming an anchor and adding a
dead entry each red the gate.

(b) THE DOCSTRING AND THE test.yml COMMENT WERE WRONG about what the guards mean.
MOBILEGL_PIPE_LEGACY_MEMOS defaults ON (CMakeLists.txt:43) and no job here clears it, so
CI split builds DO compile those arms - TwinLookupMemo (DirectGLES.cpp:114) sits inside
one and is compiled into every lane this repo runs. The rule is "the legacy arm MAY KEEP
pointer keys", a policy exemption; only !MOBILEGL_BUILD_DISAGGREGATED is code a split
build genuinely never sees. Both now say so.

(c) FRONTEND HAD NO LEADING WORD BOUNDARY, so BackendSamplerObject* matched SamplerObject
and the gate reported the memos' backend VALUES as frontend keys - which the first version
answered with two allow-list entries, i.e. it documented a false positive instead of
fixing it. (?<!\w) added, with controls both ways: the backend twins must stay green and
the qualified MG_State::GLState::ProgramObject* must still match.

The allow list therefore goes from six entries to ONE. Four were dead on arrival - two
false positives now fixed at the source, one naming a typedef with no frontend type in it,
and const void* program / Uint64 programLifetimeId, which no rule could ever consult
because void is not in FRONTEND and neither line calls GetLifetimeId(). The
ResolvedTextureBindingMemo monolith key those last two described is still deliberate and
still there; it simply never needed an exemption, and saying it did was misleading. What
remains is the twin registry's UnorderedMap<StateObject*, Entry>, which really is
suppressed and really is the pull build's only arm.
This commit is contained in:
2026-09-22 18:17:25 -04:00
parent 0f3b82725d
commit 394df89237
2 changed files with 117 additions and 32 deletions
+13 -5
View File
@@ -3113,11 +3113,19 @@ jobs:
# The same shape for Espryt's re-keyed memos (P3b/P4b, PLAN-PH-P34B-P7.md 1.2). P4a/P5f
# moved the resolved-binding, sampler-pass, image-sweep, twin-registry, unit-sampler and
# twin-lookup memos onto {slot, gen} handles and applier serials; the legacy pointer-keyed
# arms stayed behind MOBILEGL_PIPE_LEGACY_MEMOS / !MOBILEGL_BUILD_DISAGGREGATED because
# they are the PULL build's only arms and G1 pins that build's .text. Nothing checked that
# a NEW frontend-pointer key could not appear outside those arms. --self-test runs the
# negative controls and then the real scan in the same invocation, as its sibling does.
- name: Espryt memo keys carry no frontend pointer outside the legacy arms
# arms stayed because they are the PULL build's only arms and G1 pins that build's .text.
# Nothing checked that a NEW frontend-pointer key could not appear outside them.
#
# MOBILEGL_PIPE_LEGACY_MEMOS IS A POLICY EXEMPTION, NOT AN ABSENCE. It defaults ON
# (CMakeLists.txt:43) and no job here clears it, so the split builds in this workflow DO
# compile those arms - TwinLookupMemo among them. The gate's rule is "the legacy arm may
# keep pointer keys", which is a decision; only !MOBILEGL_BUILD_DISAGGREGATED is code a
# split build genuinely never sees.
#
# --self-test runs the negative controls and then the real scan in one invocation, as its
# sibling does; the scan also asserts that every memo family's anchor still matches and
# that every allow-list entry still suppresses something.
- name: Espryt memo keys carry no frontend pointer outside the exempted legacy arm
run: python3 scripts/ci/espryt_memo_purity.py --self-test
# The same question for the symbol tool the P1 gate is written in terms of.