Conversation
Test Results 44 files 44 suites 27m 13s ⏱️ For more details on these failures, see this check. Results for commit 3eafb33. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
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.NuGetresolver + 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/Test → code) 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.
…+ 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>
|
@copilot resolve the merge conflicts in this pull request |
Resolved. The merge with Conflicts resolved:
|
Code review — recent stability batch
Manual review of the last ~20 commits since Correctness — should fix before merge1. ✅ foreach (var (k, v) in perParams)
{
var newKey = "@" + prefix + k.TrimStart('@');
renamedSql = renamedSql.Replace(k, newKey);
renamedParams[newKey] = v;
}
Fix: single regex pass keyed on 2. ✅ Fix: 3. ✅ Fix: parse every query in 4. ✅ Fix: Race / lifecycle hazards5. ✅ Fix: drop the time-based heuristic in favour of a structural one — skip recovery only when the thread is still an auto-execute candidate ( 6. ✅ 7. ✅ 8. ✅ Fix: pre-allocate the Style / consistency9. ✅ 10. ✅ 11. ✅ Fix: drop the per-query Limit injection. Limit is enforced post-union via ✅ Looks good (no action needed)
|
Code review — part 2: rest of the PR
Continuing review on the bulk of the PR (everything before the recent stability batch). Focused on the new projects ( Correctness — should fix before merge12. ✅ return _cache.GetOrAdd(key, _ => ResolveCoreAsync(requested, framework, ct));If Fix: evict faulted/cancelled tasks from the cache before returning. Also pass 13. ✅ Fix: switched to 14. ✅ Fix: post-hydration, the resolver opens the package folder via 15. ✅ Fix: defensive 16. ✅ Race / lifecycle hazards17. ✅ 18. ✅ 19. ✅ Fix: replaced with a single bounded Style / consistency20. ✅ Fix: register the publisher as a true singleton via 21. ✅ Fix: gate hosted-service registration on 22. ✅ 23. ✅ ✅ Looks good (no action needed)
Areas not covered in this reviewPersistence-service refactors ( |
Review fixes applied — all 23 items addressed5 commits, organised by batch. Locally committed, not pushed yet.
Verification
Notes
Ready to push when you want. |
|
Done — review item #14 is now closed in commit |
…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>
… 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>
…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>
…, 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>
… 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>
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>
|
@copilot resolve the merge conflicts in this pull request |
Test Results (shard 1)965 tests 959 ✅ 7m 49s ⏱️ For more details on these failures, see this check. Results for commit 3eafb33. ♻️ This comment has been updated with latest results. |
Test Results (shard 0) 13 files 13 suites 12m 47s ⏱️ For more details on these failures, see this check. Results for commit 3eafb33. ♻️ This comment has been updated with latest results. |
Test Results (shard 3)322 tests 322 ✅ 1m 5s ⏱️ Results for commit 3eafb33. ♻️ This comment has been updated with latest results. |
Test Results (shard 2)1 096 tests 1 095 ✅ 5m 31s ⏱️ Results for commit 3eafb33. ♻️ This comment has been updated with latest results. |
PartitionAccessPolicy.GetPermissionCap() started from ~0 and stripped only the eight per-policy flags (Read/Create/Update/Delete/Comment/Execute/Thread/Api), so the privileged CREATE-class writes Compile (create a NodeType release) and Sync (static-repo overwrite) — which have no per-policy flag — leaked through every read-only policy cap. An Admin/Editor (whose role grants Compile) thus retained release-creation on a read-only partition (Doc/Agent/Role), and the 16 PartitionAccessPolicy/StaticNamespacePolicy "capped to Read…" tests failed once Security.Test stopped timing out and actually ran. Gate Compile/Sync on the Create flag: a partition that denies Create must deny them too (the legitimate read-only-partition compile runs as System, never the user — NodeTypeReleaseGateTest.SystemCompile_FillsCache_OnReadOnlyPartition). Writable policies keep them (the reason the base is ~0, not Permission.All). Verified: full MeshWeaver.Security.Test green (253/253), incl. all PartitionAccessPolicyTests + StaticNamespacePolicyTests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… files) The two one-off harness icons I just added are now inline SVG in the harness Definition (single-quoted attrs; the renderer treats an Icon starting with '<' as raw markup) instead of /static/NodeTypeIcons files — so the icon travels WITH the node and needs no embed glob, /static serving, or icon-allowlist entry. Deleted claude.svg + copilot.svg and reverted their KnownNodeTypeIcons entries. MeshWeaver keeps the /static/NodeTypeIcons/meshweaver-logo.svg path: its logo is a 40-path brand mark already shared with the MeshWeaverLogo component, and the central NodeTypeIcons collection stays — it's the DRY home for the icons reused across ~400 node/type references; inlining those would duplicate shared markup hundreds of times. Inline is for one-offs; the collection is for shared icons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ore deadlock Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… dropped from publish) BakeMeshLocalFeed packed MeshWeaver.BusinessRules + .Generator but added the nupkgs as <Content> inside a BeforeTargets="ComputeFilesToPublish" hook. The SDK's ComputeFilesToPublish dependency chain (ComputeResolvedFilesToPublishList -> _ComputeCopyToPublishDirectoryItems -> GetCopyToPublishDirectoryItems) runs BEFORE that hook and has already frozen @(Content) into the publish set, so the late items were silently dropped. The static nuget.config <Content> shipped fine, so the image carried the mesh-local source but an EMPTY dist/packages -> every scope node failed in prod with "No NuGet package 'MeshWeaver.BusinessRules.Generator' matching '*' found" (atioz AgenticPension/Statement). Fix: - Pack into a clean per-build staging dir under obj (RemoveDir first) so only the current curated pair ships - the repo dist/packages dev feed accumulates stale nupkgs (incl. a lib-less 3.0.0-preview1 generator) the old **/*.nupkg glob shipped. - Inject via <ResolvedFileToPublish RelativePath="dist\packages\..."> - the canonical append-only publish item that survives the BeforeTargets hook and lands at /app/dist/packages (matching nuget.config's relative mesh-local source). - Two-step item with QUALIFIED %(_MeshLocalNupkg.Filename): an unqualified %(Filename) in a target ItemGroup expands to empty -> both nupkgs collapse to the same RelativePath and fail NETSDK1152. Verified: -c Release publish output now contains both nupkgs under dist/packages; the deployed image's resolver finds the generator; AgenticPension/BalanceSheet compiles Ok. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n create Every partition must have a persisted Space root (namespace="" id=<P>); a missing root makes the bare partition address un-routable (GetDataRequest routing loop -> faulted data source). The invariant was scattered across the static-repo importer, onboarding, and SpacePostCreationHandler; centralize it on HandleCreateNodeRequest -- the one handler every node create flows through. For a CHILD create (non-empty namespace, not an _Access assignment) it ensures the Space root and the creator's Admin grant exist before the requested child is validated -- re-creating either if missing (self-healing). Both writes run under ImpersonateAsSystem (a fresh partition is owned by nobody). Reactive, idempotent (NodeAlreadyExists = success, race-safe), re-probed every create. Gated to stay inside the security model: central mesh hub only; host must use the Space type; authoritative existence via storage + static-node fallback; and crucially an AUTHORIZATION gate -- the heal runs only when the creator already holds Permission.Create on the partition (System short-circuits to All), so it can never launder an implicit-partition creation past PartitionWriteGuardValidator. SpacePostCreationHandler skips the grant for the system creator (System has Permission.All; catalog read = publicRead _Policy). Tests: PartitionRootBootstrapTest (7) -- fresh partition, repair-root-missing, repair-grant-missing, idempotent no-op, system-creator (root, no grant), no-recursion, concurrent first-writes. Security/NodeOperations/Graph green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sync onError NodeTypeReleaseGateTest.Viewer_WithoutCompile_IsRefused was a 2-core "deadlock" (deterministic timeout). The dump proved it was a missed reactive emission, not a lock (idle threadpool, no app frame); the permission probe proved GetEffectivePermissions(rel-viewer) DID emit (Read,Execute,Api — Viewer, no Compile). Root cause: a lost message. RequestNodeTypeRelease runs its CheckPermission and, when the effective-permission is already cached (warmed by the preceding NodeType compile's RLS reads), emits and invokes onError SYNCHRONOUSLY — re-entrant, inside the call. The test pushed that onError into a plain Subject and only subscribed afterwards via refusals.FirstAsync().ToTask(), so the synchronous refusal was dropped → the ToTask waited forever → timeout. Cold cache = async emission = subscribe wins = passes (the flakiness). Found via DebuggingMessageFlow.md (msg-trace + dotnet-dump + a reactive probe). Fix: ReplaySubject(1) buffers the refusal so FirstAsync observes it whether the gate answers synchronously (warm) or asynchronously (cold). Verified at DOTNET_PROCESSOR_COUNT=2: was a hard timeout, now passes in ~11s. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mespace collection, platform-admin tier)
Documents the unified pattern for partitions that ship instances of a NodeType
(Agent/Harness/Skill/Model): the DB partition root is a single nodeType:NodeType
node linking to the registered static C# definition (no Space-root vs type-def
path collision -> no GetDataRequest routing loop); instances live in the
partition; the effective set is collected across {user, space, platform}
namespaces; the platform tier is managed by platform admins via settings GUI + API.
Captures the harness routing-loop root cause (NodeType==RootNamespace collision;
Model is the exception that proves it).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…urface bound-stream faults Defense-in-depth for the atioz 2026-06-21 render hang. The hang's primary cause (a transient partition-root _RootProbe WIP, already gone from committed code) is resolved; these address the residual AccessContext-null storm and the silent-hang UX. [data] VirtualDataSource.SetupDataSourceStream: each NON-initial GetStreamUpdates emission is written into the data source's own mirror stream via stream.Update, on the upstream provider's background Rx scheduler where the AsyncLocal AccessContext is wiped. On a User-mode hub the resulting UpdateStreamRequest carried a NULL AccessContext and the PostPipeline never-null guard failed it closed -> a DeliveryFailure storm (atioz: a ds/Skill synced-query data source at ~3/sec, OnError-ing the typed-content stream so the bound area hangs). Stamp System on this infra mirror write: the data is already RLS-filtered at the query layer and per-user enforcement is re-applied at the consumer (SyncedQueryDataSourceExtensions.WrapWithPerUserRls). Same rule + fix as the resubscribe in JsonSynchronizationStream and the stale-patch refresh in SynchronizationStream. System on the WRITE does not collapse per-user READS (those stay filtered at the consumer). Note: no unit repro -- the never-null failure is specific to the distributed sync-hub identity, which the local HubTestBase data-source hub does not replicate. Existing VirtualDataSource tests still pass; the fix is verified by the atioz residual storm count dropping post-deploy. [blazor] BlazorView.DataBind: the Stream.DataBind(...).Subscribe(...) had an onNext but NO onError (unlike the sibling node-bound branch), so a faulting bound stream left the fault unobserved and the control spinning forever -- the "gui is just hanging" symptom. Add an onError that logs and renders the DEFAULT value on the UI thread so the control draws instead of hanging; ObjectDisposedException stays a benign Debug teardown artifact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n a bad enum value A DataGridView PropertyColumn bound to an enum whose data value isn't a member (atioz: HorizontalAlignment "center") made GetDataBoundValue's Enum.Parse throw INSIDE BuildRenderTree — the throw escaped the render, killed the Blazor circuit, and the whole page / side-panel thread vanished. Use Enum.TryParse(ignoreCase) with a default fallback so a mis-cased or unknown literal degrades gracefully instead of tearing the circuit down. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e self-heals DispatchView is the ONE place every UiControl becomes a Blazor component, so it's the one place to contain a render-time throw. A control that throws inside BuildRenderTree (e.g. an enum property bound to an unparseable literal in DataGridView.RenderPropertyColumn — atioz 2026-06-21) otherwise escaped the render, tore down the whole Blazor circuit, and hung the page with no feedback. The ErrorBoundary now catches it, surfaces the message in the control's own slot, and lets the rest of the page render — the environment self-heals instead of going dark. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Surfaces render-time errors instead of crashing the page (atioz 2026-06-21). The enum-parse fix itself landed in 806d501 (GetDataBoundValue uses case-insensitive TryParse); this adds: [blazor] DispatchView wraps the dynamically-rendered UiControl in a Blazor <ErrorBoundary>. DispatchView is the ONE place every control is rendered, so a control that throws inside BuildRenderTree (e.g. an enum property bound to an unparseable literal in DataGridView.RenderPropertyColumn) would otherwise escape the render, tear down the whole Blazor circuit, and hang the page with no feedback. The boundary catches it, SURFACES the message in the control's own slot, and lets the rest of the page render. [test] GetDataBoundValueEnumTest reproduces + pins the enum crash: a mis-cased literal ("center") must resolve case-insensitively (was: case-sensitive Enum.Parse -> ArgumentException inside the render), and an unknown literal must fall back to default, never throw. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…om runtime serving (fixes harness routing loop) A NodeType catalog (Harness/Agent/Skill) registered TWO nodes at the same path: the in-memory NodeType type-def (AddMeshNodes, path = NodeType discriminator) and the DB partition root (path = RootNamespace). When NodeType == RootNamespace == the partition name and the DB root wins bare-address resolution, the runtime disagrees about ds/<P> -> a GetDataRequest for the bare partition bounces -> routing-loop guard fails it -> ds/<P> faults -> the catalog's live binding + NodeType watchers die -> the harness selector disappears on switch. (Model never collided: NodeType "LanguageModel" != RootNamespace "Model".) Fix (Harness; generalizes to Agent/Skill next): the partition root is a single nodeType:NodeType node (id = type name) linking to the registered static C# type (NodeTypeDefinition.StaticTypeName) for its HubConfiguration. The in-memory type-def is registered definition-only (MeshNode.IsDefinitionOnly) on the DB-synced path: dissociated from runtime node-serving + query (MeshDataSource.WithMeshNodes, MessageHubGrain.TryResolveStaticNode, StaticNodeQueryProvider, the CreateNode existing-node probe all skip it) but still consulted as a definition (NodeTypeEnrichmentHelpers resolves the HubConfiguration via StaticTypeName from the static registry). Postgres owns the bare partition path -> no second claimant -> no loop. EnsureRoot already upserts + the PartitionRoot is in the import fingerprint, so existing Space roots re-import to NodeType roots. Doc: NodeTypeCatalogs.md. Tests: NodeTypeCatalogTest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…enied)
BuildModelQueries added namespace:{currentPath}/_Provider WITHOUT the
reserved-partition filter the agent/skill registry queries already use. On the
login page currentPath resolves to the rogue "login" ROUTE partition, so the
query read the policy-less partition and AccessControlPipeline failed the WHOLE
query with "lacks Read permission on 'login'" -> empty model picker. Apply the
same IsReservedPartition guard to currentPath + nodeTypePath. Tests:
BuildModelQueries_ReservedCurrentPath_IsSkipped / _RealCurrentPath_IsIncluded.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ub-hub reads parent) A hub initializes and syncs its own EntityStore under its own credential (ImpersonateAsHub => AccessContext.ObjectId = the hub's mesh address) and a sub-hub subscribes to its parent/ owner the same way. No AccessAssignment ever exists for a hub address, so the owner's RLS denied that Read => the sub-hub never got its parent's snapshot, its layout area never rendered, and FutuRe LineOfBusiness Search timed out (50s). Access was not propagating. Mark hub credentials explicitly (AccessContext.IsHub, set by both ImpersonateAsHub paths) and grant a hub credential Read on its OWN path + ANCESTOR scopes only (the sync direction) - never siblings, descendants, the mesh root, or a non-hub identity. Short-circuits before the cold permission-query path, so hub self-sync no longer rides it either. Repro: HubCredentialReadAccessTest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On ConnectStatus.Connected the widget showed "✓ Connected" but stayed up until the user clicked ✕. Now it auto-dismisses ~1.2s after success via a reactive Observable.Timer (no Task.Delay), stored in _connectSub so a dispose / new connect cancels the pending close. New CloseConnectWidget clears the UI state without cancelling the (already-completed) session. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On ConnectStatus.Connected the widget showed "✓ Connected" but stayed up until the user clicked ✕. Now it auto-dismisses ~1.2s after success via a reactive Observable.Timer (no Task.Delay), stored in _connectSub so a dispose / new connect cancels the pending close. New CloseConnectWidget clears the UI state without cancelling the (already-completed) session. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… side-panel header .thread-chat-widget floats up from the input (bottom: calc(100%+6px)); a fixed 280px (or the login dialog's 560px) overran the "New Thread" side-panel header on a short panel — the agent/model picker AND the login dialog were clipped at the top. Cap at min(440px, calc(100vh - 180px)) so it always fits between the header and the input; the inner list scrolls past that. Drops the login widget's bespoke inline max-height in favour of the shared responsive cap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d it back
"Not logged in after reload": the token IS stored in the ModelProvider node, but
the harness's oauthToken comes from the node-backed resolver whose cache is cold
after a reload / pod restart, and `claude setup-token` only PRINTS the token (it
never writes .credentials.json) — so nothing authenticated the CLI.
Now ClaudeConnectStrategy.PersistCredentials writes the captured token to
{configDir}/.credentials.json on the shared config-dir volume (inside the Process
IoPool worker; sync I/O), and ClaudeCodeChatClient falls back to reading it
(effectiveToken = oauthToken ?? ReadCredentialsToken) when the resolver returns
null — so CLAUDE_CODE_OAUTH_TOKEN is still set and the session authenticates.
ConnectStrategyTest now asserts the file is written holding the captured token.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…CLI exit 1) A `claude setup-token` token is consumed via the CLAUDE_CODE_OAUTH_TOKEN env var, NOT a .credentials.json file (that file is the interactive `claude login` OAuth- bundle schema). Writing the token there made the CLI parse a malformed creds file and exit 1 (the blackout + ProcessException). Revert PersistCredentials + its test assertion. The token still lives in the persistent ModelProvider node and is re-applied to CLAUDE_CODE_OAUTH_TOKEN by the harness (effectiveToken); the harness also reads back the CLI's OWN .credentials.json when present (harmless, kept). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s (match PG)
The in-memory storage adapter keeps satellites in one store, so a content query
(e.g. scope:descendants) returned satellite-path nodes that PG never would (PG
stores _Access/_Thread/... in separate per-prefix tables). This surfaced as the
auto-created {partition}/_Access/{creator}_Access grant polluting Query.Test results.
RunQueryNodes now drops satellite-path rows for non-satellite-targeted queries;
explicit satellite queries (a _-segment path, satellite nodeType, source:activity/
accessed) are unaffected. Mirrors the existing MergeAutocompleteSnapshots exclusion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ty (fixes blackout) The per-thread submission watcher's own-writes (ReconcileUserMessageIds + the claim Update) drive the data-source SynchronizationStream.Update, which posts a User-attributed UpdateStreamRequest from the sync/<id> hub. The watcher fires on a scheduler that does NOT carry the originating user's AsyncLocal AccessContext (null on the Orleans grain / no circuit), so the post went out with NO AccessContext -> the never-null PostPipeline guard failed it -> a DeliveryFailure storm the submit never recovered from = "thread disappears on submit". Fix: wrap both own-writes in AccessContextScope.FromNode(threadNode) so they FORCIBLY run under the thread OWNER's identity (the access check already gated the submit; the round inherits that trust). No System impersonation, no null-tolerant fallback. Test: ExecuteThreadMessageTest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s /code skill
The chat slash-skill autocomplete only offered the 3 built-in skills (agent/
model/harness) because it didn't collect space/user skills. BuildSkillQuery now
lists namespace:{user}/Skill|{space}/Skill|Skill nodeType:Skill — the SAME
per-partition registry pattern as agents/models, reserved-partition filtered —
and SkillAutocompleteProvider uses it, so a user's/space's Skill nodes (e.g.
AgenticPension/Skill/*) appear in the autocomplete via inheritance. Adds a /code
built-in skill (Data/Skill/code.md). Tests: AgentPickerQueriesTest.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
abac5de auto-provisions a Space root at each partition path with a CURRENT LastModified. Being a real mesh_nodes row (not a satellite), it leaked into content queries on PG and in-memory alike — dominating recency sorts (is:main scope:descendants sort:LastModified-desc) and showing up under exact partition-path reads. Partition roots are structural containers, not content: RunQueryNodes now drops them unless the query explicitly targets nodeType:Space. Fixes FanOut + EmptyQuery and the real 'partition roots flood recent-items' regression. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The RC line is done; bump the central PlatformVersion default to the clean release. The version machinery already supports a non-prerelease core (continuous builds switch the suffix to -ci.N; AssemblyVersion stays 3.0.0.<build>). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…envs Every merge to main that passes 'MeshWeaver Build and Test' (gated via workflow_run) builds the memex-portal-ai + memex-migration images to the shared ACR (tagged by commit SHA + moving 'main'), then rolls them out to memex, atioz, and memex-cloud via the documented kubectl set-image + rollout flow. The RELEASED channel (clean NuGet + GHCR images on a v*.*.* tag) is unchanged. Requires Azure CI credentials (AzureN OIDC: AZURE_CLIENT_ID/TENANT_ID/SUBSCRIPTION_ID with AcrPush + az aks command invoke rights) before it can run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…push) Adds GitWorkingTreeService: clone a GitHub repo onto the workspace volume, read/ write files, commit, and push — the working-tree counterpart to content sync, shared by the in-portal editor AND the co-hosted AI CLIs. Reactive end-to-end; git runs as a blocking Process leaf through IIoPool, the user's token is injected via an env-based credential helper (never in argv), and paths are per-user isolated. Infra: a memex-workspace RWX PVC mounted at /workspace (memex + memex-cloud only, NOT atioz), and git added to the portal-ai base image (the AI CLIs need it too). Hermetic tests cover the full clone->edit->commit->push round trip against a local bare repo, idempotent re-clone, the no-credential error, and path-escape rejection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r (kills residual AccessContext storm)
InitializeThreadLifecycle's self-healing recovery observation drove its writes
(Executing->Idle reset, HonorPendingCancelOnWake, ResumeInterruptedRound)
WITHOUT the AccessContextScope.FromNode owner scope that ExecRoundWatcher already
applies. On a context-less re-establish continuation those writes posted an
UpdateStreamRequest from the sync hub with null AccessContext -> the never-null
PostPipeline guard failed it -> a DeliveryFailure storm that faulted the
observation -> it re-established in a tight loop ("[ThreadExec] Init observation
faulted for Thread - re-establishing", ~44/70s on atioz). Wrap the whole recovery
handler in AccessContextScope.FromNode(node) so every recovery write forcibly
carries the thread owner's identity. Same root-cause class as the submission-
watcher fix (3f28da5) -- forcibly have an AccessContext = thread owner.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t exact path
The partition-root exclusion broke UserPublicReadTest.DynamicallyCreated_SpaceNode:
an exact 'path:Globex' read of an explicitly-created Space must return it. Scope the
exclusion to non-Exact (Children/Descendants/Ancestors) queries — where structural
roots pollute listings/recency (FanOut) — and leave EXACT path reads alone. Update
QueryAsync_EmptyQuery to assert on an intermediate namespace-prefix ({p}/sub), which
genuinely has no node, since the first-segment partition root {p} is now auto-provisioned.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The access-denied warning didn't name what triggered it, so a denial on a rogue/reserved path (e.g. 'login') was an unattributable warning. Log the delivery message type + sender + hub so the caller can be pinned. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
77 commits of long-running work on
bug_fix— grouped by theme: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.#r "nuget:Pkg, Version"at the top of_Source/*.csresolves via public NuGet.Protocol without an SDK on the container. Same resolver serves interactive markdown code cells.FileSystemPersistenceService.MoveNodeAsyncruns per-descendantWriteAsync/DeleteAsyncthroughTask.WhenAll; newMeshOperationOptions(defaultTimeout = 30s) +WithMeshOperationTimeout(TimeSpan)override;HandleMoveNodeRequestchains.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.CompilationCacheService,_Source/edit re-invalidates owning NodeType, cross-silo broadcast viaMeshChangeFeed, grain-dispose on node delete, live "Compiling … (Ns)" progress inLayoutAreaView.Category(falls back toNodeType), reactive Children catalog, self-as-default create location for non-NodeType nodes, sample orgs →Markdownfor search visibility.MeshChangeFeedevents, resubscribe on owner dispose,DeleteLayoutAreaemits a placeholder immediately and times out slow streams.IAsyncEnumerableaggregator fixes (satellite-safeGatherInputsAsync), 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), RxTimeout()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
dist/cleanup, fix: sample orgs invisible in search due to wrong NodeType #94 sample-org search-visibility fixUpstream already merged into this branch
refactor: reactive persistence — IMeshStorage writes return IObservable(merged)Test plan
dotnet buildsucceedsdotnet 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_Source/*.csusing#r "nuget:MathNet.Numerics, 5.0.0"— compiles & renders (cold + warm cache)/social/connect/linkedin→ profile linked; menu shows connected accountScheduledPostPublisher→ LinkedIn publisher posts;PostStatsRefresherpulls stats🤖 Generated with Claude Code