Line

You are reading the unreleased docs (next). See latest (v0.9)

Reference

Rule reference

Every rule id and its default severity, generated from the config.

This table is generated from DEFAULT_RULES in packages/core/config.mjs, the same map construct validate reads, so it is always current. Override any severity in architecture.yml:

rules:
  PAGE-004: warning
  PURE-001: off

Severity is error (validation fails), warning (reported only) or off. Entries marked number are threshold overrides rather than rules. A rule can also take an object with extra options, for example PAGE-007: { severity: error, similarity: 0.9 }.

All rules#

Rule Default What it enforces
ROUTE-001 error Routes delegate to controllers
ROUTE-002 error Routes cannot own business logic or effects
PAGE-001 warning Pages hold no state or effect of their own (presentation-only)
PAGE-002 error Pages cannot import workflows
PAGE-003 error Pages cannot import services
PAGE-004 error Pages cannot call fetch
PAGE-005 error Pages cannot import domain logic
PAGE-006 error Pages cannot use application state/machines
HOOK-002 error A hook named use<Name>Provider must be built through defineProvider(...)
HOOK-001 error A hook named use<Name>State must be built through useTrackedState(...), with nothing unrelated alongside it
COMPONENT-001 warning Components own no application state machine (presentation-only)
COMPONENT-002 error Components cannot import controllers
COMPONENT-003 error Components cannot import workflows/services/domain
COMPONENT-005 warning Components cannot contain inline conditional/loop logic in JSX — must be a named @expression unit
COMPONENT-006 warning Component-level JSX complexity budget (nesting depth / inline conditional-or-loop branch count), separate from any one Expression's own cap
COMPONENT-006-max-depth number Override for COMPONENT-006's max JSX nesting depth
COMPONENT-006-max-branches number Override for COMPONENT-006's max inline conditional/loop branch count
PAGE-008 warning Pages cannot contain inline conditional/loop logic in JSX — must be a named @expression unit
PAGE-009 warning Page-level JSX complexity budget (nesting depth / inline conditional-or-loop branch count), separate from any one Expression's own cap
PAGE-009-max-depth number Override for PAGE-009's max JSX nesting depth
PAGE-009-max-branches number Override for PAGE-009's max inline conditional/loop branch count
EXPR-001 error Expressions are pure (no side effects)
EXPR-002 warning An Expression's own JSX complexity budget (nesting depth / inline conditional-or-loop branch count)
EXPR-002-max-depth number Override for EXPR-002's max JSX nesting depth
EXPR-002-max-branches number Override for EXPR-002's max inline conditional/loop branch count
EXPR-003 warning Expressions need an unambiguous, non-trivial name — not the bare name of their control-flow kind
EXPR-004 error Expressions cannot contain hand-authored JSX beyond wrapping/passthrough
EXPR-005 error Expressions must accept children and return JSX
EXPR-006 error Expressions must be built through defineExpression(...) (the shared Template<Props> type)
WORKFLOW-001 error Workflows cannot import React/UI
WORKFLOW-002 warning Workflow states must be reachable from the initial state
WORKFLOW-003 warning Non-final workflow states must have a way out
WORKFLOW-004 off Every non-final workflow state must decide every event the machine handles (transition or explicit ignore)
STATE-001 off Workflow/hook state is a discriminated union on one status field, not a bag of co-occurring loading/error/data flags
CONTROLLER-001 error Controllers must compose (import + wire only) — no business logic or raw fetch()
PAGE-007 warning Pages wrap frozen (externally-authored) markup instead of reimplementing it
COMPONENT-004 warning Components wrap frozen (externally-authored) markup instead of reimplementing it
CONTROLLER-002 warning Controllers wrap frozen (externally-authored) markup instead of reimplementing it
SERVICE-001 error Services own external effects
SERVICE-002 error Services cannot import React/UI
SERVICE-003 off Services forward the caller's AbortSignal to fetch() so a superseded request never lands
CONTROLLER-003 off A controller holds no state of its own (no useState/useRef/useEffect/useMemo/useCallback), so it binds the hook's live value, never a stale copy
HOOK-003 off A useEffect that starts a listener, timer, subscription or request returns its cleanup, so it never outlives its hook
ROUTE-003 off A route forwards params/searchParams whole instead of reading them, so a raw URL string never travels inward
DOMAIN-001 error Domain is pure
DOMAIN-002 off Domain code may only reference its own parameters/local bindings, type-only imports, and a small set of JS built-ins (allowlist, not denylist)
CLIENT-001 off A 'use client' file cannot import server-only code
SLICE-001 error Feature internals are isolated
SLICE-002 error Cross-feature imports use public index.ts
MODULE-001 error One primary module per file
PURE-001 warning Domain functions should be deterministic (no Math.random, Date.now, new Date(), performance.now, crypto id)
DRY-001 warning Business knowledge has one source of truth
SOC-001 error Every responsibility has an architectural owner
SLICE-003 warning Public API (index.ts) stays in sync with actual feature exports
SLICE-004 error Cross-feature component/provider re-exports must be a distinct wrapper
READ-001 error Components/controllers are PascalCase; hooks are use-prefixed camelCase
READ-002 error Files and functions stay under their length threshold
READ-003 warning Public API exports document intent with JSDoc
READ-002-max-loc number Override for READ-002's max-lines-per-file threshold
READ-004 off A unit's filename encodes its layer as a suffix (Name.layer.ext)
TYPE-001 off Code must type-check (a real tsc --noEmit run with the project's own TypeScript)
NAME-001 off A unit's file path and exported symbol must match layerTargetFile/layerFileBaseName's derivation for its own name
TYPE-002 off An exported function's parameter and return value must each carry an explicit type annotation (no implicit any at a unit boundary)
IMPORT-001 error Relative imports must resolve to a file that exists
SLOT-001 error A generated file's slot region must match its member's stored slot body in the map
SLOT-002 error A slot body may only import types, never a value
EXCEPTION-EXPIRED warning Time-boxed exceptions must be renewed or removed once they expire
PROP-LINK info A required prop is never passed at some call site, or a call site passes an undeclared prop
PARSE-ERROR error A file must be syntactically valid TypeScript/JSX to be checked

To add a rule, see Extending Construct.