Repository navigation
A core change in b88be8a05..c41a34fd breaks the plugin-catalog card render — caught only by a test in another repo #3276
Description
A core change in b88be8a05..c41a34fd breaks the plugin-catalog card render — and core CI cannot see it
Two tests go red when the core commit under test advances across this range, and are 6/6 green at the old end:
MeshWeaver.PluginCatalog.Test.CatalogRenderTest.Catalog_ListsPackagesFromGitSource_AsCards
MeshWeaver.PluginCatalog.Test.CatalogRenderTest.ALandedModule_PutsTheRestartNoteOnItsPackageCard
| Good | core b88be8a058689e216f0df20e795cde121da0a365 |
| Bad | core c41a34fd |
| Range | 48 commits (git rev-list --count b88be8a05..c41a34fd = 48) |
| Subject under test | src/MeshWeaver.PluginCatalog/ — this repo's code |
| Where the test lives | Systemorph/MeshWeaver.Plugins, src/MeshWeaver.PluginCatalog.Test/CatalogRenderTest.cs |
🚨 Why this is worth a ticket rather than a note
The test that catches it is in another repository, so nothing in this repo's CI runs it. MeshWeaver.PluginCatalog is compiled and shipped from here; its card-rendering behaviour is asserted only over in MeshWeaver.Plugins, by a job (Portal hosts) that checks core out at whatever MW_PLATFORM_REF names. So:
- every one of these 48 commits was merged green here;
- the breakage becomes visible only when a satellite deliberately advances its pin;
- and it then presents as "my pin bump is red", which reads like the bumper's problem and is not.
This is the shape recorded in Doc/Architecture/ and in the fleet's own history as a test that is never executed before merge. The Dependent suites (MeshWeaver.Plugins) gate exists for exactly this class — worth checking whether it covers MeshWeaver.PluginCatalog.Test and, if it does, why this got through; if it does not, that is the actionable gap and it is bigger than the two tests.
How it surfaced
Found by the session landing MeshWeaver.Plugins#1268. It moved MW_PLATFORM_REF and the two node-repo-module-pack.yml@<sha> refs together b88be8a05 → c41a34fd, and the two tests went red. The landed workaround splits the pins (uses: on c41a34fd for the workflow definition, MW_PLATFORM_REF held at b88be8a05 for the source) — correct for unblocking a module move, and explicitly not a fix for this:
Whatever broke those two PluginCatalog tests among the 48 commits is still out there and will bite the next core-pin bump. That is a real follow-up, with a bisect as its whole job.
So the pin is held back today. It cannot stay held; the next bump meets this again.
What to do
- Bisect the 48. The range is small and the signal is binary, so this is a short job. Run the two tests against core commits in
b88be8a05..c41a34fd— the PluginsPortal hostslane already does exactly this, parameterised byMW_PLATFORM_REF. - Fix the cause in
src/MeshWeaver.PluginCatalog/— or, if the behaviour change was deliberate, update the assertions in Plugins in the same change set and say so, since a deliberate change to card rendering that nobody told the dependent repo about is the same defect wearing a different hat. - Close the visibility gap, which is the durable half: either the dependent-suites gate must cover
MeshWeaver.PluginCatalog.Test, or this repo needs its own coverage of the catalog card render. Right now a change here can break a shipped surface and go green.
🚨 Do not "fix" this by relaxing the two assertions, and do not fix it by keeping the pin back — the second is what is happening now by necessity, and it converts a code defect into a permanent pin freeze.
Refs: Systemorph/MeshWeaver.Plugins#1268, #3259 (the repo tests one core and ships another — same family: what is tested and what is shipped are different objects).
Activity
rbuergi commentedon Sep 4, 2026
Bisected:
c521f929e— the catalog's landing stopped rendering cards on purposeCase 2 of the two: a deliberate behaviour change, not a regression in
src/MeshWeaver.PluginCatalog/.Both ends reproduced first, then the range narrowed
A fresh
MeshWeaver.Pluginsclone atmain(which still holdsMW_PLATFORM_REF = b88be8a05), builtwith
-p:MeshWeaverRoot=pointed at a real core worktree — never the default sibling, which wouldhave measured the stale primary checkout.
CatalogRenderTest+RestartRequiredCardTestb88be8a058689e216f0df20e795cde121da0a365a2b312d9f97ad19cc1^1— main immediately before the merge97ad19cc1c521f929e)c41a34fdThe 48 commits are 13 merges on the first-parent path; sandwiching the candidate merge pins it to
one. Independent corroboration that needs no test run:
c521f929eis the only commit of the 48that touches
src/MeshWeaver.PluginCatalog/at all —git diff --stat b88be8a05..c41a34fd -- src/MeshWeaver.PluginCatalog/is one file,CatalogLayoutAreas.cs, +366/−45.The mechanism
Both tests render
new LayoutAreaReference(CatalogLayoutAreas.CatalogArea)— no parameters — andwait for the returned
StackControlto carry/pkg-*sub-areas.c521f929emade that page the category landing.RenderFromSourcenow reads the area referencefirst and branches on a
CatalogPlan; the landing branch composes nothing but the source's manifestlisting and calls
BuildLanding, whose areas aresource+categories(holdingcat-1…cat-nandall). The commit says so in its own words — "The landing'sCatalogPlan.Packagesis EMPTY byconstruction — that is the statement 'read no install record for this page'" — and the flat list
moved behind
?all=true, which is where the landing's own "All packages" tile navigates.So the tests do not fail an assertion; they wait 60 s for a card on a page that no longer has one and
fail as a timeout. The failure text is exactly that: "Last of 5 emission(s) was: StackControl { … }"
— the page renders fine, it just has no
pkg-area.Why "deliberate" and not "regression"
c521f929eshipped with core-side coverage of the new shape:test/Memex.Portal.Shared.Test/CatalogCategoryFirstTest.cs(350 lines, added by the same commit) —the landing renders tiles and no card while an install record exists on the mesh, a category page
renders exactly its members with the installed one reading as installed, and an empty catalog renders
the localized empty state, all through the real
GetRemoteStreamrender path. It even names thisrepo's test in a comment. So point 3 of this issue is already half-satisfied: core is not without
coverage of the catalog card render — it gained it in the very commit that broke the dependent.
The visibility gap is real, but it is not the one this issue assumed
It does not exist.
dependent-suites.ymllanded on 2026-09-03 08:46 (b37225497, #3103) and waswithdrawn the same morning at 09:56 (
7c27f3e95) on a maintainer directive — "none of thetop-level repos should have any dependency to anyone else"; "it must be event based" — because it
put a context on every core PR that only Plugins could turn green.
c521f929elanded at 20:14 thatevening, ten hours after the withdrawal. Measured, not remembered: no
Dependent suitesjob existsin any core workflow, and
gh api repos/Systemorph/MeshWeaver/commits/main/check-runslists no suchcontext. AGENTS.md still instructed you to read it — that stale sentence is fixed in the PR below,
because an absent required context reads as green.
And the
Cross-repo pair (public surface)gate could not have seen this either: it fires on publictypes and members leaving, and
c521f929eremoved nothing. It passed on #3258, correctly.The actual shape, which no existing mechanism covers
A public method's BEHAVIOUR changing behind an UNCHANGED signature.
RenderFromSourcehas thesame name and the same parameters before and after; it simply answers differently. No surface
detector can see that, by construction.
The documented answer is the event-based one — "a shape-1…6 break surfaces as a red release-follow
run in the dependent's repository, minutes after the platform published". That is over-claimed for
a dependent that pins. MeshWeaver.Plugins pins core deliberately (its own #1255), and its
platform-refjob resolves the sameMW_PLATFORM_REFon arepository_dispatchrelease event ason a pull request — the event changes what is baked, not what
src/compiles against. So therelease-follow run rebuilds Plugins against the commit it already used, and a break introduced after
the pin is invisible to it until a human bumps the pin. That is why this presented as "my pin bump
is red", and why it took 48 commits to surface.
That is not an argument for unpinning — the pin was bought with a real incident. It is an argument
for saying it out loud: for a dependent that pins, the pin bump IS the integration test, and the
cost of a break scales with how long the pin sat.
What is being done
?all=truepage, which is wherecards live now. Nothing is relaxed: the same two cards are still required to render, and the
restart note is still required to reach one of them through
ModuleLandingService.ActivationChangedwhile the area is subscribed. The id is a literal andnot
CatalogLayoutAreas.AllParam, because that constant does not exist at the pin this repocurrently holds — which is what lets the fix land before the pin moves instead of with it.
CrossRepoPairGate.md, thepinned-dependent correction, and AGENTS.md no longer telling you to read a check that was
withdrawn.
🚦 Can
MW_PLATFORM_REFmove forward?Yes, once #1315 merges — these two tests are no longer a reason to hold it. Measured with
-c Release -warnaserror --no-incremental, one project per invocation:The second line also rules out a second break in the range: the fixed tests are green at the far
end, not merely at the near one. Scope note — this measures
MeshWeaver.PluginCatalog.Testonly;the rest of the
Portal hostslane atc41a34fdis the pin-bump PR's own job to prove, and that PRis owned elsewhere. The pin was not touched here.
rbuergi commentedon Sep 4, 2026
This is now the critical path for at least four other fixes — measured 2026-09-04
Filing this as priority context, not new analysis. MeshWeaver.Plugins is holding
MW_PLATFORM_REFatb88be8a058689e216f0df20e795cde121da0a365because of this issue — Plugins#1268 split its pins deliberately (uses:refs forward for the workflow definition,MW_PLATFORM_REFheld back for the source) precisely because advancing the source across these 48 commits reddens the twoCatalogRenderTestcases.What that held pin now blocks, verified by ancestry against the live pin rather than inferred:
main, but CI on the pin is red withCS0117: 'NotificationService' does not contain a definition for 'BellQuery' / 'PlatformAddressee'. Core landed the write side; the reader cannot compile until the pin moves.CodeViews.IsOutputStalelives in Plugins;OutputCurrency()is not at the pin.isGlobalAdminfield is 7 hits on coremain, 0 at the pin.So the cost of this issue is no longer "two red tests on a pin bump" — it is that four landed core fixes cannot reach the portal, and the two notification issues had to be REOPENED today after the write half alone was mistaken for the whole fix.
🚨 The tempting shortcut is to bump the pin and accept two red tests, or to relax the two assertions. Both are wrong for the same reason:
Portal hostsis a REQUIRED context in Plugins, so a knowingly-red pin bump either blocks every subsequent Plugins PR or gets the assertions weakened to unblock it — and the second permanently removes the only coverage core has of the catalog card render, which is what let 48 commits merge green in the first place.The bisect is the unlock, and it is a short job: 48 commits, a binary signal, ~6 steps.
Nothing here changes the diagnosis in the issue body; it changes the priority.
rbuergi commentedon Sep 4, 2026
Fixed and merged — the pin is free
Systemorph/MeshWeaver.Plugins#1315 is merged (
df7950df).MW_PLATFORM_REFis no longer heldby these two tests.
The bisect, restated with its evidence
b88be8a05— the held pina2b312d9f=97ad19cc1^197ad19cc1— the merge of #3258, commitc521f929ec41a34fdc521f929eis also the only commit of the 48 that touchessrc/MeshWeaver.PluginCatalog/.Deliberate behaviour change, not a regression: the catalog landing now renders category tiles
and, by construction, no package card; the flat list moved behind
?all=true. It shipped withcore-side coverage of the new shape in the same commit
(
test/Memex.Portal.Shared.Test/CatalogCategoryFirstTest.cs), so this repo is not withoutcoverage of the catalog render — that premise in the description is out of date.
The fix relaxes nothing: the same two cards are still required to render, and the restart note is
still required to reach one of them through
ModuleLandingService.ActivationChanged. Only the pagethey open moved. The id is a literal rather than
CatalogLayoutAreas.AllParam(which does not existat the held pin), so it is green against both cores and could land before the pin moves.
🚦 Can the pin move? Yes — measured wider than the two tests
and the whole
Portal hostsgraph — all 48 suites plus their closure, one solution,-c Release -warnaserror -p:ShouldUnsetParentConfigurationAndPlatform=false— builds clean againstc41a34fd:0 Warning(s) 0 Error(s). So there is no compile break anywhere in the 48, and thegreen-at-the-far-end test run rules out a second behavioural break in these two. Scope kept honest:
that measures compilation of the other 47 suites, not their execution — the pin-bump PR still owns
that, and the pin was not touched here.
The visibility gap — corrected, and it is not what the description assumed
Dependent suites (MeshWeaver.Plugins)gate.dependent-suites.ymllanded2026-09-03 08:46 (
b37225497, Cross-repo pairs: four shapes the surface gate cannot see — the answer is triggering the dependent's suite, not a wider detector #3103) and was withdrawn at 09:56 the same morning (7c27f3e95)— ten hours before
c521f929e. Measured: no such job in any core workflow, no such context onany
maincheck-run listing. AGENTS.md still told readers to look for it (now corrected by docs(AGENTS.md): name the gate that exists, not the one that was designed #3280).c521f929eremoved nothing, so it passed on feat: the Store opens with categories and loads plugins per category #3258 correctly.can see by construction.
platform-refjob applies the sameMW_PLATFORM_REFon arepository_dispatchrelease event ason a PR — its
ci.ymlsays "Every GATE reads it, unchanged", while only the bake follows therelease. For a dependent that pins, the pin bump IS the integration test, and the cost scales
with how long the pin sat: 48 commits here.
The documentation half is #3285 (shape 7 in
CrossRepoPairGate.md+ the pinned-dependentcorrection). Its own checks were 27/27 green, but the merge queue dequeued it on an unrelated
fleet-wide failure: four satellites opened a
rest-not-graphqlshared-rule block that core's.github/shared-rules.jsondoes not declare, which hasAGENTS.md shared rule blocksred on coremainsince 07:37Z and is blocking every core merge. #3285 needs re-arming once that is fixed inthe repo the error names.
Closing this: the break is bisected, the cause is named, the fix is merged, and the pin is free.