Fix Tab key incorrectly tree-nesting non-list blocks
Details
The global Tab KeyDown handler in NotesView was catching Tab presses in
definition lists, tables, and other non-RTE blocks and calling
IndentBlock(), which removes the block from its position and appends it
as a child of the previous sibling — appearing as a "merge" with the
block above.
This was wrong for all non-list block types:
- RTE blocks (paragraph, heading, etc.) already handle Tab internally
via IndentRequested, adjusting visual IndentLevel — so the global
handler was unreachable for those.
- Non-RTE blocks (definition list, table, image, code) don't support
Tab indentation, but the global handler was tree-nesting them.
Remove the global Tab handler entirely. Each editor handles Tab
appropriately on its own.
Update DetailedDescriptions with expanded AI intent listings
Details
All 12 plugins now list their complete AI intent inventory in the
DetailedDescription field, which is RAG-indexed for Duncan's intent
classification pipeline.
Updated from single-line format to multi-line bullet format matching
the Habits gold-standard pattern. Each intent line includes the intent
ID, action description, and slot signature with required (*) markers.
Intent count by plugin:
Calendar: 4, Notes: 4, Contacts: 5, Email: 5, Tasks: 4 (unchanged),
Finance: 10 (unchanged), Journal: 3, Habits: 6, Snippets: 4, RSS: 4,
WebClips: 3, Files: 3, Canvas: 2 (new), Data: 2 (new)
Total: ~59 intents across 14 plugins (up from 25).
Add IIntentProvider to Canvas and Data plugins
Details
Canvas: 2 new intents (create_whiteboard, delete_whiteboard)
- create_whiteboard: create new blank whiteboard
- delete_whiteboard: delete by ID or title search
- Changed CanvasPlugin from sealed class to sealed partial class
Data: 2 new intents (run_query, import_csv)
- run_query: execute saved SQL query by name, returns result preview
- import_csv: create empty dataset placeholder for import
- Changed DataPlugin from sealed class to sealed partial class
These two plugins previously had zero AI intent support. Both now follow
the standard partial class IIntentProvider pattern with entity resolution
helpers.
Expand AI intents for Snippets, RSS, WebClips, and Files plugins
Details
Snippets: +3 intents (search_snippets, delete_snippet, create_collection)
— 4 total
- search_snippets: search by title/content with language/collection filter
- delete_snippet: trash snippet by ID or title search
- create_collection: create snippet collection with description/color
RSS: +3 intents (remove_feed, mark_all_read, search_articles) — 4 total
- remove_feed: unsubscribe + delete articles by ID or name search
- mark_all_read: mark all articles read (optionally per-feed)
- search_articles: search by title/summary with feed/starred filter
WebClips: +2 intents (search_clips, update_clip_status) — 3 total
- search_clips: search by title/URL/content with status filter
- update_clip_status: set status (unread/reading/read/archived)
Files: +2 intents (search_files, delete_file) — 3 total
- search_files: search by file name with folder filter
- delete_file: soft-delete (trash) by ID or name search
Uses `with` expressions for init-only record properties (RssArticle.Read,
WebClip.StatusRaw). Reuses existing service search methods where available.
Expand AI intents for Email, Journal, and Habits plugins
Details
Email: +4 intents (search_email, mark_read, move_message, reply) — 5 total
- search_email: search by subject/sender with folder filter
- mark_read: mark messages read/unread by ID or subject search
- move_message: move to folder (trash/archive/junk/custom)
- reply: create reply draft (saves as draft, does not send)
Journal: +2 intents (search_entries, delete_entry) — 3 total
- search_entries: search by content with date/mood filters
- delete_entry: delete by ID or date search
Habits: +3 intents (update_habit, get_streak, get_today_status) — 6 total
- update_habit: modify name, frequency, target, category, active status
- get_streak: returns current/best streak and completion rate
- get_today_status: checklist of today's logged/pending habits
All plugins use ResolveEntityAsync pattern with ID-first/search-fallback.
Email uses `with` expressions for init-only record properties.
Get notified about new releases