⬡ FRAMEWERK
Core

Requirements

A document carries its requirements beside the screens that answer them — what the product must do, the criteria that say it does, and links validate() checks.

View as Markdown

Requirements

Requirements say what the product must do, in the same document as the screens that answer them: each one links the screens it is about, and validate() reports a link to a screen that is not there.

Requirements are a draft part of Framewerk 1: the shape may change between minor versions until it is marked stable. Screens, components, flows and styles are stable.

Examples

A screen, and the requirement it answers:

A requirement linked to its screen
phone
SPEC.JSON
RENDERED OUTPUTFRAMEWERK RENDERER
Coffee Cart
Order
Edit the JSON to update the rendered screen.Edits stay in this preview

A capability and a task under it:

A capability and its task
phone
SPEC.JSON
RENDERED OUTPUTFRAMEWERK RENDERER
Coffee Cart
Toggle oat milk
Edit the JSON to update the rendered screen.Edits stay in this preview

Anatomy

{
  "id": "order-a-coffee",
  "title": "A customer orders a coffee from the menu",
  "type": "user-story",
  "scope": "capability",
  "source": "stakeholder",
  "priority": "P0",
  "status": "implemented",
  "linkedScreens": ["menu", "order"]
}

Seven fields are required: id, title, type, scope, source, priority and status.

Because requirements are draft, a document that states a formatVersion and carries any names them at the top level: "drafts": ["requirements"]. validate() reports an error when it does not. See The document.

Scope is the level. A capability says what the product does and never closes; a task is a piece of the work that makes a capability true, and names it in parentCapabilityId.

Status is how far the work got: proposed, accepted, in-progress, implemented, blocked, verified. Why a requirement stopped being live is a separate field, resolution: fixed, wont-fix, duplicate, cannot-reproduce, superseded. A superseded requirement may name its replacement in supersededBy.

Type is one of user-story, requirement, acceptance-criteria, bug, feedback, qa-note. Source is one of stakeholder, research, agent, audit. Priority is P0, P1 or P2. A bug may carry a severity: critical, major, minor, cosmetic.

Criteria are the acceptance checklist. Each has an id unique within its requirement, a text, and verified.

Links point into the same document:

FieldNames
linkedScreensids from screens
linkedFlowsids from flowPackages
personasids from project.personas
parentCapabilityId, supersededBythe id of another requirement

validate() reports a missing scope, a value outside a list, and a linkedScreens, linkedFlows, personas or parentCapabilityId entry that names nothing in the document, as errors. A supersededBy that names nothing is a warning.

Optional fields: feature (the area of the product), description, tags, blockerReason, refCode (a short handle people say aloud), reporter and assignee (a name to show, never an account id), and the ISO 8601 datetimes createdAt, updatedAt, startedAt and closedAt.

A tool may add its own fields to a requirement. validate() passes over fields it does not know.

The value lists are exported, so a form or a schema reads them and does not retype them:

import { REQUIREMENT_STATUSES, validate, type Requirement } from "@framewerk/spec";

What the format does not carry

A requirement in a document is a record. Everything that does work on one stays in the tool that holds the document. Airframe adds, and does not publish:

  • the account behind an assignee or reporter, the build a requirement rides, and its milestone
  • Features, test plans, the roadmap and boards
  • the agents and MCP server that write requirements, status reconciliation, alignment against code, and the test walker

Stability

Draft. Requirements are a draft part of Framewerk 1: the shape may change between minor versions until it is marked stable. Screens, components, flows and styles are stable.