Review changed code against all Cratis project standards and produce a structured report.
C# Architecture
- Each slice is its own folder
<Module>/<Feature>/<Slice>/<Slice>.cswith all backend artifacts — no top-levelFeatures/wrapper - Commands:
recordtype withHandle()directly on them — no separate handler classes - Business rejection returns a
ValidationResult/Result<TEvent, ValidationResult>(or validator) — never thrown fromProvide()/Handle()(a throw is HTTP 500, not a validation error) - Fetched/computed handler data is in
Provide(), not inline inHandle() - Events:
recordtype, no mutable/nullable properties, past tense, never carry the event-source id - Identity concepts derive from
EventSourceId<T>(notConceptAs<Guid>) - Projections: AutoMap is on by default —
.AutoMap()only after.NoAutoMap(); projections consume events, never read models - Model-bound query custom paths use
[Path("...")], not[Route] - No service locator (
IServiceProvidernot injected); discover implementations withIInstancesOf<T>, notIEnumerable<T> - Namespace matches folder under the app source root (
<RootNamespace>.<Module>.<Feature>.<Slice>)
C# Code Style
- File-scoped namespaces;
usingdirectives alphabetically sorted - No unused
usingdirectives -
is null/is not null— never== null/!= null -
varpreferred over explicit types - No postfixes:
Async,Impl,Serviceon class names - No regions
- All public types, methods, and properties have multiline XML doc comments
-
<summary>tags always multiline — never/// <summary>Text</summary>on one line - Methods with parameters include
<param name="...">for each - Non-void methods include
<returns> - Custom exception types only — never
InvalidOperationException,ArgumentException, etc. - Exception XML docs start with "The exception that is thrown when …"
- Copyright header on every file
- Strongly-typed Concepts for all domain IDs/values (no raw
Guid/stringin domain models)
TypeScript Code Style
-
constoverletovervar - Full descriptive names — never
e,idx,prev,dir,pos - No
anytype —unknownwith type guards - No
(x as any)— usevalue as unknown as TargetType - No unused imports
- Copyright header on every file
Component Rules
-
CommandDialogfrom@cratis/components/CommandDialogfor command dialogs -
Dialogfrom@cratis/components/Dialogsfor data-only dialogs - Never imports
Dialogfromprimereact/dialogdirectly - No hard-coded hex/rgb colors — PrimeReact CSS variables only
- README.md present for complex component folders with multiple sub-components
Performance
Performance is part of code review, not a separate pass. Flag the common degradations:
- Projections don't join on a read model; reactors don't re-query the event log inside a handler — use event data directly
- New projections can replay all historical events without crashing; events carry no large blobs
- MongoDB queries filter on indexed fields; lists that can grow return
IQueryable<T>for server-side paging (never load all rows or hydrate the full collection for a count) - No N+1 query pattern; response payloads include only fields the client uses
- React: large/growing lists page rather than render all rows; no inline object/array literals as props that change identity every render;
useEffectdeps are correct - .NET: filter before materializing (no
.ToList()before.Where()); don't enumerate anIEnumerable<T>multiple times
Classify findings: 🔴 measurable degradation at moderate load (fix before merge) · 🟡 degrades under load/scale · 🟢 minor.
Output format
Start with: Review result: ✅ Approved / ⚠️ Approved with comments / ❌ Changes requested
Then list issues:
### <file path>
**[BLOCKING]** Line N: `problematic code`
Because: explanation
Fix:
```corrected code```
End with a concise summary of what passed and what must change.
For the full expanded checklists across all categories, see references/CHECKLISTS.md.