Skip to content

The gate can load a module built outside its image — the seam that lets source leave core (#2276) - #2541

Merged
rbuergi merged 3 commits into
mainfrom
feat/2276-gate-loads-external-modules
Aug 27, 2026
Merged

rbuergi merged 3 commits into
mainfrom
feat/2276-gate-loads-external-modules

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Why

A module's delivery (image vs registry) and its source location (platform repo vs node repo) are independent properties. We flipped AI's delivery today; its source could not follow, and neither can MeshWeaver.Maps, for one reason:

The bake host builds what it needs from the platform checkout. It can land a module the way a portal does — a tester-local MeshModuleClosure row — only while that module's source is still in this tree.

The gate judges a node repo's content, and that content declares node types a MODULE provides (an Agent/Skill node needs the AI engine's types registered, or the install is refused "not registered"). Once the source moves, the platform image cannot build those bytes, and the only build of them is the one the node repo's own CI just produced.

What

--module <dll>, repeatable, on mw-plugin-test:

  • each path joins both Modules:Assemblies (activation) and Modules:Required (the loud half), so an absent one fails RED before the mesh boots — never a gate that quietly ran without it and then blamed the content for every refused install;
  • absolute paths pass through ResolveModulePath untouched, so a mounted module can never be silently substituted by a same-named copy inside the image (the A view-pack fix can merge, build and deploy while the portal keeps loading an older copy of that pack #2223 shadowing class, one level down);
  • every external module is echoed at startup, because a run that loaded none must not look like a run that loaded them.

Consumer side (next change, in MeshWeaver.Plugins): the gate job mounts the modules job's freshly built bundle and passes --module. Then src/MeshWeaver.AI can leave core.

Tests

ExternalModuleGateTest (3): absolute paths resolve exactly as given (never probed); external modules carry through GateOptions; MissingRequired names an absent external module. Plus the existing 91 MeshWeaver.PluginTester.Test cases still green.

Docs

Modules.md gains the AI engine's inventory row and a Deciding section written as mechanism, not history: delivery vs source as independent properties, the structural reasons some modules must stay image-shipped (storage bootstrap, middleware order), why the two activation lists are mutually exclusive for one name (ComputeEffectiveModuleEntries dedupe + the landing 409), why a host with no plugin catalog (Memex.LocalMesh) cannot use the registry lane at all, and the ordering rule the carve-out follows.

Doc link/embed integrity gates pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tz1i2fFcJhvR1Eje8yFH5F

…ts source leave core (#2276)

A module's DELIVERY and its SOURCE location are independent, and only the
first was solvable before now. The bake host (mw-plugin-test) judges a node
repo's content, and that content may declare node types a MODULE provides —
an Agent or Skill node needs the AI engine's types registered or the install
is refused "not registered". While the module's source sits in core, the
tester lands it from its own closure lane. The moment the source moves to a
node repo, the platform image cannot build those bytes at all, and the only
build of them is the one that repo's CI just produced.

`--module <dll>` (repeatable) is how that build reaches the gate. Each path
joins Modules:Assemblies AND Modules:Required, so an absent one fails RED
before the mesh boots rather than booting a gate that then refuses every
install needing the module and blames the CONTENT. Absolute paths pass
through ResolveModulePath untouched, so a mounted module can never be
silently substituted by a same-named copy in the image (the #2223 shadowing
class). Every external module is echoed at startup — a run that loaded none
must not look like a run that loaded them.

This unblocks moving src/MeshWeaver.AI (and later MeshWeaver.Maps) out of
core: the plugins gate mounts its own freshly built module instead of
depending on the platform image to have built it.

Docs: Modules.md gains the AI engine's inventory row and a "Deciding" section
that states the model rather than the history — delivery vs source as
independent properties, why the two activation lists are mutually exclusive
for one name, why a host without a plugin catalog (Memex.LocalMesh) cannot
use the registry lane, and the ordering rule the whole carve-out follows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tz1i2fFcJhvR1Eje8yFH5F
Copilot AI lite review requested due to automatic review settings August 27, 2026 20:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for loading externally-built module entry assemblies into the mw-plugin-test gate run, enabling node-repo CI outputs to be used for type registration during gating even when module source moves out of the platform repo.

Changes:

  • Add repeatable --module <dll> CLI option and surface it through GateOptions into gate mesh boot configuration.
  • Activate external modules by injecting them into both Modules:Assemblies and Modules:Required, and echo configured external modules at startup for traceability.
  • Add targeted tests for the external-module seam and expand module documentation to cover delivery vs source decisions.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
tools/MeshWeaver.PluginTester/Program.cs Parses --module, validates existence, and passes external module paths into gate options while logging them.
tools/MeshWeaver.PluginTester/PluginGateRunner.cs Threads external module entries into gate mesh configuration and required-module validation.
test/MeshWeaver.PluginTester.Test/ExternalModuleGateTest.cs Adds tests around module-path resolution and required-module missing detection.
src/MeshWeaver.Documentation/Data/Architecture/Modules.md Documents AI module inventory entry and adds a “Deciding” section about delivery vs source location.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

1 606 tests  +5   1 605 ✅ +5   10m 5s ⏱️ +6s
    9 suites ±0       1 💤 ±0 
    9 files   ±0       0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 088 tests  ±0   896 ✅ ±0   5m 11s ⏱️ -8s
    6 suites ±0   192 💤 ±0 
    6 files   ±0     0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

1 312 tests  ±0   1 312 ✅ ±0   6m 16s ⏱️ +23s
    6 suites ±0       0 💤 ±0 
    6 files   ±0       0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

    8 files  ±0      8 suites  ±0   11m 12s ⏱️ -6s
4 417 tests +5  4 414 ✅ +5  3 💤 ±0  0 ❌ ±0 
5 022 runs  +6  5 019 ✅ +6  3 💤 ±0  0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

1 113 tests  ±0   1 113 ✅ ±0   18m 41s ⏱️ + 5m 33s
    7 suites ±0       0 💤 ±0 
    7 files   ±0       0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

739 tests  ±0   735 ✅ ±0   7m 17s ⏱️ -3s
  8 suites ±0     4 💤 ±0 
  8 files   ±0     0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    44 files  ± 0      44 suites  ±0   58m 43s ⏱️ + 5m 43s
10 273 tests +10  10 073 ✅ +10  200 💤 ±0  0 ❌ ±0 
10 880 runs  +11  10 680 ✅ +11  200 💤 ±0  0 ❌ ±0 

Results for commit 134ec38. ± Comparison against base commit 9028de3.

♻️ This comment has been updated with latest results.

rbuergi and others added 2 commits August 27, 2026 22:56
…t review)

- ExternalModules_JoinBothActivationLists asserted only that GateOptions
  carries the paths. Renamed to say that, and it now checks the paths arrive
  VERBATIM and in order — rewriting one is how a mounted module gets silently
  replaced by a same-named copy in the image. The Required half is covered by
  MissingRequired_NamesAnAbsentExternalModule; the end-to-end fold by the gate
  suites that boot a mesh with the engine activated.
- "NEVER under Modules:Assemblies" contradicted the very next paragraph
  (LocalMesh keeps the engine in its app closure) and the module's own
  guidance. Scoped to catalog-enabled deployments, with the LocalMesh case
  named: the rule is about not listing it in BOTH lanes, not about one lane
  being wrong.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tz1i2fFcJhvR1Eje8yFH5F
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.

2 participants