Read a use case as a story
Each row runs left to right as one complete scenario — the command that started it, every aggregate it read or wrote, and where it ended.
Failure paths repeat the prefix on purpose, so a refusal reads on its own rather than as a branch you have to trace back. Here the two refusals come from different places: the repository knows whether the copy exists, and only the aggregate knows it was already lost.

See what an aggregate holds
Every object gets one page — its invariants, a diagram of the aggregate it belongs to, its behaviours, the events and errors those produce, and the repository that stores it.
Follow the same object from anywhere and you land on the same page. The kind of the thing decides what you see, never the link you happened to click.

And where it contradicts itself
Every count opens what it counted. Beneath them, the findings: an invariant declared but attached to nothing, an event missing from its union, an error whose instanceof is broken at runtime, a use case whose failures were widened to Error.
The same pass that builds the model reports them, with the file and line to go and fix.

What it finds
Detection keys on Ontologic's base classes and type arguments, never on filenames — so it works whatever you named your folders, and whether your event union lives in its own file or inline.
- Aggregates and entities
- Value objects
- Domain events
- Typed errors
- Invariants
- Repositories
- Use cases
- Commands and queries
- Read models
Start with a domain you did not write
The library example, generated by the tool itself. Search it, filter it, open an aggregate, follow an event to the view built from it.