Context
ADR 0120 gave specs lanes (full, lite, bug, chore) and change risk, and ADR 0362’s plan gate refuses code on a branch until its spec is answered and planned. Every change paid the same toll: a typo fix still needed a spec folder, and nothing told a money or permission change apart from a one-package bug fix. Approvals were agreed in chat and recorded nowhere a gate could read.Decision
-
Four tiers. A spec declares
**Tier**:in its header. -
The diff sets a floor. The lane check computes a minimum tier from the changed paths: a migration, a public
contract (
src/contracts/,stackra.manifest.json,openapi.json), a permission (*.permissions.ts,access/), payment or money code (packages/commerce/, paths naming payment, money, ledger, billing, payout or refund) or a new app or Worker member forces at least feature; a new service or package forces big. A branch with no spec declares trivial. A declared tier below the computed one fails the lane check. -
Approval is recorded where the gate reads it. An approval is
Approved by <who> <YYYY-MM-DD>on the stage it approves: on the**Status**line while the spec sits there, and on that stage’s## Status historyline after. A feature spec needs its Planned approval before Tasked; a big spec needs its Clarified approval before Planned and its Planned approval before Tasked. The stage gate and the plan-gate hook check them before tasks or code. -
Who approves.
**Approver**:names it: the owner for product, money, legal, security, brand and pricing; the leader session for technical-only stops, under the owner’s delegation. Feature and big specs carry the field. - How an agent asks. At a stop the agent asks with the question tool (Approve, Revise with notes, Reject). Revise loops back to the stage with the notes; Reject sets the spec Abandoned.
-
Trivial is never blocked. The plan-gate hook lets a branch with no spec folder write code; the lane check is
what refuses a diff that needed more. A spec without
**Tier**keeps the ADR 0362 rule (answered spec and plan.md). -
Kiro depth in spec-kit’s three files. The owner compared the flow with Kiro and kept spec-kit’s spec.md,
plan.md and tasks.md at the same depth:
- spec.md carries
## Acceptance criteria, one EARS line per criterion with an id tasks and tests trace to:- **AC-001**: WHEN <event> THE <system> SHALL <response>, or theIF <condition> THEN THE …,WHILE <state> THE …,WHERE <feature> THE …andTHE <system> SHALL …forms. - plan.md is the design. It has nine sections in order: architecture overview, components and responsibilities, files and folders (the exact paths), data models and migrations, contracts (actions, queries, events, API), error handling, security and tenancy, testing strategy, and rollout; “none” fills one that does not apply. At the approval stop the agent calls it “the design” when it asks the owner.
- tasks.md stays a checklist; each task covers at least one
AC-###and names at least one file, and every criterion is covered by a task. - A small spec keeps a short form in spec.md: the criteria,
## Designwith the nine sections as###headings (a line each), and## Tasks.
**Tier**(specCheckCriteria,specCheckDesign,specCheckTraceTasks). - spec.md carries
Consequences
- Most fixes need no spec. A money, permission, migration or contract change cannot slip in as trivial: the lane check names the paths that raised the floor.
- Approvals are auditable in the spec itself; a missing one fails the gate, not a review.
- Lanes stay as the Impact answer for older specs; the tier is the field the gates read.
Enforcement
- Vellum’s
gate(@stackra/vellum/gate:checkStage,checkPlan,checkDesign,checkCriteria,checkTraceTasks, the tier, the diff floor and the approval stops) is the only home of these rules;stackra check’s spec phase callsvellum gate ciandvellum trace ci.@stackra/repo-checksholds no copy. .agents/hooks/_rules.mjsdecidePlanGate(ADR 0362), with its tests, imports@stackra/vellum/gate.
Supersedes and sources
Supersedes: none. Amends 0120 (lanes) and 0362 (the plan gate). Sources: STA-1721; owner approval 2026-10-31, relayed
by the leader session.