State Transitions
Valid states and the named transitions that move a system between them.
22 items in this guidance cluster.
Tagged guidance
Guide item
Boundary rules
Avoid Global Mutable StateBOUNDARY-AVOID-GLOBAL-MUTABLE-STATEKeep shared process state behind explicit owners, handles, synchronization, and reset policy. This preserves test isolation and lifecycle reasoning while still allowing deliberate globals such as caches or registries when their contract is visible.Choose Resource Identity ModelBOUNDARY-CHOOSE-RESOURCE-IDENTITY-MODELDecide whether the boundary mutates records, sets, files, sessions, handles, or whole documents before designing reconciliation. The chosen unit controls idempotency, matching, conflict handling, and the cost of later migration.Define Compaction InvariantsBOUNDARY-DEFINE-COMPACTION-INVARIANTSState the budget and cut-point rules before deleting, summarizing, or moving context. Explicit invariants make compaction reviewable and reduce the risk that later work treats lossy or nondeterministic summaries as authoritative.Expose Partial Stream OutputBOUNDARY-EXPOSE-PARTIAL-STREAM-OUTPUTSurface streaming tokens, chunks, or events as provisional output until completion promotes a final result. Callers get progress and diagnostics without corrupting authoritative state with partial provider data.Identify Anemic State MachinesBOUNDARY-IDENTIFY-ANEMIC-STATE-MACHINESReplace scattered booleans and conditionals with named states and transitions when lifecycle behavior is already complex. The move exposes illegal transitions and missing recovery paths without over-formalizing simple linear code.Keep One Authoritative Owner Per FactBOUNDARY-KEEP-ONE-AUTHORITATIVE-OWNER-PER-FACTGive each state fact one definite authority and derive other views from it where practical. Cached, persisted, or adapter-specific projections may duplicate a fact only when their source and invalidation or reconciliation contract are explicit.Make Dynamic Conflicts DeterministicBOUNDARY-MAKE-DYNAMIC-CONFLICTS-DETERMINISTICDefine stable ordering, duplicate handling, priority, or override policy for dynamic registrations. Deterministic conflict behavior prevents hash order or load timing from changing which plugin, guest, generated item, or handler wins.Name Lifecycle TransitionsBOUNDARY-NAME-LIFECYCLE-TRANSITIONSModel creation, activation, cancellation, teardown, reload, and promotion as named operations when they carry different invariants. This keeps ordering, cleanup, retry, and recovery rules visible without adding ceremony to simple constructed values.Read Normalize Compare MutateBOUNDARY-READ-NORMALIZE-COMPARE-MUTATEReconcile external state by reading the current provider view, normalizing it, comparing intent, and mutating only the real difference. The loop avoids destructive or noisy writes when formatting, defaults, ordering, or outside actors create drift.Separate UI And App StateBOUNDARY-SEPARATE-UI-AND-APP-STATEKeep selection, focus, scroll, expansion, and transient input mode separate from application-owned data when they change under different rules. The separation prevents rendering concerns from mutating domain state while allowing tiny tools to stay simple until friction appears.
Observability rules
Distinguish Failure StatesOBSERVABILITY-DISTINGUISH-FAILURE-STATESPreserve status distinctions that change recovery, messaging, metrics, or debugging. Collapsing timeouts, denials, aborts, partial work, and failures makes callers guess.Surface Durable FailuresOBSERVABILITY-SURFACE-DURABLE-FAILURESGive persistent failures a stable status, error surface, or retry path instead of only an ephemeral UI log. Users and maintainers need something actionable after the moment passes.
Rust rules
Preserve Valid State On FailureRUST-PRESERVE-VALID-STATE-ON-FAILUREKeep values valid when fallible operations return errors so callers can retry, inspect, or drop them predictably. Use transactional updates or staging when partial mutation would expose a broken state.Validate Builders On BuildRUST-VALIDATE-BUILDERS-ON-BUILDValidate cross-field builder invariants in build where partial configuration becomes a usable value. Keep build infallible only when defaults and setters make invalid states impossible.
Testing rules
Cover Async Routing Edge CasesTEST-COVER-ASYNC-ROUTING-EDGE-CASESTest late replies, unrelated input, timeouts, and unmatched async responses. These cases protect request correlation and cleanup without relying on wall-clock luck.Fuzz Parsers, Formatters, and State MachinesTEST-FUZZ-PARSERS-FORMATTERS-AND-STATE-MACHINESUse fuzzing or property tests for input-heavy parsers, formatters, and state machines. Large input spaces hide failures, so keep long fuzzing outside PR gates unless it is stable.
Pattern items
Make Invalid States Hard To Expressmake-invalid-states-hard-to-expressRepeated validation spreads invariants across callers and lets unchecked values travel too far. Move the rule into a construction boundary or precise type when that reduces downstream reasoning without adding local ceremony.Make Runtime State Agent Legiblemake-runtime-state-agent-legibleAgents can only validate behavior reliably when the relevant runtime state is observable through their tools. Expose the smallest useful signal first, such as app boot, UI inspection, logs, metrics, screenshots, traces, or generated artifacts.Make State Transitions Explicitmake-state-transitions-explicitLifecycle rules become fragile when status fields, timestamps, events, and validation checks are coordinated by hand. Give meaningful transitions a named owner that holds the preconditions, state update, event, and error behavior together.
Principle items
Avoid Global Mutable Stateavoid-global-mutable-stateMutable process-wide state hides ownership, lifecycle, reset, ordering, and concurrency policy. Prefer explicit owners or narrow handles unless the global behavior has a documented policy.Explicit Boundaries Preserve Correctnessexplicit-boundaries-preserve-correctnessMove uncertainty into named boundary policy before core logic uses the data. Parsed inputs, explicit side effects, and visible lifecycle transitions reduce repeated downstream guessing.