Repository navigation
Three satellites verify nothing about the digest they pin — SocialMedia, Manufacturing and Crm have no pin-consistency gate at all, so a half-moved set merges green #3454
Description
Three satellites have NO pin-consistency gate — a wrong digest merges green
Measured 2026-09-06 while staging the coordinated platform-pin move for the 3.0.0 wave.
| repo | check-platform-pins.py |
"Both platform pins name ONE promoted build" | pin sites a move must pass through |
|---|---|---|---|
| MeshWeaver.Plugins | ✅ | ✅ | 14 |
| MeshWeaver.Reinsurance | ✅ | ✅ | 12 |
| MeshWeaver.SocialMedia | ❌ absent | ❌ absent | 4 |
| MeshWeaver.Manufacturing | ❌ absent | ❌ absent | 1 |
| MeshWeaver.Crm | ❌ absent | ❌ absent | 1 (a step output, not env:) |
0 matches in the bottom three — this is not a gate that skips, it is a gate that does not exist.
🚨 The distinction matters because the fleet's usual failure is a skipped gate wearing a passing
tick; here there is nothing to skip. A pin move that names one build in one place and a different
build in another merges green in those three repos, and the first symptom is whatever the wrong
reference set does at bake or compile time.
Why this is a blocker-list item rather than a nice-to-have
The pins are moving right now as one coordinated set for the release wave, and they move again at
the tag. In Plugins and Reinsurance a half-moved set is caught mechanically. In SocialMedia,
Manufacturing and Crm it is caught by whoever notices.
The precedent is on record and it was expensive: a withdrawal that took a line it did not add
dropped a 4th pin, took core CD down for an hour, and every check was green (#3344). That is
exactly the shape these three repos cannot detect.
What the gate would have to check
Not merely "is the digest well-formed". The two properties that matter:
- Every pin in the repo names ONE promoted build — the set name, the source ref, the tester
digest and the portal digest must be mutually consistent, including sites outside theenv:block. - The digests actually resolve in ACR at the tag the set names (
--check-tags). 🚨 This one is
load-bearing given Retention: the locks hold nightly — apply the decided 30-day window to the paused purge-old-images, read production back, and inventory bundles/active builds as consumers #3438: ACR retention has already deleted a pinned tester digest and wedged an
entire repo's CI including its own nightly.
🚨 A placeholder must fail RED, not silently pass. check-platform-pins.py matches
sha256:[0-9a-f]+, so a non-hex placeholder digest reads as "no literal pin present" and the check
passes having verified nothing. Any gate added here must be falsified against that case specifically
— it is the vacuity trap this fleet keeps rediscovering (most recently in #3441, where a release
gate read its denominator from the store it was judging).
Site counts are not uniform, which is the other half of the risk
A single sed is wrong everywhere. From the same survey:
- Plugins: 14 sites — set 1, source sha 7 (four
platform-ref:values, of which two are
literals at L2994/L3153 and two are derived${{ needs.platform-ref.outputs.sha }}), tester
digest 3, portal digest 3. A digest pasted intoenv:alone leaves four stale pins. - Reinsurance: 12 sites — set 1, source sha 9, tester 1, portal 1.
- 🚨
clients/react/src/i18n/catalog-source.jsonholds the same core sha and is NOT a platform
pin. A repo-wide replace silently moves the i18n mirror's comparison ref, whose drift guard
compares VALUES against a pinned core commit. Excluded deliberately. - Education pins under entirely different names —
MW_PORTAL_DIGEST,MW_MIGRATION_DIGEST,
MW_TEST_DIGEST— so any fleet-wide gate keyed onMW_IMAGE_DIGEST/MW_PLATFORM_SETwould report
Education clean while checking none of its pins. Another absence that reads as a pass.
Provenance
Surfaced while staging the five coordinated draft PRs for the wave (Plugins#1415, Reinsurance#170,
SocialMedia#138, Manufacturing#56, Crm#56). Filed at the release session's request against #3355's
blocker list; whether it blocks the tag is theirs to decide once the site count is visible.
Activity
rbuergi commentedon Sep 6, 2026
The generalised form — and a second instance, reproduced independently within the hour
The Education line in the description ("a fleet-wide gate keyed on
MW_IMAGE_DIGEST/MW_PLATFORM_SETwould report it compliant") is not a footnote to this issue's thesis. It is a second instance of it, and the general form is worth stating outright because it is what any gate added here must be falsified against:Instance 1 — the pin sweep (this issue).
grep -c MW_IMAGE_DIGESTover the fleet returns0for MeshWeaver.Education. That0does not mean "Education has no unpinned platform digest to worry about"; it means Education pins underMW_PORTAL_DIGEST/MW_MIGRATION_DIGEST/MW_TEST_DIGESTand the sweep checked none of its three pins. A fleet pin-consistency gate keyed on the common names would report Education compliant while verifying nothing — a gate that does not exist, wearing a passing tick, which is precisely this issue's thesis.Instance 2 — measured 2026-09-06, in the act of relaying instance 1. A sweep for the
publish-bakewebhook defect countedwebhook-url:occurrences per repo and read every0as "the caller omits it":Education's
0meant "there is no caller to omit it" — it runs a localpublish-bakewith noRegister the publication with memexstep at all. Without thereusable-callercolumn (the denominator), Education is indistinguishable from the four genuinely-broken repos. The corrected count is four, not five.That the same trap was walked into while relaying a warning about the same trap is the argument for encoding it in a gate rather than in guidance.
Why this belongs on this issue specifically
This issue is about gates that do not exist reading as gates that pass. The denominator failure is the mechanism by which that happens in a sweep: the numerator alone is a measurement whose negative is ambiguous, so a clean-looking
0is produced by both the compliant case and the never-examined case.It is also the same family as this fleet's standing rule that config audits go by LENGTH, never
keys[]— a key present with an empty value reads identically to an absent one. Same defect, different surface.Concretely, for whatever gate lands here: it must emit a per-repo denominator — "N pin sites found, of which M verified" — and fail RED on N = 0 rather than reporting a pass. A repo whose pins the gate cannot locate (because they are named differently, as Education's are) has not been checked, and "not checked" must not be spelled the same way as "clean". This is the same acceptance criterion the description already sets for the non-hex placeholder digest, applied one level up: there, a pin the regex cannot match reads as "no pin"; here, a repo the sweep cannot key on reads as "no findings".
rbuergi commentedon Sep 6, 2026
Requirement 2 of this issue is now covered fleet-wide by #3462 — requirement 1 is not
#3462 (the #3438 guard half) lands
.github/scripts/check-pinned-digests.py+ a dailypinned-digests.yml. Mapping it onto this issue's "What the gate would have to check":Set-consistency is a property of one repository's own workflow and stays this issue's ask.
meshweaver-cloudApp reaches — which is org-wide (repository_selection=all), so SocialMedia,Manufacturing and Crm are swept whether or not they ever gain a local gate.
sha256:PLACEHOLDERis a failure there,not an absence, and so is a truncated digest that
sha256:[0-9a-f]+would happily accept. Bothare asserted in a self-test that runs on every core PR.
One correction to the survey, measured against the live registry 2026-09-06
This issue's table is right that the three repos have no local gate. It is worth adding that
they do all pin, and that a fleet check keyed on variable NAMES would have reported them clean:
Manufacturing writes
MW_IMAGE_DIGEST, SocialMedia and Crm write theirs into a$GITHUB_OUTPUTstep output, and Education uses three names of its own. #3462 extracts by shape for that reason.
Live sweep, denominator printed — 8 scanned · 6 pin · 2 do not · 15 pin declarations over 9
distinct digests · 12 resolve · 3 GONE · 0 indeterminate · 0 malformed.
🚨 The 15-vs-9 gap is directly relevant to the "site counts are not uniform" section here. The
fleet pins 9 manifests from 15 places, so a pin move edits 15 sites, and the three GONE are
Education's —
#3438itself, still live onmainas of this comment:Education's bump has to move all three, not just the tester.
Not closing anything here — requirement 1 is untouched. Background:
Doc/Architecture/PinnedImageRetention.fix(#3454): the fleet set-consistency arm must not sit dead behind th…
fix(#3454): scope the same-name invariant to ONE FILE
chore(#3454): the docstring names every arm it runs, and _where drops…
docs(#3454): the i18n mirror's comparison ref is excluded STRUCTURALL…
docs(#3454): record where the extractor stops — an OMITTED platform-r…
rbuergi commentedon Sep 6, 2026
Closed by hand — all four parts are merged and each merge commit verified an ancestor of its repo's
mainThe merge queue does not fire
Closeslinks, so this is manual and the ancestry was measured, notassumed.
origin/maincac18fd9ce40c312a50966bdb4c4b93d1136b54c14c917e490091e9fe4c36523bb4de9da98aaca4dd9e2768cba6d415f28d3281ce10b21ec91ebcac8f0a2b031a005191070d619294bc85e5e974ad6baRED-then-GREEN in every repo — a gate nobody has watched fail is not a gate
Each satellite branch carried a deliberate half-move of ONE of its two
platform-image-digest:literals — the
publish-bakecopy, which never runs on a pull request, so nothing but the newpin-setjob could see it. This is the #3344 shape reproduced.Then restored, and
Platform pins name one buildis green on each repo'smain.The denominator, printed — and why "3" is the number, not "4 / 3 / 4"
platform-ref:🚨 The issue's "4 / 3 / 4 literal pin sites" and the extractor's "3 / 3 / 3" are counting different
things, and neither is wrong. The extractor's denominator counts literal digest pins; the
issue's figure adds the literal core-commit refs a pin move must also pass. Under that second
accounting SocialMedia is arguably 5, not 4 — it carries
MW_PLATFORM_REFand a literalplatform-ref:on itsnode-repo-module-packcall. The number CI now prints on every PR is the oneto reason with, because it is the one the verdict is computed from.
No unclassified pin in any of the three (I5 has nothing to report), and no pattern was widened to
make it so. All three jobs run with
--require-pins, so a ZERO denominator is RED (I6) — verifiedseparately against a tree with workflows and no pin: exit 1 with "not one literal platform pin was
found… zero means the extractor stopped matching, not that pinning stopped", versus exit 0 and
"a measured zero, not an unchecked one" without the flag.
Two premises the adoption corrected
The three repos are not variations of one shape. Two write the tester pin into a
$GITHUB_OUTPUTand one into anenv:key; one declaresMW_PLATFORM_REFand two do not; onepasses no literal
platform-ref:at all. So I3 and I8 have nothing to compare in Manufacturingtoday — and the printed denominator says so instead of the verdict quietly reading "consistent".
The gate could not be fetched at each repo's existing platform pin, because that value is
older than the script. Hence
MW_PIN_GATE_REF, a script-DEFINITION pin in the same category asa
uses: …@<sha>lane ref — and named so that I8 cannot see it: a guard ref matchingplatform.?refwould be read as a platform source ref and demanded a lane pinned at it, whichis exactly the coupling this gate refuses to assert (Plugins#1268).
🚨 A finding outside the issue's scope: Manufacturing had never run the platform's OTHER guards
check-workflow-timeouts.pyandcheck-pr-secret-preflight.pylive insidenode-repo-validate.yml. MeshWeaver.Manufacturing hand-rollsvalidateand does not call that lane,so neither had ever executed against it — while both siblings measured 0 violations the same day:
GitHub's default is 360 minutes against a fleet cap of 45. Capped in MeshWeaver.Manufacturing#58.
The transferable rule — a repository that keeps a hand-rolled copy of a shared lane silently opts
out of every guard that lane grows later, and nothing anywhere reports it — is the same shape as
the pin gate that did not exist, and is written up in #3502.
Branch protection updated in the same change set
Platform pins name one buildis now a required context on all three repos'main(each measuredfirst: all three are classic protection,
strict: false, their only ruleset being the Copilotreview — no ruleset carries required checks here). No context was RENAMED: a job was added, no lane
was adopted. The five open PRs that predate the job were each told, on the PR, that they need a
mainsync.Work products
Doc/Architecture/PinSetConsistency): the satellite lane's shape, whyMW_PIN_GATE_REFmust be invisible to I8, the per-repo difference table, and the hand-rolled-lanerule. Held as a draft on purpose — core
mainis inside a release wave and a docs mergeenqueues another CD run; take it out of draft when the release session says the wave has settled.
Platform pinssection in each satellite's ownAGENTS.md, carrying thatrepo's pin table, its denominator, and the grep-the-old-value move procedure.