Code analysis
The Cratis Stack
The build enforces the conventions
Cratis leans on conventions: model-bound commands, [EventType] events, declarative projections, generated proxies, vertical slices, and thin React views. Conventions only help if something catches you when you stray. Cratis does that with Roslyn analyzers in dotnet build and ESLint rules in the JavaScript build, so the feedback lands where you, or an AI agent, can act on it.
Why build gates, not docs alone
Section titled “Why build gates, not docs alone”If you can break a convention silently, it is a suggestion. Append a type that
isn’t marked [EventType], or write a reactor method with the wrong signature,
and the framework cannot discover it. The failure shows up at runtime as
“nothing happened.” The analyzers move that failure to build time: the build
reports which rule you broke and how to fix it, and several rules ship an
editor code fix.
The frontend has the same kind of rules. Generated proxy files should not produce lint noise, view models should not call React hooks, and Components consumers should import from component subpaths and use the Cratis dialog wrappers. Those are architectural choices, so Cratis packages them as ESLint rules instead of leaving them as tribal knowledge.
This matters twice over in the AI-native workflow. When an agent scaffolds a slice, a wrong shape fails the build, the agent reads the diagnostic, and it corrects itself. Cratis AI teaches the conventions; the build gates enforce them.
Roslyn analyzer packages
Section titled “Roslyn analyzer packages”The Arc analyzers come in as dependencies of the Arc packages they check:
reference the package and the rules are active on your next build. The Chronicle
analyzers arrive the same way with Cratis.Chronicle (and with
Cratis.Chronicle.AspNetCore) from 19.4.8. Only the Architecture analyzers are a
separate, opt-in package.
Rules for events, projections, reactors, reducers, and other event-sourcing constructs. Arrives with Cratis.Chronicle and Cratis.Chronicle.AspNetCore from 19.4.8. Older versions need Cratis.Chronicle.CodeAnalysis added at the client’s version.
Rules for command, query, validation, and concept declarations. Arrives with Cratis.Arc.Core through Cratis.Arc.Core.CodeAnalysis. Does not need Chronicle.
Rules for Arc’s Chronicle integration: command identity, aggregate event handlers, reactor side effects, and audit metadata for secret command values. Arrives with Cratis.Arc.Chronicle.
House coding and architecture conventions used across Cratis codebases, such as exception naming and logging through LoggerMessage. Install Cratis.Architecture.CodeAnalysis separately if you want them.
Each rule page lists the current rules and their default severity. The rule sets grow between releases, so check the page for the version you use instead of relying on a count.
ESLint packages
Section titled “ESLint packages”TypeScript and React projects get the same kind of feedback from a shared flat-config preset and two product plugins:
| Package | Source | What it checks |
|---|---|---|
@cratis/eslint-config | Fundamentals | The consumer preset: TypeScript and React hygiene, plus relaxations for for_* BDD spec files. (The internal preset adds the Cratis license-header rule for Cratis’s own repositories.) |
@cratis/eslint-plugin-arc | Arc | Skips generated Arc proxies, forbids React hook calls inside MVVM view models, and forbids importing mobx-react directly. |
@cratis/eslint-plugin-components | Components | Requires component subpath imports instead of the @cratis/components root, forbids Dialog from primereact/dialog in favor of the Cratis wrappers, requires onBeforeExecute to return the command values, and forbids hooks in view models and hand-written CommandForm markers. |
Install the ones you need as development dependencies, then compose them in
eslint.config.mjs:
import cratis from '@cratis/eslint-config';import arc from '@cratis/eslint-plugin-arc';import components from '@cratis/eslint-plugin-components';
export default [ ...cratis.configs.consumer, ...arc.configs.recommended, ...components.configs.recommended,];Keep @cratis/eslint-plugin-components on the same major version as the
Components package you use; see its README for the supported range.
Inside the Cratis product repositories, CI runs these as lint gates.
The AI layer and the enforcement layer
Section titled “The AI layer and the enforcement layer”The architecture and coding guidance lives in Cratis AI: C#, TypeScript, vertical slices, React components, BDD specs, Chronicle reactors, review agents, and task-specific skills. That layer tells an assistant what good Cratis code looks like.
Code analysis is the enforcement layer. Roslyn analyzers and ESLint rules run after the assistant writes code, catch what drifted, and produce concrete diagnostics it can fix in the same loop. Instructions reduce bad output; build gates make the remaining mistakes visible. Neither proves the code does the right thing. Specs do that.