From plan to frozen spec

After planning, the AI writes a spec (by hand or through the optional spec pipeline), paqad-ai spec freeze checks it and stores specification.json, and paqad-ai rules load records the applicable rules. Hook-capable tools block code edits until these records exist.

  • Planning
  • Checked against paqad-ai 1.91.1
  • Reviewed 25 September 2026 by Eliyce

The path from request to first code edit

Before code is written, a change passes through a fixed sequence: it is routed and sized, planned, specified, frozen, and the project rules are loaded. Each step either produces an official record in the change's evidence bundle or opens a question for you. This page walks through the sequence and says, for each step, whether a script, the AI or you decides.

StepWhat happensWho decides
1. Route and laneThe message is routed to feature-development and given a lane.The AI picks the route; on Claude Code and Codex CLI a script records it and the lane.
2. PlanThe AI writes a plan; paqad-ai plan compile checks it and stores plan.json.AI writes; script checks; you answer any reuse-or-create pause.
3. SpecifyThe AI writes the spec by hand, or runs the spec pipeline if it is switched on.AI writes; scripts ground, check and trace; you answer questions and expert conflicts.
4. Freezepaqad-ai spec freeze checks the spec and stores specification.json.Script checks; the freeze is meant to be your sign-off.
5. Load the rulespaqad-ai rules load prints the rules that apply to the changed files and records that they were loaded.Script.

Routing and lanes are covered in Routing and lanes, and planning in Planning a change. The rest of this page covers steps 3 to 5.

Writing the spec

A spec is written as Markdown and must contain three things the freeze can check: behaviour statements, acceptance criteria and invariants. An acceptance criterion (AC-1, AC-2, and so on) is a testable statement in given, when, then form, with a proof_type saying how it will be proven: automated, manual or visual. An invariant (INV-1 and so on) is something that must stay true, which a person confirms. A spec may also list non-goals.

By default the AI writes the spec itself. That is judgement, and the checks at freeze time are the safety net.

The optional spec pipeline

With spec_pipeline_enabled switched on (it is off by default), the spec is produced through paqad-ai spec pipeline, a fixed sequence of steps. Each step writes one file into a scratch folder, and the next step is locked until the previous file exists and validates. A crashed run resumes at the first unfinished step, and paqad-ai spec pipeline status shows where it stands.

StepWhat happensWho does it
groundCollects the vocabulary, rules and document references for the area the request touches, from retrieval when it is on, otherwise from docs/modules/. A thinly documented area is marked sparse, not failed.Script
labelRates how clear the request is against that grounding: vague, okay or clear.Script
expertsOnly with spec_pipeline_experts_enabled on. Chooses which domain experts, if any, should comment, collects their notes, and has chief-architect weigh them.AI, limited to a fixed roster that a script enforces
questionsOne batch of plain-language questions, only when something is genuinely undecided. A question already answered on an earlier change is filled in from the decision record and not asked again.AI phrases; script filters; you answer
taskA structured restatement of the request and your answers.AI
craftWrites the spec in the format the freeze accepts, with a trace file tying each line to its source.AI writes; script checks the trace
finishRecords how the spec was produced and what the run cost.Script

Four settings shape the pipeline. spec_pipeline_clarification (off, warn by default, or strict) decides whether unanswered questions block. spec_pipeline_final_review (off by default, warn or strict) can require a named person to approve before the freeze. spec_pipeline_token_ceiling (20,000 by default) warns, never blocks, when a run uses more model tokens than that. spec_pipeline_adoption (warn by default, or strict) decides whether a hand-written spec is still accepted.

Freezing the spec

The AI freezes the spec with paqad-ai spec freeze <spec.md> --signed-off-by <name> --confirm-invariants, adding --from-pipeline when the pipeline produced it. The freeze is a machine check. It refuses to freeze when:

  • there are no behaviour statements, no acceptance criteria or no invariants;
  • an acceptance criterion has no proof_type;
  • an invariant is not confirmed;
  • an open question is unresolved;
  • the built-in spec quality review finds a critical defect (lesser findings are reported but do not block);
  • visual evidence is on, the change touches frontend files, and no criterion has proof_type visual;
  • adoption is strict and the spec did not come from the pipeline, unless --manual --reason "<why>" is given, and the reason is recorded.

On success it writes specification.json (the official record) and a read-only specification.md view into the bundle, and deletes the draft.

The --confirm-invariants flag is described as the human sign-off, and --signed-off-by records a name. paqad records what the command was given; it cannot prove that a person read the invariants. If you want a real human sign-off, ask the AI to show you the invariants and wait for your answer before it freezes, or use spec_pipeline_final_review=strict.

Loading the rules before the first edit

After reading the rule text paqad composed for the files in play, the AI runs paqad-ai rules load. It prints the full text of every rule that applies to the changed files and writes rules-loaded.json into the bundle. The record shows the rules were loaded, not that they were understood. Rules that are enforced by scripts run whether or not their text was read.

The gates that hold this order

On Claude Code and Codex CLI, these are machine checks that block the edit:

  • No code edit until planning has a recorded start, end and plan file.
  • On the graduated and full lanes, no code edit until the specification stage has the same, pointing at specification.json.
  • No feature-development code edit until rules-loaded.json exists, when the project has compiled rules. This gate has no setting to switch it off.
  • No edit while a decision pause is unresolved.

At the end of the change, a change whose rules were never loaded fails, and one whose rule record is out of date reads Inconclusive. After the freeze, a change of goal or a contradiction between the work and the spec is raised as a spec.change or spec.contradiction decision pause rather than absorbed silently.

Something on this page out of date or unclear? Open an issue on GitHub and name the page.