Skip to content

fix(371): remediate nullable debt in Outlook item-adapter cluster (MailItem/Item/Conversation/Attachment/Table) - #387

Merged
drmoisan merged 15 commits into
epic/utilitiescs-nullable-remediation-integrationfrom
bug/utilitiescs-nullable-outlook-mailitem-item-371
Jul 19, 2026
Merged

fix(371): remediate nullable debt in Outlook item-adapter cluster (MailItem/Item/Conversation/Attachment/Table)#387
drmoisan merged 15 commits into
epic/utilitiescs-nullable-remediation-integrationfrom
bug/utilitiescs-nullable-outlook-mailitem-item-371

Conversation

@drmoisan

Copy link
Copy Markdown
Owner

Summary

Verification

  • CS86xx across all 30 in-scope files: 0. CS86xx across the entire UtilitiesCS assembly (including out-of-scope nullable-enabled consumers): 0 — no regression introduced.
  • No <Nullable> element added to UtilitiesCS.csproj or TaskMaster.sln. /p:Nullable=enable was never passed — the nullable/type-check gate for this child is the documented pragma-only deviation: msbuild TaskMaster.sln /t:Rebuild /p:Configuration=Debug /p:Platform="Any CPU" /p:TreatWarningsAsErrors=true.
  • The solution-wide TWAE rebuild halts on a pre-existing, out-of-scope vendored SVGControl CS0649 error (confirmed present at the branch point, unrelated to this change); CS86xx is authoritatively measured via an isolated UtilitiesCS.csproj rebuild, the same technique used by the already-merged sibling child Feature: utilitiescs-nullable-helperclasses #364. Independently verified sound by feature-review.
  • MSTest: 4511/4511 passed. Coverage: in-scope OutlookObjects line coverage flat at 87.07%; overall flat; no changed-line regression.
  • CSharpier and analyzer/codestyle gates: clean, 0 errors, 0 new in-scope warnings.
  • OutlookItem.cs (504 lines) and OlToDoTable.EnsureItemValues's dynamic item remain unmodified pre-existing conditions, flagged per plan (not fixed — out of scope).
  • CidImageResolver.cs is the sole non-COM-exempt file in scope; coverage held at 94.7%, unchanged.
  • A self-correction during Batch I (commit 2f6f3fec) reverted an initially-introduced nullable change to OlTableExtensions.ETL/EtlAsync/GetTableInViewAsync/EtlPrepAsync return-tuple types after Phase 10's full-solution gate showed it broke public-signature behavior-compatibility for out-of-scope consumers (Extensions/DfDeedle.cs, DfDeedle.FrameUtilities.cs); final state is behavior-compatible.

Acceptance Criteria

  • Source: spec.md (Definition of Done + AC1-AC6 + seeded test conditions) — 17/17 checked.
  • Source: user-story.md (Acceptance Criteria) — 6/6 checked.

Feature Review

  • blocking_count = 0 (policy-audit, code-review, feature-audit all PASS). Artifacts: docs/features/active/utilitiescs-nullable-outlook-mailitem-item/{policy-audit,code-review,feature-audit}.2026-07-19T12-50.md.

Test plan

  • All 30 in-scope files carry #nullable enable and are CS86xx-clean under the pragma-only gate
  • No <Nullable> element added anywhere in the solution
  • Full existing UtilitiesCS.Test suite green (4511/4511)
  • No coverage regression on changed lines
  • Feature review blocking_count = 0

Closes #371

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

drmoisan and others added 15 commits July 19, 2026 11:00
Capture policy-read, csharpier, analyzer, pragma-only nullable, and
coverage baselines for the utilitiescs-nullable-outlook-mailitem-item
child (#371). In-scope CS86xx baseline = 0 (all 30 files oblivious);
in-scope OutlookObjects production line coverage = 87.07%. Solution-wide
TWAE Rebuild halts on pre-existing out-of-scope SVGControl CS0649;
authoritative in-scope CS86xx verified via isolated UtilitiesCS build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…odule2, ItemComparer)

Add per-file #nullable enable pragma to the two commented-out dead files.
No live code; zero CS86xx. CaptureEmailAddressesModule2Tests green (2/2).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Add whole-file #nullable enable to the host-neutral cid: image resolver.
One CS8602 fixed with a justified null-forgiving operator (guarded by the
preceding IsNullOrEmpty check); public signatures unchanged. 0 CS86xx.
CidImageResolver tests green (3/3); changed line covered, no regression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Add per-file #nullable enable to MailResolution, MailItemExtensions,
OlItemPseudoInterface, OlItemSummary, OlToDoTable. Annotation-only nullable
returns/locals reflecting actual null behavior (MailItem?/byte[]?/Task<object?>/
Outlook.Table? and nullable locals). dynamic item line left byte-unchanged
and flagged. 0 CS86xx; 51/51 Batch C tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…able

Add #nullable enable to OutlookItem, OutlookItemExtensions,
OutlookItemFlaggable, OutlookItemTry, OutlookItemTryGet,
OutlookItemFlaggableTry. Deliberate unconstrained-generic T? contract for
TryGet<T>/TryCall<T>/GetPropertyValueIfExists<T> and out T?, propagated
consistently to the try/catch-swallowing decorators' reference-type
members. Nullable fields/getters; justified ! at reflection derefs. Seams
preserved. OutlookItem.cs left intact at 504 lines (flagged). 0 CS86xx;
175/175 Batch D tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Add #nullable enable to AttachmentSerializable and AttachmentHelper.
Nullable POCO props/lazy fields/out params reflecting actual null behavior;
AttachmentData setter rebuilt as explicit Lazy<byte[]?> (ToLazy has a class
constraint). FilePathSave/FolderPathSave keep the #364 FilePathHelper
non-nullable default contract as-is. Verified #364 FilePathHelper contract
landed (P5-T1). 0 CS86xx; 40/40 Batch E tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…e enable

Add #nullable enable to ItemInfo (nullable POCO IItemInfo props mirroring
the Batch G MailItemHelper decisions), EmailDetails (nullable dictRemap
params), and EmailDetailsWrapper (nullable default-null params; seam
preserved). 0 CS86xx; 25/25 Batch F tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Opt in all 5 MailItemHelper.* files as one unit. Lazy backing fields
nullable (resolving 125 CS8618; net481 has no MemberNotNull); the four
lazy props without a ?? fallback (Sender/FolderInfo/AttachmentsInfo/Globals)
annotated nullable per P7-T6 with value?.ToLazy() setters. Html.cs interior
pragma region normalized to whole-file. ResolveMail -> MailItem? consuming
Initializer.GetOrLoad. Cross-batch reconcile: EmailDetails helper derefs
(!) and CidImageResolver attachments params nullable. #363/#364 contracts
verified (P7-T1/T2). 0 CS86xx as one unit; 125/125 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Opt in both ConversationHelper.* files as one unit. Nullable DataFrame?/
Table?/Conversation? returns and null-default params reflecting actual null
behavior; shared LogConversationTiming details -> string? consumed
consistently cross-file; GetConversationTable param nullable to match the
RunWithTimeout delegate target. #364 PrettyText verified (P8-T2); #363
ForEach resolves at build time (P8-T1 flag, not a block). 0 CS86xx as one
unit; 75/75 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…able

Opt in all 4 OlTableExtensions.* files as one unit. ETL-family tuples ->
(object[,]? , Dictionary?) reflecting the genuine (null,null) error path;
nullable objectConverters/progress/objFields/objIndices across the ETL call
graph; TableAccess GetTable/TryGetTableAsync nullable returns. #363
ArrayExtensions contract verified (P9-T1). Cross-batch reconcile: Formatting.cs
ETL consumers deconstruct nullable with justified !; oblivious DfDeedle
unaffected. 0 CS86xx as one unit; 162/162 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…or behavior compatibility

The full-solution nullable gate surfaced that making the ETL-family public
tuples and GetTableInViewAsync nullable introduced 7 CS86xx in the
nullable-enabled out-of-scope consumers DfDeedle.cs/DfDeedle.FrameUtilities.cs,
violating public-signature behavior-compatibility. Revert those public
signatures to non-null; express the genuine null paths with justified ! at
the internal return sites. Total UtilitiesCS CS86xx = 0; 162/162 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Final toolchain pass on the complete remediation: CSharpier clean, analyzer
0 errors/0 in-scope warnings, pragma-only nullable gate 0 CS86xx across all
30 files (and 0 total across UtilitiesCS), 4511/4511 tests green. Coverage
flat vs baseline (in-scope 87.07%; overall 65.30%); no changed-line
regression. No <Nullable> element. AC1-AC6 checked off in spec.md and
user-story.md; DoD and seeded test conditions satisfied.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…cts nullable remediation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eature-audit)

blocking_count = 0. All 30 in-scope OutlookObjects files verified CS86xx-clean
under the pragma-only nullable gate; partial-class groups verified as
consistent units; SVGControl pre-existing halt and isolated-build
substitution methodology independently verified sound; Batch I self-correction
(commit 2f6f3fe) verified behavior-compatible; coverage flat, no regression.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ailitem-item-371

Sync with sibling children (#370/#374/#375) that merged into
epic/utilitiescs-nullable-remediation-integration in parallel. No overlap
with this child's in-scope files (OutlookObjects/{MailItem,Item,Conversation,
Attachment,Table}); only conflict was an additive atomic-executor
agent-memory index entry, resolved by keeping both entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@drmoisan
drmoisan merged commit f642513 into epic/utilitiescs-nullable-remediation-integration Jul 19, 2026
@drmoisan
drmoisan deleted the bug/utilitiescs-nullable-outlook-mailitem-item-371 branch July 21, 2026 01:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant