Fix subsystem active status: green dot = actively running, not just allocated
Details
IsActive was true when NativeBytes > 0 or ManagedAllocBytes > 0, which
made subsystems like P2P Sync show as active just because Rust allocated
3.2 KB of sync engine structures at init (even with P2P disabled/local-only).
Green dot now only means ActiveTaskCount > 0 — the subsystem is actually
executing work, not just holding pre-allocated memory.
Tap into GC/thread APIs for real subsystem metrics
Details
Rendering:
- Track UI thread allocations via GC.GetAllocatedBytesForCurrentThread()
on each timer tick (runs on DispatcherTimer = UI thread). Captures
all layout, binding, render composition, and input allocations.
Shows cumulative memory + per-second alloc rate.
.NET GC:
- Add LOH + POH (Large/Pinned Object Heap) as native bytes — these
heaps hold render targets, bitmaps, and large buffers that are the
real memory consumers in a UI app.
Thread Pool:
- Show ThreadPool.CompletedWorkItemCount as alloc counter for
throughput visibility.
Shell:
- Show actual process thread count (proc.Threads.Count)
- Track loaded assembly count as alloc counter (proxy for shell
complexity / plugin load)
Native (Rust):
- Fixed aggregation to only sum core.* subsystems (not self-referencing
runtime.native which caused double-counting)
Fix subsystem metrics: remove false AI tag, fix runtime counters
Details
- Remove ai.rag scope from BacklinkService — backlink index builds
are a core linking feature, not AI. They run at startup regardless
of AI settings and were incorrectly inflating RAG Index memory.
- Thread Pool: use ThreadPool.ThreadCount (actual pool threads)
instead of GetMaxThreads-GetAvailableThreads which was always ~0
- Native (Rust): aggregate NativeBytes from all core.* subsystems
so the row shows total Rust memory instead of just the untagged
bucket (which is typically 0)
- Shell: mark active (task=1) but don't attribute process-wide
WorkingSet-GcHeap which double-counted Rust/GC memory
- Rendering: mark active (task=1) while UI is running
Fix data metrics display + instrument subsystems for memory tracking
Details
Data tab fixes:
- Dashboard: always reports Plugin Catalog + Subsystems tables (never
filtered out by the EntityCount==0 check in SystemMetricsService)
- Graph: always reports Nodes + Edges tables even when 0 (plugin is
loaded and allocated regardless of graph data)
- Data (in PrivStack-Plugins): always reports at least a Dataset Store
entry; also includes saved queries count when available
Subsystem instrumentation:
- Add RefreshRuntimeMetrics() to SubsystemTracker — populates .NET GC
heap size, ThreadPool active workers, and Shell process-level metrics
from system APIs (no RunTagged needed for these)
- Wire RefreshRuntimeMetrics into Dashboard live timer tick
- Instrument LocalLlamaProvider.CompleteAsync/StreamCompleteAsync with
EnterScope("ai.llm") for LLM inference tracking
- Instrument RegistryUpdateService.CheckForUpdatesAsync with
EnterScope("updates")
- Instrument SnapshotSyncService.StartAsync with EnterScope("core.sync")
- Instrument FileEventSyncService.Start with EnterScope("core.sync")
- Instrument BacklinkService.BuildIndexAsync with EnterScope("ai.rag")
Note: Build may fail at this commit due to concurrent in-progress work
by another session (PluginFooter.axaml) — will be resolved in a
subsequent commit.
Fix Dashboard tab controls: remove linter-generated InitializeComponent stubs
Details
The linter added `private static void InitializeComponent() { throw
new NotImplementedException(); }` to all three tab UserControls. This
shadowed the Avalonia source generator's instance method, preventing
XAML from loading — all tabs rendered empty.
Get notified about new releases