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, and do my sources agree about it?Fleet-wide, merged across every source
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 switch that screen to its Event Model view for the fleet's command → event → projection spine as canonical Event Modeling slices. 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 card for its handler-chain detail, a projection card for its projection detail, a message or event card to re-seed the whole screen on that type — 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 Workflow graph comes 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.

⚠️ That generator enriches the lifecycle, not the Event Model's slices: it emits aggregates, handler relationships and sagas, and explicitly no slices. The Event Model's derived half comes from the IEventModelDefinitionSource implementations registered in your app — which every Wolverine host has one of already.

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.

Part of this has landed. The Event Model is assembled from several sources and the merge emits a SourceDisagreement hotspot where two of them describe the same slice differently — most often production doing something the code does not say it does. And where a Bobcat spec monitor is bound, each slice chip carries an evidence dot that flags drift between a slice and the specifications bound to it. The per-node declared / drift / missing status pills an older revision of this section pointed at were on the retired per-service swim-lane and no longer exist.

What is still missing is the declared rung itself: CritterWatch registers no hand-written overlay of its own, so nothing in the console's own merge can claim Declared. An overlay declared in your app arrives through that service's pushed manifest.

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