This is a public, read-only report. Striff reads this repository's docs, turns each sentence that makes a claim about the code into a rule, and checks the rule against the code on the default branch. How this works
Each sentence below has a stale name: a type the default branch doesn't declare, or declares somewhere else. Edit the doc so it matches the code, or bring the type back.
GraphMailService has no ILocalStoreService dependency — every read goes straight to the Graph REST API, so the uncreated SQLite schema never matters.
GraphMailService may not depend on ILocalStoreService
Holds
Read Oct 3
--online mode (#62):GraphMailService has no ILocalStoreService dependency — every read (connect, folders, summaries, detail, since-date) goes straight to Graph, so --online (which leaves the SQLite schema uncreated) is fully supported for Graph accounts with no behavioral difference.
GraphMailService may not depend on ILocalStoreService
Holds
Read Oct 3
SyncService runs background IMAP sync. It raises FolderSynced, MessagesRemoved, and RulesApplied events; MainViewModel subscribes and merges new data into observable collections.
MainViewModel depends on SyncService
Holds
Read Oct 3
A static ProviderCatalog.IsICloud(account) replaces what used to be an ImapHost == "imap.mail.me.com" comparison duplicated across six files.
ProviderCatalog has an IsICloud method
Holds
Read Oct 3
A second Gmail entry, gmail-oauth ("Gmail (sign in with Google)", IProviderCatalog.GmailGoogleSignIn), defaults to AuthType.OAuth2Google and carries no app-password hint.
IProviderCatalog has GmailGoogleSignIn
Holds
Read Oct 3
no runtime authentication path consults it, so an account already saved as OAuth2Google connects normally regardless, and AccountEditorViewModel.ShowGoogleAuthOption ORs in AuthType == OAuth2Google so such an account is never shown a blank Authentication combo.
AccountEditorViewModel has ShowGoogleAuthOption
Holds
Read Oct 3
The model exposes computed ResolvedMemberCount and MissingContactCount (both [JsonIgnore]) and a human-readable Display ("Name, N members" / "(M missing)" / "Empty group") so the UI does not have to recompute them.
Actions lists them all when there is more than one (#682), and AllActions() returns them in the order they run — marking, then copying, then moving or deleting.
MailRule has an AllActions method
Holds
Read Oct 3
Every rule belongs to one account (AccountId);
MailRule has AccountId
Holds
Read Oct 3
LoadRules throws RulesFileUnreadableException (#700), because every writer loads the whole list, changes it and saves it back, so an empty read made the next save wipe the file.
RuleService has LoadRules
Holds
Read Oct 3
Arriving mail reaches the rules through SyncService.ApplyRulesToArrivalsAsync: the store records every message it caches as waiting for rules (MessageSummary.rules_applied = 0; rows cached before the column existed default to done), and SettlePendingRulesAsync runs the rules on an Inbox's waiting mail that is arriving and records all of it done, one pass at a time per Inbox, recording other folders' waiting mail done without running anything.
SyncService has ApplyRulesToArrivalsAsync
Holds
Read Oct 3
they now ask for a pass straight after caching, through ISyncService.ApplyPendingRulesAsync.
ISyncService has ApplyPendingRulesAsync
Holds
Read Oct 3
A SavedView bundles one or more folders with a view mode, filter, sort order, optional Hotkey gesture string, IsDefault flag, and optional DaysOfMail limit.
2 rules from this sentence
SavedView has Hotkey
Holds
SavedView has DaysOfMail
Holds
Read Oct 3
FindByGesture() checks user overrides from hotkeys.json first, then falls back to defaults.
CommandRegistry has a FindByGesture method
Holds
Read Oct 3
BatchObservableCollection<T> (Helpers/BatchObservableCollection.cs) — subclass of ObservableCollection<T> that suppresses individual CollectionChanged notifications during bulk mutations and fires a single Reset when the batch closes. This prevents screen readers from re-announcing the focused item after every insert during background sync. Always use BeginBatchScope() in a using block (auto-closes on exception);
BatchObservableCollection has a BeginBatchScope method
Holds
Read Oct 3
the manual BeginBatch() / EndBatch() pair is available for explicit try/finally sites.
2 rules from this sentence
BatchObservableCollection has a BeginBatch method
Holds
BatchObservableCollection has an EndBatch method
Holds
Read Oct 3
It exposes Groups: ObservableCollection<GroupModel> sorted by LastUsedTicks descending and a derived SelectedGroupMembers: ObservableCollection<ContactModel> rebuilt whenever SelectedGroup changes.
2 rules from this sentence
AddressBookViewModel has Groups
Holds
AddressBookViewModel has SelectedGroupMembers
Holds
Read Oct 3
Confirmation dialogs and screen reader announcements are surfaced via event Func<string, string, Task<bool>>? ConfirmRequested and event Action<string, AnnouncementCategory>? AnnouncementRequested;
2 rules from this sentence
AddressBookViewModel has ConfirmRequested
Holds
AddressBookViewModel has AnnouncementRequested
Holds
Read Oct 3
The InsertGroup(Action<ContactModel>) private helper iterates SelectedGroupMembers in recency order and calls the inserter for each — the Compose window sets those inserters via SetInsertActions(to, cc, bcc) so a group can be dropped into any address field with one command.
AddressBookViewModel has an InsertGroup method
Holds
Read Oct 3
it shares the same IContactService instance and raises GroupsChanged for the parent to refresh.
GroupManagerViewModel has GroupsChanged
Holds
Read Oct 3
All of them are handled in CommandPaletteWindow.OnPreviewKeyDown.
CommandPaletteWindow has OnPreviewKeyDown
Holds
Read Oct 3
Markdown mode inserts the equivalent syntax through MarkdownEditing (Helpers/MarkdownEditing.cs — pure, unit-tested text operations applied via TextBox.SelectedText so each toggle is one undo unit).
MarkdownEditing is in QuickMail.Helpers
Holds
Read Oct 3
Rich-mode messages are sent as multipart/alternative by MimeMessageBuilder whenever ComposeModel.HtmlBody is non-empty.
MimeMessageBuilder depends on ComposeModel
Holds
Read Oct 3
EventEditorWindow and GoToDateWindow enter dates, times and the repeat interval through Controls/DateTimeField.cs — a TextBox subclass that steps with the arrow keys.
DateTimeField is in QuickMail.Controls
Holds
Read Oct 3
Stepping and free-text parsing live in Helpers/DateTimeFieldParser.cs (pure, unit-tested in DateTimeFieldParserTests).
DateTimeFieldParser is in QuickMail.Helpers
Holds
Read Oct 3
Helpers/TabStripNavigation.cs installs this once, from App.OnStartup, as a class handler on TabControl — a per-control attached property can be forgotten when a window with tabs is added, a class handler cannot.
TabStripNavigation is in QuickMail.Helpers
Holds
Read Oct 3
Helpers/ContextMenuKeys.cs carries the full account (issue #631) — it is why the attachment lists open their own menu for Shift+F10 and deliberately leave the Applications key to Windows.
ContextMenuKeys is in QuickMail.Helpers
Holds
Read Oct 3
Each consults Helpers/ContextMenuFocusPolicy.cs, which exists because Keyboard.FocusedElement being null means two unrelated things:
ContextMenuFocusPolicy is in QuickMail.Helpers
Holds
Read Oct 3
MainViewModel.SetGroupFlagAsync was added to support batch flagging from the context menu (with the same optimistic update and announcement pattern used by SetMessageFlagAsync).
MainViewModel has SetGroupFlagAsync
Holds
Read Oct 3
MessageSort.FlaggedFirst added.
MessageSort has FlaggedFirst
Holds
Read Oct 3
FlagName/FlagColorHex are resolved from FlagService.LoadFlagDefinitionsAsync() in MainViewModel after summaries are loaded.
FlagService has a LoadFlagDefinitionsAsync method
Holds
Read Oct 3
IsServerFlagged is a transient import field on MailMessageSummary (not persisted directly; it drives setting FlagId to the default flag's Id if no local flag_id exists, and vice versa — see §9).
MailMessageSummary has an IsServerFlagged field
Holds
Read Oct 3
Write: New SetMessageFlaggedAsync in GraphMailService:
GraphMailService has SetMessageFlaggedAsync
Holds
Read Oct 3
MailServiceRouter must expose SetMessageFlaggedAsync and route to the correct backend (ImapMailService or GraphMailService) based on account type — following the same dispatch pattern used for DeleteMessageAsync, MarkReadAsync, etc.
MailServiceRouter has SetMessageFlaggedAsync
Holds
Read Oct 3
Flags: ObservableCollection<FlagDefinition> (sorted by SortOrder)
FlagManagerViewModel has Flags
Holds
Read Oct 3
CanMoveUp / CanMoveDown: based on SelectedFlag's position
TestConnectionAsync for Graph accounts:AccountEditorViewModel.TestConnectionAsync is currently IMAP-specific — it guards on ImapHost, builds an AccountModel with IMAP fields, and calls ConnectAsync.
Router itself implements IMailService so MainViewModel, SyncService, RuleService are unchanged — they always saw IMailService.
MailServiceRouter implements IMailService
Holds
Read Oct 3
MailMessageDetail : MailMessageSummary inherits.
MailMessageDetail extends MailMessageSummary
Holds
Read Oct 3
GraphSendMailService builds the MIME with MimeMessageBuilder, base64-encodes it, and POSTs the ASCII base64 via GraphClient.PostRawAsync.
GraphSendMailService depends on GraphClient
Holds
Read Oct 3
GraphClient.PostRawAsync was added;
GraphClient has PostRawAsync
Holds
Read Oct 3
The ICS-reply MIME building moved to MimeMessageBuilder.BuildIcsReply, shared by both backends.
MimeMessageBuilder has BuildIcsReply
Holds
Read Oct 3
When a new account is added at runtime, the caller (MainViewModel.AddAccountAsync) must call mailRouter.RegisterAccount(account.Id, backendForKind(account.BackendKind)) before the first IMailService method runs against that account.
MailServiceRouter has a RegisterAccount method
Holds
Read Oct 3
Add a case for [features] that copies all key/value pairs into ConfigModel.Features.
ConfigModel has Features
Holds
Read Oct 3
A MessageWindow in v1 has its own MessageWindowViewModel, which is a thin wrapper around a single MessageTabViewModel and a minimal message list (for the user to navigate to the next / previous message without going back to the main window).
MessageWindow depends on MessageWindowViewModel
Holds
Read Oct 3
Add MainWindow.OpenTabs / ActiveTab / ShowTabStrip (all hidden by default).
File QuickMail/ViewModels/MainViewModel.cs, Change Add OpenTabs , ActiveTab , ShowTabStrip , MessageOpenMode , the tab commands, the HandleOpenMessageAsync decision tree, and the new events
MainViewModel has MessageOpenMode
Holds
Read Oct 3
File QuickMail/ViewModels/ComposeViewModel.cs, Change Add WindowTitle , Subject (if not already), the debounced title refresh, and the ComposeKind enum
2 rules from this sentence
ComposeViewModel has WindowTitle
Holds
ComposeViewModel has ComposeKind
Holds
72 rules from 5 docs
See these where the change is. The browser extension puts a pull request's doc findings, and a diagram of what it changed, on the GitHub page itself, so the code and what your docs say about it are side by side.