Spec Schema
Flow-Next specs follow the template in plugins/flow-next/templates/spec.md.
Required sections
Section titled “Required sections”- Goal and context
- Architecture and data models
- API contracts
- Edge cases and constraints
- Acceptance Criteria
- Boundaries
- Decision context
Recommended shape
Section titled “Recommended shape”---id: fn-12-add-pr-cognitive-aidtitle: Add PR cognitive aid generation---
## Goal and Context
## Architecture and Data Models
## API Contracts
## Edge Cases and Constraints
## Acceptance Criteria
**R1:** ...**R2:** ...
## Boundaries
## Decision ContextThe exact template in the Flow-Next repository is the source of truth. This page explains how to think about the sections when writing or reviewing.
Auxiliary sections are written only when they apply - ## Strategy Alignment and ## Strategy Conflicts when STRATEGY.md has content, ## Glossary Conflicts on a doc-aware vocabulary mismatch, ## Conversation Evidence from capture, ## Resolved via Codebase / ## Resolved via Project Docs from interview, and ## Parked unknowns for genuinely-unknown items. Park an item only when it fails the fog-or-ticket test: decidable now means decide it, schedulable means make it a task, and only true fog gets parked. Parked items graduate into the real sections as interview or plan resolves them, so the section empties as the spec matures.
Spec and task ids
Section titled “Spec and task ids”A spec is referenced by one of two id schemes. fn-NN is the most common form in these docs, but it is not the only form - a spec linked to a tracker is referenced by its tracker key instead.
| Flow-first (the default) | Tracker-first | |
|---|---|---|
| canonical spec id | fn-NN-slug | wor-17-slug |
| canonical task ids | fn-NN-slug.M | wor-17-slug.M |
| branch | fn-NN-slug | wor-17-slug |
| bare aliases that resolve | fn-NN, fn-NN.M | wor-17, wor-17.M, and WOR-17 (the tracker display key) |
| how it is created | /flow-next:capture, flowctl spec create | flowctl spec create --tracker-first --tracker-identifier WOR-17 |
| linking to a tracker | flowctl sync set-tracker-id adds WOR-17 as a resolvable alias; the fn-NN id, branch, and tasks are unchanged | already tracker-keyed at creation |
All four trackers can be grabbed tracker-first. Linear WOR-17 and Jira PROJ-123 are already alpha-prefixed KEY-N display keys and mint directly. GitHub #N and GitLab <project>#<iid> are not KEY-N, so they mint through a synthetic key derived from the tracker type: GitHub issue 123 becomes gh-123-slug, and a GitLab project-scoped iid of 456 becomes gl-456-slug. That is unambiguous because a repo has exactly one configured tracker, and it is guarded so a minted id can never collide with a historical one. A non-standard Jira Data Center / Server key that can’t slugify into a canonical id (an underscore key like MY_PROJECT-7, or a long alphanumeric one) still links flow-first / display-only.
The full …-slug form is the filesystem, branch, and task identity. A shared bare ordinal (two fn-122-… files with different slugs) is untidy, not a broken identity.
Which scheme new specs use is a setting: flowctl config set tracker.specIds tracker makes tracker-keyed ids the default, and setup asks once when a tracker is configured. Teams want it - see why.
Both schemes resolve everywhere a spec or task id is accepted. flowctl show wor-17, /flow-next:work wor-17, /flow-next:plan wor-17, and the task form wor-17.1 all resolve, and resolution is case-insensitive - WOR-17 works the same as wor-17.
The two columns are set at creation and never converted into each other. Only a spec created with --tracker-first is canonically wor-17-slug; linking an existing fn-NN spec to a tracker keeps it fn-NN and merely adds the tracker key as an alias.
Three rules keep the two schemes from colliding:
- Ids never change. There is no rename-on-push. When a
fn-NNspec is linked to a tracker, the tracker key is added as a resolvable alias, and the existing id, branch, and dependency edges are never mutated.flowctl spec set-titleon a tracker-linked spec updates the title only; it does not re-slug the id. Switchingtracker.specIdsaffects new specs only, so mixed stores are permanent and expected. - The
fn-prefix is reserved for the native sequential scheme. Tracker-key resolution is tried only after thefn-path misses, and nativefn-Nallocation countsfn-*ids only - awor-9999never bumps the nextfnnumber. - One tracker team per repo. The bridge assumes a single team key so a bare
wor-17resolves unambiguously. Two teams both keyedWORin the same repo is out of scope.
Native fn-N allocation takes the max across the working tree, every registered git worktree, and every ref, which shrinks parallel-create races inside one repo. Separate unfetched clones can still collide; tracker-keyed ids avoid that race by using the tracker as the allocator.
The tracker key only exists once a spec is linked to a tracker - see Tracker Sync. If you never connect a tracker, every spec stays fn-NN and nothing here changes. Bridge mechanics: Tracker Sync. Team recommendation: Collaboration.
Writing acceptance criteria
Section titled “Writing acceptance criteria”Acceptance criteria use stable R-IDs:
**R1:** The command creates `.flow/specs/<id>.md`.**R2:** The command writes task files under `.flow/tasks/`.**R3:** Validation fails if a task references a missing dependency.Source tags
Section titled “Source tags”/flow-next:capture marks criteria with source tags:
[user]: verbatim user requirement[paraphrase]: restated user requirement[inferred]: agent-inferred fill[strategy:<track>]: derived fromSTRATEGY.md
The read-back surfaces inferred counts before writing.
Section ownership
Section titled “Section ownership”| Section | Primary owner | Review question |
|---|---|---|
| Goal and context | PO, PM, user, maintainer | Does this describe the real outcome? |
| Acceptance criteria | PO + tech lead | Can we verify every requirement? |
| Boundaries | PO + tech lead | What must not be built? |
| Architecture and data models | Tech lead | Does this match the repo and constraints? |
| API contracts | Tech lead | Are integrations and compatibility clear? |
| Edge cases and constraints | PO + engineering | Are failure modes explicit enough? |
| Decision context | Whoever made the tradeoff | Will this still make sense in six months? |
R-ID rules
Section titled “R-ID rules”- Use
R1,R2,R3in order. - Freeze meanings after review.
- Leave gaps when removing accepted criteria.
- Append new criteria at the end.
- Map tasks back to R-IDs with
satisfies: [R1, R3].
R-IDs are not formatting. They are how Flow-Next connects requirements to tasks, review receipts, and PR explanations.
Project-wide criteria (G-IDs)
Section titled “Project-wide criteria (G-IDs)”A criterion that belongs to the project rather than to one spec (“every route change regenerates the API contract”) uses the same grammar with a G prefix, in .flow/criteria.md:
- **G1:** Every route change regenerates the API contract.- **G2:** No new dependency without a health check (scope: package.json).Spec completion review judges every G-ID against the whole implementation and records met / violated / n/a per criterion in the review receipt. The same never-renumber rule applies. Full model: Standing Criteria.
G-IDs are never restated as R-IDs in a spec’s ## Acceptance Criteria. A copy would drift as criteria.md evolves and be judged twice. Reference the G-ID in prose; an R-ID covers only what the spec adds beyond the standing rule.
Flow-Next 1.1.4 treats ## Acceptance Criteria as canonical. The parser still accepts legacy ## Acceptance and ## Acceptance criteria headings so older specs keep working.
Inferred criteria
Section titled “Inferred criteria”Treat [inferred] criteria as provisional. They are useful because they show where the agent filled gaps, but they need human review before implementation. A high inferred count is a signal to run /flow-next:interview, not a signal to trust the draft harder.