Remove bottom status bar, move AI + storage state into sidebar
Details
Delete the bottom status bar (~30px) to give plugin content full window
height. The bar contained: status message (removed — no value), active
timer indicator (already in sidebar footer), update status (in Dashboard),
subscription badge (in Settings > About), AI persona button (moved to
sidebar), and storage state pill (moved to sidebar Sync row).
Sidebar expanded footer gains:
- AI Persona button (star icon + gold dot for unseen insights) between
Search and Sync rows
- Storage state label ("Local"/"Cloud") appended to the Sync row
Sidebar collapsed footer gains:
- AI Persona icon with gold dot indicator
- Sync tooltip now includes storage state text
AI balloon repositioned from bottom-right to bottom-left to align with
the sidebar star icon. Balloon positioning code updated to search the
visual tree (star icon is now in NavigationSidebar's name scope).
Removed unused timer-pulse animation style from MainWindow.
Version: 1.69.0 → 1.70.0
Add per-subsystem memory tracker and Dashboard Subsystems tab
Details
Adds visibility into which subsystems consume memory across .NET managed
heap, native Rust allocations, and background task activity. Enables
live per-subsystem metrics in the Dashboard.
Rust tracking allocator (Phase 1):
- New allocator.rs: custom GlobalAlloc with 16-byte header per allocation
storing size + subsystem ID. Per-subsystem atomic counters track bytes
and allocation counts. Thread-local subsystem tag set via with_subsystem()
scope guard.
- Subsystem IDs: untagged(0), storage(1), sync(2), crypto(3), cloud(4),
plugins(5), ffi(6), reserved(7)
- New FFI export: privstack_subsystem_memory() returns JSON snapshots
- Key entry points wrapped: privstack_execute (FFI), auth_initialize/unlock
(Crypto), sync_status (Sync)
C# SubsystemTracker (Phase 2):
- SubsystemTracker: singleton service with AsyncLocal tagging, RunTagged()
for async/sync task wrapping, EnterScope() for synchronous code blocks,
5-sample rolling allocation rate, native counter merging from Rust FFI
- SubsystemDefinitions: static table of 16 built-in subsystems across
UI, AI, Core, Services, and Runtime categories
- Static RunTaggedStatic() convenience for instrumentation without DI
Entry point instrumentation (Phase 3):
- RagIndexService: consumer + deferred init tagged as ai.rag
- IntentEngine: signal consumer tagged as ai.intent
- EmbeddingService: ONNX load + tokenizer tagged as ai.embedding
- LocalLlamaProvider: model load tagged as ai.llm
- WhisperService: model load tagged as ai.whisper
- IpcServer: listener tagged as ipc
- ReminderSchedulerService: initial poll tagged as reminders
- FileEventInboundScanner: poll loop tagged as core.sync
- SyncOutboundService: debounce callback tagged as core.sync
- CloudSyncSettingsViewModel: push + status loop tagged as core.cloud
- UpdateViewModel: startup check tagged as updates
Dashboard Subsystems tab (Phase 4):
- New SubsystemItemViewModel with status dot coloring (active/idle/stopped)
- DashboardViewModel extended with Subsystems tab, summary cards (threads,
managed heap, native memory, active count), per-subsystem item collection
- DashboardView.axaml: third tab button, summary stat cards, table-style
subsystem list with status dot, name, category, task count, memory,
alloc rate columns
- Live refresh on 1-second timer when Subsystems tab is active
Registration wiring (Phase 5):
- SubsystemTracker registered as singleton in CoreServiceRegistration
- Static subsystems registered at startup, eagerly resolved in WireCorePostBuild
- Plugin subsystems registered dynamically in DashboardPlugin.CreateViewModelCore()
- NativeLibrary P/Invoke added for privstack_subsystem_memory
Version bumps:
- Rust workspace: 1.15.3 → 1.15.4
- Desktop app: 1.68.6 → 1.69.0
- Dashboard plugin: 1.4.0 → 1.5.0
Rework GitHub Gist integration: sync-all, gist picker for publish
Details
Replace the individual gist source picker with a "Sync All Gists" button that
pulls every user gist as a collection in a single operation. Replace the inline
"Publish as Gist" dialog in both Snippets and Notes with a gist picker modal
that lets users add files to existing gists or create new ones.
Snippets plugin:
- GistSyncService: add SyncAllGistsAsync() for bulk gist discovery/sync,
add AddSnippetToExistingGistAsync() for adding files to existing gists
- GistSourcesViewModel: remove add-source flow (IsAddingSource, gist picker
list, LoadAvailableGistsAsync), add SyncAllGists command with progress
- GistSourcesOverlay: remove gist picker panel, update empty state text,
replace footer with "Sync All Gists" button + progress indicator
- New GistPickerViewModel + GistPickerOverlay: two-tab picker (add to
existing gist from local GistSources, or create new gist)
- SnippetsViewModel: replace ShowPublishGistDialog/CancelPublishGist/
ConfirmPublishGist with PublishToGistAsync using the new picker
- SnippetsView: remove inline publish panel, add GistPickerOverlay
Notes plugin:
- GistPublishService: add ListUserGistsAsync() with pagination and
AddToExistingGistAsync() with duplicate filename handling
- New GistPickerViewModel + GistPickerOverlay: two-tab picker (add to
existing gist from GitHub API, or create new gist)
- NotesViewModel: replace fire-and-forget PublishToGistAsync with picker
workflow that returns gist URL on confirm
- NotesView: add GistPickerOverlay
Snippets 1.9.0 → 1.10.0, Notes 1.65.2 → 1.66.0
Add article category tags, tag filtering, and summary dedup
Details
Parse <category> elements from RSS/Atom feeds into a new Categories
field on RssArticle. Both FetchFeedAsync and RefreshFeedAsync now
extract category terms via SyndicationItem.Categories.
Article detail view shows category tags as styled pills below the
author/date line. Article list items also display compact tag labels.
Tag filter dropdown in the toolbar lets users filter articles by any
tag present in the current article set. Clear button resets the filter.
Summary preamble box is now hidden when the summary text is just a
prefix repetition of the article content — detected via normalized
plain-text comparison in HasDistinctSummary on RssArticle. This
prevents the redundant preamble block seen with feeds like the
PrivStack changelog where summary == content.
Version bump 1.9.6 → 1.10.0
Add fuzzy search, new AI intents, and RAG improvements to Contacts plugin
Details
Add StringSimilarity utility (Jaro-Winkler, Levenshtein, Token Jaccard) for
fuzzy name matching in contact resolution and search. ResolveContactAsync now
falls back to fuzzy matching (threshold 0.6) when exact match fails, including
a full scan fallback for typos/nicknames. Search intent also augments SDK
results with fuzzy matches.
New intents:
- contacts.get_contact: retrieves full contact details (emails, phones,
addresses, social profiles, tags, recent interactions)
- contacts.list_by_company: lists contacts at a company (fuzzy matched)
- contacts.list_by_group: lists contacts in a group (fuzzy matched)
RAG indexing now includes:
- Company chunks with name, industry, website, employee count
- Group chunks with name, description, member count, member names
- Enriched contact chunks with tags, address, social profiles
Version bump 1.9.7 → 1.10.0
Get notified about new releases