Serena MCP is mandatory for C# code. First call
mcp__serena__initial_instructionsto load the Serena tool manual, then use the Serena tools for ALL.csreading / searching / navigation / creation / editing — prefer symbol navigation (get_symbols_overview/find_symbol/find_referencing_symbols) over whole-file reads. NativeEdit/Writeon.csis hook-blocked (the TS/React frontend uses the native tools).
Add a domain entity / value object
The procedure for our rich, base-class-free DDD model. Source of truth (the facts — read them):
.claude/rules/backend/domain-model.md and docs/projectStandards/coding-standards.md. The domain is
persistence-ignorant (no EF types/navigations). C# (.cs) edits via Serena.
Entity / aggregate
- Place in
{{ProjectName}}.Domain/<Feature>. - Rich mutable class (NEVER a record). Shape:
- a private parameterless constructor (EF materialization);
- a
public static Create(...)(or named) factory with guard clauses that throws on invalid input and mints the id viaGuid.CreateVersion7()(neverGuid.NewGuid()/Guid.Empty-until-save); - all setters private — state changes only through behaviour methods;
- invariants enforced inside every behaviour method (throw on violation — the domain is the last line of defence);
- a non-null
TenantIdpreserved across mutations (the tenancy invariant); - identity-based equality declared on the type itself (no base
Entity/AggregateRoot, no domain events).
- No primary constructors.
Value object
- A record (or
readonly record struct) — immutable, value equality (e.g.Money,ModelId,TenantId).
After
- EF mapping (config) and repository → the
efcore-patternsskill. Build (dotnet build, warnings = errors). - Tests (factory guards, invariant throws, behaviour) → the
write-testsskill, per the plan's exact test list.