Skip to content

Hold an unmet dependent back at its previous generation instead of refusing the whole landing wave - #6462

Closed
systemorph-com[bot] wants to merge 3 commits into
mainfrom
bugfix/systemorph-meshweaver-6192
Closed

systemorph-com[bot] wants to merge 3 commits into
mainfrom
bugfix/systemorph-meshweaver-6192

Conversation

@systemorph-com

Copy link
Copy Markdown
Contributor

What changed

ModuleLandingService.ProposeCheckedModuleSet no longer refuses the WHOLE landing wave when a declared dependency floor is unmet. The new ModuleSetHoldBack.Plan holds back only the dependent whose floor is unmet, at its previous generation (ModuleActivationEntry.PreviousDirectory, the generation the mesh ran before the landing), and the rest of the wave is proposed through the new ModuleSetStore.ProposeGenerations. It still refuses when the dependent has no previous generation on the volume, or when holding it back would break another installed package's declared requirement.

Why

Measured on memex on 2026-10-06: OpenAI 1.5.9 declares AI@^1.23.0 while the landed set carries MeshWeaver.AI at 1.21.1. The guard (#6067) refused the entire wave, so every module that landed beside OpenAI waited, and every reconcile (boot, the module-published broadcast, the 30-minute safety net) re-landed nothing new and logged the same error again (7 lines on 3 pods). The module lane cannot prevent the skew itself: the consumer index entry carries no requires, there is no per-adopt range check, and the registry's ModulePublish.Validate never reads requires. Publish-side atomicity of AI and OpenAI lives in MeshWeaver.Plugins CI (.github, not writable from this branch) and stays a separate person's change.

How tested

New ModuleSetHoldBackTest in test/Memex.Portal.Shared.Test (the existing home of the #6067 floor tests; test/MeshWeaver.PluginCatalog.Test does not exist at main): OpenAI 1.5.9 requiring AI@^1.23.0 beside AI 1.21.1 holds only OpenAI back at 1.5.8 and proposes AI and an unrelated module as landed; the held set is written once; the wave is still refused when OpenAI has no previous generation; and still refused when a held-back OpenAI 1.5.8 would break another package's OpenAI@^1.5.9. CI is the build; the Architecture page ModuleSetConvergence.md gets the conserved finding in a follow-up commit on this branch.

Scope note: the fix needed one new test file under test/Memex.Portal.Shared.Test and the documentation page, beside src/MeshWeaver.PluginCatalog.

Refs #6192


Refs #6192
Bug-Thread: Hosting/Triage/_Thread/bug-systemorph-meshweaver-6192

Opened by Dispatch's control plane on behalf of Essentials/Agent/bug-triage (auto · Provider/OpenRouterEU/anthropic/claude-sonnet-5.5), from the bug's own branch bugfix/systemorph-meshweaver-6192. It is never merged by Dispatch: the merge is the governed activity dev.merge, signed by a person once the checks and the internal review are green.

… test

The checked proposal holds back only the dependent whose declared floor is unmet, at the previous generation the mesh ran, and proposes the rest of the wave. It still refuses when the dependent has no previous generation or when holding it back breaks another package's requirement.

Refs #6192
@github-actions

Copy link
Copy Markdown
Contributor

Test Results

   12 files     12 suites   35m 7s ⏱️
7 432 tests 7 432 ✅ 0 💤 0 ❌
7 444 runs  7 444 ✅ 0 💤 0 ❌

Results for commit de54c9f.

@rbuergi

rbuergi commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Verdict: mitigation of the symptom, and unsafe as written. Recommend closing unmerged.

Judged against AGENTS.md, "No band-aids: root cause only". Read: the PR body, #6192 with all comments, the diff at de54c9f2, and ModuleActivation.cs on this branch. Nothing was built or run; the defect below is from reading the code.

The root cause is elsewhere, and this PR says so. #6192: "The refusal itself is the guard working as intended; the defect is that an unsatisfiable bundle became visible." That is publish-side: a package's install record declares a floor its dependency's shelf does not meet yet. It is still live and it is not one pair: #6192 now counts over 4,000 refusals across OpenAI/AI, Hosting/AI, AppleMaps/Maps and Governance/Essentials (latest update 2026-10-11). This PR leaves that untouched and changes what the consumer does about it.

What it would hide. The refusal is LogError, which is how #6192 exists at all. The hold-back is LogWarning. After this change a skewed publication no longer reaches the incident log wherever the dependent has an earlier generation on the volume, which is the usual case. The cause would keep occurring with nothing counting it.

The defect: the generation it holds back at is not the one the mesh ran, and its floors are never checked. The plan uses ModuleActivationEntry.PreviousDirectory and describes it as "the generation the mesh ran before the landing". ModuleActivation.cs derives that slot from the landing records (the fallback selection, around line 1525): among every landed generation that is not the head, the one that is present, then linkable, then the highest version. It is the boot fallback slot, not a record of what was adopted.

#6192's own sequence shows the consequence. OpenAI 1.5.9 landed on 2026-10-06 by 06:54Z and OpenAI 1.6.2 by 17:24Z, both requiring AI@^1.23.0, with AI at 1.21.1 throughout. With 1.5.8, 1.5.9 and 1.6.2 on the volume the head is 1.6.2 and the fallback slot is 1.5.9. ModuleSetHoldBack.Plan holds OpenAI at 1.5.9 and proposes OpenAI 1.5.9 beside AI 1.21.1. That is the set #6067's guard was added to refuse, and the shape that fails at run time with MissingMethodException (#6007). The install record carries only the head version's requires, so the held generation's own floors cannot be checked here; the second loop in Plan checks other packages' floors against the held version, never the held version's own. ModuleSetHoldBackTest lands exactly one earlier generation in every case, so it cannot see this.

The same slot can also hold a generation newer than the one that runs (a shelved landing built for a newer platform competes for it, per ModuleAdoptionPolicy.md), and the plan would propose that too.

Why I did not repair it. A sound hold-back needs each landed generation's own requires recorded with it, and the held generation taken from the adopted set and not from the fallback slot. That is a design change to the landing record, not a review fix, and it would still be a mitigation.

Root-cause work and where it is tracked.

  • A dependency network publishes atomically, or the registry refuses a bundle whose requires the shelf does not satisfy (the PR body notes ModulePublish.Validate never reads requires). That is MeshWeaver.Plugins' publish lane. I found no open Plugins issue for it (one REST search, so read that as "not found", not "none"); OpenAI 1.5.9 bundle is served requiring AI@^1.23.0 while only AI 1.21.1 is served with it — landed module set refused wholesale #6192 is the tracking issue until one exists.
  • The repeat of the same error line on every reconcile (boot, broadcast, 30-minute pass) is a real second finding in the PR body. It is a small change of its own: log the refusal once per distinct unmet set. It should not ride on a change to what gets proposed.

State of this PR. The only red is Automatic review answered: there is no review and no review thread on this head, so there is nothing to answer. I have not pushed, closed or armed anything.

Review by Claude Opus 5.5 (agent session, tag bot1).

@rbuergi

rbuergi commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Closing on the maintainer's go (2026-10-11): band-aid per AGENTS.md, and unsafe as written — the cause is publish-side (a bundle visible before its dependency network, #6192), the change downgrades the refusal from Error to Warning, and the 'previous generation' it holds at is the highest present non-head generation whose own floors are never checked. Root cause stays on #6192. Verdict: #6462 (comment)

@rbuergi rbuergi closed this Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant