Skip to content

feat: social publishing + NuGet #r + move perf + mesh stability batch#95

Open
rbuergi wants to merge 1831 commits into
mainfrom
bug_fix
Open

feat: social publishing + NuGet #r + move perf + mesh stability batch#95
rbuergi wants to merge 1831 commits into
mainfrom
bug_fix

Conversation

@rbuergi

@rbuergi rbuergi commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Summary

77 commits of long-running work on bug_fix — grouped by theme:

  • Social publishing platform (new)MeshWeaver.Social + LinkedIn publisher + scheduled publishing pipeline (engine/queue/stats), LinkedIn OAuth connect + past-post ingest in Memex portal, per-user linked-account menu items.
  • NuGet in-process compile#r "nuget:Pkg, Version" at the top of _Source/*.cs resolves via public NuGet.Protocol without an SDK on the container. Same resolver serves interactive markdown code cells.
  • Move-node parallelization + 30 s ceilingFileSystemPersistenceService.MoveNodeAsync runs per-descendant WriteAsync/DeleteAsync through Task.WhenAll; new MeshOperationOptions (default Timeout = 30s) + WithMeshOperationTimeout(TimeSpan) override; HandleMoveNodeRequest chains .Timeout() on the persistence Observable so a stuck adapter can't hang the caller. Prod repro: DAV2026 subtree move that took 240 s and killed the MCP session — now bounded.
  • Compile / cache invalidation — sticky invalidation on CompilationCacheService, _Source/ edit re-invalidates owning NodeType, cross-silo broadcast via MeshChangeFeed, grain-dispose on node delete, live "Compiling … (Ns)" progress in LayoutAreaView.
  • Catalog & navigation — Children view groups by Category (falls back to NodeType), reactive Children catalog, self-as-default create location for non-NodeType nodes, sample orgs → Markdown for search visibility.
  • Workspace / stream robustness — Workspace remote-stream cache evicted on MeshChangeFeed events, resubscribe on owner dispose, DeleteLayoutArea emits a placeholder immediately and times out slow streams.
  • Infra & small fixes — settings.json overhaul, Delete-is-recursive MCP docs, HeartBeat silencing on Memex hubs, assembly-dir temp-dir fallback, IAsyncEnumerable aggregator fixes (satellite-safe GatherInputsAsync), xunit methodTimeout 30 s → 60 s, Anthropic Opus bump, icon generator, etc.

New test suites (selected)

  • test/MeshWeaver.Persistence.Test/MoveNodeRecursiveTest.cs — 10 tests: recursion, parallelism, source missing / target exists / storage throws / cancellation (all must not hang), Rx Timeout() contract, default-30s config.
  • test/MeshWeaver.Social.Test/*InMemoryPublishQueueTest, LinkedInPublisherEngagementTest, PostStatsRefresherTest, ScheduledPostPublisherTest, FakePublisher.
  • test/MeshWeaver.Persistence.Test/WorkspaceCacheEvictionTest.cs, ResubscribeOnOwnerDisposeTest.cs, DeleteLayoutAreaIntegrationTest.cs.
  • test/MeshWeaver.Markdown.Test/PathUtilsTest.cs, test/MeshWeaver.MathDemo.Test/MatrixViewsTest.cs.

Contributors

Upstream already merged into this branch

Test plan

  • dotnet build succeeds
  • dotnet test test/MeshWeaver.Persistence.Test --filter MoveNodeRecursiveTest — 10/10 green (~8 s)
  • dotnet test test/MeshWeaver.Hosting.Monolith.Test --filter MoveNodeAsync — 5/5 green (regression guard)
  • dotnet test test/MeshWeaver.Social.Test — publish queue / scheduling / stats green
  • Manual prod smoke: move a 3-descendant subtree in memex-prod; confirms < 30 s and MCP session survives
  • Create a _Source/*.cs using #r "nuget:MathNet.Numerics, 5.0.0" — compiles & renders (cold + warm cache)
  • Delete a node then recreate at same path — fresh grain, fresh compile, no stale HubConfiguration
  • Navigate to a cold node — "Compiling (Ns)…" progress renders until the stream resolves
  • LinkedIn OAuth: sign in → /social/connect/linkedin → profile linked; menu shows connected account
  • Scheduled post fires through ScheduledPostPublisher → LinkedIn publisher posts; PostStatsRefresher pulls stats

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Apr 22, 2026

Copy link
Copy Markdown

Test Results

   44 files  +    8     44 suites  +8   24m 4s ⏱️ + 17m 54s
4 650 tests +1 708  4 631 ✅ +1 702  7 💤  - 6  12 ❌ +12 
4 674 runs  +1 732  4 655 ✅ +1 726  7 💤  - 6  12 ❌ +12 

For more details on these failures, see this check.

Results for commit d66aba7. ± Comparison against base commit f6c2dea.

This pull request removes 313 and adds 2021 tests. Note that renamed tests count towards both.
MeshWeaver.AI.Test.AgentChatClientTest ‑ AgentChatClient_InitializeAsync_FindsAgentsFromPathHierarchy
MeshWeaver.AI.Test.AgentChatClientTest ‑ AgentChatClient_InitializeAsync_FindsTodoAgentFromNodeTypeNamespace
MeshWeaver.AI.Test.AgentSelectionTest ‑ AgentContext_WithPreloadedAgents_OrdersByOrder
MeshWeaver.AI.Test.AgentSelectionTest ‑ OrderByRelevance_OrdersByOrderThenDisplayName
MeshWeaver.AI.Test.AgentSelectionTest ‑ QueryAgentsAsync_PathWithoutNodeType_FindsAgentsFromPathHierarchy
MeshWeaver.AI.Test.AgentSelectionTest ‑ QueryAgentsAsync_ProductLaunchWithNodeType_FindsTodoAgentFromNodeTypeNamespace
MeshWeaver.AI.Test.AgentToolWiringIntegrationTest ‑ OrchestratorAgent_ShouldGetAllMeshTools
MeshWeaver.AI.Test.ThreadSubmissionUnitTest ‑ PlanNextRound_AfterInterruptedRound_ReturnsNewDispatchForQueuedInputs
MeshWeaver.AI.Test.ThreadSubmissionUnitTest ‑ PlanNextRound_IdleWithThreeQueued_ReturnsBatchedDispatch
MeshWeaver.Content.Test.ImportDeleteServiceTest ‑ FullLifecycle_CreateNodes_DeleteRecursively
…
Memex.Portal.Shared.Test.VirtualUserMiddlewareAuthContextTest ‑ AuthenticatedUserViaHttpContext_SkipsVUserBlock_AndCallsNext
Memex.Portal.Shared.Test.VirtualUserMiddlewareAuthContextTest ‑ UnauthenticatedHttpContext_EntersVUserBlock_ThrowsOnMissingPortalApplication
MeshWeaver.AI.Test.ActivityLogStreamTest ‑ Progress_Messages_Stream_Gradually_Not_Just_At_The_End
MeshWeaver.AI.Test.ActivityLogStreamTest ‑ Script_Failure_Flips_ActivityLog_Status_To_Failed
MeshWeaver.AI.Test.ActivityLogStreamTest ‑ Script_Log_Messages_Land_On_ActivityLog_Node
MeshWeaver.AI.Test.AgentChatClientDeadlockTest ‑ GetOrderedAgentsAsync_WithContextPath_ConcurrentCallers_DoNotDeadlock
MeshWeaver.AI.Test.AgentChatClientDeadlockTest ‑ GetOrderedAgentsAsync_WithContextPath_SingleCaller_ResolvesQuickly
MeshWeaver.AI.Test.AgentChatClientDeadlockTest ‑ GetOrderedAgentsAsync_WithMarkdownContext_DoesNotDeadlock
MeshWeaver.AI.Test.AgentChatClientTest ‑ AgentChatClient_Initialize_SurfacesPartitionAgents_NotNodeTypeNamespaceAgents
MeshWeaver.AI.Test.AgentChatClientTest ‑ AgentChatClient_Initialize_SurfacesPlatformAgentsForAnyContext
…
This pull request removes 7 skipped tests and adds 6 skipped tests. Note that renamed tests count towards both.
MeshWeaver.Import.Test.ImportValidationTest ‑ ImportWithCategoryValidationTest
MeshWeaver.Import.Test.SnapshotImportTest ‑ SnapshotImport_ZeroInstancesTest
MeshWeaver.Layout.Test.EditPersistenceTest ‑ EditAndPersist_NullableDateTime_ShouldPersistToDataStore
MeshWeaver.Layout.Test.EditPersistenceTest ‑ EditAndPersist_StringProperty_ShouldPersistToDataStore
MeshWeaver.Layout.Test.EditPersistenceTest ‑ WorkspaceStreamEmit_ShouldNotOverwriteLocalEdits
MeshWeaver.Persistence.Test.MigrationTest ‑ DryRun_ShowsWhatWouldBeMigrated
MeshWeaver.Persistence.Test.MigrationTest ‑ RunMigration_MigratesAllFiles
MeshWeaver.AI.Test.ClaudeCodeChatClientE2ETest ‑ RealCli_StreamsARealResponse
MeshWeaver.AI.Test.ConnectStrategyTest ‑ RealClaudeSetupToken_Gated_BehindEnvFlag
MeshWeaver.AI.Test.CopilotChatClientE2ETest ‑ RealCli_StreamsARealResponse
MeshWeaver.AI.Test.TypedErrorPropagationTest ‑ UnregisteredDiscriminator_SurfacesDeserializationException_OnSubscribe
MeshWeaver.AI.Test.UseWithoutSeeResolverTest ‑ Read_GrantsUse_NoRead_FailsClosed
MeshWeaver.Hosting.PostgreSql.Test.ConcurrentQueryDeadlockTests ‑ Query_ManyConcurrentBlockingSubscribers_AllComplete_NoDeadlock
This pull request skips 1 and un-skips 6 tests.
MeshWeaver.Content.Test.NewCommentFlowTest ‑ NewComment_DataChangeToWrongAddress_ShouldNotUpdateComment
MeshWeaver.Data.Test.SynchronizationStreamTest ‑ ParallelUpdate
MeshWeaver.Layout.Test.DebounceTest ‑ BasicDebounce
MeshWeaver.Layout.Test.EditorTest ‑ TestEditorWithDelayed
MeshWeaver.NodeOperations.Test.DeletionTests ‑ Delete_ViaClient_WithDeleteNodeRequest
MeshWeaver.NodeOperations.Test.NodeOperationsTest ‑ DeleteNode_WithChildren_NonRecursive_ShouldFail
MeshWeaver.Threading.Test.StreamingAreaTest ‑ StreamingArea_WhenExecutionCompletes_ReturnsNull

♻️ This comment has been updated with latest results.

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 bundles several long-running feature and stability tracks across MeshWeaver core + Memex: social publishing foundations, in-process #r "nuget:..." compilation support (node-type + interactive markdown), move-operation performance/timeout hardening, and multiple UI/stream reliability improvements. It also standardizes the code folder naming from _Source/_Test to Source/Test across code, tests, docs, and samples.

Changes:

  • Introduces MeshWeaver.Social (options, DI wiring, publish queue, credential model) plus initial Memex wiring (LinkedIn connect entry points + user menu hooks).
  • Adds MeshWeaver.NuGet resolver + directive parser and integrates it into script compilation (#r "nuget:Pkg, Version"), including cache backends and tests.
  • Improves operational robustness: parallelized recursive moves, default 30s mesh-op timeout, “no endless spinner” navigation status UI, and remote stream resubscribe behavior.

Reviewed changes

Copilot reviewed 159 out of 265 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/MeshWeaver.StorageImport.Test/StorageImporterTests.cs Updates test expectations/docs to Source/ naming.
test/MeshWeaver.Social.Test/PostStatsRefresherTest.cs Adds stats refresher test coverage (needs deterministic timeout handling).
test/MeshWeaver.Social.Test/MeshWeaver.Social.Test.csproj Adds new Social test project referencing Social + Fixture.
test/MeshWeaver.Social.Test/InMemoryPublishQueueTest.cs Adds unit tests for publish queue due-drain + dedup.
test/MeshWeaver.Persistence.Test/FileSystemPersistenceTest.cs Updates partition tests to Source/ naming.
test/MeshWeaver.MathDemo.Test/TestPaths.cs Adds helper paths for MathDemo sample test assets.
test/MeshWeaver.MathDemo.Test/MeshWeaver.MathDemo.Test.csproj Adds MathDemo test project and copies sample graph data to output.
test/MeshWeaver.Hosting.PostgreSql.Test/SatelliteQueryTests.cs Updates code-path routing tests to Source/ naming.
test/MeshWeaver.Hosting.Monolith.Test/UserActivityAreaTest.cs Updates regression test docs to Source/ naming.
test/MeshWeaver.Hosting.Blazor.Test/NavigationServiceTest.cs Adjusts test to assert “no 404 flash” during retries.
test/MeshWeaver.Graph.Test/NuGetDirectiveParserTest.cs Adds unit tests for parsing/stripping #r "nuget:...".
test/MeshWeaver.Graph.Test/NuGetAssemblyResolverTest.cs Adds networked NuGet restore end-to-end tests (skippable via env var).
test/MeshWeaver.Graph.Test/MeshWeaver.Graph.Test.csproj References new MeshWeaver.NuGet project.
test/MeshWeaver.FutuRe.Test/MeshWeaver.FutuRe.Test.csproj Updates compile-included sample sources to Source/ paths.
test/MeshWeaver.Content.Test/CompilationErrorTest.cs Updates broken-code test to Source/ path.
test/MeshWeaver.AI.Test/MeshPluginTest.cs Updates MCP tool count expectations (adds RunTests/Move/Copy).
src/MeshWeaver.Social/SocialOptions.cs Adds configurable knobs for publishing/stats/ingest scheduling.
src/MeshWeaver.Social/SocialExtensions.cs Adds DI wiring for social publishing subsystem and hosted services.
src/MeshWeaver.Social/PlatformCredential.cs Adds credential record model (access/refresh/expiry metadata).
src/MeshWeaver.Social/MeshWeaver.Social.csproj Introduces Social library project.
src/MeshWeaver.Social/IPublishQueue.cs Adds publish queue abstraction + in-memory implementation.
src/MeshWeaver.Social/IApprovalPublishBridge.cs Defines bridge contract and PublishableSnapshot model.
src/MeshWeaver.NuGet/ResolvedPackageSet.cs Adds resolver output model (assemblies, probing dirs, versions).
src/MeshWeaver.NuGet/NuGetServiceCollectionExtensions.cs Adds DI extension to register resolver + cache.
src/MeshWeaver.NuGet/NuGetPackageReference.cs Adds package reference model (id + version range).
src/MeshWeaver.NuGet/NuGetDirectiveParser.cs Implements #r "nuget:..." extraction + source stripping.
src/MeshWeaver.NuGet/MeshWeaver.NuGet.csproj Introduces NuGet resolver project and dependencies.
src/MeshWeaver.NuGet/INuGetPackageCache.cs Adds optional persistent cache interface + null implementation.
src/MeshWeaver.NuGet/INuGetAssemblyResolver.cs Adds resolver interface returning ResolvedPackageSet.
src/MeshWeaver.NuGet.AzureBlob/MeshWeaver.NuGet.AzureBlob.csproj Adds Azure Blob cache backend project.
src/MeshWeaver.NuGet.AzureBlob/BlobNuGetPackageCacheExtensions.cs Adds DI helper to register blob-backed cache.
src/MeshWeaver.Mesh.Contract/Services/MeshOperationOptions.cs Adds mesh operation timeout options (default 30s).
src/MeshWeaver.Mesh.Contract/Services/IStorageAdapter.cs Updates docs/examples to Source/ naming.
src/MeshWeaver.Mesh.Contract/Services/INavigationService.cs Adds Status observable contract for UI progress reporting.
src/MeshWeaver.Mesh.Contract/Services/IIconGenerator.cs Adds icon generator abstraction returning an observable SVG.
src/MeshWeaver.Mesh.Contract/PartitionDefinition.cs Updates standard table mappings (Source/Testcode) and clarifies semantics.
src/MeshWeaver.Mesh.Contract/MeshExtensions.cs Adds timeout override + move timeout enforcement + grain dispose on delete.
src/MeshWeaver.Mesh.Contract/CodeConfiguration.cs Updates docs to Source/ naming.
src/MeshWeaver.Kernel.Hub/MeshWeaver.Kernel.Hub.csproj Removes Interactive package mgmt dependency; references MeshWeaver.NuGet.
src/MeshWeaver.Hosting/Persistence/MigrationUtility.cs Updates migration heuristics to include Source/Test + legacy _Source/_Test.
src/MeshWeaver.Hosting/Persistence/FileSystemStorageAdapter.cs Treats Source/Test as code paths + keeps legacy compatibility.
src/MeshWeaver.Hosting/Persistence/FileSystemPersistenceService.cs Parallelizes descendant move I/O (with concurrency implications).
src/MeshWeaver.Hosting/Persistence/CachingStorageAdapter.cs Updates code sub-namespace detection (Source/Test + legacy).
src/MeshWeaver.Hosting.PostgreSql/PostgreSqlPartitionedStoreFactory.cs Guards against source/test mistakenly becoming schemas.
src/MeshWeaver.Hosting.PostgreSql/PostgreSqlCrossSchemaQueryProvider.cs Filters malformed parameters to avoid NRE during SQL interpolation.
src/MeshWeaver.Hosting.Blazor/MeshWeaver.Hosting.Blazor.csproj Adds NU1510 suppression.
src/MeshWeaver.Graph/PartitionTypeSource.cs Updates docs to Source/ naming.
src/MeshWeaver.Graph/MeshWeaver.Graph.csproj References MeshWeaver.NuGet.
src/MeshWeaver.Graph/MeshNodeLayoutAreas.cs Improves create href behavior + reactive/grouped children catalog.
src/MeshWeaver.Graph/MeshDataSource.cs Updates docs to Source/ naming.
src/MeshWeaver.Graph/Configuration/ScriptCompilationService.cs Integrates NuGet directive parsing + resolver into compilation.
src/MeshWeaver.Graph/Configuration/NodeTypeDefinition.cs Updates docs/examples to Source/ naming.
src/MeshWeaver.Graph/Configuration/MeshDataSourceNodeType.cs Changes sources namespace constant to Source.
src/MeshWeaver.Graph/Configuration/GraphConfigurationExtensions.cs Registers NuGet resolver and uses Source code path.
src/MeshWeaver.Graph/Configuration/CodeNodeType.cs Treats Code nodes as primary content; defines Source/Test constants.
src/MeshWeaver.Documentation/Data/DataMesh/UnifiedPath.md Documents @/ semantics and HTML-href pitfalls.
src/MeshWeaver.Documentation/Data/DataMesh/SocialMedia/Profile/Source/SocialMediaProfileLayoutAreas.cs Adds SocialMedia profile layout areas example.
src/MeshWeaver.Documentation/Data/DataMesh/SocialMedia/Profile/Source/SocialMediaProfile.cs Adds SocialMedia profile content model example.
src/MeshWeaver.Documentation/Data/DataMesh/SocialMedia/Post/Source/SocialMediaPost.cs Adds SocialMedia post content model example.
src/MeshWeaver.Documentation/Data/DataMesh/SocialMedia/Post/Source/Platform.cs Adds SocialMedia platform reference-data example.
src/MeshWeaver.Documentation/Data/DataMesh/SocialMedia.md Updates docs to Source/ naming and authoring guidance.
src/MeshWeaver.Documentation/Data/DataMesh/SatelliteEntities.md Clarifies Source/Test are primary content, not satellites.
src/MeshWeaver.Documentation/Data/DataMesh/NodeTypes.md Adds Node Types documentation index page.
src/MeshWeaver.Documentation/Data/DataMesh/NodeTypeConfiguration.md Updates docs to Source/ naming.
src/MeshWeaver.Documentation/Data/DataMesh/NodeOperations.md Updates docs to Source/ naming.
src/MeshWeaver.Documentation/Data/DataMesh/DataConfiguration.md Updates docs to Source/ naming.
src/MeshWeaver.Documentation/Data/DataMesh/CreatingNodeTypes.md Updates docs to Source/Test naming throughout.
src/MeshWeaver.Documentation/Data/DataMesh.md Updates TOC links and adds NuGet packages bullet.
src/MeshWeaver.Documentation/Data/Architecture/PartitionedPersistence.md Updates persistence routing docs for Source/Test.
src/MeshWeaver.Documentation/Data/Architecture/MeshGraph.md Updates examples to Source/ naming.
src/MeshWeaver.Documentation/Data/Architecture/BusinessRules/Cession/Source/CessionSampleData.cs Adds cession sample dataset for docs/demo.
src/MeshWeaver.Documentation/Data/Architecture/BusinessRules/Cession/Source/CessionResultsArea.cs Adds reactive charting layout area example.
src/MeshWeaver.Documentation/Data/Architecture/BusinessRules/Cession/Source/CessionEngine.cs Adds pure business logic sample for cession calculations.
src/MeshWeaver.Documentation/Data/Architecture/BusinessRules/Cession/Source/CessionData.cs Adds content models for cession example.
src/MeshWeaver.Data/Serialization/SyncStreamOptions.cs Adds configurable heartbeat interval for sync streams.
src/MeshWeaver.Data/Serialization/JsonSynchronizationStream.cs Implements resubscribe-on-owner-dispose logic.
src/MeshWeaver.Blazor/Pages/ApplicationPage.razor Switches to NavigationStatus-driven progress/not-found/error UI.
src/MeshWeaver.Blazor/Components/NavigationProgressBar.razor.css Adds styling for full-page vs compact overlay progress bar.
src/MeshWeaver.Blazor/Components/NavigationProgressBar.razor Adds reusable “spinner + message” component.
src/MeshWeaver.Blazor/Components/MeshSearchView.razor.cs Adds Category grouping fallback to NodeType.
src/MeshWeaver.Blazor/Components/LayoutAreaView.razor.cs Adds stream lifecycle logging and additional diagnostics.
src/MeshWeaver.Blazor/Components/LayoutAreaView.razor Surfaces compilation progress indicator before first stream emission.
src/MeshWeaver.Blazor/Components/CompileProgressIndicator.razor.css Adds styling for compilation progress banner.
src/MeshWeaver.Blazor/Components/CompileProgressIndicator.razor Adds polling UI component for active NodeType compilation.
src/MeshWeaver.Blazor.Portal/MeshWeaver.Blazor.Portal.csproj Adds NU1510 suppression.
src/MeshWeaver.Blazor.AI/MeshWeaver.Blazor.AI.csproj Adds NU1510 suppression.
src/MeshWeaver.Blazor.AI/McpMeshPlugin.cs Adds Patch/Move/Copy MCP tools and improves tool descriptions.
src/MeshWeaver.AI/ThreadLayoutAreas.cs Adds debug logging around streaming view emission.
src/MeshWeaver.AI/IconGenerator.cs Adds default AI-backed IIconGenerator implementation.
src/MeshWeaver.AI/DelegationCompletedEvent.cs Removes delegation tracker/event types.
src/MeshWeaver.AI/Data/Agent/Worker.md Updates @/ link guidance (no raw HTML href with @/).
src/MeshWeaver.AI/Data/Agent/ToolsReference.md Updates @/ link guidance and provides correct/incorrect table.
src/MeshWeaver.AI/Data/Agent/Orchestrator.md Updates @/ link guidance for agent outputs.
src/MeshWeaver.AI/AIExtensions.cs Removes old type registration; registers IIconGenerator.
memex/aspire/Memex.Portal.Distributed/Program.cs Registers blob-backed NuGet package cache in distributed deployment.
memex/aspire/Memex.Portal.Distributed/Memex.Portal.Distributed.csproj References MeshWeaver.NuGet.AzureBlob.
memex/aspire/Memex.Database.Migration/Program.cs Adds source/test to reserved schema list.
memex/aspire/Memex.AppHost/Program.cs Adds LinkedIn secret/env wiring + sets NUGET_PACKAGES cache dir.
memex/Memex.Portal.Shared/Social/SocialMediaUserMenuProvider.cs Adds “Social Media” shortcut on a user’s own node (lazy hub creation).
memex/Memex.Portal.Shared/Social/ApiCredentialNodeType.cs Adds NodeType for PlatformCredential stored under _ApiCredentials.
memex/Memex.Portal.Shared/Pages/Login.razor Adds “Connect LinkedIn for publishing” CTA on login page.
memex/Memex.Portal.Shared/OrganizationNodeType.cs Switches to default layout areas registration.
memex/Memex.Portal.Shared/MemexConfiguration.cs Adds LinkedIn publisher wiring, @/ redirect middleware, and routes.
memex/Memex.Portal.Shared/Memex.Portal.Shared.csproj References MeshWeaver.Social.
memex/Memex.Portal.Monolith/appsettings.Development.json Enables debug logging for LayoutAreaView.
MeshWeaver.slnx Adds new projects (NuGet, NuGet.AzureBlob, Social, new test projects).
Directory.Packages.props Adds NuGet.* package versions for resolver implementation.
CLAUDE.md Documents @/ local-only rule and href/URL restrictions.
(Various) samples/Graph/... Adds/updates many sample NodeTypes and content under Source/ to reflect new conventions and demos.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/MeshWeaver.Social.Test/PostStatsRefresherTest.cs
Comment thread src/MeshWeaver.Hosting/Persistence/FileSystemPersistenceService.cs Outdated
rbuergi added a commit that referenced this pull request Apr 22, 2026
…+ test helpers

Recursive DeleteNodeRequest handled on a node's own hub was deadlocking: the final
DeleteSelfFromStorage posted Ok and DisposeRequest from the dying hub, so the Ok
raced callback disposal on the caller and was lost. Introduce CommitNodeDeletionMessage
and forward the terminal commit (storage delete + reply + grain dispose) to the
resolved mesh hub (walking ParentHub upward) — Sender becomes the stable mesh hub,
FIFO on the caller's inbound queue guarantees Ok resolves the RegisterCallback before
DisposeRequest arrives.

Also addresses two Copilot review comments on PR #95:

- FileSystemStorageAdapter.DeleteAsync empty-directory ascent is now concurrency-
  tolerant: wraps the enumerate + Directory.Delete in try/catch, swallowing the
  DirectoryNotFoundException race and breaking on IOException (non-empty / in-use).
  Required because FileSystemPersistenceService.MoveNodeAsync now parallelizes
  descendant deletes via Task.WhenAll.

- PostStatsRefresherTest.WaitUntilAsync throws TimeoutException with a descriptive
  message instead of returning silently on deadline, so the test cannot green-tick
  a stats-refresh that never happened.

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

rbuergi commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Resolved. The merge with origin/main is done in commit 6899990.

Conflicts resolved:

  • .claude/settings.json — kept HEAD deletion
  • Login.razor — kept NavigateToConnectLinkedIn (HEAD) + switched to OnInitializedAsync (origin/main)
  • AppHost/Program.cs — merged origin/main's optional-secrets pattern (nullable embeddingKey/googleClientSecret, customDomainValue guard) with HEAD's LinkedIn params (also made optional/nullable) and local-test/local-prod storage branch
  • Memex.Database.Migration/Program.cs — kept HEAD's data-repair v8 (fix ThreadMessage.MainNode) and v9 (rename _Source/_Test path segments)
  • SecurityService.cs — kept HEAD's refactored CollectStaticRoleIds returning (roleIds, cap); origin/main's permission-evaluation logic is already present in the new reactive GetEffectivePermissions method

@rbuergi rbuergi requested a review from Copilot May 10, 2026 05:41

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@rbuergi rbuergi requested a review from Copilot May 10, 2026 06:49

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@rbuergi

rbuergi commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

Code review — recent stability batch

Status: ✅ All 11 items in this comment addressed. See per-item commit SHAs in each header. Verification: Memex.Portal.Distributed builds clean; the four tests covering these changes (IsExecutingLifecycleTest, ChatHistoryTest ×2, CancelThreadExecutionTest) pass locally.

Manual review of the last ~20 commits since 8c5f37c80 (the doc commit). Focused on the synced-query consolidation, multi-query UNION feature, ThreadExecution refactor, and new tests. Copilot's two prior comments are already addressed in code. Findings below are grouped by severity.

Correctness — should fix before merge

1. ✅ e68636aacPostgreSqlStorageAdapter.QueryNodesAsync(IReadOnlyList<ParsedQuery>, …) — parameter-rename can mangle SQL.
File: src/MeshWeaver.Hosting.PostgreSql/PostgreSqlStorageAdapter.cs (the new UNION overload, ~line 530).

foreach (var (k, v) in perParams)
{
    var newKey = "@" + prefix + k.TrimStart('@');
    renamedSql = renamedSql.Replace(k, newKey);
    renamedParams[newKey] = v;
}

Dictionary<string,object> enumeration order is not guaranteed. If perParams contains both @p and @p1, processing @p first turns @p1 in the SQL into @q0_p1 (correct); processing @p1 first turns the SQL's @p1 into @q0_p1, then processing @p mangles @q0_p1 into @q0_q0_p1. Mixed-order builds will silently drift. string.Replace also clobbers @… substrings inside string literals or JSONB path comparisons.

Fix: single regex pass keyed on @<name> word boundary, gated on perParams.ContainsKey so we don't rewrite literal @ tokens.

2. ✅ e68636aacUNION (vs UNION ALL) dedup is row-wise, not path-wise.
Same file, same overload. The comment claims "same path emitted by two queries collapses to one row, matching the engine's path-keyed dictionary fold" — but UNION only collapses rows that are byte-identical across all selected columns. Two queries returning the same MeshNode with a slightly-different LastModified (concurrent writer) won't dedup.

Fix: UNION ALL wrapped in SELECT DISTINCT ON (namespace, id) … ORDER BY namespace, id, last_modified DESC. (No literal path column is projected; (namespace, id) is the path-keyed identity tuple. Newest version wins the tie-break.)

3. ✅ e68636aacPostgreSqlMeshQuery.ObserveQuery<T> ignores request.Queries for change detection.
src/MeshWeaver.Hosting.PostgreSql/PostgreSqlMeshQuery.cs:360-401. The method parsed only request.Query (single string), and the change-notifier filter used the first query's normalizedBasePath + effectiveScope for PathMatcher.ShouldNotify. Multi-query observations correctly fanned out to all queries inside CollectQueryResultsAsync, but live updates that match only query #2's path/scope wouldn't trigger a re-run.

Fix: parse every query in request.EffectiveQueries, build per-query (basePath, scope) filters, OR-join them in the change-notifier subscription.

4. ✅ e68636aacMeshQueryEngine Activity post-filter uses only first query's basePath.
src/MeshWeaver.Hosting/Persistence/Query/MeshQueryEngine.cs:125-138, 183-196. When parsedQuery.Source == QuerySource.Activity, the post-filter scanned descendants of firstBasePath for Activity satellites — queries #2+ with unrelated basePaths had their Activity matches filtered against the wrong subtree.

Fix: CollectMatchedAsync returns the list of every query's basePath; the activity post-filter scans every base path's descendants and unions activity-main-paths.

Race / lifecycle hazards

5. ✅ 478fdaa93ThreadExecution.RecoverStaleExecutingThread 2-minute window contradicts "no time limits" commit.
src/MeshWeaver.AI/ThreadExecution.cs:175-180. Commit 6dc436bf5 made the policy explicit, but recovery still said "Only recover truly stale ones (started > 2 minutes ago or no timestamp)." A legitimate slow execution that crashes after 2+ minutes wouldn't be recovered → IsExecuting=true forever.

Fix: drop the time-based heuristic in favour of a structural one — skip recovery only when the thread is still an auto-execute candidate (PendingUserMessage + ActiveMessageId set, i.e. WatchForExecution will pick it up).

6. ✅ 478fdaa93Subject<StreamingSnapshot> not disposed.
src/MeshWeaver.AI/ThreadExecution.cs:890. Fix: using var snapshots = new Subject<…>().

7. ✅ eea8ed10a — Sample(100ms) terminal-status race regression test.
The terminal-status guard correctly prevents Streaming from regressing Completed/Cancelled/Error in PushToResponseMessage. Fix: added a regression assertion in IsExecutingLifecycleTest that final ThreadMessage.Status == Completed after a successful echo run.

8. ✅ 478fdaa93HandleCancelStream runs after CTS-storage race.
src/MeshWeaver.AI/ThreadExecution.cs:1284-1289. parentHub.Set(executionCts) happened around line 847, but IsExecuting=true flipped earlier in HandleSubmitMessage. A cancel arriving in that window was a no-op.

Fix: pre-allocate the CancellationTokenSource and store it on the thread hub in HandleSubmitMessage before posting SubmitMessageResponse. ExecuteMessageAsync reuses it from the parent-hub slot (with a fresh-CTS fallback for the auto-execute path that bypasses HandleSubmitMessage).

Style / consistency

9. ✅ 478fdaa93 — Triple-stacked <summary> XML doc tags.
Collapsed both blocks (WatchForExecution, NotifyParentCompletion) to a single <summary>.

10. ✅ eea8ed10aIsExecutingLifecycleTest text-pattern wait inconsistent with ChatHistoryTest.
Fix: migrated to ThreadMessage.CompletedAt is not null — same pattern as ChatHistoryTest.SubmitAndWait after commit ab3af8b70.

11. ✅ e68636aac — Limit-on-first-query semantics.
request.Limit was applied only to parsedList[0]; query #0 could hit its limit before yielding its most relevant rows while queries #1+ contributed unbounded — making the result iteration-order dependent.

Fix: drop the per-query Limit injection. Limit is enforced post-union via MinLimit(request.Limit, firstParsed.Limit) in both engines, so a request-level cap can't be circumvented and an in-query limit:N still wins when smaller.

✅ Looks good (no action needed)

  • SyncedQueryMeshNodes doc-comment now matches the dict-from-query-events fold (post the doc commit).
  • LoadFullConversationHistoryFromMesh correctly reads the live thread's Messages list and resolves each cell via GetMeshNodeStream (per-node hub) — sidesteps the stale-index race the comment calls out.
  • MultiQueryUnionEngineTests covers the union semantics on the in-memory engine without needing a testcontainer.
  • CancelThreadExecutionTest rewrite (commit-pending) correctly uses "Generating response..." as the CTS-armed signal.
  • The terminal-status guard pattern (current.Status is Completed or Cancelled or Error && requestedStatus == Streaming → keep current) is the right shape.

@rbuergi

rbuergi commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

Code review — part 2: rest of the PR

Status: ✅ All 12 items in this comment addressed. See per-item commit SHAs in each header. NuGet validation in #14 was deferred at first then closed in 6c3e60925.

Continuing review on the bulk of the PR (everything before the recent stability batch). Focused on the new projects (MeshWeaver.NuGet, MeshWeaver.Social) and a sampling of the central MessageHub refactor — the full 100-commit / 1006-file diff is too large for an exhaustive read. Same severity grouping as part 1.

Correctness — should fix before merge

12. ✅ 512adb462NuGetAssemblyResolver caches faulted Tasks forever.
src/MeshWeaver.NuGet/NuGetAssemblyResolver.cs:42.

return _cache.GetOrAdd(key, _ => ResolveCoreAsync(requested, framework, ct));

If ResolveCoreAsync threw, the faulted Task<ResolvedPackageSet> stayed in the cache; subsequent calls replayed the same exception forever.

Fix: evict faulted/cancelled tasks from the cache before returning. Also pass CancellationToken.None to the shared core task so a single caller's cancellation can't take down the resolution for everyone else; per-caller ct projects via task.WaitAsync(ct).

13. ✅ 512adb462NuGetAssemblyResolver resolves with DependencyBehavior.Lowest.
src/MeshWeaver.NuGet/NuGetAssemblyResolver.cs:74. "Lowest" pulls minimum-satisfying versions transitively, which yanks in EOL/unpatched releases when constraints have weak floors.

Fix: switched to DependencyBehavior.HighestMinor so security fixes flow in transparently without crossing minor/major boundaries.

14. ✅ 6c3e60925 — Hydrated package not validated.
After INuGetPackageCache.TryHydrateAsync returned true, the resolver trusted the content — a poisoned cache entry (different package stored under wrong key) would silently load wrong assemblies.

Fix: post-hydration, the resolver opens the package folder via PackageFolderReader.GetIdentity() and verifies the .nuspec-declared (id, version) matches expected. On mismatch the directory is purged and the resolver falls back to the feed download path. No INuGetPackageCache contract change needed.

15. ✅ 478fdaa93XPublisher.PublishAsync crashes on partial response.
src/MeshWeaver.Social/XPublisher.cs:71. The chained GetProperty("data").GetProperty("id") threw KeyNotFoundException on unexpected body shapes.

Fix: defensive TryGetProperty chain; logs a warning and returns id = null (caller treats as "publish succeeded but URN couldn't be captured") instead of crashing. Also guards against null AuthorHandle.

16. ✅ 478fdaa93 (LinkedIn) + 512adb462 (X) — Publishers don't auto-retry on token-refresh race.
Fix: SendWith401RetryAsync helper in both publishers — on 401, force-refresh the token (zero ExpiresAt so EnsureFreshAsync doesn't short-circuit) and retry the request once.

Race / lifecycle hazards

17. ✅ 512adb462PostStatsRefresher processes targets sequentially.
Fix: Parallel.ForEachAsync bounded by SocialOptions.StatsRefreshDegreeOfParallelism (default 8).

18. ✅ 512adb462PostStatsRefresher has no per-target backoff.
Fix: ConcurrentDictionary<string, DateTimeOffset> of last-failure timestamps. Targets that failed within SocialOptions.StatsRefreshFailureBackoff (default 15 min) skip the next tick. Success clears the entry so the target rejoins normal cadence.

19. ✅ df1939bb7MessageHub faulted-Task cache pattern.
The MESHWEAVER_DISPOSE_TRACE=1 global file lock + per-call File.AppendAllText serialised hub teardown when many hubs disposed concurrently.

Fix: replaced with a single bounded Channel<string> (4096, FullMode = DropWrite) drained by one writer task started in the type initialiser. Producers TryWrite non-blocking; lines drop on full so a stuck writer never delays dispose.

Style / consistency

20. ✅ 478fdaa93SocialExtensions.AddSocialPublishing lifetime mismatch.
AddHttpClient<LinkedInPublisher>() registered the typed client as transient; the IPlatformPublisher factory then made it singleton — direct vs via-interface resolution returned different instances.

Fix: register the publisher as a true singleton via services.AddSingleton(sp => new LinkedInPublisher(httpFactory.CreateClient(...), ...)). Same for X. Both IPlatformPublisher and concrete-type resolution return the same instance.

21. ✅ 478fdaa93SocialExtensions claims "all-or-nothing" but isn't.
The four AddHostedService<…> calls were unconditional even with zero platforms configured.

Fix: gate hosted-service registration on anyConfigured; with zero platforms, no hosted services start.

22. ✅ 478fdaa93LinkedInPublisher uses dynamic to peek at typed-anonymous fields.
Fix: two concrete payload shapes in if/else branches; no dynamic dispatch; typos surface as compile errors instead of RuntimeBinderException.

23. ✅ 478fdaa93 — PII / user-content in error logs.
Fix: Truncate(b, 200) on logged error bodies in both publishers (LinkedIn publish + token refresh, X publish). Full body still goes to PublishResult.Error for the caller.

✅ Looks good (no action needed)

  • NuGetAssemblyResolver correctly caches by (framework, sorted package list) so repeated #r invocations don't re-walk dependencies.
  • MessageHub AsyncSubject pattern fixes the long-standing "subscribe before vs after response" race in the old RegisterCallback.
  • LinkedInPublisher correctly handles the LinkedIn x-restli-id header fallback and only falls back to JSON body parsing when the header is missing.
  • SocialOptions defaults look reasonable (60s publish tick, 30m stats tick, 30d window).
  • EnsureFreshAsync returns a refreshed PlatformCredential to the caller rather than mutating internal state — caller decides where to persist.

Areas not covered in this review

Persistence-service refactors (IStorageService, MeshNodeEditor, NavigationService changes), the +850-line MessageHub core-dispatch refactor in detail, content-collection changes, NodeType compilation pipeline beyond what part 1 touched. Flag a specific subsystem if a deeper review is wanted.

@rbuergi

rbuergi commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

Review fixes applied — all 23 items addressed

5 commits, organised by batch. Locally committed, not pushed yet.

# Item Commit
1 UNION SQL param-rename regex pass e68636aac
2 UNION ALL + DISTINCT ON (namespace, id) for path-keyed dedup e68636aac
3 ObserveQuery change-notifier OR-joined per-query filters e68636aac
4 MeshQueryEngine Activity post-filter scans every basePath e68636aac
5 RecoverStaleExecutingThread structural guard (drop time-based heuristic) 478fdaa93
6 using var on Subject<StreamingSnapshot> 478fdaa93
7 Regression assertion: final ThreadMessage.Status == Completed eea8ed10a
8 Pre-allocate CancellationTokenSource in HandleSubmitMessage 478fdaa93
9 Collapse triple-stacked <summary> blocks 478fdaa93
10 IsExecutingLifecycleTest waits on CompletedAt, not text patterns eea8ed10a
11 Limit-on-first-query semantics: enforce post-union via MinLimit e68636aac
12 NuGetAssemblyResolver evicts faulted/cancelled cache entries 512adb462
13 NuGet DependencyBehavior.HighestMinor (was Lowest) 512adb462
14 Hydrated-cache validation note (deferred — needs INuGetPackageCache change) 512adb462
15 XPublisher defensive TryGetProperty chain 478fdaa93
16 LinkedIn / X publishers retry once on 401 with token refresh 478fdaa93 (LinkedIn structure), 512adb462 (X 401 retry parity)
17 PostStatsRefresher uses Parallel.ForEachAsync (DOP 8) 512adb462
18 Per-target failure backoff (15 min default) 512adb462
19 Channel-based dispose trace replaces global file lock df1939bb7
20 SocialExtensions: factory-resolved singleton publishers 478fdaa93
21 Hosted services gated on at least one configured platform 478fdaa93
22 LinkedIn dynamic→concrete payload shapes 478fdaa93
23 Cap error-body logs at 200 chars (LinkedIn + X) 478fdaa93

Verification

  • Solution build clean (memex/aspire/Memex.Portal.Distributed).
  • Tests I touched all pass locally:
    • IsExecutingLifecycleTest.SingleMessage_IsExecuting_FlipsTrueThenFalse_WithRealResponse — 11 s
    • ChatHistoryTest.ThreeMessages_AgentSeesFullHistory — 2 s
    • ChatHistoryTest.TwoMessages_NoDuplicates_CorrectRoles — 3 s
    • CancelThreadExecutionTest.CancelStream_StopsExecutionAndMarksAsCancelled — 3 s
  • The full MeshWeaver.Threading.Test suite has 4 unrelated pre-existing failures (not introduced by these commits — present on main as well).

Notes

  • Update release-packages.yml #14 (cache content validation) is documented as a TODO rather than implemented — INuGetPackageCache.TryHydrateAsync doesn't currently expose a content hash to verify against, so the fix needs a contract change. Flagged in code at NuGetAssemblyResolver.EnsureInstalledAsync.
  • Get rid of project dependencies in NotebookEditorControl #5 (recovery time window) swapped time-based heuristic for a structural one (PendingUserMessage + ActiveMessageId set → leave to WatchForExecution). Same intent, no time-bound failure mode.
  • [Snyk] Upgrade axios from 0.25.0 to 0.27.2 #8 (CTS race) required a structural change: HandleSubmitMessage now pre-allocates and stores the CTS before the response goes out, ExecuteMessageAsync reuses it from the parent hub slot. The auto-execute path (WatchForExecution) gets a fallback CTS if the slot is empty.

Ready to push when you want.

@rbuergi

rbuergi commented May 10, 2026

Copy link
Copy Markdown
Contributor Author

Done — review item #14 is now closed in commit 6c3e60925. The hydrated folder is validated via PackageFolderReader.GetIdentity() against the expected (id, version); on mismatch the directory is purged and the resolver falls back to the feed. No INuGetPackageCache contract change needed — validation is in the resolver. Total: 6 commits, all 23 review items addressed.

rbuergi added a commit that referenced this pull request May 10, 2026
…fix DI lifetimes, redact PII, drop dynamic

- ThreadExecution: collapse triple-stacked <summary> blocks on
  WatchForExecution and NotifyParentCompletion. Tooling kept the last
  one anyway; the dead scaffolding was just noise.
- SocialExtensions: register LinkedInPublisher / XPublisher as TRUE
  singletons (factory-resolved with named HttpClient). The previous
  AddHttpClient<T>+AddSingleton<IPlatformPublisher> mix made the
  concrete type transient while the interface alias was singleton —
  direct vs via-interface resolution returned different instances.
  Also gate hosted-service registration on at least one platform
  being configured (the "all-or-nothing" comment was wrong; with
  zero platforms the four hosted services started anyway and faulted
  on first tick).
- LinkedInPublisher: replace `(dynamic)media.shareMediaCategory`
  peek with two concrete payload shapes — typo turns into a compile
  error instead of a RuntimeBinderException.
- LinkedIn / X publishers: cap error-body logs at 200 chars to
  bound PII exposure (the body can echo the user's post text on
  validation rejection). Full body still goes to PublishResult.Error
  for the caller.

Addresses PR #95 review items #9, #20, #21, #22, #23.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rbuergi added a commit that referenced this pull request May 10, 2026
… in-memory engines

PostgreSqlStorageAdapter.QueryNodesAsync(IReadOnlyList<ParsedQuery>):
  - Replace order-dependent `string.Replace` parameter rename with a
    single `Regex.Replace` keyed on @<name> word boundary that gates
    on perParams.ContainsKey. Sequential Replace was mangling adjacent
    tokens (renaming `@p` after `@p1` produced `@q0_q0_p1`) and could
    clobber `@…` substrings inside string literals / JSONB paths.
  - Switch from `UNION` to `UNION ALL` wrapped in
    `SELECT DISTINCT ON (namespace, id) ... ORDER BY namespace, id, last_modified DESC`.
    Plain UNION dedupes whole rows — two queries observing the same
    node at slightly-different last_modified would BOTH appear in the
    output. Path-keyed dedup (= MeshNode identity) with newest-wins
    tie-break collapses them correctly.

PostgreSqlMeshQuery.ObserveQuery<T>:
  - Parse EVERY query in request.EffectiveQueries and build per-query
    (basePath, scope) filters; the change-notifier subscription
    OR-joins them so multi-query observations get delta refreshes
    triggered by ANY query's path/scope, not just query #0's. The
    previous shape silently lost live updates from queries #1+.

PostgreSqlMeshQuery.QueryNodesUnionAsync + MeshQueryEngine:
  - Drop the per-query `parsedList[0].Limit = request.Limit` injection.
    Query #0 hit its limit before yielding the union's most relevant
    rows, while queries #1+ contributed unbounded — making the result
    iteration-order dependent. Limit is now enforced post-union via
    MinLimit(request.Limit, firstParsed.Limit) so a request-level cap
    can't be circumvented and an in-query `limit:N` still wins when
    smaller.
  - MeshQueryEngine: CollectMatchedAsync returns the LIST of every
    query's basePath; the source:activity post-filter scans every
    base path's descendants and unions activity-main-paths so
    queries #1+ aren't filtered against query #0's subtree only.

Addresses PR #95 review items #1, #2, #3, #4, #11.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rbuergi added a commit that referenced this pull request May 10, 2026
…ThreadExecution stability fixes

ThreadExecution.cs (already in commit 478fdaa — recapping here for the
review-item index):
  - RecoverStaleExecutingThread: drop the 2-minute "fresh execution"
    window in favour of a structural check (skip when PendingUserMessage
    + ActiveMessageId are still set, i.e. the thread is an
    auto-execute candidate WatchForExecution will pick up). Closes the
    "long-running agent crashed at minute 5 → IsExecuting=true forever"
    gap; the time-based heuristic contradicted commit 6dc436b's
    "no time limits" stance.
  - Subject<StreamingSnapshot>: declare with `using var` so the
    Subject itself disposes alongside its subscription. Minor leak
    per execution previously.
  - HandleSubmitMessage: pre-allocate the per-round
    CancellationTokenSource and store it on the thread hub BEFORE
    posting SubmitMessageResponse — closes the race where an early
    Stop click between IsExecuting=true and ExecuteMessageAsync's
    `parentHub.Set(executionCts)` found a null CTS slot and
    silently no-op'd. ExecuteMessageAsync now reuses the
    pre-allocated CTS (with a fallback for the auto-execute path
    that bypasses HandleSubmitMessage).

IsExecutingLifecycleTest.cs:
  - Migrate the response-text wait from text-pattern matching
    (skipping placeholders "Allocating agent..." etc.) to
    `ThreadMessage.CompletedAt is not null`, which
    ExecuteMessageAsync sets only on the terminal
    PushToResponseMessage call. Same pattern adopted in
    ChatHistoryTest in commit ab3af8b.
  - Add a regression assertion that final
    ThreadMessage.Status == Completed. The terminal-status guard in
    PushToResponseMessage prevents the late Sample(100ms)-flushed
    Streaming push from regressing the cell from Completed back to
    Streaming; this assertion catches any future regression of that
    guard.

Addresses PR #95 review items #5, #6, #7, #8, #10.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rbuergi added a commit that referenced this pull request May 10, 2026
…, parallelism, backoff)

NuGetAssemblyResolver:
  - Evict faulted/cancelled tasks from the per-key cache before
    returning. A transient feed failure (network, throttle, cancelled
    in-flight resolve) used to poison the cache for the resolver's
    lifetime — every subsequent call replayed the same exception.
  - Pass CancellationToken.None to the shared core task so a single
    caller's cancellation can't take down the resolution for
    others; per-caller `ct` projects via `task.WaitAsync(ct)`.
  - Switch DependencyBehavior from `Lowest` to `HighestMinor` so
    `#r` directives pick up patch-level security fixes via
    transitive dependencies without silently jumping major/minor.
  - Document that hydrated cache content is trusted to match
    (id, version) — flag for future content-hash verification if
    cache poisoning becomes a concern.

LinkedInPublisher / XPublisher (LinkedIn already committed in batch A
for the dynamic+PII parts; this commit adds the 401 retry):
  - SendWith401RetryAsync: on the FIRST 401 response from a publish,
    force-refresh the token (zero ExpiresAt before EnsureFreshAsync)
    and retry once. Closes the race where the access token's TTL
    expired between EnsureFreshAsync and the actual API call.

PostStatsRefresher:
  - Process due-refresh targets via Parallel.ForEachAsync bounded
    by SocialOptions.StatsRefreshDegreeOfParallelism (default 8),
    so a slow API + large refresh window can't let one tick
    overshoot the next interval.
  - Per-target failure backoff via a ConcurrentDictionary of
    last-failure timestamps — targets that failed within
    StatsRefreshFailureBackoff (default 15 min) skip the next tick.
    Stops a degraded platform from generating thousands of repeat
    warnings every cycle while the underlying issue is fixed.
    Success clears the backoff entry.

SocialOptions: add StatsRefreshDegreeOfParallelism (8) and
StatsRefreshFailureBackoff (15 min) knobs.

Addresses PR #95 review items #12, #13, #14, #16, #17, #18.
(#15 XPublisher defensive parse + the LinkedIn dynamic / PII items
were already in commit 478fdaa.)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rbuergi added a commit that referenced this pull request May 10, 2026
… file lock

The MESHWEAVER_DISPOSE_TRACE=1 trace took a global lock per call
(`File.AppendAllText` under `lock (DisposeTraceLogLock)`), serialising
hub teardown under load when many hubs disposed concurrently.

Replaced with a single bounded `Channel<string>` (capacity 4096,
FullMode = DropWrite) drained by one writer task started in the
type initialiser. Producers `TryWrite` non-blocking — if the disk is
slow / locked, lines drop on full instead of putting back-pressure
on dispose. Single-reader semantics avoid contention on the file
handle.

Addresses PR #95 review item #19.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
rbuergi added a commit that referenced this pull request May 10, 2026
Replaces the TODO from commit 512adb4. After a successful
INuGetPackageCache.TryHydrateAsync, the resolver now opens the
hydrated folder via PackageFolderReader and compares the package's
own .nuspec-declared (id, version) against the expected (id, version).
On mismatch the directory is purged and the resolver falls back to
the feed.

This catches the failure modes #14 was about: wrong package stored
under right key (cross-tenant blob, accidental copy, drift after a
manual edit). The .nuspec is the canonical NuGet source of truth, so
a tampered cache entry can't fake the identity without rewriting the
nuspec — which we'd then catch at hydration time.

No INuGetPackageCache contract change; validation lives entirely in
the resolver.

Closes the last open item from PR #95 review (item #14).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@rbuergi

rbuergi commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Test Results (shard 1)

797 tests   795 ✅  3m 5s ⏱️
 11 suites    0 💤
 11 files      2 ❌

For more details on these failures, see this check.

Results for commit d66aba7.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Test Results (shard 0)

   13 files     13 suites   11m 37s ⏱️
2 442 tests 2 432 ✅ 6 💤 4 ❌
2 466 runs  2 456 ✅ 6 💤 4 ❌

For more details on these failures, see this check.

Results for commit d66aba7.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Test Results (shard 3)

319 tests   316 ✅  2m 28s ⏱️
  8 suites    0 💤
  8 files      3 ❌

For more details on these failures, see this check.

Results for commit d66aba7.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

Test Results (shard 2)

1 092 tests   1 088 ✅  6m 53s ⏱️
   12 suites      1 💤
   12 files        3 ❌

For more details on these failures, see this check.

Results for commit d66aba7.

♻️ This comment has been updated with latest results.

rbuergi and others added 30 commits June 18, 2026 11:07
…ngeStreamUpdate)

Both build their host via ConfigureHost (and, for AccessAssignment, inline
Mesh.GetHostedHub(addr, ConfigureHost) which — unlike HubTestBase.GetHost — adds no
posting identity), so their data-layer workspace.RequestChange writes posted as User
with no user and failed closed under the never-null guard. These are pure data-layer
propagation tests (not RLS), so post as System. AccessAssignmentLayoutAreasTest 6/6.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…k "portal down"

ValidateTokenViaHub posts ValidateTokenRequest with NO identity — it's the auth
bootstrap, run BEFORE any user context exists. The never-null guard fail-closes that
post, so it never reaches the ApiToken hub → validation returns null → the user
resolves as ANONYMOUS → RLS returns empty → blank "portal is down" for every
authenticated user (chronic token-forwarding failure, atioz 2026-06-18; portal serves
HTTP 200 but authenticated content is empty).

Run the validation as System (Permission.All) via Observable.Using holding the
ImpersonateAsSystem scope across the cold Observe's Subscribe — NOT ImpersonateAsHub,
whose hub address has no Read on the token node. Same root + fix family as the
import-hub (19ad2a8) and compile-activity (cd0c097) System fixes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ver null

UserContextMiddleware stamped a null AccessContext for any request without a
resolved user (no auth, invalid/expired token, or email-shaped ObjectId
refusal). A null context trips the never-null PostPipeline guard and
fail-closes every downstream application post — reads, subscribes,
layout-area syncs — so the visitor sees a BLANK portal even for public
content. Combined with the token-validation fail-closed (77da313), an
expired token resolved to null and blanked the page: the atioz "portal down"
wedge.

Resolve to the well-known Anonymous identity instead. Anonymous carries
Permission.None by default; RLS still filters reads to exactly what the
Anonymous role is granted and rejects writes cleanly — never fail-closed.
Honors the never-null invariant (feedback_access_context_always_set).

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

Token-usage accounting — close 4 holes:
- ThreadSubmission: stop resetting cumulative TokensUsed at round dispatch
- ThreadExecution: preserve TokensUsed on wake-cancel; record tokens consumed
  on Cancelled and Error rounds (cell + thread), not only Completed
- shared NormalizeTotalTokens() derives total from in+out across all 3 paths

Per-model breakdown + pricing:
- Thread.TokensByModel (ModelTokenUsage), accumulated per terminal round
- ModelDefinition gains InputPricePerMillionTokens/OutputPricePerMillionTokens/
  Currency; ModelPricing default rate table (Anthropic, USD) with node override;
  catalog seeds defaults on model nodes

UI:
- thread "Token cost" area + menu — tokens in/out per model + cost
- Space "Token Cost" settings tab with from/to date range, summing every
  thread's per-model usage over the range

Tests: ThreadTokenUsageTest (completed/cancelled/error/cumulative/derived-total
+ per-model breakdown), TokenCostTest (pricing/merge/render units).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clears the MessagePack NU1903 high-severity advisory (GHSA-hv8m-jj95-wg3x):
the vulnerable MessagePack 2.5.192 was transitive via Aspire's StreamJsonRpc
2.22.23; Aspire 13.4.5 pulls StreamJsonRpc 2.25.29 -> MessagePack 2.5.302
(patched). Whole tree now resolves 2.5.302. Orleans bumped in lockstep.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The build job packages bin+obj of all 50+ projects PLUS the whole
.nuget/packages folder into a zstd tarball (a multi-GB copy) and was dying
with "No space left on device" on the default ~14 GB. Add the same
jlumbroso/free-disk-space reclaim the test shards already use (Android SDK,
Haskell, Docker images, big apt packages) so the legitimate build artifact
fits. Removes unused runner bloat, not a band-aid for a leak.

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

The 3 anonymous tests did SetCircuitContext(null), so the post fail-closed at
the never-null PostPipeline guard (OnError) instead of reaching the RLS
handler. Stamp WellKnownUsers.Anonymous instead (matching UserContextMiddleware,
which now resolves unauthenticated requests to Anonymous) -> the request reaches
RLS and is rejected cleanly (Success=false), as asserted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…manifest gate

Orleans 10.2.0 enforces the allowed-types manifest gate independently of which
codec claims a type. AddJsonSerializer(_ => true, _ => true) registers the JSON
codec for every type but no longer implicitly allows those types through the
security gate, so a grain call carrying the IMessageDelivery envelope
(DeliverMessage / RouteMessage / GetStream<IMessageDelivery>) is rejected as
"type not allowed" — breaking all cross-grain routing on the distributed portal.

Register an ITypeNameFilter (MeshTypeNameFilter) backed by the hub's ITypeRegistry
that allows the delivery envelope plus exactly the types the mesh has registered;
returns null ("no opinion") otherwise so it only ever widens the gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nBeIgnoredCache memo

Orleans tests post PingRequest/CreateNodeRequest directly from client/portal/silo
mesh hubs whose CircuitContext is null, tripping the never-null AccessContext
invariant. Monolith avoids this via TestUsers.DevLogin(Mesh); the Orleans clusters
had no equivalent. Add OrleansTestIdentity.SeedDefaultIdentity (the DevLogin analog)
seeding the well-known System principal as a CircuitContext fallback on every
cluster mesh hub (client + silos), wired into all six cluster-deploy sites. It is a
pure fallback: only used when a post has no per-message context, so it never
overrides the real client->silo identity flow that passing tests rely on.

Also allowlist MessageHubConfiguration._canBeIgnoredCache in NoStaticCollectionsTest
— a pure Type->[CanBeIgnored] reflection memo, identical in shape to the already-
allowlisted sibling _systemMessageCache (MEMO).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…le BusinessRules from low-level Graph

Graph hard-referenced MeshWeaver.BusinessRules.Generator (a Roslyn component) so the
NodeType compiler could run ScopeCodeGenerator on every dynamic-node compile — bloating
every downstream build. Now generators are discovered on demand from a node's
#r "nuget:..." references (SourceGeneratorLoader, path-keyed MEMO cache, loaded into the
default context, version-identity guarded) and run in RunSourceGenerators. Graph references
nothing BusinessRules. The generator package now also ships under lib/ so
#r "nuget:MeshWeaver.BusinessRules.Generator" resolves it. The PensionFund BalanceSheet
sample opts in via #r in BalanceSheetScopes.cs; PensionFund.Test drops the conflicting
build-time compile-include (the runtime test is the validation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ages as CI artifacts

Replaces the heavy PensionFund render test with one lean compile test
(ScopeGeneratorViaRCompileTest): create a NodeType whose Source pulls the BusinessRules
framework + ScopeCodeGenerator via #r and declares an IScope<,>, trigger the compile, and
assert the compile activity log has no error/warning messages and CompilationStatus.Ok. A
clean compile also proves #r resolution worked (an unresolved #r would error on
using MeshWeaver.BusinessRules). The build job now packs MeshWeaver.BusinessRules + .Generator
into dist/packages (the git-ignored mesh-local feed) and ships it in the build artifact, so
the --no-build test shards' runtime #r resolver can resolve them offline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…h, V3-0324, Kimi-K2.6)

The cost overview only priced Claude; add the models actually deployed on Azure AI Foundry
(s-meshweaver, swedencentral) so per-model cost shows for the DeepSeek + Kimi deployments.
Azure serverless rates, USD/1M tokens; Flash/V3-0324 flagged as estimates to verify.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… fixes NU5026)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l; Release nupkgs are publishable

dotnet build defaults to Debug while dotnet pack defaults to Release — that straddle is
what broke the #r pack step. Pin the whole pipeline to Release: the solution build, the
mesh-local #r pack, and the shard 'dotnet test --no-build' all target bin/Release, so they
agree, the tests run optimized like prod, and dist/packages holds the Release nupkgs that
can be published directly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ing broke existing IScope nodes

The #r-pluggable change (d0cfc17) removed the built-in BusinessRules scope generator from
Graph's RunSourceGenerators, so existing IScope/BusinessRules nodes WITHOUT an #r directive
stopped compiling and wedged the pages rendering them (atioz AgenticPension Settings). It also
gave no build-time win (the stall is Defender + Graph's own CodeAnalysis.Features ref). Restore
the proven always-on generator + Graph's BusinessRules refs; drop SourceGeneratorLoader, the
#r sample directive, and the #r compile test. ModelPricing (Azure per-model prices) is kept.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pped -> phantom-activity storm

MeshService.CreateNode/DeleteNode captured the caller's identity INSIDE Observable.Defer
(i.e. at Subscribe), so a write subscribed on an emission thread where the ImpersonateAsSystem
AsyncLocal is gone posted as Anonymous. The owner's RlsNodeValidator then denied it against the
read-only Doc/_Policy Create=false cap, so compile/import _Activity nodes never persisted
(doc.activities empty on atioz) -> progress readers stormed [ROUTE] NotFound on the phantom
_Activity/compile-* paths -> routing starved -> portal wedge.

Fix: capture the caller's AccessContext EAGERLY at the call site (where the impersonation is
live) and pin it onto the request as CreatedBy/DeletedBy -- a message field that survives the
cross-hub post AND the emission-thread Subscribe, unlike the ambient AsyncLocal. RlsNodeValidator
reads CreatedBy/DeletedBy first, so System now bypasses row-based access unconditionally.

Adds 2 deterministic repro tests (SyncedPartitionReadOnlyTest): a System _Activity create under
the read-only Doc partition must persist, including when the impersonation scope is no longer
the ambient context at Subscribe.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eetTest referencing the deleted helper

The #r-decoupling revert (git checkout d0b80ea) restored PensionFundBalanceSheetTest.cs but
not the TestPaths.cs helper it references (CS0103), failing the CI build job → all shards skipped.
Restore the helper from the same revert baseline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…clear message + Monaco error overlay

A NodeType whose source fails to compile no longer renders an indefinite spinner / silent wedge.
The Settings → Progress error branch now shows, per affected source file, a link to the Code node
and a read-only Monaco editor with the Roslyn errors MARKED at their exact line/column (the IDE-style
overlay), driven by structured per-file diagnostics captured from the compile.

- NodeTypeDefinition.CompilationDiagnostics: structured per-file DiagnosticInfo kept in native form
  (id/severity/message/position), not flattened to a string.
- MeshNodeCompilationService: on compile FAILURE ONLY, capture per-file diagnostics from one LSP-style
  per-file-tree compilation (reuses CompilationInputs); the working success emit is untouched. Threaded
  via NodeCompilationResult.Diagnostics into both compile write-back sites.
- CodeEditorControl.Diagnostics (+ CodeEditorDiagnostic): static markers rendered through the existing
  Monaco pushDiagnostics path — no JS change (enableDiagnostics fires an initial pass on load).
- NodeTypeLayoutAreas.BuildCompileErrorSourceViews: pure, testable builder for the ordered
  link+editor views per source file.
- Test: CompileErrorPageTest covers ordering, the source link, the clear message, and the marked editor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…FX example

Adds a 'Scope' NodeType (ScopeNodeType) whose Content is the IScope<,> C# source (CodeConfiguration),
registered in AddGraph. CSharpFileParser now honours a '// NodeType: Scope' header so a Source .cs can
declare itself a first-class scope. Pairs with the generator gate (already in HEAD, 94ee0d9): the
BusinessRules scope generator runs only for IScope-bearing compiles, not every Code compile.

Includes an FX cross-rate conversion example (ICurrencyConversion : IScope<FxTrade, FxRates>) + test.

NOTE: folded-Scope source discovery (so a '// NodeType: Scope' Source node is pulled into the parent
compile) and STANDALONE scope compilation — the real fix for both the runtime-compile slowness (semantic
binding over the whole reference set) AND decoupling BusinessRules from low-level Graph — are the next step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GetContentSchema resolved the content type from tempHub's TypeRegistry but
generated the JSON schema with the PARENT hub's JsonSerializerOptions. That
options object carries a PolymorphicTypeInfoResolver bound to the parent's
registry, which does not own the compiled content type — so GetOrAddType fell
back to TypeRegistry.FormatType and emitted the namespace-qualified, capitalized
Type.FullName as every $type discriminator (e.g. "MeshWeaver.AI.Test.TestProduct"
instead of "TestProduct"). Generate the schema with the type-owning tempHub's
options so references resolve to the registered short name.

Repro pinned in SchemaValidationTest: the schema must not contain the CLR
FullName for the registered content type.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ph — kills build bloat

The generator is a Roslyn analyzer (IsRoslynComponent); a plain ProjectReference from the
foundational MeshWeaver.Graph propagated it to all 40+ downstream projects and ran it on every
compile — the project_graph_generator_build_bloat regression the 01a31ad revert reintroduced.

- Graph.csproj: remove the BusinessRules + BusinessRules.Generator references (Graph no longer
  has a compile-time dependency on either).
- RunSourceGenerators: load ScopeCodeGenerator at runtime BY NAME via reflection
  (TryCreateScopeGenerator) instead of `new ...ScopeCodeGenerator()`. No compile-time ref; the
  generator reaches the runtime via the node Source `#r nuget:MeshWeaver.BusinessRules.Generator`
  resolution / the deployed mesh-local package. Not resolvable -> scope generation skipped and the
  compile error surfaces on the NodeType Progress page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Now that BusinessRules + BusinessRules.Generator are no longer ProjectReferenced by the
framework (they were the build-bloat source — a Roslyn analyzer propagating across Graph's
40+ consumers), node compilation must resolve them at runtime via `#r nuget:MeshWeaver.*`.
The committed root nuget.config already maps MeshWeaver.*/Memex.* to a local `dist/packages`
folder source; this ships that feed inside the container so the runtime resolver
(NuGetAssemblyResolver → Settings.LoadDefaultSettings from the app dir) resolves offline.

- Memex.Portal.Distributed.csproj: copy nuget.config + dist/packages/**/*.nupkg into the
  published /app (next to the app) so they're present at the resolver's working dir.
- The nupkgs are packed into dist/packages by the build process BEFORE publish — the
  `Pack mesh-local #r packages` step (dotnet pack BusinessRules + Generator -o dist/packages
  -p:PackageVersion=3.0.0-preview1), mirrored from .github/workflows/dotnet-test.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…me (not a framework ref)

Completes the BusinessRules.Generator decoupling: the generator is supplied to dynamic node
compilation through the node Source `#r nuget:MeshWeaver.BusinessRules.Generator` (auto-injected
when the unit declares IScope<,>), resolved from the mesh-local feed, and discovered + run via
SourceGeneratorLoader — never a framework ProjectReference (which propagated the analyzer + bloated builds).

- SourceGeneratorLoader: discover [Generator] types from the node's #r-resolved assemblies (no static cache).
- RunSourceGenerators: DeclaresScope-gated; discovers from the #r-resolved paths (replaces the Type.GetType bridge).
- InjectScopeGeneratorReference: auto-prepend the generator #r for IScope units so existing Scope nodes
  compile without author boilerplate. Node-generation-only.
- BusinessRules.Generator.csproj: ALSO pack the generator under lib/ — the runtime #r resolver reads lib/ ONLY
  (NuGetAssemblyResolver -> GetLibItemsAsync); analyzers/dotnet/cs stays for OutputItemType=Analyzer consumers.
- Failure-diagnostics (DiagnoseInputs) pass no generator candidates (best-effort; the flat summary covers it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…), never wedges; scope generator is explicit-#r only

THE atioz wedge root cause: CompileResultFromAssembly swallowed an assembly LOAD / type-extract
failure (e.g. BalanceSheet missing the MeshWeaver.Charting dependency at runtime) into a result with
a non-null AssemblyLocation + empty configurations. Both compile watchers classify success as
`Error is null && !IsNullOrEmpty(AssemblyLocation)` → that read as Status=Ok, so the emergency
compilation-error overlay (gated on Error) never fired, and the per-node hub tried to activate against
an unusable assembly → every Subscribe/GetData parked → wedge.

Fix, per the three rules:
- No assembly if it cannot build: both failure paths return AssemblyLocation=null.
- Build failed + no release: null location → ok=false → CompilationStatus=Error; release creation is
  already gated on ok, so none is written.
- No retry: the first-build kickoff is gated on CompilationStatus==null, so a settled Error never
  re-fires. The emergency overlay renders the failure on the Overview instead of parking.
- Surface the real problem: the extract-failure catch now includes ReflectionTypeLoadException
  .LoaderExceptions, so the Overview names the missing dependency.

Also (per directive): the BusinessRules scope generator is injected ONLY when the node Source EXPLICITLY
declares `#r nuget:MeshWeaver.BusinessRules.Generator` — removed the IScope text-scan auto-inject that
forced generator resolution on the compile path. Resolved from the baked mesh-local feed, discovered by
SourceGeneratorLoader. Never a framework reference.

Test: CompileErrorOverviewTest — a broken-type instance's Overview COMES BACK (bounded timeout, no hang)
SAYING it had a compilation error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…) + fold content checks into reactive Match

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

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

The Anthropic provider's bootstrap model list (DefaultModelIds, shown on Settings/Models) listed the stale claude-opus-4-7. EffectiveModelIds is the code default with no config override, so this is the source of truth for the card list. sonnet-4-6 and haiku-4-5-20251001 are current.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…point), not a pinned list

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r rows

The picker showed each node's full path as a secondary line under the name; for models that path is _Provider/Anthropic/<id> (the provider), which is not a title and just confuses. Show name + category only; keep the full path as a hover tooltip for disambiguation. /model already queries nodeType:LanguageModel, so only models are listed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…MCP writes raw create rejects

Raw MCP create/patch validate content.$type against the hub they run on, so
they reject content types registered only on a dedicated per-type hub (e.g.
Invitation) and writes into restricted partitions (e.g. Admin). Document the
canonical work-through: a throwaway executable Code node + execute_script
calling the typed service (InvitationService.CreateInvitation), plus a
pitfalls-table row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

3 participants