Skip to content

The AI application folds into the engine — one assembly, one module, one Store entry (#2276) - #2297

Merged
rbuergi merged 2 commits into
mainfrom
refactor/ai-application-folds-in
Aug 25, 2026
Merged

rbuergi merged 2 commits into
mainfrom
refactor/ai-application-folds-in

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Installing AI must install the app that maintains agents, models, skills and harnesses. One entry in the Store, not two. MeshWeaver.AI.Application becomes MeshWeaver.AI/Application/ — namespaces unchanged (they were already sub-namespaces of the engine), only the assembly boundary goes.

The application was dead code, and nothing said so

It carried [assembly: AgentsApplication]. But a MeshNodeProviderAttribute is read in exactly one place — MeshBuilder.InstallAssemblies, i.e. the Modules:Assemblies lane — and that assembly was never listed there. It rode the app closure through a ProjectReference from MeshWeaver.Blazor.Portal, so it shipped in every image contributing nothing: no Agents hub, no agent overview, and its two autocomplete providers registered on a container that was never built.

ThreadChatView carries the scar. It news up SkillAutocompleteProvider by hand, with a comment explaining that resolving it from DI "returned null and typing '/' showed nothing".

Both portals now list MeshWeaver.AI.dll under Modules:Assemblies, so the attribute is read and the application is contributed by the same load that brings the engine. The DLL still rides the app closure, so ResolveModulePath falls back to the app folder — the documented thin lane, the same step #1644 used for every module that has since left.

Turning it on surfaced a platform hang

DataExtensions.HandleAutocompleteRequest took LastAsync() — which emits only when the combined stream completes. A provider backed by mesh data never completes: it is a live subscription by design (SkillAutocompleteProvider composes ObserveSkillQueries → ObserveSnapshot → Switch). So on any hub with such a provider registered, the handler ran, returned Processed in 27 ms, and posted nothing. The caller waited out its timeout against silence — no error, nothing to grep.

Read straight off the message trace, per the /debug procedure:

:35.082  HUB_HANDLE_START | AutocompleteRequest | Hub: app/Agents
:35.110  HUB_HANDLE_END   | AutocompleteRequest | Hub: app/Agents | Result: Processed
         … 30 s, no response post from that hub …

A burst of work then total silence — a missed observation, not a lock.

"Settled" is now a quiet period, never completion. First of three wins: a 150 ms throttle; a 2 s deadline answering with the best snapshot so far; a 2.5 s floor answering empty if no provider ever produced anything. A one-shot request must produce exactly one answer — a hang is indistinguishable from "still thinking". One shared RefCount subscription, so the providers' queries are not issued twice.

The AI application's duplicate handler is deleted with it: the platform's copy has relevance scoring this one never had, and a second registration for one request type is how the two drifted.

The round trip that timed out at 30 s now answers in well under a second.

Verification

  • Full solution build under CI's flags → 0 Error(s).
  • MeshWeaver.Autocomplete.Test — 155/155.
  • MeshWeaver.Data.Test — 385/385.
  • New AgentsApplicationModuleTest (the attribute travels with the engine and names the app) and AgentsApplicationInstallTest (installing the assembly the way Modules:Assemblies does builds the hub and it answers). The second one failed before the handler fix, which is what makes it a gate rather than a formality.

What this sets up

MeshWeaver.AI is now a single assembly carrying the engine and its maintenance application, activated through the module lane. That is the shape a Store package needs: one content.module, one entry, Modules:Required once it ships from the registry.

Refs #2276

🤖 Generated with Claude Code

…one Store entry

`MeshWeaver.AI.Application` becomes `MeshWeaver.AI/Application/`. The namespaces are unchanged
(`MeshWeaver.AI.Application`, `…Application.Layout`) because they were already sub-namespaces of the
engine; only the assembly boundary goes. Step toward #2276: installing AI must install the app that
maintains agents, models, skills and harnesses — one entry in the Store, not two.

**The application was DEAD, and nothing said so.** It carried `[assembly: AgentsApplication]`, but a
`MeshNodeProviderAttribute` is read in exactly ONE place — `MeshBuilder.InstallAssemblies`, i.e. the
`Modules:Assemblies` lane — and that assembly was never listed there. It rode the app closure through
a ProjectReference from `MeshWeaver.Blazor.Portal` and shipped in every image contributing nothing:
no Agents hub, no agent overview, and its two autocomplete providers registered on a container that
was never built. `ThreadChatView` carries the scar — it news up `SkillAutocompleteProvider` by hand,
with a comment that resolving it from DI "returned null and typing '/' showed nothing".

Both portals now list `MeshWeaver.AI.dll` under `Modules:Assemblies`, so the attribute is read and
the application is contributed by the same load that brings the engine. The DLL still rides the app
closure, so `ResolveModulePath` falls back to the app folder — the documented thin lane, the same
step #1644 used for every module that has since left.

**Turning it on surfaced a platform hang, which is fixed here rather than worked around.**
`DataExtensions.HandleAutocompleteRequest` took `LastAsync()` — which emits only when the combined
stream COMPLETES. A provider backed by mesh data never completes: it is a live subscription by
design (`SkillAutocompleteProvider` composes ObserveSkillQueries → ObserveSnapshot → Switch). So on
any hub with such a provider the handler ran, returned `Processed` in 27 ms, and posted NOTHING. The
caller waited out its timeout against silence.

Read straight off the message trace, per the /debug procedure: `HUB_HANDLE_START` → `HUB_HANDLE_END
Result: Processed` at +27 ms, then no response post from that hub for the remaining 30 s — a burst of
work followed by silence, i.e. a missed observation, not a lock.

"Settled" is now a QUIET PERIOD, never completion: first of a 150 ms throttle, a 2 s deadline
answering with the best snapshot so far, or a 2.5 s floor answering empty if no provider ever
produced anything. A one-shot request must produce exactly one answer — never a hang, which is
indistinguishable from "still thinking". The AI application's duplicate handler is deleted with it:
the platform's copy has relevance scoring this one never had, and a second registration for one
request type is how the two drifted.

The round trip that timed out at 30 s now answers in well under a second.

Verified: full solution build with CI's flags; `MeshWeaver.Autocomplete.Test` 155/155;
`MeshWeaver.Data.Test` 385/385; the new `AgentsApplicationInstallTest` round trip green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

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

This PR folds the (previously inactive) MeshWeaver.AI.Application into the MeshWeaver.AI engine assembly so installing AI brings along the Agents maintenance application as a single module/Store entry, and fixes the platform autocomplete one-shot handler so it always answers (no more LastAsync() hang on non-completing provider streams).

Changes:

  • Moved the Agents application node contribution into MeshWeaver.AI via an assembly attribute and removed the separate MeshWeaver.AI.Application project/reference.
  • Fixed AutocompleteRequest handling to respond based on a “settled/quiet”, deadline, or silence-floor policy rather than waiting for stream completion.
  • Added module-install and round-trip response tests to ensure the Agents app hub is actually built when installed via Modules:Assemblies.

Reviewed changes

Copilot reviewed 13 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/MeshWeaver.AI.Test/AgentsApplicationModuleTest.cs Adds tests asserting the Agents app is contributed by the engine assembly attribute and responds when installed via InstallAssemblies.
src/MeshWeaver.Data/DataExtensions.cs Fixes HandleAutocompleteRequest to always emit one response without requiring stream completion.
src/MeshWeaver.Blazor.Portal/MeshWeaver.Blazor.Portal.csproj Removes the now-obsolete MeshWeaver.AI.Application project reference.
src/MeshWeaver.AI/MeshWeaver.AI.csproj Adds MeshWeaver.Layout reference to support the folded-in application views/areas.
src/MeshWeaver.AI/Application/Layout/AgentsApplicationLayoutExtensions.cs Renames the layout extension class and continues to provide the layout registration entrypoint used by the app configuration.
src/MeshWeaver.AI/Application/Layout/AgentDetailsArea.cs Introduces a new agent-details layout area (includes delegation rendering and navigation).
src/MeshWeaver.AI/Application/ApplicationAddress.cs Introduces a canonical address for the Agents application hub.
src/MeshWeaver.AI/Application/AgentsApplicationExtensions.cs Configures the Agents application hub services (autocomplete providers) without duplicating the platform handler.
src/MeshWeaver.AI/Application/AgentsApplicationAttribute.cs Adds the assembly-level mesh node contribution ([assembly: AgentsApplication]) in the engine assembly.
src/MeshWeaver.AI.Application/README.md Deleted (project removed/folded into engine).
src/MeshWeaver.AI.Application/MeshWeaver.AI.Application.csproj Deleted (project removed/folded into engine).
src/MeshWeaver.AI.Application/GlobalUsings.cs Deleted (project removed/folded into engine).
src/MeshWeaver.AI.Application/AgentsApplicationExtensions.cs Deleted (migrated into MeshWeaver.AI).
MeshWeaver.slnx Removes the MeshWeaver.AI.Application project from the solution.
memex/Memex.Portal.Monolith/appsettings.json Adds MeshWeaver.AI.dll to Modules:Assemblies so the assembly attribute is actually read/applied.
memex/aspire/Memex.Portal.Distributed/appsettings.json Same as monolith: ensures the module lane installs MeshWeaver.AI.dll.

💡 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 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

    9 files  ±0      9 suites  ±0   6m 19s ⏱️ -19s
1 824 tests +1  1 820 ✅ +1  4 💤 ±0  0 ❌ ±0 
2 354 runs  +1  2 350 ✅ +1  4 💤 ±0  0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

2 107 tests  +1   1 807 ✅ +1   8m 46s ⏱️ +43s
    9 suites ±0     300 💤 ±0 
    9 files   ±0       0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

   10 files  ±0     10 suites  ±0   7m 8s ⏱️ +13s
1 301 tests ±0  1 300 ✅ ±0  1 💤 ±0  0 ❌ ±0 
1 302 runs  ±0  1 301 ✅ ±0  1 💤 ±0  0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

1 201 tests  ±0   1 201 ✅ ±0   13m 31s ⏱️ - 3m 0s
    9 suites ±0       0 💤 ±0 
    9 files   ±0       0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

1 880 tests  ±0   1 880 ✅ ±0   8m 2s ⏱️ +6s
   10 suites ±0       0 💤 ±0 
   10 files   ±0       0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

3 305 tests  ±0   3 305 ✅ ±0   9m 53s ⏱️ +38s
    8 suites ±0       0 💤 ±0 
    8 files   ±0       0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    55 files  ±0      55 suites  ±0   53m 41s ⏱️ - 1m 39s
11 618 tests +2  11 313 ✅ +2  305 💤 ±0  0 ❌ ±0 
12 149 runs  +2  11 844 ✅ +2  305 💤 ±0  0 ❌ ±0 

Results for commit 8c9eff0. ± Comparison against base commit e6a1945.

♻️ This comment has been updated with latest results.

@rbuergi

rbuergi commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Blocked on Systemorph/MeshWeaver.Plugins#685 — by design, and the gate proved it.

The Landed modules compile against this PR job is red with exactly the failure the cross-repo audit predicted:

error MSB9008: The referenced project src/MeshWeaver.AI.Application/MeshWeaver.AI.Application.csproj
does not exist. [plugins-repo/src/MeshWeaver.Blazor.Portal/MeshWeaver.Blazor.Portal.csproj]

The plugins repo keeps its own copy of MeshWeaver.Blazor.Portal, and its csproj carried a ships-the-bits ProjectReference to the project this PR deletes — the same reference core's copy had, and the same reason the application was dead code: it shipped in the closure while listed under no Modules:Assemblies, so nothing ever read its assembly attribute. Nothing there uses the project; the only mention is a comment.

Plugins#685 drops it, verified building that project against both core main (0 errors) and this branch with the project already deleted (0 errors) — so it is safe to land first and does not wait on this PR. Merge order: Plugins#685 → this.

The other red, AiContentPackDriftTest, was main's own — fixed by #2288, which merged after this branch was cut. origin/main is now merged in.

@rbuergi
rbuergi merged commit 25a372d into main Aug 25, 2026
26 checks passed
rbuergi added a commit that referenced this pull request Aug 25, 2026
…n build cannot

`FrameworkBuildIdentityTest.CanonicalList_MatchesTheTesterClosure` went red: the canonical
`FrameworkBuildIdentity.ContentSurfaceAssemblies` list is the surface in-mesh CONTENT may compile
against, and it is pinned to the bake host's project closure. Adding `MeshWeaver.Mesh.Operations`
puts a new assembly in that closure — through `MeshWeaver.AI`, which the tester references — so the
list has to gain it or the two drift.

A real finding, not a flake, and worth noting HOW it was found: a full solution build cannot see it
(everything compiles either way), and it is the closure of a TOOL rather than of anything the diff
names. The gate recomputes the closure from the csproj graph precisely so the list cannot silently
fall behind.

Also merges origin/main (#2297 landed).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rbuergi
rbuergi deleted the refactor/ai-application-folds-in branch August 28, 2026 08:56
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