Stabilize QuickFiler conversation and metrics flows while syncing development fixes into main#107
Merged
Conversation
sync-main-to-dev
- catch COM failures when reading Exchange sender and recipient properties - fall back to mail item, address entry, and property accessor values when Exchange data is unavailable - add regression tests covering sender and recipient fallback behavior for unreadable Exchange users
(fix(recipient)): harden Outlook recipient fallback resolution
- Update ConcurrentObservableBase to raise CollectionChanged with the wrapper instance for relayed view-model and base-collection events - Add regression tests covering add, remove, and concrete wrapper casting scenarios for ConcurrentObservableCollection subscribers - Include the new sender regression test file in the UtilitiesCS.Test project Refs: #87
…onversation load
- Add catch (OperationCanceledException) { throw; } before the broad
catch (System.Exception) so mid-load cancellation is not suppressed
- Extract ConversationResolver.LoadAsync into protected virtual
DoLoadConversationResolverCoreAsync to enable seam-based testing
without WinForms infrastructure
- Guard PopulateConversationAsync against null ConversationResolver
after a silently-swallowed load failure; add token check after load
- Add QfcItemControllerTests with four regression tests covering
cancellation propagation and null-guard paths
…cleanup and fix metrics predicate - Add `_isExecuting` volatile flag to drop re-entrant calls before any field access, preventing NullReferenceException when Cleanup() nulls _globals mid-await - Capture _globals into a local before MoveToFolderAsync as defense-in-depth against concurrent Cleanup() racing the post-await continuation - Fix inverted predicate in QuickFileMetrics_WRITE: `Count == 0` → `Count > 0` to write metrics for non-empty move results instead of empty ones - Add EfcHomeControllerTests with three regression tests covering the re-entrancy guard and both empty-list and null-list paths through QuickFileMetrics_WRITE
…d in another branch
…k-clean chore/mixed branch excluded work clean
…failures - replace recursive error-message property access with nameof() so invalid conversation state throws cleanly instead of overflowing the stack - treat a zero row count as a valid initialized value by switching the Count cache sentinel to (-1,-1) and using an explicit initialization predicate - add regression tests for the stack overflow and zero-count reload paths, and expose internals to QuickFiler.Test for deterministic coverage
…ite-loop Bug/conversation resolver infinite loop
- In GetMoveDiagnostics, wrap olAppointment.Body access with `if (olAppointment is not null)` to eliminate NullReferenceException when the "Email Time" calendar subfolder is absent - In QuickFileMetrics_WRITE, guard olEmailCalendar before .Items.Add() and propagate null olAppointment safely downstream - Add regression tests covering both null paths in QfcCollectionControllerTests and QfcHomeControllerTests - Capture Phase 0–2 baseline and QA gate evidence artifacts; add atomic-executor, atomic-planner, and feature-review skill definitions Refs: #97
…rd-97-clean fix(QuickFiler): guard null calendar and appointment in GetMoveDiagnostics #97
…mpty expansions - assign ConversationInfo before UpdateUI and pass pair.Expanded directly to avoid lazy getter re-entry in LoadConversationInfoAsync - return a logged single-item MailHelper fallback when Count.Expanded is zero and update ConversationResolver regression tests for the new behavior - capture issue, plan, baseline evidence, QA gates, and final policy/feature audits for the Issue #103 fix Refs: #103
…ordering-103 fix(QuickFiler): prevent ConversationResolver re-entry and add empty-conversation fallback
… conversation on focus - Add Keys.Right → ToggleExpansionAsync() in RegisterFocusAsyncActions, restoring the handler omitted during the async migration - Add corresponding Remove in UnregisterFocusAsyncActions to prevent stale handler accumulation across focus changes - Add regression tests verifying Right-arrow is registered on focus and cleaned up on unfocus (QfcItemController_KeyboardRegistrationTests, P1-T1 and P1-T2) - Promote feature to active folder with issue, plan, baseline, QA-gate, and regression evidence artifacts Refs: #96
…g-96-clean bug/quickfiler gui not expanding 96 clean
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.
Stabilize QuickFiler conversation and metrics flows while syncing development fixes into main
Summary
Email Timecalendar data no longer throws in the metrics flow, the Right arrow key expands conversations again during keyboard navigation, andConversationResolverno longer re-enters and throws when expanded conversation rows are empty.QuickFiler.TestforQfcHomeController,QfcCollectionController,QfcItemController,ConversationResolver, andEfcHomeController.UtilitiesCS/OutlookObjects/Recipient/RecipientStatic.csso unreadable Exchange sender/recipient properties fall back to safer mail/address-entry/property-accessor values.UtilitiesSwordfish/Collections/ConcurrentObservableBase.cssoCollectionChangedrelays the wrapper instance as the event sender, with matching regression coverage..codex/and.github/workflows/codex-web-setup-test.yml, plus the issue/plan/evidence/audit artifacts for the QuickFiler bug-fix tracks.Why
#97documents thatUtilitiesCS.Calendar.GetCalendar("Email Time", ...)can returnnull, which propagated intoQuickFileMetrics_WRITEandGetMoveDiagnosticsand caused aNullReferenceExceptionwhen the Outlook calendar subfolder did not exist.#96documents thatQfcItemController.RegisterFocusAsyncActions()no longer registered aKeys.Righthandler after the async keyboard-action migration, so the key press fell through to the focused WinForms control and activated the sendermailto:link instead of expanding the conversation.#103documents a read-before-write ordering bug inConversationResolver.LoadConversationInfoAsync():UpdateUI(ConversationInfo.Expanded)ran before the localpairwas assigned back toConversationInfo, which re-entered the synchronous loader and threwInvalidOperationExceptionwhenCount.Expanded == 0.#103also require a second constraint: when the expanded conversation is empty, the synchronous path should return a safe single-item fallback instead of throwing for a recoverable scenario.developmentbefore merging back tomain.What Changed
Core behavior / architecture
QuickFiler/Controllers/QfcCollectionController.csandQuickFiler/Controllers/QfcHomeController.csto guard null calendar/appointment data in the QuickFiler metrics path described by issue#97.QuickFiler/Controllers/QfcItemController.csto restoreKeys.Rightregistration/removal in the async focus-action path so keyboard navigation can expand conversations again.QuickFiler/Helper Classes/ConversationResolver.csso the async path assignsConversationInfo = pairbefore invoking the UI callback, passespair.Expandeddirectly, and returns a logged single-item fallback whenCount.Expanded <= 0.QuickFiler/Controllers/EfcHomeController.csto guardExecuteMovesAsyncagainst re-entrant cleanup and to adjust the metrics predicate.UtilitiesCS/OutlookObjects/Recipient/RecipientStatic.csto tolerate unreadable Exchange sender/recipient properties via layered fallbacks.UtilitiesSwordfish/Collections/ConcurrentObservableBase.csso collection-change subscribers receive the wrapper instance as the event sender.Tooling / automation / CI / DevEx
.codex/agents/atomic-executor.toml,.codex/agents/atomic-planner.toml,.codex/agents/feature-reviewer.toml, and.codex/prompts/feature-review-remediate.md..codex/codex-web-setup.plan.md,.codex/codex-web-setup.sh, and.github/workflows/codex-web-setup-test.yml.TaskMaster/AppGlobals/AppAutoFileObjects.cs,TaskMaster/Ribbon/RibbonExplorer.xml,TaskMaster/TaskMaster.csproj, andmissing-serializable-list.json.Tests
QuickFiler.Test/Controllers/EfcHomeControllerTests.cs,QuickFiler.Test/Controllers/QfcCollectionControllerTests.cs,QuickFiler.Test/Controllers/QfcItemControllerTests.cs, andQuickFiler.Test/Helper Classes/ConversationResolverTests.cs.QuickFiler.Test/Controllers/QfcHomeControllerTests.csand updatedQuickFiler.Test/QuickFiler.Test.csproj.UtilitiesCS.Test/OutlookObjects/Recipient/RecipientStaticTests.cs,UtilitiesCS.Test/OutlookObjects/Table/OlToDoTable_Tests.cs, andUtilitiesCS.Test/UtilitiesCS.Test.csproj.UtilitiesCS.Test/ReusableTypeClasses/Concurrent/Observable/Collection/ConcurrentObservableCollectionSenderTests.cs.Docs / templates / agents
docs/features/active/2026-03-25-getmovediagnostics-null-guard-97/docs/features/active/2026-03-25-quickfiler-gui-not-expanding-96/docs/features/active/2026-03-26-conversation-info-updateui-ordering-103/docs/features/potential/2026-03-25-quickfiler-gui-not-expanding.md.Architecture / How It Fits Together
QuickFiler keyboard flow
KeyboardHandlerdispatches registered async key actions.QfcItemController.RegisterFocusAsyncActions()now registersKeys.Right.ToggleExpansionAsync(Enums.ToggleState.On)instead of falling through to the focused control.QuickFiler metrics flow
QuickFileMetrics_WRITEandGetMoveDiagnostics.olEmailCalendar.ItemsorolAppointment.Body.Conversation loading flow
ConversationResolver.LoadConversationInfoAsync()builds the localpair, assignsConversationInfo = pair, then callsUpdateUI(pair.Expanded).ConversationResolver.LoadConversationInfo()now returns a single-item[MailHelper]fallback whenCount.Expanded <= 0, which avoids the recoverable empty-conversation exception path described in issue#103.Shared library behavior
RecipientStaticnow wraps Exchange lookups with fallback resolution paths for sender/recipient data.ConcurrentObservableBase<T>now preserves the wrapper-level sender contract for subscribers that cast theCollectionChangedsender back to the wrapper type.Verification
Completed
#96:dotnet tool run csharpier format .→EXIT_CODE: 0pwsh -NoProfile -ExecutionPolicy Bypass -File scripts/vscode/Invoke-VSBuild.ps1 -SolutionPath TaskMaster.sln -Configuration Debug -Platform "Any CPU" -EnableNETAnalyzers -EnforceCodeStyleInBuild→EXIT_CODE: 0pwsh -NoProfile -ExecutionPolicy Bypass -File scripts/vscode/Invoke-VSBuild.ps1 -SolutionPath TaskMaster.sln -Configuration Debug -Platform "Any CPU" -EnableNullable -TreatWarningsAsErrors→EXIT_CODE: 0& "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" "QuickFiler.Test\bin\Debug\QuickFiler.Test.dll" /InIsolation /EnableCodeCoverage→EXIT_CODE: 0QfcItemController→EXIT_CODE: 1#97:#102records nullable build success and an MSTest coverage run, with14failures called out there as pre-existing onorigin/development.#103:dotnet tool run csharpier format .→EXIT_CODE: 0EXIT_CODE: 0EXIT_CODE: 0vstest.console.exe "QuickFiler.Test\bin\Debug\QuickFiler.Test.dll" /InIsolation /TestCaseFilter:"FullyQualifiedName~ConversationResolver"→EXIT_CODE: 0vstest.console.exe "QuickFiler.Test\bin\Debug\QuickFiler.Test.dll" /InIsolation /EnableCodeCoverage→EXIT_CODE: 0origin/main..developmentrange beyond the feature-specific evidence above.Recommended
dotnet tool run csharpier format .pwsh -NoProfile -ExecutionPolicy Bypass -File scripts/vscode/Invoke-VSBuild.ps1 -SolutionPath TaskMaster.sln -Configuration Debug -Platform "Any CPU" -EnableNETAnalyzers -EnforceCodeStyleInBuildpwsh -NoProfile -ExecutionPolicy Bypass -File scripts/vscode/Invoke-VSBuild.ps1 -SolutionPath TaskMaster.sln -Configuration Debug -Platform "Any CPU" -EnableNullable -TreatWarningsAsErrors& "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" "QuickFiler.Test\bin\Debug\QuickFiler.Test.dll" /InIsolation /TestCaseFilter:"FullyQualifiedName~QfcItemController_KeyboardRegistration"& "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" "QuickFiler.Test\bin\Debug\QuickFiler.Test.dll" /InIsolation /TestCaseFilter:"FullyQualifiedName~ConversationResolver"& "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" "QuickFiler.Test\bin\Debug\QuickFiler.Test.dll" /InIsolation /EnableCodeCoverageBackward Compatibility / Migration Notes
ConversationResolver.LoadConversationInfo()now returns a single-item fallback whenCount.Expanded <= 0instead of throwingInvalidOperationExceptionfor that case.QfcItemControlleragain and expands the selected conversation instead of falling through to the focused WinForms control.Email Timecalendar data is now treated as a null-safe path instead of an exception path..codex/and additional evidence/audit documentation underdocs/features/active/....Risks and Mitigations
development..maincomparison includes multiple merged PRs and supporting docs/tooling, which increases review surface.ConversationResolverfallback changes behavior for callers that previously observed an exception on empty expanded conversations.#102records pre-existing MSTest failures onorigin/development, so full-range verification may still need a clean re-run before merge.Review Guide
docs/features/active/2026-03-25-quickfiler-gui-not-expanding-96/issue.md,docs/features/active/2026-03-25-getmovediagnostics-null-guard-97/issue.md, anddocs/features/active/2026-03-26-conversation-info-updateui-ordering-103/issue.mdfor the bug statements.QuickFiler/Controllers/QfcItemController.cswithQuickFiler.Test/Controllers/QfcItemControllerTests.csfor the Right-arrow registration fix.QuickFiler/Controllers/QfcCollectionController.csandQuickFiler/Controllers/QfcHomeController.cswith their tests for the metrics null-guard fix.QuickFiler/Helper Classes/ConversationResolver.cswithQuickFiler.Test/Helper Classes/ConversationResolverTests.csfor the async ordering and empty-conversation fallback changes.QuickFiler/Controllers/EfcHomeController.cswithQuickFiler.Test/Controllers/EfcHomeControllerTests.csfor the re-entrant cleanup and metrics-predicate adjustments.UtilitiesCS/OutlookObjects/Recipient/RecipientStatic.cswithUtilitiesCS.Test/OutlookObjects/Recipient/RecipientStaticTests.cs, thenUtilitiesSwordfish/Collections/ConcurrentObservableBase.cswithUtilitiesCS.Test/ReusableTypeClasses/Concurrent/Observable/Collection/ConcurrentObservableCollectionSenderTests.cs..codex/*,.github/workflows/codex-web-setup-test.yml, and thedocs/features/active/...evidence/audit artifacts; these are useful context but are noisier than the product-code deltas.Follow-ups
Email Timecalendar handlingJunk E-mailconversation loading with empty expanded rowsmainrequires a single consolidated verification record for the entire comparison range.GitHub Auto-close
Related issues / PRs