Skip to content

refactor(arch): move Egg Operations into Modules/EggOperations - #1093

Merged
mforce merged 4 commits into
mainfrom
refactor/1087-egg-operations-module
Oct 5, 2026
Merged

mforce merged 4 commits into
mainfrom
refactor/1087-egg-operations-module

Conversation

@mforce

@mforce mforce commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Refs #1087

S5 of the package-by-module design: Egg Operations moves into Modules/EggOperations in Domain, Application and Api. This is a pure move with no behaviour change. Its repositories and EF configurations stay in place until S9. Proofs compare this head 52c88352 with the base 541eca98 (#1092 merged). The branch was rebuilt on that base by re-running the codemod for every commit, not by hand-merging.

Review order

  1. split (mechanical): 15 contract declarations leave 10 mixed files. Each becomes a verbatim slice in its own file, in the same namespace.
    • Domain: DailyEntryStatus (from DailyEntry.cs); EggGradeType and DailyEntryKind (from EggGrade.cs); EggMovementType (from EggInventoryMovement.cs).
    • Application: AdjustDailyEntryResponse, SubmitDailyEntryResponse, VoidDailyEntryResponse, DailyEntryLockPass, LockedDailyEntry, RefusedDailyEntryLock, StockByGrade, RecordEggLotMovementResult, SaleDemandLine, PlannedEggLotDraw, SaleAllocationPlan.
  2. move (generated; skim it): 60 git mvs, with namespaces taken from folders. tools/module-move/move.py rewrote references, usings, ledger strings, snapshot entity names and paths. prune then dropped the usings the move left unused. The rules file's Namespaces now holds Cluckwork.Domain.Modules.EggOperations and Cluckwork.Application.Modules.EggOperations. Implementations is unchanged until S9.
  3. docs: fixes two layer-relative paths in docs/architecture.md that the codemod's project-relative rewrite does not match.
  4. marks: deletes the 33 Egg Operations [ModuleContract] marks (4 Domain, 29 Application).

This slice needed no codemod change.

Change map

Before After
Domain/Eggs/{DailyEntry,EggGrade,EggInventoryMovement,EggLot}.cs Domain/Modules/EggOperations/Eggs/
DailyEntryStatus, EggGradeType, DailyEntryKind, EggMovementType (split out) Domain/Modules/EggOperations/Contracts/
Application/Features/{DailyEntries,EggGrades,EggLots,Eggs}/** contracts (11 whole files, 18 types; 11 split types) Application/Modules/EggOperations/Contracts/ (29 types)
Application/Features/{DailyEntries,EggGrades,EggLots,Eggs}/** handlers, validators, lookups, EggStock, EggOperationsModule, SaleAllocationPlanner, repository ports Application/Modules/EggOperations/{DailyEntries,EggGrades,EggLots,Eggs}/**
Api/Endpoints/{DailyEntries,EggGrades,Stock}/*.cs, Api/Hosting/Modules/EggOperationsModuleServiceCollectionExtensions.cs Api/Modules/EggOperations/: Platform-owned adapters. Stock goes with the module it reaches.
AppDbContextModelSnapshot.cs: 19 entity-name lines new CLR names. No migration was added, and no historical migration or Designer file changed.

Checks at the head (base measured on 541eca98)

Check Base Head
dotnet build Cluckwork.sln 0 warnings 0 warnings
Application.Tests Architecture + TenantBypass + Documentation + ImagePin 474/474 474/474
Application.Tests DailyEntry/EggGrade/EggLot/EggStock/SaleAllocation/Stock classes 59/59 59/59
Domain.Tests 495/495 495/495
ServingGuardCoverageTests, TrackedMutationReadTests, InsightsReadOnlyTests 9/9 9/9

Proofs (base 541eca98 vs head 52c88352)

Proof Result
EF migrations has-pending-model-changes "No changes have been made to the model since the last migration." No migration added. The only Migrations/ diff is the 19 snapshot entity-name lines. Control: HasMaxLength(DailyEntry.MaxReasonLength + 1) on AdjustReason makes the same command exit 1
tools/schema-docs/generate.sh --check "docs/schema/ is up to date" (no content change)
Ordered DI descriptors: Production/Development × serving/one-shot × Redis absent/configured (8 dumps) identical after the type map
Generated OpenAPI document (Development) identical
Exact normalized contract set per owner identical: 160 types; Egg Operations 33 (4 in Domain Contracts, 29 in Application Contracts)
Module-edge report (live edges) identical after the type map and the owner-root renames. Five old roots collapse into two, so a symbol's referenced-namespace list is compared as a set
Peer-reach report identical
Table-owner report identical (DailyEntries, DailyEntryGrades, EggGrades, EggInventoryMovements, EggLots still Egg Operations)
Adapter-reach report identical except one expected registration entry, as in S1–S4. AddEggOperationsModule is now under the adapter root (walked 406 → 407), with empty reach, and the persistence ban passes
Tenant-bypass registry unchanged (0 changed lines)
coupling-matrix.md unchanged (CouplingMatrixRealTreeTests green)
Unused usings (IDE0005, whole solution) base 229, head 224, 0 new. The 5 removed were already-unused usings of the emptied Application.Features.DailyEntries and Domain.Eggs namespaces

The type map covers every top-level declaration in the 60 moved files, read at the split commit. The report comparison excludes positions (file, line).

CI at 52c88352

18 checks pass, including the four test legs, "Build, audit and schema docs", both image smoke tests and the three Playwright shards. "Publish the commit image" is skipped, as on every PR.

Mutations

Each case ran in a spare worktree at the head. It was reset, built, and run against the Architecture + TenantBypass filter.

# Mutation Result Contract-set diff vs base
M1a codemod moves Contracts/VoidDailyEntryCommand.cs (file and namespace) back to DailyEntries/VoidDailyEntry/ red AdapterReachRealTreeTests, CouplingMatrixRealTreeTests Egg Operations −VoidDailyEntryCommand
M1b same file moved, .Contracts namespace kept red NamespaceFolderAgreementTests only none: the gap the folder rule closes
M1c codemod moves the Domain enum Contracts/DailyEntryStatus.cs back to Domain/Modules/EggOperations/Eggs/ green (see note) Egg Operations −DailyEntryStatus
M2 DailyEntryEndpoints also injects IDailyEntryRepository red AdapterReachRealTreeTests, CouplingMatrixRealTreeTests —
M3 moved EggGradeFloorPolicy references Commerce's SalesOrder (no Egg Operations → Commerce edge) build red CW1001: undeclared cross-owner edge EggOperations -> Commerce. With analyzers off: red ModuleLedgerRealTreeTests, CouplingMatrixRealTreeTests (2) —
M4 peer ConfirmSaleHandler also takes IEggLotRepository, which is outside the Egg Operations contract red PeerContractRealTreeTests —
M5 contract AdjustDailyEntryResponse gains a DailyEntry aggregate property red ModuleContractRealAssemblyTests —

Note on M1c (a gap that already exists, not a regression). No adapter or peer takes any of the four Egg Operations Domain enums as a parameter or service resolution. They are reached only inside Egg Operations' own contract records, such as DailyEntryDetails.Status, and the walks never read return types or members. Flock Management's M1c went red because FlockEndpoints reaches FlockStatus directly. Here, taking an enum out of the contract turns no guard red. Only the contract-set parity above catches it. Removing the mark from DailyEntryStatus on main would be equally green. No guard checks that a contract type exposes only contract types of its own module. That rule would be a separate decision, so it is not part of this move.

mforce added 4 commits October 5, 2026 22:31
…files

move.py split: the four Domain contract enums leave DailyEntry.cs,
EggGrade.cs and EggInventoryMovement.cs, and eleven Application contract
records leave four handlers, IEggLotRepository.cs and
SaleAllocationPlanner.cs, each into its own file in the same namespace.
Each declaration is a verbatim slice of the original.

Refs #1087
move.py move with the slice's table: Domain, Application and Api files go
under Modules/EggOperations, contract types (including the four Domain
enums) under Contracts, with the namespace taken from the folder. The Stock
endpoints go with Egg Operations, the module they reach. The current model
snapshot follows the moved entities; historical migrations and Designer
files are untouched. The rules file now names
Cluckwork.Domain.Modules.EggOperations and
Cluckwork.Application.Modules.EggOperations; Implementations stay for S9.
move.py prune drops the usings the move left unused.

Refs #1087
…gOperations

docs/architecture.md names the two handlers by layer-relative path, which
the codemod's project-relative rewrite does not match.

Refs #1087
The thirty-three Egg Operations contract types now sit in Contracts folders
(Domain's four enums, Application's twenty-nine types); the folder makes
them contract, and a type with both fails.

Refs #1087
@mforce
mforce force-pushed the refactor/1087-egg-operations-module branch from f047fe6 to 52c8835 Compare October 5, 2026 22:34
@mforce
mforce merged commit 51e9cbb into main Oct 5, 2026
19 checks passed
@mforce
mforce deleted the refactor/1087-egg-operations-module branch October 5, 2026 22:57
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