Skip to content

Spec Schema

Flow-Next specs follow the template in plugins/flow-next/templates/spec.md.

  • Goal and context
  • Architecture and data models
  • API contracts
  • Edge cases and constraints
  • Acceptance Criteria
  • Boundaries
  • Decision context
---
id: fn-12-add-pr-cognitive-aid
title: Add PR cognitive aid generation
---
## Goal and Context
## Architecture and Data Models
## API Contracts
## Edge Cases and Constraints
## Acceptance Criteria
**R1:** ...
**R2:** ...
## Boundaries
## Decision Context

The 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.

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 idfn-NN-slugwor-17-slug
canonical task idsfn-NN-slug.Mwor-17-slug.M
branchfn-NN-slugwor-17-slug
bare aliases that resolvefn-NN, fn-NN.Mwor-17, wor-17.M, and WOR-17 (the tracker display key)
how it is created/flow-next:capture, flowctl spec createflowctl spec create --tracker-first --tracker-identifier WOR-17
linking to a trackerflowctl sync set-tracker-id adds WOR-17 as a resolvable alias; the fn-NN id, branch, and tasks are unchangedalready 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-NN spec 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-title on a tracker-linked spec updates the title only; it does not re-slug the id. Switching tracker.specIds affects 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 the fn- path misses, and native fn-N allocation counts fn-* ids only - a wor-9999 never bumps the next fn number.
  • One tracker team per repo. The bridge assumes a single team key so a bare wor-17 resolves unambiguously. Two teams both keyed WOR in 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.

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.

/flow-next:capture marks criteria with source tags:

  • [user]: verbatim user requirement
  • [paraphrase]: restated user requirement
  • [inferred]: agent-inferred fill
  • [strategy:<track>]: derived from STRATEGY.md

The read-back surfaces inferred counts before writing.

SectionPrimary ownerReview question
Goal and contextPO, PM, user, maintainerDoes this describe the real outcome?
Acceptance criteriaPO + tech leadCan we verify every requirement?
BoundariesPO + tech leadWhat must not be built?
Architecture and data modelsTech leadDoes this match the repo and constraints?
API contractsTech leadAre integrations and compatibility clear?
Edge cases and constraintsPO + engineeringAre failure modes explicit enough?
Decision contextWhoever made the tradeoffWill this still make sense in six months?
  • Use R1, R2, R3 in 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.

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.

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.