Skip to content

refactor(config): nest grid-style options into group records (#118) - #177

Merged
mrcsin merged 1 commit into
masterfrom
grid-style-nest-record
Aug 6, 2026
Merged

mrcsin merged 1 commit into
masterfrom
grid-style-nest-record

Conversation

@mrcsin

@mrcsin mrcsin commented Aug 5, 2026

Copy link
Copy Markdown
Member

Problem

The flat 78-arity GridStyleOptions record forced a wide flatten/unflatten surface across the grid-style stack: two mappers, a color-enumerating validator, and a ×3 view-model mirror (property declarations, Seed, BuildRecord) each had to name every one of the 78 fields. A field surfaced in one block but dropped from another compiled fine and silently misbehaved. Slice 3 of the #118 grid-style debloat replaces the flat record with a nested shape so each reader touches only the group it needs.

What changed

GridStyleOptions is now a one-level nested root composing 10 group records + root Orientation:

  • GridStyleFonts, GridStyleLayout, SelectionColors, ChangedCellColors, DepthPalette (one type reused for ReadOnlyCells and DisabledCells), ExecutionPalette, StatusBarStyle, ValidationPanelStyle, ChromeColors.
  • Both mappers rebuilt as per-group construction, preserving the exact fallback regimes: whole-DTO-null → return Default; ?? defaults.<group>.<field> for the loose groups (fonts/layout/selection/changed/grid_line/status_bar/validation_panel/chrome); a no-fallback ! chain for the three validator-guaranteed cell palettes (readonly/disabled/execution); Orientation via Parse. colors.grid_line folds into Chrome.GridLine; colors.cells.changed/changed_selected into ChangedCellColors — the two DTO cross-sections the one-level nesting absorbs into the mapper.
  • All grid and style-editor consumers read the nested paths; the view model's Seed/BuildRecord rebuild each group positionally (a dropped field is now a compile error, CS7036).
  • The slice-1 silent-drop guards are adapted to the nested record — a hand-maintained VM-property→nested-path map plus a typed recursive leaf walk that keeps root Orientation a first-class leaf — and their non-vacuity re-proven by scratch checks.

Deliberately out of scope (later slices): colors stay string (StyleColor is slice 4); the view model's public property surface is unchanged (the split is slice 5). The on-disk YAML, the DTOs, and GridStyleValidator are byte-identical.

Verification

  • dotnet build SemiStep.slnx — 0 warnings, 0 errors; dotnet test — 1687 passed, 0 failed; dotnet format clean.
  • Default is byte-equal to the old flat Default, so the nested record round-trips losslessly through the unchanged file format (SaveThenLoad_DistinctFixture, record→dto→yaml→dto→record, green).
  • The adapted guards were proven to still bite by scratch checks: a BuildRecord cross-wire → BuildRecord_PerturbingEachProperty… RED; a dropped Seed line → Seed_PopulatesEverySurfacedProperty… RED; a dropped GridStyleDtoMapper line → SaveThenLoad_DistinctFixture RED.
  • Review chain: comprehensive (5 agents) → smells → comment audit → critical (2 agents), all OUTCOME: ACHIEVED, no critical/major at any point. Fixes applied: 2 stale with-mechanism comments corrected, 10 restatement banners removed.
  • Manual test (operator): confirmed. The style-editor Save that rewrote grid_style.yaml during testing was discarded (config file unchanged on the branch).

Slice 3 of #118 (stays open). Next: slice 4 introduces StyleColor and folds the validator's per-key checks into the mapper.

Per-task commits before collapse
d987331 docs(plan): record exec branch and verify steps
6c589e2 test(config): drop restatement banners in grid-style guard map
5235d36 docs(config): correct grid-style BuildRecord comments
7b05310 docs(config): note grid-style record is now nested
5d0d652 refactor(config): nest GridStyleOptions into group records

🤖 Generated with Claude Code

The flat 78-arity GridStyleOptions record forced a wide flatten/unflatten
surface: two mappers, a color-enumerating validator, and a x3 view-model
mirror (property declarations, Seed, BuildRecord) all had to name every
field. Slice 3 of the #118 grid-style debloat replaces it with a
one-level nested root composing 10 group records, so each reader touches
only the group it needs.

- GridStyleOptions is now a nested root: Fonts, Layout, Selection,
  ChangedCells, ReadOnlyCells/DisabledCells (one shared DepthPalette),
  Execution, StatusBar, ValidationPanel, Chrome, plus root Orientation.
- Both mappers rebuilt as per-group construction, preserving the exact
  fallback regimes: whole-DTO-null returns Default; ?? defaults per field
  for the loose groups; a no-fallback ! chain for the three
  validator-guaranteed cell palettes; Orientation via Parse. grid_line
  folds into Chrome.GridLine and the changed/changed_selected pair into
  ChangedCellColors, matching the DTO cross-sections.
- All grid and style-editor consumers read the nested paths; the view
  model's Seed/BuildRecord rebuild each group positionally.
- The slice-1 silent-drop guards are adapted to the nested record (a
  hand-maintained property-to-path map plus a typed recursive leaf walk)
  and their non-vacuity re-proven.

The on-disk YAML, the DTOs, and GridStyleValidator are byte-identical;
only the record shape and its readers change. Default is byte-equal to
the old flat Default, so the record round-trips losslessly through the
unchanged file format. Colors stay string (StyleColor is slice 4) and
the view model's public property surface is unchanged (the split is
slice 5); #118 stays open.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mrcsin
mrcsin marked this pull request as ready for review August 6, 2026 08:53
@mrcsin
mrcsin merged commit 89a5476 into master Aug 6, 2026
1 check passed
@mrcsin
mrcsin deleted the grid-style-nest-record branch August 6, 2026 08:53
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