Repository navigation
Availability confirms a CONSISTENT sealed set; the bake refuses a doubly-produced module (#3175) - #3187
Merged
Conversation
…bly-produced module (#3175) Every satellite release-follow gate declined four map galleries on 2026-09-03 ("'MeshWeaver.Maps' built against mvid:4d04617…, live is ref:1D8FDE5B…"): the portal host shipped MeshWeaver.Maps.dll in /app (ref:) while the Plugins bake composed it as a module (mvid:) — two producers of one assembly for one identity, no diff in any repo, nothing sealed, memex-cloud holding. The same morning memex-cloud rolled to ci.7621 on a presence-only verdict and declined SocialMedia at adoption ('MeshWeaver.Markdown.Collaboration' mvid:A vs mvid:B). Maps is a Plugins module only (maintainer, 2026-09-03: "move 100% to plugins"). - BakeHost.ShippedByHostProblem: a --module the host also ships in its app directory or surface manifest fails the bake RED by name, under --app and in-process (BakeAgainstPlatformHostTest.AComposedModuleTheHostAlsoShips_…). - PublishedBundleCatalogue.ArtifactsForIdentity reads each sealed source's module set (entry assembly MVID, PE header only) and every sealed bundle's dependency records (manifest only); ReleaseAvailability.IsUpdatable holds with PackageAvailabilityKind.SealedSetInconsistent when a record names a module build the identity's set does not carry or two sources sealed one module twice; an unreadable set is Indeterminate (SealedSetConsistencyTest). - Stale Maps remnants in core rewritten (Memex.Portal.Shared.csproj "DIRECT ON PURPOSE" block, compose-gate-host.sh fixture, gate lane, tester, CLI text). - Docs: ModuleBuildArchitecture "One producer per (module, framework identity)"; CandidateReleaseProtocol "Availability is a CONSISTENT sealed set"; What's New (Fix). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G4xPnGYEbdu8AVvR5jytyj
Contributor
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The core logic changes are coherent, regression-tested, and align with the stated incident/acceptance criteria; remaining notes are minor doc/perf nits.
Pull request overview
This PR hardens the plugin bake and release-availability gate to treat “availability” as a consistent sealed set: for a target framework identity, every sealed bundle’s dependency records must match the exact module builds sealed for that same identity, and the bake refuses producing a bundle when the host also ships an assembly with the same simple name (preventing “two producers” mismatches like the Maps incident).
Changes:
- Refuse bakes where a composed
--moduleassembly name is also shipped by the bake host (by surface manifest or app directory), preventing doubly-produced assemblies from being sealed. - Extend the release-availability observation to read the sealed module set (module bundle entry assembly → MVID) and per-NodeType dependency records, and gate updates on set consistency.
- Add targeted regression tests and update docs/fixtures to reflect the “one producer per (module, identity)” invariant.
File summaries
| File | Description |
|---|---|
| tools/MeshWeaver.PluginTester/TreeBake.cs | Applies the “two producers” refusal in in-process mode before baking. |
| tools/MeshWeaver.PluginTester/GateHostCheck.cs | Updates explanatory comment to remove stale Maps reference. |
| tools/MeshWeaver.PluginTester/BakeHost.cs | Introduces and enforces ShippedByHostProblem for both --app and in-process hosts. |
| test/MeshWeaver.PluginTester.Test/BakeAgainstPlatformHostTest.cs | Pins the “composed module the host also ships” refusal and avoids assembly-name reuse across tests. |
| test/Memex.Portal.Shared.Test/SealedSetConsistencyTest.cs | New suite pinning sealed-set consistency and indeterminate behavior. |
| src/MeshWeaver.PluginCatalog/ReleaseAvailability.cs | Adds set-consistency evaluation, new verdict kind, and supporting records (SealedModuleSet, BundleDependencyRecord). |
| src/MeshWeaver.PluginCatalog/PublishedBundleCatalogue.cs | Observes sealed bundles + module set + dependency records; reads module MVIDs from module bundles. |
| src/MeshWeaver.Cli/BuildPluginCommand.cs | Adjusts error text to remove stale Maps/.AI/.Indexing mention. |
| memex/Memex.Portal.Shared/Memex.Portal.Shared.csproj | Rewrites Maps-related comment to reflect post-move reality and the double-producer failure mode. |
| .github/workflows/node-repo-gate.yml | Updates workflow comment to clarify “portal-only assembly” examples over time. |
| .github/scripts/compose-gate-host.sh | Updates self-test fixture to avoid Maps-specific naming and keep intent intact. |
| src/MeshWeaver.Documentation/Data/WhatsNew/2026-09-03-an-update-is-held-when-its-packages-do-not-fit-together.md | Adds a user-facing “Fix” entry describing the new hold behavior. |
| src/MeshWeaver.Documentation/Data/Architecture/ModuleBuildArchitecture.md | Documents the invariant, the two controls, and the remaining “second producer in time” gap. |
| src/MeshWeaver.Documentation/Data/Architecture/CandidateReleaseProtocol.md | Updates protocol docs to define availability as a consistent sealed set. |
Review details
- Files reviewed: 14/14 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
This was referenced Sep 3, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Availability must confirm a CONSISTENT sealed set — one producer per (module, identity)
Closes #3175
Maps is a Plugins module only (maintainer, 2026-09-03: "all maps should be in plugins and removed from core — move 100% to plugins").
Root cause (measured 2026-09-03 07:21–07:33Z)
Every satellite release-follow gate failed its consumption postcondition — Reinsurance run 33727661313
adopted 236 of 240 … 4 DECLINED, Manufacturing 3372766185097 of 102 … 5 DECLINED:ref:is the surface-manifest scheme: the gate host — the portal's/app— SHIPSMeshWeaver.Maps.dlland lists it in its manifest.mvid:is the module scheme: the Plugins bake COMPOSED Maps with--module(the id resolver puts modules first). Two producers of one assembly for one identity: the portal host in MeshWeaver.Plugins (Memex.Portal.Gui.csproj) had kept a directProjectReferencetosrc/MeshWeaver.Mapsfrom before Maps became a Store module (core #2941 / Plugins #1057). Core itself already carried no Maps project, no reference and noContentSurfaceAssembliesentry — only stale comments and a self-test fixture claiming otherwise. Nothing had changed in any repo; no satellite could seal; memex-cloud held at ci.7652 ("no sealed content bake").The same morning memex-cloud (ci.7621) declined
SocialMedia/Post|PostsHub|Profile—'MeshWeaver.Markdown.Collaboration' built against mvid:A, live is mvid:B— because the availability gate checked PRESENCE of a sealed bundle, not CONSISTENCY of the set (#3175's finding).What this PR does (core half)
BakeHost.ShippedByHostProblem, applied under--appand in-process: a--modulewhose simple name the host also ships in its app directory or lists in its surface manifest fails the bake RED ("two builds of one assembly name in one bake … remove the assembly from the platform host's closure or stop composing it"). Pinned byBakeAgainstPlatformHostTest.AComposedModuleTheHostAlsoShips_IsRefusedByName.PublishedBundleCatalogue.ArtifactsForIdentitynow reads, for the candidate identity, every complete source's sealed module set (each module bundle's entry assembly → MVID, PE header only) and every sealed bundle's per-NodeType dependency records (manifest only).ReleaseAvailability.IsUpdatablethen holds with the newPackageAvailabilityKind.SealedSetInconsistentwhen a record names a module build the set does not carry, or two sources sealed one module at two MVIDs — naming bundle, NodeType, module and both builds. An unreadable module set isIndeterminate(hold, named); a module outside the set is not judged. Consumed unchanged by the self-update poll, CD's post-promote assertion and/api/plugins/is-updatable. Pinned bySealedSetConsistencyTest(8 cases, both failure directions).Memex.Portal.Shared.csproj(the "DIRECT ON PURPOSE" block described a reference that no longer exists and would have sent the next reader to re-add it),compose-gate-host.shself-test fixture,node-repo-gate.yml,GateHostCheck.cs,BuildPluginCommand.cserror text.ModuleBuildArchitecture.md→ "One producer per (module, framework identity)" (the incident table, the two controls, and what the gate still cannot see);CandidateReleaseProtocol.md→ "Availability is a CONSISTENT sealed set". What's NewCategory: Fix.Deliberately not in this PR
MeshWeaver.AI/MeshWeaver.Markdown.Collaboration: core CD'splugins-modulesrebuilds them per release to feed the Plugins seal while the registry's package endpoint serves the Plugins lane's content-versioned build — the bytes a portal installs. Core holds no registry credential (MW_REGISTRY_KEYis not among its secrets), so its bake cannot compose the registry's bytes today; the alternative is the instance adopting module bytes for its identity from the sealed publication. The new gate now HOLDS on the set it can see rather than rolling; the remaining gap is documented in ModuleBuildArchitecture.publish-bake-bundles.sh: a single bake's set is consistent by construction against its own composed modules once (1) refuses the double; cross-source consistency is asserted by (2).Counterpart
Counterpart (independent halves, either order merges cleanly): Systemorph/MeshWeaver.Plugins#1242 — drops the
MeshWeaver.Mapsproject reference fromMemex.Portal.Gui/MeshWeaver.AI.Testand makes AppleMaps/GoogleMaps/OpenStreetMap/CornerstonerequireMaps. No public type leaves core in this PR.Acceptance
The next Reinsurance release-follow gate after both halves are in the promoted set adopts N of N (
seed: adopted 240 of 240— the control arm was run 33623801785). Verified locally:Memex.Portal.Shared.Test622/622,MeshWeaver.PluginTester.Test319/319,MeshWeaver.Documentation.Test239/239, all-c Release -warnaserror.🤖 Generated with Claude Code
Claude-Session: https://claude.ai/code/session_01G4xPnGYEbdu8AVvR5jytyj