Skip to content

Delete Blazor and the portal GUI from core - #2293

Merged
rbuergi merged 20 commits into
mainfrom
feat/delete-blazor-and-gui-from-core
Aug 26, 2026
Merged

rbuergi merged 20 commits into
mainfrom
feat/delete-blazor-and-gui-from-core

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Stacked on #2285 (the infrastructure lift), which has to land first — this deletes the projects
that lift empties of platform code.

Core ends up with no GUI at all. 389 files, 54,428 lines deleted.

src/MeshWeaver.Blazor                  112 files
src/MeshWeaver.Blazor.Portal           102
src/MeshWeaver.Hosting.Blazor           10
memex/Memex.Portal.Shared               29 GUI files  (77 platform files STAY)
memex/Memex.Portal.{Monolith,Distributed}, Memex.AppHost   — the hosts
test/MeshWeaver.Hosting.Blazor.Test     32  (it tests deleted code)

🚨 The test sweep was wrong three times before it was right

Selecting test files by "imports a Blazor namespace" is a proxy for "is a view test", and the two
are different sets. That predicate selected 27 files. The compiler says 16 actually need a
view type. Among the 11 it would have exiled for an unused using:

OrleansTopLevelPartitionGuardTest — the top-level partition guard. It imports Blazor.Portal
for silo wiring whose extensions (ConfigureMeshWeaverServer, UseOrleansMeshServer) all live in
core
. It compiles fine without the import.

Eight MeshWeaver.Hosting.PostgreSql.Test files were the same shape. Name-matching fared no
better
— it misses MessageBubbleState, CompletionItem and MarkdownCellEditing, view types
that don't end in View or Page.

What works is neither: strip the import and let the compiler classify. Every file that stays lost
one stale using and nothing else — which is why the diff shows PartitionAccessTest.cs | 1 -
rather than a deletion.

Two checks that earned their place

  • Test-count diff across the eight affected suites: −244 removed against 244 expected, exact.
    It took three attempts to measure correctly (wrong checkout, then obj/ copies) — and each wrong
    version showed a suite gaining tests from a deletion, which is the only reason I caught them.
  • Guard/ratchet name check: named the partition guard before the compiler would have.

The ratchet that was one predicate away

NodeTypeDeclarationSelfTypingTest stays in core and still runs — verified build exit=0, then
2/2 passed (an earlier run reported "Passed" while the build had exited 1, i.e. against a stale DLL;
that result was discarded). It guards a defect measured at 3.2 failures/second on every serving
pod
, and its absence is silent by construction.

Two stragglers no source-level check could see

MSBuild <Content Include> items in Acme.Test copying CSS out of the deleted projects. Not
usings, not ProjectReferences, not C# — only a full-solution build surfaces them.

Verification

Full solution: -c Release -warnaserror, 0 warnings, 0 errors. The final pass was incremental,
so CI's clean checkout remains the real test of a from-scratch build.

No What's New entry: no user-visible change — the portal builds from a different repo and nothing
about it changes for a viewer.

Core no longer contains any GUI. The three Blazor projects, the portal's razor,
and the hosts that serve them move to MeshWeaver.Plugins, where the view packs
already live.

  src/MeshWeaver.Blazor              112 files
  src/MeshWeaver.Blazor.Portal       102
  src/MeshWeaver.Hosting.Blazor       10
  memex/Memex.Portal.Shared           29 GUI files (77 platform files STAY)
  memex/Memex.Portal.Monolith        ┐
  memex/aspire/Memex.Portal.Distributed  ├ hosts
  memex/aspire/Memex.AppHost         ┘
  test/MeshWeaver.Hosting.Blazor.Test 32 files (it tests deleted code)

🚨 The test sweep was WRONG THREE TIMES before it was right, and the wrong
versions all looked reasonable.

Selecting test files by "imports a Blazor namespace" is a proxy for "is a view
test", and the two are different sets. That predicate selected 27 files; the
compiler says only 16 of them actually need a view type. Among the 11 it would
have exiled for an unused `using`:

  OrleansTopLevelPartitionGuardTest — the top-level partition guard. It imports
  Blazor.Portal for silo wiring whose extensions (ConfigureMeshWeaverServer,
  UseOrleansMeshServer) all live in CORE. It compiles fine without the import.

Eight MeshWeaver.Hosting.PostgreSql.Test files were the same shape. Name-matching
fared no better: it misses MessageBubbleState, CompletionItem and
MarkdownCellEditing, which are view types that do not end in View or Page.

What works is neither: strip the import and let the COMPILER classify. Every
file that stays here lost one stale `using` and nothing else.

Two checks earned their place, both suggested in review:
  • test COUNT diff across the eight affected suites — -244 removed against 244
    expected, exact. It took three attempts to measure correctly (a wrong
    checkout, then obj/ copies), and each wrong version showed a suite GAINING
    tests from a deletion, which is the only reason I caught them.
  • guard/ratchet name check — it named the partition guard before the compiler
    would have.

Also verified: NodeTypeDeclarationSelfTypingTest STAYS in core and still runs
(build exit=0 then 2/2 passed). It guards a defect measured at 3.2 failures per
second on every serving pod, its absence is silent by construction, and it was
one predicate away from being swept out.

And two stragglers no source-level check could see: MSBuild <Content Include>
items in Acme.Test copying CSS out of the deleted projects. Only a full-solution
build surfaces those.

Full solution builds clean: -c Release -warnaserror, 0 warnings, 0 errors.
…rojects

CI's clean checkout caught what my local build could not: two MSB3030 failures
copying src/MeshWeaver.Blazor/wwwroot/standard-page-layout.css and
src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor.css, both of which
this change deletes.

🚨 The fix existed locally and never reached the commit. I edited the csproj
AFTER the last `git add`, then collapsed the WIP history with `git reset --soft`
— which preserves STAGED content and leaves working-tree edits behind. The
local build then passed against a tree the commit did not contain.

That is the same shape as the stale-DLL trap earlier tonight: a green signal
measuring something other than what was about to ship. The remedy is the same —
the authority is the clean build, not the one with my uncommitted work in it.
…ucture-out-of-blazor' into feat/delete-blazor-and-gui-from-core
@rbuergi
rbuergi marked this pull request as draft August 25, 2026 22:28
@rbuergi

rbuergi commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

🚧 Back to draft — this must not merge yet.

It deletes 77 test files plus MemexConfiguration.cs from core, and those are not yet present in MeshWeaver.Plugins. They are staged locally, which is not the same thing. Merging as it stands would delete the coverage rather than move it — which is precisely the failure this PR's own description argues against.

Remaining before it is mergeable:

  • place the 77 staged test files in plugins (they span 11 former core suites and need homes: the Blazor.Portal ones, the portal-Gui ones, and MeshWeaver.Hosting.Blazor.Test which moves whole)
  • MemexConfiguration.cs is now placed in Memex.Portal.Gui on Plugins#674, but that PR has to land first

The core-side deletion itself is verified and unchanged: full solution builds clean under -c Release -warnaserror.

…ucture-out-of-blazor' into feat/delete-blazor-and-gui-from-core

# Conflicts:
#	test/Memex.Portal.Shared.Test/AppleAuthenticationTest.cs
@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

    9 files  ±  0      9 suites  ±0   5m 24s ⏱️ -20s
2 023 tests +213  2 022 ✅ +217  1 💤  - 4  0 ❌ ±0 
2 572 runs  +213  2 571 ✅ +217  1 💤  - 4  0 ❌ ±0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 54 and adds 267 tests. Note that renamed tests count towards both.
MeshWeaver.ContentCollections.Test.ContentCollectionClaimApplyRaceTest ‑ TornIngestOvertakenBetweenClaimAndPost_CannotOverwriteTheLaterTriggeredArticle
MeshWeaver.ContentCollections.Test.ContentCollectionIngestOrderTest ‑ TornReadFromTheCreatedEvent_CannotOverwriteTheCompleteArticle
MeshWeaver.ContentCollections.Test.ContentCollectionWriteIngestTest ‑ SaveFile_ingests_the_article_without_the_watcher
MeshWeaver.ContentCollections.Test.ContentCollectionWriteReadRaceTest ‑ Write_Succeeds_While_A_Concurrent_Read_Holds_The_File
MeshWeaver.ContentCollections.Test.ContentServiceDelegationTest ‑ ContentService_ShouldDelegateToParent
MeshWeaver.ContentCollections.Test.ImageContentGuardTest ‑ FileContentProvider_Guards_Image_Returns_Placeholder_Not_Bytes
MeshWeaver.ContentCollections.Test.MapContentCollectionTest ‑ MapContentCollection_ShouldNotCauseStackOverflow
MeshWeaver.ContentCollections.Test.NodeHubContentCollectionTest ‑ CollectionNamedArea_RendersBrowserForFolder_AndContentForFile
MeshWeaver.ContentCollections.Test.NodeHubContentCollectionTest ‑ CollectionNamedArea_UrlDecodesEncodedPathSegments
MeshWeaver.ContentCollections.Test.NodeHubContentCollectionTest ‑ Hidden_Storage_Collection_Not_In_GetAllCollectionConfigs
…
MeshWeaver.Hosting.Sqlite.Test.MemexInstanceBootstrapTest ‑ Instances_are_nodes_and_read_back_via_GetQuery
MeshWeaver.Hosting.Sqlite.Test.SqliteEventLogStoreTest ‑ Append_is_idempotent_by_path_kind_version
MeshWeaver.Hosting.Sqlite.Test.SqliteEventLogStoreTest ‑ ReadFrom_and_cursor_roundtrip
MeshWeaver.Hosting.Sqlite.Test.SqliteMonolithMeshTest ‑ Create_read_and_query_a_node_through_a_monolith_mesh_on_sqlite
MeshWeaver.Hosting.Sqlite.Test.SqliteQueryTests ‑ Query_nodeType_filters_by_type
MeshWeaver.Hosting.Sqlite.Test.SqliteQueryTests ‑ Query_scope_children_returns_only_direct_children
MeshWeaver.Hosting.Sqlite.Test.SqliteQueryTests ‑ Query_scope_descendants_includes_nested_nodes
MeshWeaver.Hosting.Sqlite.Test.SqliteRawBootstrapTest ‑ Raw_monolith_mesh_bootstrap_on_sqlite_creates_and_reads_a_node
MeshWeaver.Hosting.Sqlite.Test.SqliteStorageAdapterTests ‑ Changes_feed_emits_Deleted_on_delete
MeshWeaver.Hosting.Sqlite.Test.SqliteStorageAdapterTests ‑ Changes_feed_emits_Updated_on_write
…

♻️ 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)

593 tests   - 613   589 ✅  - 617   14m 34s ⏱️ - 2m 21s
  7 suites  -   2     4 💤 +  4 
  7 files    -   2     0 ❌ ±  0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 832 and adds 219 tests. Note that renamed tests count towards both.
MeshWeaver.Autocomplete.Test.MonacoCompletionSessionTest ‑ Dispose_ClosesTheActiveSubscription
MeshWeaver.Autocomplete.Test.MonacoCompletionSessionTest ‑ FirstQuery_SubscribesOnce_PushesSnapshotsKeyedByQuery
MeshWeaver.Autocomplete.Test.MonacoCompletionSessionTest ‑ StreamError_ReportsTheFailingQuery
MeshWeaver.Autocomplete.Test.MonacoCompletionSessionTest ‑ SupersededQuery_SnapshotIsNeverServedForTheNewTrigger
MeshWeaver.Autocomplete.Test.MonacoCompletionSessionTest ‑ SynchronousEmissionOnSubscribe_IsReturnedByTheFirstCall
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunkCount_EqualsNumberOfChunks
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunkCount_UnknownFile_IsZero
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunk_OutOfRange_ReturnsNull
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunk_ReturnsChunkAtIndex
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunk_UnknownFile_ReturnsNull
…
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_AppPath_ReturnsPrefixAndRemainder
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_CaseInsensitive_MatchesCorrectly
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_EmptyPath_ReturnsNull
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_ExactMatch_ReturnsNullRemainder
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_MultipleNodes_HighestScoreWins
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_NullPath_ReturnsNull
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_SegmentWithSpace_ResolvesToExactNode
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_SingleSegmentNode_MatchesAndReturnsRemainder
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_SpaceSegmentWithAreaSuffix_FallsBackToNode
MeshWeaver.PathResolution.Test.AddressResolutionTest ‑ ResolvePath_ThreadMessageNode_ResolvesToFullMessagePath
…

♻️ 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)

    9 files   -   1      9 suites   - 1   7m 5s ⏱️ +17s
1 612 tests +302  1 611 ✅ +302  1 💤 ±0  0 ❌ ±0 
1 613 runs  +302  1 612 ✅ +302  1 💤 ±0  0 ❌ ±0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 77 and adds 379 tests. Note that renamed tests count towards both.
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ Overview_RendersChangeSubjectButton
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ Overview_RendersSubjectPickerQueries
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ Thumbnail_ClickRemoveRole_RemovesRole
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ Thumbnail_ClickRemoveUser_DeletesAssignment
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ Thumbnail_RendersStackControl
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ UpdateAccessObject_CanSelectAnyNodeType_ViaDataChange
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ UpdateAccessObject_ChangesSubject_ViaDataChange
MeshWeaver.AccessControl.Test.AccessAssignmentThumbnailTest ‑ UpdateAccessObject_RejectsEmpty_Validation
MeshWeaver.AccessControl.Test.AccessThumbnailDeniedFallbackTest ‑ DeniedSubjectRead_IsClassifiedBenign_NoToast
MeshWeaver.AccessControl.Test.AccessThumbnailDeniedFallbackTest ‑ ShouldSurfaceStreamError_SwallowsAccessDenied_SurfacesInfraFaults
…
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunkCount_EqualsNumberOfChunks
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunkCount_UnknownFile_IsZero
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunk_OutOfRange_ReturnsNull
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunk_ReturnsChunkAtIndex
MeshWeaver.ContentCollections.Indexing.Test.ChunkNavigationStoreTest ‑ GetChunk_UnknownFile_ReturnsNull
MeshWeaver.ContentCollections.Indexing.Test.ContentChunkSearchTest ‑ Grammar_EmptyText_ReturnsHint_NoHits
MeshWeaver.ContentCollections.Indexing.Test.ContentChunkSearchTest ‑ Grammar_NamespaceFromDefault_WhenNoNamespaceToken
MeshWeaver.ContentCollections.Indexing.Test.ContentChunkSearchTest ‑ Grammar_NamespaceTokenWins_OverDefault
MeshWeaver.ContentCollections.Indexing.Test.ContentChunkSearchTest ‑ Grammar_NoNamespaceAndNoDefault_ReturnsHint_NoHits
MeshWeaver.ContentCollections.Indexing.Test.ContentChunkSearchTest ‑ Grammar_NoScope_DefaultsToSubtree
…

♻️ 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 064 tests   - 108   2 061 ✅ +188   12m 32s ⏱️ +35s
   10 suites +  1       3 💤  - 296 
   10 files   +  1       0 ❌ ±  0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 575 and adds 467 tests. Note that renamed tests count towards both.
MeshWeaver.Acme.Test.AcmeSearchTest ‑ AcmeIndexLinks_ResolveWithoutPathDuplication
MeshWeaver.Acme.Test.AcmeSearchTest ‑ AcmeOrganization_IsAccessibleToAuthenticatedUser
MeshWeaver.Acme.Test.AcmeSearchTest ‑ DescendantsSearch_FindsOrganizationRootNode
MeshWeaver.Acme.Test.AcmeSearchTest ‑ PortalSearch_WithContextSearch_FindsAcme
MeshWeaver.Acme.Test.AcmeSearchTest ‑ SearchSuggestions_FreeText_BindsWholeCollectionContainingMatch
MeshWeaver.Acme.Test.AcmeSearchTest ‑ SubtreeSearch_FindsOrganizationRootNode
MeshWeaver.Acme.Test.MessageBubbleStateEqualityTest ‑ BothNullLists_IdenticalScalars_AreEqual
MeshWeaver.Acme.Test.MessageBubbleStateEqualityTest ‑ DifferentToolCallContent_AreNotEqual
MeshWeaver.Acme.Test.MessageBubbleStateEqualityTest ‑ EmptyVsNullList_AreEqual
MeshWeaver.Acme.Test.MessageBubbleStateEqualityTest ‑ IdenticalContent_DistinctListInstances_AreEqual
…
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ Every_localization_key_the_about_tab_reads_exists_in_the_catalog
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ StartedAt_is_rendered_in_the_viewers_zone_not_utc
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ StartedAt_renders_nothing_when_the_start_time_is_unknown
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ ToRows_maps_manifests_to_display_rows
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ UpdateStatusMarkdown_renders_both_verdicts_and_nothing_when_unknown
Memex.Portal.Shared.Test.ApiTokenBasicAuthTest ‑ ATokenContainingAColonSurvives
Memex.Portal.Shared.Test.ApiTokenBasicAuthTest ‑ BasicWithoutAColonYieldsNoToken
Memex.Portal.Shared.Test.ApiTokenBasicAuthTest ‑ BasicYieldsThePasswordHalf(username: \"\")
Memex.Portal.Shared.Test.ApiTokenBasicAuthTest ‑ BasicYieldsThePasswordHalf(username: \"anything\")
Memex.Portal.Shared.Test.ApiTokenBasicAuthTest ‑ BasicYieldsThePasswordHalf(username: \"nuget\")
…

♻️ 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)

2 046 tests  +216   1 853 ✅ + 23   8m 9s ⏱️ - 1m 19s
    9 suites  -   1     193 💤 +193 
    9 files    -   1       0 ❌ ±  0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 405 and adds 621 tests. Note that renamed tests count towards both.
MeshWeaver.Hosting.Sqlite.Test.MemexInstanceBootstrapTest ‑ Instances_are_nodes_and_read_back_via_GetQuery
MeshWeaver.Hosting.Sqlite.Test.SqliteEventLogStoreTest ‑ Append_is_idempotent_by_path_kind_version
MeshWeaver.Hosting.Sqlite.Test.SqliteEventLogStoreTest ‑ ReadFrom_and_cursor_roundtrip
MeshWeaver.Hosting.Sqlite.Test.SqliteMonolithMeshTest ‑ Create_read_and_query_a_node_through_a_monolith_mesh_on_sqlite
MeshWeaver.Hosting.Sqlite.Test.SqliteQueryTests ‑ Query_nodeType_filters_by_type
MeshWeaver.Hosting.Sqlite.Test.SqliteQueryTests ‑ Query_scope_children_returns_only_direct_children
MeshWeaver.Hosting.Sqlite.Test.SqliteQueryTests ‑ Query_scope_descendants_includes_nested_nodes
MeshWeaver.Hosting.Sqlite.Test.SqliteRawBootstrapTest ‑ Raw_monolith_mesh_bootstrap_on_sqlite_creates_and_reads_a_node
MeshWeaver.Hosting.Sqlite.Test.SqliteStorageAdapterTests ‑ Changes_feed_emits_Deleted_on_delete
MeshWeaver.Hosting.Sqlite.Test.SqliteStorageAdapterTests ‑ Changes_feed_emits_Updated_on_write
…
MeshWeaver.Documentation.Test.BlockingBridgeInTestRatchetGuard ‑ NoNewTestBridgesAnObservableToABlockingWait
MeshWeaver.Documentation.Test.BlockingBridgeInTestRatchetGuard ‑ TheScannerFindsTheShapeItIsRatcheting
MeshWeaver.Documentation.Test.BlockingBridgeSelfDeadlockMechanismTest ‑ AwaitingInstead_UnderTheSameCapturedContext_CompletesPromptly
MeshWeaver.Documentation.Test.BlockingBridgeSelfDeadlockMechanismTest ‑ BlockingBridge_UnderASingleThreadedCapturedContext_Deadlocks
MeshWeaver.Documentation.Test.BrowserProvisioningGateGuard ‑ EveryBrowserProvisioner_BanksTheDownloadBeforeApt
MeshWeaver.Documentation.Test.BrowserProvisioningGateGuard ‑ EveryBrowserProvisioner_TreatsADependencyFailureAsAWarning
MeshWeaver.Documentation.Test.CessionExampleTest ‑ CedeIntoLayer_AllSampleClaims_CorrectTotals
MeshWeaver.Documentation.Test.CessionExampleTest ‑ CedeIntoLayer_ClaimAboveLimit_CappedAtLimit
MeshWeaver.Documentation.Test.CessionExampleTest ‑ CedeIntoLayer_ClaimBelowAttachment_FullyRetained
MeshWeaver.Documentation.Test.CessionExampleTest ‑ CedeIntoLayer_ClaimWithinLayer_PartiallyCeded
…

♻️ 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)

2 831 tests   - 605   2 728 ✅  - 708   9m 11s ⏱️ -34s
    9 suites +  1     103 💤 +103 
    9 files   +  1       0 ❌ ±  0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 781 and adds 176 tests. Note that renamed tests count towards both.
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ Every_localization_key_the_about_tab_reads_exists_in_the_catalog
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ StartedAt_is_rendered_in_the_viewers_zone_not_utc
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ StartedAt_renders_nothing_when_the_start_time_is_unknown
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ ToRows_maps_manifests_to_display_rows
Memex.Portal.Shared.Test.AboutSettingsTabTest ‑ UpdateStatusMarkdown_renders_both_verdicts_and_nothing_when_unknown
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ AiMenu_Seeds_NewThread_First
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ NewThread_Carries_No_Href_So_It_Stays_Imperative
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ NewThread_Icon_Is_LanguageNeutral
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ NewThread_Routes_To_The_Users_Own_Composer_In_Main
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ Only_The_Imperative_Entry_Stays_Compiled
…
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ ChildPolicyFurtherRestrictsSinglePermission
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ DenyOnChildBlocksSubtree
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ DirectUserAllowCreatesEffectivePermission
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ DirectUserDenyBlocksPermission
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ GetEffectivePermissions
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ GroupExpansionGrantsMembersAccess
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ HierarchicalPromotionAllowOnParentGrantsChild
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ ManualRebuildProducesSameResults
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ MostSpecificPrefixWins
MeshWeaver.Hosting.Snowflake.Test.AccessControlTests ‑ MultiplePoliciesAccumulate
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    53 files   -   2      53 suites   - 2   56m 57s ⏱️ - 3m 43s
11 169 tests  - 595  10 864 ✅  - 595  305 💤 ±0  0 ❌ ±0 
11 719 runs   - 595  11 414 ✅  - 595  305 💤 ±0  0 ❌ ±0 

Results for commit 2e83a93. ± Comparison against base commit f98a96b.

This pull request removes 595 tests.
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ AiMenu_Seeds_NewThread_First
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ NewThread_Carries_No_Href_So_It_Stays_Imperative
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ NewThread_Icon_Is_LanguageNeutral
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ NewThread_Routes_To_The_Users_Own_Composer_In_Main
Memex.Portal.Shared.Test.AiMenuNewThreadTest ‑ Only_The_Imperative_Entry_Stays_Compiled
Memex.Portal.Shared.Test.AppleAuthenticationTest ‑ AddAppleAuthentication_PrivateKeyWithoutTeamOrKeyId_FailsFastNamingTheKey(teamId: \"TEAM123456\", keyId: null, expectedInMessage: \"Authentication:Apple:KeyId\")
Memex.Portal.Shared.Test.AppleAuthenticationTest ‑ AddAppleAuthentication_PrivateKeyWithoutTeamOrKeyId_FailsFastNamingTheKey(teamId: null, keyId: \"KEY1234567\", expectedInMessage: \"Authentication:Apple:TeamId\")
Memex.Portal.Shared.Test.AppleAuthenticationTest ‑ AddAppleAuthentication_WithPrivateKey_GeneratesClientSecretFromKey
Memex.Portal.Shared.Test.AppleAuthenticationTest ‑ AddAppleAuthentication_WithStaticSecretOnly_FallsBackToClientSecret
Memex.Portal.Shared.Test.AppleAuthenticationTest ‑ AddAppleAuthentication_WithoutClientId_RegistersNoScheme
…

♻️ This comment has been updated with latest results.

rbuergi and others added 4 commits August 26, 2026 08:04
The deletion took MemexConfiguration.cs with the GUI, but it is not GUI. It is
1644 lines referenced by 7 core test projects (AI, Content, ContentCollections,
GitSync, Hosting.Monolith, Hosting.PostgreSql, PluginCatalog) and by core src —
Documentation, AI/Connect, Graph configuration, Mesh.Contract FeatureFlags.

Portal.Shared splits rather than moving: the ~29 GUI files (razor/css/png) leave,
the platform half stays. This restores the one non-GUI file the deletion caught.

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

# Conflicts:
#	memex/Memex.Portal.Monolith/appsettings.json
#	memex/Memex.Portal.Shared/Authentication/EaGraphAuth.cs
#	memex/aspire/Memex.Portal.Distributed/Program.cs
#	memex/aspire/Memex.Portal.Distributed/RequiredModulesHealthCheck.cs
#	memex/aspire/Memex.Portal.Distributed/appsettings.json
#	src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor.cs
#	src/MeshWeaver.Blazor.Portal/MeshWeaver.Blazor.Portal.csproj
#	src/MeshWeaver.Blazor/Components/DispatchView.razor
#	src/MeshWeaver.Blazor/Components/LayoutAreaView.razor
#	src/MeshWeaver.Blazor/wwwroot/standard-page-layout.css
#	test/Memex.Portal.Shared.Test/RequiredModulesHealthCheckTest.cs
…goes

Portal.Shared splits rather than moving wholesale, so this file has to split
too. It was the portal's composition root AND the mesh configuration entry
point; only the second is what core uses.

Moves out with the portal host (they had ZERO remaining callers in core — the
callers were the deleted Monolith/Distributed Program.cs):

  ConfigureMemexServices        402 lines  ASP.NET + Blazor service wiring
  StartMemexApplication<TApp>   429 lines  Blazor HTTP pipeline (TApp : IComponent)
  ConfigureMemexPortal           60 lines  per-circuit portal hub config
  AddMeshViews                   21 lines  razor page assemblies
  AiMenuItems + registration     35 lines  click-sentinel resolved in the circuit

Stays, untouched, because 7 core test projects and core src use it:
ConfigureMemexMesh, plus ValidateContentStorageDurability,
ReportUnloadedActivatedModules and the If<T> helper. 1644 -> 691 lines.

Two things the portal GUI module must now contribute, both via
MeshNodeProviderAttribute rather than core naming a Blazor type:
  • the portal address type (was .AddPortalType() inside ConfigureMemexMesh)
  • the AI top-bar "New thread" entry (was AiMenuItems)

A grep for "Blazor" said ConfigureMemexMesh was already clean. It was not —
PortalLayoutBase and AddPortalType carry no "Blazor" in the name, and only the
compiler found them. Classify by compiler, not by name.

Verified: solution build -c Release -warnaserror --no-incremental, 117 projects,
0 Warning(s) 0 Error(s), 138s — a real compile, not an up-to-date no-op.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deleting the GUI takes two of this repo's three surface-manifest hosts with it:
Memex.Portal.Monolith and Memex.Portal.Distributed move to MeshWeaver.Plugins,
leaving only MeshWeaver.PluginTester here. So
CanonicalContentSurface_IsRecordedByEverySurfaceManifestHost failed on its
HaveCountGreaterThan(1) — correctly. Its own reason says a run that finds one
project "has verified nothing", and that is exactly what happened.

This matters more than a red test. That assertion is the pin for #1814, where
mw-plugin-test and memex-portal-ai resolved different framework identities, every
bake published to an address nobody read, publication stayed GREEN, and pods
recompiled everything at boot — two hours of course covers on a fallback card.
Those two hosts are precisely the pair the GUI move puts in separate repos, so
the split recreates that topology and no single-repo test can compare them again.

Relaxing >1 to >0 was the wrong fix twice over: it reads as a pass for a broken
discovery, and it silently drops the invariant instead of relocating it. Instead
the check splits along the same line the code did — each repo asserts ITS hosts
carry the complete canonical surface, and the two halves together are the old
check:

  here    every surface-manifest host in this tree is complete, and the tester is
          pinned BY NAME so a broken discovery cannot pass by matching some other
          csproj
  plugins the identical closure check against its portal host — owed by the PR
          that brings the portal in (#674), and required before #2293 can land

Verified: 23/23 in MeshWeaver.Graph.Test, fresh trx.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rbuergi and others added 6 commits August 26, 2026 08:38
AiResolutionSeamAuditTest asserts every AI-resolution entry point goes through
AiSourceCatalog rather than reading nodes directly. One of its entry points —
src/MeshWeaver.Blazor.Portal/Chat/ThreadChatView.razor.cs, pinned on
ObserveResolvedModels( — moves to MeshWeaver.Plugins with the GUI, so the audit
fails with "Entry point moved or vanished".

That assertion is doing real work and must not simply be dropped: it is what
stops direct node access creeping back into the chat view's model resolution.
Verified the invariant still HOLDS at the destination before touching this —
ObserveResolvedModels( is present in that repo's copy of the file — so what
changes is where it is asserted, not whether it is true.

Same treatment as the surface-manifest pin: this list stays authoritative for
the entry points still in THIS repo, and the plugins-side audit owns the one
that left. Neither half alone is the old check.

18/18 in MeshWeaver.AI.Test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ucture-out-of-blazor' into feat/delete-blazor-and-gui-from-core

# Conflicts:
#	memex/Memex.Portal.Shared/Authentication/EaGraphAuth.cs
PortalOverlayLayeringTest asserts the layering contract between the portal
header and the toast container, reading PortalLayoutBase.razor.css and
standard-page-layout.css. Both stylesheets left with the GUI, and this PR had
already removed the Content links that fed them to the test — so the test was
failing here on a subject that no longer exists in this repo.

Deleted only AFTER the destination was confirmed, not on the assumption that
"the GUI moved": Plugins#693 is merged, the test runs there against both
stylesheets (3/3, PortalCss/ populated in the output). Verified by presence in
plugins main, then removed here.

The reverse order — delete first, port later — is how the same split silently
lost the dark-mode render-error fix earlier tonight: the code reached the
destination while the check that verifies it stayed behind, and the destination
looked complete because the file was there.

Acme.Test builds -c Release -warnaserror, 0 warnings, 0 errors.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Memex.Portal.Shared still carried PackageReferences to
Microsoft.FluentUI.AspNetCore.Components and .Components.Icons. Nothing uses
them: the razor that did left with the GUI, and zero .cs files in the project
reference the namespace. Proven rather than assumed — removing them and
rebuilding -c Release -warnaserror --no-incremental gives 0 warnings, 0 errors,
which a live dependency could not.

This is the literal goal: no GUI packages on core. After it, core's tracked tree
contains zero .razor, .razor.cs and .razor.css files, and zero tracked files
under MeshWeaver.Blazor, MeshWeaver.Blazor.Portal and MeshWeaver.Hosting.Blazor
(the directories left on disk are stale bin/obj from earlier builds).

MeshWeaver.Hosting.AspNetCore was already clean: its only match for
Microsoft.AspNetCore.Components is a COMMENT explaining that these projects were
Blazor-free, which is what made lifting the portal infrastructure into it
possible in the first place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ErrorPageRouteTest reflects over typeof(ErrorRoutes).Assembly — core's
Memex.Portal.Shared — and asserts the exception-handler path is served by a
routable component. This PR deletes every routable component from that assembly
while ErrorRoutes stays, so after the deletion the test reflects over an assembly
with the constant and no components. It cannot pass, and worse, its sibling
assertion ("a path no component serves is absent from the route templates") would
pass VACUOUSLY over an empty set — the exact shape a reviewer flagged on the
plugins side.

🚨 This is the one relocation in this change where "verify the destination by
RUNNING it" could NOT be satisfied, and I am recording that rather than implying
otherwise. Memex.Portal.Gui does not compile against core main today: the move
COPIED SeoHead/Onboarding/MainLayout/PlatformUpdateIndicator without deleting the
originals, so both copies land in one compilation (RZ9985 "Multiple components
use the tag", CS0436) — measured on the plugins side, and all four are on this
PR's deletion list. THIS deletion is what unblocks that build.

So the order is forced and the window is real:
  1. plugins #674 merges — GUI broken-but-inert, nothing compiles it
  2. THIS PR lands — the duplicates die, Gui becomes buildable
  3. the plugins-side job + relocated ErrorPageRouteTest land — first compile of
     the moved hosts, and the first run of this guard at its destination

Between 2 and 3 the guard runs nowhere. That is inherent to the ordering, not an
oversight: it cannot run before the assembly it targets can build. It is carried
on the plugins branch feat/portal-hosts-tested-v2 and lands at step 3, where both
directions get proven — route deleted ⇒ red, and component set non-empty so it is
aimed at Memex.Portal.Gui rather than vacuously green.

Memex.Portal.Shared.Test builds -c Release -warnaserror, 0 warnings, 0 errors.

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

rbuergi commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up: this PR silently drops MeshWeaver.AI from the image

Not a review of the Blazor removal itself — a specific consequence I found while working #2276, with the fix.

MeshWeaver.AI.dll reaches the portal image through exactly one chain:

Memex.Portal.Distributed → Memex.Portal.Shared → src/MeshWeaver.Blazor.Portal → MeshWeaver.AI

src/MeshWeaver.Blazor.Portal is the only project in src/ or memex/ referencing MeshWeaver.AI.csproj (verified against origin/main). Deleting it takes AI.dll out of the app closure.

What happens then:

  • MeshWeaver.AI is not in MeshModule / MeshModuleClosure (memex/MeshModulesPublish.targets), so nothing else lays it down;
  • ResolveModulePath finds nothing, and Modules:Assemblies is skip-and-continue — one stderr line;
  • it is in Assemblies, not Required, so the required-modules health check stays Healthy.

Net: a green rollout of a portal with no AI — chat, agents, models absent, no failing probe.

The fix — one line, your choice of two

Both are legitimate; which one depends on where you intend AI to come from after the split:

  1. Keep it in the image — add MeshWeaver.AI.csproj to MeshModuleClosure in memex/MeshModulesPublish.targets, joining MeshWeaver.Social. This is the documented flip for "module whose ProjectReference is GONE", which is exactly what this PR makes it.
  2. Registry-delivered — move MeshWeaver.AI.dll from Modules:Assemblies to Modules:Required in both host appsettings, so an instance without the package fails readiness and the rollout stalls instead of silently losing AI.

(1) is the smaller step and keeps this PR self-contained; (2) is where #2276 ends up eventually.

You will not have to remember this

I have opened #2347, a guard that fails CI naming exactly this. Once it lands, your branch goes red with the message above rather than merging quietly — so please expect it, and treat it as the checklist rather than an obstacle. I verified it genuinely fails by simulating your deletion locally: red on both hosts, green again when restored.

I have deliberately not pushed the one-line fix into your branch — where AI ships from is your call, and this PR is stacked on refactor/lift-nonvisual-infrastructure-out-of-blazor, so I would rather not touch the chain.

rbuergi added a commit that referenced this pull request Aug 26, 2026
…ureSubset

The lane inventory in MeshModulesPublish.targets is shared, but a host may narrow the
CLOSURE half with MeshModulesClosureSubset — the targets remove every @(MeshModuleClosure)
the subset does not name. Reading it globally credited a host with modules its own publish
drops: a guard passing on evidence belonging to a different host, which is the one thing a
guard must never do.

The thin lane @(MeshModule) is not narrowed by the subset, so only the closure half is
filtered.

No host sets a subset today, so this closes the hole before it opens rather than fixing a
live miss. Re-verified both directions: green on the tree, and still red on BOTH hosts when
the Blazor.Portal reference is removed to simulate #2293.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rbuergi
rbuergi changed the base branch from refactor/lift-nonvisual-infrastructure-out-of-blazor to main August 26, 2026 09:40
# Conflicts:
#	memex/Memex.Portal.Shared/MemexConfiguration.cs
#	src/MeshWeaver.Blazor.Portal/Layout/PortalLayoutBase.razor.cs
#	test/Memex.Portal.Shared.Test/AiMenuNewThreadTest.cs
rbuergi added a commit that referenced this pull request Aug 26, 2026
Conflict was in the weight table only. Resolved by keeping THIS branch's
re-measured weights and applying main's removals on top — never the other way
round, which would have silently reverted merged work:

  * 2e83a93 removed MeshWeaver.MemexTemplate.Test (the template generator and
    its six projects left the repo);
  * #2293 removed MeshWeaver.Hosting.Blazor.Test (delete-blazor).

Both rows dropped. Table now reconciles EXACTLY against the tree — 52 entries,
52 test projects, no stale row and none falling through to DEFAULT_WEIGHT.
Sum 2792 -> 2758, so the split rule's worked example in the header is updated to
2758 ÷ 6 ≈ 460 s. Loads: 460 460 460 459 459 459.
rbuergi added a commit that referenced this pull request Aug 26, 2026
#2293 deleted memex/aspire/Memex.Portal.Distributed from this repo. Three workflows still
named it, so main-cd failed at its very first step for every commit on main:

    VERSION=$(dotnet msbuild memex/aspire/Memex.Portal.Distributed/... -getProperty:Version)
    ##[error]Process completed with exit code 1

promote is all-or-nothing, so NOTHING published. Production stayed up on the images it
already had — stable, but frozen, including on the deletion itself.

Repointed in main-cd.yml, edge-images.yml and release-images.yml:

1. Each checks out MeshWeaver.Plugins (path plugins-repo) and publishes the host from
   there, resolving the platform through -p:MeshWeaverRoot=${{ github.workspace }}.

2. `ref: ${{ vars.MW_PLUGINS_REF || 'main' }}` — default main, overridable by a repo
   variable, mirroring the plugins lane's own MW_PLATFORM_REF. This does NOT decouple
   "which plugins commit shipped with which core commit"; it makes that coupling steerable,
   so pinning to a known-good plugins commit during an incident is a variable change rather
   than editing a workflow under pressure.

3. VERSION now reads src/MeshWeaver.Mesh.Contract — a project that STAYS here. It must be
   computed in THIS repo: the same property resolves to 1.0.0 in the plugins tree against
   3.0.0-rc8.ci.<n> here, and an install's self-updater compares that monotonically, so a
   plugins-derived version would roll every install BACKWARDS past VersionSelect's
   monotonic-build-number assumption. Verified any core project yields the identical value.

   It stays `-getProperty:` rather than a grep of Directory.Build.props, deliberately: a
   regex keeps returning a plausible, well-formed, WRONG number after the definition moves,
   and that number gets published. And it now REFUSES on empty instead of continuing — an
   empty version becomes `:` or `latest` downstream, which is the failure where a tag exists
   and points at the wrong thing.

Root cause worth stating: this was a known-open item ("CD repoint for memex-portal-ai's
build source") that was not sequenced before the deletion merged. The question "what does
the world look like BETWEEN the two merges?" was asked of the COMPILE pairing and verified
three ways; it was never asked of the delivery pipeline. Right question, one system too
narrow.

Verified: all three files parse; every `dotnet publish` of the host resolves to
plugins-repo/src/... and carries MeshWeaverRoot; no workflow still reads Version from a
moved project; no reference to the deleted path remains anywhere under .github/workflows.
rbuergi added a commit that referenced this pull request Aug 26, 2026
#2293 deleted memex/aspire/Memex.Portal.Distributed from this repo. Three workflows still
named it, so main-cd failed at its very first step for every commit on main:

    VERSION=$(dotnet msbuild memex/aspire/Memex.Portal.Distributed/... -getProperty:Version)
    ##[error]Process completed with exit code 1

promote is all-or-nothing, so NOTHING published. Production stayed up on the images it
already had — stable, but frozen, including on the deletion itself.

Repointed in main-cd.yml, edge-images.yml and release-images.yml:

1. Each checks out MeshWeaver.Plugins (path plugins-repo) and publishes the host from
   there, resolving the platform through -p:MeshWeaverRoot=${{ github.workspace }}.

2. `ref: ${{ vars.MW_PLUGINS_REF || 'main' }}` — default main, overridable by a repo
   variable, mirroring the plugins lane's own MW_PLATFORM_REF. This does NOT decouple
   "which plugins commit shipped with which core commit"; it makes that coupling steerable,
   so pinning to a known-good plugins commit during an incident is a variable change rather
   than editing a workflow under pressure.

3. VERSION now reads src/MeshWeaver.Mesh.Contract — a project that STAYS here. It must be
   computed in THIS repo: the same property resolves to 1.0.0 in the plugins tree against
   3.0.0-rc8.ci.<n> here, and an install's self-updater compares that monotonically, so a
   plugins-derived version would roll every install BACKWARDS past VersionSelect's
   monotonic-build-number assumption. Verified any core project yields the identical value.

   It stays `-getProperty:` rather than a grep of Directory.Build.props, deliberately: a
   regex keeps returning a plausible, well-formed, WRONG number after the definition moves,
   and that number gets published. And it now REFUSES on empty instead of continuing — an
   empty version becomes `:` or `latest` downstream, which is the failure where a tag exists
   and points at the wrong thing.

Root cause worth stating: this was a known-open item ("CD repoint for memex-portal-ai's
build source") that was not sequenced before the deletion merged. The question "what does
the world look like BETWEEN the two merges?" was asked of the COMPILE pairing and verified
three ways; it was never asked of the delivery pipeline. Right question, one system too
narrow.

Verified: all three files parse; every `dotnet publish` of the host resolves to
plugins-repo/src/... and carries MeshWeaverRoot; no workflow still reads Version from a
moved project; no reference to the deleted path remains anywhere under .github/workflows.
rbuergi added a commit that referenced this pull request Aug 26, 2026
#2367: a developer following the local-dev docs from a core checkout got a portal with no
login UI and no control views. The docs said `dotnet run --project memex/Memex.Portal.Monolith`
and `memex/aspire/Memex.AppHost` -- paths #2293 deleted, together with the login pages, when the
GUI extraction moved the hosts to MeshWeaver.Plugins.

Eight files carried those commands: AGENTS.md, Readme.md, Deployment.md, LocalDevWorkflow.md,
MacLocalStack.md and three more. Every occurrence now points at
`../MeshWeaver.Plugins/src/Memex.Portal.Monolith` / `.../Memex.AppHost`, which runs UNCHANGED
from the documented working directory under the standard sibling layout -- plugins'
src/Directory.Build.props defaults MeshWeaverRoot to `../MeshWeaver`. A note at the top of
LocalDevWorkflow.md says where the hosts went, why a core checkout alone cannot run a portal,
and how to override the root if the layout differs.

The second half of #2367 (DefaultViews/GraphViews reaching a deployment only as registry
bundles) is #2169 Phase B2's decision and is not a docs matter; it is left open there.

DocumentationLinkIntegrityTest passes.
rbuergi added a commit that referenced this pull request Aug 26, 2026
The csproj said "Blazor.Portal REMAINS a compiled reference for now — it is SHELL
infrastructure (PortalLayoutBase, auth, viewport), tracked for extraction as #2169
Phase B3." #2293 completed that extraction, so the sentence became false at merge.

Caught in review ON #2293 and merged knowingly rather than fixed there: main was red on
`Landed modules compile against this PR` (the additive half of the move had landed while
the deletion half stayed open), three unrelated PRs were blocked behind it, and a
comment-only push costs a full CI cycle with main red throughout. The trade was one wrong
sentence against other people's blocked work; this is the other half of it, landing
immediately as promised on the thread.

Worth the commit rather than a silent resolve, because this is the same failure the same
PR corrected twice in ContinuousDeliveryContract.md: prose describing intent as if it were
state, sitting next to the code and outliving it. That file predicted "moving the generator
does not help" and asserted a compile gate lived somewhere it did not — one of which cost
me an afternoon and a wrong escalation to another session. A comment nobody re-reads after
the change it describes is how that happens.
rbuergi added a commit that referenced this pull request Aug 26, 2026
#2293 deleted memex/aspire/Memex.Portal.Distributed from this repo. Three workflows still
named it, so main-cd failed at its very first step for every commit on main:

    VERSION=$(dotnet msbuild memex/aspire/Memex.Portal.Distributed/... -getProperty:Version)
    ##[error]Process completed with exit code 1

promote is all-or-nothing, so NOTHING published. Production stayed up on the images it
already had — stable, but frozen, including on the deletion itself.

Repointed in main-cd.yml, edge-images.yml and release-images.yml:

1. Each checks out MeshWeaver.Plugins (path plugins-repo) and publishes the host from
   there, resolving the platform through -p:MeshWeaverRoot=${{ github.workspace }}.

2. `ref: ${{ vars.MW_PLUGINS_REF || 'main' }}` — default main, overridable by a repo
   variable, mirroring the plugins lane's own MW_PLATFORM_REF. This does NOT decouple
   "which plugins commit shipped with which core commit"; it makes that coupling steerable,
   so pinning to a known-good plugins commit during an incident is a variable change rather
   than editing a workflow under pressure.

3. VERSION now reads src/MeshWeaver.Mesh.Contract — a project that STAYS here. It must be
   computed in THIS repo: the same property resolves to 1.0.0 in the plugins tree against
   3.0.0-rc8.ci.<n> here, and an install's self-updater compares that monotonically, so a
   plugins-derived version would roll every install BACKWARDS past VersionSelect's
   monotonic-build-number assumption. Verified any core project yields the identical value.

   It stays `-getProperty:` rather than a grep of Directory.Build.props, deliberately: a
   regex keeps returning a plausible, well-formed, WRONG number after the definition moves,
   and that number gets published. And it now REFUSES on empty instead of continuing — an
   empty version becomes `:` or `latest` downstream, which is the failure where a tag exists
   and points at the wrong thing.

Root cause worth stating: this was a known-open item ("CD repoint for memex-portal-ai's
build source") that was not sequenced before the deletion merged. The question "what does
the world look like BETWEEN the two merges?" was asked of the COMPILE pairing and verified
three ways; it was never asked of the delivery pipeline. Right question, one system too
narrow.

Verified: all three files parse; every `dotnet publish` of the host resolves to
plugins-repo/src/... and carries MeshWeaverRoot; no workflow still reads Version from a
moved project; no reference to the deleted path remains anywhere under .github/workflows.
rbuergi added a commit that referenced this pull request Aug 26, 2026
…link that leaves the repo

Review on #2380 caught what the first pass missed: my rewrite matched the run/watch forms of the
portal-host path and not the build/publish ones, so LocalDevWorkflow.md's step 3 rebuild, the
AKS publish in DeploymentAKS.md and LocalColimaMac.md, and a DebuggingMessageFlow.md table row
still named memex/aspire/Memex.Portal.Distributed -- a path #2293 deleted. Every occurrence now
points at the sibling MeshWeaver.Plugins checkout, and step 3 says so in prose so a reader in a
core checkout knows why the command leaves it.

samples/Graph/README.md linked to ../../../MeshWeaver.Plugins/... -- a relative link that leaves
the repository renders broken on GitHub. Now an absolute URL.

Prose that cites old src/MeshWeaver.Blazor.Portal/... file paths as the location of PAST fixes is
left as history; only runnable commands were rewritten.
rbuergi added a commit that referenced this pull request Aug 26, 2026
… deliberate

Review: "gone from this repo entirely" overstated it. The MeshWeaver.Blazor.Portal PROJECT left
in #2293; the assembly NAME remains in InternalsVisibleTo on purpose, because that assembly now
builds in MeshWeaver.Plugins and needs the same internals it always had. A comment that says
"gone entirely" invites the next reader to delete a grant that is load-bearing.
rbuergi added a commit that referenced this pull request Aug 26, 2026
The Blazor.Portal comment described a state #2293 ended
rbuergi added a commit that referenced this pull request Aug 26, 2026
#2367: a developer following the local-dev docs from a core checkout got a portal with no
login UI and no control views. The docs said `dotnet run --project memex/Memex.Portal.Monolith`
and `memex/aspire/Memex.AppHost` -- paths #2293 deleted, together with the login pages, when the
GUI extraction moved the hosts to MeshWeaver.Plugins.

Eight files carried those commands: AGENTS.md, Readme.md, Deployment.md, LocalDevWorkflow.md,
MacLocalStack.md and three more. Every occurrence now points at
`../MeshWeaver.Plugins/src/Memex.Portal.Monolith` / `.../Memex.AppHost`, which runs UNCHANGED
from the documented working directory under the standard sibling layout -- plugins'
src/Directory.Build.props defaults MeshWeaverRoot to `../MeshWeaver`. A note at the top of
LocalDevWorkflow.md says where the hosts went, why a core checkout alone cannot run a portal,
and how to override the root if the layout differs.

The second half of #2367 (DefaultViews/GraphViews reaching a deployment only as registry
bundles) is #2169 Phase B2's decision and is not a docs matter; it is left open there.

DocumentationLinkIntegrityTest passes.
rbuergi added a commit that referenced this pull request Aug 26, 2026
…link that leaves the repo

Review on #2380 caught what the first pass missed: my rewrite matched the run/watch forms of the
portal-host path and not the build/publish ones, so LocalDevWorkflow.md's step 3 rebuild, the
AKS publish in DeploymentAKS.md and LocalColimaMac.md, and a DebuggingMessageFlow.md table row
still named memex/aspire/Memex.Portal.Distributed -- a path #2293 deleted. Every occurrence now
points at the sibling MeshWeaver.Plugins checkout, and step 3 says so in prose so a reader in a
core checkout knows why the command leaves it.

samples/Graph/README.md linked to ../../../MeshWeaver.Plugins/... -- a relative link that leaves
the repository renders broken on GitHub. Now an absolute URL.

Prose that cites old src/MeshWeaver.Blazor.Portal/... file paths as the location of PAST fixes is
left as history; only runnable commands were rewritten.
@rbuergi
rbuergi deleted the feat/delete-blazor-and-gui-from-core 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