Rules and findings
Structural findings block a save; rule findings never do. How the linter reaches each one.
Two kinds of thing can be wrong with a design, and Zeema keeps them apart everywhere: in the engine, in the API, in the command line and in the editor.
| Structural finding | Rule finding | |
|---|---|---|
| Means | The document is invalid | The design may be wrong |
| Examples | Unknown component, edge to a missing node, enum value that is not in the enum | No dead-letter queue, retry without backoff, single-region datastore |
| Severity | Always an error | error, warning or info |
| Blocks a save | Yes, always | No, never |
Fails zeema lint | Yes | At or above --fail-on, default error |
| Produced by | packages/core/structure.js | packages/core/rules.js |
How the linter reaches a finding
For every rule, in order:
- Select subjects. Nodes of a kind or category, edges, or the design itself — once each.
- Resolve effective properties for each node: the node's
props, then the component'sdefaults, then the property definition'sdefault. A property that resolves to nothing is omitted rather than set to null. - Evaluate the predicate against the subject, the design's requirements, the node's group ancestry and the edges touching it.
- Emit the message with the rule's severity, for every subject where the predicate is true.
Everything is deterministic. The same design and the same catalogue always produce the same findings, in the same order.
Severities
error— data loss, availability or correctness. Fails a CI gate.warning— performance and cost. Comments without failing.info— style. Listed and nothing more.
The severity is a property of the rule, not of the design, and it is chosen when the rule is written. Governance has the criteria.
What a finding looks like
From the command line:
zeema lint architecture/checkout.yamlerror queue-missing-dlq Queue 'orders-queue' receives async traffic but has no dead-letter queue. error datastore-missing-backup Datastore 'orders-db' has no backup or no retention policy declared. warning sync-chain-too-deep Entry point 'api' starts a synchronous call chain deeper than 3 hops while the design states a p95 latency target. 2 errors, 1 warning
From the API, and from the editor that calls it:
{ "valid": true, "findings": [ { "id": "queue-missing-dlq", "severity": "error", "message": "Queue 'orders-queue' receives async traffic but has no dead-letter queue.", "blocking": false, "subject": { "type": "node", "ref": "orders-queue" } } ], "counts": { "nodes": 3, "edges": 2, "groups": 0 } }
valid is about structure alone. blocking is true only on a structural finding, and it is
the single flag storage consults. subject is what the canvas highlights: node, edge (by
index) or design.
Turning a rule off
In your own repository, zeema.config.json disables rules per path:
{ "designs": ["architecture"], "failOn": "error", "disable": {} }
failOn sets the severity at which the command exits non-zero; never reports without failing.
Disabling is per repository and never travels with the design, so a published design always shows
every finding it has.
Where to look next
- Rules reference — the predicate vocabulary and every rule that ships.
- Command line — formats, exit codes and the CI workflow.
- Every rule also has its own page, with the condition in plain English and the reference designs whose broken twin trips it.