Articles

EARS requirements syntax explained, with examples

EARS (Easy Approach to Requirements Syntax) is a requirements notation: a small set of English sentence patterns, also called EARS syntax, that keep a condition, a trigger, and a system response in a fixed order. A requirement is one testable obligation a system must meet. Spec-driven development (SDD) is the practice of writing that obligation into a specification before code, and treating the specification as the source of truth. A product requirements document (PRD) is the prose that states the problem and the scope before the work is split into tasks. In SpecScore, a requirement (REQ) is a named rule inside a feature, and an acceptance criterion (AC) is an optional abstract condition that points at one or more of those rules. Continuous integration (CI) is an automatic check on every proposed change. The check itself is a command-line interface (CLI) command, specscore spec lint. Kiro, an agentic integrated development environment (IDE) from Amazon Web Services (AWS), writes one of these patterns. The notation was first published by Alistair Mavin and colleagues at Rolls-Royce at an Institute of Electrical and Electronics Engineers (IEEE) Requirements Engineering conference in 2009.

Last updated: 2 November 2026

Where EARS came from

Alistair Mavin, Philip Wilkinson, Adrian Harwood, and Mark Novak, then at Rolls-Royce PLC, published “Easy Approach to Requirements Syntax (EARS)” at the 17th IEEE International Requirements Engineering Conference in 2009. The paper’s document identifier is 10.1109/RE.2009.9. They built the rules while extracting engine-control requirements from the Certification Specification for Engines (CS-E), section CS-E 50, an airworthiness regulation. That source mixed requirements, design guidance, and notes.

The paper names eight problems in unconstrained natural language: ambiguity, vagueness, complexity, omission, duplication, wordiness, inappropriate implementation, and untestability. A small ruleset was meant to let every such requirement use one of five templates. The authors say the notation suits high-level stakeholder requirements, and they do not claim it covers every level of system decomposition.

Mavin’s own guide describes EARS as a way to gently constrain textual requirements. The clauses stay in one order, following what he calls temporal logic: any precondition, then the trigger, then the system name and the response. His ruleset is zero or many preconditions, zero or one trigger, one system name, and one or many system responses. The 2009 paper specialises that shape into five templates. The same guide also names complex requirements, which combine the keywords.

In the paper’s case study, the raw extract held 36 requirements and the rewritten set held 47. Average length fell from 36.9 words to 25.6. The authors report that, in that study, complexity, omission, duplication, inappropriate implementation, and untestability were absent from the rewritten set, while ambiguity, vagueness, and wordiness were reduced and not eliminated. They also list the limits: a small sample, high-level safety requirements only, and judgment in how vagueness was classified. Those counts are the paper’s, for that one document.

The EARS sentence patterns

The keywords below are the ones in the 2009 paper and on Mavin’s guide. The paper also allows During in place of While for a state, with the same meaning, when that reads more clearly. The example sentences are illustrations of the templates. They are not quotations from the paper. Kiro writes the event-driven pattern in capitals; the original notation uses sentence case.

Ubiquitous

The <system name> shall <system response>

Always active. There is no EARS keyword, because there is no precondition and no trigger. The 2009 paper’s own illustration is a control system that shall prevent engine overspeed.

Example The checkout system shall keep the order total equal to the sum of its line items.

Event-driven

When <trigger>, the <system name> shall <system response>

The response is required when a trigger is detected at the system boundary, and only then. The keyword is When.

Example When a shopper submits the checkout form with invalid data, the checkout system shall show a validation error next to the invalid field.

State-driven

While <precondition>, the <system name> shall <system response>

The response is required for as long as the system remains in the named state. The keyword is While.

Example While the cart is empty, the checkout system shall keep the pay button disabled.

Unwanted behaviour

If <trigger>, then the <system name> shall <system response>

The response handles a failure, a disturbance, a deviation, or other unwanted behaviour. The keywords are If and then. The paper gave this pattern its own keywords so those requirements stay visible. The authors note that wanted and unwanted is sometimes a matter of viewpoint.

Example If the submitted email is not a valid address, then the checkout system shall reject the form.

Optional feature

Where <feature is included>, the <system name> shall <system response>

The response applies only when the product includes the named feature. The keyword is Where.

Example Where the shop includes gift wrapping, the checkout system shall offer gift wrapping on the order review step.

Complex

While <precondition>, when <trigger>, the <system name> shall <system response>

More than one keyword. Mavin’s guide keeps the same clause order: While for the precondition, then When for the trigger, then the system response. The 2009 paper also combines While with If / then for unwanted behaviour in a state. One illustration of that combination: While the shopper is signed out, if the shopper submits the checkout form, then the checkout system shall refuse the order.

Example While the shopper is signed in, when the shopper submits a valid checkout form, the checkout system shall place the order.

Common mistakes

Several obligations in one sentence

The paper treats a compound sentence as the complexity problem and splits it. The SpecScore requirement specification says the same thing in its own terms: each REQ must express exactly one testable obligation.

Hiding unwanted behaviour in When

When is for a trigger you expect. If / then is for the behaviour you would rather not meet. Using one keyword for both makes the unwanted case look like the normal case, which is the omission problem the paper called out.

Writing the implementation

“The checkout system shall store the flag in Redis” names a design. The paper calls that inappropriate implementation. The response should say what the system must achieve, not which component does it.

No system name

“When the form is submitted, shall show an error” has no subject. Mavin’s ruleset requires one system name.

Trigger after the response

“The checkout system shall show an error when the form is submitted” puts the trigger last. The published clause order is precondition, then trigger, then response.

Treating Kiro’s one line as all of EARS

Kiro’s feature-spec page publishes a single pattern, WHEN … THE SYSTEM SHALL …. Ubiquitous, While, If / then, Where, and complex combinations are part of the notation in the paper and on Mavin’s guide. They are not on that Kiro page.

How Kiro uses EARS

Kiro’s feature specs page, marked updated on 4 August 2026 and read on 2 November 2026, says the requirements.md file uses EARS. The pattern printed there is WHEN [condition/event] followed by THE SYSTEM SHALL [expected behavior]. The page’s example is: WHEN a user submits a form with invalid data, THE SYSTEM SHALL display validation errors next to the relevant fields.

The requirements-first page says a generated requirements.md includes user stories with acceptance criteria and system behaviors in that same WHEN … THE SYSTEM SHALL … form. Its registration example is three sentences: valid registration data creates an account, an email that already exists shows “Email already registered”, and an invalid email format shows a validation error.

Before design, Analyze Requirements looks for logical inconsistencies, ambiguities, conflicting constraints, and gaps. The feature-spec page says you select it from the chat options or the Continue dropdown in the editor after requirements are generated. design.md and tasks.md sit beside the requirements. Quick Spec runs requirements, design, and tasks without an approval stop between them.

That analysis is a step inside Kiro. The feature-spec page does not describe it as a format linter you add to your own CI. How other spec-driven tools check a specification is on the tools guide. The comparison of the two products is SpecScore vs Kiro.

The same requirement in SpecScore

SpecScore does not check that a sentence matches an EARS template. specscore spec lint, from the specscore-cli repository, checks structure. Its help text names README files, Open Questions sections, heading levels, feature references, internal links, and index entries. An EARS sentence can be the prose under a REQ heading. The linter does not grade the English.

The requirement specification places each requirement under a topic heading inside ## Behavior, one heading level down, typically #### REQ: slug. The slug uses lowercase letters, numbers, and hyphens. The identifier is {feature-path}#req:{slug}. The specification says a requirement should use RFC 2119 (Request for Comments 2119) keywords: MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY. In the mapping below, EARS shall is written as MUST.

An acceptance criterion is optional. When one is used, it is ### AC: slug inside ## Acceptance Criteria, and the next line is **Requirements:** with those identifiers. The acceptance-criteria specification says the AC states an abstract condition and must not contain Given/When/Then steps, specific inputs, or implementation detail. A concrete flow is a scenario in the feature’s _tests/ directory. The feature specification also requires a status, a summary, a problem, behavior, acceptance criteria, open questions, and an adherence footer.

The files below are one checkout feature. show-field-error is the event-driven example. reject-invalid-email is the unwanted-behaviour example. On 2 November 2026, specscore spec lint reported 0 violations for this tree with specscore 0.55.1, the latest release published on 30 October 2026, and with specscore 0.39.1, the version pinned in dogfood.yml. The format repository is where that workflow lives.

spec/features/checkout/README.md
---
format: https://specscore.md/feature-specification
status: Draft
---

# Feature: Checkout validation

> [SpecScore.**Studio**](https://specscore.studio): | [Explore](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=explore) | [Edit](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=edit) | [Ask question](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=ask) | [Request change](https://specscore.studio/app/github.com/example/checkout/spec/features/checkout?op=request-change) |

**Status:** Draft
**Source Ideas:** —

## Summary

The checkout form shows a validation error next to a field when the shopper submits invalid data, and it rejects an email that is not a valid address.

## Problem

A vague sentence such as "the form should handle bad input" does not say which event causes which response. Checkout needs those obligations written so a reviewer and a linter can point at them.

## Behavior

### Field validation

The checkout system checks the form when the shopper submits it.

#### REQ: show-field-error

When a shopper submits the checkout form with invalid data, the checkout system MUST show a validation error next to the invalid field.

#### REQ: reject-invalid-email

If the submitted email is not a valid address, then the checkout system MUST reject the form.

## Acceptance Criteria

### AC: invalid-submission

**Requirements:** checkout#req:show-field-error, checkout#req:reject-invalid-email

Submitting the checkout form with invalid data shows a validation error next to the invalid field, and an email that is not a valid address is rejected.

## Open Questions

None at this time.

---
*This document follows the https://specscore.md/feature-specification*
spec/features/README.md — the description cell is the feature’s summary sentence. The linter’s feature-index-row-sync rule rejected a shorter description.
---
format: https://specscore.md/features-index-specification
---

# Features

| Feature | Status | Description |
|---|---|---|
| [Checkout validation](checkout/README.md) | Draft | The checkout form shows a validation error next to a field when the shopper submits invalid data, and it rejects an email that is not a valid address. |

## Open Questions

None at this time.

---
*This document follows the https://specscore.md/features-index-specification*
spec/README.md — removing the Open Questions section produced oq-section: Open Questions section not found.
# Checkout specification

## Open Questions

None at this time.
specscore.yaml — project.host, project.org, and project.repo are what the studio-toolbar line is checked against. Without them the linter reported studio-toolbar: studio toolbar requires project host/org/repo.
# SpecScore Repo Config Schema: https://specscore.md/repo-config

project:
  title: Checkout sample
  host: github.com
  org: example
  repo: checkout

Two further errors showed up while this sample was being made to pass, and both are fixed in the files above. A feature without **Source Ideas:** failed feature-source-ideas-required; — is the empty value. The features index also needed the frontmatter field format: https://specscore.md/features-index-specification.

The linter’s pass means the files match those structural rules. It does not mean the sentences are good EARS, and it does not mean the checkout product exists. Given/When/Then for this behaviour would be a scenario file under spec/features/checkout/_tests/, not another paragraph inside the AC.

Questions

What does EARS stand for?

Easy Approach to Requirements Syntax. It is a set of sentence patterns for requirements, published by Alistair Mavin, Philip Wilkinson, Adrian Harwood, and Mark Novak of Rolls-Royce at the 17th IEEE International Requirements Engineering Conference in 2009, and described on Mavin’s site.

Is Kiro’s notation the whole of EARS?

Kiro’s feature-spec page specifies one pattern: WHEN … THE SYSTEM SHALL …. The 2009 paper and Mavin’s guide also define ubiquitous requirements, state-driven While, unwanted-behaviour If/then, optional-feature Where, and complex combinations of those keywords.

Does SpecScore validate EARS syntax?

No. specscore spec lint validates SpecScore file structure. An EARS sentence can be the prose of a REQ. The linter does not score the English.

Where do Given/When/Then examples go?

In a scenario under the feature’s _tests/ directory. An acceptance criterion stays an abstract condition and, in the acceptance-criteria specification, must not contain Given/When/Then steps.

Put the requirement in a file CI can reject.

Have an idea how to improve this page?