Skip to main content
Accepted (STA-1721); the owner approved it on 2026-10-31. Amends 0120 (lanes) and 0362 (the plan gate).

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

  1. Four tiers. A spec declares **Tier**: in its header.
  2. 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.
  3. 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 history line 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.
  4. 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.
  5. 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.
  6. 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).
  7. 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 the IF <condition> THEN THE …, WHILE <state> THE …, WHERE <feature> THE … and THE <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, ## Design with the nine sections as ### headings (a line each), and ## Tasks.
    The stage gate checks each part for a spec with a **Tier** (specCheckCriteria, specCheckDesign, specCheckTraceTasks).

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 calls vellum gate ci and vellum trace ci. @stackra/repo-checks holds no copy.
  • .agents/hooks/_rules.mjs decidePlanGate (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.