Skip to content

Understanding your system

Most of the console answers operational questions — is it healthy, is it keeping up, what's in the dead-letter queue. A second, quieter set of screens answers a structural question instead: what is this system, actually? They read your running Critter Stack application back to you — its message flows, its event model, its generated HTTP surface, the DDL it installed — assembled live from the code and the runtime rather than from a diagram someone drew once and forgot to update.

This page is a map of those reflection surfaces and the order to reach for them. Each has its own reference page; this is the "which one, and when."

Why it stays honest. Hand-drawn architecture diagrams drift the moment someone ships a change. These surfaces don't: every one is derived from what's running — the assembled lifecycle model, Wolverine's own ActivitySource, the projection code the service actually executes, the schema Marten/Wolverine actually installed. If the picture is wrong, the system is wrong, not the doc.

The question each surface answers

SurfaceThe question it answersScope
WorkflowWhere does this message / event / saga fit?Fleet-wide, seeded on a type
Event ModelWhat is the command → event → projection → read-model shape here?One service, or one type stitched across services
ConversationsWhat actually happened to this one message instance?A single concrete request, across services
Message TopologyWho produces this message, and who handles it?Fleet-wide routing graph
HTTP chain detailWhat did Wolverine generate for this route?One HTTP endpoint
Projection StepperWhat is this projection doing on this stream?One projection over one slice of events
DDL viewerWhat schema did the stack actually install?One store's durability / projection tables

Two axes: shape vs. behaviour

The surfaces split along one line — what the system can do (static shape, read from code and declared structure) versus what it did do (observed behaviour, read from the runtime).

Workflow sits deliberately on the seam — it unions inferred (static code structure), observed (runtime causation edges), and confirmed (both), so a single graph shows you where the drawn shape and the lived behaviour agree and where they don't.

A reading order

When you're trying to understand an unfamiliar corner of the system — a service you didn't write, an incident in a flow you don't own — the surfaces compose top-down, broad to narrow:

  1. Start with the shape. Seed Workflow on the type at the centre of your question and follow it across service boundaries, or open a single service's Event Model swim-lane to see its command → event → projection spine at a glance. Message Topology is the routing-only view when you just need "who sends, who handles."
  2. Drop into one instance. When the static shape raises a "but did this one make it through?" question, switch to Conversations and open the concrete message instance — the real causal graph, captured with no tracing backend to stand up.
  3. Drill into the internals. From there the fine-grained tools take over: HTTP chain detail for the generated code + OpenAPI of a route, the Projection Stepper to step a projection row-by-row over a slice of a stream, and the DDL viewer for the exact schema the stack installed.

The Event Model drill-downs tie the levels together: click a Handler node for its generated source, a Projection node to jump into the stepper — so you can move from "here's the shape" to "here's the code" to "here's what it did" without leaving the thread.

Richer with the source generator

Every surface renders from runtime observation alone, filling in as messages actually flow. A service that references CritterWatch.SourceGeneration additionally contributes a statically-discovered manifest, so its Event Model lanes and Workflow graph come through fully populated before any traffic — the shape is known from the code, not inferred from load. Both render; the source-generated service is simply richer up front. See Event Modeling → Richness scales with the source generator.

On the roadmap: declared-vs-implemented drift

The strongest form of "reads your app back to you" is drift detection: comparing what a service declares it does (an EventModelDefinition) against what it actually implements, and flagging the gaps — a handler you built but never declared, or a declared step with no matching handler. The Event Model swim-lane carries the rendering scaffold for this (per-node declared / drift / missing status pills), but it is not yet wired into the live assembler model — the current lifecycle projection does not compute the comparison, so the pills stay suppressed. Treat this section as a signpost, not a feature you can use today; it will graduate to the top of this page once the declared-model overlay lands on the assembler path.

Free for read-only monitoring. A commercial license is required for administrative actions and the MCP server.