---
title: "The Complete Flow Law"
source: "/reference/layr-002-complete-flow"
description: "A feature is complete when the user can enter, understand, act, wait, succeed, fail, recover, and continue through the surrounding task."
---
# The Complete Flow Law

A feature is complete when the user can enter, understand, act, wait, succeed, fail, recover, and continue through the surrounding task.

> **Design the task, not the requested component.**

A frontend feature is not complete because the requested component exists.

A button can render correctly and still leave the experience unfinished. A card can look polished and still fail to support the work the user came to do. A form can submit successfully in the happy path and still collapse when validation fails, the network slows down, the user lacks permission, the server returns a conflict, or the user needs to correct a mistake.

The Complete Flow Law asks designers, frontend engineers, and coding agents to treat the **user task** as the unit of completion.

The requested interface element is only one part of that task.

A complete experience considers how the user reaches the feature, what they understand before acting, what they can do, what the system does while work is in progress, how success is communicated, what happens when something fails, how the user recovers, and where the experience goes next.

This matters especially in AI-assisted development because coding agents often optimize for the literal surface of a prompt.

A prompt such as:

> Add an invoice card.

can easily produce:

- invoice number,
- customer,
- amount,
- date,
- status,
- perhaps a menu.

The component may be correct. The task may still be incomplete.

If the existing product already allows invoices to be opened, edited, downloaded, cancelled, deleted, or otherwise acted upon, the new card lives inside that behavioral system.

The implementation question therefore changes from:

> What component was requested?

to:

> What user task does this component participate in, and what states are required for that task to actually work?

---

## Human reading layer



## Core definition

> **A feature is complete when its expected user task can be entered, understood, performed, interrupted, corrected, recovered from, and finished across the states that reasonably belong to the product.**

This does not mean every feature must anticipate every theoretical edge case.

It means the implementation should cover the **expected state space** of the task.

That commonly includes:

- entry,
- discovery,
- ready state,
- input,
- loading or pending,
- success,
- expected failure,
- recovery,
- cancellation when relevant,
- continuation after completion.

Higher-consequence actions such as deletion, payment, account changes, and irreversible operations generally need stronger completeness.

---

## Why this matters

Incomplete flows create iteration debt.

A developer or agent implements the visible request. A reviewer clicks it and asks what happens next. Another iteration adds the action. Then someone notices there is no loading state. Another iteration adds loading. Then a failed request leaves stale UI. Another iteration adds error handling. Then mobile has nowhere to place the actions. Another iteration creates an overflow menu. Then deletion has no confirmation or undo path. Another iteration fixes that.

The work was not necessarily large. It became expensive because the task was discovered one missing state at a time.

Without Complete Flow:

```text
component
→ review
→ missing action
→ review
→ missing loading
→ review
→ missing failure
→ review
→ missing recovery
```

With Complete Flow:

```text
user goal
→ task
→ flow
→ states
→ exceptions
→ implementation
→ review
```

Iteration still exists. Avoidable iteration is reduced.

---

## The unit of design is the task

A component is an implementation boundary.

It is often a poor product boundary.

Consider:

```text
┌─────────────────────────────────────┐
│ INV-1042                 Paid       │
│ Acme Manufacturing                  │
│ $8,420.00 · Sep 18, 2026            │
└─────────────────────────────────────┘
```

A component review asks:

- Is spacing correct?
- Is typography correct?
- Is status styled correctly?
- Does it fit on mobile?

A task review also asks:

- What happens when the card is activated?
- What actions already exist for invoices?
- Are actions permission-aware?
- What happens while data loads?
- What if the invoice disappears?
- What happens while edit/delete/download is pending?
- Is success observable?
- What if the request fails?
- Can the user retry?
- Is previous work preserved?
- Are keyboard users able to reach the same task?
- Where does the user end up after completion?

Those questions describe the experience.

That experience is the feature.

---

## The Complete Flow Model

Nine stages carry a task from the moment the user arrives to the moment they move on. A feature is complete when every stage its path reaches has been designed.

Layr evaluates an interactive feature through nine dimensions:

```text
1. ENTRY
2. DISCOVERY
3. ACTION
4. INPUT
5. SYSTEM STATE
6. OUTCOME
7. FAILURE
8. RECOVERY
9. CONTINUATION
```

A context layer modifies them:

```text
permissions
responsive behavior
accessibility
empty state
first use
long content
large data
concurrency
offline/degraded network
destructive consequence
```

---

## 1. Entry

How does the user reach the feature?

Inspect:

- route,
- parent screen,
- deep link,
- list/card,
- search result,
- notification,
- command,
- contextual action.

Questions:

- Is the entry point discoverable?
- Does it match existing product patterns?
- Can the user return?
- Does a deep link work?
- What happens if the target no longer exists?

---

## 2. Discovery

Can the user understand what can be done?

Inspect:

- primary action,
- secondary actions,
- hierarchy,
- labels,
- disabled actions,
- destructive actions,
- menus,
- affordances.

The interface should expose behavior without overexplaining obvious controls.

A capability that technically exists but is practically undiscoverable is still an incomplete experience.

---

## 3. Action

What actions actually belong to this object or state?

The agent should derive them from:

1. explicit requirements,
2. existing routes,
3. existing APIs,
4. neighboring interfaces,
5. types/state machines,
6. tests,
7. established product conventions.

Do not create actions solely because they are common in the industry.

---

## 4. Input

What information must the user provide?

Inspect:

- required fields,
- optional fields,
- defaults,
- validation,
- server validation,
- formats,
- file limits,
- accessible labels,
- submit availability,
- draft preservation.

A failed request should not unnecessarily erase valid user work.

---

## 5. System State

What is the system doing after the action begins?

Common states:

- idle,
- loading,
- pending,
- uploading,
- processing,
- queued,
- retrying,
- synchronizing,
- completed.

The UI may need:

- duplicate-submit prevention,
- optimistic state,
- progress,
- cancellation,
- re-entry,
- stale-data handling.

The correct behavior depends on task duration and consequence.

---

## 6. Outcome

How does the user know the task worked?

Success might be communicated through:

- changed data,
- new object appearing,
- status update,
- route transition,
- inline feedback,
- persistent result,
- transient status.

Do not add a toast after every action by default.

The requirement is that the successful outcome is understandable.

---

## 7. Failure

What expected failures belong to the task?

Examples:

- validation,
- transport/network,
- permission,
- expired authentication,
- conflict,
- stale record,
- missing resource,
- rate limit,
- invalid file,
- external dependency,
- partial batch failure.

The UI should distinguish failures that require different user responses.

---

## 8. Recovery

What can the user do after failure or mistake?

Possible recovery:

- retry,
- edit,
- undo,
- restore,
- reconnect,
- refresh,
- request access,
- resolve conflict,
- retry failed subset,
- return safely.

An error message is not always a recovery path.

---

## 9. Continuation

What happens after completion?

Inspect:

- focus,
- route,
- selected item,
- scroll position,
- filters,
- refreshed data,
- next action,
- back navigation.

A mutation can succeed technically and still disorient the user.

---

## Context changes the flow

The nine stages are not fixed. A context layer decides which of them a task can reach at all, and a flow that is complete for one user can be unreachable for another.

## Permissions

Do not show actions that will always fail unless exposing the restriction itself has value.

Use the product's established permission model.

---

## Responsive behavior

Responsive completeness means the task remains available.

A desktop action row may become an overflow menu on mobile.

Do not hide necessary actions merely to make a layout fit.

---

## Accessibility

The flow should remain operable through:

- keyboard,
- visible focus,
- programmatic labels,
- semantic controls,
- appropriate status feedback,
- assistive technology.

Accessibility belongs to completion, not a future polishing pass.

---

## Empty states

Different empty states can represent different tasks:

```text
No invoices exist.
```

```text
No invoices match filters.
```

```text
Invoices could not be loaded.
```

They require different next steps.

---

## Long and unusual content

Test realistic extremes:

- long names,
- large currency values,
- missing optional fields,
- long localization strings,
- many tags,
- long tables.

Do not design only against ideal mock fixtures.

---

## Concurrency

Collaborative products may need to handle:

- stale data,
- edits by another user,
- deleted records,
- changed statuses,
- conflicts.

Only implement this when the product architecture supports such states.

---

## Completeness is not feature creep

Completing a task is not the same as inventing product scope. Three levels separate the work that belongs to the request from the work that belongs to a product decision.

This distinction is foundational.

Layr separates three levels.

## Level A — Interaction completeness

Behavior required to make an already-supported action correct.

Example:

```text
Delete
→ safety strategy
→ pending
→ success
→ failure
→ recovery
```

Usually implement.

---

## Level B — Product inference

Capabilities already established elsewhere.

Example:

The existing invoice detail screen already supports:

```text
Edit
Download
Delete
```

A new card may need to preserve those capabilities.

Reuse established behavior.

---

## Level C — New product scope

New capability or business rule.

Examples:

```text
Refund
Duplicate
WhatsApp
Reminder automation
AI summary
Recurring invoice conversion
```

Do not implement without explicit product evidence or approval.

---

## The implied-completeness test

Before adding behavior, ask:

1. Is this required for an existing action to work correctly?
2. Does the product already contain this behavior?
3. Is it supported by routes, APIs, types, tests, or established patterns?
4. Would omitting it leave the task broken, ambiguous, unsafe, or unrecoverable?
5. Would adding it create a new capability or business rule?

If #5 is yes, it is probably new product scope.

---

## Worked flow examples

Four tasks, each traced from the requested surface to the states a real path reaches.

## Example — Invoice card

Prompt:

> Add invoice cards to the billing page.

Repository already contains:

```text
/invoices/:id
/invoices/:id/edit
downloadInvoice()
deleteInvoice()
```

Existing table exposes:

```text
Open
Edit
Download
Delete
```

A complete interpretation considers:

```text
ENTRY
Billing page

DISCOVERY
Card clearly opens invoice
Secondary actions follow existing pattern

ACTION
Open
Edit
Download
Delete

SYSTEM STATE
Collection loading
Delete pending
Download pending if needed

OUTCOME
Edited invoice updates
Deleted invoice disappears
Download behavior is clear

FAILURE
Load failure
Edit/save failure
Delete failure
Download failure

RECOVERY
Retry
Preserve invoice when delete fails

CONTINUATION
Return to billing context
Preserve useful filters/position

CONTEXT
Mobile
Keyboard
Permissions
Long customer names
```

No new invoice capability was invented.

---

## Example — Destructive action

A delete button alone is not a complete destructive flow.

Weak:

```text
[ Delete ]
```

Then immediately:

```text
DELETE /api/invoices/1042
```

Complete Flow asks:

- Is deletion reversible?
- How severe is the consequence?
- Is confirmation appropriate?
- Would undo be better?
- What happens while pending?
- What happens if it fails?
- Is optimistic removal safe?

Low-cost reversible action:

```text
Delete
→ remove
→ Undo
```

High-cost irreversible action:

```text
Delete
→ clear confirmation
→ pending
→ success
```

No universal modal requirement exists.

The law requires a deliberate safety-and-recovery strategy.

---

## Example — Edit form

Weak:

```text
Edit
→ form
→ Save
→ API
```

Complete:

```text
entry
→ populated form
→ validation
→ pending
→ success
```

Failure:

```text
server/network failure
→ preserve values
→ explain problem
→ retry
```

Cancel:

```text
return without mutation
```

Unsaved-change warning should exist only when losing the work is meaningful.

---

## Example — Long-running import

Literal implementation:

```text
Upload CSV
[ Import ]
```

then:

```text
Importing...
```

Complete flow may require:

```text
select
→ validate
→ upload
→ accepted
→ processing
→ progress
→ partial failure
→ completion
→ result summary
→ retry failed items
→ re-entry after navigation
```

For long work, loading is not a spinner problem.

It is a workflow problem.

---

## State completeness

Not every component needs every state. It needs the states its own task can reach, which is a shorter and more specific list.

A useful candidate-state set:

```text
initial
loading
empty
ready
pending
success
error
disabled
partial success
permission denied
conflict/stale
```

Not every component needs every state.

Ask:

> Which of these states can actually occur in this task?

Then design those.

---

## Feedback loops

Every meaningful action creates a loop:

```text
intent
↓
action
↓
system receives action
↓
system changes
↓
user perceives result
```

The loop is incomplete when the user cannot tell what happened.

Examples:

- save succeeds but UI never updates,
- upload completes but file never appears,
- deletion succeeds but row remains,
- background job finishes invisibly.

---

## Failure loops

Failure creates:

```text
action
↓
failure
↓
explanation
↓
recovery
↓
retry or safe exit
```

An error banner may explain failure but still leave the user stranded.

---

## Partial success

Batch work may produce:

```text
100 requested
94 succeeded
6 failed
```

Do not label that simply "success" or "failure."

A complete flow may need:

```text
94 completed
6 failed

Review failures
Retry failed
```

depending on task scale.

---

## Interruption and re-entry

Users leave.

Connections fail.

Long tasks continue.

For significant-duration work ask:

- Can the user navigate away?
- Does work continue?
- Is status persisted?
- Can they return?
- Is completion discoverable?
- Can failure be revisited?

Not every short mutation needs this.

Long-running workflows often do.

---

## The completion envelope

Use three boundaries.

## Minimum complete

The minimum required for correct interaction.

```text
input
validation
pending
success
failure
preservation/recovery
```

## Product-complete

Adds behavior clearly established by the product.

```text
permissions
navigation conventions
existing actions
existing feedback patterns
```

## Extended scope

Adds a new capability.

Requires explicit product approval.

---

## Anti-patterns

Four shapes a surface-only implementation takes. Each is a decision the flow never made.

## Anti-pattern — Screenshot-complete

A screenshot-complete feature often has:

- polished default state,
- no loading state,
- no failure path,
- mock data only,
- actions without behavior,
- no mobile action strategy,
- forms that only accept perfect input,
- no permission behavior,
- no rollback.

It looks complete.

The task is incomplete.

---

## Anti-pattern — Speculative completeness

Prompt:

> Add invoice card.

Agent adds:

- refunds,
- reminders,
- sharing,
- duplication,
- AI summary.

This is not Complete Flow.

The law requires depth across the task, not breadth of speculation.

---

## Anti-pattern — Modal by default

Do not map:

```text
danger
→ confirmation modal
```

automatically.

Consider:

- undo,
- inline confirmation,
- typed confirmation,
- permission restriction,
- no confirmation.

Consequence and reversibility determine the strategy.

---

## Anti-pattern — Toast by default

A toast is not universal completion feedback.

Avoid relying on transient feedback when:

- the result must remain visible,
- the user needs recovery actions,
- a field has an error,
- consequence is high,
- the workflow continues.

---

## Agent execution layer

How an agent applies this law: the order of reasoning, the evidence that supports a finding, the scope boundary that stops one, and the exact shape a report has to emit.

## Agent directive

When implementing an interactive frontend feature:

1. Identify the user task.
2. Inspect existing product capabilities.
3. Map expected flow states.
4. Implement implied completeness.
5. Preserve established conventions.
6. Surface expected failures.
7. Provide recovery where necessary.
8. Preserve user work where feasible.
9. Verify responsive and accessible operation.
10. Stop before introducing new product scope.

---

## Severity



## Low

Flow works but continuity or feedback is weaker than it should be.

## Medium

A common path becomes confusing, inefficient, or unrecoverable.

## High

The flow can cause:

- data loss,
- unsafe action,
- blocked task,
- misleading state,
- duplicate transaction,
- inaccessible critical behavior.

---

## Confidence



## High

Repository/runtime clearly proves the missing state.

## Medium

Product patterns strongly suggest it.

## Low

Reviewer is guessing that a feature might be useful.

Low-confidence product ideas are questions, not findings.

---

## Review directive

Do not ask:

> Does every component have every possible state?

Ask:

> Which states can occur in this task, and are the important ones designed?

A strong finding contains:

```text
observable evidence
+
task context
+
missing state
+
user consequence
+
specific correction
```

---

## Human checklist

Before calling a feature complete:

- Can the user get into the task?
- Can they tell what can be done?
- Can they perform the action?
- Is required input understandable?
- Is pending work visible?
- Is success observable?
- Are expected failures represented?
- Is recovery possible where necessary?
- Does the user remain oriented afterward?
- Does it work on mobile?
- Does it work by keyboard?
- Are permissions respected?
- Is user work preserved on failure?
- Did we avoid adding unsupported capability?

---

---

## Required behavior

- Identify the user task the requested surface belongs to, not only the surface named in the prompt.
- Inspect the repository for states the product already implements, and reuse those conventions rather than inventing new ones.
- Map the nine flow stages against the implementation and record which stages a real path reaches.
- Report a missing state only when a real path reaches it; name the path in the finding.
- Name the user consequence of the missing state, not the omission alone.
- Propose the smallest correction that completes the task, reusing existing components.
- Classify every addition as interaction completeness, existing product capability, or new product scope.
- Stop at the scope boundary: raise new product scope as a question, never as a finding.

## Prohibited agent behavior

- Do not require every component to implement every conceivable state.
- Do not invent product capability the repository does not support.
- Do not report a missing state without naming the path that reaches it.
- Do not treat a design choice you would have made differently as an incomplete flow.
- Do not replace an established product pattern with a generic one while adding a state.
- Do not report speculative features as findings; they are questions.

## Evidence hierarchy



### High-confidence evidence

- A mutation with no pending state in the component that triggers it.
- A form that discards user input when the request fails.
- A destructive action with no confirmation and no undo.
- An error branch that renders nothing the user can read.
- A route that can be reached with no data and renders no empty state.

### Medium-confidence evidence

- A flow whose success is announced only by a transient toast the user can miss.
- A long-running action with a pending state but no progress or cancel path.
- A list that handles loading and success but not partial failure.
- An entry point that exists in one surface and is missing from the equivalent one.

### Low-confidence evidence

- A feature you believe users would want that the product does not offer.
- A state that no observed path reaches.
- A preference for a different interaction pattern with equivalent completeness.

## Finding contract

```yaml
finding:
  rule_id: LAYR-002
  title: string

  task: string
  surface: string
  location: string

  stage:
    - entry
    - discovery
    - action
    - input
    - system-state
    - outcome
    - failure
    - recovery
    - continuation

  evidence:
    observable:
      - string
    path: string

  missing_state: string
  consequence: string

  correction:
    change: string
    reuses: string | null

  scope:
    level: interaction-completeness | existing-product-capability | new-product-scope
    within_boundary: true | false

  severity: low | medium | high
  confidence: low | medium | high
```

## Worked findings



### Finding A: a failed save discards the user's edits

```yaml
finding:
  rule_id: LAYR-002
  title: Failed save discards the user's edits
  task: Correct a customer address before invoicing
  surface: EditCustomerForm
  location: components/customer/edit-form.tsx
  stage:
    - failure
    - recovery
  evidence:
    observable:
      - The mutation's catch branch calls reset() on the form.
      - No error is rendered next to any field.
    path: Submit with a server-side validation error on postcode.
  missing_state: A failure state that keeps the entered values and names the rejected field.
  consequence: The user retypes the whole form and cannot tell which value was rejected.
  correction:
    change: Keep form state on error and render the field-level message the API already returns.
    reuses: FieldError, already used by the billing form.
  scope:
    level: interaction-completeness
    within_boundary: true
  severity: high
  confidence: high
```

### Finding B: a long import reports no progress

```yaml
finding:
  rule_id: LAYR-002
  title: Import runs with no progress and no way out
  task: Import a contacts CSV
  surface: ImportDialog
  location: components/import/import-dialog.tsx
  stage:
    - system-state
    - continuation
  evidence:
    observable:
      - The dialog renders a spinner for the whole upload.
      - The job endpoint returns processed and total counts that the UI never reads.
    path: Import a file large enough to take more than a few seconds.
  missing_state: Determinate progress, and a path that survives closing the dialog.
  consequence: The user cannot tell whether the import is advancing or stalled, and closing the dialog appears to lose the job.
  correction:
    change: Render the counts the endpoint already returns and keep the job resumable from the imports list.
    reuses: ProgressMeter, already used by the export flow.
  scope:
    level: interaction-completeness
    within_boundary: true
  severity: medium
  confidence: high
```

### Finding C: a missing capability that is not a finding

```yaml
finding: null
reason: >
  The reviewer expected bulk editing from the invoice list. The product has no
  bulk mutation anywhere, and no path in this task reaches a bulk state. This is
  new product scope, so it is raised as a question rather than reported as an
  incomplete flow.
question: Should the invoice list support bulk actions? No existing surface implies it.
scope:
  level: new-product-scope
  within_boundary: false
```

## Agent routing hints

Route to this rule when the work adds or reviews an interactive surface: a form, a mutation, a destructive action, an upload, a long-running job, or any control that changes server state. Route to LAYR-001 instead when the question is whether an element should exist at all.

---

## Before and after

Each pair is one task, written twice: the surface the prompt asked for, and the flow the task actually needs.

## Deleting a record



### Surface-only

```text
[ Delete ]  →  row disappears
```

### Complete flow

```text
[ Delete ]
  → confirmation naming the record and what is lost
  → pending state on the button, list still readable
  → row removed, undo offered for a bounded window
  → failure: row stays, reason shown, action still available
```

## Saving a form



### Surface-only

```text
[ Save ]  →  toast: "Saved"
```

### Complete flow

```text
[ Save ]
  → submit disabled while pending, values preserved
  → success: the record reflects the new values in place
  → failure: field-level messages, nothing retyped
  → the user stays where the next step happens
```

## Uploading a file



### Surface-only

```text
[ Choose file ]  →  spinner  →  done
```

### Complete flow

```text
[ Choose file ]
  → accepted types and size stated before the choice
  → determinate progress, cancel available
  → rejected file: reason and the same control ready to retry
  → partial success: what landed, what did not, what to do
```

---

## Research foundation

The Complete Flow Law is a Layr synthesis. It restates no single source; it draws the task-as-unit-of-completion idea from task analysis and use-case modelling, and grounds the failure, status and recovery stages in accessibility success criteria.

## Task and flow analysis

- [Nielsen Norman Group — Task Analysis: Support Users in Achieving Their Goals](https://www.nngroup.com/articles/task-analysis/)
- [Nielsen Norman Group — User Journeys vs. User Flows](https://www.nngroup.com/articles/user-journeys-vs-user-flows/)
- [Alistair Cockburn — Writing Effective Use Cases](https://people.inf.elte.hu/molnarba/Informaciorendszerek_ELTE/Writing_effective_Use_cases_Cockburn.pdf)

## Accessibility criteria for the failure and state stages

- [W3C — Understanding WCAG 2.2, SC 3.3.1: Error Identification](https://www.w3.org/WAI/WCAG22/Understanding/error-identification)
- [W3C — Understanding WCAG 2.2, SC 3.3.6: Error Prevention (All)](https://www.w3.org/WAI/WCAG22/Understanding/error-prevention-all)
- [W3C — Understanding WCAG 2.2, SC 4.1.3: Status Messages](https://www.w3.org/WAI/WCAG22/Understanding/status-messages)
- [W3C — Web Content Accessibility Guidelines 2.2](https://www.w3.org/TR/WCAG22/)

## Agent guidance

Review criteria, the finding contract a report must use, and worked examples.

Original Layr principle. Category: Layr Principles.

## Retrieve
- Canonical page: https://layr.design/reference/layr-002-complete-flow
- Markdown for agents: https://layr.design/__layr/pages/reference/layr-002-complete-flow.md
- Reference map: https://layr.design/llms.txt
- Route index: https://layr.design/__layr/routes.toon

## Rule object
```yaml
rule:
  id: "LAYR-002"
  title: "The Complete Flow Law"
  category: "Layr Principles"
  origin: layr-original
  canonical_url: "https://layr.design/reference/layr-002-complete-flow"
  principle: "Design the task, not the requested component."
  directive: "When implementing an interactive frontend feature: 1. Identify the user task. 2. Inspect existing product capabilities. 3. Map expected flow states. 4. Implement implied completeness. 5. Preserve established conventions. 6. Surface expected failures. 7. Provide recovery where necessary. 8. Preserve user work where feasible. 9. Verify responsive and accessible operation. 10. Stop before introducing new product scope. ---"
  applies_when: []
  observable_signals: []
  audit_questions:
    - "The implied-completeness test: Before adding behavior, ask:"
  recommended_actions:
    - "Identify the user task the requested surface belongs to, not only the surface named in the prompt."
    - "Inspect the repository for states the product already implements, and reuse those conventions rather than inventing new ones."
    - "Map the nine flow stages against the implementation and record which stages a real path reaches."
    - "Report a missing state only when a real path reaches it; name the path in the finding."
    - "Name the user consequence of the missing state, not the omission alone."
    - "Propose the smallest correction that completes the task, reusing existing components."
    - "Classify every addition as interaction completeness, existing product capability, or new product scope."
    - "Stop at the scope boundary: raise new product scope as a question, never as a finding."
  avoid_when:
    - "Do not require every component to implement every conceivable state."
    - "Do not invent product capability the repository does not support."
    - "Do not report a missing state without naming the path that reaches it."
    - "Do not treat a design choice you would have made differently as an incomplete flow."
    - "Do not replace an established product pattern with a generic one while adding a state."
    - "Do not report speculative features as findings; they are questions."
  common_failure_patterns: []
```

## Routing
Route to this rule when the work adds or reviews an interactive surface: a form, a mutation, a destructive action, an upload, a long-running job, or any control that changes server state. Route to LAYR-001 instead when the question is whether an element should exist at all. ---

## Review procedure
For every finding:
1. Identify the user task the requested surface belongs to, not only the surface named in the prompt.
2. Inspect the repository for states the product already implements, and reuse those conventions rather than inventing new ones.
3. Map the nine flow stages against the implementation and record which stages a real path reaches.
4. Report a missing state only when a real path reaches it; name the path in the finding.
5. Name the user consequence of the missing state, not the omission alone.
6. Propose the smallest correction that completes the task, reusing existing components.
7. Classify every addition as interaction completeness, existing product capability, or new product scope.
8. Stop at the scope boundary: raise new product scope as a question, never as a finding.

## Prohibited
- Do not require every component to implement every conceivable state.
- Do not invent product capability the repository does not support.
- Do not report a missing state without naming the path that reaches it.
- Do not treat a design choice you would have made differently as an incomplete flow.
- Do not replace an established product pattern with a generic one while adding a state.
- Do not report speculative features as findings; they are questions.

## Evidence hierarchy
high-confidence:
- A mutation with no pending state in the component that triggers it.
- A form that discards user input when the request fails.
- A destructive action with no confirmation and no undo.
- An error branch that renders nothing the user can read.
- A route that can be reached with no data and renders no empty state.

medium-confidence:
- A flow whose success is announced only by a transient toast the user can miss.
- A long-running action with a pending state but no progress or cancel path.
- A list that handles loading and success but not partial failure.
- An entry point that exists in one surface and is missing from the equivalent one.

low-confidence:
- A feature you believe users would want that the product does not offer.
- A state that no observed path reaches.
- A preference for a different interaction pattern with equivalent completeness.

## Finding contract — emit exactly this shape
```yaml
finding:
  rule_id: LAYR-002
  title: string

  task: string
  surface: string
  location: string

  stage:
    - entry
    - discovery
    - action
    - input
    - system-state
    - outcome
    - failure
    - recovery
    - continuation

  evidence:
    observable:
      - string
    path: string

  missing_state: string
  consequence: string

  correction:
    change: string
    reuses: string | null

  scope:
    level: interaction-completeness | existing-product-capability | new-product-scope
    within_boundary: true | false

  severity: low | medium | high
  confidence: low | medium | high
```

## Worked examples
### Finding A: a failed save discards the user's edits
```yaml
finding:
  rule_id: LAYR-002
  title: Failed save discards the user's edits
  task: Correct a customer address before invoicing
  surface: EditCustomerForm
  location: components/customer/edit-form.tsx
  stage:
    - failure
    - recovery
  evidence:
    observable:
      - The mutation's catch branch calls reset() on the form.
      - No error is rendered next to any field.
    path: Submit with a server-side validation error on postcode.
  missing_state: A failure state that keeps the entered values and names the rejected field.
  consequence: The user retypes the whole form and cannot tell which value was rejected.
  correction:
    change: Keep form state on error and render the field-level message the API already returns.
    reuses: FieldError, already used by the billing form.
  scope:
    level: interaction-completeness
    within_boundary: true
  severity: high
  confidence: high
```

### Finding B: a long import reports no progress
```yaml
finding:
  rule_id: LAYR-002
  title: Import runs with no progress and no way out
  task: Import a contacts CSV
  surface: ImportDialog
  location: components/import/import-dialog.tsx
  stage:
    - system-state
    - continuation
  evidence:
    observable:
      - The dialog renders a spinner for the whole upload.
      - The job endpoint returns processed and total counts that the UI never reads.
    path: Import a file large enough to take more than a few seconds.
  missing_state: Determinate progress, and a path that survives closing the dialog.
  consequence: The user cannot tell whether the import is advancing or stalled, and closing the dialog appears to lose the job.
  correction:
    change: Render the counts the endpoint already returns and keep the job resumable from the imports list.
    reuses: ProgressMeter, already used by the export flow.
  scope:
    level: interaction-completeness
    within_boundary: true
  severity: medium
  confidence: high
```

### Finding C: a missing capability that is not a finding
```yaml
finding: null
reason: >
  The reviewer expected bulk editing from the invoice list. The product has no
  bulk mutation anywhere, and no path in this task reaches a bulk state. This is
  new product scope, so it is raised as a question rather than reported as an
  incomplete flow.
question: Should the invoice list support bulk actions? No existing surface implies it.
scope:
  level: new-product-scope
  within_boundary: false
```

## Before and after
### Deleting a record
```text
# before
[ Delete ]  →  row disappears
```
```text
# after
[ Delete ]
  → confirmation naming the record and what is lost
  → pending state on the button, list still readable
  → row removed, undo offered for a bounded window
  → failure: row stays, reason shown, action still available
```

### Saving a form
```text
# before
[ Save ]  →  toast: "Saved"
```
```text
# after
[ Save ]
  → submit disabled while pending, values preserved
  → success: the record reflects the new values in place
  → failure: field-level messages, nothing retyped
  → the user stays where the next step happens
```

### Uploading a file
```text
# before
[ Choose file ]  →  spinner  →  done
```
```text
# after
[ Choose file ]
  → accepted types and size stated before the choice
  → determinate progress, cancel available
  → rejected file: reason and the same control ready to retry
  → partial success: what landed, what did not, what to do
```

## Reporting rules
- Report only what the interface shows as observable evidence; phrase psychological or motivational effects as possible consequences.
- Returning no finding is a valid result when evidence is insufficient.
