Repository navigation
fix(modules): a module type is served from the modules wherever it is asked — provider catalogs and chat-client factories reach MeshWeaver.AI (reviews down) - #6206
Merged
Conversation
… asked — provider contributions reach MeshWeaver.AI, the mesh hub and dependents Since #6127 each module's services live in a container of their own, and a type a module DECLARES was served only inside that container: - a dependent module's registrations of it (every AI provider's LanguageModelCatalogSource / IChatClientFactory) went to the root as forwarders the declaring module never consulted — and a root DispatchProxy over a collectible interface cannot even be built; - the root (mesh hub) and other module containers could not resolve it at all. On the control instance the Provider import listed only platform nodes, Provider/OpenRouterEU had 0 models, "No IChatClientFactory is registered", and every PR review stopped. Now: a registration of another module's type routes Contributed (never into the root); ModuleServices.RegistrationsElsewhere answers a module type with the declaring module's registrations plus every contribution; the root serves it through ModuleOwnedRootSource (replacing the per-node forwarders, which it subsumes) and other module containers through ModuleFallbackSource. ModuleContributionsCrossContainersTest pins four directions; all four fail on the previous code. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
Test Results 22 files ±0 22 suites ±0 43m 56s ⏱️ - 1m 24s Results for commit 456b994. ± Comparison against base commit b437e46. This pull request removes 40 and adds 20 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
Contributor
Contributor
Contributor
Test Results (shard 3)2 339 tests ±0 2 339 ✅ ±0 5m 49s ⏱️ -30s Results for commit 456b994. ± Comparison against base commit b437e46. This pull request removes 3 and adds 1 tests. Note that renamed tests count towards both. |
Contributor
Contributor
Contributor
Test Results (shard 4) 4 files ±0 4 suites ±0 16m 8s ⏱️ -47s Results for commit 456b994. ± Comparison against base commit b437e46. This pull request removes 37 and adds 19 tests. Note that renamed tests count towards both. |
rbuergi
added a commit
that referenced
this pull request
Oct 6, 2026
Conflicts with #6202/#6206 (module types served from the modules wherever asked): - ModuleServiceForwarders.AddModuleOwned: main replaced the per-node forwarders with ModuleOwnedRootSource; this branch had taught them keyed registrations. Taken main's deletion and carried the keyed half into the root source: a KeyedService for a type a module declares is answered by key (ModuleServices.KeyedRegistrationsElsewhere). - ModuleServices.Scope: Contributed joins the index-keyed routes, and a keyed registration keeps its own key on every route (both intents). - RegistrationsElsewhere never counts a keyed registration among a type's unkeyed positions (ResolveAt would point past the end) nor serves a keyed contribution as an unkeyed one. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Why (sev:B: PR reviews are down fleet-wide)
Since #6127, each module's services run in their own container. A type that a module declares was served only inside that module's container. On memex.systemorph.com (the control instance) every replica's Provider import has listed only the 9 platform nodes since 07:10Z.
Provider/OpenRouterEUhad 0 models, the control logged "No IChatClientFactory is registered", and the review lane had no model.There are three defects, and all three are reproduced in
ModuleContributionsCrossContainersTest. It runs two real Roslyn-emitted modules in a real mesh: a hub module shaped likeMeshWeaver.AIand a provider module shaped likeMeshWeaver.AI.OpenAI.MeshWeaver.AI'sLanguageModelCatalogSourceandIChatClientFactory. Those registrations went into the root as forwarders. The AI container's fallback refuses to ask the root about its own types. A rootDispatchProxyover a collectible interface cannot even be constructed:A non-collectible assembly may not reference a collectible assembly.ChatClientCredentialResolverand the catalog throughHub.ServiceProvider, which is the mesh hub.Fix (core)
ModuleServiceRoute.Contributedroute. It covers a registration of a type that another module declares. Such a registration is never placed in the root.ModuleServices.RegistrationsElsewhere. For a type a module declares, it returns that module's own registrations (viaResolveAt, one per registration), followed by every contribution from other modules, all from the current generations.ModuleOwnedRootSource. It is registered on the root bySetupModules. The mesh hub and every per-node hub are scopes under the root, so they all see these types. This replaces the per-nodeAddModuleOwnedforwarders, which it covers.ModuleFallbackSource.LiveModuleUpdate.md→ "Root services" is updated.Evidence
ModuleContributionsCrossContainersTesthas 4 tests: the declaring module's list, the mesh hub, a per-node hub, and a dependent resolving its dependency. Negative control: on the code before this PR all 4 fail. The first one fails withExpected {"hub"} to equal {"hub","OpenRouter","OpenRouterEU"}.Module*tests inMeshWeaver.Compiler.Pipeline.Testpass. That includesModuleRootServicesSwapTest, which checks that generation N is actually collected after a swap, andModuleServicesKeepEveryRegistrationTest.Memex.Portal.Shared.TestModule* tests: 431/431.MeshWeaver.Hosting.TestModule*/StaticNodePrecedence tests: 10/10.MeshWeaver.AI.Test(2700),MeshWeaver.AI.OpenAI.Test(135) andMeshWeaver.AI.Anthropic.Test(28) are all green against this branch.-warnaserrorbuild is clean for ServiceProvider, Mesh.Contract, Compiler.Pipeline.Test, Hosting.Test and Portal.Shared.Test.Pairs-with: none — this PR removes no public type or member (only the internal
ModuleServiceForwarding.AddModuleOwned). It addsModuleServiceRoute.Contributed,ModuleOwnedRootSource,ModuleServices.RegistrationsElsewhere/IsOwnedByAnotherModule,ModuleServiceProvider.StandInsand aCreateoverload. No interface members are added.There is a companion Plugins PR, which can land in either order. It registers each catalog source as its own registration (the old pattern found the shared
LanguageModelCatalogOptionssingleton and appended to it, which cannot cross containers). It also takes Kimi out of the review lane's fallback tier.After deploy (memex / control)
The Provider import runs at boot, so a roll/restart of the control instance is required. After that, recycle
Provider/OpenRouterEUandProvider/OpenRouterif they still list 0 models.🤖 Generated with Claude Code