Skip to content

Enable genuine CI nullable-gate enforcement via per-file #nullable opt-in remediation across UtilitiesCS (epic: utilitiescs-nullable-remediation)#390

Merged
drmoisan merged 172 commits into
mainfrom
epic/utilitiescs-nullable-remediation-integration
Jul 20, 2026
Merged

Enable genuine CI nullable-gate enforcement via per-file #nullable opt-in remediation across UtilitiesCS (epic: utilitiescs-nullable-remediation)#390
drmoisan merged 172 commits into
mainfrom
epic/utilitiescs-nullable-remediation-integration

Conversation

@drmoisan

Copy link
Copy Markdown
Owner

Enable genuine CI nullable-gate enforcement via per-file #nullable opt-in remediation across UtilitiesCS (epic: utilitiescs-nullable-remediation)

Summary

  • Integrates the completed utilitiescs-nullable-remediation epic (13 child features across 3 dependency waves) into main, merging the epic integration branch epic/utilitiescs-nullable-remediation-integration.
  • Remediates the pre-existing nullable-reference-type debt (~2100+ CS86xx diagnostics) across the UtilitiesCS assembly under a per-file #nullable enable opt-in architecture, so no non-opted-in file is forced to compile clean before it is ready.
  • Repairs and genuinely enforces the CI nullable gate: the gate now runs under /t:Rebuild /p:TreatWarningsAsErrors=true with per-file #nullable pragmas and drops the global /p:Nullable=enable that previously masked/mis-scoped enforcement. This supersedes the open PR ci(nullable-gate): use /t:Rebuild so the nullable gate is actually enforced #361 (the original /t:Rebuild gate-repair commit is the base of this integration branch).
  • Annotation-only and null-safety changes: no runtime behavior changes; 5702/5702 tests pass; coverage 83.89% line / 76.37% branch with no changed-line regression.
  • The final capstone (Feature: utilitiescs-nullable-ci-capstone #376) also remediated the cross-child fan-in debt that only surfaces on the integrated tree (annotation propagation across sibling-owned files), plus a pre-existing SVGControl CS0649, so the newly-genuine gate builds green on the integrated tree.

Why

The CI nullable gate had been effectively a no-op. Turning it into a genuine gate against the whole assembly at once would have blocked all future PRs on ~2100+ pre-existing diagnostics. This epic makes genuine enforcement viable by:

  • Migrating UtilitiesCS to nullable-clean file by file via per-file #nullable enable pragmas, so enforcement scope grows monotonically as files opt in.
  • Rewriting the gate to enforce only the opted-in surface under /t:Rebuild (the /t:Rebuild fix from PR ci(nullable-gate): use /t:Rebuild so the nullable gate is actually enforced #361 was required so the gate does not silently no-op), removing the global /p:Nullable=enable.

Epic intent (enabler): the repaired gate can be enforced without permanently blocking future PRs, because remediation lands under a per-file opt-in that each child feature could deliver independently.

What Changed

Core remediation (per-file #nullable enable, annotation-only) — 393 production .cs files across the epic's 13 children:

Tooling / CI (.github/workflows/ci.yml):

  • Nullable gate rebuilt to per-file pragma enforcement under /t:Rebuild /p:TreatWarningsAsErrors=true; global /p:Nullable=enable removed.
  • Verified genuine by an expect-fail probe (an opted-in synthetic defect fails the gate; a non-opted-in defect does not; both reverted) and by a green workflow_dispatch run (29719565487) against the branch head on the real windows-latest runner, satisfying modified-workflow-needs-green-run.

Capstone integrated-tree remediation (#376): 296 CS86xx + 28 CS0618 + 2 CS0168 across 62 UtilitiesCS files, plus escalation layers in ToDoModel / TaskVisualization / QuickFiler / TaskMaster / test projects, all resolved behavior-neutrally to reach a solution-wide gate EXIT 0. The pre-existing SVGControl CS0649 (SvgImageSelector.cs) was addressed so the full-solution TWAE build is clean.

Docs: per-feature evidence, audits, specs, and plans for all 13 children under docs/features/.

Architecture / How It Fits Together

  • Enforcement is opt-in at file granularity: a file carries #nullable enable when it has been remediated; the CI gate compiles the assembly under /t:Rebuild with warnings-as-errors and fails only on diagnostics from opted-in code. Un-opted files remain oblivious and non-blocking.
  • The dictionary-base where TKey : notnull constraint is a forward-looking public-contract change (on net481 the BCL reference assemblies are un-annotated, so it emits zero CS8714 today; runtime is unchanged because ConcurrentDictionary already rejects null keys).
  • The epic was delivered wave-by-wave into epic/utilitiescs-nullable-remediation-integration; this PR merges that integration branch into main. origin/main (PR chore(memory): salvage uncommitted agent-memory and #317 audit artifacts from stale worktrees #362) was synced into the integration branch beforehand, so this PR merges cleanly.

Verification

Completed (recorded in epic evidence and child feature-audits):

  • 5702/5702 tests pass at the integrated tip.
  • Coverage 83.89% line / 76.37% branch; no changed-line regression.
  • Solution-wide nullable gate EXIT 0 under /t:Rebuild /p:TreatWarningsAsErrors=true.
  • Gate genuine-enforcement probe passed (opted-in defect fails; non-opted-in does not; both reverted).
  • workflow_dispatch CI run 29719565487 concluded success on the real windows-latest runner.
  • Each child feature-review reached blocking_count == 0.

Recommended (this PR runs it automatically):

  • Full ci.yml on the PR to main, including the now-genuine nullable gate, on the real runner.

Backward Compatibility / Migration Notes

  • No runtime behavior changes; all edits are null annotations, null-safety guards, and the forward-looking generic-key constraint.
  • Public generic dictionary bases now require TKey : notnull. This is source-compatible for all in-repo callers (already non-null keys) and emits no diagnostics on net481.

Risks and Mitigations

  • Risk: the genuine gate fails on main CI on a diagnostic not seen on the integration branch. Mitigation: the integration branch was synced with origin/main and the solution-wide gate was verified EXIT 0; the workflow_dispatch run already exercised the gate on the runner. If CI surfaces a residual, it is remediated before merge.
  • Risk: large diff. Mitigation: annotation-only; the bulk of insertions are committed per-feature evidence/coverage artifacts, not source.

Review Guide

  • Start with .github/workflows/ci.yml (the enforcement change).
  • Then the dictionary-base constraint in UtilitiesCS/.../ReusableTypes and its four NewtonsoftHelpers consumers (Feature: utilitiescs-nullable-reusabletypes #366).
  • The remaining .cs changes are mechanical per-file #nullable enable + null annotations; the large docs/features/** additions are evidence artifacts (mechanical, high-volume).

Follow-ups (maintainer flags recorded in the capstone spec, not resolved here)

  • .claude/rules/csharp.md wording conflict flagged for the maintainer (no rules edits made).
  • Optional project-level <Nullable> flip deliberately left out of scope.
  • Analyzer-package version drift across 16 .csproj (pre-existing on main).
  • Residual CS2002 in UtilitiesCS.Test.csproj.
  • PeopleScoDictionaryNew.cs #nullable disable island retained (removing it reintroduces 12 CS8644).
  • Consolidated dead-duplicate / To Depricate/* / >500-line-file inventory recorded as a maintainer flag.

Note: PR #361 (ci(nullable-gate): use /t:Rebuild ...) is superseded by this epic PR (its gate-repair commit is the base of this integration branch and its ci.yml was further revised by the capstone). It is closed separately with a reference to this PR rather than merged.

GitHub Auto-close

drmoisan and others added 30 commits July 18, 2026 19:20
…ntly no-op'ing

The "Build with nullable warnings treated as errors" step ran /t:Build
immediately after "Build with analyzers" had already compiled everything
under the projects' own Nullable settings. MSBuild's incremental
up-to-date check does not invalidate on a changed -p:Nullable command-line
property alone, so this step was silently skipping recompilation and
never actually enforcing the gate -- it reliably passed in a few seconds
regardless of the code's real nullable-safety state.

Switching to /t:Rebuild forces a genuine full recompile under
/p:Nullable=enable every run. This is expected to surface a large body of
pre-existing nullable debt across UtilitiesCS (confirmed locally: ~2131
errors on main itself, unrelated to any pending PR's changes) that this
gate was never actually catching. Remediating that debt is tracked
separately; this change only makes the gate report the true state.
…route

Scaffold the utilitiescs-nullable-remediation epic on the integration branch:
- docs/features/epics/utilitiescs-nullable-remediation/epic.md: 12-feature manifest
  (6 wave-0, 5 wave-1, 1 wave-2 capstone), per-file #nullable opt-in architecture,
  SVGControl included, cycle-free DAG. Based on PR #361 head (20d163a), not origin/main,
  so children validate against the repaired /t:Rebuild nullable gate.
- config/orchestration-routing.json: add the "preparation" route (task-researcher,
  prd-feature, atomic-planner, atomic-executor; requires_pr_gate/requires_ci_gate false)
  so preparation-mode child orchestrator runs satisfy their completion gate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Preparation-mode outputs for the utilitiescs-nullable-remediation epic
Wave-0 child utilitiescs-nullable-extensions (issue #363): issue.md with
acceptance criteria, spec.md, user-story.md, research findings, and the
preflight-cleared atomic plan.

Scope: remediate pre-existing CS86xx nullable-reference-type debt across
UtilitiesCS/Extensions/ (25 .cs files; 2 already opted in, 23 to remediate)
under a per-file #nullable enable opt-in architecture. Annotation and
null-safety only; no behavior changes. Plan phases the 23 files into five
leaf-first batches (C precedes E) plus baseline and final-QC phases.

Plan validated by the MCP plan validator; atomic-executor preflight returned
PREFLIGHT: ALL CLEAR. Atomic execution, PR authoring, and CI monitoring are
out of scope for this preparation run and are executed later by
epic-orchestrator.

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

Preparation-mode outputs for epic child issue #364 of
utilitiescs-nullable-remediation: per-file #nullable enable remediation of
CS86xx debt across UtilitiesCS/HelperClasses/ (43 .cs files).

- issue.md: full-feature requirements and acceptance criteria
- spec.md: nullability-contract spec, per-file pragma architecture, 9 DoD
  acceptance criteria, and the five research mechanics flags
- user-story.md: maintainer/downstream-consumer story with AC
- research/research-findings.2026-07-18T21-45.md: 8-batch phasing, risk files,
  Designer/Form handling rule, and pragma-only build-command mechanics
- plan.2026-07-18T21-21.md: 10-phase atomic plan (81 tasks), preflight ALL
  CLEAR; validated by the plan validator

Atomic execution, PR authoring, and CI monitoring are out of scope for this
preparation run and are executed later by epic-orchestrator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fan-in of the two validated canary preparation children (extensions #363,
helperclasses #364) into the integration branch. Replaces provisional
placeholder issue_num 9001/9002 with the real promoted issue numbers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…c, user-story, plan, research)

Wave-1 child of the utilitiescs-nullable-remediation epic. Per-file
#nullable enable remediation of the EmailIntelligence parsing/sorting
cluster (EmailParsingSorting + SubjectMap + Ctf, 24 target files).
Annotation and null-safety only; no behavior changes. Consumes upstream
utilitiescs-nullable-extensions (#363) annotation contracts.

Preparation only: 9-phase/54-task atomic plan is plan-validated and
executor-preflight-cleared (PREFLIGHT: ALL CLEAR). Atomic execution is
performed later by epic-orchestrator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fan-in of the utilitiescs-nullable-email-parsing preparation child
(PREFLIGHT: ALL CLEAR). Resolves the manifest placeholder issue_num
9009 to the real GitHub issue number 370.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d, preparation only)

Wave-0 child of the utilitiescs-nullable-remediation epic. Prepares the
SVGControl/ net481 WinForms control project for per-file #nullable enable
remediation (issue #368): promotion documents, research findings, spec,
user-story, and a preflight-cleared atomic plan. No atomic execution;
execution and PR authoring are handled later by epic-orchestrator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ec, plan, research)

Epic child of utilitiescs-nullable-remediation (Wave 0, C3). Per-file
#nullable enable opt-in remediation of UtilitiesCS/NewtonsoftHelpers/ (19
files); annotation-only, no behavior change. Preparation only: promotion,
research, spec/user-story, atomic plan, executor preflight ALL CLEAR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Preparation-only for epic child utilitiescs-nullable-reusabletypes (Issue
#366, Wave 0, C3) under the utilitiescs-nullable-remediation epic. Adds the
promoted issue.md, spec.md, user-story.md, research findings, and the
preflight-cleared atomic plan for per-file #nullable enable remediation of
UtilitiesCS/ReusableTypeClasses/ (incl. TimedActions, NewSmartSerializable).
Annotation-only; no source changes in this preparation run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on (preparation fan-in)

Fan in prepared utilitiescs-nullable-svgcontrol child (issue #368, PREFLIGHT: ALL CLEAR).
Preparation only: issue, research, spec, user-story, approved atomic plan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve placeholder issue number for utilitiescs-nullable-svgcontrol after
child promotion (issue #368).

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

Wave-1 epic child of utilitiescs-nullable-remediation. Preparation only
(promotion, research, spec/user-story, atomic plan, preflight ALL CLEAR).
Per-file #nullable enable remediation of UtilitiesCS/OutlookObjects/
{MailItem,Item,Conversation,Attachment,Table} (~30 files), consuming the
Wave-0 #363 (Extensions) and #364 (HelperClasses) annotation contracts.
No atomic execution in this run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Preparation-only (no atomic execution) for the utilitiescs-nullable-remediation
epic, Wave 0. Adds the promoted issue.md (#369), spec.md, user-story.md,
research findings, and the preflight-cleared atomic plan for per-file
#nullable enable remediation of UtilitiesCS/Threading/ (25 hand-written .cs
files). Annotation and null-safety only; no behavior or concurrency-semantics
change. Verification uses the pragma-only build (no /p:Nullable=enable).

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

Preparation-mode outputs for the Wave-1 EmailIntelligence classifier cluster
child of the utilitiescs-nullable-remediation epic (issue #372): promoted
issue.md, spec.md, user-story.md, research findings, and a preflight-cleared
atomic plan. Scope is annotation-only nullable remediation (per-file
`#nullable enable` opt-in) of UtilitiesCS/EmailIntelligence Bayesian +
ClassifierGroups + Flags; no scoring/model/behavior change. Consumes the
Wave-0 Extensions (#363) annotation contracts. No atomic execution performed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ld (Wave 1)

Preparation-only for epic child utilitiescs-nullable-outlook-folder-store
(issue #365, epic utilitiescs-nullable-remediation, Wave 1). Adds the active
feature folder: issue.md (AC1-AC7, full-feature), spec.md, user-story.md,
research findings, and the atomic plan (13 phases, 63 opt-in targets).

Scope is null-annotation and null-safety remediation of
UtilitiesCS/OutlookObjects/Folder + UtilitiesCS/OutlookObjects/Store under the
per-file #nullable enable opt-in architecture; no behavior changes. depends_on
extensions (#363) and helperclasses (#364). Atomic-executor preflight: ALL CLEAR.

Atomic execution, PR authoring, and CI monitoring are out of scope for this
preparation run and are executed later by epic-orchestrator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…es (issue #366) into integration

Preparation-mode child orchestrator run for utilitiescs-nullable-reusabletypes reached PREFLIGHT: ALL CLEAR.
Disjoint feature-folder-only merge; child branched from f377c85.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…elpers (issue #367) into integration

Preparation-mode child orchestrator run for utilitiescs-nullable-newtonsofthelpers reached PREFLIGHT: ALL CLEAR.
Disjoint feature-folder-only merge; child branched from f377c85.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…litem-item (issue #371) into integration

Preparation-mode child orchestrator run for utilitiescs-nullable-outlook-mailitem-item reached PREFLIGHT: ALL CLEAR.
Disjoint feature-folder-only merge; child branched from f377c85.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…issue #369) into integration

Preparation-mode child orchestrator run for utilitiescs-nullable-threading reached PREFLIGHT: ALL CLEAR.
Disjoint feature-folder-only merge; child branched from f377c85.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…thelpers #367, threading #369, outlook-mailitem-item #371

Four preparation-mode children fanned in and their manifest placeholders
(9003, 9004, 9005, 9008) resolved to real GitHub issue numbers.
Remaining placeholders: 9007, 9010, 9011, 9012 (outstanding children).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ifier (issue #372)

Preparation-mode child completed PREFLIGHT: ALL CLEAR. Feature-folder-only,
disjoint from other prepared children; child branch based off f377c85.
Plan: docs/features/active/utilitiescs-nullable-email-classifier/plan.2026-07-18T22-06.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…der-store (issue #365)

Preparation-mode child completed PREFLIGHT: ALL CLEAR. Feature-folder-only,
disjoint from other prepared children; child branch based off f377c85.
Plan: docs/features/active/utilitiescs-nullable-outlook-folder-store/plan.2026-07-18T22-03.md
Child checkpoint deviation: step8/9/10 recorded as not_applicable (outside MCP
step-status enum); no --require-complete assertion at preparation terminus.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nd email-classifier (#372)

Replace manifest placeholders 9007->365 and 9010->372 from child promotion
receipts after fan-in. Remaining placeholders 9011 (dialogs-misc) and 9012
(ci-capstone) stay provisional until those children are prepared.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, user-story, research, plan)

Preparation-mode planning for Wave-1 epic child utilitiescs-nullable-dialogs-misc
(issue #374) of the utilitiescs-nullable-remediation epic. CS86xx nullable-reference
remediation for UtilitiesCS/Dialogs/ (12 targets, 4 Designer files excluded) plus two
zero-risk verify-only misc files (WindowsAPI/ExtraDeclarations.cs, Properties/AssemblyInfo.cs)
under the per-file #nullable enable opt-in architecture. Annotation and null-safety only.

- Research artifact: definitive scope determination; Dialogs/ accounts for the epic's
  ~16-file estimate; larger residual UtilitiesCS trees flagged as epic ownership gaps.
- spec.md + user-story.md (full-feature): AC1-AC6, batches A-E, upstream WinFormsExtensions.Clone<T>
  (#363 Batch D) contract, net481 constraints, per-file pragma gate.
- plan.2026-07-18T22-30.md: 8-phase atomic plan; plan validator passed; atomic-executor
  preflight ALL CLEAR. Execution deferred to epic-orchestrator.

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

Preparation-mode child for the Dialogs/ cluster (12 remediation targets + 2 verify-only
misc files). PREFLIGHT: ALL CLEAR. Feature-folder-only, disjoint from prior fan-ins.

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

Back-fill dialogs-misc issue_num 9011 -> 374. Residual-scope decision: the residual
unowned trees flagged by dialogs-misc contain 44 in-scope CS86xx-risk production files
(Examples 1, To Depricate 2, OneDriveHelpers 2, OutlookObjects residual 13,
EmailIntelligence residual 26), so a new Wave-1 remediation child
utilitiescs-nullable-residuals (placeholder 9013, depends_on extensions+helperclasses+
threading) is added to own them; added to capstone depends_on. Interfaces/** (~62) and
2 Properties Designer files excluded epic-wide (near-zero CS86xx risk). dialogs-misc
helperclasses edge (grep-unconfirmed) retained and its #363 Batch D execution-start gate
recorded.

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

Preparation-only run for Wave-1 epic child utilitiescs-nullable-residuals
(issue #375) of utilitiescs-nullable-remediation. Annotation-only per-file
#nullable enable remediation of 44 residual UtilitiesCS files (37 effective
compiled opt-ins; 6 Designer files + 1 dead duplicate excluded).

Includes promotion (issue #375), research, spec.md + user-story.md (AC1-AC8),
and an atomic plan cleared by atomic-executor preflight (ALL CLEAR) and the
MCP plan validator. Execution, PR authoring, and CI monitoring are deferred
to epic-orchestrator.

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

Back-fill manifest placeholder 9013->375 (utilitiescs-nullable-residuals
promoted). Record residuals preparation findings for epic-orchestrator
execution: effective opt-in set 37/44 (PeopleScoDictionaryNewBackup.cs
dead-duplicate + 6 OlFolderTools Designer files excluded), undeclared-harmless
reusabletypes #366 edge, three pre-existing >500-line files not split, and
maintainer-decision flags (MSDemoConv.cs, To Depricate/*, MailResolution_ToRemove).

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

Preparation-mode (route_id: preparation) child for the CI nullable-gate
capstone (issue #376, epic manifest placeholder 9012). Deliverables:

- issue.md with AC1-AC7 (drop global /p:Nullable=enable; genuine-enforcement
  verification; csharp.md rules-conflict flag; optional project-level Nullable
  flip gate; consolidated maintainer-decision summary; no behavior/coverage
  regression).
- research/ findings covering the gate edit, verification method+candidates,
  rules conflict, optional-flip feasibility, maintainer-decision inventory,
  and CI-workflow rule applicability.
- spec.md (full-feature) + user-story.md.
- plan.2026-07-19T04-25.md: 6-phase atomic plan, MCP plan-validator PASS,
  atomic-executor PREFLIGHT: ALL CLEAR (2 passes).
- child-scoped orchestrator-state checkpoint (model_budget.fable_policy
  disabled; all delegated phases C2 -> sonnet; require_model_routing PASS).

Terminates at next_step S5_atomic_execution. Atomic execution, PR authoring,
and CI monitoring are out of scope and performed later by epic-orchestrator.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
drmoisan and others added 28 commits July 19, 2026 12:50
…re-audit) — PASS, 0 blocking

Verdict PASS, blocking_count 0. AC1-AC5 all verified against
git diff df2235b..HEAD and executor evidence.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…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>
…ation-integration' into feature/utilitiescs-nullable-email-classifier-372

# Conflicts:
#	.claude/agent-memory/atomic-executor/MEMORY.md
…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>
…k-mailitem-item-371

fix(371): remediate nullable debt in Outlook item-adapter cluster (MailItem/Item/Conversation/Attachment/Table)
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
…tlook-folder-store-365

feat(365): nullable-enable Folder/Store cluster (Wave 1, utilitiescs-nullable-remediation)
…ation-integration' into feature/utilitiescs-nullable-email-classifier-372

# Conflicts:
#	.claude/agent-memory/atomic-executor/MEMORY.md
…ail-classifier-372

nullable(#372): per-file #nullable enable remediation of the EmailIntelligence classifier cluster
Per-file `#nullable enable` opt-in remediation for 32 reusable base/value
types under UtilitiesCS/ReusableTypeClasses/ (Batches 1-5: trivial leaves,
value/utility types, matrices, timed actions, locking core). Each file
carries a `#nullable enable` pragma and reaches zero CS86xx under the
per-file pragma gate. Annotation and null-safety only: nullable `?`
annotations, guard clauses, justified `!`, and unconstrained-generic
`T?`/`default!` fields. No behavior changes, no refactors, no file splits,
no post-condition attributes (net481 lacks the polyfills), no record/init
conversion. No `<Nullable>` element added to UtilitiesCS.csproj (AC2).

Verification (cluster, isolated-compile methodology): 0 CS86xx, 0 CS8714
across the 32 files under their pragmas; csharpier clean; analyzers build
succeeds (75 warnings = baseline, 0 errors); 5702 MSTest tests pass with
no regression; line coverage 83.8% / branch 76.4% (unchanged within
rounding, annotations are IL-invariant).

Batch 6-8 and the CS8714 `where TKey : notnull` public-contract change on
the four generic dictionary bases are HALTED pending maintainer
ratification (see evidence/other/cs8714-notnull-ratification.md, BLOCKED).
Phases 6-9 are out of scope for this commit.

Epic child of utilitiescs-nullable-remediation (Wave 0). Refs #366.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Atomic-executor memory: on net481 the ConcurrentDictionary reference
assemblies are not nullable-annotated, so `where TKey : notnull` is not
required to clear CS8714 under the per-file pragma gate; and the pragma
gate must be measured with the isolated-compile methodology because the
whole-project TWAE build carries pre-existing unrelated errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Orchestrator memory: (1) TaskMaster lacks the Python orchestrator-state
validator, so the SubagentStop completion hook uses the portable PowerShell
path (no require-complete) — a blocked child can terminate and open its PR
with blocked_reason=none and steps 5-8 non-pending; (2) rebasing an epic
child onto an advanced integration tip conflicts only on the shared
agent-memory MEMORY.md index (resolve as a union), and pr_context must be
regenerated from the real diff in an isolated agent worktree.

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

Nullable-annotate the 5 Batch 6 concurrent-observable base files under per-file
#nullable enable (ConcurrentObservableBag, ConcurrentObservableCollection[.Serialization],
ConcurrentObservableDictionary, ObservableDictionary; DictionaryChangedEventArgs newValue/oldValue
made TValue?). Zero CS86xx / zero CS8714 for the cluster (isolated pragma gate); 5702 tests pass.

Apply the maintainer-RATIFIED (2026-07-19T22:14:30Z) `where TKey : notnull` public generic-parameter-list
constraint to ConcurrentObservableDictionary<TKey, TValue>. The ConcurrentBag<T>-based
ConcurrentObservableBag is NOT constrained.

Cross-child two-file scope waiver (epic-orchestrator authorized 2026-07-19T23:10:00Z, Option A
extended to two files): to keep the ratified public contract internally consistent, add EXACTLY ONE
`where TKey : notnull` line to EACH of two #367-owned NewtonsoftHelpers consumers that otherwise emit
CS8714 once ConcurrentObservableDictionary is constrained, and nothing else:
  - UtilitiesCS/NewtonsoftHelpers/WrapperScoDictionary.cs   -> WrapperScoDictionary<TDerived, TKey, TValue>
  - UtilitiesCS/NewtonsoftHelpers/ScoDictionaryConverter.cs -> ScoDictionaryConverter<TDerived, TKey, TValue>
The cascade is statically bounded at these two files; PeopleScoConverter.cs (commented-out reference)
and WrapperPeopleScoDictionaryNew.cs (concrete type args) are SAFE and are NOT edited. A third
cross-child consumer would require re-escalation to the epic layer (none surfaced). Additive constraint
only; no runtime behavior change (ConcurrentDictionary already rejects null keys on net481).

Refs #366. Epic: utilitiescs-nullable-remediation.

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

Per-file #nullable enable annotation of the 7 Batch 7 files (NewSmartSerializableConfig,
SmartSerializableBase, SmartSerializable, SmartSerializableStatic, SmartSerializableNonTyped,
SmartSerializableLoader, ConfigController). Reflection-populated fields become `= null!`
(// set by deserialization); uninitialized events become nullable; an inherited CS8766
mismatch on SmartSerializable<T>.DeserializeObject was conformed to the interface `T` return
with a justified `!` rather than editing the out-of-scope interface.

Zero CS86xx/CS87xx attributable to the 7 Batch 7 files under the isolated per-file pragma gate
(whole-assembly nonzero exit is the pre-existing out-of-scope CS0618/CS0168 baseline only).
5702 tests pass; line 83.79% / branch 76.34%. Annotation-only: no record/init conversion, no
file split (SmartSerializable.cs and SmartSerializableBase.cs remain single files), no
NewtonsoftHelpers or exempt-WinForms file touched, no <Nullable> element added to the csproj.

Refs #366. Epic: utilitiescs-nullable-remediation.

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

Per-file #nullable enable annotation of the 7 Batch 8 files (SerializableList, ScBag,
ScoDictionaryStatic, ScoDictionaryNew, SloLinkedList, SloStack, ScDictionary). Serialization
round-trip fields become `= null!` (// set by deserialization); SloLinkedList NotImplementedException
interface stubs annotated to the interface nullable contract without bodies. Zero CS86xx and zero
CS8714 attributable to the 7 files under the isolated per-file pragma gate; 5702 tests pass;
line 83.79% / branch 76.34%. Annotation-only: no record/init, no file split (SerializableList.cs
remains single), no NewtonsoftHelpers/exempt-WinForms touch, no <Nullable> element added.

Ratified `where TKey : notnull` constraint status for Batch 8 bases:
  - ScoDictionaryNew<TKey, TValue>: APPLIED (cascade fully absorbed by the two already-waived
    #367 files WrapperScoDictionary.cs + ScoDictionaryConverter.cs; 0 CS8714).
  - ScoDictionaryStatic: NOT APPLICABLE — it is a non-generic static class of Type extension
    methods with no TKey (the plan's "four generic bases" wording is inaccurate for this file);
    reaches 0/0 regardless.
  - ScDictionary<TKey, TValue>: DEFERRED / NOT APPLIED. Applying the constraint surfaces a THIRD
    cross-child CS8714 in UtilitiesCS/NewtonsoftHelpers/WrapperScDictionary.cs(18) — a #367-owned
    consumer distinct from the two epic-authorized waiver files. Per the AUTHORIZED PROGRAM
    third-consumer clause, the child orchestrator STOPPED and re-escalated to the epic layer rather
    than widen the waiver unilaterally. The tree is green WITHOUT this constraint (net481 no-op).

[P8-T1] complete; [P8-T2..T4] pending the epic-layer decision on the ScDictionary constraint.

Refs #366. Epic: utilitiescs-nullable-remediation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
Epic layer authorized extending the ratified `where TKey : notnull`
cross-child waiver to a THIRD #367-owned NewtonsoftHelpers consumer,
UtilitiesCS/NewtonsoftHelpers/WrapperScDictionary.cs (one constraint
line on WrapperScDictionary<TDerived,TKey,TValue>), triggered by
constraining the fourth ratified base ScDictionary<TKey,TValue>.

Three-file waiver total (one `where TKey : notnull` line each):
  1. WrapperScoDictionary.cs   (Batch 6)
  2. ScoDictionaryConverter.cs (Batch 6)
  3. WrapperScDictionary.cs    (A', Batch 8 completion)

Factual correction: ScoDictionaryStatic is a non-generic static class
of Type extension methods (no TKey); the ratified "four generic bases"
wording is inapplicable there. The constraint applies to the three
truly generic bases (ConcurrentObservableDictionary, ScoDictionaryNew,
ScDictionary). ScBag remains unconstrained.

Revises plan tasks [P8-T2], [P9-T9], [P9-T10] and appends the OPTION
A-PRIME resolution section to the cs8714-notnull-ratification dossier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…our-file A'' cross-child waiver)

Applies `where TKey : notnull` to the third truly-generic base ScDictionary and propagates it to
the four #367-owned NewtonsoftHelpers consumers under the epic-authorized four-file waiver
(A''): WrapperScoDictionary.cs, ScoDictionaryConverter.cs, WrapperScDictionary.cs,
ScDictionaryConverter.cs. Cross-child consumer set is closed at four (Wrapper+Converter per base).
P9-T3 solution-wide count carries expected cross-child fan-in from sibling files (capstone #376).

Batch 8 isolated-cluster pragma gate: 0 CS86xx / 0 CS8714 in the #366 cluster including the four
waived NewtonsoftHelpers lines. Tests 5702/5702 pass; line coverage 83.79% -> 83.88% (no
changed-line regression). AC1-AC6 checked off in issue.md. Phase 8/9 final-QC evidence recorded.

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 four-file A'' waiver
completion. blocking_count 0; solution-wide CS86xx recorded as expected
cross-child fan-in (capstone #376), sub-85% repo-wide line coverage
dispositioned non-blocking (pre-existing baseline, AC4 no-regression PASS).

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

Nullable remediation: UtilitiesCS/ReusableTypeClasses (#366)
…remediate integrated-tree build debt

Wave-2 capstone of the utilitiescs-nullable-remediation epic. Drops the global
/p:Nullable=enable override from ci.yml's nullable-gate step so enforcement relies
entirely on each file's own #nullable enable pragma under /t:Rebuild
/p:TreatWarningsAsErrors=true (AC1), with a genuine-enforcement verification cycle
proving opted-in files fail and non-opted-in files do not cross-block (AC2).

Remediates build debt that only became measurable once all twelve Wave-0/Wave-1
children were fanned into the integration branch (ci.yml never runs on that branch,
so this is the first genuine full-solution /t:Rebuild attempted under
TreatWarningsAsErrors): a pre-existing SVGControl CS0649 dead-field warning, a
62-file UtilitiesCS cross-child nullable/CS0618/CS0168 fan-in (296+28+2
diagnostics), and three further escalation layers of pre-existing,
never-before-reached warnings-as-errors debt in ToDoModel, TaskVisualization,
QuickFiler, TaskMaster, and their .Test counterparts -- all resolved via
nullable annotation, null-forgiving operators, guard clauses, narrow pragma
suppression, or deletion of compiler-confirmed-dead code, with no behavior
change (AC7).

Flags (does not resolve) the .claude/rules/csharp.md rules-vs-convention
conflict for the maintainer (AC4), documents the optional project-level
<Nullable> flip as separately-gated and not performed (AC5), and consolidates
the epic's maintainer-decision inventory in spec.md (AC6).

Solution-wide pragma gate reaches EXIT_CODE 0; 5702/5702 MSTest passed;
coverage 83.89%/76.37% line/branch, no regression vs 83.88%/76.36% baseline.
feature-review: blocking_count 0.

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

Finalize CI nullable gate to per-file pragma enforcement and remediate integrated-tree build debt (#376)
… modified-workflow-needs-green-run

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
…egration branch before final PR

# Conflicts:
#	.claude/agent-memory/feature-review/MEMORY.md
#	.claude/agent-memory/orchestrator/MEMORY.md
Post-merge orchestrator memory note documenting that the per-child
fan-in debt is deferred to the Wave-2 CI capstone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXCu1xPtNbJs2HwKxgS9Bv
@drmoisan
drmoisan merged commit 1e6995b into main Jul 20, 2026
2 checks passed
@drmoisan
drmoisan deleted the epic/utilitiescs-nullable-remediation-integration branch July 20, 2026 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment