mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 18:13:23 +09:00
[scripts, CI, docs] (P7): the 184-symbol link-closure ratchet lands as a gate
CONTRACT-P6.md 12.1 has carried "a ratchet recomputes the 184 in CI and asserts it only
ever falls" as an obligation since P6. The roadmap handed it to P6.5; the P6.5 line never
received it, and scripts/ci/ has never had anything that computes this number. ID-P7-7
gives it to P7 wave 0. This is it.
scripts/link_ratchet.py mechanises a6's hand experiment: partition the per-object output
of the single MobileGL target into SERVER / FRONTEND / SHARED, then compute
(SERVER undefined) - (SERVER defined) - (SHARED defined) intersect (FRONTEND defined),
which is the undefined-symbol list a real link of a server-only image would print. The
partition is an explicit table with a rationale per row, because it IS the module boundary
the build system does not have (SOURCE_FILES is one flat list; boundaries are P13's work).
An object matching no row is a hard failure, as is a build whose CMakeCache lacks the three
disaggregated options, or an empty role set - every way this gate could go green without
having measured anything is an explicit exit 2.
Measured on 78b7d6be: 186 symbols. The three backend buckets reproduce a6's hand-made
101 / 14 / 60 exactly, as do its per-object referrer and definer distributions
(UniformManager 90, VulkanRenderer 60, Managers 53, DirectGLES 51; TextureObject 59,
SamplerObject 30, BufferObject 18, FramebufferObject 16, PipeFill 9). Nothing from a6's
184 has been cleared; the +2 are both P6.5's:
Client::ClientSession::StartSpawned() - fork-per-session
GLState::ProgramArtifactsSchemaFingerprint() - archive v2 caps
The baseline stores the LIST, not a count (ID-P7-7): a count-only ratchet goes green on the
day one symbol is cleared and another added. --assert-monotone fails only on symbols absent
from the baseline and names each one's defining object and every referring object; symbols
that disappeared are reported with an instruction to re-baseline in the same commit, and
never fail.
The CI step goes in build-linux-split, not build-linux: build-linux takes the three options
from MOBILEGL_CI_DISAGGREGATED, which is ON only on feat/disaggregated and
codex/fix-github-ci, so on any other branch it builds a monolith and the gate would measure
a SERVER set with no transport half. The JSON is uploaded even when the gate fires.
Two findings for the integrator, both written up in the note:
- a6's four published bucket totals sum to 181 against its own headline of 184. These
buckets are a strict partition and always sum to the headline; the difference is in
a6's core bucket, which it listed selectively.
- 5 of the 14 "P3b/P4b" symbols are MG_Pipe slot-allocator and apply-thread plumbing
that sits under MG_Impl/Pipe/ by file location alone. P3b/P4b cannot clear them by
migrating Espryt functionality; they need P13's module move. That bucket's floor is
5, not 0, so the plan's 0.5-day Tier 1 estimate for "D12's 14 symbols" should be
re-cut against 9. All 7 symbols from that object carry a `# P13` annotation.
red-once (R-16) is recorded verbatim in the note. Worth knowing: the plan's own example
(SamplerObject::GetMinFilter) does NOT turn this gate red, because it is already in the
baseline - the ratchet reddens on new symbols, so a negative control has to pick one that
is not in the 186. A reach to GetBorderColorForm() from DirectGLES/Utils.cpp does, naming
the symbol, its definer and its referrer, exit 1; reverted and green again.
This commit is contained in:
@@ -987,6 +987,48 @@ jobs:
|
||||
fi
|
||||
echo "libMobileGL.so defines ${remote} MG_Remote symbol(s) and the MGPipe applier (${defined} defined symbols)"
|
||||
|
||||
# The link-closure ratchet (CONTRACT-P6.md 12.1, ID-P7-7): the set of frontend symbols a
|
||||
# server-only image would still have to link, recomputed from the per-object partition in
|
||||
# scripts/link_ratchet.py and compared against the stored LIST.
|
||||
#
|
||||
# THIS job and not `build-linux`: build-linux passes the same three options from
|
||||
# ${MOBILEGL_CI_DISAGGREGATED}, which is ON only on feat/disaggregated and
|
||||
# codex/fix-github-ci, so on every other branch it builds a monolith - MG_Remote would not
|
||||
# be compiled at all, the SERVER half of the partition would be empty, and the gate would
|
||||
# go green having measured nothing. This job turns the three options on unconditionally,
|
||||
# and the nm step immediately above has just proved they took. The script re-reads them
|
||||
# from CMakeCache.txt anyway and refuses the run if they are not all ON.
|
||||
#
|
||||
# Only NEW symbols fail. A symbol that has DISAPPEARED is the ratchet turning and is
|
||||
# printed with an instruction to re-baseline in the same commit - the baseline stores the
|
||||
# list rather than a count precisely so that clearing one symbol while adding another does
|
||||
# not walk through at an unchanged total (ID-P7-7).
|
||||
#
|
||||
# It reads the per-object output of the MobileGL target, so it must run before anything
|
||||
# that cleans the build tree; the packaging step below excludes *.o from the tarball but
|
||||
# does not delete them.
|
||||
- name: The server image reaches no further into the frontend than the baseline
|
||||
run: |
|
||||
mkdir -p ci-artifacts
|
||||
python3 scripts/link_ratchet.py --self-test
|
||||
python3 scripts/link_ratchet.py \
|
||||
--build-dir "${BUILD_DIR}" \
|
||||
--baseline scripts/data/link_ratchet_baseline.txt \
|
||||
--assert-monotone \
|
||||
--bucket \
|
||||
--json ci-artifacts/link-ratchet.json
|
||||
|
||||
# Uploaded even when the gate fired: a red ratchet is exactly the moment someone needs the
|
||||
# per-symbol definer/referrer attribution the JSON carries, and a job that failed before
|
||||
# uploading its evidence is a job nobody can act on.
|
||||
- name: Upload link ratchet
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: link-ratchet
|
||||
path: ci-artifacts/link-ratchet.json
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Show ccache stats
|
||||
if: always()
|
||||
run: ccache --show-stats
|
||||
|
||||
Reference in New Issue
Block a user