feat(365): nullable-enable Folder/Store cluster (Wave 1, utilitiescs-nullable-remediation) - #388
Merged
Conversation
…ation Records baseline file inventory (83 files: 18 already-enabled, 2 Designer, 63 targets), csharpier-clean state, analyzer build (0 errors), nullable pragma gate (0 CS86xx; pre-existing SVGControl CS0649 and UtilitiesCS CS0618/CS0168 warning debt documented as out-of-scope), and 4511 passing tests at 65.30% line / 61.32% branch coverage. Confirms AC2 baseline (no <Nullable> in csproj) and that all 6 Wave-0 upstream files already carry #nullable enable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Adds #nullable enable to 14 Folder interface/enum/DTO files and applies the interface contract shapes: IFolderHandleResolver.TryResolve(node?, out folder?), IFolderHierarchyProvider.ResolveLeafKeyAsync -> Task<FolderTreeNodeKey?>, and IFolderSearchHandler.FindFolder default-null optional params. Zero CS86xx; 4511/4511 tests pass; coverage unchanged (65.30% line / 61.32% branch). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…ers (P2) Adds #nullable enable to 10 files: FolderTreeNodeKey (IEquatable nullable overrides), FolderTreeRequest/FolderTreeSelectionOverlay (nullable enumerables/ node), and the five IEqualityComparer implementations (nullable Equals params). FolderWrapperNodeComparer needed three behavior-identical null-safety guard refinements. Zero CS86xx; 4511/4511 tests pass; coverage 65.32% line / 61.35% branch (no regression). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Adds #nullable enable to 7 snapshot files with nullable parentKey/ParentKey, TryGetNode(out node?), nullable FindByPath/GetArchiveRoot/CreateNode returns, nullable _highlighted, and FolderHierarchyBuilder nullable locals. Also widens IOutlookFolderHierarchyReader.ReadFoldersAsync clocks to nullable to match the null-tolerant FolderTreeSnapshotBuilder. Zero CS86xx; 4511/4511 tests pass; coverage 65.29% line / 61.34% branch (no regression). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Pragma-enables all 8 F3 files (P4-T1) and annotates the 4 group-a files: FolderConverter (string? ToFsFolderpath), FolderNavigator (Folder? return), FolderMinimalWrapper and FolderWrapper .cs (nullable COM fields/props, string? Name/RelativePath, nullable-by-design Globals, nullable PropertyChanged event). Nullable-string lazies use new Lazy<string?> since #363 ToLazy has where T:class. Zero CS86xx for the 4 group-a files; 4511/4511 tests pass; coverage unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Initializes _roots, makes PropertyChanged event nullable, forgives COM OlFolder.Folders derefs and selections.Contains(RelativePath!). Zero CS86xx; 4511/4511 tests pass; coverage 65.30% line / 61.35% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Adds nullable predictions array and cast-with-as locals (string[]? folders, AddArray(string[]?)). FolderScoring struct fields verified set at all sites. Zero CS86xx; 4511/4511 tests pass; coverage 65.30% line / 61.34% branch. Not split. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
… T11-T14) Remediates FolderPredictor.cs (974 lines, not split) + its IFolderSearchHandler partial together (AC7): nullable GetFolder/CreateFolder/ InputFoldername returns, nullable optional params matching the interface shape, Regex?/List<string>? fields, and null! partial-init for the navigation-only ctor so Suggestions/_globals stay non-null for the interface contract. Zero CS86xx across all of UtilitiesCS (17 verify-only Folder files confirmed clean, P4-T14); 4511/4511 tests pass; coverage 65.30% line / 61.35% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Annotates OutlookFolderHierarchyProvider (Task<FolderTreeNodeKey?> ResolveLeafKey) and OutlookFolderTreeService (nullable state fields/event, nullable request/snapshot pipeline params). Refines the request-nullable contract chain across BuildSnapshotAsync/ReadFoldersAsync and FolderTreeSnapshotChangedEventArgs. Zero CS86xx; 4511/4511 tests pass; coverage 65.31% line / 61.35% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Pragma-enables IDisabledStoresViewer, IStoreWrapperViewer, DisabledStoreRow; keeps WinForms control props and BindRows non-null by contract, sets event-handler senders to object?, and initializes DisabledStoreRow string props to string.Empty. Zero CS86xx; 4511/4511 tests pass; coverage 65.30% line / 61.32% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Annotates StoreIdentity (nullable Resolve params), StoreFilterAttribution (documented-nullable Decide/FormatLine params), StoreLockupAttribution, StoreWrapperInitProbe. StoreRehookResult verify-only confirmed clean (P7-T5). Zero CS86xx; 4511/4511 tests pass; coverage 65.29% line / 61.33% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Makes Init/Restore-populated properties nullable (DisplayName, StoreId, InnerStore, Inbox, RootFolder, UserEmailAddress, GlobalAddressBook), GetSmtpAddressFromStore returns string?, InnerStore! at Init COM derefs. Zero CS86xx; 4511/4511 tests pass; coverage 65.30% line / 61.33% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Remediates StoresWrapper.cs + StoresWrapper.Filtering.cs together (AC7): nullable Globals/Stores, nullable primitive-read locals, consistent static/instance StoreIsIncluded nullable params. StoreDisableService: nullable rehook ctor param, StoresWrapper? GetModelOrNull. Zero CS86xx; 4511/4511 tests pass; coverage 65.3%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Annotates OutlookFolderHandleResolver (TryResolve node?/folder?), OutlookFolderHierarchyReader (IOutlookFolderAdapter? GetRootFolder, nullable request/clock params threaded through), OutlookFolderNotificationSink (nullable events/_handler, string? storeId in FolderTreeNotification, 499 lines not split), MAPIMethods + WpfDispatcherYield (pragma only). Zero CS86xx; 4511/4511 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
StoreWrapperController: nullable viewer-bound optional fields, = null! for lifecycle-set Viewer/Model/Current/FsConverter, IList<string?> DisplayNames, nullable SelectFolder/SelectFsFolder returns; confirmed the CS8625 disable/restore pair still needed. DisabledStoresController: nullable-by-design Viewer. Cross-batch: StoreWrapper configurable props nullable. Zero CS86xx; 4511/4511 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
StoreWrapperViewer (nullable-by-design Controller, object? senders) and DisabledStoresViewer (object? sender). Designer siblings left non-opted-in per convention. Cross-batch: two controller event-handler senders widened to object?. Zero CS86xx; 4511/4511 tests pass; coverage 65.30% line / 61.34% branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…CS8766) The final comprehensive nullable gate (full CS8xxx range) caught a CS8766 that the per-batch CS86xx grep missed: OutlookStoreAdapter.GetRootFolder returns IOutlookFolderAdapter? but the nested IOutlookStoreAdapter interface declared it non-null. Widened the interface to match the impl. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
csharpier clean; analyzers 0 errors/0 warnings; scoped nullable gate zero CS86xx/CS87xx across all 63 remediated + 18 verify-only files; 4511/4511 tests pass; overall coverage 65.30%->65.31% (no regression), changed-line coverage 96.97%. Verified AC2 (no <Nullable>), AC5 (signature compat), AC6 (no post-condition attrs/records), AC7 (partial groups together), scope guards (no splits, filename intact), upstream contracts stable. Checks off AC1-AC7 in spec.md and user-story.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Policy audit, code review, and feature audit for the Folder/Store nullable-enable remediation. All AC1-AC7 evaluated PASS; zero blocking findings. Repo-wide C# coverage below the 85/75 uniform floor is dispositioned non-blocking (pre-existing legacy VSTO/COM debt, ratified CLAUDE.md exemption, first-party UtilitiesCS package above floor, no regression). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
drmoisan
deleted the
feature/utilitiescs-nullable-outlook-folder-store-365
branch
July 21, 2026 01:13
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.
Summary
utilitiescs-nullable-remediation: bringsUtilitiesCS/OutlookObjects/Folder/(includingMsgToMime/) andUtilitiesCS/OutlookObjects/Store/to zero CS86xx/CS87xx nullable diagnostics under a per-file#nullable enableopt-in pragma, withTreatWarningsAsErrors. No project-level<Nullable>element was added toUtilitiesCS.csproj; enforcement remains per-file only.#nullable enablepragma and nullable annotations/guards/justified!; 18 already-opted-in files were re-verified clean with no edits; the 2 Designer-generated files (DisabledStoresViewer.Designer.cs,StoreWrapperViewer.Designer.cs) remain non-opted-in per repository convention.FolderPredictor.cs+FolderPredictor.IFolderSearchHandler.cs;StoresWrapper.cs+StoresWrapper.Filtering.cs) were remediated together with a consistent nullable shape for shared members.Closes #365.
Test plan
UtilitiesCS.Testsuite: 4511/4511 passing, no regressions.msbuild UtilitiesCS/UtilitiesCS.csproj /t:Rebuild ... /p:TreatWarningsAsErrors=true /p:BuildProjectReferences=false): zero CS86xx/CS87xx across all 63 remediated + 18 verify-only files.msbuild TaskMaster.sln /t:Rebuild ... /p:TreatWarningsAsErrors=true, no/p:Nullable=enable): only 2 pre-existingCS0649errors in the vendoredSVGControlproject remain (sibling feature Feature: utilitiescs-nullable-svgcontrol #368's scope; confirmed pre-existing at the merge-base and outside this feature's Folder/Store diff).UtilitiesCSpackage 88.75% line / 82.55% branch.spec.mdanduser-story.md.Notes for reviewers
epic/utilitiescs-nullable-remediation-integration, notmain. Per this epic's CI configuration,ci.ymltriggers only on PRs tomain/development, so no required checks run against this PR by design.docs/features/active/utilitiescs-nullable-outlook-folder-store/evidence/. Policy/code/feature audit artifacts are committed at the feature-folder root (policy-audit.2026-07-19T12-52.md,code-review.2026-07-19T12-52.md,feature-audit.2026-07-19T12-52.md).FolderPredictor.cs(983 lines),FolderScorer.cs(664 lines), and"FolderWrapper .cs"(532 lines, literal trailing space in filename, not renamed) remain single files per policy; a pre-existing analyzer package/version mismatch in the committedUtilitiesCS.csproj/packages.configwas worked around locally (gitignoredpackages/folder only, no tracked file changed) and is flagged for the maintainer.