Repository navigation
Description
Maintainer direction (2026-08-25): "all ai stuff deleted from core and all deployed and green."
MeshWeaver.AI and MeshWeaver.AI.Application are the last AI in the platform repo. This issue is the program: the verified inventory of every compiled edge, the three surfaces inside MeshWeaver.AI that are not AI and must be carved out first, and the phased move to MeshWeaver.Plugins.
What already left
0b3b4266f "Fourteen modules leave the platform" (2026-08-19) took the AI provider packs — MeshWeaver.AI.OpenAI, .AzureFoundry, .ClaudeCode, .Copilot, .WebSearch — to MeshWeaver.Plugins (Plugins#524). Memex.Portal.Shared.csproj:105 documents the flip. The directories still visible under src/MeshWeaver.AI.*/ in a dev tree are untracked bin/obj leftovers (git ls-files = 0 for all five); they are not in MeshWeaver.slnx.
Why the engine stayed
That commit states its own criterion: "Nothing in the platform's own src/ referenced them. That is what made this a deletion rather than an untangling." False for MeshWeaver.AI — it has 21 compiled consumers across 5 platform projects, using ~40 distinct public types:
| Consumer | Files | Types used |
|---|---|---|
memex/Memex.Portal.Shared |
10 | ModelProviderNodeType, MeshOperations, IChatClientFactory, Harness, ConnectSessionManager, IConnectStrategy/IConnectTokenSink/IMcpBackConnection, SkillNodeType/SkillDefinition/SkillInfo/SkillAction, AiContentSources, AiCatalogLayoutAreas, TokenUsage*, ModelPrice*, IProviderKeyProtector, LanguageModelCatalog*, ProviderCredentialSeed, ThreadComposer, Thread |
src/MeshWeaver.GitSync |
8 | AiContentLocator, AgentFileParser, AgentConfiguration, BuiltInAgentProvider/BuiltInSkillProvider, SkillDefinition/SkillMarkdown/SkillNodeType, AgentChatClient, DescriptionGenerator, IProviderKeyProtector |
src/MeshWeaver.Blazor.Portal |
14 | chat views (Chat/*), AddAITypes |
memex/Memex.LocalMesh |
1 | MeshOperations |
tools/MeshWeaver.PluginTester |
1 | AddAI(AiContentSources.ContentPartitions) |
Plus 11 test projects referencing MeshWeaver.AI.csproj (AI.Test, Threading.Test, Content.Test, GitSync.Test, Autocomplete.Test, Documentation.Test, PathResolution.Test, Query.Test, Hosting.{Orleans,PostgreSql,Snowflake}.Test).
Verified NOT coupled (so these are not blockers): nothing in MeshWeaver.Mesh.Contract, Messaging.Hub, Hosting, Layout or Graph compiles against it — every StartThread/SubmitMessage hit in those assemblies is a comment. MeshWeaver.Layout's ThreadMessageBubbleControl and PromptCell are already contract-shaped.
Phase A — carve the non-AI OUT of MeshWeaver.AI (platform-only, no cross-repo ordering)
Three surfaces live in the AI assembly but are not AI. Each is a compiled edge that would otherwise force the platform to reference a module.
A1. MeshOperations → a platform assembly. src/MeshWeaver.AI/MeshOperations.cs is 4,385 lines of mesh get/search/create/update/patch/move/copy/delete/export — the facade behind the portal's REST API (Memex.Portal.Shared/Api/MeshApiEndpoints.cs) and Memex.LocalMesh/LocalMeshApiEndpoints.cs, as well as the MCP tools. Its only AI coupling is one member: ResolveContextPath(IAgentChat chat, string path) (line 158) — which stays behind in the AI assembly as an extension. Moves with it: NodeReadOutcome, NodeChangeEntry, MeshExportManifest/MeshExportFileEntry. New project (its dep set — ContentCollections, Indexing(.Graph), Kernel, Markdown, Layout, Graph — is wider than any existing platform assembly's, so folding it into MeshWeaver.Graph would bloat a core assembly).
A2. IProviderKeyProtector / IMasterKeyProvider / ConfigMasterKeyProvider → platform security. AES-256-GCM at-rest protection for stored credentials. Consumers are already mostly non-AI: GitSync/GitHubCredential + GitHubCredentialService (GitHub PATs) and Memex.Portal.Shared/Authentication/EaGraphAuth.cs (Entra), alongside AI's own ModelProviderConfiguration.ApiKey. Related: the plaintext-key rotation item.
A3. AiContentLocator / AiContentSources / the Agent+Skill parsing set — decision required. AgentFileParser, SkillNodeType, SkillDefinition, SkillMarkdown, AgentConfiguration, BuiltInAgentProvider/BuiltInSkillProvider. These are AI, so under "all AI deleted from core" they leave — which means their platform consumers (GitSync's five AI-content-sync files, Portal.Shared/Skills/AgentSkillSyncService, AiMenuContributions, PluginTester) leave with them (Phase B), rather than a MeshWeaver.AI.Contract staying behind. Recording the alternative explicitly so the choice is deliberate, not defaulted.
Phase B — the AI features leave the portal composition root
Each of these is an AI feature living in a platform assembly. A module can carry all of it: MeshNodeProviderAttribute.BuilderConfigurations hands a module the full MeshBuilder surface (incl. ConfigureServices, ConfigureDefaultNodeHub), MeshEndpointProviderAttribute carries routes, and menus/settings tabs go through the existing provider interfaces — the MeshWeaver.Social module is the worked precedent.
Memex.Portal.Shared:AiMenuContributions,Models/ModelProviderService,Models/ConnectTokenSink,Authentication/McpBackConnectionService,Settings/TokenUsageSettingsTab,Skills/AgentSkillSyncService, and the AI halves ofMemexConfiguration+StaticRepoSyncExtensions.MeshWeaver.GitSync:AiContentDiskWriter,AiContentSyncArea,AiContentSyncMenuProvider,HubAiContentSyncExtensions,PullRequestDraftService.MeshWeaver.Blazor.Portal/Chat/*(14 files) — rides Extract the GUI implementations from the core repo: RN app + Blazor packs move to MeshWeaver.Plugins #2169 Phase B3 or moves to an AI view pack, whichever lands first.tools/MeshWeaver.PluginTester— its.AddAI(...)inPluginGateRunner.
Phase C — the move
src/MeshWeaver.AI (156 files) + src/MeshWeaver.AI.Application (8 files, already a self-contained module: [assembly: AgentsApplication] : MeshNodeProviderAttribute, and Blazor.Portal's reference to it is ships-the-bits only — no code usage) + the AI-only test projects → MeshWeaver.Plugins. Delete here; declare under Modules:Required (not merely Assemblies) so a deployment that lost the bundle fails readiness instead of silently shipping a portal with no chat.
🚨 Ordering rule from Plugins#524: this merges only once the registry SERVES the bundles. Until then the image is where every consumer gets them and the deletion would take the capability with it.
Phase D — deployed and green
Registry serves the AI bundles → CD rolls memex / memex-cloud / client-i → verify a real chat round on a portal, not an API probe.
Risks to hold
HubThreadExtensionsis AGENTS.md's canonical thread-submission surface (hub.StartThread/SubmitMessage/MarkThreadDone/ …) and it lives insrc/MeshWeaver.AI. Moving it makes threads a module-provided capability; AGENTS.md andThreadOperations.mdmust be updated in the same change set to name the new home.AiContentSources.ContentPartitionsdecides who SERVES the Agent/Provider/Harness/Skill partitions — a listed partition is served from Postgres and its in-memoryStaticNodePartitionStorageProvideris not registered. Getting this wrong makes the in-memory provider shadow the DB nodes the Agent plugin installs.- 11 test projects must each drop the dependency or travel with the module.
- A closure/app-root duplicate of a landed module is a 409 on every instance — the
MeshModulesGuardPublishAppRootrefusal exists for exactly this and must stay armed.
🤖 Generated with Claude Code
Activity
rbuergi commentedon Aug 25, 2026
Sharpened plan after building A1 + A2 — Phase B is intra-repo, and that reorders everything
Building the first two steps changed the shape of the rest. Phase B does not need MeshWeaver.Plugins at all.
The 14-module commit's criterion was "Nothing in the platform's own
src/referenced them — that is what made this a deletion rather than an untangling." The way to reach that state is not to move AI features to Plugins one at a time (each needing a served bundle before it can merge). It is to relocate every AI feature currently sitting in a platform assembly INTOMeshWeaver.AIitself, in this repo, with CI green at every step. When that is done the platform has zero AI files and zero AI references, and the engine moves out as ONE clean deletion — the same shape as the fourteen.B1 —
Memex.Portal.Shared's AI features →MeshWeaver.AIAiMenuContributions,Models/ModelProviderService,Models/ConnectTokenSink,Authentication/McpBackConnectionService,Settings/TokenUsageSettingsTab,Skills/AgentSkillSyncService, and the AI halves ofMemexConfiguration+StaticRepoSyncExtensions. Their registrations ride a module attribute —MeshNodeProviderAttribute.BuilderConfigurationshands a module the fullMeshBuilder(ConfigureServices,ConfigureDefaultNodeHub,AddHostedService), whichMeshWeaver.Socialalready proves in production.B2 —
MeshWeaver.GitSync's AI-content sync →MeshWeaver.AI, inverting the dependencyAiContentDiskWriter,AiContentSyncArea,AiContentSyncMenuProvider,HubAiContentSyncExtensions,PullRequestDraftService. GitSync currently points AT the AI engine; afterwardsMeshWeaver.AIpoints at GitSync's git primitives, which is the right direction — a module may reference the platform, never the reverse. A2 already removed the other half of that edge (IProviderKeyProtector), so B2 takes GitSync's AI dependency to zero.🚨 This edge is load-bearing beyond GitSync:
MeshWeaver.PluginCatalog→MeshWeaver.GitSync→MeshWeaver.AIis how the plugin catalog compiles against AI types today. It is a transitive reference, so it never appeared in anygrepof directProjectReferences.B3 —
Blazor.Portal/Chat/*andtools/MeshWeaver.PluginTesterThe chat views ride #2169 Phase B3 (the shell extraction) or move to an AI view pack, whichever lands first. PluginTester's
.AddAI(AiContentSources.ContentPartitions)is real, not incidental — the plugin gate composes the in-mesh compile reference set, so it needs a decision, not a deletion.Then C — one deletion
src/MeshWeaver.AI+src/MeshWeaver.AI.Application+ the AI-only suites leave together, registry bundle first per Plugins#524.A trap found while cutting an edge, worth writing down
Memex.LocalMesh's AI reference LOOKED dead the moment A1 movedMeshOperations— a staleusingand nothing else. Removing it built clean. It was reverted anyway: dropping aProjectReferencedrops the DLL from the app closure, and the closure is whatCompileReferencescomposes the in-mesh compile reference set from. In-mesh source is invisible todotnet buildand to CI (AGENTS.md), so "it compiles" says nothing about whether a device-mesh NodeType still resolvesusing MeshWeaver.AI. Every edge cut in Phase B needs the node-JSON sweep, not just a green build.Status
MeshOperations→MeshWeaver.Mesh.Operations. In CI.MeshWeaver.Mesh.Security, registration moved toAddGraph(). In CI.The local-mesh sidecar stops referencing the AI engine
rbuergi commentedon Aug 25, 2026
The Store entry: ONE, and it does not need a source move
Maintainer direction (2026-08-26): "build it including application … this must be all one entry in store."
Checked how plugins are actually injected, and two facts change the plan:
1. The CI matrix can build from the nested core checkout.
MeshWeaver.Plugins/.github/workflows/ci.ymlcarries{package, module, project}rows, and two of them already point INTO a nestedmeshweaver/checkout:{"package": "DefaultViews", "module": "MeshWeaver.Blazor.Views", "project": "meshweaver/src/MeshWeaver.Blazor.Views/MeshWeaver.Blazor.Views.csproj"}So
MeshWeaver.AIcan become a Store package before its source relocates — that is exactly the order DefaultViews/GraphViews took. The source move is a later tidy-up, not a prerequisite.2. The package is one
content.module, so the app must be in the same assembly.OpenAI/index.jsonis aStore/Pluginnode with"module": "MeshWeaver.AI.OpenAI"— singular. #2297 foldsMeshWeaver.AI.ApplicationintoMeshWeaver.AIfor that reason: one assembly, one module, one entry, and installing AI installs the app that maintains agents/models/skills/harnesses.Target entry:
{ "id": "AI", "nodeType": "Store/Plugin", "category": "AI", "content": { "module": "MeshWeaver.AI", "app": true, "entryPoint": ".../area/AgentOverview", "minMeshVersion": "…" } }🚨 Installation is gated on the closure edge, not on the package. A closure DLL and a registry module of the same name are mutually exclusive — the landing service refuses with a 409 on every instance. So the entry may be defined, but must not be
preInstalleduntilMemex.Portal.Sharedstops referencingMeshWeaver.AI.Two findings from making the application live (#2297)
The Agents application has been dead code since it was written. It carried
[assembly: AgentsApplication], but aMeshNodeProviderAttributeis read in exactly ONE place —MeshBuilder.InstallAssemblies— andMeshWeaver.AI.Applicationwas never listed underModules:Assemblies. It rode the app closure viaBlazor.Portal's ProjectReference and shipped in every image contributing nothing.ThreadChatViewcarries the scar: it constructsSkillAutocompleteProviderby hand because resolving it from DI "returned null and typing '/' showed nothing".Turning it on surfaced a platform hang —
AutocompleteRequestcould never be answered on a hub with a mesh-backed provider.DataExtensions.HandleAutocompleteRequesttookLastAsync(), which emits only on COMPLETION, whileSkillAutocompleteProvidercomposesObserveSkillQueries → ObserveSnapshot → Switch— live subscriptions that never complete. Trace:HUB_HANDLE_END Result: Processedat +27 ms, then 30 s of silence and no response post. Fixed at the root — "settled" is now a quiet period (150 ms throttle / 2 s deadline / 2.5 s empty floor), never completion. Likely the same root cause as the open chat @-autocomplete report.Remaining edges before the entry can be installed
Memex.Portal.SharedAgentSkillSyncServiceneedsPortalApplication.HubBlazor.Portal/Chat/*tools/MeshWeaver.PluginTester.AddAI(AiContentSources.ContentPartitions)— a real decision, the plugin gate composes the in-mesh compile reference setMemex.LocalMeshMeshWeaver.GitSync(+PluginCatalogtransitively)rbuergi commentedon Aug 25, 2026
The last step has a real constraint: a module attribute cannot read configuration
For the AI entry to carry the engine,
AddAImust move from the portal's composition root onto the module's assembly attribute (BuilderConfigurations, theMeshWeaver.Socialshape). That is blocked by one thing, and it is worth stating precisely rather than discovering it mid-PR:AddAItakes a config-derived set, and decides at BUILDER time which partitions Postgres serves versus which get a read-only in-memory provider. A module attribute has noIConfiguration:MeshBuilderexposes none (checked), andMeshWeaver.Socialdocuments the same limit — "there is no IConfiguration instance at install time", which is why it binds through the options pipeline instead.🚨 Defaulting the argument is not available as a shortcut.
AiContentSources.ContentPartitionsis load-bearing in the dangerous direction: membership decides who SERVES a partition, and droppingAgentre-registers the in-memory provider, which then shadows the DB nodes the Agent plugin installs — the agents silently revert to whatever the binary embeds. A module that guessed this set would fail exactly that way.Two ways out, both design calls rather than mechanics:
AddAI()needs no argument and the attribute can carry it. Follows theLinkedInOptionsprecedent.MeshBuildera configuration surface for install-time module contributions. Larger, and it changes the module contract for every pack.Until one lands,
Modules:Assembliescarries the AI assembly (so the Agents application is contributed — #2297) whileAddAIstays a compiled call, and the Store entry cannot bepreInstalledbecause the closure DLL and a registry module of the same name are mutually exclusive (409).One rule worth extracting from today, across three independent findings
Three separate mechanisms turned out to be built but not reachable, each found by a different session, each invisible from the definition side:
MeshBuilder.InstallAssemblies, and it was listed under noModules:AssembliesFrameworkReleaseBroadcaster(Plugins#686)plugin-registryHTTP clientCheck the call sites, not the declaration — and if there are none, that is the finding. Nothing in review catches these, because each diff is internally consistent; enumerating consumers is the only move that works.
rbuergi commentedon Aug 25, 2026
Correction: the runtime-options route does not work, and the coupling is deeper than one argument
I proposed resolving the serve-from-DB decision from bound options at runtime so the module attribute needs no configuration. That does not survive contact with the code, for a reason worth recording:
dbSynceddecides two things, not one: whether the in-memory partition provider is registered (deferrable), and whether the type-definition node is definition-only (not deferrable — it is aninitproperty baked into the node at builder time). Leaving a DB-synced type's definition node servable is #902: the type-def node sits at the same path as the partition ROOT, so the durable root can be neither read, re-created, nor written — a permanently unrecoverable partition.So the decision has to be available at BUILDER time, which means the module attribute has to see configuration.
The good news: the install path already holds it.
MeshBuilderModuleActivation.InstallConfiguredModules(builder, configuration, …)takesIConfiguration, readsModules:Assembliesfrom it, and then callsbuilder.InstallAssemblies(resolved)— dropping the configuration on the floor. GivingMeshBuildera configuration surface set at that point is additive, backward-compatible, and fixes this for every pack rather than for AI. It is the general gapMeshWeaver.Socialdocuments as "there is no IConfiguration instance at install time".A second coupling, found while scoping it
Features:StaticRepoSync:Partitionsis not only AI's gate.MemexConfigurationapplies an AI-specific union to it —— and then passes the SAME set to
AddDocumentation(...)andAddStaticRepoSync(...). So the portal's static-repo IMPORT depends on knowing AI's partition names. RemovingMemex.Portal.Shared's reference toMeshWeaver.AImeans that union cannot stay where it is, and simply deleting it would drop Agent/Provider/Harness/Skill out of the import set — AI content silently stops being imported.That needs a contributor seam (a module declaring the partitions it wants imported), not a moved constant. It is the last real design question in this program, and it is bigger than the
AddAIargument that surfaced it.Sequencing recommendation: land the four open edge-cuts first (they are independent and reviewable), then take this as its own change with the seam designed deliberately. Until then the AI assembly rides
Modules:Assembliesfor its application (#2297) whileAddAIstays a compiled call, and the Store entry stays un-preInstalled.rbuergi commentedon Aug 25, 2026
Correcting myself again: the import "seam" is smaller than I said — no new interface needed
I described the static-repo coupling as needing a contributor seam ("a module declaring the partitions it wants imported"). Reading
AddStaticRepoSyncrather than inferring from its signature, that is not so.serveFromPartitionis used at builder time for exactly one thing: deciding whichIStaticRepoSourceregistrations to add. The importer itself resolves them at RUNTIME —So a module that registers its own sources is already a first-class contributor; the enumerable IS the seam. What the portal's copy does today is register AI's sources on AI's behalf:
Both blocks are AI deciding AI's own business from a config key, in the composition root. With #2300 the module can read that key itself, so they move to the module and the portal stops naming AI partitions at all. No
IPartitionGroup, no new contract — I was designing around a constraint that turned out not to exist.What that leaves, and why it is ONE atomic change rather than three
It cannot be split, and the reason is worth writing down: if the module registers the AI content sources from configuration while
MemexConfigurationstill calls.AddAI(serveFromPartition)compiled-in,AddBuiltInAiContentSources()runs twice — duplicateIStaticRepoSourceregistrations, and the importer imports each source twice. So the module attribute and the removal of the compiled call have to land together, along with the rest ofMemexConfiguration's AI wiring (~13 types: the Connect strategies,IChatClientFactory,Harness,ConnectSessionManager, the catalog options).Not starting it tonight, deliberately.
Memex.Portal.Sharedis being actively split by another workstream (~30 razor files out asMemex.Portal.Gui, ~79 staying), and a large refactor ofMemexConfiguration— the one file that workstream says MOVES — against a tree that is mid-split is how two sessions build opposite things. It goes after that split lands, and after #2300 gives the module its configuration.Order from here: Plugins#685 → #2297 → #2283 / #2287 / #2292 / #2300 (independent) → the Portal.Shared split lands → the atomic AI-wiring move → the Store entry flips to
preInstalled.Merge pull request #2297 from Systemorph/refactor/ai-application-fold…
Merge pull request #2287 from Systemorph/refactor/ai-exit-phase-a2
Merge pull request #2292 from Systemorph/refactor/ai-exit-gitsync
Merge pull request #2300 from Systemorph/feat/module-install-sees-con…
Merge pull request #2283 from Systemorph/refactor/ai-exit-phase-a
rbuergi commentedon Aug 26, 2026
All five core PRs merged — where the program stands
MeshWeaver.AI.Applicationfolds intoMeshWeaver.AI— one assembly, one module, one Store entryMeshWeaver.Mesh.Security; registrationAddAI()→AddGraph()MeshBuilder.Configuration— a module can read deployment config at INSTALL timeMeshOperations→MeshWeaver.Mesh.Operationsassembly (namespace staysMeshWeaver.Mesh)module: MeshWeaver.AI,app: true,entryPoint: Agent/AiAgentsPlatform consumers of the AI engine: 5 → 2.
Memex.LocalMesh,MeshWeaver.GitSyncandMeshWeaver.PluginCatalogare at zero.Memex.Portal.Shared(2 references) andtools/MeshWeaver.PluginTesterremain.The one remaining change, and why it is atomic
MemexConfiguration's AI wiring — the module attribute carryingAddAI, the removal of the compiled call, and ~13 types (Connect strategies,IChatClientFactory,Harness,ConnectSessionManager, the catalog options) — must land TOGETHER. Split it andAddBuiltInAiContentSources()runs twice: duplicateIStaticRepoSourceregistrations, and the importer imports every AI source twice.It is unblocked on mechanism now that #2300 is in. It is blocked on sequencing:
MemexConfigurationis the one file the Portal.Shared split moves, and #2293 deletes 389 files including all ofMeshWeaver.Blazor*.Then the entry ships
Plugins#687 flips to
preInstalledonce (a)Memex.Portal.Sharedstops referencingMeshWeaver.AI— otherwise the closure DLL and the registry module collide at 409 on every instance — and (b)minMeshVersionnames a release that actually carries #2297. rc7 (2026-08-22) predates it, so that needs a release decision.What this program cost, and what it bought beyond the move
Three defects found by building it rather than by looking for them:
[assembly: AgentsApplication]shipped in every image while listed under noModules:Assemblies— andMeshBuilder.InstallAssembliesis the only reader of that attribute.ThreadChatViewcarried the scar: it constructsSkillAutocompleteProviderby hand because DI "returned null and typing '/' showed nothing".AutocompleteRequestcould never be answered on a hub with a mesh-backed provider.LastAsync()waits for COMPLETION;SkillAutocompleteProvidercomposes live subscriptions that never complete. The handler ran, returnedProcessedin 27 ms, and posted nothing. Fixed at the root — settled is now a quiet period, never completion.AddAI(), while four unrelated subsystems resolve it optionally and store the secret verbatim on null. The day AI left, all four would have written plaintext silently.Two cross-repo breaks were caught before shipping — a new namespace that would have failed on the plugins TRUNK rather than on the PR, and a deleted project the plugins' own
Blazor.Portalstill referenced (MSB9008— not a symbol, so no grep would have found it).rbuergi commentedon Aug 26, 2026
Directive sharpened:
MeshWeaver.AIis removed entirely from coreNot "stops being referenced" — the project gone from
src/. Here is the full dependency order, measured rather than assumed, so the final deletion is mechanical.What holds the engine in core, after #2315
src/MeshWeaver.Blazor.Portaltools/MeshWeaver.PluginTester.AddAI(AiContentSources.ContentPartitions)Memex.Portal.Sharedthe composition rootThe PluginTester is not a reference to delete — it is a lane to switch
It registers the AI node types because plugin packages ship
AgentandSkillnodes, and without the types those installs are refused "not registered". That requirement does not go away when the engine leaves; it is the gate doing its job. The right shape is the one every deployment uses — install the module — which means themw-plugin-testimage must carry the AI bundle. So it cannot be done before the bundle ships, and the bundle cannot ship before the 409 clears (Plugins#687).The nine remaining test suites are a per-TEST question, not per-project
They use threads and agents as the platform's canonical workload:
Hosting.Orleans.TestnamesThreadNodeType49 times,Query.Test10,Hosting.PostgreSql.Test6. Two different things are mixed together:OrleansChatHistoryTest,OrleansCompileActivityAccessTest) — these travel with the engine;Splitting them per-test is the work; moving whole projects would exile framework suites into a downstream repo, which is the same mistake the Portal.Shared split avoided.
🚨 Guards that assert OVER the AI project — check these BEFORE deleting, not after
Three times in one night a guard stayed behind while its subject moved (the #1814 surface-manifest pin, the overlay z-index test, the AI resolution-seam audit). Each time the destination looked complete because the code was there; only the check that verifies it was missing. The ones that would be orphaned here:
Plus one that is easy to miss because it names no AI type in its assertion:
FrameworkBuildIdentityTest.FrameworkBuildIdentity.ContentSurfaceAssemblieslistsMeshWeaver.AIas part of the surface in-mesh content compiles against, and the list is pinned to the PluginTester's closure. When the engine leaves that closure, the canonical list must drop it in the same change — the same gate that caught #2283 addingMeshWeaver.Mesh.Operations.Order
Memex.Portal.Sharedto zero (in CI)Blazor.Portaldeleted from core (meshweaver-c0; unblocked, CI running)preInstalled— the 409 clears once 2 and 4 are inContentSurfaceAssembliesdrops the entrysrc/MeshWeaver.AIandsrc/MeshWeaver.AI.Application's remains leave coreSteps 6–8 are gated on 5, which is gated on 4. Nothing in 6–8 can be done earlier without shipping a portal that cannot install the engine it needs.
Merge pull request #2317 from Systemorph/chore/drop-dead-ai-test-refe…
Merge pull request #2315 from Systemorph/refactor/ai-leaves-the-compo…
19 remaining items
rbuergi commentedon Aug 27, 2026
Correction to the 08-26 22:42 note — gate 1 (the 409) is NOT clear on the plugins side
At MeshWeaver.Plugins
main(7edad75a, 2026-08-27)src/Memex.Portal.Gui/Memex.Portal.Gui.csproj:111carries a live<ProjectReference Include="$(MeshWeaverRoot)/src/MeshWeaver.AI/MeshWeaver.AI.csproj" />(withusing MeshWeaver.AI.Connect;inMemexPortalComposition.csforIMcpBackConnection, which already lives inMeshWeaver.Mesh.Contract). So the portal image built from plugins DOES shipMeshWeaver.AI.dllin its app closure, and a registry module of that name would 409 on every instance.It cannot simply be dropped:
FrameworkBuildIdentity.ContentSurfaceAssemblieslistsMeshWeaver.AI, and the plugins hosts write their surface manifest from their compile closure — dropping the reference alone makes the portal hash AI as absent whilemw-plugin-test(core) still hashes a real surface id: the #1814 identity split. So the Gui reference leaves in the same atomic change as theContentSurfaceAssembliesentry (and the PluginTester's closure) — item 6 of the step list — not before.Context: the storage/transport carve-out landed today (core #2479, #2486, plugins #737, #738; core #2485 deleting the projects is the last piece). Two things from it matter here: (a) the module-pack lane now reads a node repo's
src/platform-shipped.txt(projects that live in the node repo but ship in the image are treated as platform by the pack — the mechanism to reuse if AI ever needs an image-lane transition); (b)MeshWeaver.Hosting.Orleans.TestBaseis now a shipped src project holdingOrleansTestBase& co — the "surgery" forHosting.Orleans.Test(the ~24 AI-specific classes coming out from under a base that seedsAddAITypes()) now happens in that project, which currently referencesMeshWeaver.AIfor exactly that seeding.The sharding rationale keeps its true history (Copilot review)
Merge pull request #2524 from Systemorph/feat/2276-ai-leaves-the-cont…
rbuergi commentedon Aug 27, 2026
The bake-host blocker is not AI-specific — it gates MeshWeaver.Maps too (measured 2026-08-27)
Surveying what else can leave core turned up the same structural item from a second direction, worth stating once for the whole programme:
A project can only leave core while the core bake host can still BUILD it.
tools/MeshWeaver.PluginTestercompiles core's gated sample content, and #2524's trick — replacing theProjectReferencewith a tester-localMeshModuleClosurerow — works precisely becausesrc/MeshWeaver.AIis still in core's tree. The moment the source leaves, that row has nothing to build from.Maps hits this today.
.github/scripts/stage-samples-gate.shstagessamples/Graph/Data/{ACME,Northwind,Cornerstone,…}through the gate, andCornerstone/Pricing/Source/PricingLayoutAreas.csmakes real symbol use ofMapControl/MapMarker. So movingsrc/MeshWeaver.Mapsto plugins breaks the gated core sample — not the identity flip (that part is routine), the build source.Consequence for #2276's remaining step: the AI SOURCE move needs the same thing Maps needs — the bake host consuming a plugins-BUILT bundle (registry or CI artifact) rather than building from core source. That is the one genuine design item left in this programme; both moves unblock together, and neither should be attempted before it.
Measured alongside: what can leave core with no such blocker is
MeshWeaver.Speech.Contract,MeshWeaver.Observability.Contractandtools/MeshWeaver.LogWatcher— all outsideContentSurfaceAssemblies, so zero identity consequence. That move is in flight.ContentCollections.Indexing(+.Graph)remains blocked behind AI (AI is one of its four consumers; the residue is a tinyIImageDescriber+DocumentPathscontract).GitSync(6 consumers, takes PluginCatalog's registry half) is the large one after that.MeshWeaver.Cliis a shipped NuGet tool — zero project consumers is expected, it stays.Merge pull request #2547 from Systemorph/chore/2276-speech-observabil…
Merge pull request #2541 from Systemorph/feat/2276-gate-loads-externa…
Core's samples must not require a module (#2276)
The migration guard scanned content/, which left with AI (#2276)
rbuergi commentedon Aug 28, 2026
Status 2026-08-28: the core half is complete — #2588 merged (MeshWeaver.AI + the moved test suites leave core, combining #2568 + #2526 + #2586), on top of the seam PRs already recorded here (#2524 gate-lands-the-engine, #2541, #2547 Speech.Contract + log watcher, #2485/#2501 Orleans test-rig split).
The remaining leg is MeshWeaver.Plugins#786 ("The AI engine moves in") — open with auto-merge armed at the time of writing. This issue closes when #786 lands; if #786 is merged and something still references the departed trees, that is a new finding, not this program.
rbuergi commentedon Aug 28, 2026
Done. The AI engine has left the platform.
The two halves, merged today:
src/MeshWeaver.AI,content/ai, the AI testsuites and
Application.Styles(folded into Domain) are deleted — 547 files, −105,414 lines —plus the AI-free Orleans test rig and the compacted AGENTS.md. The three prior carve-out PRs
(Generations GC can no longer break a module a running process still needs #2523/The AI engine leaves the content surface — the gate lands it as a module (#2276) #2524/The portal hands its configuration to the module system (#2507) #2525 wave, content/ai becomes the one master for built-in agents and skills #2579 one-master, fix: a recycle now reaches the subscribers it orphans (#2551) #2582 recycle seam) sequenced it.
land beside the modules that bind it; the module matrix packs
src/MeshWeaver.AIlike everyother module. Carried across the four-step content rescue (content/ai becomes the one master for built-in agents and skills #2579's skills), the seven
Application.Stylesrepoints, and the emigrated drift-test ledger.Also true as of today, beyond the letter of this issue:
main=tree-identical
7d1181ffee); the last legacy pin (voice-model-swiss-german) is one merge fromeviction (fix: the Swiss-German voice model moves to MeshWeaver.Plugins — evicting the last pre-rewrite pin (#2593) #2602/Move the Swiss-German voice model off the GitHub release — it is the last pin keeping pre-rewrite history alive #2593).
(plugins#805/Remove the duplicate InternalsVisibleTo Copilot flagged on #804 #806,
check-module-floors.py).smaller half of the codebase (~48:52).
Remaining threads are tracked in their own issues: #2584 (fresh-install activation, interim
cutting now), Systemorph/MeshWeaver.Plugins#977 (Blazor.Portal decoupling end-state), #2593 (voice-model pin eviction).
ci(compile-check): the reusable lane can add external modules to the …
fix(collaboration): keep the assembly NAME so already-published modul…
docs: the two watcher build instructions point at the published image…
fix(combo-gate): compose the combo's compiled modules into the gate (#…