fix(quickfiler): resolve issue #726 code-correctness sweep (6 of 8 findings) - #738
Merged
Merged
Conversation
…ndings) Consolidated fix for eight code-correctness findings surfaced during the bugs-638-644-647 parallel-orchestration review sweep, each left unfixed by its originating item to stay within that item's declared file-footprint. 1. FilerQueue drain-barrier hardening (Major): wrap the consumer loop body in try/finally so _consumerRunning always clears, add a null guard on Enqueue, and a null/empty-safe diagnostic path in the catch handler. ConsumeAsync narrowed to internal (no external callers). Applied the identical try/finally hardening to the sibling TaskVisualization/FlagChangeTrainingQueue.cs guard-reset. 2. QfcHomeController.Metrics: null-guard the diagnostics line array and delete the orphaned calendar appointment when diagnostics are empty, instead of reordering (GetMoveDiagnostics takes the appointment by ref). 4. EfcItemController: route both InitializeWebViewAsync fire-and-forget call sites through a new guarded wrapper (mirroring QfcItemController's existing fault boundary) so a fault is logged instead of silently finalized away. 5. Guard both WebView fault-boundary sinks (Efc and Qfc) and EfcFormController.BoundaryErrorSink against a null or throwing sink delegate, so a misconfigured sink cannot reinstate an unobserved fault. 6. Removed QfcFormController's dead _helperTasks field: it started a FromMailItemAsync call per item and discarded the result unawaited, while the sync pipeline it feeds builds its own MailItemHelper via a separate synchronous constructor -- confirmed by grep as write-only with no reader anywhere in the repo. 7. TaskViewer.ProcessCmdKey now falls through to base.ProcessCmdKey when the controller does not consume the Alt-chord keystroke, instead of unconditionally claiming every Alt-modified key. 8. QfcFormViewer.ProcessCmdKey: removed two dead locals with no effect on the real event pipeline. Added the missing positive regression test for Keys.Menu | Keys.Alt in EfcViewerTests (the Keys.Menu disjunct of ClaimsAltChord's guard was previously deletable without failing any test). Deferred, with evidence, not fixed in this change: - Finding 3 (StoreWrapperController.EvaluateLaunchReadiness): already tracked as an open item in docs/features/active/2026-07-09-storewrapper-dialog-imprecise-for-genuine-failure-287/spec.md, crosses the UtilitiesCS/TaskMaster assembly boundary. - Finding 6, LoadFolderHandler/InitAsync gap: the sync LoadFolderHandler has no synchronous equivalent of FolderPredictor.InitAsync, and its three call sites run through PopulateFolderComboBox, which checks InvokeRequired -- forcing a synchronous await risks a UI-thread deadlock. A minimal fix here would trade a latent hang for a more certain one. - Finding 6, dead QfcHighConfidencePreFilter.FilterAsync: confirmed unreachable in production (HighConfidencePreFilterLoader is declared but never invoked), but removal cascades into three test files (QfcHighConfidencePreFilterTests.cs, QfcHomeControllerIssue218Tests.cs, QfcHomeControllerRunAsyncHighConfidenceTests.cs), exceeding this change's minimal-fix scope. - Finding 6, two stale comments and one stale test docstring from item #678's remediation: the issue gives no file/line citation and #678 touches 26 files, too broad to identify reliably without expanding scope for a documentation-only latent nit. New regression tests: FilerQueue null-Enqueue and empty-Helpers-drain-recovery; EfcViewer Keys.Menu | Keys.Alt positive Alt-chord match. Toolchain: CSharpier format, analyzer rebuild (EnableNETAnalyzers+EnforceCodeStyleInBuild), nullable rebuild (TreatWarningsAsErrors), MSTest 1475/1475 passed across QuickFiler.Test + TaskVisualization.Test. Fixes #726 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ATYLDoRLKXS5sgAzegW7ZL
…-sweep-code-defects-726
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Suggested title
fix(quickfiler): resolve issue #726 code-correctness sweep (6 of 8 findings)
Summary
FilerQueue's consumer-running flag with atry/finallybarrier so an exception in the worker loop can no longer leave the queue permanently stuck; applies the same hardening to the siblingFlagChangeTrainingQueue.EfcItemController's two fire-and-forgetInitializeWebViewAsynccalls through a new guarded wrapper, mirroring the existingQfcItemControllerfault boundary, so a fault is logged instead of silently discarded.EfcItemController,QfcItemController,EfcFormController) against a null or throwing sink, closing a latent path back to the exact unobserved-fault behavior those boundaries exist to prevent.QfcHomeController's metrics write path and removes an orphaned calendar appointment when diagnostics are empty.TaskViewer.ProcessCmdKeyto fall through tobase.ProcessCmdKeywhen the controller does not consume an Alt-chord keystroke, instead of unconditionally swallowing every Alt-modified key.QfcFormViewer.ProcessCmdKey, and a write-only field inQfcFormControllerthat started a discarded, unawaitedMailItemHelper.FromMailItemAsynccall per item.Keys.Menu | Keys.AltAlt-chord shape and twoFilerQueueregression tests (null-item guard, empty-Helpers exceptional-exit recovery).Why
This consolidates eight code-correctness findings surfaced during the
bugs-638-644-647parallel-orchestration review sweep. Each finding was identified by a prior item's feature-review agent but deliberately left unfixed at the time because fixing it would have exceeded that item's declared file-footprint scope. Rather than run eight separate bug-fix cycles for findings that are each small in isolation, they are consolidated into this one issue (see issue #726 body, and the repo's established practice for consolidated multi-defect issues per #451 and #619).Two findings are rated High severity individually:
FilerQueueflag leak (finding 1) can hang the background mail-filing mover once the narrow trigger condition — an exception inside the diagnostic branch of the catch handler, or a null item — is hit.EfcItemControllerunguarded fire-and-forget (finding 4) is classified live by the same reasoning that made the sibling fix in issue Bug: qfc-initializewebviewasync-fault-is-unobserved #670 necessary: a discarded faultedTaskunder .NET Framework 4.5+ is silently finalized with no diagnostic.What Changed
Core logic:
QuickFiler/Controllers/FilerQueue.cs— null guard onEnqueue;ConsumeAsyncnarrowed tointernal(no external callers); worker loop body wrapped intry/finallyclearing_consumerRunningunder the lock on every exit path; empty/null-safe diagnostic logging extracted toLogItemFailure.TaskVisualization/FlagChangeTrainingQueue.cs— the identicaltry/finallyguard-reset hardening applied to this sibling queue's consumer loop.QuickFiler/Controllers/EfcItemController.cs+ newQuickFiler/Controllers/EfcItemController.WebViewFaultBoundary.cs— bothInitializeWebViewAsynccall sites now go throughInitializeWebViewGuardedAsync, which catches and routes faults to an injectableWebViewInitializationErrorSink.QuickFiler/Controllers/QfcItemController.WebViewFaultBoundary.csandQuickFiler/Controllers/EfcFormController.cs— sink invocations wrapped so a null or throwing sink delegate falls back to the logger instead of faulting the guard task.QuickFiler/Controllers/QfcHomeController.Metrics.cs— null-safe diagnostics line array; deletes the orphaned calendar appointment when diagnostics are empty (kept the existing call order becauseGetMoveDiagnosticstakes the appointment byref).TaskVisualization/TaskViewer.cs—ProcessCmdKeynow returnstrueonly when the controller actually consumed the Alt-chord keystroke, otherwise falls through tobase.ProcessCmdKey.QuickFiler/Viewers/QfcFormViewer.cs— removed two dead locals with no effect on the real event pipeline.QuickFiler/Controllers/QfcFormController.cs+QfcFormController.Actions.cs— removed the write-only_helperTasksfield, which started aMailItemHelper.FromMailItemAsynccall per item and discarded the result unawaited; the sync pipeline it fed builds its ownMailItemHelpervia a separate synchronous constructor.Tests:
QuickFiler.Test/Controllers/FilerQueueTests.cs—Enqueue_NullItem_ThrowsArgumentNullException;ConsumeAsync_ItemWithEmptyHelpersThrows_ConsumerRecoversForLaterItems(proves the consumer recovers and processes a later item after an exceptional exit, not just the normal empty-queue exit).QuickFiler.Test/Controllers/EfcViewerTests.cs—ClaimsAltChord_WithMenuKeyAndAlt_ReturnsTrue(theKeys.Menudisjunct ofClaimsAltChord's guard was previously deletable without failing any existing test).Build:
QuickFiler/QuickFiler.csproj— registers the newEfcItemController.WebViewFaultBoundary.cscompile item.Architecture / How It Fits Together
No new components or wiring. Each fix stays within the file(s) that own the defective behavior:
FilerQueue/FlagChangeTrainingQueue: internal loop hardening, no external contract change (ConsumeAsync's narrowing tointernalwas verified to have zero external callers).EfcItemController's new fault boundary is apartial classfile mirroring the existingQfcItemController.WebViewFaultBoundary.cspattern already in the codebase, so both viewers now expose the same shape of injectable error sink.QfcFormControllerdead-field removal has no downstream effect: the field was never read, so the pipeline's actual behavior (a freshMailItemHelperbuilt synchronously per item insideQfcItemController.Initialize) is unchanged.Verification
Completed:
dotnet tool run csharpier format .— clean, 14 files in the intended change set, no unrelated drift.msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true— Build succeeded, 0 Error(s).msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:TreatWarningsAsErrors=true— Build succeeded, 0 Error(s).vstest.console.exe QuickFiler.Test.dll TaskVisualization.Test.dll /Platform:x64 /InIsolation— 1475/1475 tests passed, including the three new regression tests.Recommended:
Backward Compatibility / Migration Notes
FilerQueue.ConsumeAsyncvisibility narrowed frompublictointernal. Verified via repository-wide grep that it has no external callers; theConsumerproperty that tests read remainspublicand unchanged.Risks and Mitigations
try/finallychange toFilerQueue's andFlagChangeTrainingQueue's consumer loops changes control flow in a background worker.Mitigation: the normal empty-queue exit path still clears the flag inline as before; the
finallyonly adds coverage for the previously-unhandled exceptional exit. New regression testConsumeAsync_ItemWithEmptyHelpersThrows_ConsumerRecoversForLaterItemsproves the consumer keeps draining after an exceptional item._helperTaskseliminates a live Outlook COM call (FromMailItemAsync) per item in the syncLoadItemspath.Mitigation: confirmed by repository-wide grep that the field was write-only (no reader anywhere, including tests); the call's result was never consumed, so no behavior depended on it running.
Review Guide
Suggested order:
QuickFiler/Controllers/FilerQueue.cs+FilerQueueTests.cs— the highest-severity fix and its regression tests.TaskVisualization/FlagChangeTrainingQueue.cs— the same pattern applied to the sibling queue.QuickFiler/Controllers/EfcItemController.cs+EfcItemController.WebViewFaultBoundary.cs(new file) +QfcItemController.WebViewFaultBoundary.cs+EfcFormController.cs— the fault-boundary guarding cluster (findings 4 and 5).QuickFiler/Controllers/QfcHomeController.Metrics.cs— the null-guard/appointment-deletion fix.TaskVisualization/TaskViewer.csandQuickFiler/Viewers/QfcFormViewer.cs+EfcViewerTests.cs— the Alt-chord/ProcessCmdKeycluster (findings 7 and 8).QuickFiler/Controllers/QfcFormController.cs+QfcFormController.Actions.cs— the dead-field removal (finding 6, live sub-part).No mechanical moves or renames in this change.
Follow-ups
Three sub-findings from the issue are explicitly deferred, not fixed here:
StoreWrapperController.EvaluateLaunchReadinessconflates two distinct causes): already tracked as an open item indocs/features/active/2026-07-09-storewrapper-dialog-imprecise-for-genuine-failure-287/spec.md; resolving it needs a new readiness state and crosses theUtilitiesCS/TaskMasterassembly boundary.LoadFolderHandler/InitAsyncgap:FolderPredictorhas only an asyncInitAsync, no synchronous equivalent. The syncLoadFolderHandler's three production call sites run throughPopulateFolderComboBox, which checksInvokeRequired— forcing a synchronous block on the async init risks a UI-thread deadlock. A minimal fix here would trade a latent hang for a more certain one; needs a dedicated design decision, not a one-line patch.QfcHighConfidencePreFilter.FilterAsync: confirmed unreachable in production by grep (HighConfidencePreFilterLoaderis declared with a default delegate but never invoked anywhere). Removal cascades into three test files (QfcHighConfidencePreFilterTests.cs,QfcHomeControllerIssue218Tests.cs,QfcHomeControllerRunAsyncHighConfidenceTests.cs), exceeding this change's minimal-fix scope.GitHub Auto-close