Skip to main content

Releases and Scopes

A release is the unit of delivery in REQQA — a named, bounded slice of an application that you intend to hand to a build team and accept back when it is done. It has a lifecycle, a set of stories drawn from your requirements, an advisory quality gate, point-in-time snapshots, and one or more build plans attached to it.

If you have worked in any delivery team, the word is familiar: "what's in the v2 release?" This page explains what sits underneath that word in REQQA, and why the model is shaped the way it is.

Release and scope: the same thing, two words

In the user interface you always see Release. Underneath, the object is stored as a scope (the table is scopes, the page is scopeView, the code paths are all scope*). This is deliberate and worth understanding, because both words appear in the product:

  • A release is the deliverable — the thing with a name, a status, a plan, and a lifecycle.
  • A scope is a property of that release: its contents and its boundary — what is in, what is out, and the constraints it must respect.

So a release has a scope; the scope is not a separate object you manage. When you create a release you give it a name, a description, an out-of-scope note, and any constraints. The out-of-scope and constraints fields are where the boundary lives — they are the scope-as-property, captured in prose.

note

You will sometimes see "scope" in URLs and in this manual where the model is being explained. That is the underlying object name. In everyday use, think and speak in terms of releases.

For the difference stated plainly, see the FAQ: Scope vs Release.

What a release groups

A release does not contain requirements directly. It contains stories, and each story carries its parent requirement along with it. When you add stories to a release, REQQA pins each one to its current revision — so the release records not just which stories are in it, but the exact version of each story at the moment it was included. This is what lets REQQA later detect a stale story: one whose parent requirement has been updated since the story was written.

On the release view, stories are grouped by their parent requirement, so you read the release as "these requirements, delivered through these stories" rather than as a flat list.

To learn how to build up a release's contents, see How to manage releases. For where stories come from in the first place, see Generating stories.

The scope lifecycle (analyst side)

The release itself has a deliberately small lifecycle — just two active states and two closed states. This is the analyst's view of the release: it tracks how mature the specification is, and nothing about build progress.

StatusLabelMeaning
draftDraftBeing defined. Stories can be added and removed; the release can be edited.
handover_readyHandover ReadyThe analyst has finished defining the release; it is ready to hand to a build team.
acceptedRelease AcceptedThe analyst has confirmed the delivered work is acceptable. Terminal.
abandonedAbandonedThe release will not be pursued. Reversible back to draft.

The permitted transitions are:

  • Draft → Handover Ready — the normal flow once the release is fully defined.
  • Draft → Abandoned — decide not to pursue a release before handover.
  • Handover Ready → Draft — send it back for revision.
  • Handover Ready → Release Accepted — accept the delivered work after testing.
  • Handover Ready → Abandoned — reject the delivery or change strategy.
  • Abandoned → Draft — un-abandon a release.
  • Release Accepted — terminal; no transitions out.

Two rules are worth knowing:

  • You can only edit a release, or add and remove its stories, while it is in Draft. Once it is Handover Ready the contents are frozen, which is what makes a handover meaningful.
  • Status changes use optimistic locking. When you change the status, REQQA checks the release has not been moved by someone else since you loaded the page. If it has, you are asked to refresh and retry rather than silently overwriting.
tip

Moving a release from Draft to Handover Ready is the moment its scope is fixed. Treat it as a checkpoint, not a casual click — run the quality gate first.

Why scope and plan are separate

Originally a release carried a single status column with seven states that tried to track both specification maturity and build progress at once. That conflation produced contradictions — the same transition appeared to belong to the analyst in one place and the builder in another. The fix was to split the model into two state machines:

  • The scope status (above) is owned by the analyst and answers "is the specification ready?"
  • The plan status (below) is owned mostly by the builder and answers "how far has the build progressed?"

The guiding insight: when the builder pauses work, the specification does not change — so "paused" belongs to the plan, not the release. Every transition now has exactly one owner, with no shared ones.

Plans attached to a release

A build plan is a separate object attached to a release. It is a Markdown document — the agreed approach for delivering the release's scope — and a release can accumulate several versions over time. Plans are stored in scope_plans, each with a version number and its own status.

The key distinction:

  • The scope is what is to be delivered (the stories and their boundary).
  • The plan is how and in what order it will be delivered, plus how it will be verified.

A plan has a richer, seven-state lifecycle:

StatusLabelOwnerMeaning
draftDraftBuilderSubmitted, awaiting analyst approval.
approvedApprovedAnalystApproved; ready for the build to start.
in_progressIn ProgressBuilderBuild under way.
pausedPausedBuilderWork stopped or blocked.
acceptedDone (Builder)BuilderBuild complete; builder's handover signal.
closedAccepted (Customer)AnalystCustomer/analyst has accepted the delivery. Terminal.
supersededSupersededAutomaticA newer draft was submitted; the old draft is retired.

The transitions, by owner:

  • Analyst: Draft → Approved; Done (Builder) → Accepted (Customer); Done (Builder) → In Progress (reject the delivery and ask for more work).
  • Builder: Approved → In Progress; In Progress → Paused; Paused → In Progress; In Progress → Done (Builder).
  • Automatic: any previous draft is moved to Superseded when a new draft is submitted.

Rules around plan submission and approval

  • A plan can only be submitted when its release is Handover Ready. A release still in Draft has no fixed scope to plan against.
  • Only one plan may be in flight at a time. Draft, Approved, In Progress, and Paused all count as in-flight. You cannot submit a new plan while a non-draft plan is still active — the existing one must reach a terminal state (Accepted by Customer or Superseded) first. An outstanding draft, by contrast, is automatically superseded by the new submission.
  • Approval is blocked while the plan has unresolved questions. Before an analyst can approve a draft, REQQA scans the plan's Markdown for non-empty Blockers, Queries, or Unmitigated Risks sections. If any have real content, approval is refused and the builder must resubmit a new version with those sections cleared — either by addressing them or by reclassifying them as settled annotations (Assumptions, Caveats, Risks).

The advisory quality gate

Before a release is handed over, you can run a quality gate — a set of advisory checks over everything in the release. It is advisory: it informs the decision, it does not block the transition. The gate runs four checks:

  1. Requirement analysis coverage — every in-scope requirement has been analysed through at least the minimum DeFOSPAM steps (Definition, Faults, Ambiguity, Measurability). Container requirements that carry no features of their own are not required to have the Faults step.
  2. Story analysis coverage — every in-scope story has been analysed through at least its minimum steps (Definition, Structure, Ambiguity).
  3. No HIGH-severity open issues — no in-scope requirement or story has an unresolved HIGH-severity analysis issue.
  4. No stale stories — no story's parent requirement has been updated more recently than the story itself.

For what the analyser steps mean, see The analysis engine and the FAQ on analyser codes.

Snapshots: as-scoped and as-built

REQQA captures two immutable JSON snapshots over a release's life, each at a precise moment:

  • The as-scoped snapshot is taken the first time a release moves from Draft to Handover Ready. It records the release's name, boundary, every in-scope story with its content and pinned revision, the analysis summary for each, the quality-gate result, and the issue counts — a frozen record of exactly what was handed over.
  • The as-built snapshot is taken on the plan, when a build transitions from In Progress to Done (Builder). It records the same shape, capturing the state at the point the build was declared complete.

Together they give a defensible before-and-after record of a release: what was promised, and what was delivered.

The RBAC model: analysts in the UI, builders through the API

The split between scope and plan maps directly onto a security boundary:

  • Analysts work through the REQQA web interface. They define releases, add and remove stories, run the quality gate, drive the scope lifecycle (Draft ↔ Handover Ready, Accepted, Abandoned), approve plans, and accept delivered work. All of this is session-authenticated and happens in the browser.
  • Builders work through the HTTP API. Build tools — including the autonomous build agent of the Dark Factory — are restricted to plan transitions: starting an approved build, pausing and resuming, and signalling the build complete (Done). They do not touch the scope lifecycle.

The rule of thumb: anything that crosses into specification territory — fixing the scope, sending a release back to draft, accepting a release — is analyst-only and lives in the UI. Anything that is build progress on an already-agreed plan is the builder's, through the API. The analyst always retains the final accept: a builder marks a plan Done, but only an analyst marks it Accepted (Customer).

Every status change — scope or plan — is recorded with the user, timestamp, and an optional comment in a history table, so the full lifecycle of a release is auditable after the fact.