mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-14 19:31:55 -04:00
Slice 3b task 1 (D8/D9): ClampRail gains RemovalMinutes (D9, default 5 minutes, validated finite >= 0) and Plate gains RemovedClamps (rail clamp ids taken off this sheet as a last resort) plus the computed ClampRemovalMinutes. Plate.SetClampRail gains an overload that attaches a rail with a removed-clamp set; zones become the rail's resolution for the sheet minus those ids, re-resolved on every resize/rotate so a removed clamp stays off and reappears removed if a later resize brings it back onto the sheet. ClampRail.Matches gains an overload comparing against the reduced resolution. IO: PlateDto.RemovedClamps and ClampRailDto.RemovalMinutes persist (missing removalMinutes falls back to the default; missing removedClamps means none). The writer's empty-plate drop logic no longer drops a sheet whose only content is a removal state the defaults can't recreate. The reader re-attaches the nest rail to a plate only when its saved zones equal the rail's resolution minus its saved removed ids, so a reduced-clamp sheet keeps following the rail (and the removal) through later resizes instead of freezing as static zones. Engine/desktop wiring (minimal-removal computation, Auto Nest last-resort removal, cut-time, UI) is Slice 3b tasks 2-3, not yet done. Tests: 16 new Core (ClampRailTests) + 5 new IO (ClampRailPersistenceTests) covering validation, resize/resolve behavior, round-trip, legacy missing-key defaults, and the empty-plate-with-removal-only retention case. Mutation check (reverting the RemovedClamps subtraction) turns 3 Core + 2 IO assertions red, confirming real coverage. Gates: Release OpenNest.Tests 3884 passed/31 skipped, OpenNest.IO.Tests 105 passed, OpenNest.Engine.Tests (Clamp filter) 98 passed; scoped dotnet format --verify-no-changes clean.