Learn · 05 of 5

Quality: smells, errors, and warnings

The validator checks structure. Business clarity still requires judgment.

The four anti-patterns

These shapes are warnings worth investigating, not automatic rejections.

Left chair

1 Command → many Events. Check whether several business capabilities are mixed together.

Right chair

many Events → 1 Read Model. Check whether the Read Model answers more than one question.

Bed

1 Screen → many Commands. Check whether the Screen combines unrelated user intents.

Shelf

1 workflow → many scenarios, others → none. Check which workflows still rely on implicit rules.

What the validator rejects outright

The default profile rejects invalid HCL and unknown syntax, missing required semantic attributes, wrong literal types and invalid examples, duplicate identities, unresolved or wrong-kind references, non-canonical flow directions, invalid pattern-specific scenario structure, non-contiguous chapters, and incorrect Automation/Translation externality. Diagnostics use stable EMxxx codes — EM0xx structural, EM1xx references, EM2xx flow, EM3xx scenarios, EM4xx modeling judgment.

What it leaves to human judgment

Some checks need judgment rather than hard rejection: a Command with no incoming flow, API endpoint, or trigger (EM404); the four anti-patterns above; an open hotspot (EM406). Three profiles decide how strict that judgment is:

ProfileJudgment diagnostics (EM404, EM406, the four smells)
workshopInformational — incomplete discovery stays easy to work with
valid (default)Warnings
strictEM404 and EM406 become errors; the four smells stay non-blocking judgment signals

This Command has no incoming flow, API endpoint, or trigger:

bounded_context "appointments" { event "appointment_added" { } } state_change "schedule_appointment" { command "add_appointment" { to = [event.appointments.appointment_added] } }

Under the default valid profile, it's a warning and the file still validates:

em404-test.em.hcl:6:3: Warning EM404: Every command has a reason: command "add_appointment" has no incoming flow, api_endpoint, or external_trigger. em404-test.em.hcl valid

Under --profile strict, the same diagnostic becomes a hard error and nothing is reported valid:

em404-test.em.hcl:6:3: Error EM404: Every command has a reason: command "add_appointment" has no incoming flow, api_endpoint, or external_trigger.

A shipped example also produces a right-chair warning:

pet-management-detailed.em.hcl:459:12: Warning EM403: Right chair anti-pattern: readmodel "owner_details" connects to several events; review whether the workflow contains more than one business capability. pet-management-detailed.em.hcl valid

Use strictness to make an agent-ready model more explicit; don't use permissiveness to hide uncertainty. Unknown business facts belong in hotspot blocks, not in silence.

Validity-spotting drill

For each item, decide: invalid (validator-level problem), valid but suspicious (a warning or smell), or valid.

A event "order_placed" { title = "Order Placed" }
Answer

Invalid Events are bounded-context-owned contracts and must be declared inside a bounded_context.

B to = ["event.orders.order_placed"]
Answer

Invalid Relationships are typed, unquoted HCL traversals — this is a string.

C readmodel "order_summary" { title = "Order Summary" }
Answer

Invalid A readmodel block only exists inside a state_view, automation, or translation workflow — and even declared correctly, it would still need a concrete question.

D One command -> five semantically unrelated events
Answer

Valid but suspicious A left-chair smell — investigate whether several capabilities are hiding inside one Command.

E A translation consumes only event.orders.order_placed, where "orders" is an internal bounded context.
Answer

Invalid A Translation must consume at least one Event from an external bounded context — the validator checks this externality rule directly.

F A State Change scenario contains two "when" blocks.
Answer

Invalid State Change scenarios require one when, targeting a Command.

Keep going

The full guide includes more exercises, facilitation notes, and a capstone.