Repository navigation
FuzzyScorer joins its own assembly's namespace — and three phantom AI imports go with it - #2349
Conversation
… phantom AI imports go
src/MeshWeaver.Data/Completion/FuzzyScorer.cs declared `namespace MeshWeaver.AI.Completion`
while shipping in MeshWeaver.Data — the only file in its own directory to do so; its two
neighbours are MeshWeaver.Data.Completion. Renamed to match the assembly it is in.
That mismatch was not cosmetic. Declaring a type in MeshWeaver.AI.Completion from
MeshWeaver.Data makes the PARENT namespace MeshWeaver.AI *exist* in the compilation of
every project that references MeshWeaver.Data — with or without the AI assembly anywhere
in sight. Three core files were importing exactly that:
src/MeshWeaver.GitSync/GitHubCredentialService.cs
src/MeshWeaver.PluginCatalog/InstanceAutoRegistrationService.cs
src/MeshWeaver.PluginCatalog/SyncTokenSigningKeyService.cs
Each carried `using MeshWeaver.AI;` resolving to an empty-but-existing namespace, and
NEITHER project has a ProjectReference to MeshWeaver.AI. They import nothing; they only
ever compiled as a side effect of the misplaced namespace, and all three broke the moment
it was fixed — which is how they were found.
The cost is exactly the one #2276 cannot afford: `git grep MeshWeaver.AI src/` reported
hits in two core projects with no dependency on AI at all. An audit of "has AI left core?"
would either chase them or conclude the extraction was incomplete when it was not.
Consumers updated: StaticNodeQueryProvider (a fully-qualified `new
MeshWeaver.AI.Completion.FuzzyScorer()` inside core hosting, plus its cref), QueryEvaluator,
ContentAutocompleteProvider, AutocompleteMultiSourceTest, and SpacesInFileNameTest — which
already imported MeshWeaver.Data.Completion, so its AI import simply went.
MeshWeaver.AI.Completion still exists for the three types that genuinely belong to it
(AutocompleteClient, AutocompleteStreamProvider, SkillAutocompleteProvider).
After this, the only MeshWeaver.AI left in core is prose comments plus one deliberate
by-name entry in Plugin.Build/CompilationEnvironment.cs — the in-mesh compile reference
set, which needs the name.
Verified: MeshWeaver.ContentCollections, MeshWeaver.PluginCatalog, MeshWeaver.Autocomplete.Test
and MeshWeaver.AI.Test all build -c Release -warnaserror at 0 Warning(s)/0 Error(s), and the
FuzzyScorer-exercising tests pass (7 + 24).
No What's New entry: internal refactor, no user-visible effect.
Closes #2344
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a namespace/assembly mismatch by moving FuzzyScorer into the MeshWeaver.Data.Completion namespace (matching its project), and updates consumers accordingly. This removes accidental “phantom” MeshWeaver.AI references in core projects that do not actually depend on the AI assembly, supporting the broader effort to keep AI concerns out of core (#2276).
Changes:
- Rename
FuzzyScorer’s namespace fromMeshWeaver.AI.CompletiontoMeshWeaver.Data.Completion. - Update core/query/autocomplete consumers to reference the corrected namespace (including XML
crefand fully-qualified construction). - Remove now-invalid/unused
using MeshWeaver.AI;imports from non-AI core projects.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/MeshWeaver.Data/Completion/FuzzyScorer.cs |
Moves FuzzyScorer into MeshWeaver.Data.Completion to match the assembly/project. |
src/MeshWeaver.Hosting/Persistence/Query/QueryEvaluator.cs |
Switches using to the corrected MeshWeaver.Data.Completion namespace. |
src/MeshWeaver.Hosting/Persistence/Query/StaticNodeQueryProvider.cs |
Updates cref and fully-qualified instantiation to MeshWeaver.Data.Completion.FuzzyScorer. |
src/MeshWeaver.ContentCollections/Completion/ContentAutocompleteProvider.cs |
Removes AI completion import; relies on MeshWeaver.Data.Completion for scoring. |
src/MeshWeaver.GitSync/GitHubCredentialService.cs |
Removes phantom using MeshWeaver.AI; from a non-AI project. |
src/MeshWeaver.PluginCatalog/InstanceAutoRegistrationService.cs |
Removes phantom using MeshWeaver.AI; from a non-AI project. |
src/MeshWeaver.PluginCatalog/SyncTokenSigningKeyService.cs |
Removes phantom using MeshWeaver.AI; from a non-AI project. |
test/MeshWeaver.Autocomplete.Test/AutocompleteMultiSourceTest.cs |
Updates test to construct the scorer from Data.Completion. |
test/MeshWeaver.AI.Test/SpacesInFileNameTest.cs |
Removes now-invalid using MeshWeaver.AI.Completion; while keeping data completion usage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Test Results 53 files 53 suites 1h 1m 55s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
…ne too The first pass swept src/ only, found three phantom `using MeshWeaver.AI;` and declared core clean. It was not: test/MeshWeaver.Graph.Test/SatelliteContentAndMenuStateTest.cs carried the same dead import, resolving to the same empty namespace MeshWeaver.Data was contributing to. CI's solution build caught it; the per-project builds could not, because none of them compiled that project. Rerunning the scan across BOTH trees reported fourteen — and acting on that would have broken four test projects. The check only looked at DIRECT ProjectReference, while NodeOperations.Test, Hosting.Monolith.Test, Security.Test and Acme.Test all reach MeshWeaver.AI TRANSITIVELY, so their usings import real types. Computing the transitive closure cuts fourteen to exactly one — Graph.Test — which is precisely what CI failed on. So the same too-narrow predicate produced both errors: first missing a tree, then over-claiming within it. Also re-verified the two src/ projects already changed against the transitive standard: MeshWeaver.PluginCatalog and MeshWeaver.GitSync genuinely cannot reach MeshWeaver.AI, so those removals were correct. Verified with a full solution build this time, not per-project ones — a namespace change has repo-wide blast radius, and per-project builds are exactly what let this through: MW_ALLOW_SOLUTION_BUILD=1 dotnet build MeshWeaver.slnx -c Release -p:CIRun=true -warnaserror → 0 Warning(s), 0 Error(s). Confirmed it was a real compile rather than an up-to-date no-op: MeshWeaver.Graph.Test.dll (11:54:33) is newer than the edited source (11:54:15). Refs #2344 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixed — my sweep was incomplete, and the correction is worth recordingCI was right and I was wrong twice, in the same direction. Miss 1 — wrong scope. I swept Miss 2 — wrong predicate. Rerunning across both trees reported 14 phantoms. Acting on that would have broken four test projects:
The check only looked at direct Same too-narrow predicate behind both: first it missed a tree, then it over-claimed within it. I also re-checked the two Verification, tightenedPer-project builds are what let this through, so this time: And confirmed it was a real compile rather than an up-to-date no-op — |
Test Results (shard 5) 9 files 9 suites 7m 4s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
Test Results (shard 3) 9 files 9 suites 5m 20s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
Test Results (shard 0)599 tests 595 ✅ 17m 4s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
Test Results (shard 1)2 027 tests 1 834 ✅ 9m 20s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
Test Results (shard 2)2 878 tests 2 775 ✅ 8m 11s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
Test Results (shard 4)2 161 tests 2 157 ✅ 14m 53s ⏱️ Results for commit 77a996d. ♻️ This comment has been updated with latest results. |
CI caught a fourth `using MeshWeaver.AI;` resolving to the empty namespace FuzzyScorer's misplaced declaration created: memex/Memex.Portal.Shared/Api/MeshApiEndpoints.cs. The earlier sweep covered src/ and test/ and stopped there, so memex/ was never looked at — the third scope miss on the same task. Swept every tree this time (src, test, memex, tools, samples), classifying by TRANSITIVE ProjectReference reachability rather than a direct reference, since four test projects legitimately reach MeshWeaver.AI through their dependencies and their imports are real. Result across the whole repository: exactly one phantom, the file above. Verified with a solution build rather than per-project ones — per-project builds are precisely what let the previous two escape: MW_ALLOW_SOLUTION_BUILD=1 dotnet build MeshWeaver.slnx -c Release -p:CIRun=true -warnaserror → EXIT=0, 0 Warning(s), 0 Error(s). Refs #2344 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixed — and the sweep is now repo-wideCI found a fourth phantom import: This time I swept every tree — Repo-wide result: exactly one phantom, the file above. Verified with a solution build rather than per-project ones, since per-project builds are exactly what let the previous two escape: |
Re-synced onto current main (was 55 commits behind)The red was Merging main here is justified on staleness, not hope: the branch was 55 commits behind, so it was re-sampling whatever main has since fixed, and every red on it looks like a defect in the change. Revert-check with three dots confirms the branch still contributes only its own files (11 changed, 5 insertions / 12 deletions), so the merge reverted nothing. Re-verified on the merged tree with a solution build — per-project builds are what let two earlier phantoms escape: If it reds again on |
Re-synced (40 commits behind) — and the plugins-gate red was a FALSE regressionRead rather than retried. The gate's own log says the compile succeeded: The failure appears after that, alongside the gate losing its own bookkeeping to a cross-hub write race: So the compile-state writes were refused as stale, the gate then read a state that did not record success, and reported 🚨 Worth stating plainly, because a namespace rename is exactly the change this gate exists to catch: had Also re-synced: the branch was 40 commits behind, so it was re-sampling whatever main has since fixed. Revert-check with three dots confirms it still contributes only its own files (11 changed, 5 insertions / 12 deletions). Re-verified on the merged tree with a solution build — per-project builds are what let two earlier phantom imports escape: |
#2349 removed `using MeshWeaver.AI;` from MeshApiEndpoints as a phantom, and main went red with CS0246. Two fixes then restored it independently — #2408 added it under a banner comment at the top of the file, #2411 added it again inline further down with its own explanation. Both landed, so main now carries the SAME using twice and fails CS0105 under warnings-as-errors. The type genuinely needs it: MeshOperations ships in assembly MeshWeaver.Mesh.Operations but keeps namespace MeshWeaver.AI, frozen by the TypeForwardedTo contract in #2370. So this keeps ONE directive and folds both explanations into the banner that sits directly above it, including why it looks removable and the fact that removing it has now cost three red-main incidents. One directive, one explanation, kept together — the two split copies are exactly how the second restore could not see the first. Verified: Memex.Portal.Shared builds clean.
Closes #2344.
The mismatch
src/MeshWeaver.Data/Completion/FuzzyScorer.csdeclarednamespace MeshWeaver.AI.Completionwhile shipping in MeshWeaver.Data — the only file in its own directory to do so:AutocompletePrefixRegistry.csMeshWeaver.Data.CompletionDataAutocompleteProvider.csMeshWeaver.Data.CompletionFuzzyScorer.csMeshWeaver.AI.Completion🚨 It was not cosmetic — it manufactured three phantom dependencies
Declaring a type in
MeshWeaver.AI.Completionfrom MeshWeaver.Data makes the parent namespaceMeshWeaver.AIexist in the compilation of every project referencingMeshWeaver.Data— with or without the AI assembly anywhere in sight.Three core files were importing precisely that:
MeshWeaver.AI?src/MeshWeaver.GitSync/GitHubCredentialService.cssrc/MeshWeaver.PluginCatalog/InstanceAutoRegistrationService.cssrc/MeshWeaver.PluginCatalog/SyncTokenSigningKeyService.csEach carried
using MeshWeaver.AI;resolving to an empty namespace. They import nothing. They only ever compiled as a side effect of the misplaced namespace, and all three broke the moment it was fixed — which is how they were found, not by inspection.The cost is the one #2276 cannot afford:
git grep MeshWeaver.AI src/reported hits in two core projects with no dependency on AI at all. An audit of "has AI left core?" would chase them, or conclude the extraction was incomplete when it was not.Consumers updated
StaticNodeQueryProvider— a fully-qualifiednew MeshWeaver.AI.Completion.FuzzyScorer()inside core hosting, plus itscrefQueryEvaluator,ContentAutocompleteProvider,AutocompleteMultiSourceTestSpacesInFileNameTest— already importedMeshWeaver.Data.Completion, so its AI import simply wentMeshWeaver.AI.Completionstill exists for the three types that genuinely belong to it (AutocompleteClient,AutocompleteStreamProvider,SkillAutocompleteProvider).Result
The only
MeshWeaver.AIleft in core is prose comments plus one deliberate by-name entry inPlugin.Build/CompilationEnvironment.cs— the in-mesh compile reference set, which needs the name.Verification
ContentCollections,PluginCatalog,Autocomplete.Test,AI.Testall build-c Release -p:CIRun=true -warnaserror→0 Warning(s),0 Error(s)No What's New entry — internal refactor, no user-visible effect.
Refs #2276
🤖 Generated with Claude Code